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

Add to/bytes/bits[range]

This commit is contained in:
Mattias Wadman 2021-10-15 18:19:59 +02:00
parent a050adca49
commit 7f36f703dd
10 changed files with 450 additions and 53 deletions

View File

@ -1,4 +1,5 @@
Copyright (c) 2021 Mattias Wadman Copyright (c) 2021 Mattias Wadman
colorjson fork and various code in gojqextra package Copyright (c) 2019-2021 itchyny
Permission is hereby granted, free of charge, to any person obtaining a copy of Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in this software and associated documentation files (the "Software"), to deal in

View File

@ -142,16 +142,22 @@ notable is support for arbitrary-precision integers.
- `format_root/0` return root value of format for value - `format_root/0` return root value of format for value
- `parent/0` return parent value - `parent/0` return parent value
- `parents/0` output parents of value - `parents/0` output parents of value
- `find` and `grep` all take 1 or 2 arguments. First is a scalar to match, where a string is - All `find` and `grep` functions take 1 or 2 arguments. First is a scalar to match, where a string is
treated as a regexp. A buffer will be matches exact bytes. Second argument is regexp treated as a regexp. A buffer scalar will be matches exact bytes. Second argument are regexp
flags with addition to "b" which will treat each byte in the input buffer as a rune, this flags with addition that "b" will treat each byte in the input buffer as a code point, this
makes it possible to match exact bytes, ex: `find("\u00ff"; b")` will match the byte `0xff` and not makes it possible to match exact bytes, ex: `find("\u00ff"; b")` will match the byte `0xff` and not
the UTF-8 codepoint `0xff`. the UTF-8 encoded codepoint for 255.
- `find/1`, `find/2` match in buffer and output match buffers - `find/1`, `find/2` match in buffer and output match buffers
- `grep/1`, `grep/2` recursively match value and buffer - `grep/1`, `grep/2` recursively match value and buffer
- `vgrep/1`, `vgrep/2` recursively match value - `vgrep/1`, `vgrep/2` recursively match value
- `bgrep/1`, `bgrep/2` recursively match buffer - `bgrep/1`, `bgrep/2` recursively match buffer
- `fgrep/1`, `fgrep/2` recursively match field name - `fgrep/1`, `fgrep/2` recursively match field name
- Buffers:
- `tobits` - Transform input into a bits buffer not preserving source range, will start at zero.
- `tobitsrange` - Transform input into a bits buffer preserving source range if possible.
- `tobytes` - Transform input into a bytes buffer not preserving source range, will start at zero.
- `tobytesrange` - Transform input into a byte buffer preserving source range if possible.
- `buffer[start:end]`, `buffer[:end]`, `buffer[start:]` - Create a sub buffer from start to end in buffer units preserving source range.
- `open` open file for reading - `open` open file for reading
- `probe` or `decode` probe format and decode - `probe` or `decode` probe format and decode
- `mp3`, `matroska`, ..., `<name>`, `decode([name])` force decode as format - `mp3`, `matroska`, ..., `<name>`, `decode([name])` force decode as format

View File

