diff --git a/fmp/fmp_chunk.go b/fmp/fmp_chunk.go index 84c99cf..eb19ba5 100644 --- a/fmp/fmp_chunk.go +++ b/fmp/fmp_chunk.go @@ -1,9 +1,5 @@ package fmp -import ( - "encoding/binary" -) - func (ctx *FmpFile) readChunk(payload []byte) (*FmpChunk, error) { // Simple data @@ -34,7 +30,7 @@ func (ctx *FmpFile) readChunk(payload []byte) (*FmpChunk, error) { return &FmpChunk{ Type: FMP_CHUNK_SIMPLE_DATA, Value: payload[1 : 1+length], - Length: 1 + uint32(length), + Length: 1 + uint64(length), }, nil } if 0x12 <= payload[0] && payload[0] <= 0x15 { @@ -42,7 +38,7 @@ func (ctx *FmpFile) readChunk(payload []byte) (*FmpChunk, error) { return &FmpChunk{ Type: FMP_CHUNK_SIMPLE_DATA, Value: payload[1 : 1+length], - Length: 1 + uint32(length), + Length: 1 + uint64(length), }, nil } if 0x1A <= payload[0] && payload[0] <= 0x1D { @@ -50,7 +46,7 @@ func (ctx *FmpFile) readChunk(payload []byte) (*FmpChunk, error) { return &FmpChunk{ Type: FMP_CHUNK_SIMPLE_DATA, Value: payload[1 : 1+length], - Length: 1 + uint32(length), + Length: 1 + uint64(length), }, nil } @@ -59,7 +55,7 @@ func (ctx *FmpFile) readChunk(payload []byte) (*FmpChunk, error) { if payload[0] == 0x01 { return &FmpChunk{ Type: FMP_CHUNK_SIMPLE_KEY_VALUE, - Key: uint32(payload[1]), + Key: uint64(payload[1]), Value: payload[2 : 2+1], Length: 3, }, nil @@ -68,24 +64,24 @@ func (ctx *FmpFile) readChunk(payload []byte) (*FmpChunk, error) { length := 2 * (payload[0] - 1) return &FmpChunk{ Type: FMP_CHUNK_SIMPLE_KEY_VALUE, - Key: uint32(payload[1]), + Key: uint64(payload[1]), Value: payload[2 : 2+length], - Length: 2 + uint32(length), + Length: 2 + uint64(length), }, nil } if payload[0] == 0x06 { length := payload[2] return &FmpChunk{ Type: FMP_CHUNK_SIMPLE_KEY_VALUE, - Key: uint32(payload[1]), + Key: uint64(payload[1]), Value: payload[3 : 3+length], // docs say offset 2? - Length: 3 + uint32(length), + Length: 3 + uint64(length), }, nil } if payload[0] == 0x09 { return &FmpChunk{ Type: FMP_CHUNK_SIMPLE_KEY_VALUE, - Key: uint32(binary.BigEndian.Uint16(payload[1:3])), + Key: parseVarUint64(payload[1:3]), Value: payload[3 : 3+1], // docs say offset 2? Length: 4, }, nil @@ -94,18 +90,18 @@ func (ctx *FmpFile) readChunk(payload []byte) (*FmpChunk, error) { length := 2 * (payload[0] - 9) return &FmpChunk{ Type: FMP_CHUNK_SIMPLE_KEY_VALUE, - Key: uint32(binary.BigEndian.Uint16(payload[1:3])), + Key: parseVarUint64(payload[1:3]), Value: payload[3 : 3+length], // docs say offset 2? - Length: 2 + uint32(length), + Length: 2 + uint64(length), }, nil } if payload[0] == 0x0E { length := payload[2] return &FmpChunk{ Type: FMP_CHUNK_SIMPLE_KEY_VALUE, - Key: uint32(binary.BigEndian.Uint16(payload[1:3])), + Key: parseVarUint64(payload[1:3]), Value: payload[4 : 4+length], // docs say offset 2? - Length: 4 + uint32(length), + Length: 4 + uint64(length), }, nil } @@ -115,18 +111,18 @@ func (ctx *FmpFile) readChunk(payload []byte) (*FmpChunk, error) { length := payload[4] return &FmpChunk{ Type: FMP_CHUNK_LONG_KEY_VALUE, - Key: parseVarUint32(payload[1 : 1+3]), + Key: parseVarUint64(payload[1 : 1+3]), Value: payload[5 : 5+length], - Length: 5 + uint32(length), + Length: 5 + uint64(length), }, nil } if payload[0] == 0x17 { - length := uint32(binary.BigEndian.Uint16(payload[4 : 4+2])) + length := parseVarUint64(payload[4 : 4+2]) return &FmpChunk{ Type: FMP_CHUNK_LONG_KEY_VALUE, - Key: uint32(binary.BigEndian.Uint16(payload[1 : 1+2])), + Key: parseVarUint64(payload[1 : 1+2]), Value: payload[6 : 6+length], - Length: 6 + uint32(length), + Length: 6 + uint64(length), }, nil } if payload[0] == 0x1E { @@ -134,40 +130,40 @@ func (ctx *FmpFile) readChunk(payload []byte) (*FmpChunk, error) { valueLength := payload[2+keyLength] return &FmpChunk{ Type: FMP_CHUNK_LONG_KEY_VALUE, - Key: parseVarUint32(payload[2 : 2+keyLength]), + Key: parseVarUint64(payload[2 : 2+keyLength]), Value: payload[2+keyLength+1 : 2+keyLength+1+valueLength], - Length: 3 + uint32(keyLength) + uint32(valueLength), + Length: 3 + uint64(keyLength) + uint64(valueLength), }, nil } if payload[0] == 0x1F { - keyLength := uint32(payload[1]) - valueLength := parseVarUint32(payload[2+keyLength : 2+keyLength+2+1]) + keyLength := uint64(payload[1]) + valueLength := parseVarUint64(payload[2+keyLength : 2+keyLength+2+1]) return &FmpChunk{ Type: FMP_CHUNK_LONG_KEY_VALUE, - Key: parseVarUint32(payload[2 : 2+keyLength]), + Key: parseVarUint64(payload[2 : 2+keyLength]), Value: payload[2+keyLength+2 : 2+keyLength+2+valueLength], - Length: 4 + uint32(keyLength) + uint32(valueLength), + Length: 4 + uint64(keyLength) + uint64(valueLength), }, nil } // Segmented data if payload[0] == 0x07 { - length := binary.BigEndian.Uint16(payload[2 : 2+2]) - payloadLimit := min(4+length, uint16(len(payload))) + length := parseVarUint64(payload[2 : 2+2]) + payloadLimit := min(4+length, uint64(len(payload))) return &FmpChunk{ Type: FMP_CHUNK_SEGMENTED_DATA, - Index: uint32(payload[1]), + Index: uint64(payload[1]), Value: payload[4:payloadLimit], - Length: 4 + uint32(length), + Length: 4 + uint64(length), }, nil } if payload[0] == 0x0F { - length := uint32(binary.BigEndian.Uint16(payload[3 : 3+2])) - payloadLimit := min(5+length, uint32(len(payload))) + length := parseVarUint64(payload[3 : 3+2]) + payloadLimit := min(5+length, uint64(len(payload))) return &FmpChunk{ Type: FMP_CHUNK_SEGMENTED_DATA, - Index: uint32(binary.BigEndian.Uint16(payload[1 : 1+2])), + Index: parseVarUint64(payload[1 : 1+2]), Value: payload[5:payloadLimit], Length: 5 + length, }, nil @@ -208,7 +204,7 @@ func (ctx *FmpFile) readChunk(payload []byte) (*FmpChunk, error) { return &FmpChunk{ Type: FMP_CHUNK_PATH_PUSH, Value: payload[2 : 2+length], - Length: 2 + uint32(length), + Length: 2 + uint64(length), }, nil } diff --git a/fmp/fmp_file.go b/fmp/fmp_file.go index 3bca990..70399d0 100644 --- a/fmp/fmp_file.go +++ b/fmp/fmp_file.go @@ -2,7 +2,6 @@ package fmp import ( "bytes" - "encoding/binary" "io" "os" "time" @@ -39,7 +38,7 @@ func OpenFile(path string) (*FmpFile, error) { ctx.NumSectors = ctx.FileSize / sectorSize ctx.Sectors = make([]*FmpSector, ctx.NumSectors) - currentPath := make([]uint16, 0) + currentPath := make([]uint64, 0) for i := uint(0); i < ctx.NumSectors; i++ { sector, err := ctx.readSector() @@ -55,7 +54,7 @@ func OpenFile(path string) (*FmpFile, error) { for _, chunk := range sector.Chunks { switch chunk.Type { case FMP_CHUNK_PATH_PUSH: - currentPath = append(currentPath, uint16(chunk.Value[0])) + currentPath = append(currentPath, uint64(chunk.Value[0])) case FMP_CHUNK_PATH_POP: if len(currentPath) > 0 { @@ -74,13 +73,13 @@ func OpenFile(path string) (*FmpFile, error) { case FMP_CHUNK_SIMPLE_KEY_VALUE: ctx.Dictionary.set( - append(currentPath, uint16(chunk.Key)), + append(currentPath, uint64(chunk.Key)), chunk.Value, ) case FMP_CHUNK_LONG_KEY_VALUE: ctx.Dictionary.set( - append(currentPath, uint16(chunk.Key)), // todo: ?? + append(currentPath, uint64(chunk.Key)), // todo: ?? chunk.Value, ) @@ -131,8 +130,8 @@ func (ctx *FmpFile) readSector() (*FmpSector, error) { sector := &FmpSector{ Deleted: buf[0] != 0, Level: uint8(buf[1]), - PrevSectorID: binary.BigEndian.Uint32(buf[2:6]), - NextSectorID: binary.BigEndian.Uint32(buf[6:10]), + PrevSectorID: parseVarUint64(buf[2:6]), + NextSectorID: parseVarUint64(buf[6:10]), } payload := make([]byte, sectorSize-sectorHeaderSize) @@ -160,7 +159,7 @@ func (ctx *FmpFile) readSector() (*FmpSector, error) { panic("chunk length not set") } sector.Chunks = append(sector.Chunks, chunk) - payload = payload[min(chunk.Length, uint32(len(payload))):] + payload = payload[min(chunk.Length, uint64(len(payload))):] if len(payload) == 0 || (len(payload) == 1 && payload[0] == 0x00) { break } diff --git a/fmp/fmp_table.go b/fmp/fmp_table.go index 60592ff..5b2bf6c 100644 --- a/fmp/fmp_table.go +++ b/fmp/fmp_table.go @@ -2,9 +2,9 @@ package fmp func (ctx *FmpFile) Tables() []*FmpTable { tables := make([]*FmpTable, 0) - metaDict := ctx.Dictionary.get([]uint16{4, 1, 7}) + metaDict := ctx.Dictionary.get([]uint64{4, 1, 7}) for _, meta := range *metaDict.Children { - name := decodeByteSeq(meta.Children.get([]uint16{16}).Value) + name := decodeByteSeq(meta.Children.get([]uint64{16}).Value) table := &FmpTable{Name: name} tables = append(tables, table) } diff --git a/fmp/fmp_type.go b/fmp/fmp_type.go index d015c51..3f53ce5 100644 --- a/fmp/fmp_type.go +++ b/fmp/fmp_type.go @@ -19,20 +19,20 @@ type FmpFile struct { type FmpSector struct { Deleted bool Level uint8 - PrevSectorID uint32 - NextSectorID uint32 + PrevSectorID uint64 + NextSectorID uint64 Chunks []*FmpChunk } type FmpChunk struct { Type FmpChunkType - Length uint32 - Key uint32 // If Type == FMP_CHUNK_SHORT_KEY_VALUE or FMP_CHUNK_LONG_KEY_VALUE - Index uint32 // Segment index, if Type == FMP_CHUNK_SEGMENTED_DATA + Length uint64 + Key uint64 // If Type == FMP_CHUNK_SHORT_KEY_VALUE or FMP_CHUNK_LONG_KEY_VALUE + Index uint64 // Segment index, if Type == FMP_CHUNK_SEGMENTED_DATA Value []byte } -type FmpDict map[uint16]*FmpDictEntry +type FmpDict map[uint64]*FmpDictEntry type FmpDictEntry struct { Value []byte @@ -43,7 +43,7 @@ type FmpTable struct { Name string } -func (dict *FmpDict) get(path []uint16) *FmpDictEntry { +func (dict *FmpDict) get(path []uint64) *FmpDictEntry { for i, key := range path { _, ok := (*dict)[key] if !ok { @@ -59,7 +59,7 @@ func (dict *FmpDict) get(path []uint16) *FmpDictEntry { return nil } -func (dict *FmpDict) getValue(path []uint16) []byte { +func (dict *FmpDict) getValue(path []uint64) []byte { ent := dict.get(path) if ent != nil { return ent.Value @@ -67,7 +67,7 @@ func (dict *FmpDict) getValue(path []uint16) []byte { return nil } -func (dict *FmpDict) set(path []uint16, value []byte) { +func (dict *FmpDict) set(path []uint64, value []byte) { for i, key := range path { _, ok := (*dict)[key] if !ok { diff --git a/fmp/fmp_util.go b/fmp/fmp_util.go index 59ca347..eafe231 100644 --- a/fmp/fmp_util.go +++ b/fmp/fmp_util.go @@ -1,14 +1,14 @@ package fmp -func parseVarUint32(payload []byte) uint32 { - var length uint32 +func parseVarUint64(payload []byte) uint64 { + var length uint64 n := len(payload) - if n > 4 { - n = 4 // clamp to max uint32 + if n > 8 { + n = 8 // clamp to max uint64 } for i := range n { length <<= 8 - length |= uint32(payload[i]) + length |= uint64(payload[i]) } return length }