1
0
mirror of https://github.com/garraflavatra/go-fmp.git synced 2025-07-18 20:14:05 +00:00

Restructure, add script step constants

This commit is contained in:
2025-06-14 16:28:41 +02:00
parent 53134a0d09
commit 10285084eb
8 changed files with 390 additions and 200 deletions

View File

@ -1,10 +1,24 @@
package fmp
import (
"encoding/hex"
"fmt"
"io"
)
type FmpSector struct {
ID uint64
Level uint8
Deleted bool
PrevID uint64
NextID uint64
Prev *FmpSector
Next *FmpSector
Payload []byte
Chunks []*FmpChunk
}
type FmpChunk struct {
Type FmpChunkType
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
}
func (sect *FmpSector) readChunks() error {
if len(sect.Chunks) > 0 {
@ -24,12 +38,9 @@ func (sect *FmpSector) readChunks() error {
debug("0x%02x (pos %v, type %v)\n", sect.Payload[0], pos, int(chunk.Type))
}
if err == io.EOF {
break
}
if err != nil {
debug("chunk error at sector %d", sect.ID)
debug(hex.EncodeToString(sect.Payload))
dump(sect.Payload)
return err
}
if chunk == nil {
@ -58,43 +69,38 @@ func (sect *FmpSector) processChunks(dict *FmpDict) error {
currentPath := make([]uint64, 0)
for _, chunk := range sect.Chunks {
switch chunk.Type {
case FMP_CHUNK_PATH_PUSH, FMP_CHUNK_PATH_PUSH_LONG:
case FmpChunkPathPush, FmpChunkPathPushLong:
currentPath = append(currentPath, parseVarUint64(chunk.Value))
dumpPath(currentPath)
s := ""
for _, ent := range currentPath {
s += fmt.Sprintf("%v. ", ent)
}
debug("path: %s", s)
case FMP_CHUNK_PATH_POP:
case FmpChunkPathPop:
if len(currentPath) > 0 {
currentPath = (currentPath)[:len(currentPath)-1]
}
case FMP_CHUNK_SIMPLE_DATA:
case FmpChunkSimpleData:
dict.SetValue(currentPath, chunk.Value)
case FMP_CHUNK_SEGMENTED_DATA:
case FmpChunkSegmentedData:
// Todo: take index into account
dict.SetValue(
currentPath,
append(dict.GetValue(currentPath), chunk.Value...),
)
case FMP_CHUNK_SIMPLE_KEY_VALUE:
case FmpChunkSimpleKeyValue:
dict.SetValue(
append(currentPath, uint64(chunk.Key)),
chunk.Value,
)
case FMP_CHUNK_LONG_KEY_VALUE:
case FmpChunkLongKeyValue:
dict.SetValue(
append(currentPath, uint64(chunk.Key)), // todo: ??
chunk.Value,
)
case FMP_CHUNK_NOOP:
case FmpChunkNoop:
// noop
}
}
@ -112,55 +118,55 @@ func (sect *FmpSector) readChunk(payload []byte) (*FmpChunk, error) {
switch chunkCode {
case 0x00:
chunk.Length = 2
chunk.Type = FMP_CHUNK_SIMPLE_DATA
chunk.Type = FmpChunkSimpleData
chunk.Value = payload[1:chunk.Length]
case 0x01, 0x02, 0x03, 0x04, 0x05:
chunk.Length = 2 + 2*uint64(chunkCode-0x01) + addIf(chunkCode == 0x01, 1)
chunk.Type = FMP_CHUNK_SIMPLE_KEY_VALUE
chunk.Type = FmpChunkSimpleKeyValue
chunk.Key = uint64(payload[1])
chunk.Value = payload[2:chunk.Length]
case 0x06:
chunk.Length = 3 + uint64(payload[2])
chunk.Type = FMP_CHUNK_SIMPLE_KEY_VALUE
chunk.Type = FmpChunkSimpleKeyValue
chunk.Key = uint64(payload[1])
chunk.Value = payload[3:chunk.Length]
case 0x07:
valueLength := parseVarUint64(payload[2 : 2+2])
chunk.Length = min(4+valueLength, uint64(len(payload)))
chunk.Type = FMP_CHUNK_SEGMENTED_DATA
chunk.Type = FmpChunkSegmentedData
chunk.Index = uint64(payload[1])
chunk.Value = payload[4:chunk.Length]
case 0x08:
chunk.Length = 3
chunk.Type = FMP_CHUNK_SIMPLE_DATA
chunk.Type = FmpChunkSimpleData
chunk.Value = payload[1:chunk.Length]
case 0x09:
chunk.Length = 4
chunk.Type = FMP_CHUNK_SIMPLE_KEY_VALUE
chunk.Type = FmpChunkSimpleKeyValue
chunk.Key = parseVarUint64(payload[1 : 1+2])
chunk.Value = payload[3:chunk.Length]
case 0x0A, 0x0B, 0x0C, 0x0D:
chunk.Length = 3 + 2*uint64(chunkCode-0x09)
chunk.Type = FMP_CHUNK_SIMPLE_KEY_VALUE
chunk.Type = FmpChunkSimpleKeyValue
chunk.Key = parseVarUint64(payload[1 : 1+2])
chunk.Value = payload[3:chunk.Length]
case 0x0E:
if payload[1] == 0xFF {
chunk.Length = 7
chunk.Type = FMP_CHUNK_SIMPLE_DATA
chunk.Type = FmpChunkSimpleData
chunk.Value = payload[2:chunk.Length]
break
}
chunk.Length = 4 + uint64(payload[3])
chunk.Type = FMP_CHUNK_SIMPLE_KEY_VALUE
chunk.Type = FmpChunkSimpleKeyValue
chunk.Key = parseVarUint64(payload[1 : 1+2])
chunk.Value = payload[4:chunk.Length]
@ -170,43 +176,43 @@ func (sect *FmpSector) readChunk(payload []byte) (*FmpChunk, error) {
if chunk.Length > 5+valueLength {
return nil, ErrBadChunk
}
chunk.Type = FMP_CHUNK_SEGMENTED_DATA
chunk.Type = FmpChunkSegmentedData
chunk.Index = parseVarUint64(payload[1 : 1+2])
chunk.Value = payload[5:chunk.Length]
case 0x10, 0x11:
chunk.Length = 4 + addIf(chunkCode == 0x11, 1)
chunk.Type = FMP_CHUNK_SIMPLE_DATA
chunk.Type = FmpChunkSimpleData
chunk.Value = payload[1:chunk.Length]
case 0x12, 0x13, 0x14, 0x15:
chunk.Length = 4 + 2*(uint64(chunkCode)-0x11)
chunk.Type = FMP_CHUNK_SIMPLE_DATA
chunk.Type = FmpChunkSimpleData
chunk.Value = payload[1:chunk.Length]
case 0x16:
chunk.Length = 5 + uint64(payload[4])
chunk.Type = FMP_CHUNK_LONG_KEY_VALUE
chunk.Type = FmpChunkLongKeyValue
chunk.Key = parseVarUint64(payload[1 : 1+3])
chunk.Value = payload[5:chunk.Length]
case 0x17:
chunk.Length = 6 + parseVarUint64(payload[4:4+2])
chunk.Type = FMP_CHUNK_LONG_KEY_VALUE
chunk.Type = FmpChunkLongKeyValue
chunk.Key = parseVarUint64(payload[1 : 1+3])
chunk.Value = payload[6:chunk.Length]
case 0x19, 0x1A, 0x1B, 0x1C, 0x1D:
valueLength := uint64(payload[1])
chunk.Length = 2 + valueLength + 2*uint64(chunkCode-0x19) + addIf(chunkCode == 0x19, 1)
chunk.Type = FMP_CHUNK_SIMPLE_DATA
chunk.Type = FmpChunkSimpleData
chunk.Value = payload[2 : 2+valueLength]
case 0x1E:
keyLength := uint64(payload[1])
valueLength := uint64(payload[2+keyLength])
chunk.Length = 2 + keyLength + 1 + valueLength
chunk.Type = FMP_CHUNK_LONG_KEY_VALUE
chunk.Type = FmpChunkLongKeyValue
chunk.Key = parseVarUint64(payload[2 : 2+keyLength])
chunk.Value = payload[2+keyLength+1 : chunk.Length]
@ -214,44 +220,44 @@ func (sect *FmpSector) readChunk(payload []byte) (*FmpChunk, error) {
keyLength := uint64(payload[1])
valueLength := parseVarUint64(payload[2+keyLength : 2+keyLength+2+1])
chunk.Length = 2 + keyLength + 2 + valueLength
chunk.Type = FMP_CHUNK_LONG_KEY_VALUE
chunk.Type = FmpChunkLongKeyValue
chunk.Key = parseVarUint64(payload[2 : 2+keyLength])
chunk.Value = payload[2+keyLength+2 : chunk.Length]
case 0x20, 0xE0:
if payload[1] == 0xFE {
chunk.Length = 10
chunk.Type = FMP_CHUNK_PATH_PUSH
chunk.Type = FmpChunkPathPush
chunk.Value = payload[2:chunk.Length]
break
}
chunk.Length = 2
chunk.Type = FMP_CHUNK_PATH_PUSH
chunk.Type = FmpChunkPathPush
chunk.Value = payload[1:chunk.Length]
case 0x23:
chunk.Length = 2 + uint64(payload[1])
chunk.Type = FMP_CHUNK_SIMPLE_DATA
chunk.Type = FmpChunkSimpleData
chunk.Value = payload[1:chunk.Length]
case 0x28, 0x30:
chunk.Length = 3 + addIf(chunkCode == 0x30, 1)
chunk.Type = FMP_CHUNK_PATH_PUSH
chunk.Type = FmpChunkPathPush
chunk.Value = payload[1:chunk.Length]
case 0x38:
valueLength := uint64(payload[1])
chunk.Length = 2 + valueLength
chunk.Type = FMP_CHUNK_PATH_PUSH_LONG
chunk.Type = FmpChunkPathPushLong
chunk.Value = payload[2:chunk.Length]
case 0x3D, 0x40:
chunk.Type = FMP_CHUNK_PATH_POP
chunk.Type = FmpChunkPathPop
chunk.Length = 1
case 0x80:
chunk.Type = FMP_CHUNK_NOOP
chunk.Type = FmpChunkNoop
chunk.Length = 1
default:
@ -260,10 +266,3 @@ func (sect *FmpSector) readChunk(payload []byte) (*FmpChunk, error) {
return chunk, nil
}
func addIf(cond bool, val uint64) uint64 {
if cond {
return val
}
return 0
}