1*1c12ee1eSDan Willemsen// Copyright 2019 The Go Authors. All rights reserved. 2*1c12ee1eSDan Willemsen// Use of this source code is governed by a BSD-style 3*1c12ee1eSDan Willemsen// license that can be found in the LICENSE file. 4*1c12ee1eSDan Willemsen 5*1c12ee1eSDan Willemsenpackage json 6*1c12ee1eSDan Willemsen 7*1c12ee1eSDan Willemsenimport ( 8*1c12ee1eSDan Willemsen "bytes" 9*1c12ee1eSDan Willemsen "fmt" 10*1c12ee1eSDan Willemsen "strconv" 11*1c12ee1eSDan Willemsen) 12*1c12ee1eSDan Willemsen 13*1c12ee1eSDan Willemsen// Kind represents a token kind expressible in the JSON format. 14*1c12ee1eSDan Willemsentype Kind uint16 15*1c12ee1eSDan Willemsen 16*1c12ee1eSDan Willemsenconst ( 17*1c12ee1eSDan Willemsen Invalid Kind = (1 << iota) / 2 18*1c12ee1eSDan Willemsen EOF 19*1c12ee1eSDan Willemsen Null 20*1c12ee1eSDan Willemsen Bool 21*1c12ee1eSDan Willemsen Number 22*1c12ee1eSDan Willemsen String 23*1c12ee1eSDan Willemsen Name 24*1c12ee1eSDan Willemsen ObjectOpen 25*1c12ee1eSDan Willemsen ObjectClose 26*1c12ee1eSDan Willemsen ArrayOpen 27*1c12ee1eSDan Willemsen ArrayClose 28*1c12ee1eSDan Willemsen 29*1c12ee1eSDan Willemsen // comma is only for parsing in between tokens and 30*1c12ee1eSDan Willemsen // does not need to be exported. 31*1c12ee1eSDan Willemsen comma 32*1c12ee1eSDan Willemsen) 33*1c12ee1eSDan Willemsen 34*1c12ee1eSDan Willemsenfunc (k Kind) String() string { 35*1c12ee1eSDan Willemsen switch k { 36*1c12ee1eSDan Willemsen case EOF: 37*1c12ee1eSDan Willemsen return "eof" 38*1c12ee1eSDan Willemsen case Null: 39*1c12ee1eSDan Willemsen return "null" 40*1c12ee1eSDan Willemsen case Bool: 41*1c12ee1eSDan Willemsen return "bool" 42*1c12ee1eSDan Willemsen case Number: 43*1c12ee1eSDan Willemsen return "number" 44*1c12ee1eSDan Willemsen case String: 45*1c12ee1eSDan Willemsen return "string" 46*1c12ee1eSDan Willemsen case ObjectOpen: 47*1c12ee1eSDan Willemsen return "{" 48*1c12ee1eSDan Willemsen case ObjectClose: 49*1c12ee1eSDan Willemsen return "}" 50*1c12ee1eSDan Willemsen case Name: 51*1c12ee1eSDan Willemsen return "name" 52*1c12ee1eSDan Willemsen case ArrayOpen: 53*1c12ee1eSDan Willemsen return "[" 54*1c12ee1eSDan Willemsen case ArrayClose: 55*1c12ee1eSDan Willemsen return "]" 56*1c12ee1eSDan Willemsen case comma: 57*1c12ee1eSDan Willemsen return "," 58*1c12ee1eSDan Willemsen } 59*1c12ee1eSDan Willemsen return "<invalid>" 60*1c12ee1eSDan Willemsen} 61*1c12ee1eSDan Willemsen 62*1c12ee1eSDan Willemsen// Token provides a parsed token kind and value. 63*1c12ee1eSDan Willemsen// 64*1c12ee1eSDan Willemsen// Values are provided by the difference accessor methods. The accessor methods 65*1c12ee1eSDan Willemsen// Name, Bool, and ParsedString will panic if called on the wrong kind. There 66*1c12ee1eSDan Willemsen// are different accessor methods for the Number kind for converting to the 67*1c12ee1eSDan Willemsen// appropriate Go numeric type and those methods have the ok return value. 68*1c12ee1eSDan Willemsentype Token struct { 69*1c12ee1eSDan Willemsen // Token kind. 70*1c12ee1eSDan Willemsen kind Kind 71*1c12ee1eSDan Willemsen // pos provides the position of the token in the original input. 72*1c12ee1eSDan Willemsen pos int 73*1c12ee1eSDan Willemsen // raw bytes of the serialized token. 74*1c12ee1eSDan Willemsen // This is a subslice into the original input. 75*1c12ee1eSDan Willemsen raw []byte 76*1c12ee1eSDan Willemsen // boo is parsed boolean value. 77*1c12ee1eSDan Willemsen boo bool 78*1c12ee1eSDan Willemsen // str is parsed string value. 79*1c12ee1eSDan Willemsen str string 80*1c12ee1eSDan Willemsen} 81*1c12ee1eSDan Willemsen 82*1c12ee1eSDan Willemsen// Kind returns the token kind. 83*1c12ee1eSDan Willemsenfunc (t Token) Kind() Kind { 84*1c12ee1eSDan Willemsen return t.kind 85*1c12ee1eSDan Willemsen} 86*1c12ee1eSDan Willemsen 87*1c12ee1eSDan Willemsen// RawString returns the read value in string. 88*1c12ee1eSDan Willemsenfunc (t Token) RawString() string { 89*1c12ee1eSDan Willemsen return string(t.raw) 90*1c12ee1eSDan Willemsen} 91*1c12ee1eSDan Willemsen 92*1c12ee1eSDan Willemsen// Pos returns the token position from the input. 93*1c12ee1eSDan Willemsenfunc (t Token) Pos() int { 94*1c12ee1eSDan Willemsen return t.pos 95*1c12ee1eSDan Willemsen} 96*1c12ee1eSDan Willemsen 97*1c12ee1eSDan Willemsen// Name returns the object name if token is Name, else it panics. 98*1c12ee1eSDan Willemsenfunc (t Token) Name() string { 99*1c12ee1eSDan Willemsen if t.kind == Name { 100*1c12ee1eSDan Willemsen return t.str 101*1c12ee1eSDan Willemsen } 102*1c12ee1eSDan Willemsen panic(fmt.Sprintf("Token is not a Name: %v", t.RawString())) 103*1c12ee1eSDan Willemsen} 104*1c12ee1eSDan Willemsen 105*1c12ee1eSDan Willemsen// Bool returns the bool value if token kind is Bool, else it panics. 106*1c12ee1eSDan Willemsenfunc (t Token) Bool() bool { 107*1c12ee1eSDan Willemsen if t.kind == Bool { 108*1c12ee1eSDan Willemsen return t.boo 109*1c12ee1eSDan Willemsen } 110*1c12ee1eSDan Willemsen panic(fmt.Sprintf("Token is not a Bool: %v", t.RawString())) 111*1c12ee1eSDan Willemsen} 112*1c12ee1eSDan Willemsen 113*1c12ee1eSDan Willemsen// ParsedString returns the string value for a JSON string token or the read 114*1c12ee1eSDan Willemsen// value in string if token is not a string. 115*1c12ee1eSDan Willemsenfunc (t Token) ParsedString() string { 116*1c12ee1eSDan Willemsen if t.kind == String { 117*1c12ee1eSDan Willemsen return t.str 118*1c12ee1eSDan Willemsen } 119*1c12ee1eSDan Willemsen panic(fmt.Sprintf("Token is not a String: %v", t.RawString())) 120*1c12ee1eSDan Willemsen} 121*1c12ee1eSDan Willemsen 122*1c12ee1eSDan Willemsen// Float returns the floating-point number if token kind is Number. 123*1c12ee1eSDan Willemsen// 124*1c12ee1eSDan Willemsen// The floating-point precision is specified by the bitSize parameter: 32 for 125*1c12ee1eSDan Willemsen// float32 or 64 for float64. If bitSize=32, the result still has type float64, 126*1c12ee1eSDan Willemsen// but it will be convertible to float32 without changing its value. It will 127*1c12ee1eSDan Willemsen// return false if the number exceeds the floating point limits for given 128*1c12ee1eSDan Willemsen// bitSize. 129*1c12ee1eSDan Willemsenfunc (t Token) Float(bitSize int) (float64, bool) { 130*1c12ee1eSDan Willemsen if t.kind != Number { 131*1c12ee1eSDan Willemsen return 0, false 132*1c12ee1eSDan Willemsen } 133*1c12ee1eSDan Willemsen f, err := strconv.ParseFloat(t.RawString(), bitSize) 134*1c12ee1eSDan Willemsen if err != nil { 135*1c12ee1eSDan Willemsen return 0, false 136*1c12ee1eSDan Willemsen } 137*1c12ee1eSDan Willemsen return f, true 138*1c12ee1eSDan Willemsen} 139*1c12ee1eSDan Willemsen 140*1c12ee1eSDan Willemsen// Int returns the signed integer number if token is Number. 141*1c12ee1eSDan Willemsen// 142*1c12ee1eSDan Willemsen// The given bitSize specifies the integer type that the result must fit into. 143*1c12ee1eSDan Willemsen// It returns false if the number is not an integer value or if the result 144*1c12ee1eSDan Willemsen// exceeds the limits for given bitSize. 145*1c12ee1eSDan Willemsenfunc (t Token) Int(bitSize int) (int64, bool) { 146*1c12ee1eSDan Willemsen s, ok := t.getIntStr() 147*1c12ee1eSDan Willemsen if !ok { 148*1c12ee1eSDan Willemsen return 0, false 149*1c12ee1eSDan Willemsen } 150*1c12ee1eSDan Willemsen n, err := strconv.ParseInt(s, 10, bitSize) 151*1c12ee1eSDan Willemsen if err != nil { 152*1c12ee1eSDan Willemsen return 0, false 153*1c12ee1eSDan Willemsen } 154*1c12ee1eSDan Willemsen return n, true 155*1c12ee1eSDan Willemsen} 156*1c12ee1eSDan Willemsen 157*1c12ee1eSDan Willemsen// Uint returns the signed integer number if token is Number. 158*1c12ee1eSDan Willemsen// 159*1c12ee1eSDan Willemsen// The given bitSize specifies the unsigned integer type that the result must 160*1c12ee1eSDan Willemsen// fit into. It returns false if the number is not an unsigned integer value 161*1c12ee1eSDan Willemsen// or if the result exceeds the limits for given bitSize. 162*1c12ee1eSDan Willemsenfunc (t Token) Uint(bitSize int) (uint64, bool) { 163*1c12ee1eSDan Willemsen s, ok := t.getIntStr() 164*1c12ee1eSDan Willemsen if !ok { 165*1c12ee1eSDan Willemsen return 0, false 166*1c12ee1eSDan Willemsen } 167*1c12ee1eSDan Willemsen n, err := strconv.ParseUint(s, 10, bitSize) 168*1c12ee1eSDan Willemsen if err != nil { 169*1c12ee1eSDan Willemsen return 0, false 170*1c12ee1eSDan Willemsen } 171*1c12ee1eSDan Willemsen return n, true 172*1c12ee1eSDan Willemsen} 173*1c12ee1eSDan Willemsen 174*1c12ee1eSDan Willemsenfunc (t Token) getIntStr() (string, bool) { 175*1c12ee1eSDan Willemsen if t.kind != Number { 176*1c12ee1eSDan Willemsen return "", false 177*1c12ee1eSDan Willemsen } 178*1c12ee1eSDan Willemsen parts, ok := parseNumberParts(t.raw) 179*1c12ee1eSDan Willemsen if !ok { 180*1c12ee1eSDan Willemsen return "", false 181*1c12ee1eSDan Willemsen } 182*1c12ee1eSDan Willemsen return normalizeToIntString(parts) 183*1c12ee1eSDan Willemsen} 184*1c12ee1eSDan Willemsen 185*1c12ee1eSDan Willemsen// TokenEquals returns true if given Tokens are equal, else false. 186*1c12ee1eSDan Willemsenfunc TokenEquals(x, y Token) bool { 187*1c12ee1eSDan Willemsen return x.kind == y.kind && 188*1c12ee1eSDan Willemsen x.pos == y.pos && 189*1c12ee1eSDan Willemsen bytes.Equal(x.raw, y.raw) && 190*1c12ee1eSDan Willemsen x.boo == y.boo && 191*1c12ee1eSDan Willemsen x.str == y.str 192*1c12ee1eSDan Willemsen} 193