1
1
mirror of https://github.com/wader/fq.git synced 2024-12-18 02:41:44 +03:00
fq/pkg/interp/buffer.go

166 lines
3.7 KiB
Go
Raw Normal View History

2020-06-08 03:29:51 +03:00
package interp
import (
"bytes"
"fmt"
"io"
"math/big"
"github.com/wader/fq/internal/gojqextra"
"github.com/wader/fq/pkg/bitio"
"github.com/wader/fq/pkg/ranges"
2020-06-08 03:29:51 +03:00
)
2021-10-05 23:26:05 +03:00
var _ Value = BufferView{}
var _ ToBufferView = BufferView{}
2020-06-08 03:29:51 +03:00
type BufferView struct {
bb *bitio.Buffer
r ranges.Range
2020-06-08 03:29:51 +03:00
unit int
}
2021-10-05 23:26:05 +03:00
func bufferViewFromBuffer(bb *bitio.Buffer, unit int) BufferView {
return BufferView{
bb: bb,
r: ranges.Range{Start: 0, Len: bb.Len()},
2020-06-08 03:29:51 +03:00
unit: unit,
}
}
2021-10-05 23:26:05 +03:00
func (bv BufferView) toBytesBuffer(r ranges.Range) (*bytes.Buffer, error) {
bb, err := bv.bb.BitBufRange(r.Start, r.Len)
if err != nil {
return nil, err
}
buf := &bytes.Buffer{}
if _, err := io.Copy(buf, bb.Copy()); err != nil {
return nil, err
}
return buf, nil
}
func (BufferView) DisplayName() string { return "buffer" }
func (BufferView) ExtKeys() []string {
2020-06-08 03:29:51 +03:00
return []string{
"size",
"start",
"stop",
"bits",
"bytes",
}
}
2021-10-05 23:26:05 +03:00
func (bv BufferView) ToBufferView() (BufferView, error) {
return bv, nil
2020-06-08 03:29:51 +03:00
}
2021-10-05 23:26:05 +03:00
func (bv BufferView) JQValueLength() interface{} {
return int(bv.r.Len / int64(bv.unit))
2020-06-08 03:29:51 +03:00
}
2021-10-05 23:26:05 +03:00
func (bv BufferView) JQValueSliceLen() interface{} {
return bv.JQValueLength()
}
2021-09-23 19:35:04 +03:00
2021-10-05 23:26:05 +03:00
func (bv BufferView) JQValueIndex(index int) interface{} {
if index < 0 {
return nil
2021-10-05 23:26:05 +03:00
}
2021-10-05 23:26:05 +03:00
buf, err := bv.toBytesBuffer(ranges.Range{Start: bv.r.Start + int64(index*bv.unit), Len: int64(bv.unit)})
if err != nil {
return err
}
extraBits := uint((8 - bv.r.Len%8) % 8)
return new(big.Int).Rsh(new(big.Int).SetBytes(buf.Bytes()), extraBits)
2020-06-08 03:29:51 +03:00
}
2021-10-05 23:26:05 +03:00
func (bv BufferView) JQValueSlice(start int, end int) interface{} {
rStart := int64(start * bv.unit)
rLen := int64((end - start) * bv.unit)
2020-06-08 03:29:51 +03:00
return BufferView{
2021-10-05 23:26:05 +03:00
bb: bv.bb,
r: ranges.Range{Start: bv.r.Start + rStart, Len: rLen},
unit: bv.unit,
2020-06-08 03:29:51 +03:00
}
}
2021-10-05 23:26:05 +03:00
func (bv BufferView) JQValueKey(name string) interface{} {
2020-06-08 03:29:51 +03:00
switch name {
case "size":
2021-10-05 23:26:05 +03:00
return new(big.Int).SetInt64(bv.r.Len / int64(bv.unit))
2020-06-08 03:29:51 +03:00
case "start":
2021-10-05 23:26:05 +03:00
return new(big.Int).SetInt64(bv.r.Start / int64(bv.unit))
2020-06-08 03:29:51 +03:00
case "stop":
2021-10-05 23:26:05 +03:00
stop := bv.r.Stop()
stopUnits := stop / int64(bv.unit)
if stop%int64(bv.unit) != 0 {
2020-06-08 03:29:51 +03:00
stopUnits++
}
return new(big.Int).SetInt64(stopUnits)
case "bits":
2021-10-05 23:26:05 +03:00
if bv.unit == 1 {
return bv
2020-06-08 03:29:51 +03:00
}
2021-10-05 23:26:05 +03:00
return BufferView{bb: bv.bb, r: bv.r, unit: 1}
2020-06-08 03:29:51 +03:00
case "bytes":
2021-10-05 23:26:05 +03:00
if bv.unit == 8 {
return bv
2020-06-08 03:29:51 +03:00
}
2021-10-05 23:26:05 +03:00
return BufferView{bb: bv.bb, r: bv.r, unit: 8}
2020-06-08 03:29:51 +03:00
}
return nil
}
2021-10-05 23:26:05 +03:00
func (bv BufferView) JQValueEach() interface{} {
2020-06-08 03:29:51 +03:00
return nil
}
2021-10-05 23:26:05 +03:00
func (bv BufferView) JQValueType() string {
2020-06-08 03:29:51 +03:00
return "buffer"
}
2021-10-05 23:26:05 +03:00
func (bv BufferView) JQValueKeys() interface{} {
2021-10-15 19:19:59 +03:00
return gojqextra.FuncTypeNameError{Name: "keys", Typ: "buffer"}
2020-06-08 03:29:51 +03:00
}
2021-10-05 23:26:05 +03:00
func (bv BufferView) JQValueHas(key interface{}) interface{} {
2020-06-08 03:29:51 +03:00
return gojqextra.HasKeyTypeError{L: "buffer", R: fmt.Sprintf("%v", key)}
}
2021-10-05 23:26:05 +03:00
func (bv BufferView) JQValueToNumber() interface{} {
buf, err := bv.toBytesBuffer(bv.r)
if err != nil {
return err
}
2021-10-05 23:26:05 +03:00
extraBits := uint((8 - bv.r.Len%8) % 8)
2020-06-08 03:29:51 +03:00
return new(big.Int).Rsh(new(big.Int).SetBytes(buf.Bytes()), extraBits)
}
2021-10-05 23:26:05 +03:00
func (bv BufferView) JQValueToString() interface{} {
return bv.JQValueToGoJQ()
2020-06-08 03:29:51 +03:00
}
2021-10-05 23:26:05 +03:00
func (bv BufferView) JQValueToGoJQ() interface{} {
buf, err := bv.toBytesBuffer(bv.r)
if err != nil {
return err
}
2020-06-08 03:29:51 +03:00
return buf.String()
}
2021-10-05 23:26:05 +03:00
func (bv BufferView) JQValueUpdate(key interface{}, u interface{}, delpath bool) interface{} {
return notUpdateableError{Key: fmt.Sprintf("%v", key), Typ: "buffer"}
}
2021-10-05 23:26:05 +03:00
func (bv BufferView) Display(w io.Writer, opts Options) error {
if opts.RawOutput {
2021-10-05 23:26:05 +03:00
bb, err := bv.toBuffer()
if err != nil {
2020-06-08 03:29:51 +03:00
return err
}
if _, err := io.Copy(w, bb.Copy()); err != nil {
2020-06-08 03:29:51 +03:00
return err
}
return nil
2020-06-08 03:29:51 +03:00
}
2021-10-05 23:26:05 +03:00
return hexdump(w, bv, opts)
2020-06-08 03:29:51 +03:00
}
2021-10-05 23:26:05 +03:00
func (bv BufferView) toBuffer() (*bitio.Buffer, error) {
return bv.bb.BitBufRange(bv.r.Start, bv.r.Len)
2020-06-08 03:29:51 +03:00
}