diff --git a/tape/skim.go b/tape/skim.go new file mode 100644 index 0000000..b4d2ab6 --- /dev/null +++ b/tape/skim.go @@ -0,0 +1,54 @@ +package tape + +import "fmt" + +// Skim uses up data from a decoder to "skim" over one value (and all else +// contained within it) without actually putting the data anywhere. +func Skim(decoder *Decoder, tag Tag) (n int, err error) { + switch tag.WithoutCN() { + case SI: + // SI: (none) + return n, nil + case LI, LSI, FP: + // LI: + // LSI: + // FP: + nn, err := decoder.Discard(tag.CN() + 1) + n += nn; if err != nil { return n, err } + case SBA: + // SBA: * + nn, err := decoder.Discard(tag.CN()) + n += nn; if err != nil { return n, err } + case LBA: + // LBA: * + length, nn, err := decoder.ReadUintN(tag.CN() + 1) + n += nn; if err != nil { return n, err } + nn, err = decoder.Discard(int(length)) + n += nn; if err != nil { return n, err } + case OTA: + // OTA: * + length, nn, err := decoder.ReadUintN(tag.CN() + 1) + n += nn; if err != nil { return n, err } + oneTag, nn, err := decoder.ReadTag() + n += nn; if err != nil { return n, err } + for _ = range length { + nn, err := Skim(decoder, oneTag) + n += nn; if err != nil { return n, err } + } + case KTV: + // KTV: ( )* + length, nn, err := decoder.ReadUintN(tag.CN() + 1) + n += nn; if err != nil { return n, err } + for _ = range length { + nn, err := decoder.Discard(2) + n += nn; if err != nil { return n, err } + itemTag, nn, err := decoder.ReadTag() + n += nn; if err != nil { return n, err } + nn, err = Skim(decoder, itemTag) + n += nn; if err != nil { return n, err } + } + default: + return n, fmt.Errorf("unknown TN %d", tag.TN()) + } + return n, nil +}