1
1
mirror of https://github.com/wader/fq.git synced 2024-12-24 13:52:02 +03:00

fq: Generate decode alises code

This commit is contained in:
Mattias Wadman 2021-09-04 12:54:26 +02:00
parent 834f4a5893
commit 8cb380e7d9
4 changed files with 104 additions and 57 deletions

View File

@ -20,8 +20,6 @@ import (
"net/url"
"time"
"github.com/wader/fq/format"
"github.com/wader/fq/format/registry"
"github.com/wader/fq/internal/aheadreadseeker"
"github.com/wader/fq/internal/ctxreadseeker"
"github.com/wader/fq/internal/gojqextra"
@ -34,7 +32,7 @@ import (
)
// TODO: make it nicer somehow? generate generators? remove from struct?
func (i *Interp) makeFunctions(registry *registry.Registry) []Function {
func (i *Interp) makeFunctions() []Function {
fs := []Function{
{[]string{"readline"}, 0, 2, i.readline, nil},
{[]string{"eval"}, 1, 2, nil, i.eval},
@ -54,10 +52,10 @@ func (i *Interp) makeFunctions(registry *registry.Registry) []Function {
{[]string{"history"}, 0, 0, i.history, nil},
{[]string{"open"}, 0, 0, i._open, nil},
{[]string{"decode"}, 0, 1, i.makeDecodeFn(registry, registry.MustGroup(format.PROBE)), nil},
{[]string{"_decode"}, 2, 2, i._decode, nil},
{[]string{"format"}, 0, 0, i.format, nil},
{[]string{"_display"}, 1, 1, nil, i.display},
{[]string{"_display"}, 1, 1, nil, i._display},
{[]string{"preview", "p"}, 0, 1, nil, i.preview},
{[]string{"hexdump", "hd", "h"}, 0, 1, nil, i.hexdump},
@ -98,9 +96,6 @@ func (i *Interp) makeFunctions(registry *registry.Registry) []Function {
{[]string{"find"}, 1, 1, nil, i.find},
}
for name, f := range i.registry.Groups {
fs = append(fs, Function{[]string{name}, 0, 0, i.makeDecodeFn(registry, f), nil})
}
return fs
}
@ -537,56 +532,52 @@ func (i *Interp) _open(c interface{}, a []interface{}) interface{} {
}
}
func (i *Interp) makeDecodeFn(registry *registry.Registry, decodeFormats []*decode.Format) func(c interface{}, a []interface{}) interface{} {
return func(c interface{}, a []interface{}) interface{} {
filename := "unnamed"
func (i *Interp) _decode(c interface{}, a []interface{}) interface{} {
filename := "unnamed"
// TODO: progress hack
// would be nice to move progress code into decode but it might be
// tricky to keep track of absolute positions in the underlaying readers
// when it uses BitBuf slices, maybe only in Pos()?
if bbf, ok := c.(*bitBufFile); ok {
if bbf.decodeDoneFn != nil {
defer bbf.decodeDoneFn()
}
filename = bbf.filename
// TODO: progress hack
// would be nice to move progress code into decode but it might be
// tricky to keep track of absolute positions in the underlaying readers
// when it uses BitBuf slices, maybe only in Pos()?
if bbf, ok := c.(*bitBufFile); ok {
if bbf.decodeDoneFn != nil {
defer bbf.decodeDoneFn()
}
bb, err := toBuffer(c)
if err != nil {
return err
}
opts := map[string]interface{}{}
if len(a) >= 1 {
formatName, err := toString(a[0])
if err != nil {
return fmt.Errorf("%s: %w", formatName, err)
}
decodeFormats, err = registry.Group(formatName)
if err != nil {
return fmt.Errorf("%s: %w", formatName, err)
}
}
dv, _, err := decode.Decode("", filename, bb, decodeFormats, decode.DecodeOptions{FormatOptions: opts})
if dv == nil {
var decodeFormatsErr decode.DecodeFormatsError
if errors.As(err, &decodeFormatsErr) {
var vs []interface{}
for _, fe := range decodeFormatsErr.Errs {
vs = append(vs, fe.Value())
}
return valueError{vs}
}
return valueError{err}
}
return makeDecodeValue(dv)
filename = bbf.filename
}
bb, err := toBuffer(c)
if err != nil {
return err
}
opts := map[string]interface{}{}
formatName, err := toString(a[0])
if err != nil {
return fmt.Errorf("%s: %w", formatName, err)
}
decodeFormats, err := i.registry.Group(formatName)
if err != nil {
return fmt.Errorf("%s: %w", formatName, err)
}
dv, _, err := decode.Decode("", filename, bb, decodeFormats, decode.DecodeOptions{FormatOptions: opts})
if dv == nil {
var decodeFormatsErr decode.DecodeFormatsError
if errors.As(err, &decodeFormatsErr) {
var vs []interface{}
for _, fe := range decodeFormatsErr.Errs {
vs = append(vs, fe.Value())
}
return valueError{vs}
}
return valueError{err}
}
return makeDecodeValue(dv)
}
func (i *Interp) format(c interface{}, a []interface{}) interface{} {
@ -601,7 +592,7 @@ func (i *Interp) format(c interface{}, a []interface{}) interface{} {
return f
}
func (i *Interp) display(c interface{}, a []interface{}) gojq.Iter {
func (i *Interp) _display(c interface{}, a []interface{}) gojq.Iter {
opts, err := i.Options(a...)
if err != nil {
return gojq.NewIter(err)

View File

@ -570,7 +570,7 @@ func (i *Interp) Eval(ctx context.Context, mode RunMode, c interface{}, src stri
}
var compilerOpts []gojq.CompilerOption
for _, f := range ni.makeFunctions(ni.registry) {
for _, f := range ni.makeFunctions() {
for _, n := range f.Names {
if f.IterFn != nil {
compilerOpts = append(compilerOpts,
@ -621,6 +621,18 @@ func (i *Interp) Eval(ctx context.Context, mode RunMode, c interface{}, src stri
fmt.Fprintf(sb, "include \"@format/%s\";\n", f.Name)
}
return bytes.NewReader(sb.Bytes()), nil
} else if filename == "decode.jq" {
sb := &bytes.Buffer{}
fmt.Fprintf(sb, "def decode($name; $opts): _decode($name; $opts);\n")
fmt.Fprintf(sb, "def decode($name): _decode($name; {});\n")
fmt.Fprintf(sb, "def decode: _decode(\"probe\"; {});\n")
for name := range i.registry.Groups {
fmt.Fprintf(sb, ""+
"def %[1]s($opts): _decode(%[1]q; $opts);\n"+
"def %[1]s: _decode(%[1]q; {});\n",
name)
}
return bytes.NewReader(sb.Bytes()), nil
} else {
formatName := strings.TrimRight(filename, ".jq")
for _, f := range allFormats {

View File

@ -4,6 +4,7 @@ include "args";
include "query";
# will include all per format specific function etc
include "@format/decode";
include "@format/all";
# optional user init

43
pkg/interp/testdata/decode.fqtest vendored Normal file
View File

@ -0,0 +1,43 @@
/test.mp3:
$ fq -i -d mp3 . /test.mp3
mp3> decode
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f| |.: {} unnamed (mp3)
0x000|49 44 33 04 00 00 00 00 00 23 54 53 53 45 00 00|ID3......#TSSE..| headers: [1]
* |until 0x2c.7 (45) | |
0x020| ff fb 40| ..@| frames: [3]
0x030|c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00|................|
* |until 0x283.7 (end) (599) | |
| | | footers: [0]
mp3> decode("mp3")
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f| |.: {} unnamed (mp3)
0x000|49 44 33 04 00 00 00 00 00 23 54 53 53 45 00 00|ID3......#TSSE..| headers: [1]
* |until 0x2c.7 (45) | |
0x020| ff fb 40| ..@| frames: [3]
0x030|c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00|................|
* |until 0x283.7 (end) (599) | |
| | | footers: [0]
mp3> decode("mp3"; {})
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f| |.: {} unnamed (mp3)
0x000|49 44 33 04 00 00 00 00 00 23 54 53 53 45 00 00|ID3......#TSSE..| headers: [1]
* |until 0x2c.7 (45) | |
0x020| ff fb 40| ..@| frames: [3]
0x030|c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00|................|
* |until 0x283.7 (end) (599) | |
| | | footers: [0]
mp3> probe
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f| |.: {} unnamed (mp3)
0x000|49 44 33 04 00 00 00 00 00 23 54 53 53 45 00 00|ID3......#TSSE..| headers: [1]
* |until 0x2c.7 (45) | |
0x020| ff fb 40| ..@| frames: [3]
0x030|c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00|................|
* |until 0x283.7 (end) (599) | |
| | | footers: [0]
mp3> probe({})
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f| |.: {} unnamed (mp3)
0x000|49 44 33 04 00 00 00 00 00 23 54 53 53 45 00 00|ID3......#TSSE..| headers: [1]
* |until 0x2c.7 (45) | |
0x020| ff fb 40| ..@| frames: [3]
0x030|c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00|................|
* |until 0x283.7 (end) (599) | |
| | | footers: [0]
mp3> ^D