Skip to content

Commit

Permalink
decode: Add float 80 reader
Browse files Browse the repository at this point in the history
Rename *d.Bits to UintBits as it return a uint
Add *d.Bits that return []byte
  • Loading branch information
wader committed Mar 10, 2023
1 parent b79b7ca commit 980ecdb
Show file tree
Hide file tree
Showing 26 changed files with 239 additions and 59 deletions.
2 changes: 1 addition & 1 deletion format/asn1/asn1_ber.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ func decodeASN1BERValue(d *decode.D, bib *bitio.Buffer, sb *strings.Builder, par
case form == formConstructed || tag == universalTypeSequence || tag == universalTypeSet:
d.FieldArray("constructed", func(d *decode.D) {
for !d.End() {
if length == lengthIndefinite && d.PeekBits(16) == lengthEndMarker {
if length == lengthIndefinite && d.PeekUintBits(16) == lengthEndMarker {
break
}

Expand Down
4 changes: 2 additions & 2 deletions format/bencode/bencode.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,14 @@ func decodeBencodeValue(d *decode.D) {
d.FieldUTF8("end", 1, d.StrAssert("e"))
case "l":
d.FieldArray("values", func(d *decode.D) {
for d.PeekBits(8) != 'e' {
for d.PeekUintBits(8) != 'e' {
d.FieldStruct("value", decodeBencodeValue)
}
})
d.FieldUTF8("end", 1, d.StrAssert("e"))
case "d":
d.FieldArray("pairs", func(d *decode.D) {
for d.PeekBits(8) != 'e' {
for d.PeekUintBits(8) != 'e' {
d.FieldStruct("pair", func(d *decode.D) {
d.FieldStruct("key", decodeBencodeValue)
d.FieldStruct("value", decodeBencodeValue)
Expand Down
2 changes: 1 addition & 1 deletion format/bitcoin/bitcoin_block.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func decodeBitcoinBlock(d *decode.D) any {
size := d.BitsLeft()

if bbi.HasHeader {
magic := d.PeekBits(32)
magic := d.PeekUintBits(32)
switch magic {
case 0xf9beb4d9,
0x0b110907,
Expand Down
2 changes: 1 addition & 1 deletion format/bitcoin/bitcoin_script.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ func decodeBitcoinScript(d *decode.D) any {
}

for !d.End() {
opcode := byte(d.PeekBits(8))
opcode := byte(d.PeekUintBits(8))
ope, ok := opcodeEntries.lookup(opcode)
if !ok {
d.Fatalf("unknown opcode %x", opcode)
Expand Down
2 changes: 1 addition & 1 deletion format/bitcoin/bitcoin_transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func decodeBitcoinTranscation(d *decode.D) any {

d.FieldU32("version")
witness := false
if d.PeekBits(8) == 0 {
if d.PeekUintBits(8) == 0 {
witness = true
d.FieldU8("marker")
d.FieldU8("flag")
Expand Down
2 changes: 1 addition & 1 deletion format/bzip2/bzip2.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ func bzip2Decode(d *decode.D) any {
compressedSize := (readCompressedSize - compressedStart) - footerByteSize*8
for i := 0; i < 8; i++ {
d.SeekAbs(compressedStart + compressedSize)
if d.PeekBits(48) == footerMagic {
if d.PeekUintBits(48) == footerMagic {
break
}
compressedSize--
Expand Down
8 changes: 4 additions & 4 deletions format/cbor/cbor.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ func decodeCBORValue(d *decode.D) any {
if shortCount == shortCountIndefinite {
bb := &bytes.Buffer{}
d.FieldArray("items", func(d *decode.D) {
for d.PeekBits(8) != breakMarker {
for d.PeekUintBits(8) != breakMarker {
d.FieldStruct("item", func(d *decode.D) {
v := decodeCBORValue(d)
switch v := v.(type) {
Expand All @@ -149,7 +149,7 @@ func decodeCBORValue(d *decode.D) any {
if shortCount == shortCountIndefinite {
sb := &strings.Builder{}
d.FieldArray("items", func(d *decode.D) {
for d.PeekBits(8) != breakMarker {
for d.PeekUintBits(8) != breakMarker {
d.FieldStruct("item", func(d *decode.D) {
v := decodeCBORValue(d)
switch v := v.(type) {
Expand All @@ -171,7 +171,7 @@ func decodeCBORValue(d *decode.D) any {
majorTypeArray: {s: scalar.Uint{Sym: "array"}, d: func(d *decode.D, shortCount uint64, count uint64) any {
d.FieldArray("elements", func(d *decode.D) {
for i := uint64(0); true; i++ {
if shortCount == shortCountIndefinite && d.PeekBits(8) == breakMarker {
if shortCount == shortCountIndefinite && d.PeekUintBits(8) == breakMarker {
break
} else if i >= count {
break
Expand All @@ -187,7 +187,7 @@ func decodeCBORValue(d *decode.D) any {
majorTypeMap: {s: scalar.Uint{Sym: "map"}, d: func(d *decode.D, shortCount uint64, count uint64) any {
d.FieldArray("pairs", func(d *decode.D) {
for i := uint64(0); true; i++ {
if shortCount == shortCountIndefinite && d.PeekBits(8) == breakMarker {
if shortCount == shortCountIndefinite && d.PeekUintBits(8) == breakMarker {
break
} else if i >= count {
break
Expand Down
2 changes: 1 addition & 1 deletion format/dns/dns.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ func fieldDecodeLabel(d *decode.D, pointerOffset int64, name string) {
seenTermintor := false
for !seenTermintor {
d.FieldStruct("label", func(d *decode.D) {
if d.PeekBits(2) == 0b11 {
if d.PeekUintBits(2) == 0b11 {
d.FieldU2("is_pointer")
pointer := d.FieldU14("pointer")
if endPos == 0 {
Expand Down
6 changes: 3 additions & 3 deletions format/gif/gif.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ func gifDecode(d *decode.D) any {
d.FieldArray("blocks", func(d *decode.D) {
blocks:
for {
switch d.PeekBits(8) {
switch d.PeekUintBits(8) {
case ';':
break blocks
case '!': /* "!" */
Expand All @@ -89,7 +89,7 @@ func gifDecode(d *decode.D) any {
d.FieldStruct("func_data_byte", func(d *decode.D) {
byteCount := d.FieldU8("byte_count")
b := d.FieldRawLen("data", int64(byteCount*8))
if d.PeekBits(8) == 0 {
if d.PeekUintBits(8) == 0 {
d.FieldU8("terminator")
seenTerminator = true
}
Expand Down Expand Up @@ -135,7 +135,7 @@ func gifDecode(d *decode.D) any {
d.FieldStruct("func_data_byte", func(d *decode.D) {
byteCount := d.FieldU8("byte_count")
d.FieldRawLen("data", int64(byteCount*8))
if d.PeekBits(8) == 0 {
if d.PeekUintBits(8) == 0 {
d.FieldU8("terminator")
seenTerminator = true
}
Expand Down
2 changes: 1 addition & 1 deletion format/id3/id3v1.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ func init() {
func id3v1Decode(d *decode.D) any {
d.AssertAtLeastBitsLeft(128 * 8)
d.FieldUTF8("magic", 3, d.StrAssert("TAG"))
if d.PeekBits(8) == uint64('+') {
if d.PeekUintBits(8) == uint64('+') {
d.Errorf("looks like id3v11")
}
d.FieldUTF8NullFixedLen("song_name", 30)
Expand Down
4 changes: 2 additions & 2 deletions format/id3/id3v2.go
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ func textNullLenFn(encoding int, notFoundFixedBytes int) func(d *decode.D) strin

d.SeekRel(nullLen * 8)
// seems sometimes utf16 etc has one exta null byte
if nullLen > 1 && d.PeekBits(8) == 0 {
if nullLen > 1 && d.PeekUintBits(8) == 0 {
d.SeekRel(8)
}

Expand Down Expand Up @@ -592,7 +592,7 @@ func decodeFrame(d *decode.D, version int) uint64 {
func decodeFrames(d *decode.D, version int, size uint64) {
d.FieldArray("frames", func(d *decode.D) {
for size > 0 {
if d.PeekBits(8) == 0 {
if d.PeekUintBits(8) == 0 {
return
}

Expand Down
2 changes: 1 addition & 1 deletion format/jpeg/jpeg.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ func jpegDecode(d *decode.D) any {
if inECD {
ecdLen := int64(0)
for {
if d.PeekBits(8) == 0xff && d.PeekBits(16) != 0xff00 {
if d.PeekUintBits(8) == 0xff && d.PeekUintBits(16) != 0xff00 {
break
}
d.SeekRel(8)
Expand Down
2 changes: 1 addition & 1 deletion format/matroska/matroska.go
Original file line number Diff line number Diff line change
Expand Up @@ -445,7 +445,7 @@ func matroskaDecode(d *decode.D) any {
d.ArgAs(&mi)

ebmlHeaderID := uint64(0x1a45dfa3)
if d.PeekBits(32) != ebmlHeaderID {
if d.PeekUintBits(32) != ebmlHeaderID {
d.Errorf("no EBML header found")
}
dc := &decodeContext{tracks: []*track{}}
Expand Down
6 changes: 3 additions & 3 deletions format/mp4/boxes.go
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ func decodeBoxesWithParentData(ctx *decodeContext, d *decode.D, parentData any,

if d.BitsLeft() > 0 {
// "Some sample descriptions terminate with four zero bytes that are not otherwise indicated."
if d.BitsLeft() >= 32 && d.PeekBits(32) == 0 {
if d.BitsLeft() >= 32 && d.PeekUintBits(32) == 0 {
d.FieldU32("zero_terminator")
}
if d.BitsLeft() > 0 {
Expand Down Expand Up @@ -904,7 +904,7 @@ func decodeBox(ctx *decodeContext, d *decode.D, typ string) {
decodeBoxes(ctx, d)
case "meta":
// TODO: meta box sometimes has a 4 byte unknown field? (flag/version?)
maybeFlags := d.PeekBits(32)
maybeFlags := d.PeekUintBits(32)
if maybeFlags == 0 {
// TODO: rename?
d.FieldU32("maybe_flags")
Expand Down Expand Up @@ -1687,7 +1687,7 @@ func decodeBox(ctx *decodeContext, d *decode.D, typ string) {
// TODO: better probe? ffmpeg uses box name heuristics?
// if 16 length field seems to match assume box with length, language and value
// otherwise decode as box with value rest of box
probeLength := d.PeekBits(16)
probeLength := d.PeekUintBits(16)
// +2 for length field, +2 for language field
if (probeLength+2+2)*8 == uint64(d.BitsLeft()) {
length := d.FieldU16("length")
Expand Down
2 changes: 1 addition & 1 deletion format/mpeg/avc_pps.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ func init() {

func moreRBSPData(d *decode.D) bool {
l := d.BitsLeft()
return l >= 8 && d.PeekBits(8) != 0b1000_0000
return l >= 8 && d.PeekUintBits(8) != 0b1000_0000
}

func avcPPSDecode(d *decode.D) any {
Expand Down
2 changes: 1 addition & 1 deletion format/mpeg/mpeg_pes.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ type subStream struct {
func pesDecode(d *decode.D) any {
substreams := map[int]*subStream{}

prefix := d.PeekBits(24)
prefix := d.PeekUintBits(24)
if prefix != 0b0000_0000_0000_0000_0000_0001 {
d.Errorf("no pes prefix found")
}
Expand Down
4 changes: 2 additions & 2 deletions format/mpeg/mpeg_pes_packet.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ func pesPacketDecode(d *decode.D) any {

}
case startCode == packHeader:
isMPEG2 := d.PeekBits(2) == 0b01
isMPEG2 := d.PeekUintBits(2) == 0b01
if isMPEG2 {
d.FieldU2("marker_bits0", mpegVersion)
} else {
Expand Down Expand Up @@ -140,7 +140,7 @@ func pesPacketDecode(d *decode.D) any {
d.FieldU1("packet_rate_restriction_flag")
d.FieldU7("reserved")
d.FieldArray("stream_bound_entries", func(d *decode.D) {
for d.PeekBits(1) == 1 {
for d.PeekUintBits(1) == 1 {
d.FieldStruct("stream_bound_entry", func(d *decode.D) {
d.FieldU8("stream_id")
d.FieldU2("skip0")
Expand Down
2 changes: 1 addition & 1 deletion format/mpeg/mpeg_spu.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ var commandNames = scalar.UintMapSymStr{
}

func rleValue(d *decode.D) (uint64, uint64, int) {
p := uint(d.PeekBits(8))
p := uint(d.PeekUintBits(8))

// match zero prefix
switch {
Expand Down
5 changes: 1 addition & 4 deletions format/riff/aiff.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ package riff

import (
"github.com/wader/fq/format"
"github.com/wader/fq/internal/mathex"
"github.com/wader/fq/pkg/decode"
"github.com/wader/fq/pkg/interp"
"github.com/wader/fq/pkg/scalar"
Expand Down Expand Up @@ -81,9 +80,7 @@ func aiffDecode(d *decode.D) any {
d.FieldU32("num_sample_frames")
d.FieldU16("sample_size")
// TODO: support big float?
d.FieldFltFn("sample_rate", func(d *decode.D) float64 {
return mathex.NewFloat80FromBytes(d.BytesLen(10)).Float64()
})
d.FieldF80("sample_rate")
return false, nil
case "SSND":
d.FieldU32("offset")
Expand Down
6 changes: 3 additions & 3 deletions format/rtmp/amf0.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ func amf0DecodeValue(d *decode.D) {
l := d.FieldU16("length")
d.FieldUTF8("value", int(l))
})
typ = d.PeekBits(8)
typ = d.PeekUintBits(8)
d.FieldStruct("value", amf0DecodeValue)
})
}
Expand All @@ -98,7 +98,7 @@ func amf0DecodeValue(d *decode.D) {
l := d.FieldU16("length")
d.FieldUTF8("value", int(l))
})
typ = d.PeekBits(8)
typ = d.PeekUintBits(8)
d.FieldStruct("value", amf0DecodeValue)
})
}
Expand Down Expand Up @@ -134,7 +134,7 @@ func amf0DecodeValue(d *decode.D) {
l := d.FieldU16("length")
d.FieldUTF8("value", int(l))
})
typ = d.PeekBits(8)
typ = d.PeekUintBits(8)
d.FieldStruct("value", amf0DecodeValue)
})
}
Expand Down
2 changes: 1 addition & 1 deletion format/rtmp/rtmp.go
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,7 @@ func rtmpDecode(d *decode.D) any {
var chunkSteamID uint64

fmt := d.FieldU2("fmt")
switch d.PeekBits(6) {
switch d.PeekUintBits(6) {
case 0:
// 64-319: 2 byte
d.FieldU6("chunk_stream_id_prefix")
Expand Down
2 changes: 1 addition & 1 deletion format/tls/tls.go
Original file line number Diff line number Diff line change
Expand Up @@ -695,7 +695,7 @@ func decodeTLS(d *decode.D) any {
tc.server.currentCipherSuit = ciphersuites.TLS_NULL_WITH_NULL_NULL
tc.server.nextCipherSuit = ciphersuites.TLS_NULL_WITH_NULL_NULL

firstByte := d.PeekBits(8)
firstByte := d.PeekUintBits(8)
if firstByte&0x80 != 0 {
d.FieldStruct("ssl_v2", func(d *decode.D) {
decodeV2ClientHello(d, tc)
Expand Down
45 changes: 33 additions & 12 deletions pkg/decode/decode.go
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ func (d *D) SharedReadBuf(n int) []byte {
if len(*d.readBuf) < n {
*d.readBuf = make([]byte, n)
}
return *d.readBuf
return (*d.readBuf)[:n]
}

func (d *D) FillGaps(r ranges.Range, namePrefix string) {
Expand Down Expand Up @@ -370,34 +370,55 @@ func (d *D) IOPanic(err error, op string) {
panic(IOError{Err: err, Pos: d.Pos(), Op: op})
}

// TryBits reads nBits bits from buffer
func (d *D) TryBits(nBits int) ([]byte, error) {
if nBits < 0 {
return nil, fmt.Errorf("nBits must be >= 0 (%d)", nBits)
}
buf := d.SharedReadBuf(int(bitio.BitsByteCount(int64(nBits))))
_, err := bitio.ReadFull(d.bitBuf, buf, int64(nBits))
if err != nil {
return nil, err
}

return buf[:], nil
}

// Bits reads nBits bits from buffer
func (d *D) TryBits(nBits int) (uint64, error) {
func (d *D) Bits(nBits int) []byte {
b, err := d.TryBits(nBits)
if err != nil {
panic(IOError{Err: err, Op: "Bits", ReadSize: int64(nBits), Pos: d.Pos()})
}
return b
}

// TryUintBits reads nBits bits as a uint64 from buffer
func (d *D) TryUintBits(nBits int) (uint64, error) {
if nBits < 0 || nBits > 64 {
return 0, fmt.Errorf("nBits must be 0-64 (%d)", nBits)
}
// 64 bits max, 9 byte worse case if not byte aligned
buf := d.SharedReadBuf(9)
_, err := bitio.ReadFull(d.bitBuf, buf, int64(nBits)) // TODO: int64?
buf, err := d.TryBits(nBits)
if err != nil {
return 0, err
}

return bitio.Read64(buf[:], 0, int64(nBits)), nil // TODO: int64
}

// Bits reads nBits bits from buffer
func (d *D) Bits(nBits int) uint64 {
n, err := d.TryBits(nBits)
// UintBits reads nBits bits as uint64 from buffer
func (d *D) UintBits(nBits int) uint64 {
n, err := d.TryUintBits(nBits)
if err != nil {
panic(IOError{Err: err, Op: "Bits", ReadSize: int64(nBits), Pos: d.Pos()})
panic(IOError{Err: err, Op: "UintBits", ReadSize: int64(nBits), Pos: d.Pos()})
}
return n
}

func (d *D) PeekBits(nBits int) uint64 {
func (d *D) PeekUintBits(nBits int) uint64 {
n, err := d.TryPeekBits(nBits)
if err != nil {
panic(IOError{Err: err, Op: "PeekBits", ReadSize: int64(nBits), Pos: d.Pos()})
panic(IOError{Err: err, Op: "PeekUintBits", ReadSize: int64(nBits), Pos: d.Pos()})
}
return n
}
Expand Down Expand Up @@ -450,7 +471,7 @@ func (d *D) TryPeekBits(nBits int) (uint64, error) {
if err != nil {
return 0, err
}
n, err := d.TryBits(nBits)
n, err := d.TryUintBits(nBits)
if _, err := d.bitBuf.SeekBits(start, io.SeekStart); err != nil {
return 0, err
}
Expand Down

0 comments on commit 980ecdb

Please sign in to comment.