1
1
mirror of https://github.com/wader/fq.git synced 2024-12-23 05:13:30 +03:00

Merge pull request #615 from wader/float80-refactor

decode: Add float 80 reader
This commit is contained in:
Mattias Wadman 2023-03-10 10:11:09 +01:00 committed by GitHub
commit fcacd7e3a3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 239 additions and 59 deletions

View File

@ -202,7 +202,7 @@ func decodeASN1BERValue(d *decode.D, bib *bitio.Buffer, sb *strings.Builder, par
case form == formConstructed || tag == universalTypeSequence || tag == universalTypeSet: case form == formConstructed || tag == universalTypeSequence || tag == universalTypeSet:
d.FieldArray("constructed", func(d *decode.D) { d.FieldArray("constructed", func(d *decode.D) {
for !d.End() { for !d.End() {
if length == lengthIndefinite && d.PeekBits(16) == lengthEndMarker { if length == lengthIndefinite && d.PeekUintBits(16) == lengthEndMarker {
break break
} }

View File

@ -71,14 +71,14 @@ func decodeBencodeValue(d *decode.D) {
d.FieldUTF8("end", 1, d.StrAssert("e")) d.FieldUTF8("end", 1, d.StrAssert("e"))
case "l": case "l":
d.FieldArray("values", func(d *decode.D) { d.FieldArray("values", func(d *decode.D) {
for d.PeekBits(8) != 'e' { for d.PeekUintBits(8) != 'e' {
d.FieldStruct("value", decodeBencodeValue) d.FieldStruct("value", decodeBencodeValue)
} }
}) })
d.FieldUTF8("end", 1, d.StrAssert("e")) d.FieldUTF8("end", 1, d.StrAssert("e"))
case "d": case "d":
d.FieldArray("pairs", func(d *decode.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("pair", func(d *decode.D) {
d.FieldStruct("key", decodeBencodeValue) d.FieldStruct("key", decodeBencodeValue)
d.FieldStruct("value", decodeBencodeValue) d.FieldStruct("value", decodeBencodeValue)

View File

@ -42,7 +42,7 @@ func decodeBitcoinBlock(d *decode.D) any {
size := d.BitsLeft() size := d.BitsLeft()
if bbi.HasHeader { if bbi.HasHeader {
magic := d.PeekBits(32) magic := d.PeekUintBits(32)
switch magic { switch magic {
case 0xf9beb4d9, case 0xf9beb4d9,
0x0b110907, 0x0b110907,

View File

@ -171,7 +171,7 @@ func decodeBitcoinScript(d *decode.D) any {
} }
for !d.End() { for !d.End() {
opcode := byte(d.PeekBits(8)) opcode := byte(d.PeekUintBits(8))
ope, ok := opcodeEntries.lookup(opcode) ope, ok := opcodeEntries.lookup(opcode)
if !ok { if !ok {
d.Fatalf("unknown opcode %x", opcode) d.Fatalf("unknown opcode %x", opcode)

View File

@ -49,7 +49,7 @@ func decodeBitcoinTranscation(d *decode.D) any {
d.FieldU32("version") d.FieldU32("version")
witness := false witness := false
if d.PeekBits(8) == 0 { if d.PeekUintBits(8) == 0 {
witness = true witness = true
d.FieldU8("marker") d.FieldU8("marker")
d.FieldU8("flag") d.FieldU8("flag")

View File

@ -127,7 +127,7 @@ func bzip2Decode(d *decode.D) any {
compressedSize := (readCompressedSize - compressedStart) - footerByteSize*8 compressedSize := (readCompressedSize - compressedStart) - footerByteSize*8
for i := 0; i < 8; i++ { for i := 0; i < 8; i++ {
d.SeekAbs(compressedStart + compressedSize) d.SeekAbs(compressedStart + compressedSize)
if d.PeekBits(48) == footerMagic { if d.PeekUintBits(48) == footerMagic {
break break
} }
compressedSize-- compressedSize--

View File

@ -124,7 +124,7 @@ func decodeCBORValue(d *decode.D) any {
if shortCount == shortCountIndefinite { if shortCount == shortCountIndefinite {
bb := &bytes.Buffer{} bb := &bytes.Buffer{}
d.FieldArray("items", func(d *decode.D) { d.FieldArray("items", func(d *decode.D) {
for d.PeekBits(8) != breakMarker { for d.PeekUintBits(8) != breakMarker {
d.FieldStruct("item", func(d *decode.D) { d.FieldStruct("item", func(d *decode.D) {
v := decodeCBORValue(d) v := decodeCBORValue(d)
switch v := v.(type) { switch v := v.(type) {
@ -149,7 +149,7 @@ func decodeCBORValue(d *decode.D) any {
if shortCount == shortCountIndefinite { if shortCount == shortCountIndefinite {
sb := &strings.Builder{} sb := &strings.Builder{}
d.FieldArray("items", func(d *decode.D) { d.FieldArray("items", func(d *decode.D) {
for d.PeekBits(8) != breakMarker { for d.PeekUintBits(8) != breakMarker {
d.FieldStruct("item", func(d *decode.D) { d.FieldStruct("item", func(d *decode.D) {
v := decodeCBORValue(d) v := decodeCBORValue(d)
switch v := v.(type) { switch v := v.(type) {
@ -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 { majorTypeArray: {s: scalar.Uint{Sym: "array"}, d: func(d *decode.D, shortCount uint64, count uint64) any {
d.FieldArray("elements", func(d *decode.D) { d.FieldArray("elements", func(d *decode.D) {
for i := uint64(0); true; i++ { for i := uint64(0); true; i++ {
if shortCount == shortCountIndefinite && d.PeekBits(8) == breakMarker { if shortCount == shortCountIndefinite && d.PeekUintBits(8) == breakMarker {
break break
} else if i >= count { } else if i >= count {
break break
@ -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 { majorTypeMap: {s: scalar.Uint{Sym: "map"}, d: func(d *decode.D, shortCount uint64, count uint64) any {
d.FieldArray("pairs", func(d *decode.D) { d.FieldArray("pairs", func(d *decode.D) {
for i := uint64(0); true; i++ { for i := uint64(0); true; i++ {
if shortCount == shortCountIndefinite && d.PeekBits(8) == breakMarker { if shortCount == shortCountIndefinite && d.PeekUintBits(8) == breakMarker {
break break
} else if i >= count { } else if i >= count {
break break

View File

@ -141,7 +141,7 @@ func fieldDecodeLabel(d *decode.D, pointerOffset int64, name string) {
seenTermintor := false seenTermintor := false
for !seenTermintor { for !seenTermintor {
d.FieldStruct("label", func(d *decode.D) { d.FieldStruct("label", func(d *decode.D) {
if d.PeekBits(2) == 0b11 { if d.PeekUintBits(2) == 0b11 {
d.FieldU2("is_pointer") d.FieldU2("is_pointer")
pointer := d.FieldU14("pointer") pointer := d.FieldU14("pointer")
if endPos == 0 { if endPos == 0 {

View File

@ -72,7 +72,7 @@ func gifDecode(d *decode.D) any {
d.FieldArray("blocks", func(d *decode.D) { d.FieldArray("blocks", func(d *decode.D) {
blocks: blocks:
for { for {
switch d.PeekBits(8) { switch d.PeekUintBits(8) {
case ';': case ';':
break blocks break blocks
case '!': /* "!" */ case '!': /* "!" */
@ -89,7 +89,7 @@ func gifDecode(d *decode.D) any {
d.FieldStruct("func_data_byte", func(d *decode.D) { d.FieldStruct("func_data_byte", func(d *decode.D) {
byteCount := d.FieldU8("byte_count") byteCount := d.FieldU8("byte_count")
b := d.FieldRawLen("data", int64(byteCount*8)) b := d.FieldRawLen("data", int64(byteCount*8))
if d.PeekBits(8) == 0 { if d.PeekUintBits(8) == 0 {
d.FieldU8("terminator") d.FieldU8("terminator")
seenTerminator = true seenTerminator = true
} }
@ -135,7 +135,7 @@ func gifDecode(d *decode.D) any {
d.FieldStruct("func_data_byte", func(d *decode.D) { d.FieldStruct("func_data_byte", func(d *decode.D) {
byteCount := d.FieldU8("byte_count") byteCount := d.FieldU8("byte_count")
d.FieldRawLen("data", int64(byteCount*8)) d.FieldRawLen("data", int64(byteCount*8))
if d.PeekBits(8) == 0 { if d.PeekUintBits(8) == 0 {
d.FieldU8("terminator") d.FieldU8("terminator")
seenTerminator = true seenTerminator = true
} }

View File

@ -21,7 +21,7 @@ func init() {
func id3v1Decode(d *decode.D) any { func id3v1Decode(d *decode.D) any {
d.AssertAtLeastBitsLeft(128 * 8) d.AssertAtLeastBitsLeft(128 * 8)
d.FieldUTF8("magic", 3, d.StrAssert("TAG")) d.FieldUTF8("magic", 3, d.StrAssert("TAG"))
if d.PeekBits(8) == uint64('+') { if d.PeekUintBits(8) == uint64('+') {
d.Errorf("looks like id3v11") d.Errorf("looks like id3v11")
} }
d.FieldUTF8NullFixedLen("song_name", 30) d.FieldUTF8NullFixedLen("song_name", 30)

View File

@ -315,7 +315,7 @@ func textNullLenFn(encoding int, notFoundFixedBytes int) func(d *decode.D) strin
d.SeekRel(nullLen * 8) d.SeekRel(nullLen * 8)
// seems sometimes utf16 etc has one exta null byte // 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) d.SeekRel(8)
} }
@ -592,7 +592,7 @@ func decodeFrame(d *decode.D, version int) uint64 {
func decodeFrames(d *decode.D, version int, size uint64) { func decodeFrames(d *decode.D, version int, size uint64) {
d.FieldArray("frames", func(d *decode.D) { d.FieldArray("frames", func(d *decode.D) {
for size > 0 { for size > 0 {
if d.PeekBits(8) == 0 { if d.PeekUintBits(8) == 0 {
return return
} }

View File

@ -180,7 +180,7 @@ func jpegDecode(d *decode.D) any {
if inECD { if inECD {
ecdLen := int64(0) ecdLen := int64(0)
for { for {
if d.PeekBits(8) == 0xff && d.PeekBits(16) != 0xff00 { if d.PeekUintBits(8) == 0xff && d.PeekUintBits(16) != 0xff00 {
break break
} }
d.SeekRel(8) d.SeekRel(8)

View File

@ -445,7 +445,7 @@ func matroskaDecode(d *decode.D) any {
d.ArgAs(&mi) d.ArgAs(&mi)
ebmlHeaderID := uint64(0x1a45dfa3) ebmlHeaderID := uint64(0x1a45dfa3)
if d.PeekBits(32) != ebmlHeaderID { if d.PeekUintBits(32) != ebmlHeaderID {
d.Errorf("no EBML header found") d.Errorf("no EBML header found")
} }
dc := &decodeContext{tracks: []*track{}} dc := &decodeContext{tracks: []*track{}}

View File

@ -295,7 +295,7 @@ func decodeBoxesWithParentData(ctx *decodeContext, d *decode.D, parentData any,
if d.BitsLeft() > 0 { if d.BitsLeft() > 0 {
// "Some sample descriptions terminate with four zero bytes that are not otherwise indicated." // "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") d.FieldU32("zero_terminator")
} }
if d.BitsLeft() > 0 { if d.BitsLeft() > 0 {
@ -904,7 +904,7 @@ func decodeBox(ctx *decodeContext, d *decode.D, typ string) {
decodeBoxes(ctx, d) decodeBoxes(ctx, d)
case "meta": case "meta":
// TODO: meta box sometimes has a 4 byte unknown field? (flag/version?) // TODO: meta box sometimes has a 4 byte unknown field? (flag/version?)
maybeFlags := d.PeekBits(32) maybeFlags := d.PeekUintBits(32)
if maybeFlags == 0 { if maybeFlags == 0 {
// TODO: rename? // TODO: rename?
d.FieldU32("maybe_flags") d.FieldU32("maybe_flags")
@ -1687,7 +1687,7 @@ func decodeBox(ctx *decodeContext, d *decode.D, typ string) {
// TODO: better probe? ffmpeg uses box name heuristics? // TODO: better probe? ffmpeg uses box name heuristics?
// if 16 length field seems to match assume box with length, language and value // if 16 length field seems to match assume box with length, language and value
// otherwise decode as box with value rest of box // 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 // +2 for length field, +2 for language field
if (probeLength+2+2)*8 == uint64(d.BitsLeft()) { if (probeLength+2+2)*8 == uint64(d.BitsLeft()) {
length := d.FieldU16("length") length := d.FieldU16("length")

View File

@ -17,7 +17,7 @@ func init() {
func moreRBSPData(d *decode.D) bool { func moreRBSPData(d *decode.D) bool {
l := d.BitsLeft() 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 { func avcPPSDecode(d *decode.D) any {

View File

@ -36,7 +36,7 @@ type subStream struct {
func pesDecode(d *decode.D) any { func pesDecode(d *decode.D) any {
substreams := map[int]*subStream{} substreams := map[int]*subStream{}
prefix := d.PeekBits(24) prefix := d.PeekUintBits(24)
if prefix != 0b0000_0000_0000_0000_0000_0001 { if prefix != 0b0000_0000_0000_0000_0000_0001 {
d.Errorf("no pes prefix found") d.Errorf("no pes prefix found")
} }

View File

@ -97,7 +97,7 @@ func pesPacketDecode(d *decode.D) any {
} }
case startCode == packHeader: case startCode == packHeader:
isMPEG2 := d.PeekBits(2) == 0b01 isMPEG2 := d.PeekUintBits(2) == 0b01
if isMPEG2 { if isMPEG2 {
d.FieldU2("marker_bits0", mpegVersion) d.FieldU2("marker_bits0", mpegVersion)
} else { } else {
@ -140,7 +140,7 @@ func pesPacketDecode(d *decode.D) any {
d.FieldU1("packet_rate_restriction_flag") d.FieldU1("packet_rate_restriction_flag")
d.FieldU7("reserved") d.FieldU7("reserved")
d.FieldArray("stream_bound_entries", func(d *decode.D) { 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.FieldStruct("stream_bound_entry", func(d *decode.D) {
d.FieldU8("stream_id") d.FieldU8("stream_id")
d.FieldU2("skip0") d.FieldU2("skip0")

View File

@ -48,7 +48,7 @@ var commandNames = scalar.UintMapSymStr{
} }
func rleValue(d *decode.D) (uint64, uint64, int) { func rleValue(d *decode.D) (uint64, uint64, int) {
p := uint(d.PeekBits(8)) p := uint(d.PeekUintBits(8))
// match zero prefix // match zero prefix
switch { switch {

View File

@ -4,7 +4,6 @@ package riff
import ( import (
"github.com/wader/fq/format" "github.com/wader/fq/format"
"github.com/wader/fq/internal/mathex"
"github.com/wader/fq/pkg/decode" "github.com/wader/fq/pkg/decode"
"github.com/wader/fq/pkg/interp" "github.com/wader/fq/pkg/interp"
"github.com/wader/fq/pkg/scalar" "github.com/wader/fq/pkg/scalar"
@ -81,9 +80,7 @@ func aiffDecode(d *decode.D) any {
d.FieldU32("num_sample_frames") d.FieldU32("num_sample_frames")
d.FieldU16("sample_size") d.FieldU16("sample_size")
// TODO: support big float? // TODO: support big float?
d.FieldFltFn("sample_rate", func(d *decode.D) float64 { d.FieldF80("sample_rate")
return mathex.NewFloat80FromBytes(d.BytesLen(10)).Float64()
})
return false, nil return false, nil
case "SSND": case "SSND":
d.FieldU32("offset") d.FieldU32("offset")

View File

@ -77,7 +77,7 @@ func amf0DecodeValue(d *decode.D) {
l := d.FieldU16("length") l := d.FieldU16("length")
d.FieldUTF8("value", int(l)) d.FieldUTF8("value", int(l))
}) })
typ = d.PeekBits(8) typ = d.PeekUintBits(8)
d.FieldStruct("value", amf0DecodeValue) d.FieldStruct("value", amf0DecodeValue)
}) })
} }
@ -98,7 +98,7 @@ func amf0DecodeValue(d *decode.D) {
l := d.FieldU16("length") l := d.FieldU16("length")
d.FieldUTF8("value", int(l)) d.FieldUTF8("value", int(l))
}) })
typ = d.PeekBits(8) typ = d.PeekUintBits(8)
d.FieldStruct("value", amf0DecodeValue) d.FieldStruct("value", amf0DecodeValue)
}) })
} }
@ -134,7 +134,7 @@ func amf0DecodeValue(d *decode.D) {
l := d.FieldU16("length") l := d.FieldU16("length")
d.FieldUTF8("value", int(l)) d.FieldUTF8("value", int(l))
}) })
typ = d.PeekBits(8) typ = d.PeekUintBits(8)
d.FieldStruct("value", amf0DecodeValue) d.FieldStruct("value", amf0DecodeValue)
}) })
} }

View File

@ -368,7 +368,7 @@ func rtmpDecode(d *decode.D) any {
var chunkSteamID uint64 var chunkSteamID uint64
fmt := d.FieldU2("fmt") fmt := d.FieldU2("fmt")
switch d.PeekBits(6) { switch d.PeekUintBits(6) {
case 0: case 0:
// 64-319: 2 byte // 64-319: 2 byte
d.FieldU6("chunk_stream_id_prefix") d.FieldU6("chunk_stream_id_prefix")

View File

@ -695,7 +695,7 @@ func decodeTLS(d *decode.D) any {
tc.server.currentCipherSuit = ciphersuites.TLS_NULL_WITH_NULL_NULL tc.server.currentCipherSuit = ciphersuites.TLS_NULL_WITH_NULL_NULL
tc.server.nextCipherSuit = 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 { if firstByte&0x80 != 0 {
d.FieldStruct("ssl_v2", func(d *decode.D) { d.FieldStruct("ssl_v2", func(d *decode.D) {
decodeV2ClientHello(d, tc) decodeV2ClientHello(d, tc)

View File

@ -306,7 +306,7 @@ func (d *D) SharedReadBuf(n int) []byte {
if len(*d.readBuf) < n { if len(*d.readBuf) < n {
*d.readBuf = make([]byte, n) *d.readBuf = make([]byte, n)
} }
return *d.readBuf return (*d.readBuf)[:n]
} }
func (d *D) FillGaps(r ranges.Range, namePrefix string) { func (d *D) FillGaps(r ranges.Range, namePrefix string) {
@ -370,14 +370,35 @@ func (d *D) IOPanic(err error, op string) {
panic(IOError{Err: err, Pos: d.Pos(), Op: op}) 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 // 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 { if nBits < 0 || nBits > 64 {
return 0, fmt.Errorf("nBits must be 0-64 (%d)", nBits) return 0, fmt.Errorf("nBits must be 0-64 (%d)", nBits)
} }
// 64 bits max, 9 byte worse case if not byte aligned buf, err := d.TryBits(nBits)
buf := d.SharedReadBuf(9)
_, err := bitio.ReadFull(d.bitBuf, buf, int64(nBits)) // TODO: int64?
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -385,19 +406,19 @@ func (d *D) TryBits(nBits int) (uint64, error) {
return bitio.Read64(buf[:], 0, int64(nBits)), nil // TODO: int64 return bitio.Read64(buf[:], 0, int64(nBits)), nil // TODO: int64
} }
// Bits reads nBits bits from buffer // UintBits reads nBits bits as uint64 from buffer
func (d *D) Bits(nBits int) uint64 { func (d *D) UintBits(nBits int) uint64 {
n, err := d.TryBits(nBits) n, err := d.TryUintBits(nBits)
if err != nil { 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 return n
} }
func (d *D) PeekBits(nBits int) uint64 { func (d *D) PeekUintBits(nBits int) uint64 {
n, err := d.TryPeekBits(nBits) n, err := d.TryPeekBits(nBits)
if err != nil { 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 return n
} }
@ -450,7 +471,7 @@ func (d *D) TryPeekBits(nBits int) (uint64, error) {
if err != nil { if err != nil {
return 0, err return 0, err
} }
n, err := d.TryBits(nBits) n, err := d.TryUintBits(nBits)
if _, err := d.bitBuf.SeekBits(start, io.SeekStart); err != nil { if _, err := d.bitBuf.SeekBits(start, io.SeekStart); err != nil {
return 0, err return 0, err
} }

View File

@ -18260,6 +18260,52 @@ func (d *D) FieldF64(name string, sms ...scalar.FltMapper) float64 {
return d.FieldScalarF64(name, sms...).Actual return d.FieldScalarF64(name, sms...).Actual
} }
// Reader F80
// TryF80 tries to read 80 bit IEEE 754 float in current endian
func (d *D) TryF80() (float64, error) { return d.tryFEndian(80, d.Endian) }
// F80 reads 80 bit IEEE 754 float in current endian
func (d *D) F80() float64 {
v, err := d.tryFEndian(80, d.Endian)
if err != nil {
panic(IOError{Err: err, Op: "F80", Pos: d.Pos()})
}
return v
}
// TryFieldScalarF80 tries to add a field and read 80 bit IEEE 754 float in current endian
func (d *D) TryFieldScalarF80(name string, sms ...scalar.FltMapper) (*scalar.Flt, error) {
s, err := d.TryFieldScalarFltFn(name, func(d *D) (scalar.Flt, error) {
v, err := d.tryFEndian(80, d.Endian)
return scalar.Flt{Actual: v}, err
}, sms...)
if err != nil {
return nil, err
}
return s, err
}
// FieldScalarF80 adds a field and reads 80 bit IEEE 754 float in current endian
func (d *D) FieldScalarF80(name string, sms ...scalar.FltMapper) *scalar.Flt {
s, err := d.TryFieldScalarF80(name, sms...)
if err != nil {
panic(IOError{Err: err, Name: name, Op: "F80", Pos: d.Pos()})
}
return s
}
// TryFieldF80 tries to add a field and read 80 bit IEEE 754 float in current endian
func (d *D) TryFieldF80(name string, sms ...scalar.FltMapper) (float64, error) {
s, err := d.TryFieldScalarF80(name, sms...)
return s.Actual, err
}
// FieldF80 adds a field and reads 80 bit IEEE 754 float in current endian
func (d *D) FieldF80(name string, sms ...scalar.FltMapper) float64 {
return d.FieldScalarF80(name, sms...).Actual
}
// Reader F16LE // Reader F16LE
// TryF16LE tries to read 16 bit IEEE 754 float in little-endian // TryF16LE tries to read 16 bit IEEE 754 float in little-endian
@ -18398,6 +18444,52 @@ func (d *D) FieldF64LE(name string, sms ...scalar.FltMapper) float64 {
return d.FieldScalarF64LE(name, sms...).Actual return d.FieldScalarF64LE(name, sms...).Actual
} }
// Reader F80LE
// TryF80LE tries to read 80 bit IEEE 754 float in little-endian
func (d *D) TryF80LE() (float64, error) { return d.tryFEndian(80, LittleEndian) }
// F80LE reads 80 bit IEEE 754 float in little-endian
func (d *D) F80LE() float64 {
v, err := d.tryFEndian(80, LittleEndian)
if err != nil {
panic(IOError{Err: err, Op: "F80LE", Pos: d.Pos()})
}
return v
}
// TryFieldScalarF80LE tries to add a field and read 80 bit IEEE 754 float in little-endian
func (d *D) TryFieldScalarF80LE(name string, sms ...scalar.FltMapper) (*scalar.Flt, error) {
s, err := d.TryFieldScalarFltFn(name, func(d *D) (scalar.Flt, error) {
v, err := d.tryFEndian(80, LittleEndian)
return scalar.Flt{Actual: v}, err
}, sms...)
if err != nil {
return nil, err
}
return s, err
}
// FieldScalarF80LE adds a field and reads 80 bit IEEE 754 float in little-endian
func (d *D) FieldScalarF80LE(name string, sms ...scalar.FltMapper) *scalar.Flt {
s, err := d.TryFieldScalarF80LE(name, sms...)
if err != nil {
panic(IOError{Err: err, Name: name, Op: "F80LE", Pos: d.Pos()})
}
return s
}
// TryFieldF80LE tries to add a field and read 80 bit IEEE 754 float in little-endian
func (d *D) TryFieldF80LE(name string, sms ...scalar.FltMapper) (float64, error) {
s, err := d.TryFieldScalarF80LE(name, sms...)
return s.Actual, err
}
// FieldF80LE adds a field and reads 80 bit IEEE 754 float in little-endian
func (d *D) FieldF80LE(name string, sms ...scalar.FltMapper) float64 {
return d.FieldScalarF80LE(name, sms...).Actual
}
// Reader F16BE // Reader F16BE
// TryF16BE tries to read 16 bit IEEE 754 float in big-endian // TryF16BE tries to read 16 bit IEEE 754 float in big-endian
@ -18536,6 +18628,52 @@ func (d *D) FieldF64BE(name string, sms ...scalar.FltMapper) float64 {
return d.FieldScalarF64BE(name, sms...).Actual return d.FieldScalarF64BE(name, sms...).Actual
} }
// Reader F80BE
// TryF80BE tries to read 80 bit IEEE 754 float in big-endian
func (d *D) TryF80BE() (float64, error) { return d.tryFEndian(80, BigEndian) }
// F80BE reads 80 bit IEEE 754 float in big-endian
func (d *D) F80BE() float64 {
v, err := d.tryFEndian(80, BigEndian)
if err != nil {
panic(IOError{Err: err, Op: "F80BE", Pos: d.Pos()})
}
return v
}
// TryFieldScalarF80BE tries to add a field and read 80 bit IEEE 754 float in big-endian
func (d *D) TryFieldScalarF80BE(name string, sms ...scalar.FltMapper) (*scalar.Flt, error) {
s, err := d.TryFieldScalarFltFn(name, func(d *D) (scalar.Flt, error) {
v, err := d.tryFEndian(80, BigEndian)
return scalar.Flt{Actual: v}, err
}, sms...)
if err != nil {
return nil, err
}
return s, err
}
// FieldScalarF80BE adds a field and reads 80 bit IEEE 754 float in big-endian
func (d *D) FieldScalarF80BE(name string, sms ...scalar.FltMapper) *scalar.Flt {
s, err := d.TryFieldScalarF80BE(name, sms...)
if err != nil {
panic(IOError{Err: err, Name: name, Op: "F80BE", Pos: d.Pos()})
}
return s
}
// TryFieldF80BE tries to add a field and read 80 bit IEEE 754 float in big-endian
func (d *D) TryFieldF80BE(name string, sms ...scalar.FltMapper) (float64, error) {
s, err := d.TryFieldScalarF80BE(name, sms...)
return s.Actual, err
}
// FieldF80BE adds a field and reads 80 bit IEEE 754 float in big-endian
func (d *D) FieldF80BE(name string, sms ...scalar.FltMapper) float64 {
return d.FieldScalarF80BE(name, sms...).Actual
}
// Reader FP // Reader FP
// TryFP tries to read nBits fixed-point number in current endian // TryFP tries to read nBits fixed-point number in current endian

View File

@ -2,6 +2,7 @@ package decode
import ( import (
"bytes" "bytes"
"encoding/binary"
"fmt" "fmt"
"math" "math"
"math/big" "math/big"
@ -20,7 +21,7 @@ func (d *D) tryUEndian(nBits int, endian Endian) (uint64, error) {
if nBits < 0 { if nBits < 0 {
return 0, fmt.Errorf("tryUEndian nBits must be >= 0 (%d)", nBits) return 0, fmt.Errorf("tryUEndian nBits must be >= 0 (%d)", nBits)
} }
n, err := d.TryBits(nBits) n, err := d.TryUintBits(nBits)
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -88,20 +89,22 @@ func (d *D) tryFEndian(nBits int, endian Endian) (float64, error) {
if nBits < 0 { if nBits < 0 {
return 0, fmt.Errorf("tryFEndian nBits must be >= 0 (%d)", nBits) return 0, fmt.Errorf("tryFEndian nBits must be >= 0 (%d)", nBits)
} }
n, err := d.TryBits(nBits) b, err := d.TryBits(nBits)
if err != nil { if err != nil {
return 0, err return 0, err
} }
if endian == LittleEndian { if endian == LittleEndian {
n = bitio.ReverseBytes64(nBits, n) ReverseBytes(b)
} }
switch nBits { switch nBits {
case 16: case 16:
return float64(mathex.Float16(uint16(n)).Float32()), nil return float64(mathex.Float16(binary.BigEndian.Uint16(b)).Float32()), nil
case 32: case 32:
return float64(math.Float32frombits(uint32(n))), nil return float64(math.Float32frombits(binary.BigEndian.Uint32(b))), nil
case 64: case 64:
return math.Float64frombits(n), nil return math.Float64frombits(binary.BigEndian.Uint64(b)), nil
case 80:
return mathex.NewFloat80FromBytes(b).Float64(), nil
default: default:
return 0, fmt.Errorf("unsupported float size %d", nBits) return 0, fmt.Errorf("unsupported float size %d", nBits)
} }
@ -111,7 +114,7 @@ func (d *D) tryFPEndian(nBits int, fBits int, endian Endian) (float64, error) {
if nBits < 0 { if nBits < 0 {
return 0, fmt.Errorf("tryFPEndian nBits must be >= 0 (%d)", nBits) return 0, fmt.Errorf("tryFPEndian nBits must be >= 0 (%d)", nBits)
} }
n, err := d.TryBits(nBits) n, err := d.TryUintBits(nBits)
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -160,7 +163,7 @@ func (d *D) tryTextLenPrefixed(lenBits int, fixedBytes int, e encoding.Encoding)
} }
p := d.Pos() p := d.Pos()
l, err := d.TryBits(lenBits) l, err := d.TryUintBits(lenBits)
if err != nil { if err != nil {
return "", err return "", err
} }
@ -228,7 +231,7 @@ func (d *D) tryUnary(ov uint64) (uint64, error) {
p := d.Pos() p := d.Pos()
var n uint64 var n uint64
for { for {
b, err := d.TryBits(1) b, err := d.TryUintBits(1)
if err != nil { if err != nil {
d.SeekAbs(p) d.SeekAbs(p)
return 0, err return 0, err
@ -242,7 +245,7 @@ func (d *D) tryUnary(ov uint64) (uint64, error) {
} }
func (d *D) tryBool() (bool, error) { func (d *D) tryBool() (bool, error) {
n, err := d.TryBits(1) n, err := d.TryUintBits(1)
if err != nil { if err != nil {
return false, err return false, err
} }

View File

@ -290,6 +290,13 @@
"call" : "d.tryFEndian(64, d.Endian)" , "call" : "d.tryFEndian(64, d.Endian)" ,
"doc" : "64 bit IEEE 754 float in current endian" "doc" : "64 bit IEEE 754 float in current endian"
}, },
{
"name" : "80" ,
"args" : "" ,
"params": "" ,
"call" : "d.tryFEndian(80, d.Endian)" ,
"doc" : "80 bit IEEE 754 float in current endian"
},
{ {
"name" : "16LE" , "name" : "16LE" ,
"args" : "" , "args" : "" ,
@ -311,6 +318,13 @@
"call" : "d.tryFEndian(64, LittleEndian)" , "call" : "d.tryFEndian(64, LittleEndian)" ,
"doc" : "64 bit IEEE 754 float in little-endian" "doc" : "64 bit IEEE 754 float in little-endian"
}, },
{
"name" : "80LE" ,
"args" : "" ,
"params": "" ,
"call" : "d.tryFEndian(80, LittleEndian)" ,
"doc" : "80 bit IEEE 754 float in little-endian"
},
{ {
"name" : "16BE" , "name" : "16BE" ,
"args" : "" , "args" : "" ,
@ -331,6 +345,13 @@
"params": "" , "params": "" ,
"call" : "d.tryFEndian(64, BigEndian)" , "call" : "d.tryFEndian(64, BigEndian)" ,
"doc" : "64 bit IEEE 754 float in big-endian" "doc" : "64 bit IEEE 754 float in big-endian"
},
{
"name" : "80BE" ,
"args" : "" ,
"params": "" ,
"call" : "d.tryFEndian(80, BigEndian)" ,
"doc" : "80 bit IEEE 754 float in big-endian"
} }
] ]
}, },