parse.mx raw

   1  package json
   2  
   3  import (
   4  	"errors"
   5  	"strconv"
   6  	"unsafe"
   7  )
   8  
   9  func parseValue(data []byte, pos int, typ *_rawType, ptr unsafe.Pointer) (int, error) {
  10  	pos = skipWS(data, pos)
  11  	if pos >= len(data) {
  12  		return pos, errors.New("json: unexpected end of input")
  13  	}
  14  
  15  	// Check Unmarshaler interface.
  16  	iface := ptrToIface(typ, ptr)
  17  	if iface != nil {
  18  		if u, ok := iface.(Unmarshaler); ok {
  19  			start := pos
  20  			end := skipJSONValue(data, pos)
  21  			if end < 0 {
  22  				return pos, errors.New("json: invalid value")
  23  			}
  24  			err := u.UnmarshalJSON(data[start:end])
  25  			return end, err
  26  		}
  27  	}
  28  
  29  	c := data[pos]
  30  
  31  	// null -> zero the field
  32  	if c == 'n' && pos+4 <= len(data) && string(data[pos:pos+4]) == "null" {
  33  		zeroField(typ, ptr)
  34  		return pos + 4, nil
  35  	}
  36  
  37  	switch typ.kind() {
  38  	case jkBool:
  39  		return parseBool(data, pos, ptr)
  40  	case jkInt, jkInt8, jkInt16, jkInt32, jkInt64:
  41  		return parseIntField(data, pos, typ, ptr)
  42  	case jkUint, jkUint8, jkUint16, jkUint32, jkUint64:
  43  		return parseUintField(data, pos, typ, ptr)
  44  	case jkFloat32, jkFloat64:
  45  		return parseFloatField(data, pos, typ, ptr)
  46  	case jkBytes:
  47  		return parseStringField(data, pos, ptr)
  48  	case jkPointer:
  49  		return parsePtrField(data, pos, typ, ptr)
  50  	case jkStruct:
  51  		return parseStructField(data, pos, typ, ptr)
  52  	case jkSlice:
  53  		return parseSliceField(data, pos, typ, ptr)
  54  	case jkMap:
  55  		return pos, errors.New("json: map types not supported")
  56  	case jkInterface:
  57  		return pos, errors.New("json: interface{} fields not supported")
  58  	}
  59  	return pos, errors.New("json: unsupported type")
  60  }
  61  
  62  func parseBool(data []byte, pos int, ptr unsafe.Pointer) (int, error) {
  63  	if pos+4 <= len(data) && string(data[pos:pos+4]) == "true" {
  64  		*(*bool)(ptr) = true
  65  		return pos + 4, nil
  66  	}
  67  	if pos+5 <= len(data) && string(data[pos:pos+5]) == "false" {
  68  		*(*bool)(ptr) = false
  69  		return pos + 5, nil
  70  	}
  71  	return pos, errors.New("json: expected boolean")
  72  }
  73  
  74  func parseIntField(data []byte, pos int, typ *_rawType, ptr unsafe.Pointer) (int, error) {
  75  	if pos >= len(data) || (data[pos] != '-' && (data[pos] < '0' || data[pos] > '9')) {
  76  		return pos, errors.New("json: expected number for integer field")
  77  	}
  78  	start := pos
  79  	if data[pos] == '-' {
  80  		pos++
  81  	}
  82  	for pos < len(data) && data[pos] >= '0' && data[pos] <= '9' {
  83  		pos++
  84  	}
  85  	// Reject floats in integer fields.
  86  	if pos < len(data) && (data[pos] == '.' || data[pos] == 'e' || data[pos] == 'E') {
  87  		return start, errors.New("json: cannot unmarshal float into integer field")
  88  	}
  89  	n, err := strconv.ParseInt(string(data[start:pos]), 10, 64)
  90  	if err != nil {
  91  		return start, errors.New("json: " | err.Error())
  92  	}
  93  	switch typ.size() {
  94  	case 1:
  95  		if n < -128 || n > 127 {
  96  			return start, errors.New("json: integer overflow for int8")
  97  		}
  98  		*(*int8)(ptr) = int8(n)
  99  	case 2:
 100  		if n < -32768 || n > 32767 {
 101  			return start, errors.New("json: integer overflow for int16")
 102  		}
 103  		*(*int16)(ptr) = int16(n)
 104  	case 4:
 105  		if n < -2147483648 || n > 2147483647 {
 106  			return start, errors.New("json: integer overflow for int32")
 107  		}
 108  		*(*int32)(ptr) = int32(n)
 109  	default:
 110  		*(*int64)(ptr) = n
 111  	}
 112  	return pos, nil
 113  }
 114  
 115  func parseUintField(data []byte, pos int, typ *_rawType, ptr unsafe.Pointer) (int, error) {
 116  	if pos >= len(data) || data[pos] < '0' || data[pos] > '9' {
 117  		return pos, errors.New("json: expected number for unsigned integer field")
 118  	}
 119  	start := pos
 120  	for pos < len(data) && data[pos] >= '0' && data[pos] <= '9' {
 121  		pos++
 122  	}
 123  	if pos < len(data) && (data[pos] == '.' || data[pos] == 'e' || data[pos] == 'E') {
 124  		return start, errors.New("json: cannot unmarshal float into unsigned integer field")
 125  	}
 126  	n, err := strconv.ParseUint(string(data[start:pos]), 10, 64)
 127  	if err != nil {
 128  		return start, errors.New("json: " | err.Error())
 129  	}
 130  	switch typ.size() {
 131  	case 1:
 132  		if n > 255 {
 133  			return start, errors.New("json: integer overflow for uint8")
 134  		}
 135  		*(*uint8)(ptr) = uint8(n)
 136  	case 2:
 137  		if n > 65535 {
 138  			return start, errors.New("json: integer overflow for uint16")
 139  		}
 140  		*(*uint16)(ptr) = uint16(n)
 141  	case 4:
 142  		if n > 4294967295 {
 143  			return start, errors.New("json: integer overflow for uint32")
 144  		}
 145  		*(*uint32)(ptr) = uint32(n)
 146  	default:
 147  		*(*uint64)(ptr) = n
 148  	}
 149  	return pos, nil
 150  }
 151  
 152  func parseFloatField(data []byte, pos int, typ *_rawType, ptr unsafe.Pointer) (int, error) {
 153  	if pos >= len(data) {
 154  		return pos, errors.New("json: expected number")
 155  	}
 156  	start := pos
 157  	if data[pos] == '-' {
 158  		pos++
 159  	}
 160  	for pos < len(data) && data[pos] >= '0' && data[pos] <= '9' {
 161  		pos++
 162  	}
 163  	if pos < len(data) && data[pos] == '.' {
 164  		pos++
 165  		for pos < len(data) && data[pos] >= '0' && data[pos] <= '9' {
 166  			pos++
 167  		}
 168  	}
 169  	if pos < len(data) && (data[pos] == 'e' || data[pos] == 'E') {
 170  		pos++
 171  		if pos < len(data) && (data[pos] == '+' || data[pos] == '-') {
 172  			pos++
 173  		}
 174  		for pos < len(data) && data[pos] >= '0' && data[pos] <= '9' {
 175  			pos++
 176  		}
 177  	}
 178  	f, err := strconv.ParseFloat(string(data[start:pos]), 64)
 179  	if err != nil {
 180  		return start, errors.New("json: " | err.Error())
 181  	}
 182  	if typ.size() == 4 {
 183  		*(*float32)(ptr) = float32(f)
 184  	} else {
 185  		*(*float64)(ptr) = f
 186  	}
 187  	return pos, nil
 188  }
 189  
 190  func parseStringField(data []byte, pos int, ptr unsafe.Pointer) (int, error) {
 191  	if pos >= len(data) || data[pos] != '"' {
 192  		return pos, errors.New("json: expected string")
 193  	}
 194  	s, end := scanString(data, pos)
 195  	if end < 0 {
 196  		return pos, errors.New("json: unterminated string")
 197  	}
 198  	*(*[]byte)(ptr) = []byte(s)
 199  	return end, nil
 200  }
 201  
 202  func parsePtrField(data []byte, pos int, typ *_rawType, ptr unsafe.Pointer) (int, error) {
 203  	pos = skipWS(data, pos)
 204  	if pos+4 <= len(data) && string(data[pos:pos+4]) == "null" {
 205  		*(*unsafe.Pointer)(ptr) = nil
 206  		return pos + 4, nil
 207  	}
 208  	elemType := typ.elem()
 209  	elemPtr := *(*unsafe.Pointer)(ptr)
 210  	if elemPtr == nil {
 211  		// Allocate new element.
 212  		buf := []byte{:int(elemType.size())}
 213  		elemPtr = unsafe.Pointer(&buf[0])
 214  		*(*unsafe.Pointer)(ptr) = elemPtr
 215  	}
 216  	return parseValue(data, pos, elemType, elemPtr)
 217  }
 218  
 219  func parseStructField(data []byte, pos int, typ *_rawType, ptr unsafe.Pointer) (int, error) {
 220  	pos = skipWS(data, pos)
 221  	if pos >= len(data) || data[pos] != '{' {
 222  		return pos, errors.New("json: expected object")
 223  	}
 224  	pos++
 225  	sf := structFieldsFor(typ)
 226  	for {
 227  		pos = skipWS(data, pos)
 228  		if pos >= len(data) {
 229  			return pos, errors.New("json: unexpected end of object")
 230  		}
 231  		if data[pos] == '}' {
 232  			return pos + 1, nil
 233  		}
 234  		if data[pos] == ',' {
 235  			pos++
 236  			continue
 237  		}
 238  		// Parse key.
 239  		if data[pos] != '"' {
 240  			return pos, errors.New("json: expected string key")
 241  		}
 242  		key, keyEnd := scanString(data, pos)
 243  		if keyEnd < 0 {
 244  			return pos, errors.New("json: unterminated key string")
 245  		}
 246  		pos = skipWS(data, keyEnd)
 247  		if pos >= len(data) || data[pos] != ':' {
 248  			return pos, errors.New("json: expected colon")
 249  		}
 250  		pos = skipWS(data, pos+1)
 251  
 252  		// Look up field.
 253  		idx, ok := sf.byName[string(key)]
 254  		if !ok {
 255  			// Unknown field - skip value.
 256  			end := skipJSONValue(data, pos)
 257  			if end < 0 {
 258  				return pos, errors.New("json: invalid value")
 259  			}
 260  			pos = end
 261  			continue
 262  		}
 263  		ft := typ.fieldType(idx)
 264  		fp := unsafe.Add(ptr, typ.fieldOffset(idx))
 265  		var err error
 266  		pos, err = parseValue(data, pos, ft, fp)
 267  		if err != nil {
 268  			return pos, err
 269  		}
 270  	}
 271  }
 272  
 273  func parseSliceField(data []byte, pos int, typ *_rawType, ptr unsafe.Pointer) (int, error) {
 274  	pos = skipWS(data, pos)
 275  	if pos >= len(data) {
 276  		return pos, errors.New("json: expected array")
 277  	}
 278  	// null -> nil slice
 279  	if data[pos] == 'n' && pos+4 <= len(data) && string(data[pos:pos+4]) == "null" {
 280  		*(*_sliceHeader)(ptr) = _sliceHeader{}
 281  		return pos + 4, nil
 282  	}
 283  	if data[pos] != '[' {
 284  		return pos, errors.New("json: expected array")
 285  	}
 286  	pos++
 287  
 288  	elemType := typ.elem()
 289  	hdr := (*_sliceHeader)(ptr)
 290  	// Initialize as empty-but-allocated via makeSliceOf (GC-visible).
 291  	sp := makeSliceOf(elemType, 0, 4)
 292  	*hdr = *(*_sliceHeader)(sp)
 293  
 294  	for {
 295  		pos = skipWS(data, pos)
 296  		if pos >= len(data) {
 297  			return pos, errors.New("json: unexpected end of array")
 298  		}
 299  		if data[pos] == ']' {
 300  			return pos + 1, nil
 301  		}
 302  		if data[pos] == ',' {
 303  			pos++
 304  			continue
 305  		}
 306  		// Grow slice.
 307  		sliceAppend(ptr, elemType)
 308  		elemPtr := unsafe.Add(hdr.data, elemType.size()*uintptr(hdr.len-1))
 309  		var err error
 310  		pos, err = parseValue(data, pos, elemType, elemPtr)
 311  		if err != nil {
 312  			return pos, err
 313  		}
 314  	}
 315  }
 316  
 317  // --- JSON scanner helpers ---
 318  
 319  func scanString(data []byte, pos int) (string, int) {
 320  	if pos >= len(data) || data[pos] != '"' {
 321  		return "", -1
 322  	}
 323  	pos++
 324  	start := pos
 325  	result := []byte{:0:64}
 326  	for pos < len(data) {
 327  		if data[pos] == '\\' {
 328  			result = append(result, data[start:pos]...)
 329  			pos++
 330  			if pos >= len(data) {
 331  				return "", -1
 332  			}
 333  			switch data[pos] {
 334  			case '"', '\\', '/':
 335  				result = append(result, data[pos])
 336  			case 'n':
 337  				result = append(result, '\n')
 338  			case 'r':
 339  				result = append(result, '\r')
 340  			case 't':
 341  				result = append(result, '\t')
 342  			case 'b':
 343  				result = append(result, '\b')
 344  			case 'f':
 345  				result = append(result, '\f')
 346  			case 'u':
 347  				if pos+4 >= len(data) {
 348  					return "", -1
 349  				}
 350  				cp := hexVal(data[pos+1])<<12 | hexVal(data[pos+2])<<8 | hexVal(data[pos+3])<<4 | hexVal(data[pos+4])
 351  				if cp >= 0xD800 && cp <= 0xDBFF && pos+10 < len(data) && data[pos+5] == '\\' && data[pos+6] == 'u' {
 352  					lo := hexVal(data[pos+7])<<12 | hexVal(data[pos+8])<<8 | hexVal(data[pos+9])<<4 | hexVal(data[pos+10])
 353  					if lo >= 0xDC00 && lo <= 0xDFFF {
 354  						cp = 0x10000 + (cp-0xD800)*0x400 + (lo - 0xDC00)
 355  						pos += 6
 356  					}
 357  				}
 358  				result = appendRune(result, rune(cp))
 359  				pos += 4
 360  			default:
 361  				result = append(result, data[pos])
 362  			}
 363  			pos++
 364  			start = pos
 365  			continue
 366  		}
 367  		if data[pos] == '"' {
 368  			result = append(result, data[start:pos]...)
 369  			return string(result), pos + 1
 370  		}
 371  		pos++
 372  	}
 373  	return "", -1
 374  }
 375  
 376  func hexVal(c byte) int {
 377  	if c >= '0' && c <= '9' {
 378  		return int(c - '0')
 379  	}
 380  	if c >= 'a' && c <= 'f' {
 381  		return int(c-'a') + 10
 382  	}
 383  	if c >= 'A' && c <= 'F' {
 384  		return int(c-'A') + 10
 385  	}
 386  	return 0
 387  }
 388  
 389  func appendRune(buf []byte, r rune) []byte {
 390  	if r < 0x80 {
 391  		return append(buf, byte(r))
 392  	}
 393  	if r < 0x800 {
 394  		return append(buf, byte(0xC0|(r>>6)), byte(0x80|(r&0x3F)))
 395  	}
 396  	if r < 0x10000 {
 397  		return append(buf, byte(0xE0|(r>>12)), byte(0x80|((r>>6)&0x3F)), byte(0x80|(r&0x3F)))
 398  	}
 399  	return append(buf, byte(0xF0|(r>>18)), byte(0x80|((r>>12)&0x3F)), byte(0x80|((r>>6)&0x3F)), byte(0x80|(r&0x3F)))
 400  }
 401  
 402  func skipWS(data []byte, pos int) int {
 403  	for pos < len(data) && (data[pos] == ' ' || data[pos] == '\t' || data[pos] == '\n' || data[pos] == '\r') {
 404  		pos++
 405  	}
 406  	return pos
 407  }
 408  
 409  func skipJSONValue(data []byte, pos int) int {
 410  	pos = skipWS(data, pos)
 411  	if pos >= len(data) {
 412  		return -1
 413  	}
 414  	switch data[pos] {
 415  	case '"':
 416  		_, end := scanString(data, pos)
 417  		return end
 418  	case '{':
 419  		return skipBracketed(data, pos, '{', '}')
 420  	case '[':
 421  		return skipBracketed(data, pos, '[', ']')
 422  	case 't':
 423  		if pos+4 <= len(data) {
 424  			return pos + 4
 425  		}
 426  		return -1
 427  	case 'f':
 428  		if pos+5 <= len(data) {
 429  			return pos + 5
 430  		}
 431  		return -1
 432  	case 'n':
 433  		if pos+4 <= len(data) {
 434  			return pos + 4
 435  		}
 436  		return -1
 437  	default:
 438  		// Number.
 439  		for pos < len(data) && data[pos] != ',' && data[pos] != '}' && data[pos] != ']' &&
 440  			data[pos] != ' ' && data[pos] != '\t' && data[pos] != '\n' && data[pos] != '\r' {
 441  			pos++
 442  		}
 443  		return pos
 444  	}
 445  }
 446  
 447  func skipBracketed(data []byte, pos int, open, close byte) int {
 448  	if pos >= len(data) || data[pos] != open {
 449  		return -1
 450  	}
 451  	depth := 1
 452  	pos++
 453  	inStr := false
 454  	for pos < len(data) && depth > 0 {
 455  		if inStr {
 456  			if data[pos] == '\\' {
 457  				pos++
 458  			} else if data[pos] == '"' {
 459  				inStr = false
 460  			}
 461  		} else {
 462  			if data[pos] == '"' {
 463  				inStr = true
 464  			} else if data[pos] == open {
 465  				depth++
 466  			} else if data[pos] == close {
 467  				depth--
 468  			}
 469  		}
 470  		pos++
 471  	}
 472  	if depth != 0 {
 473  		return -1
 474  	}
 475  	return pos
 476  }
 477  
 478  func zeroField(typ *_rawType, ptr unsafe.Pointer) {
 479  	sz := typ.size()
 480  	for i := uintptr(0); i < sz; i++ {
 481  		*(*byte)(unsafe.Add(ptr, i)) = 0
 482  	}
 483  }
 484