1// Copyright (C) MongoDB, Inc. 2014-present. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); you may 4// not use this file except in compliance with the License. You may obtain 5// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 6 7package json 8 9import ( 10 "fmt" 11 "reflect" 12) 13 14// Transition functions for recognizing new. 15// Adapted from encoding/json/scanner.go. 16 17// stateNe is the state after reading `ne`. 18func stateNe(s *scanner, c int) int { 19 if c == 'w' { 20 s.step = stateNew 21 return scanContinue 22 } 23 return s.error(c, "in literal new (expecting 'w')") 24} 25 26// stateNew is the state after reading `new`. 27// Ensures that there is a space after the new keyword. 28func stateNew(s *scanner, c int) int { 29 if c <= ' ' && isSpace(rune(c)) { 30 s.step = stateBeginObjectValue 31 return scanContinue 32 } 33 return s.error(c, "expected space after new keyword") 34} 35 36// stateBeginObjectValue is the state after reading `new`. 37func stateBeginObjectValue(s *scanner, c int) int { 38 if c <= ' ' && isSpace(rune(c)) { 39 return scanSkipSpace 40 } 41 switch c { 42 case 'B': // beginning of BinData or Boolean 43 s.step = stateB 44 case 'D': // beginning of Date 45 s.step = stateD 46 case 'N': // beginning of NumberInt or NumberLong 47 s.step = stateNumberUpperN 48 case 'O': // beginning of ObjectId 49 s.step = stateO 50 case 'R': // beginning of RegExp 51 s.step = stateR 52 case 'T': // beginning of Timestamp 53 s.step = stateUpperT 54 default: 55 return s.error(c, "looking for beginning of value") 56 } 57 58 return scanBeginLiteral 59} 60 61// stateNumberUpperN is the state after reading `N`. 62func stateNumberUpperN(s *scanner, c int) int { 63 if c == 'u' { 64 s.step = stateUpperNu 65 return scanContinue 66 } 67 return s.error(c, "in literal NumberInt or NumberLong (expecting 'u')") 68} 69 70// Decodes a literal stored in the underlying byte data into v. 71func (d *decodeState) storeNewLiteral(v reflect.Value, fromQuoted bool) { 72 op := d.scanWhile(scanSkipSpace) 73 if op != scanBeginLiteral { 74 d.error(fmt.Errorf("expected beginning of constructor")) 75 } 76 77 // Read constructor identifier 78 start := d.off - 1 79 op = d.scanWhile(scanContinue) 80 if op != scanBeginCtor { 81 d.error(fmt.Errorf("expected beginning of constructor")) 82 } 83 84 // Back up so d.ctor can have the byte we just read. 85 d.off-- 86 d.scan.undo(op) 87 88 d.literalStore(d.data[start:d.off-1], v, fromQuoted) 89} 90 91// Returns a literal from the underlying byte data. 92func (d *decodeState) getNewLiteral() interface{} { 93 op := d.scanWhile(scanSkipSpace) 94 if op != scanBeginLiteral { 95 d.error(fmt.Errorf("expected beginning of constructor")) 96 } 97 return d.literalInterface() 98} 99