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:
parent
ec97eca054
commit
8eaba88a10
@ -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
|
||||
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user