diff options
author | Luke Shumaker <lukeshu@datawire.io> | 2022-08-14 17:05:38 -0600 |
---|---|---|
committer | Luke Shumaker <lukeshu@datawire.io> | 2022-08-14 20:31:42 -0600 |
commit | c11411d3591de78417f9ded2ca443c366f92367e (patch) | |
tree | b6d7c57e58858345e2caa9e41a9562b017cf68b4 | |
parent | 2ba5d96ccba101e6ccbf32b08e2fd18d4b8d7787 (diff) |
decode: Switch over to Parser
-rw-r--r-- | adapter_test.go | 4 | ||||
-rw-r--r-- | decode.go | 504 | ||||
-rw-r--r-- | parse.go | 15 |
3 files changed, 231 insertions, 292 deletions
diff --git a/adapter_test.go b/adapter_test.go index b1aec3e..6c57ebc 100644 --- a/adapter_test.go +++ b/adapter_test.go @@ -5,7 +5,6 @@ package lowmemjson import ( - "bufio" "bytes" "encoding/json" "io" @@ -76,8 +75,7 @@ func init() { } func (dec *Decoder) Buffered() io.Reader { - buf := dec.r.(*bufio.Reader) - dat, _ := buf.Peek(buf.Buffered()) + dat, _ := dec.buf.Peek(dec.buf.Buffered()) return bytes.NewReader(dat) } @@ -27,41 +27,54 @@ type runeBuffer interface { } type Decoder struct { - r io.RuneScanner + io runeTypeScanner + buf *bufio.Reader // config disallowUnknownFields bool useNumber bool // state - err error - curPos int64 - nxtPos int64 - stack []any + err error + stack []any } -var forceBufio bool +var forceBufio bool // used by the tests to implement .Buffered() func NewDecoder(r io.Reader) *Decoder { - rs, ok := r.(io.RuneScanner) + rr, ok := r.(io.RuneReader) + var ret Decoder if forceBufio || !ok { - rs = bufio.NewReader(r) + rr = bufio.NewReader(r) + if forceBufio { + ret.buf = rr.(*bufio.Reader) + } } - return &Decoder{ - r: rs, + ret.io = &noWSRuneTypeScanner{ + inner: &runeTypeScannerImpl{ + inner: rr, + }, } + return &ret } func (dec *Decoder) DisallowUnknownFields() { dec.disallowUnknownFields = true } func (dec *Decoder) UseNumber() { dec.useNumber = true } -func (dec *Decoder) InputOffset() int64 { return dec.curPos } +func (dec *Decoder) InputOffset() int64 { return dec.io.InputOffset() } func (dec *Decoder) More() bool { - dec.decodeWS() - _, ok := dec.peekRuneOrEOF() - return ok + dec.io.Reset() + _, _, t, e := dec.io.ReadRuneType() + dec.io.UnreadRune() + return e == nil && t != RuneTypeEOF } +func (dec *Decoder) stackPush(idx any) { + dec.stack = append(dec.stack, idx) +} +func (dec *Decoder) stackPop() { + dec.stack = dec.stack[:len(dec.stack)-1] +} func (dec *Decoder) stackStr() string { var buf strings.Builder buf.WriteString("v") @@ -71,30 +84,6 @@ func (dec *Decoder) stackStr() string { return buf.String() } -func (dec *Decoder) stackPush(idx any) { - dec.stack = append(dec.stack, idx) -} -func (dec *Decoder) stackPop() { - dec.stack = dec.stack[:len(dec.stack)-1] -} - -type decodeError struct { - Err error -} - -func (dec *Decoder) panicIO(err error) { - panic(decodeError{fmt.Errorf("json: I/O error at input byte %v: %s: %w", - dec.nxtPos, dec.stackStr(), err)}) -} -func (dec *Decoder) panicSyntax(err error) { - panic(decodeError{fmt.Errorf("json: syntax error at input byte %v: %s: %w", - dec.curPos, dec.stackStr(), err)}) -} -func (dec *Decoder) panicType(typ reflect.Type, err error) { - panic(decodeError{fmt.Errorf("json: type mismatch error at input byte %v: %s: type %v: %w", - dec.curPos, dec.stackStr(), typ, err)}) -} - func Decode(r io.Reader, ptr any) error { return NewDecoder(r).Decode(ptr) } @@ -112,6 +101,7 @@ func (dec *Decoder) Decode(ptr any) (err error) { return dec.err } + dec.io.Reset() defer func() { if r := recover(); r != nil { if de, ok := r.(decodeError); ok { @@ -122,90 +112,98 @@ func (dec *Decoder) Decode(ptr any) (err error) { } } }() - dec.decodeWS() dec.decode(ptrVal.Elem(), false) return nil } -func (dec *Decoder) readRune() rune { - c, size, err := dec.r.ReadRune() - if err != nil { - if err == io.EOF { - dec.panicSyntax(io.ErrUnexpectedEOF) - } - dec.panicIO(err) - } - dec.curPos = dec.nxtPos - dec.nxtPos = dec.curPos + int64(size) - return c +// io helpers ////////////////////////////////////////////////////////////////////////////////////// + +type decodeError struct { + Err error } -func (dec *Decoder) readRuneOrEOF() (c rune, ok bool) { - c, size, err := dec.r.ReadRune() - if err != nil { - if err == io.EOF { - return 0, false - } - dec.panicIO(err) +func (dec *Decoder) panicType(typ reflect.Type, err error) { + panic(decodeError{fmt.Errorf("json: type mismatch error at input byte %v: %s: type %v: %w", + dec.InputOffset(), dec.stackStr(), typ, err)}) +} + +func (dec *Decoder) readRune() (rune, RuneType) { + c, _, t, e := dec.io.ReadRuneType() + if e != nil { + panic(decodeError{e}) } - dec.curPos = dec.nxtPos - dec.nxtPos = dec.curPos + int64(size) - return c, true + return c, t } func (dec *Decoder) unreadRune() { - if err := dec.r.UnreadRune(); err != nil { + if err := dec.io.UnreadRune(); err != nil { // .UnreadRune() must succeed if the previous call was // .ReadRune(), which it always is for this code. - panic(err) + panic("should not happen") } - dec.nxtPos = dec.curPos } -func (dec *Decoder) peekRune() rune { - c, _, err := dec.r.ReadRune() - if err != nil { - if err == io.EOF { - dec.panicSyntax(io.ErrUnexpectedEOF) - } - dec.panicIO(err) +func (dec *Decoder) peekRuneType() RuneType { + _, t := dec.readRune() + dec.unreadRune() + return t +} + +func (dec *Decoder) expectRune(ec rune, et RuneType) { + ac, at := dec.readRune() + if ac != ec || at != et { + panic("should not happen") } - if err := dec.r.UnreadRune(); err != nil { - // .UnreadRune() must succeed if the previous call was - // .ReadRune(), which it always is for this code. - panic(err) +} + +func (dec *Decoder) expectRuneType(ec rune, et RuneType) { + ac, at := dec.readRune() + if ac != ec || at != et { + dec.panicType(nil, fmt.Errorf("TODO error message")) } - return c } -func (dec *Decoder) peekRuneOrEOF() (rune, bool) { - c, _, err := dec.r.ReadRune() - if err != nil { - if err == io.EOF { - return 0, false - } - dec.panicIO(err) +type decRuneTypeScanner struct { + dec *Decoder +} + +func (sc *decRuneTypeScanner) ReadRuneType() (rune, int, RuneType, error) { + c, s, t, e := sc.dec.io.ReadRuneType() + if e != nil { + panic(decodeError{e}) } - if err := dec.r.UnreadRune(); err != nil { - // .UnreadRune() must succeed if the previous call was - // .ReadRune(), which it always is for this code. - panic(err) + return c, s, t, nil +} +func (sc *decRuneTypeScanner) ReadRune() (rune, int, error) { + r, s, t, _ := sc.ReadRuneType() + switch t { + case RuneTypeEOF: + return 0, 0, io.EOF + default: + return r, s, nil } - return c, true } -func (dec *Decoder) expectRune(exp rune) { - act := dec.readRune() - if act != exp { - dec.panicSyntax(fmt.Errorf("expected %q but got %q", exp, act)) +func (sc *decRuneTypeScanner) UnreadRune() error { return sc.dec.io.UnreadRune() } +func (sc *decRuneTypeScanner) InputOffset() int64 { return sc.dec.InputOffset() } +func (sc *decRuneTypeScanner) Reset() { sc.dec.io.Reset() } + +func (dec *Decoder) limitingScanner() runeTypeScanner { + return &elemRuneTypeScanner{ + inner: &decRuneTypeScanner{ + dec: dec, + }, } } +// decoder main //////////////////////////////////////////////////////////////////////////////////// + var ( rawMessagePtrType = reflect.TypeOf((*json.RawMessage)(nil)) decodableType = reflect.TypeOf((*Decodable)(nil)).Elem() jsonUnmarshalerType = reflect.TypeOf((*json.Unmarshaler)(nil)).Elem() textUnmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem() + boolType = reflect.TypeOf(true) ) var kind2bits = map[reflect.Kind]int{ @@ -234,22 +232,22 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) { var buf bytes.Buffer dec.scan(&buf) if err := val.Addr().Interface().(*json.RawMessage).UnmarshalJSON(buf.Bytes()); err != nil { - dec.panicSyntax(err) + dec.panicType(typ, err) } case val.CanAddr() && reflect.PointerTo(typ).Implements(decodableType): obj := val.Addr().Interface().(Decodable) - if err := obj.DecodeJSON(dec.r); err != nil { - dec.panicSyntax(err) + if err := obj.DecodeJSON(dec.limitingScanner()); err != nil { + dec.panicType(typ, err) } case val.CanAddr() && reflect.PointerTo(typ).Implements(jsonUnmarshalerType): var buf bytes.Buffer dec.scan(&buf) obj := val.Addr().Interface().(json.Unmarshaler) if err := obj.UnmarshalJSON(buf.Bytes()); err != nil { - dec.panicSyntax(err) + dec.panicType(typ, err) } case val.CanAddr() && reflect.PointerTo(typ).Implements(textUnmarshalerType): - if nullOK && dec.peekRune() == 'n' { + if nullOK && dec.peekRuneType() == RuneTypeNullN { dec.decodeNull() return } @@ -257,19 +255,19 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) { dec.decodeString(&buf) obj := val.Addr().Interface().(encoding.TextUnmarshaler) if err := obj.UnmarshalText(buf.Bytes()); err != nil { - dec.panicSyntax(err) + dec.panicType(typ, err) } default: kind := typ.Kind() switch kind { case reflect.Bool: - if nullOK && dec.peekRune() == 'n' { + if nullOK && dec.peekRuneType() == RuneTypeNullN { dec.decodeNull() return } val.SetBool(dec.decodeBool()) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - if nullOK && dec.peekRune() == 'n' { + if nullOK && dec.peekRuneType() == RuneTypeNullN { dec.decodeNull() return } @@ -277,11 +275,11 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) { dec.scanNumber(&buf) n, err := strconv.ParseInt(buf.String(), 10, kind2bits[kind]) if err != nil { - dec.panicSyntax(err) + dec.panicType(typ, err) } val.SetInt(n) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - if nullOK && dec.peekRune() == 'n' { + if nullOK && dec.peekRuneType() == RuneTypeNullN { dec.decodeNull() return } @@ -289,11 +287,11 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) { dec.scanNumber(&buf) n, err := strconv.ParseUint(buf.String(), 10, kind2bits[kind]) if err != nil { - dec.panicSyntax(err) + dec.panicType(typ, err) } val.SetUint(n) case reflect.Float32, reflect.Float64: - if nullOK && dec.peekRune() == 'n' { + if nullOK && dec.peekRuneType() == RuneTypeNullN { dec.decodeNull() return } @@ -301,11 +299,11 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) { dec.scanNumber(&buf) n, err := strconv.ParseFloat(buf.String(), kind2bits[kind]) if err != nil { - dec.panicSyntax(err) + dec.panicType(typ, err) } val.SetFloat(n) case reflect.String: - if nullOK && dec.peekRune() == 'n' { + if nullOK && dec.peekRuneType() == RuneTypeNullN { dec.decodeNull() return } @@ -321,8 +319,8 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) { if typ.NumMethod() > 0 { dec.panicType(typ, fmt.Errorf("cannot decode in to non-empty interface")) } - switch dec.peekRune() { - case 'n': + switch dec.peekRuneType() { + case RuneTypeNullN: if !val.IsNil() && val.Elem().Kind() == reflect.Pointer && val.Elem().Elem().Kind() == reflect.Pointer { // XXX: I can't justify this case, other than "it's what encoding/json does, but // I don't understand their rationale". @@ -339,7 +337,7 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) { } } case reflect.Struct: - if nullOK && dec.peekRune() == 'n' { + if nullOK && dec.peekRuneType() == RuneTypeNullN { dec.decodeNull() return } @@ -372,36 +370,36 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) { fVal = fVal.Field(idx) } if field.Quote { - switch dec.peekRune() { - case 'n': + switch dec.peekRuneType() { + case RuneTypeNullN: dec.decodeNull() switch fVal.Kind() { // XXX: I can't justify this list, other than "it's what encoding/json // does, but I don't understand their rationale". case reflect.Interface, reflect.Pointer, reflect.Map, reflect.Slice: fVal.Set(reflect.Zero(fVal.Type())) + default: + // do nothing??? } - case '"': - // TODO: Figure out how to do this without buffering. + case RuneTypeStringBeg: + // TODO: Figure out how to do this without buffering, have correct offsets. var buf bytes.Buffer - subD := *dec // capture the .curPos *before* calling .decodeString dec.decodeString(&buf) - subD.r = &buf + subD := NewDecoder(&buf) subD.decode(fVal, false) default: - dec.panicSyntax(fmt.Errorf(",string field: expected %q or %q but got %q", - 'n', '"', dec.peekRune())) + dec.panicType(typ, fmt.Errorf(",string field TODO ERROR MESSAGE")) } } else { dec.decode(fVal, true) } }) case reflect.Map: - switch dec.peekRune() { - case 'n': + switch dec.peekRuneType() { + case RuneTypeNullN: dec.decodeNull() val.Set(reflect.Zero(typ)) - case '{': + case RuneTypeObjectBeg: if val.IsNil() { val.Set(reflect.MakeMap(typ)) } @@ -413,7 +411,7 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) { case reflect.PointerTo(nameValTyp).Implements(textUnmarshalerType): obj := nameValPtr.Interface().(encoding.TextUnmarshaler) if err := obj.UnmarshalText(nameBuf.Bytes()); err != nil { - dec.panicSyntax(err) + dec.panicType(nameValTyp, err) } default: switch nameValTyp.Kind() { @@ -422,13 +420,13 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: n, err := strconv.ParseInt(nameBuf.String(), 10, kind2bits[nameValTyp.Kind()]) if err != nil { - dec.panicSyntax(err) + dec.panicType(nameValTyp, err) } nameValPtr.Elem().SetInt(n) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: n, err := strconv.ParseUint(nameBuf.String(), 10, kind2bits[nameValTyp.Kind()]) if err != nil { - dec.panicSyntax(err) + dec.panicType(nameValTyp, err) } nameValPtr.Elem().SetUint(n) default: @@ -444,16 +442,16 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) { val.SetMapIndex(nameValPtr.Elem(), fValPtr.Elem()) }) default: - dec.panicSyntax(fmt.Errorf("map: expected %q or %q bug got %q", 'n', '{', dec.peekRune())) + dec.panicType(typ, fmt.Errorf("map: TODO")) } case reflect.Slice: switch { case typ.Elem().Kind() == reflect.Uint8: - switch dec.peekRune() { - case 'n': + switch dec.peekRuneType() { + case RuneTypeNullN: dec.decodeNull() val.Set(reflect.Zero(typ)) - case '"': + case RuneTypeStringBeg: var buf bytes.Buffer dec.decodeString(newBase64Decoder(&buf)) if typ.Elem() == byteType { @@ -467,14 +465,14 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) { } } default: - dec.panicSyntax(fmt.Errorf("byte slice: expected %q or %q but got %q", 'n', '"', dec.peekRune())) + dec.panicType(typ, fmt.Errorf("byte slice: TODO")) } default: - switch dec.peekRune() { - case 'n': + switch dec.peekRuneType() { + case RuneTypeNullN: dec.decodeNull() val.Set(reflect.Zero(typ)) - case '[': + case RuneTypeArrayBeg: if val.IsNil() { val.Set(reflect.MakeSlice(typ, 0, 0)) } @@ -491,11 +489,11 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) { i++ }) default: - dec.panicSyntax(fmt.Errorf("slice: expected %q or %q but got %q", 'n', '[', dec.peekRune())) + dec.panicType(typ, fmt.Errorf("slice: TODO")) } } case reflect.Array: - if nullOK && dec.peekRune() == 'n' { + if nullOK && dec.peekRuneType() == RuneTypeNullN { dec.decodeNull() return } @@ -517,8 +515,8 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) { val.Index(i).Set(reflect.Zero(typ.Elem())) } case reflect.Pointer: - switch dec.peekRune() { - case 'n': + switch dec.peekRuneType() { + case RuneTypeNullN: dec.decodeNull() /* for typ.Elem().Kind() == reflect.Pointer { @@ -542,67 +540,27 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) { } } -func (dec *Decoder) decodeWS() { - for { - c, ok := dec.readRuneOrEOF() - if !ok { - return - } - switch c { - // NB: The JSON definition of whitespace is more - // narrow than unicode.IsSpace - case 0x0020, 0x000A, 0x000D, 0x0009: - // do nothing - default: - dec.unreadRune() - return - } - } -} - func (dec *Decoder) scan(out io.Writer) { - var scanner Parser + limiter := dec.limitingScanner() for { - c, ok := dec.readRuneOrEOF() - - var t RuneType - var err error - if ok { - t, err = scanner.HandleRune(c) - } else { - t, err = scanner.HandleEOF() - } - - switch t { - case RuneTypeError: - dec.panicSyntax(err) - case RuneTypeEOF: - if ok { - dec.unreadRune() - } + c, _, err := limiter.ReadRune() + if err == io.EOF { return - case RuneTypeSpace: - // ignore - default: - if _, err := writeRune(out, c); err != nil { - dec.panicIO(err) - } } + _, _ = writeRune(out, c) } } func (dec *Decoder) scanNumber(out io.Writer) { - c := dec.peekRune() - switch c { - case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': - dec.scan(out) - default: - dec.panicSyntax(fmt.Errorf("number: expected %q or a digit, but got %q", '-', c)) + if !dec.peekRuneType().IsNumber() { + dec.panicType(numberType, fmt.Errorf("number: not a number")) } + dec.scan(out) } func (dec *Decoder) decodeAny() any { - c := dec.peekRune() + c, _ := dec.readRune() + dec.unreadRune() switch c { case '{': ret := make(map[string]any) @@ -628,14 +586,14 @@ func (dec *Decoder) decodeAny() any { return buf.String() case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': var buf strings.Builder - dec.scanNumber(&buf) + dec.scan(&buf) num := json.Number(buf.String()) if dec.useNumber { return num } f64, err := num.Float64() if err != nil { - dec.panicSyntax(err) + panic("should not happen") } return f64 case 't', 'f': @@ -644,168 +602,136 @@ func (dec *Decoder) decodeAny() any { dec.decodeNull() return nil default: - dec.panicSyntax(fmt.Errorf("any: unexpected character: %c", c)) - panic("not reached") + panic("should not happen") } } func (dec *Decoder) decodeObject(nameBuf runeBuffer, decodeKVal func()) { - dec.expectRune('{') - dec.decodeWS() - c := dec.readRune() - switch c { - case '"': + dec.expectRuneType('{', RuneTypeObjectBeg) + _, t := dec.readRune() + switch t { + case RuneTypeObjectEnd: + return + case RuneTypeStringBeg: decodeMember: dec.unreadRune() nameBuf.Reset() dec.decodeString(nameBuf) - dec.decodeWS() - dec.expectRune(':') - dec.decodeWS() + dec.expectRune(':', RuneTypeObjectColon) decodeKVal() - dec.decodeWS() - c := dec.readRune() - switch c { - case ',': - dec.decodeWS() - dec.expectRune('"') + _, t := dec.readRune() + switch t { + case RuneTypeObjectComma: + dec.expectRune('"', RuneTypeStringBeg) goto decodeMember - case '}': + case RuneTypeObjectEnd: return default: - dec.panicSyntax(fmt.Errorf("object: expected %q or %q but got %q", ',', '}', c)) + panic("should not happen") } - case '}': - return default: - dec.panicSyntax(fmt.Errorf("object: expected %q or %q but got %q", '"', '}', c)) + panic("should not happen") } } func (dec *Decoder) decodeArray(decodeMember func()) { - dec.expectRune('[') - dec.decodeWS() - c := dec.readRune() - switch c { - case ']': + dec.expectRuneType('[', RuneTypeArrayBeg) + _, t := dec.readRune() + switch t { + case RuneTypeArrayEnd: return default: dec.unreadRune() decodeNextMember: decodeMember() - dec.decodeWS() - c := dec.readRune() - switch c { - case ',': - dec.decodeWS() + _, t := dec.readRune() + switch t { + case RuneTypeArrayComma: goto decodeNextMember - case ']': + case RuneTypeArrayEnd: return default: - dec.panicSyntax(fmt.Errorf("array: expected %c or %c but got %c", ',', ']', c)) + panic("should not happen") } } } -func (dec *Decoder) decodeHex() rune { - c := dec.readRune() - switch { - case '0' <= c && c <= '9': - return c - '0' - case 'a' <= c && c <= 'f': - return c - 'a' + 10 - case 'A' <= c && c <= 'F': - return c - 'A' + 10 - default: - dec.panicSyntax(fmt.Errorf("string: expected a hex digit but got %q", c)) - panic("not reached") - } -} - func (dec *Decoder) decodeString(out io.Writer) { - dec.expectRune('"') + dec.expectRuneType('"', RuneTypeStringBeg) + var uhex [4]byte for { - c := dec.readRune() - switch { - case 0x0020 <= c && c <= 0x10FFFF && c != '"' && c != '\\': - if _, err := writeRune(out, c); err != nil { - dec.panicSyntax(err) - } - case c == '\\': - c = dec.readRune() + c, t := dec.readRune() + switch t { + case RuneTypeStringChar: + _, _ = writeRune(out, c) + case RuneTypeStringEsc, RuneTypeStringEscU: + // do nothing + case RuneTypeStringEsc1: switch c { case '"': - if _, err := writeRune(out, '"'); err != nil { - dec.panicSyntax(err) - } + _, _ = writeRune(out, '"') case '\\': - if _, err := writeRune(out, '\\'); err != nil { - dec.panicSyntax(err) - } + _, _ = writeRune(out, '\\') case '/': - if _, err := writeRune(out, '/'); err != nil { - dec.panicSyntax(err) - } + _, _ = writeRune(out, '/') case 'b': - if _, err := writeRune(out, '\b'); err != nil { - dec.panicSyntax(err) - } + _, _ = writeRune(out, '\b') case 'f': - if _, err := writeRune(out, '\f'); err != nil { - dec.panicSyntax(err) - } + _, _ = writeRune(out, '\f') case 'n': - if _, err := writeRune(out, '\n'); err != nil { - dec.panicSyntax(err) - } + _, _ = writeRune(out, '\n') case 'r': - if _, err := writeRune(out, '\r'); err != nil { - dec.panicSyntax(err) - } + _, _ = writeRune(out, '\r') case 't': - if _, err := writeRune(out, '\t'); err != nil { - dec.panicSyntax(err) - } - case 'u': - c = dec.decodeHex() - c = (c << 4) | dec.decodeHex() - c = (c << 4) | dec.decodeHex() - c = (c << 4) | dec.decodeHex() - if _, err := writeRune(out, c); err != nil { - dec.panicSyntax(err) - } + _, _ = writeRune(out, '\t') + default: + panic("should not happen") } - case c == '"': + case RuneTypeStringEscUA: + uhex[0], _ = hex2int(c) + case RuneTypeStringEscUB: + uhex[1], _ = hex2int(c) + case RuneTypeStringEscUC: + uhex[2], _ = hex2int(c) + case RuneTypeStringEscUD: + uhex[3], _ = hex2int(c) + c = 0 | + rune(uhex[0])<<12 | + rune(uhex[1])<<8 | + rune(uhex[2])<<4 | + rune(uhex[3])<<0 + _, _ = writeRune(out, c) + case RuneTypeStringEnd: return default: - dec.panicSyntax(fmt.Errorf("string: unexpected %c", c)) + panic("should not happen") } } } func (dec *Decoder) decodeBool() bool { - c := dec.readRune() + c, _ := dec.readRune() switch c { case 't': - dec.expectRune('r') - dec.expectRune('u') - dec.expectRune('e') + dec.expectRune('r', RuneTypeTrueR) + dec.expectRune('u', RuneTypeTrueU) + dec.expectRune('e', RuneTypeTrueE) return true case 'f': - dec.expectRune('a') - dec.expectRune('l') - dec.expectRune('s') - dec.expectRune('e') + dec.expectRune('a', RuneTypeFalseA) + dec.expectRune('l', RuneTypeFalseL) + dec.expectRune('s', RuneTypeFalseS) + dec.expectRune('e', RuneTypeFalseE) return false default: - dec.panicSyntax(fmt.Errorf("bool: expected %q or %q but got %q", 't', 'f', c)) + dec.panicType(boolType, fmt.Errorf("bool: expected %q or %q but got %q", 't', 'f', c)) panic("not reached") } } func (dec *Decoder) decodeNull() { - dec.expectRune('n') - dec.expectRune('u') - dec.expectRune('l') - dec.expectRune('l') + dec.expectRuneType('n', RuneTypeNullN) + dec.expectRune('u', RuneTypeNullU) + dec.expectRune('l', RuneTypeNullL1) + dec.expectRune('l', RuneTypeNullL2) } @@ -184,6 +184,21 @@ func (t RuneType) String() string { return fmt.Sprintf("<%d>", t) } +func (t RuneType) jsonType() string { + return map[RuneType]string{ + RuneTypeObjectBeg: "object", + RuneTypeArrayBeg: "array", + RuneTypeStringBeg: "string", + RuneTypeNumberIntNeg: "number", + RuneTypeNumberIntZero: "number", + RuneTypeNumberIntDig: "number", + RuneTypeTrueT: "true", + RuneTypeFalseF: "false", + RuneTypeNullN: "null", + RuneTypeEOF: "eof", + }[t] +} + func (t RuneType) IsNumber() bool { return RuneTypeNumberIntNeg <= t && t <= RuneTypeNumberExpDig } |