mirror of
https://bitbucket.org/s_l_teichmann/mtsatellite
synced 2025-01-11 01:10:17 +01:00
Support v29 blocks
This commit is contained in:
parent
827d73bed0
commit
8a344b5a6d
279
common/block.go
279
common/block.go
@ -92,6 +92,132 @@ type posBuf struct {
|
|||||||
Pos int
|
Pos int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type bigEndian struct {
|
||||||
|
data []byte
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (be *bigEndian) Err() error {
|
||||||
|
return be.err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (be *bigEndian) u8() uint8 {
|
||||||
|
if be.err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
if len(be.data) >= 1 {
|
||||||
|
x := be.data[0]
|
||||||
|
be.data = be.data[1:]
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
be.err = ErrBlockTruncated
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (be *bigEndian) u16() uint16 {
|
||||||
|
if be.err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
if len(be.data) >= 2 {
|
||||||
|
x := binary.BigEndian.Uint16(be.data)
|
||||||
|
be.data = be.data[2:]
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
be.err = ErrBlockTruncated
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (be *bigEndian) u32() uint32 {
|
||||||
|
if be.err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
if len(be.data) >= 4 {
|
||||||
|
x := binary.BigEndian.Uint32(be.data)
|
||||||
|
be.data = be.data[4:]
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
be.err = ErrBlockTruncated
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (be *bigEndian) str(l int) string {
|
||||||
|
if be.err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
if len(be.data) >= l {
|
||||||
|
s := string(be.data[:l])
|
||||||
|
be.data = be.data[l:]
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
be.err = ErrBlockTruncated
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func decode29(data []byte, colors *Colors) (*DecodedBlock, error) {
|
||||||
|
|
||||||
|
dec, err := zstd.NewReader(nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
content, err := dec.DecodeAll(data, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
be := bigEndian{data: content}
|
||||||
|
|
||||||
|
_ = be.u8() // flags
|
||||||
|
_ = be.u16() // lightning_complete
|
||||||
|
_ = be.u32() // timestamp
|
||||||
|
_ = be.u8() // name_id_mapping_version
|
||||||
|
|
||||||
|
airID, ignoreID := int32(-1), int32(-1)
|
||||||
|
indexMap := make(map[int32]int32)
|
||||||
|
transparent := false
|
||||||
|
numNameIDMappings := be.u16()
|
||||||
|
for i := uint16(0); i < numNameIDMappings; i++ {
|
||||||
|
id := int32(be.u16())
|
||||||
|
name := be.str(int(be.u16()))
|
||||||
|
switch name {
|
||||||
|
case "air":
|
||||||
|
airID = id
|
||||||
|
case "ignore":
|
||||||
|
ignoreID = id
|
||||||
|
default:
|
||||||
|
if index, found := colors.NameIndex[name]; found {
|
||||||
|
indexMap[id] = index
|
||||||
|
if !transparent && colors.IsTransparent(index) {
|
||||||
|
transparent = true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logMissing(name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ = be.u8() // content_width
|
||||||
|
_ = be.u8() // params_width
|
||||||
|
|
||||||
|
if err := be.Err(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
mapContent := make([]byte, 2*4096)
|
||||||
|
if len(be.data) < len(mapContent) {
|
||||||
|
return nil, ErrBlockTruncated
|
||||||
|
}
|
||||||
|
copy(mapContent, be.data)
|
||||||
|
|
||||||
|
return &DecodedBlock{
|
||||||
|
Version: data[0],
|
||||||
|
Transparent: transparent,
|
||||||
|
MapContent: mapContent,
|
||||||
|
AirID: airID,
|
||||||
|
IgnoreID: ignoreID,
|
||||||
|
IndexMap: indexMap,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
func NewDecodedBlock(data []byte, colors *Colors) (db *DecodedBlock, err error) {
|
func NewDecodedBlock(data []byte, colors *Colors) (db *DecodedBlock, err error) {
|
||||||
|
|
||||||
dataLen := len(data)
|
dataLen := len(data)
|
||||||
@ -101,102 +227,93 @@ func NewDecodedBlock(data []byte, colors *Colors) (db *DecodedBlock, err error)
|
|||||||
|
|
||||||
version := data[0]
|
version := data[0]
|
||||||
|
|
||||||
//var mapContent := make([]byte, uncompressedLen)
|
if version >= 29 {
|
||||||
var mapContent []byte
|
return decode29(data, colors)
|
||||||
|
}
|
||||||
|
|
||||||
var offset int
|
var offset int
|
||||||
|
|
||||||
if version >= 29 {
|
contentWidth := Min(int(data[2]), 2)
|
||||||
dec, err := zstd.NewReader(nil)
|
paramsWidth := Min(int(data[3]), 2)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
mapContent, err = dec.DecodeAll(data[1:], nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
contentWidth := Min(int(data[2]), 2)
|
|
||||||
paramsWidth := Min(int(data[3]), 2)
|
|
||||||
|
|
||||||
uncompressedLen := nodeCount * (contentWidth + paramsWidth)
|
uncompressedLen := nodeCount * (contentWidth + paramsWidth)
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case version >= 27:
|
case version >= 27:
|
||||||
offset = 6
|
offset = 6
|
||||||
case version >= 22:
|
case version >= 22:
|
||||||
offset = 4
|
offset = 4
|
||||||
default:
|
default:
|
||||||
offset = 2
|
offset = 2
|
||||||
}
|
}
|
||||||
|
|
||||||
zr := zlibReaderPool.Get().(interface {
|
zr := zlibReaderPool.Get().(interface {
|
||||||
io.ReadCloser
|
io.ReadCloser
|
||||||
zlib.Resetter
|
zlib.Resetter
|
||||||
})
|
})
|
||||||
defer func() {
|
defer func() {
|
||||||
zr.Close() // This sould not be necessary.
|
zr.Close() // This sould not be necessary.
|
||||||
zlibReaderPool.Put(zr)
|
zlibReaderPool.Put(zr)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
buf := posBuf{Data: data[offset:]}
|
buf := posBuf{Data: data[offset:]}
|
||||||
if err = zr.Reset(&buf, nil); err != nil {
|
if err = zr.Reset(&buf, nil); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
mapContent = make([]byte, uncompressedLen)
|
mapContent := make([]byte, uncompressedLen)
|
||||||
|
|
||||||
var k int
|
var k int
|
||||||
k, err = io.ReadFull(zr, mapContent)
|
k, err = io.ReadFull(zr, mapContent)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if k != uncompressedLen {
|
if k != uncompressedLen {
|
||||||
err = ErrMapContentSizeMismatch
|
err = ErrMapContentSizeMismatch
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// There is a bug before Go 1.7 that enforces
|
// There is a bug before Go 1.7 that enforces
|
||||||
// to add 4 as an offset after the compressed
|
// to add 4 as an offset after the compressed
|
||||||
// geometry data. This is resolved via build tags
|
// geometry data. This is resolved via build tags
|
||||||
// and definitions in pre17offset.go and
|
// and definitions in pre17offset.go and
|
||||||
// post17offset.go.
|
// post17offset.go.
|
||||||
offset += buf.Pos + afterCompressOfs
|
offset += buf.Pos + afterCompressOfs
|
||||||
buf.Pos = 0
|
buf.Pos = 0
|
||||||
|
if offset >= dataLen {
|
||||||
|
return nil, ErrBlockTruncated
|
||||||
|
}
|
||||||
|
buf.Data = data[offset:]
|
||||||
|
|
||||||
|
if err = zr.(zlib.Resetter).Reset(&buf, nil); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Discard the meta data.
|
||||||
|
if _, err = io.Copy(io.Discard, zr); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
offset += buf.Pos
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case version <= 21:
|
||||||
|
offset += 2
|
||||||
|
case version == 23:
|
||||||
|
offset++
|
||||||
|
case version == 24:
|
||||||
if offset >= dataLen {
|
if offset >= dataLen {
|
||||||
return nil, ErrBlockTruncated
|
return nil, ErrBlockTruncated
|
||||||
}
|
}
|
||||||
buf.Data = data[offset:]
|
ver := data[offset]
|
||||||
|
offset++
|
||||||
if err = zr.(zlib.Resetter).Reset(&buf, nil); err != nil {
|
if ver == 1 {
|
||||||
return
|
if offset+1 >= dataLen {
|
||||||
}
|
|
||||||
|
|
||||||
// Discard the meta data.
|
|
||||||
if _, err = io.Copy(io.Discard, zr); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
offset += buf.Pos
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case version <= 21:
|
|
||||||
offset += 2
|
|
||||||
case version == 23:
|
|
||||||
offset++
|
|
||||||
case version == 24:
|
|
||||||
if offset >= dataLen {
|
|
||||||
return nil, ErrBlockTruncated
|
return nil, ErrBlockTruncated
|
||||||
}
|
}
|
||||||
ver := data[offset]
|
num := int(binary.BigEndian.Uint16(data[offset:]))
|
||||||
offset++
|
offset += 2 + 10*num
|
||||||
if ver == 1 {
|
|
||||||
if offset+1 >= dataLen {
|
|
||||||
return nil, ErrBlockTruncated
|
|
||||||
}
|
|
||||||
num := int(binary.BigEndian.Uint16(data[offset:]))
|
|
||||||
offset += 2 + 10*num
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user