2013-05-21 13:34:14 +04:00
|
|
|
package binary
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/binary"
|
2013-11-18 20:24:31 +04:00
|
|
|
"errors"
|
2014-08-04 17:19:35 +04:00
|
|
|
"github.com/omniscale/imposm3/element"
|
2013-05-21 13:34:14 +04:00
|
|
|
)
|
|
|
|
|
|
|
|
func MarshalDeltaNodes(nodes []element.Node, buf []byte) []byte {
|
|
|
|
estimatedLength := len(nodes)*4*3 + binary.MaxVarintLen64
|
|
|
|
|
2013-06-03 13:04:15 +04:00
|
|
|
if cap(buf) < estimatedLength {
|
2013-05-21 13:34:14 +04:00
|
|
|
buf = make([]byte, estimatedLength)
|
2013-06-03 13:04:15 +04:00
|
|
|
} else {
|
|
|
|
// resize slice to full capacity
|
|
|
|
buf = buf[:cap(buf)-1]
|
2013-05-21 13:34:14 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
lastId := int64(0)
|
2013-11-19 11:40:27 +04:00
|
|
|
nextPos := binary.PutUvarint(buf, uint64(len(nodes)))
|
2013-05-21 13:34:14 +04:00
|
|
|
|
|
|
|
for i := range nodes {
|
|
|
|
if len(buf)-nextPos < binary.MaxVarintLen64 {
|
|
|
|
tmp := make([]byte, len(buf)*3/2)
|
|
|
|
copy(tmp, buf)
|
|
|
|
buf = tmp
|
|
|
|
}
|
|
|
|
nextPos += binary.PutVarint(buf[nextPos:], nodes[i].Id-lastId)
|
|
|
|
lastId = nodes[i].Id
|
|
|
|
}
|
|
|
|
|
|
|
|
lastLong := int64(0)
|
|
|
|
for i := range nodes {
|
|
|
|
if len(buf)-nextPos < binary.MaxVarintLen64 {
|
|
|
|
tmp := make([]byte, len(buf)*3/2)
|
|
|
|
copy(tmp, buf)
|
|
|
|
buf = tmp
|
|
|
|
}
|
|
|
|
long := int64(CoordToInt(nodes[i].Long))
|
|
|
|
nextPos += binary.PutVarint(buf[nextPos:], long-lastLong)
|
|
|
|
lastLong = long
|
|
|
|
}
|
|
|
|
|
|
|
|
lastLat := int64(0)
|
|
|
|
for i := range nodes {
|
|
|
|
if len(buf)-nextPos < binary.MaxVarintLen64 {
|
|
|
|
tmp := make([]byte, len(buf)*3/2)
|
|
|
|
copy(tmp, buf)
|
|
|
|
buf = tmp
|
|
|
|
}
|
|
|
|
lat := int64(CoordToInt(nodes[i].Lat))
|
|
|
|
nextPos += binary.PutVarint(buf[nextPos:], lat-lastLat)
|
|
|
|
lastLat = lat
|
|
|
|
}
|
|
|
|
|
|
|
|
return buf[:nextPos]
|
|
|
|
}
|
|
|
|
|
2013-11-18 20:24:31 +04:00
|
|
|
var varintErr = errors.New("unmarshal delta coords: missing data for varint or overflow")
|
|
|
|
|
2013-05-21 13:34:14 +04:00
|
|
|
func UnmarshalDeltaNodes(buf []byte, nodes []element.Node) ([]element.Node, error) {
|
2013-11-19 11:40:27 +04:00
|
|
|
length, n := binary.Uvarint(buf)
|
2013-11-18 20:24:31 +04:00
|
|
|
if n <= 0 {
|
|
|
|
return nil, varintErr
|
2013-05-21 13:34:14 +04:00
|
|
|
}
|
2013-11-18 20:24:31 +04:00
|
|
|
var offset = n
|
2013-05-21 13:34:14 +04:00
|
|
|
|
2013-11-19 11:40:27 +04:00
|
|
|
if uint64(cap(nodes)) < length {
|
2013-05-21 13:34:14 +04:00
|
|
|
nodes = make([]element.Node, length)
|
|
|
|
} else {
|
|
|
|
nodes = nodes[:length]
|
|
|
|
}
|
|
|
|
|
|
|
|
lastId := int64(0)
|
2013-11-19 11:40:27 +04:00
|
|
|
for i := 0; uint64(i) < length; i++ {
|
2013-11-18 20:24:31 +04:00
|
|
|
id, n := binary.Varint(buf[offset:])
|
|
|
|
if n <= 0 {
|
|
|
|
return nil, varintErr
|
2013-05-21 13:34:14 +04:00
|
|
|
}
|
2013-11-18 20:24:31 +04:00
|
|
|
offset += n
|
2013-05-21 13:34:14 +04:00
|
|
|
id = lastId + id
|
|
|
|
nodes[i].Id = id
|
|
|
|
lastId = id
|
|
|
|
}
|
|
|
|
|
|
|
|
lastLong := int64(0)
|
2013-11-19 11:40:27 +04:00
|
|
|
for i := 0; uint64(i) < length; i++ {
|
2013-11-18 20:24:31 +04:00
|
|
|
long, n := binary.Varint(buf[offset:])
|
|
|
|
if n <= 0 {
|
|
|
|
return nil, varintErr
|
2013-05-21 13:34:14 +04:00
|
|
|
}
|
2013-11-18 20:24:31 +04:00
|
|
|
offset += n
|
2013-05-21 13:34:14 +04:00
|
|
|
long = lastLong + long
|
|
|
|
nodes[i].Long = IntToCoord(uint32(long))
|
|
|
|
lastLong = long
|
|
|
|
}
|
|
|
|
|
|
|
|
lastLat := int64(0)
|
2013-11-19 11:40:27 +04:00
|
|
|
for i := 0; uint64(i) < length; i++ {
|
2013-11-18 20:24:31 +04:00
|
|
|
lat, n := binary.Varint(buf[offset:])
|
|
|
|
if n <= 0 {
|
|
|
|
return nil, varintErr
|
2013-05-21 13:34:14 +04:00
|
|
|
}
|
2013-11-18 20:24:31 +04:00
|
|
|
offset += n
|
2013-05-21 13:34:14 +04:00
|
|
|
lat = lastLat + lat
|
|
|
|
nodes[i].Lat = IntToCoord(uint32(lat))
|
|
|
|
lastLat = lat
|
|
|
|
}
|
|
|
|
|
|
|
|
return nodes, nil
|
|
|
|
}
|