diff --git a/format/ar/ar.go b/format/ar/ar.go index 33ef90c2..5be8c322 100644 --- a/format/ar/ar.go +++ b/format/ar/ar.go @@ -1,9 +1,6 @@ package ar import ( - "strconv" - "strings" - "github.com/wader/fq/format" "github.com/wader/fq/format/registry" "github.com/wader/fq/pkg/decode" @@ -27,29 +24,14 @@ func init() { func decodeAr(d *decode.D, in interface{}) interface{} { d.FieldUTF8("signature", 8, d.AssertStr("!\n")) d.FieldArray("files", func(d *decode.D) { - // TODO: extract? share with tar? - mapStrToSymU := func(base int) scalar.Mapper { - return scalar.Fn(func(s scalar.S) (scalar.S, error) { - ts := strings.Trim(s.ActualStr(), " ") - if ts != "" { - n, err := strconv.ParseUint(ts, base, 64) - if err != nil { - return s, err - } - s.Sym = n - } - return s, nil - }) - } - for !d.End() { d.FieldStruct("file", func(d *decode.D) { d.FieldUTF8("identifier", 16, scalar.TrimSpace) - d.FieldUTF8("modification_timestamp", 12, scalar.TrimSpace, mapStrToSymU(10)) - d.FieldUTF8("owner_id", 6, scalar.TrimSpace, mapStrToSymU(10)) - d.FieldUTF8("group_id", 6, scalar.TrimSpace, mapStrToSymU(10)) - d.FieldUTF8("file_mode", 8, scalar.TrimSpace, mapStrToSymU(8)) // Octal - sizeS := d.FieldScalarUTF8("file_size", 10, scalar.TrimSpace, mapStrToSymU(10)) + d.FieldUTF8("modification_timestamp", 12, scalar.TrimSpace, scalar.StrUintToSym(10)) + d.FieldUTF8("owner_id", 6, scalar.TrimSpace, scalar.StrUintToSym(10)) + d.FieldUTF8("group_id", 6, scalar.TrimSpace, scalar.StrUintToSym(10)) + d.FieldUTF8("file_mode", 8, scalar.TrimSpace, scalar.StrUintToSym(8)) // Octal + sizeS := d.FieldScalarUTF8("file_size", 10, scalar.TrimSpace, scalar.StrUintToSym(10)) if sizeS.Sym == nil { d.Fatalf("could not decode file_size") } diff --git a/format/tar/tar.go b/format/tar/tar.go index b0fd55f6..f1ee766e 100644 --- a/format/tar/tar.go +++ b/format/tar/tar.go @@ -5,8 +5,6 @@ package tar import ( "bytes" - "strconv" - "strings" "github.com/wader/fq/format" "github.com/wader/fq/format/registry" @@ -33,17 +31,6 @@ func tarDecode(d *decode.D, in interface{}) interface{} { const blockBits = blockBytes * 8 mapTrimSpaceNull := scalar.Trim(" \x00") - mapOctStrToSymU := scalar.Fn(func(s scalar.S) (scalar.S, error) { - ts := strings.Trim(s.ActualStr(), " ") - if ts != "" { - n, err := strconv.ParseUint(ts, 8, 64) - if err != nil { - return s, err - } - s.Sym = n - } - return s, nil - }) blockPadding := func(d *decode.D) int64 { return (blockBits - (d.Pos() % blockBits)) % blockBits } @@ -58,24 +45,24 @@ func tarDecode(d *decode.D, in interface{}) interface{} { for !d.End() { d.FieldStruct("file", func(d *decode.D) { d.FieldUTF8("name", 100, mapTrimSpaceNull) - d.FieldUTF8NullFixedLen("mode", 8, mapOctStrToSymU) - d.FieldUTF8NullFixedLen("uid", 8, mapOctStrToSymU) - d.FieldUTF8NullFixedLen("gid", 8, mapOctStrToSymU) - sizeS := d.FieldScalarUTF8NullFixedLen("size", 12, mapOctStrToSymU) + d.FieldUTF8NullFixedLen("mode", 8, scalar.StrUintToSym(8)) + d.FieldUTF8NullFixedLen("uid", 8, scalar.StrUintToSym(8)) + d.FieldUTF8NullFixedLen("gid", 8, scalar.StrUintToSym(8)) + sizeS := d.FieldScalarUTF8NullFixedLen("size", 12, scalar.StrUintToSym(8)) if sizeS.Sym == nil { d.Fatalf("could not decode size") } size := int64(sizeS.SymU()) * 8 - d.FieldUTF8NullFixedLen("mtime", 12, mapOctStrToSymU) - d.FieldUTF8NullFixedLen("chksum", 8, mapOctStrToSymU) + d.FieldUTF8NullFixedLen("mtime", 12, scalar.StrUintToSym(8)) + d.FieldUTF8NullFixedLen("chksum", 8, scalar.StrUintToSym(8)) d.FieldUTF8("typeflag", 1, mapTrimSpaceNull) d.FieldUTF8("linkname", 100, mapTrimSpaceNull) d.FieldUTF8("magic", 6, mapTrimSpaceNull, d.AssertStr("ustar")) - d.FieldUTF8NullFixedLen("version", 2, mapOctStrToSymU) + d.FieldUTF8NullFixedLen("version", 2, scalar.StrUintToSym(8)) d.FieldUTF8("uname", 32, mapTrimSpaceNull) d.FieldUTF8("gname", 32, mapTrimSpaceNull) - d.FieldUTF8NullFixedLen("devmajor", 8, mapOctStrToSymU) - d.FieldUTF8NullFixedLen("devminor", 8, mapOctStrToSymU) + d.FieldUTF8NullFixedLen("devmajor", 8, scalar.StrUintToSym(8)) + d.FieldUTF8NullFixedLen("devminor", 8, scalar.StrUintToSym(8)) d.FieldUTF8("prefix", 155, mapTrimSpaceNull) d.FieldRawLen("header_block_padding", blockPadding(d), d.BitBufIsZero()) diff --git a/pkg/scalar/scalar.go b/pkg/scalar/scalar.go index 315a3a21..dd93521f 100644 --- a/pkg/scalar/scalar.go +++ b/pkg/scalar/scalar.go @@ -8,6 +8,7 @@ package scalar import ( "bytes" "fmt" + "strconv" "strings" "github.com/wader/fq/pkg/bitio" @@ -113,6 +114,32 @@ var TrimSpace = Fn(func(s S) (S, error) { return s, nil }) +func strMapToSym(fn func(s string) (interface{}, error)) Mapper { + return Fn(func(s S) (S, error) { + ts := strings.TrimSpace(s.ActualStr()) + if ts != "" { + n, err := fn(ts) + if err != nil { + return s, err + } + s.Sym = n + } + return s, nil + }) +} + +func StrUintToSym(base int) Mapper { + return strMapToSym(func(s string) (interface{}, error) { return strconv.ParseUint(s, base, 64) }) +} + +func StrIntToSym(base int) Mapper { + return strMapToSym(func(s string) (interface{}, error) { return strconv.ParseInt(s, base, 64) }) +} + +func StrFToSym(base int) Mapper { + return strMapToSym(func(s string) (interface{}, error) { return strconv.ParseFloat(s, base) }) +} + //nolint:unparam func rawSym(s S, nBytes int, fn func(b []byte) string) (S, error) { bb, ok := s.Actual.(*bitio.Buffer)