mirror of
https://github.com/garraflavatra/go-fmp.git
synced 2025-06-27 20:15:11 +00:00
Add NewSector function
This commit is contained in:
@ -42,7 +42,7 @@ func (dict *FmpDict) GetChildren(path ...uint64) *FmpDict {
|
||||
return &FmpDict{}
|
||||
}
|
||||
|
||||
func (dict *FmpDict) SetValue(path []uint64, value []byte) {
|
||||
func (dict *FmpDict) set(path []uint64, value []byte) {
|
||||
for i, key := range path {
|
||||
_, ok := (*dict)[key]
|
||||
if !ok {
|
||||
|
@ -32,7 +32,7 @@ type FmpFile struct {
|
||||
numSectors uint64 // Excludes the header sector
|
||||
currentSectorID uint64
|
||||
|
||||
stream io.ReadSeeker
|
||||
stream *os.File
|
||||
}
|
||||
|
||||
func OpenFile(path string) (*FmpFile, error) {
|
||||
@ -41,11 +41,10 @@ func OpenFile(path string) (*FmpFile, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
stream, err := os.Open(path)
|
||||
stream, err := os.OpenFile(path, os.O_RDWR, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer stream.Close()
|
||||
|
||||
ctx := &FmpFile{stream: stream, Dictionary: &FmpDict{}}
|
||||
if err := ctx.readHeader(); err != nil {
|
||||
@ -90,6 +89,10 @@ func OpenFile(path string) (*FmpFile, error) {
|
||||
return ctx, nil
|
||||
}
|
||||
|
||||
func (ctx *FmpFile) Close() {
|
||||
ctx.stream.Close()
|
||||
}
|
||||
|
||||
func (ctx *FmpFile) readHeader() error {
|
||||
buf := make([]byte, headerSize)
|
||||
_, err := ctx.stream.Read(buf)
|
||||
@ -208,3 +211,43 @@ func (ctx *FmpFile) readTables() {
|
||||
|
||||
ctx.tables = tables
|
||||
}
|
||||
|
||||
func (ctx *FmpFile) NewSector() (*FmpSector, error) {
|
||||
id := uint64(len(ctx.Sectors)) + 1
|
||||
prevID := id - 2
|
||||
|
||||
ctx.Sectors[prevID].NextID = uint64(id)
|
||||
_, err := ctx.stream.WriteAt(encodeUint(4, int(id)), int64((id-1)*sectorSize)+4)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sector := &FmpSector{
|
||||
ID: uint64(id),
|
||||
Deleted: false,
|
||||
Level: 0,
|
||||
PrevID: prevID,
|
||||
NextID: 0,
|
||||
Chunks: make([]*FmpChunk, 0),
|
||||
}
|
||||
|
||||
ctx.Sectors = append(ctx.Sectors, sector)
|
||||
|
||||
sectorBuf := make([]byte, sectorSize)
|
||||
sectorBuf[0] = 0 // deleted
|
||||
sectorBuf[1] = 0 // level
|
||||
writeToSlice(sectorBuf, 4, encodeUint(4, int(prevID))...)
|
||||
writeToSlice(sectorBuf, 8, encodeUint(4, int(id))...)
|
||||
|
||||
_, err = ctx.stream.WriteAt(sectorBuf, int64((id+1)*sectorSize))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return sector, nil
|
||||
}
|
||||
|
||||
func (ctx *FmpFile) setValue(path []uint64, value []byte) {
|
||||
// ctx.Dictionary.set(path, value)
|
||||
|
||||
}
|
||||
|
@ -79,23 +79,23 @@ func (sect *FmpSector) processChunks(dict *FmpDict) error {
|
||||
}
|
||||
|
||||
case FmpChunkSimpleData:
|
||||
dict.SetValue(currentPath, chunk.Value)
|
||||
dict.set(currentPath, chunk.Value)
|
||||
|
||||
case FmpChunkSegmentedData:
|
||||
// Todo: take index into account
|
||||
dict.SetValue(
|
||||
dict.set(
|
||||
currentPath,
|
||||
append(dict.GetValue(currentPath...), chunk.Value...),
|
||||
)
|
||||
|
||||
case FmpChunkSimpleKeyValue:
|
||||
dict.SetValue(
|
||||
dict.set(
|
||||
append(currentPath, uint64(chunk.Key)),
|
||||
chunk.Value,
|
||||
)
|
||||
|
||||
case FmpChunkLongKeyValue:
|
||||
dict.SetValue(
|
||||
dict.set(
|
||||
append(currentPath, uint64(chunk.Key)), // todo: ??
|
||||
chunk.Value,
|
||||
)
|
||||
|
@ -10,8 +10,10 @@ func TestOpenFile(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
if f.FileSize != 229376 {
|
||||
t.Errorf("expected file size to be 393216, got %d", f.FileSize)
|
||||
t.Errorf("expected file size to be 229376, got %d", f.FileSize)
|
||||
}
|
||||
if f.numSectors != 55 {
|
||||
t.Errorf("expected number of sectors to be 55, got %d", f.numSectors)
|
||||
@ -22,6 +24,7 @@ func TestOpenFile(t *testing.T) {
|
||||
if f.VersionDate.Format("2006-01-02") != "2025-01-11" {
|
||||
t.Errorf("expected version date to be '2025-01-11', got '%s'", f.VersionDate.Format("2006-01-02"))
|
||||
}
|
||||
|
||||
f.ToDebugFile("../private/output")
|
||||
}
|
||||
|
||||
@ -30,6 +33,7 @@ func TestTables(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
expectedNames := []string{"Untitled"}
|
||||
tableNames := []string{}
|
||||
|
@ -24,3 +24,18 @@ func decodeString(payload []byte) string {
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func encodeUint(size uint, value int) []byte {
|
||||
result := make([]byte, size)
|
||||
for i := range size {
|
||||
result[i] = byte(value & 0xFF)
|
||||
value >>= 8
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func writeToSlice(slice []byte, start int, payload ...byte) {
|
||||
for i := range payload {
|
||||
slice[start+i] = payload[i]
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user