1
1
mirror of https://github.com/wader/fq.git synced 2024-09-20 08:18:51 +03:00

decode: Refactor walk code a bit, add WalkRoot* to stay inside one root

This commit is contained in:
Mattias Wadman 2021-10-18 15:06:08 +02:00
parent ec97eca054
commit 8eaba88a10
2 changed files with 54 additions and 32 deletions

View File

@ -157,11 +157,7 @@ func decode(ctx context.Context, bb *bitio.Buffer, formats []*Format, opts Optio
}
var maxRange ranges.Range
if err := d.Value.WalkPreOrder(func(v *Value, rootV *Value, depth int, rootDepth int) error {
if d.Value != v && v.IsRoot {
return ErrWalkSkipChildren
}
if err := d.Value.WalkRootPreOrder(func(v *Value, rootV *Value, depth int, rootDepth int) error {
maxRange = ranges.MinMax(maxRange, v.Range)
v.Range.Start += opts.StartOffset
v.RootBitBuf = d.Value.RootBitBuf
@ -243,9 +239,6 @@ func (d *D) FillGaps(namePrefix string) {
makeWalkFn := func(fn func(iv *Value)) func(iv *Value, rootV *Value, depth int, rootDepth int) error {
return func(iv *Value, rootV *Value, depth int, rootDepth int) error {
if iv.RootBitBuf != d.Value.RootBitBuf && iv.IsRoot {
return ErrWalkSkipChildren
}
switch iv.V.(type) {
case Struct, Array:
default:
@ -259,10 +252,10 @@ func (d *D) FillGaps(namePrefix string) {
// TODO: gaps things should be done in Framed* funcs
// TODO: pre-sorted somehow?
n := 0
_ = d.Value.WalkPreOrder(makeWalkFn(func(iv *Value) { n++ }))
_ = d.Value.WalkRootPreOrder(makeWalkFn(func(iv *Value) { n++ }))
valueRanges := make([]ranges.Range, n)
i := 0
_ = d.Value.WalkPreOrder(makeWalkFn(func(iv *Value) {
_ = d.Value.WalkRootPreOrder(makeWalkFn(func(iv *Value) {
valueRanges[i] = iv.Range
i++
}))
@ -821,11 +814,7 @@ func (d *D) DecodeRangeFn(firstBit int64, nBits int64, fn func(d *D)) {
fn(sd)
// TODO: refactor, similar to decode()
if err := sd.Value.WalkPreOrder(func(v *Value, rootV *Value, depth int, rootDepth int) error {
if v.IsRoot {
return ErrWalkSkipChildren
}
if err := sd.Value.WalkRootPreOrder(func(v *Value, rootV *Value, depth int, rootDepth int) error {
//v.Range.Start += firstBit
v.RootBitBuf = d.Value.RootBitBuf

View File

@ -59,17 +59,28 @@ var ErrWalkSkipChildren = errors.New("skip children")
var ErrWalkBreak = errors.New("break")
var ErrWalkStop = errors.New("stop")
func (v *Value) walk(preOrder bool, fn WalkFn) error {
type WalkOpts struct {
PreOrder bool
OneRoot bool
Fn WalkFn
}
func (v *Value) Walk(opts WalkOpts) error {
var walkFn WalkFn
walkFn = func(v *Value, rootV *Value, depth int, rootDepth int) error {
walkFn = func(wv *Value, rootV *Value, depth int, rootDepth int) error {
if opts.OneRoot && wv != v && wv.IsRoot {
return nil
}
rootDepthDelta := 0
if v.IsRoot {
rootV = v
if wv.IsRoot {
rootV = wv
rootDepthDelta = 1
}
if preOrder {
err := fn(v, rootV, depth, rootDepth+rootDepthDelta)
if opts.PreOrder {
err := opts.Fn(wv, rootV, depth, rootDepth+rootDepthDelta)
switch {
case errors.Is(err, ErrWalkSkipChildren):
return nil
@ -82,7 +93,7 @@ func (v *Value) walk(preOrder bool, fn WalkFn) error {
}
}
switch v := v.V.(type) {
switch v := wv.V.(type) {
case Struct:
for _, wv := range v {
if err := walkFn(wv, rootV, depth+1, rootDepth+rootDepthDelta); err != nil {
@ -102,8 +113,8 @@ func (v *Value) walk(preOrder bool, fn WalkFn) error {
}
}
}
if !preOrder {
err := fn(v, rootV, depth, rootDepth+rootDepthDelta)
if !opts.PreOrder {
err := opts.Fn(wv, rootV, depth, rootDepth+rootDepthDelta)
switch {
case errors.Is(err, ErrWalkSkipChildren):
return errors.New("can't skip children in post-order")
@ -129,6 +140,36 @@ func (v *Value) walk(preOrder bool, fn WalkFn) error {
return err
}
func (v *Value) WalkPreOrder(fn WalkFn) error {
return v.Walk(WalkOpts{
PreOrder: true,
Fn: fn,
})
}
func (v *Value) WalkPostOrder(fn WalkFn) error {
return v.Walk(WalkOpts{
PreOrder: false,
Fn: fn,
})
}
func (v *Value) WalkRootPreOrder(fn WalkFn) error {
return v.Walk(WalkOpts{
PreOrder: true,
OneRoot: true,
Fn: fn,
})
}
func (v *Value) WalkRootPostOrder(fn WalkFn) error {
return v.Walk(WalkOpts{
PreOrder: false,
OneRoot: true,
Fn: fn,
})
}
func (v *Value) root(findSubRoot bool, findFormatRoot bool) *Value {
rootV := v
for rootV.Parent != nil {
@ -148,14 +189,6 @@ func (v *Value) Root() *Value { return v.root(false, false) }
func (v *Value) BufferRoot() *Value { return v.root(true, false) }
func (v *Value) FormatRoot() *Value { return v.root(true, true) }
func (v *Value) WalkPreOrder(fn WalkFn) error {
return v.walk(true, fn)
}
func (v *Value) WalkPostOrder(fn WalkFn) error {
return v.walk(false, fn)
}
func (v *Value) Errors() []error {
var errs []error
_ = v.WalkPreOrder(func(v *Value, rootV *Value, depth int, rootDepth int) error {