]> Cypherpunks repositories - keks.git/commitdiff
Add optional offsets storage
authorSergey Matveev <stargrave@stargrave.org>
Wed, 8 Jan 2025 16:02:22 +0000 (19:02 +0300)
committerSergey Matveev <stargrave@stargrave.org>
Wed, 8 Jan 2025 16:02:22 +0000 (19:02 +0300)
go/atom-decode.go
go/cmd/print/main.go
go/ctx.go
go/iter.go
go/parse.go

index bc4096e52aed8f00e08cf04780ff7cfbfc4487dbb6570747a1b57b55960770ae..443ed14da6629e38fe4ace2492e838daef9134ac1b1231b99fc46eb28724150b 100644 (file)
@@ -37,6 +37,9 @@ var (
 )
 
 func (ctx *Decoder) DecodeAtom() (t types.Type, err error) {
+       if ctx.opts != nil && ctx.opts.SaveOffsets {
+               ctx.offsets = append(ctx.offsets, ctx.Read)
+       }
        var tag byte
        tag, err = ctx.getByte()
        if err != nil {
index 7b308c3cb1b45146d9cfb303e4ceb8fae2e2d5709095b1afcfd8c04f980a8a2a..989000855b87ab1f15bf20789141e71552b7f4a91ef5240e228564d46e0d1282 100644 (file)
@@ -41,6 +41,16 @@ func hexenc(b []byte) string {
        return strings.ToUpper(hex.EncodeToString(b))
 }
 
+func printbin(s []byte) {
+       sLen := len(s)
+       var dots string
+       if sLen > int(*MaxStrLen) {
+               s = s[:int(*MaxStrLen)]
+               dots = "..."
+       }
+       fmt.Printf("%s%d%s:%s%s\n", Magenta, sLen, Reset, hexenc(s), dots)
+}
+
 func printer(iter *keks.Iterator, count int, inList, inMap bool) {
        for i := 0; i < count; i++ {
                if !iter.Next() {
@@ -48,26 +58,31 @@ func printer(iter *keks.Iterator, count int, inList, inMap bool) {
                }
                depth := iter.Depth
                fmt.Print(Blue + strconv.Itoa(depth) + Reset)
+               var key string
+               if inMap {
+                       key = iter.Str()
+                       if !iter.Next() {
+                               panic("unexpected")
+                       }
+               }
+               fmt.Printf(" %s%03d%s ", Red, iter.Offset(), Reset)
                prindent(depth)
                if inList {
                        fmt.Printf("%s%d:%s ", Yellow, i, Reset)
                } else if inMap {
-                       fmt.Printf("%s%s%s: ", Green, iter.Str(), Reset)
-                       if !iter.Next() {
-                               panic("unexpected")
-                       }
+                       fmt.Printf("%s%s%s: ", Green, key, Reset)
                }
                switch iter.T {
                case types.List:
                        fmt.Printf("[ %s%d%s\n", Cyan, iter.Len(), Reset)
                        printer(iter, iter.Len(), true, false)
                        prindent(depth)
-                       fmt.Println(" ]")
+                       fmt.Println("     " + " ]")
                case types.Map:
                        fmt.Printf("{ %s%d%s\n", Cyan, iter.Len(), Reset)
                        printer(iter, iter.Len(), false, true)
                        prindent(depth)
-                       fmt.Println(" }")
+                       fmt.Println("     " + " }")
 
                case types.NIL:
                        fmt.Println("NIL")
@@ -88,10 +103,17 @@ func printer(iter *keks.Iterator, count int, inList, inMap bool) {
                case types.Blob:
                        blob := iter.Blob()
                        fmt.Printf("BLOB[ %s%d l=%d%s\n", Cyan, len(blob.Chunks), blob.ChunkLen, Reset)
+                       off := iter.Offset() + 1 + 8
                        for i, chunk := range blob.Chunks {
-                               fmt.Print(strings.Repeat("  ", iter.Depth+1))
-                               fmt.Printf("%d: %d:%s\n", i, len(chunk), hexenc([]byte(chunk)))
+                               fmt.Print(Blue + strconv.Itoa(depth+1) + Reset)
+                               fmt.Printf(" %s%03d%s ", Red, off, Reset)
+                               prindent(depth + 1)
+                               fmt.Printf("%s%d:%s ", Yellow, i, Reset)
+                               printbin([]byte(chunk))
+                               off += int64(len(chunk)) + 1
                        }
+                       prindent(depth)
+                       fmt.Println("     " + " ]")
                case types.TAI64:
                        t := iter.TAI64().Time()
                        utc, isLeap := tai64n.Leapsecs.Sub(t)
@@ -116,17 +138,12 @@ func printer(iter *keks.Iterator, count int, inList, inMap bool) {
                        t := iter.TAI64NA()
                        fmt.Printf("TAI64NA(%s)\n", hexenc(t[:]))
                case types.Bin:
-                       s := iter.Bin()
-                       var dots string
-                       if len(s) > int(*MaxStrLen) {
-                               s = s[:int(*MaxStrLen)]
-                               dots = "..."
-                       }
-                       fmt.Printf("%s%d%s:%s%s\n", Magenta, len(s), Reset, hexenc(s), dots)
+                       printbin(iter.Bin())
                case types.Str:
                        fmt.Print(`"`)
                        s := iter.Str()
-                       if len(s) > int(*MaxStrLen) {
+                       sLen := len(s)
+                       if sLen > int(*MaxStrLen) {
                                fmt.Print(s[:int(*MaxStrLen)])
                                fmt.Print("...")
                        } else {
@@ -143,7 +160,10 @@ func printer(iter *keks.Iterator, count int, inList, inMap bool) {
 
 func main() {
        flag.Parse()
-       ctx := keks.NewDecoderFromReader(bufio.NewReader(os.Stdin), nil)
+       ctx := keks.NewDecoderFromReader(
+               bufio.NewReader(os.Stdin),
+               &keks.DecodeOpts{SaveOffsets: true},
+       )
        _, err := ctx.Parse()
        if err != nil {
                log.Fatal(err)
index 3e7f903f16425fd142bab3f9ffa029c369f77a139c461a9ad057f44e7cabcff0..7546f66143386b2ac265207c6fc3f1b90dc880eed698884d396340ce6f87d0b3 100644 (file)
--- a/go/ctx.go
+++ b/go/ctx.go
@@ -38,6 +38,9 @@ type DecodeOpts struct {
 
        // Leave TAI64* values as is, do not convert to time.Time during unmarshal.
        LeaveTAI64 bool
+
+       // Store items offsets.
+       SaveOffsets bool
 }
 
 type Decoder struct {
@@ -50,9 +53,10 @@ type Decoder struct {
 
        opts *DecodeOpts
 
-       depth  int8
-       types  []types.Type
-       depths []int8
+       depth   int8
+       types   []types.Type
+       depths  []int8
+       offsets []int64
 
        bigints  []*big.Int
        bools    []bool
index bb327f743dff125790db08cf4ea54921c18a8f1ba00859e6b540576cefe07fa8..477613869c2ddd250ce0d50181f8dcacf77c8a46e1ccc6413d15db11cc69171a 100644 (file)
@@ -93,6 +93,12 @@ func (iter *Iterator) Next() bool {
        return true
 }
 
+// Get item's absolute offset.
+// Available only if was decoded with opts.SaveOffsets=true.
+func (iter *Iterator) Offset() int64 {
+       return iter.ctx.offsets[iter.i]
+}
+
 func (iter *Iterator) Bool() bool {
        return iter.ctx.bools[iter.bools]
 }
index 8b4107be4985a18bd6848156bed1373dc2cddb43584c828981efc6b1c1f92213..769fb5aef10c35776ee359f01232869f06b15fe82048fc7e48f0c188081eeb40 100644 (file)
@@ -33,6 +33,9 @@ var (
 func (ctx *Decoder) deTail() {
        ctx.types = ctx.types[:len(ctx.types)-1]
        ctx.depths = ctx.depths[:len(ctx.depths)-1]
+       if ctx.opts != nil && ctx.opts.SaveOffsets {
+               ctx.offsets = ctx.offsets[:len(ctx.offsets)-1]
+       }
 }
 
 func (ctx *Decoder) parse() (t types.Type, err error) {