@ -1,17 +1,40 @@
package gojqextra package gojqextra
import "fmt" import (
"fmt"
"math/big"
// many of these based on errors form gojq "github.com/wader/gojq"
)
// many of these based on errors from gojq
// TODO: refactor to use errors from gojq? // TODO: refactor to use errors from gojq?
// TODO: preview from gojq? // TODO: preview from gojq?
type NonUpdatableTypeError struct {
Typ string
Key string
}
func (err NonUpdatableTypeError) Error() string {
return fmt.Sprintf("update key %v cannot be applied to: %s", err.Key, err.Typ)
}
type FuncTypeError struct { type FuncTypeError struct {
Name string
V interface{}
}
func (err FuncTypeError) Error() string { return err.Name + " cannot be applied to: " + typeof(err.V) }
type FuncTypeNameError struct {
Name string Name string
Typ string Typ string
} }
func (err FuncTypeError) Error() string { return err.Name + " cannot be applied to: " + err.Typ } func (err FuncTypeNameError) Error() string {
return err.Name + " cannot be applied to: " + err.Typ
}
type ExpectedObjectError struct { type ExpectedObjectError struct {
Typ string Typ string
@ -70,3 +93,24 @@ type ArrayIndexTooLargeError struct {
func (err *ArrayIndexTooLargeError) Error() string { func (err *ArrayIndexTooLargeError) Error() string {
return fmt.Sprintf("array index too large: %v", err.V) return fmt.Sprintf("array index too large: %v", err.V)
} }
func typeof(v interface{}) string {
switch v := v.(type) {
case nil:
return "null"
case bool:
return "boolean"
case int, float64, *big.Int:
return "number"
case string:
return "string"
case []interface{}:
return "array"
case map[string]interface{}:
return "object"
case gojq.JQValue:
return fmt.Sprintf("JQValue(%s)", v.JQValueType())
default:
panic(fmt.Sprintf("invalid value: %v", v))
}
}

View File

@ -0,0 +1,12 @@
// from gojq
// The MIT License (MIT)
// Copyright (c) 2019-2021 itchyny
package gojqextra
import "math/bits"
const (
maxInt = 1<<(bits.UintSize-1) - 1 // math.MaxInt64 or math.MaxInt32
minInt = -maxInt - 1 // math.MinInt64 or math.MinInt32
)

View File

@ -0,0 +1,127 @@
// Some of these functions are based on gojq func.go functions
// TODO: maybe should be exported from gojq fq branch instead?
// The MIT License (MIT)
// Copyright (c) 2019-2021 itchyny
package gojqextra
import (
"math"
"math/big"
"strconv"
"github.com/wader/gojq"
)
func ToString(x interface{}) (string, bool) {
switch x := x.(type) {
case string:
return x, true
case gojq.JQValue:
return ToString(x.JQValueToGoJQ())
default:
return "", false
}
}
func ToObject(x interface{}) (map[string]interface{}, bool) {
switch x := x.(type) {
case map[string]interface{}:
return x, true
case gojq.JQValue:
return ToObject(x.JQValueToGoJQ())
default:
return nil, false
}
}
func ToArray(x interface{}) ([]interface{}, bool) {
switch x := x.(type) {
case []interface{}:
return x, true
case gojq.JQValue:
return ToArray(x.JQValueToGoJQ())
default:
return nil, false
}
}
func ToBoolean(x interface{}) (bool, bool) {
switch x := x.(type) {
case bool:
return x, true
case gojq.JQValue:
return ToBoolean(x.JQValueToGoJQ())
default:
return false, false
}
}
func IsNull(x interface{}) bool {
switch x := x.(type) {
case nil:
return true
case gojq.JQValue:
return IsNull(x.JQValueToGoJQ())
default:
return false
}
}
func ToInt(x interface{}) (int, bool) {
switch x := x.(type) {
case int:
return x, true
case float64:
return floatToInt(x), true
case *big.Int:
if x.IsInt64() {
if i := x.Int64(); minInt <= i && i <= maxInt {
return int(i), true
}
}
if x.Sign() > 0 {
return maxInt, true
}
return minInt, true
case gojq.JQValue:
return ToInt(x.JQValueToGoJQ())
default:
return 0, false
}
}
func floatToInt(x float64) int {
if minInt <= x && x <= maxInt {
return int(x)
}
if x > 0 {
return maxInt
}
return minInt
}
func ToFloat(x interface{}) (float64, bool) {
switch x := x.(type) {
case int:
return float64(x), true
case float64:
return x, true
case *big.Int:
return bigToFloat(x), true
case gojq.JQValue:
return ToFloat(x.JQValueToGoJQ())
default:
return 0.0, false
}
}
func bigToFloat(x *big.Int) float64 {
if x.IsInt64() {
return float64(x.Int64())
}
if f, err := strconv.ParseFloat(x.String(), 64); err == nil {
return f
}
return math.Inf(x.Sign())
}

View File

@ -23,15 +23,6 @@ func expectedArrayOrObject(key interface{}, typ string) error {
} }
} }
type NonUpdatableTypeError struct {
Typ string
Key string
}
func (err NonUpdatableTypeError) Error() string {
return fmt.Sprintf("update key %v cannot be applied to: %s", err.Key, err.Typ)
}
// array // array
var _ gojq.JQValue = Array{} var _ gojq.JQValue = Array{}
@ -86,7 +77,8 @@ func (v Array) JQValueUpdate(key interface{}, u interface{}, delpath bool) inter
if delpath { if delpath {
return v return v
} }
return FuncTypeError{Name: "setpath", Typ: "number"} // TODO: wrong error?
return FuncTypeNameError{Name: "setpath", Typ: "number"}
} else if intKey < 0 { } else if intKey < 0 {
intKey += len(v) intKey += len(v)
} }
@ -111,10 +103,10 @@ func (v Array) JQValueHas(key interface{}) interface{} {
} }
func (v Array) JQValueType() string { return "array" } func (v Array) JQValueType() string { return "array" }
func (v Array) JQValueToNumber() interface{} { func (v Array) JQValueToNumber() interface{} {
return FuncTypeError{Name: "tonumber", Typ: "array"} return FuncTypeNameError{Name: "tonumber", Typ: "array"}
} }
func (v Array) JQValueToString() interface{} { func (v Array) JQValueToString() interface{} {
return FuncTypeError{Name: "tostring", Typ: "array"} return FuncTypeNameError{Name: "tostring", Typ: "array"}
} }
func (v Array) JQValueToGoJQ() interface{} { return []interface{}(v) } func (v Array) JQValueToGoJQ() interface{} { return []interface{}(v) }
@ -177,10 +169,10 @@ func (v Object) JQValueHas(key interface{}) interface{} {
} }
func (v Object) JQValueType() string { return "object" } func (v Object) JQValueType() string { return "object" }
func (v Object) JQValueToNumber() interface{} { func (v Object) JQValueToNumber() interface{} {
return FuncTypeError{Name: "tonumber", Typ: "object"} return FuncTypeNameError{Name: "tonumber", Typ: "object"}
} }
func (v Object) JQValueToString() interface{} { func (v Object) JQValueToString() interface{} {
return FuncTypeError{Name: "tostring", Typ: "object"} return FuncTypeNameError{Name: "tostring", Typ: "object"}
} }
func (v Object) JQValueToGoJQ() interface{} { return map[string]interface{}(v) } func (v Object) JQValueToGoJQ() interface{} { return map[string]interface{}(v) }
@ -203,9 +195,9 @@ func (v Number) JQValueUpdate(key interface{}, u interface{}, delpath bool) inte
return expectedArrayOrObject(key, "number") return expectedArrayOrObject(key, "number")
} }
func (v Number) JQValueEach() interface{} { return IteratorError{Typ: "number"} } func (v Number) JQValueEach() interface{} { return IteratorError{Typ: "number"} }
func (v Number) JQValueKeys() interface{} { return FuncTypeError{Name: "keys", Typ: "number"} } func (v Number) JQValueKeys() interface{} { return FuncTypeNameError{Name: "keys", Typ: "number"} }
func (v Number) JQValueHas(key interface{}) interface{} { func (v Number) JQValueHas(key interface{}) interface{} {
return FuncTypeError{Name: "has", Typ: "number"} return FuncTypeNameError{Name: "has", Typ: "number"}
} }
func (v Number) JQValueType() string { return "number" } func (v Number) JQValueType() string { return "number" }
func (v Number) JQValueToNumber() interface{} { return v.V } func (v Number) JQValueToNumber() interface{} { return v.V }
@ -240,9 +232,9 @@ func (v String) JQValueUpdate(key interface{}, u interface{}, delpath bool) inte
return expectedArrayOrObject(key, "string") return expectedArrayOrObject(key, "string")
} }
func (v String) JQValueEach() interface{} { return IteratorError{Typ: "string"} } func (v String) JQValueEach() interface{} { return IteratorError{Typ: "string"} }
func (v String) JQValueKeys() interface{} { return FuncTypeError{Name: "keys", Typ: "string"} } func (v String) JQValueKeys() interface{} { return FuncTypeNameError{Name: "keys", Typ: "string"} }
func (v String) JQValueHas(key interface{}) interface{} { func (v String) JQValueHas(key interface{}) interface{} {
return FuncTypeError{Name: "has", Typ: "string"} return FuncTypeNameError{Name: "has", Typ: "string"}
} }
func (v String) JQValueType() string { return "string" } func (v String) JQValueType() string { return "string" }
func (v String) JQValueToNumber() interface{} { return gojq.NormalizeNumbers(string(v)) } func (v String) JQValueToNumber() interface{} { return gojq.NormalizeNumbers(string(v)) }
@ -255,7 +247,9 @@ var _ gojq.JQValue = Boolean(true)
type Boolean bool type Boolean bool
func (v Boolean) JQValueLength() interface{} { return FuncTypeError{Name: "length", Typ: "boolean"} } func (v Boolean) JQValueLength() interface{} {
return FuncTypeNameError{Name: "length", Typ: "boolean"}
}
func (v Boolean) JQValueSliceLen() interface{} { return ExpectedArrayError{Typ: "boolean"} } func (v Boolean) JQValueSliceLen() interface{} { return ExpectedArrayError{Typ: "boolean"} }
func (v Boolean) JQValueIndex(index int) interface{} { return ExpectedArrayError{Typ: "boolean"} } func (v Boolean) JQValueIndex(index int) interface{} { return ExpectedArrayError{Typ: "boolean"} }
func (v Boolean) JQValueSlice(start int, end int) interface{} { func (v Boolean) JQValueSlice(start int, end int) interface{} {
@ -266,13 +260,13 @@ func (v Boolean) JQValueUpdate(key interface{}, u interface{}, delpath bool) int
return expectedArrayOrObject(key, "boolean") return expectedArrayOrObject(key, "boolean")
} }
func (v Boolean) JQValueEach() interface{} { return IteratorError{Typ: "boolean"} } func (v Boolean) JQValueEach() interface{} { return IteratorError{Typ: "boolean"} }
func (v Boolean) JQValueKeys() interface{} { return FuncTypeError{Name: "keys", Typ: "boolean"} } func (v Boolean) JQValueKeys() interface{} { return FuncTypeNameError{Name: "keys", Typ: "boolean"} }
func (v Boolean) JQValueHas(key interface{}) interface{} { func (v Boolean) JQValueHas(key interface{}) interface{} {
return FuncTypeError{Name: "has", Typ: "boolean"} return FuncTypeNameError{Name: "has", Typ: "boolean"}
} }
func (v Boolean) JQValueType() string { return "boolean" } func (v Boolean) JQValueType() string { return "boolean" }
func (v Boolean) JQValueToNumber() interface{} { func (v Boolean) JQValueToNumber() interface{} {
return FuncTypeError{Name: "tonumber", Typ: "boolean"} return FuncTypeNameError{Name: "tonumber", Typ: "boolean"}
} }
func (v Boolean) JQValueToString() interface{} { func (v Boolean) JQValueToString() interface{} {
if v { if v {
@ -296,13 +290,15 @@ func (v Null) JQValueKey(name string) interface{} { return ExpectedObje
func (v Null) JQValueUpdate(key interface{}, u interface{}, delpath bool) interface{} { func (v Null) JQValueUpdate(key interface{}, u interface{}, delpath bool) interface{} {
return expectedArrayOrObject(key, "null") return expectedArrayOrObject(key, "null")
} }
func (v Null) JQValueEach() interface{} { return IteratorError{Typ: "null"} } func (v Null) JQValueEach() interface{} { return IteratorError{Typ: "null"} }
func (v Null) JQValueKeys() interface{} { return FuncTypeError{Name: "keys", Typ: "null"} } func (v Null) JQValueKeys() interface{} { return FuncTypeNameError{Name: "keys", Typ: "null"} }
func (v Null) JQValueHas(key interface{}) interface{} { return FuncTypeError{Name: "has", Typ: "null"} } func (v Null) JQValueHas(key interface{}) interface{} {
func (v Null) JQValueType() string { return "null" } return FuncTypeNameError{Name: "has", Typ: "null"}
func (v Null) JQValueToNumber() interface{} { return FuncTypeError{Name: "tonumber", Typ: "null"} } }
func (v Null) JQValueToString() interface{} { return "null" } func (v Null) JQValueType() string { return "null" }
func (v Null) JQValueToGoJQ() interface{} { return nil } func (v Null) JQValueToNumber() interface{} { return FuncTypeNameError{Name: "tonumber", Typ: "null"} }
func (v Null) JQValueToString() interface{} { return "null" }
func (v Null) JQValueToGoJQ() interface{} { return nil }
// Base // Base
@ -325,11 +321,11 @@ func (v Base) JQValueUpdate(key interface{}, u interface{}, delpath bool) interf
return expectedArrayOrObject(key, v.Typ) return expectedArrayOrObject(key, v.Typ)
} }
func (v Base) JQValueEach() interface{} { return IteratorError{Typ: v.Typ} } func (v Base) JQValueEach() interface{} { return IteratorError{Typ: v.Typ} }
func (v Base) JQValueKeys() interface{} { return FuncTypeError{Name: "keys", Typ: v.Typ} } func (v Base) JQValueKeys() interface{} { return FuncTypeNameError{Name: "keys", Typ: v.Typ} }
func (v Base) JQValueHas(key interface{}) interface{} { func (v Base) JQValueHas(key interface{}) interface{} {
return HasKeyTypeError{L: "array", R: fmt.Sprintf("%v", key)} return HasKeyTypeError{L: "array", R: fmt.Sprintf("%v", key)}
} }
func (v Base) JQValueType() string { return v.Typ } func (v Base) JQValueType() string { return v.Typ }
func (v Base) JQValueToNumber() interface{} { return FuncTypeError{Name: "tonumber", Typ: v.Typ} } func (v Base) JQValueToNumber() interface{} { return FuncTypeNameError{Name: "tonumber", Typ: v.Typ} }
func (v Base) JQValueToString() interface{} { return FuncTypeError{Name: "tostring", Typ: v.Typ} } func (v Base) JQValueToString() interface{} { return FuncTypeNameError{Name: "tostring", Typ: v.Typ} }
func (v Base) JQValueToGoJQ() interface{} { return nil } func (v Base) JQValueToGoJQ() interface{} { return nil }

View File

@ -116,7 +116,7 @@ func (bv BufferView) JQValueType() string {
return "buffer" return "buffer"
} }
func (bv BufferView) JQValueKeys() interface{} { func (bv BufferView) JQValueKeys() interface{} {
return gojqextra.FuncTypeError{Name: "keys", Typ: "buffer"} return gojqextra.FuncTypeNameError{Name: "keys", Typ: "buffer"}
} }
func (bv BufferView) JQValueHas(key interface{}) interface{} { func (bv BufferView) JQValueHas(key interface{}) interface{} {
return gojqextra.HasKeyTypeError{L: "buffer", R: fmt.Sprintf("%v", key)} return gojqextra.HasKeyTypeError{L: "buffer", R: fmt.Sprintf("%v", key)}

View File

@ -60,8 +60,8 @@ func (i *Interp) makeFunctions() []Function {
{[]string{"_display"}, 1, 1, nil, i._display}, {[]string{"_display"}, 1, 1, nil, i._display},
{[]string{"_hexdump"}, 1, 1, nil, i._hexdump}, {[]string{"_hexdump"}, 1, 1, nil, i._hexdump},
{[]string{"tobytes"}, 0, 0, i.toBytes, nil}, {[]string{"_tobitsrange"}, 0, 2, i._toBitsRange, nil},
{[]string{"tobits"}, 0, 0, i.toBits, nil},
{[]string{"tovalue"}, 0, 1, i.toValue, nil}, {[]string{"tovalue"}, 0, 1, i.toValue, nil},
{[]string{"hex"}, 0, 0, makeStringBitBufTransformFn( {[]string{"hex"}, 0, 0, makeStringBitBufTransformFn(
@ -700,20 +700,44 @@ func (i *Interp) _display(c interface{}, a []interface{}) gojq.Iter {
} }
} }
func (i *Interp) toBytes(c interface{}, a []interface{}) interface{} { // note is used to implement tobytes*/0 also
bb, err := toBuffer(c) func (i *Interp) _toBitsRange(c interface{}, a []interface{}) interface{} {
if err != nil { var unit int
return err var r bool
} var ok bool
return bufferViewFromBuffer(bb, 8)
}
func (i *Interp) toBits(c interface{}, a []interface{}) interface{} { if len(a) >= 1 {
bb, err := toBuffer(c) unit, ok = gojqextra.ToInt(a[0])
if !ok {
return gojqextra.FuncTypeError{Name: "_tobitsrange", V: a[0]}
}
} else {
unit = 1
}
if len(a) >= 2 {
r, ok = gojqextra.ToBoolean(a[1])
if !ok {
return gojqextra.FuncTypeError{Name: "_tobitsrange", V: a[1]}
}
} else {
r = true
}
// TODO: unit > 8?
bv, err := toBufferView(c)
if err != nil { if err != nil {
return err return err
} }
return bufferViewFromBuffer(bb, 1) bv.unit = unit
if !r {
bb, _ := bv.toBuffer()
return bufferViewFromBuffer(bb, unit)
}
return bv
} }
func (i *Interp) toValue(c interface{}, a []interface{}) interface{} { func (i *Interp) toValue(c interface{}, a []interface{}) interface{} {
@ -838,7 +862,7 @@ func (i *Interp) find(c interface{}, a []interface{}) gojq.Iter {
if len(a) > 1 { if len(a) > 1 {
flags, ok = a[1].(string) flags, ok = a[1].(string)
if !ok { if !ok {
return gojq.NewIter(gojqextra.FuncTypeError{Name: "find", Typ: "string"}) return gojq.NewIter(gojqextra.FuncTypeNameError{Name: "find", Typ: "string"})
} }
} }

View File

@ -51,6 +51,11 @@ def parents:
end end
); );
def tobitsrange: _tobitsrange;
def tobytesrange: _tobitsrange(8);
def tobits: _tobitsrange(1; false);
def tobytes: _tobitsrange(8; false);
def formats: def formats:
_registry.formats; _registry.formats;

View File

@ -55,3 +55,185 @@ error: buffer byte list must be bytes (0-255) got -1
mp3> [256] | tobytes mp3> [256] | tobytes
error: buffer byte list must be bytes (0-255) got 256 error: buffer byte list must be bytes (0-255) got 256
mp3> ^D mp3> ^D
$ fq -d mp3 -i . /test.mp3
mp3> .frames[1] | tobits | ., .start, .stop, .size, .[4:17], (tobits, tobytes, tobitsrange, tobytesrange | ., .start, .stop, .size, .[4:17])
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|
0x00|ff fb 50 c4 00 00 0a 2c 43 2e 55 94 80 01 80 93|..P....,C.U.....|.: none 0x0-0xcf.7 (208)
* |until 0xcf.7 (end) (208) | |
0
1664
1664
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|
0x0|ff fb 50 |..P |.: none 0x0.4-0x2 (1.5)
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|
0x00|ff fb 50 c4 00 00 0a 2c 43 2e 55 94 80 01 80 93|..P....,C.U.....|.: none 0x0-0xcf.7 (208)
* |until 0xcf.7 (end) (208) | |
0
1664
1664
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|
0x0|ff fb 50 |..P |.: none 0x0.4-0x2 (1.5)
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|
0x00|ff fb 50 c4 00 00 0a 2c 43 2e 55 94 80 01 80 93|..P....,C.U.....|.: none 0x0-0xcf.7 (208)
* |until 0xcf.7 (end) (208) | |
0
208
208
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|
0x00| 00 00 0a 2c 43 2e 55 94 80 01 80 93| ...,C.U.....|.: none 0x4-0x10.7 (13)
0x10|6b |k |
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|
0x00|ff fb 50 c4 00 00 0a 2c 43 2e 55 94 80 01 80 93|..P....,C.U.....|.: none 0x0-0xcf.7 (208)
* |until 0xcf.7 (end) (208) | |
0
1664
1664
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|
0x0|ff fb 50 |..P |.: none 0x0.4-0x2 (1.5)
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|
0x00|ff fb 50 c4 00 00 0a 2c 43 2e 55 94 80 01 80 93|..P....,C.U.....|.: none 0x0-0xcf.7 (208)
* |until 0xcf.7 (end) (208) | |
0
208
208
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|
0x00| 00 00 0a 2c 43 2e 55 94 80 01 80 93| ...,C.U.....|.: none 0x4-0x10.7 (13)
0x10|6b |k |
mp3> .frames[1] | tobytes | ., .start, .stop, .size, .[4:17], (tobits, tobytes, tobitsrange, tobytesrange | ., .start, .stop, .size, .[4:17])
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|
0x00|ff fb 50 c4 00 00 0a 2c 43 2e 55 94 80 01 80 93|..P....,C.U.....|.: none 0x0-0xcf.7 (208)
* |until 0xcf.7 (end) (208) | |
0
208
208
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|
0x00| 00 00 0a 2c 43 2e 55 94 80 01 80 93| ...,C.U.....|.: none 0x4-0x10.7 (13)
0x10|6b |k |
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|
0x00|ff fb 50 c4 00 00 0a 2c 43 2e 55 94 80 01 80 93|..P....,C.U.....|.: none 0x0-0xcf.7 (208)
* |until 0xcf.7 (end) (208) | |
0
1664
1664
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|
0x0|ff fb 50 |..P |.: none 0x0.4-0x2 (1.5)
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|
0x00|ff fb 50 c4 00 00 0a 2c 43 2e 55 94 80 01 80 93|..P....,C.U.....|.: none 0x0-0xcf.7 (208)
* |until 0xcf.7 (end) (208) | |
0
208
208
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|
0x00| 00 00 0a 2c 43 2e 55 94 80 01 80 93| ...,C.U.....|.: none 0x4-0x10.7 (13)
0x10|6b |k |
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|
0x00|ff fb 50 c4 00 00 0a 2c 43 2e 55 94 80 01 80 93|..P....,C.U.....|.: none 0x0-0xcf.7 (208)
* |until 0xcf.7 (end) (208) | |
0
1664
1664
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|
0x0|ff fb 50 |..P |.: none 0x0.4-0x2 (1.5)
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|
0x00|ff fb 50 c4 00 00 0a 2c 43 2e 55 94 80 01 80 93|..P....,C.U.....|.: none 0x0-0xcf.7 (208)
* |until 0xcf.7 (end) (208) | |
0
208
208
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|
0x00| 00 00 0a 2c 43 2e 55 94 80 01 80 93| ...,C.U.....|.: none 0x4-0x10.7 (13)
0x10|6b |k |
mp3> .frames[1] | tobitsrange | ., .start, .stop, .size, .[4:17], (tobits, tobytes, tobitsrange, tobytesrange | ., .start, .stop, .size, .[4:17])
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|
0x0e0| ff fb 50 c4 00 00 0a 2c 43 2e 55 94 80| ..P....,C.U..|.: none 0xe3-0x1b2.7 (208)
0x0f0|01 80 93 6b 27 30 80 00 07 aa c3 8e 33 85 d3 64|...k'0......3..d|
* |until 0x1b2.7 (208) | |
1816
3480
1664
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|
0xe0| ff fb 50 | ..P |.: none 0xe3.4-0xe5 (1.5)
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|
0x00|ff fb 50 c4 00 00 0a 2c 43 2e 55 94 80 01 80 93|..P....,C.U.....|.: none 0x0-0xcf.7 (208)
* |until 0xcf.7 (end) (208) | |
0
1664
1664
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|
0x0|ff fb 50 |..P |.: none 0x0.4-0x2 (1.5)
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|
0x00|ff fb 50 c4 00 00 0a 2c 43 2e 55 94 80 01 80 93|..P....,C.U.....|.: none 0x0-0xcf.7 (208)
* |until 0xcf.7 (end) (208) | |
0
208
208
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|
0x00| 00 00 0a 2c 43 2e 55 94 80 01 80 93| ...,C.U.....|.: none 0x4-0x10.7 (13)
0x10|6b |k |
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|
0x0e0| ff fb 50 c4 00 00 0a 2c 43 2e 55 94 80| ..P....,C.U..|.: none 0xe3-0x1b2.7 (208)
0x0f0|01 80 93 6b 27 30 80 00 07 aa c3 8e 33 85 d3 64|...k'0......3..d|
* |until 0x1b2.7 (208) | |
1816
3480
1664
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|
0xe0| ff fb 50 | ..P |.: none 0xe3.4-0xe5 (1.5)
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|
0x0e0| ff fb 50 c4 00 00 0a 2c 43 2e 55 94 80| ..P....,C.U..|.: none 0xe3-0x1b2.7 (208)
0x0f0|01 80 93 6b 27 30 80 00 07 aa c3 8e 33 85 d3 64|...k'0......3..d|
* |until 0x1b2.7 (208) | |
227
435
208
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|
0xe0| 00 00 0a 2c 43 2e 55 94 80| ...,C.U..|.: none 0xe7-0xf3.7 (13)
0xf0|01 80 93 6b |...k |
mp3> .frames[1] | tobytesrange | ., .start, .stop, .size, .[4:17], (tobits, tobytes, tobitsrange, tobytesrange | ., .start, .stop, .size, .[4:17])
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|
0x0e0| ff fb 50 c4 00 00 0a 2c 43 2e 55 94 80| ..P....,C.U..|.: none 0xe3-0x1b2.7 (208)
0x0f0|01 80 93 6b 27 30 80 00 07 aa c3 8e 33 85 d3 64|...k'0......3..d|
* |until 0x1b2.7 (208) | |
227
435
208
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|
0xe0| 00 00 0a 2c 43 2e 55 94 80| ...,C.U..|.: none 0xe7-0xf3.7 (13)
0xf0|01 80 93 6b |...k |
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|
0x00|ff fb 50 c4 00 00 0a 2c 43 2e 55 94 80 01 80 93|..P....,C.U.....|.: none 0x0-0xcf.7 (208)
* |until 0xcf.7 (end) (208) | |
0
1664
1664
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|
0x0|ff fb 50 |..P |.: none 0x0.4-0x2 (1.5)
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|
0x00|ff fb 50 c4 00 00 0a 2c 43 2e 55 94 80 01 80 93|..P....,C.U.....|.: none 0x0-0xcf.7 (208)
* |until 0xcf.7 (end) (208) | |
0
208
208
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|
0x00| 00 00 0a 2c 43 2e 55 94 80 01 80 93| ...,C.U.....|.: none 0x4-0x10.7 (13)
0x10|6b |k |
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|
0x0e0| ff fb 50 c4 00 00 0a 2c 43 2e 55 94 80| ..P....,C.U..|.: none 0xe3-0x1b2.7 (208)
0x0f0|01 80 93 6b 27 30 80 00 07 aa c3 8e 33 85 d3 64|...k'0......3..d|
* |until 0x1b2.7 (208) | |
1816
3480
1664
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|
0xe0| ff fb 50 | ..P |.: none 0xe3.4-0xe5 (1.5)
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|
0x0e0| ff fb 50 c4 00 00 0a 2c 43 2e 55 94 80| ..P....,C.U..|.: none 0xe3-0x1b2.7 (208)
0x0f0|01 80 93 6b 27 30 80 00 07 aa c3 8e 33 85 d3 64|...k'0......3..d|
* |until 0x1b2.7 (208) | |
227
435
208
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|
0xe0| 00 00 0a 2c 43 2e 55 94 80| ...,C.U..|.: none 0xe7-0xf3.7 (13)
0xf0|01 80 93 6b |...k |
mp3> ^D