diff --git a/decode.go b/decode.go index 5e6ae10..280cdca 100644 --- a/decode.go +++ b/decode.go @@ -1,10 +1,7 @@ package json import ( - "bytes" - "errors" "io" - "math" "reflect" "strings" "sync" @@ -22,72 +19,23 @@ const ( stateArray ) +type decoder interface { + decode(*context, uintptr) error +} + type Decoder struct { r io.Reader state int value []byte } -type context struct { - idx int - keys [][]byte - values [][]byte - start int - stack int -} - -func newContext() *context { - return &context{ - keys: make([][]byte, 64), - values: make([][]byte, 64), - } -} - -func (c *context) pushStack() { - if len(c.keys) <= c.stack { - c.keys = append(c.keys, nil) - c.values = append(c.values, nil) - } - c.stack++ -} - -func (c *context) popStack() { - c.stack-- -} - -func (c *context) setKey(key []byte) { - c.keys[c.stack] = key -} - -func (c *context) setValue(value []byte) { - c.values[c.stack] = value -} - -func (c *context) key() ([]byte, error) { - if len(c.keys) <= c.stack { - return nil, errors.New("unexpected error key") - } - key := c.keys[c.stack] - if len(key) == 0 { - return nil, errors.New("unexpected error key") - } - return key, nil -} - -func (c *context) value() ([]byte, error) { - if len(c.values) <= c.stack { - return nil, errors.New("unexpected error value") - } - return c.values[c.stack], nil -} - var ( - ctxPool sync.Pool - cachedDecodeOp map[string]DecodeOp + ctxPool sync.Pool + cachedDecoder map[string]decoder ) func init() { - cachedDecodeOp = map[string]DecodeOp{} + cachedDecoder = map[string]decoder{} ctxPool = sync.Pool{ New: func() interface{} { return newContext() @@ -112,20 +60,21 @@ func (d *Decoder) decodeForUnmarshal(src []byte, v interface{}) error { return ErrDecodePointer } name := typ.String() - op, exists := cachedDecodeOp[name] + dec, exists := cachedDecoder[name] if !exists { - decodeOp, err := d.compile(rv.Elem()) + compiledDec, err := d.compile(typ.Elem()) if err != nil { return err } if name != "" { - cachedDecodeOp[name] = decodeOp + cachedDecoder[name] = compiledDec } - op = decodeOp + dec = compiledDec } ptr := rv.Pointer() ctx := ctxPool.Get().(*context) - if err := d.decode(ctx, src, ptr, op); err != nil { + ctx.setBuf(src) + if err := dec.decode(ctx, ptr); err != nil { ctxPool.Put(ctx) return err } @@ -140,16 +89,16 @@ func (d *Decoder) Decode(v interface{}) error { return ErrDecodePointer } name := typ.String() - op, exists := cachedDecodeOp[name] + dec, exists := cachedDecoder[name] if !exists { - decodeOp, err := d.compile(rv.Elem()) + compiledDec, err := d.compile(typ.Elem()) if err != nil { return err } if name != "" { - cachedDecodeOp[name] = decodeOp + cachedDecoder[name] = compiledDec } - op = decodeOp + dec = compiledDec } ptr := rv.Pointer() ctx := ctxPool.Get().(*context) @@ -163,19 +112,20 @@ func (d *Decoder) Decode(v interface{}) error { if err != nil { return err } - if err := d.decode(ctx, buf[:n], ptr, op); err != nil { + ctx.setBuf(buf[:n]) + if err := dec.decode(ctx, ptr); err != nil { return err } } return nil } -type DecodeOp func(uintptr, []byte, []byte) error - -func (d *Decoder) compile(v reflect.Value) (DecodeOp, error) { - switch v.Type().Kind() { +func (d *Decoder) compile(typ reflect.Type) (decoder, error) { + switch typ.Kind() { + case reflect.Ptr: + return d.compilePtr(typ) case reflect.Struct: - return d.compileStruct(v) + return d.compileStruct(typ) case reflect.Int: return d.compileInt() case reflect.Int8: @@ -204,178 +154,80 @@ func (d *Decoder) compile(v reflect.Value) (DecodeOp, error) { return nil, nil } -func parseInt(b []byte) (int64, error) { - isNegative := false - if b[0] == '-' { - b = b[1:] - isNegative = true +func (d *Decoder) compilePtr(typ reflect.Type) (decoder, error) { + dec, err := d.compile(typ.Elem()) + if err != nil { + return nil, err } - maxDigit := len(b) - sum := int64(0) - for i := 0; i < maxDigit; i++ { - c := int64(b[i]) - 48 - if 0 <= c && c <= 9 { - digitValue := int64(math.Pow10(maxDigit - i - 1)) - sum += c * digitValue - } else { - return 0, errors.New("failed to parse int") - } - } - if isNegative { - return -1 * sum, nil - } - return sum, nil + return newPtrDecoder(dec, typ.Elem()), nil } -func parseUint(b []byte) (uint64, error) { - maxDigit := len(b) - sum := uint64(0) - for i := 0; i < maxDigit; i++ { - c := uint64(b[i]) - 48 - if 0 <= c && c <= 9 { - digitValue := uint64(math.Pow10(maxDigit - i - 1)) - sum += c * digitValue - } else { - return 0, errors.New("failed to parse uint") - } - } - return sum, nil +func (d *Decoder) compileInt() (decoder, error) { + return newIntDecoder(func(p uintptr, v int64) { + *(*int)(unsafe.Pointer(p)) = int(v) + }), nil } -func (d *Decoder) compileInt() (DecodeOp, error) { - return func(p uintptr, src []byte, _ []byte) error { - i64, err := parseInt(src) - if err != nil { - return err - } - *(*int)(unsafe.Pointer(p)) = int(i64) - return nil - }, nil +func (d *Decoder) compileInt8() (decoder, error) { + return newIntDecoder(func(p uintptr, v int64) { + *(*int8)(unsafe.Pointer(p)) = int8(v) + }), nil } -func (d *Decoder) compileInt8() (DecodeOp, error) { - return func(p uintptr, src []byte, _ []byte) error { - i64, err := parseInt(src) - if err != nil { - return err - } - *(*int8)(unsafe.Pointer(p)) = int8(i64) - return nil - }, nil +func (d *Decoder) compileInt16() (decoder, error) { + return newIntDecoder(func(p uintptr, v int64) { + *(*int16)(unsafe.Pointer(p)) = int16(v) + }), nil } -func (d *Decoder) compileInt16() (DecodeOp, error) { - return func(p uintptr, src []byte, _ []byte) error { - i64, err := parseInt(src) - if err != nil { - return err - } - *(*int16)(unsafe.Pointer(p)) = int16(i64) - return nil - }, nil +func (d *Decoder) compileInt32() (decoder, error) { + return newIntDecoder(func(p uintptr, v int64) { + *(*int32)(unsafe.Pointer(p)) = int32(v) + }), nil } -func (d *Decoder) compileInt32() (DecodeOp, error) { - return func(p uintptr, src []byte, _ []byte) error { - i64, err := parseInt(src) - if err != nil { - return err - } - *(*int32)(unsafe.Pointer(p)) = int32(i64) - return nil - }, nil +func (d *Decoder) compileInt64() (decoder, error) { + return newIntDecoder(func(p uintptr, v int64) { + *(*int64)(unsafe.Pointer(p)) = v + }), nil } -func (d *Decoder) compileInt64() (DecodeOp, error) { - return func(p uintptr, src []byte, _ []byte) error { - i64, err := parseInt(src) - if err != nil { - return err - } - *(*int64)(unsafe.Pointer(p)) = i64 - return nil - }, nil +func (d *Decoder) compileUint() (decoder, error) { + return newUintDecoder(func(p uintptr, v uint64) { + *(*uint)(unsafe.Pointer(p)) = uint(v) + }), nil } -func (d *Decoder) compileUint() (DecodeOp, error) { - return func(p uintptr, src []byte, _ []byte) error { - u64, err := parseUint(src) - if err != nil { - return err - } - *(*uint)(unsafe.Pointer(p)) = uint(u64) - return nil - }, nil +func (d *Decoder) compileUint8() (decoder, error) { + return newUintDecoder(func(p uintptr, v uint64) { + *(*uint8)(unsafe.Pointer(p)) = uint8(v) + }), nil } -func (d *Decoder) compileUint8() (DecodeOp, error) { - return func(p uintptr, src []byte, _ []byte) error { - u64, err := parseUint(src) - if err != nil { - return err - } - *(*uint8)(unsafe.Pointer(p)) = uint8(u64) - return nil - }, nil +func (d *Decoder) compileUint16() (decoder, error) { + return newUintDecoder(func(p uintptr, v uint64) { + *(*uint16)(unsafe.Pointer(p)) = uint16(v) + }), nil } -func (d *Decoder) compileUint16() (DecodeOp, error) { - return func(p uintptr, src []byte, _ []byte) error { - u64, err := parseUint(src) - if err != nil { - return err - } - *(*uint16)(unsafe.Pointer(p)) = uint16(u64) - return nil - }, nil +func (d *Decoder) compileUint32() (decoder, error) { + return newUintDecoder(func(p uintptr, v uint64) { + *(*uint32)(unsafe.Pointer(p)) = uint32(v) + }), nil } -func (d *Decoder) compileUint32() (DecodeOp, error) { - return func(p uintptr, src []byte, _ []byte) error { - u64, err := parseUint(src) - if err != nil { - return err - } - *(*uint32)(unsafe.Pointer(p)) = uint32(u64) - return nil - }, nil +func (d *Decoder) compileUint64() (decoder, error) { + return newUintDecoder(func(p uintptr, v uint64) { + *(*uint64)(unsafe.Pointer(p)) = v + }), nil } -func (d *Decoder) compileUint64() (DecodeOp, error) { - return func(p uintptr, src []byte, _ []byte) error { - u64, err := parseUint(src) - if err != nil { - return err - } - *(*uint64)(unsafe.Pointer(p)) = u64 - return nil - }, nil +func (d *Decoder) compileString() (decoder, error) { + return newStringDecoder(), nil } -func (d *Decoder) compileString() (DecodeOp, error) { - return func(p uintptr, src []byte, _ []byte) error { - *(*string)(unsafe.Pointer(p)) = *(*string)(unsafe.Pointer(&src)) - return nil - }, nil -} - -var ( - trueBytes = []byte("true") - falseBytes = []byte("false") -) - -func (d *Decoder) compileBool() (DecodeOp, error) { - return func(p uintptr, src []byte, _ []byte) error { - if bytes.Equal(src, trueBytes) { - *(*bool)(unsafe.Pointer(p)) = true - return nil - } - if bytes.Equal(src, falseBytes) { - *(*bool)(unsafe.Pointer(p)) = false - return nil - } - return errors.New("unexpected error bool") - }, nil +func (d *Decoder) compileBool() (decoder, error) { + return newBoolDecoder(), nil } func (d *Decoder) getTag(field reflect.StructField) string { @@ -394,14 +246,9 @@ func (d *Decoder) isIgnoredStructField(field reflect.StructField) bool { return false } -func (d *Decoder) compileStruct(v reflect.Value) (DecodeOp, error) { - type opset struct { - key []byte - op func(uintptr, []byte) error - } - typ := v.Type() +func (d *Decoder) compileStruct(typ reflect.Type) (decoder, error) { fieldNum := typ.NumField() - opMap := map[string]func(uintptr, []byte) error{} + fieldMap := map[string]*structFieldSet{} for i := 0; i < fieldNum; i++ { field := typ.Field(i) if d.isIgnoredStructField(field) { @@ -415,118 +262,16 @@ func (d *Decoder) compileStruct(v reflect.Value) (DecodeOp, error) { keyName = opts[0] } } - op, err := d.compile(v.Field(i)) + dec, err := d.compile(field.Type) if err != nil { return nil, err } - if op == nil { - continue - } - fieldOp := func(base uintptr, value []byte) error { - return op(base+field.Offset, value, nil) - } - opMap[field.Name] = fieldOp - opMap[keyName] = fieldOp - opMap[strings.ToLower(keyName)] = fieldOp + fieldSet := &structFieldSet{dec: dec, offset: field.Offset} + fieldMap[field.Name] = fieldSet + fieldMap[keyName] = fieldSet + fieldMap[strings.ToLower(keyName)] = fieldSet } - return func(p uintptr, key []byte, value []byte) error { - k := *(*string)(unsafe.Pointer(&key)) - op, exists := opMap[k] - if !exists { - return nil - } - return op(p, value) - }, nil -} - -func (d *Decoder) decode(ctx *context, src []byte, ptr uintptr, op DecodeOp) error { - slen := len(src) - for i := 0; i < slen; i++ { - c := src[i] - switch c { - case '{': - ctx.pushStack() - case '}': - key, err := ctx.key() - if err != nil { - return err - } - if err := op(ptr, key, d.value); err != nil { - return err - } - ctx.popStack() - case '[': - case ']': - case ':': - if len(d.value) == 0 { - return errors.New("unexpected error map value") - } - ctx.setKey(d.value) - case ',': - key, err := ctx.key() - if err != nil { - return err - } - if err := op(ptr, key, d.value); err != nil { - return err - } - case '"': - start := i + 1 - for i = start; i < slen && src[i] != '"'; i++ { - if src[i] == '\\' { - i++ - } - } - end := i - if end <= start { - return errors.New("unexpected error value") - } - d.value = src[start:end] - case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': - start := i - for ; i < slen; i++ { - c := src[i] - switch c { - case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.', 'e', 'E': - default: - goto end - } - } - end: - end := i - if end <= start { - return errors.New("unexpected error number") - } - d.value = src[start:end] - i-- - case 't': - if i+3 < slen && src[i+1] == 'r' && src[i+2] == 'u' && src[i+3] == 'e' { - d.value = []byte("true") - } else { - return errors.New("unexpected error true") - } - i += 3 - case 'f': - if i+4 < slen && src[i+1] == 'a' && src[i+2] == 'l' && src[i+3] == 's' && src[i+4] == 'e' { - d.value = []byte("false") - } else { - return errors.New("unexpected error false") - } - i += 4 - case 'n': - if i+3 < slen && src[i+1] == 'u' && src[i+2] == 'l' && src[i+3] == 'l' { - d.value = []byte("null") - } else { - return errors.New("unexpected error null") - } - i += 3 - } - } - return nil -} - -func (d *Decoder) parse(tokens []Token) { - + return newStructDecoder(fieldMap), nil } func (d *Decoder) DisallowUnknownFields() { diff --git a/decode_bool.go b/decode_bool.go new file mode 100644 index 0000000..a5f0a5f --- /dev/null +++ b/decode_bool.go @@ -0,0 +1,54 @@ +package json + +import ( + "errors" + "unsafe" +) + +type boolDecoder struct{} + +func newBoolDecoder() *boolDecoder { + return &boolDecoder{} +} + +func (d *boolDecoder) decode(ctx *context, p uintptr) error { + ctx.skipWhiteSpace() + buf := ctx.buf + cursor := ctx.cursor + switch buf[cursor] { + case 't': + if cursor+3 >= ctx.buflen { + return errors.New("unexpected error. invalid bool character") + } + if buf[cursor+1] != 'r' { + return errors.New("unexpected error. invalid bool character") + } + if buf[cursor+2] != 'u' { + return errors.New("unexpected error. invalid bool character") + } + if buf[cursor+3] != 'e' { + return errors.New("unexpected error. invalid bool character") + } + ctx.cursor += 4 + *(*bool)(unsafe.Pointer(p)) = true + case 'f': + if cursor+4 >= ctx.buflen { + return errors.New("unexpected error. invalid bool character") + } + if buf[cursor+1] != 'a' { + return errors.New("unexpected error. invalid bool character") + } + if buf[cursor+2] != 'l' { + return errors.New("unexpected error. invalid bool character") + } + if buf[cursor+3] != 's' { + return errors.New("unexpected error. invalid bool character") + } + if buf[cursor+4] != 'e' { + return errors.New("unexpected error. invalid bool character") + } + ctx.cursor += 5 + *(*bool)(unsafe.Pointer(p)) = false + } + return nil +} diff --git a/decode_context.go b/decode_context.go new file mode 100644 index 0000000..eba3d28 --- /dev/null +++ b/decode_context.go @@ -0,0 +1,31 @@ +package json + +type context struct { + cursor int + buf []byte + buflen int +} + +func (c *context) setBuf(buf []byte) { + c.buf = buf + c.buflen = len(buf) + c.cursor = 0 +} + +func (c *context) skipWhiteSpace() int { + buflen := c.buflen + buf := c.buf + for cursor := c.cursor; cursor < buflen; cursor++ { + switch buf[cursor] { + case ' ', '\n', '\t', '\r': + continue + } + c.cursor = cursor + return cursor + } + return buflen +} + +func newContext() *context { + return &context{} +} diff --git a/decode_int.go b/decode_int.go new file mode 100644 index 0000000..50df969 --- /dev/null +++ b/decode_int.go @@ -0,0 +1,66 @@ +package json + +import ( + "errors" + "math" +) + +type intDecoder struct { + op func(uintptr, int64) +} + +func newIntDecoder(op func(uintptr, int64)) *intDecoder { + return &intDecoder{op: op} +} + +func (d *intDecoder) parseInt(b []byte) int64 { + isNegative := false + if b[0] == '-' { + b = b[1:] + isNegative = true + } + maxDigit := len(b) + sum := int64(0) + for i := 0; i < maxDigit; i++ { + c := int64(b[i]) - 48 + digitValue := int64(math.Pow10(maxDigit - i - 1)) + sum += c * digitValue + } + if isNegative { + return -1 * sum + } + return sum +} + +func (d *intDecoder) decodeByte(ctx *context) ([]byte, error) { + ctx.skipWhiteSpace() + buf := ctx.buf + cursor := ctx.cursor + buflen := ctx.buflen + switch buf[cursor] { + case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': + start := ctx.cursor + cursor++ + for ; cursor < buflen; cursor++ { + tk := int(buf[cursor]) + if int('0') <= tk && tk <= int('9') { + continue + } + break + } + num := ctx.buf[start:cursor] + ctx.cursor = cursor + //fmt.Printf("number = [%s]\n", string(num)) + return num, nil + } + return nil, errors.New("unexpected error number") +} + +func (d *intDecoder) decode(ctx *context, p uintptr) error { + bytes, err := d.decodeByte(ctx) + if err != nil { + return err + } + d.op(p, d.parseInt(bytes)) + return nil +} diff --git a/decode_ptr.go b/decode_ptr.go new file mode 100644 index 0000000..a326c1d --- /dev/null +++ b/decode_ptr.go @@ -0,0 +1,24 @@ +package json + +import ( + "reflect" + "unsafe" +) + +type ptrDecoder struct { + dec decoder + typ reflect.Type +} + +func newPtrDecoder(dec decoder, typ reflect.Type) *ptrDecoder { + return &ptrDecoder{dec: dec, typ: typ} +} + +func (d *ptrDecoder) decode(ctx *context, p uintptr) error { + newptr := uintptr(reflect.New(d.typ).Pointer()) + if err := d.dec.decode(ctx, newptr); err != nil { + return err + } + *(*uintptr)(unsafe.Pointer(p)) = newptr + return nil +} diff --git a/decode_string.go b/decode_string.go new file mode 100644 index 0000000..15ffa4e --- /dev/null +++ b/decode_string.go @@ -0,0 +1,51 @@ +package json + +import ( + "errors" + "unsafe" +) + +type stringDecoder struct { +} + +func newStringDecoder() *stringDecoder { + return &stringDecoder{} +} + +func (d *stringDecoder) decode(ctx *context, p uintptr) error { + bytes, err := d.decodeByte(ctx) + if err != nil { + return err + } + *(*string)(unsafe.Pointer(p)) = *(*string)(unsafe.Pointer(&bytes)) + return nil +} + +func (d *stringDecoder) decodeByte(ctx *context) ([]byte, error) { + ctx.skipWhiteSpace() + buf := ctx.buf + cursor := ctx.cursor + buflen := ctx.buflen + if buf[cursor] != '"' { + return nil, errors.New("unexpected error key delimiter") + } + start := cursor + 1 + cursor++ + for ; cursor < buflen; cursor++ { + tk := buf[cursor] + if tk == '\\' { + continue + } + if tk == '"' { + break + } + } + if buf[cursor] != '"' { + return nil, errors.New("unexpected error string") + } + literal := buf[start:cursor] + //fmt.Printf("string = [%s]\n", string(literal)) + cursor++ + ctx.cursor = cursor + return literal, nil +} diff --git a/decode_struct.go b/decode_struct.go new file mode 100644 index 0000000..997e93a --- /dev/null +++ b/decode_struct.go @@ -0,0 +1,102 @@ +package json + +import ( + "errors" + "unsafe" +) + +type structFieldSet struct { + dec decoder + offset uintptr +} + +type structDecoder struct { + fieldMap map[string]*structFieldSet + keyDecoder *stringDecoder +} + +func newStructDecoder(fieldMap map[string]*structFieldSet) *structDecoder { + return &structDecoder{ + fieldMap: fieldMap, + keyDecoder: newStringDecoder(), + } +} + +func (d *structDecoder) skipValue(ctx *context) error { + ctx.skipWhiteSpace() + braceCount := 0 + bracketCount := 0 + cursor := ctx.cursor + buf := ctx.buf + buflen := ctx.buflen + for ; cursor < buflen; cursor++ { + switch buf[cursor] { + case '{': + braceCount++ + case '[': + bracketCount++ + case '}': + braceCount-- + if braceCount == -1 && bracketCount == 0 { + return nil + } + case ']': + bracketCount-- + case ',': + if bracketCount == 0 && braceCount == 0 { + return nil + } + } + } + return errors.New("unexpected error value") +} + +func (d *structDecoder) decode(ctx *context, p uintptr) error { + ctx.skipWhiteSpace() + buf := ctx.buf + buflen := ctx.buflen + cursor := ctx.cursor + if buflen < 2 { + return errors.New("unexpected error {}") + } + if buf[cursor] != '{' { + return errors.New("unexpected error {") + } + cursor++ + for ; cursor < buflen; cursor++ { + ctx.cursor = cursor + key, err := d.keyDecoder.decodeByte(ctx) + if err != nil { + return err + } + cursor = ctx.skipWhiteSpace() + if buf[cursor] != ':' { + return errors.New("unexpected error invalid delimiter for object") + } + cursor++ + if cursor >= buflen { + return errors.New("unexpected error missing value") + } + ctx.cursor = cursor + k := *(*string)(unsafe.Pointer(&key)) + field, exists := d.fieldMap[k] + if exists { + //fmt.Printf("k = %s dec = %#v, p = %x\n", k, field.dec, p) + if err := field.dec.decode(ctx, p+field.offset); err != nil { + return err + } + } else { + if err := d.skipValue(ctx); err != nil { + return err + } + } + cursor = ctx.skipWhiteSpace() + if buf[cursor] == '}' { + return nil + } + if buf[cursor] != ',' { + return errors.New("unexpected error ,") + } + } + return nil +} diff --git a/decode_test.go b/decode_test.go index 48a2bee..0611bb5 100644 --- a/decode_test.go +++ b/decode_test.go @@ -8,14 +8,32 @@ import ( func Test_Decoder(t *testing.T) { t.Run("struct", func(t *testing.T) { + type T struct { + AA int `json:"aa"` + BB string `json:"bb"` + CC bool `json:"cc"` + } var v struct { A int `json:"abcd"` B string `json:"str"` C bool + D *T } - assertErr(t, json.Unmarshal([]byte(`{ "abcd" : 123 , "str" : "hello", "c": true }`), &v)) + content := []byte(` +{ + "abcd": 123, + "str" : "hello", + "c" : true, + "d" : { + "aa": 2, + "bb": "world", + "cc": true + } +}`) + assertErr(t, json.Unmarshal(content, &v)) assertEq(t, "struct.A", 123, v.A) assertEq(t, "struct.B", "hello", v.B) assertEq(t, "struct.C", true, v.C) + assertEq(t, "struct.D.AA", 2, v.D.AA) }) } diff --git a/decode_uint.go b/decode_uint.go new file mode 100644 index 0000000..967b741 --- /dev/null +++ b/decode_uint.go @@ -0,0 +1,59 @@ +package json + +import ( + "errors" + "fmt" + "math" +) + +type uintDecoder struct { + op func(uintptr, uint64) +} + +func newUintDecoder(op func(uintptr, uint64)) *uintDecoder { + return &uintDecoder{op: op} +} + +func (d *uintDecoder) parseUint(b []byte) uint64 { + maxDigit := len(b) + sum := uint64(0) + for i := 0; i < maxDigit; i++ { + c := uint64(b[i]) - 48 + digitValue := uint64(math.Pow10(maxDigit - i - 1)) + sum += c * digitValue + } + return sum +} + +func (d *uintDecoder) decodeByte(ctx *context) ([]byte, error) { + ctx.skipWhiteSpace() + buf := ctx.buf + buflen := ctx.buflen + cursor := ctx.cursor + switch buf[cursor] { + case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': + start := cursor + cursor++ + for ; cursor < buflen; cursor++ { + tk := int(buf[cursor]) + if int('0') <= tk && tk <= int('9') { + continue + } + break + } + num := buf[start:cursor] + fmt.Printf("number = [%s]\n", string(num)) + ctx.cursor = cursor + return num, nil + } + return nil, errors.New("unexpected error number") +} + +func (d *uintDecoder) decode(ctx *context, p uintptr) error { + bytes, err := d.decodeByte(ctx) + if err != nil { + return err + } + d.op(p, d.parseUint(bytes)) + return nil +}