mirror of
https://github.com/wader/fq.git
synced 2024-11-28 03:02:55 +03:00
110 lines
3.4 KiB
Markdown
110 lines
3.4 KiB
Markdown
# Implementation details
|
|
|
|
- fq uses a gojq fork that can be found at https://github.com/wader/gojq/tree/fq (the "fq" branch)
|
|
- cli readline uses raw mode so blocks ctrl-c to become a SIGINT
|
|
|
|
## Decoder implementation help
|
|
|
|
- Main goal in the end is to produce a tree that is user-friendly and easy to work with.
|
|
Prefer a nice and easy to use tree over nice decoder implementation.
|
|
- Use same names, symbols, constant number base etc as in specification.
|
|
- Decode only ranges you know what it is. If possible let "parent" decide what to do with unknown
|
|
bits by using `*Decode*Len/Range/Limit` funcitions.
|
|
- Try to no decode too much as one value.
|
|
A length encoded int could be two fields, but maybe a length prefixed string should be one.
|
|
Flags can be struct with bit-fields.
|
|
- Map as many value as possible to more usage symbolic values.
|
|
- Endian inherited inside one format decoder, defaults to big endian for new format decoder
|
|
- Make sure zero length or no frames etc found fails decoding
|
|
- Try validate input to make it non-ambiguous with other decoders
|
|
- Try keep decoder code as declarative as possible
|
|
- Split into multiple sub formats if possible. Makes it possible to use them separately.
|
|
- Validate/Assert
|
|
- Error/Fatal/panic
|
|
- Is format probeable or not?
|
|
- Can new formats be added to other formats
|
|
|
|
## Tests
|
|
|
|
Write new actual output:
|
|
```sh
|
|
make actual # write all actual outputs
|
|
WRITE_ACTUAL=1 go run -run ... # write only specific tests
|
|
```
|
|
|
|
## Debug
|
|
|
|
Split debug and normal output even when using repl:
|
|
|
|
Write `log` package output and stderr to a file that can be `tail -f`:ed in another terminal:
|
|
```sh
|
|
LOGFILE=/tmp/log go run fq.go ... 2>>/tmp/log
|
|
```
|
|
|
|
gojq execution debug:
|
|
```sh
|
|
GOJQ_DEBUG=1 go run -tags debug fq.go ...
|
|
```
|
|
|
|
Memory and CPU profile (will open a browser):
|
|
```sh
|
|
make memprof ARGS=". file"
|
|
make cpuprof ARGS=". test.mp3"
|
|
```
|
|
|
|
## From start to decoded value
|
|
|
|
```
|
|
main:main()
|
|
cli.Main(default registry)
|
|
interp.New(registry, std os interp implementation)
|
|
interp.(*Interp).Main()
|
|
interp.jq _main/0:
|
|
args.jq _args_parse/2
|
|
populate filenames for input/0
|
|
interp.jq inputs/0
|
|
foreach valid input/0 output
|
|
interp.jq open
|
|
funcs.go _open
|
|
interp.jq decode
|
|
funcs.go _decode
|
|
decode.go Decode(...)
|
|
...
|
|
interp.jq eval expr
|
|
funcs.go _eval
|
|
interp.jq display
|
|
funcs.go _display
|
|
for interp.(decodeValueBase).Display()
|
|
dump.go
|
|
print tree
|
|
empty output
|
|
```
|
|
|
|
## bitio and other io packages
|
|
|
|
```
|
|
*os.File, *bytes.Buffer
|
|
^
|
|
ctxreadseeker.Reader defers blocking io operations to a goroutine to make them cancellable
|
|
^
|
|
progressreadseeker.Reader approximates how much of a file has been read
|
|
^
|
|
aheadreadseeker.Reader does readahead caching
|
|
^
|
|
| (io.ReadSeeker interface)
|
|
|
|
|
bitio.Reader (implements bitio.Bit* interfaces)
|
|
^
|
|
| (bitio.Bit* interfaces)
|
|
|
|
|
bitio.Buffer convenience wrapper to read bytes from bit reader, create section readers etc
|
|
SectionBitReader
|
|
MultiBitReader
|
|
```
|
|
|
|
## jq oddities
|
|
|
|
```
|
|
jq -n '[1,2,3,4] | .[null:], .[null:2], .[2:null], .[:null]'
|
|
```
|