private CBORObject ObjectFromUtf8Array(byte[] data, int lengthHint) { CBORObject cbor = data.Length == 0 ? CBORObject.FromObject(String.Empty) : CBORObject.FromRawUtf8(data); if (this.stringRefs != null) { this.stringRefs.AddStringIfNeeded(cbor, lengthHint); } return(cbor); }
private CBORObject ParseJSONObject(int depth) { // Assumes that the last character read was '{' if (depth > 1000) { this.RaiseError("Too deeply nested"); } int c; CBORObject key = null; CBORObject obj; var nextchar = new int[1]; var seenComma = false; var myHashMap = new SortedDictionary <CBORObject, CBORObject>(); while (true) { c = this.SkipWhitespaceJSON(); switch (c) { case -1: this.RaiseError("A JSON object must end with '}'"); break; case '}': if (seenComma) { // Situation like '{"0"=>1,}' this.RaiseError("Trailing comma"); return(null); } return(CBORObject.FromRaw(myHashMap)); default: { // Read the next string if (c < 0) { this.RaiseError("Unexpected end of data"); return(null); } if (c != '"') { this.RaiseError("Expected a string as a key"); return(null); } // Parse a string that represents the object's key // The tokenizer already checked the string for invalid // surrogate pairs, so just call the CBORObject // constructor directly obj = CBORObject.FromRawUtf8(this.NextJSONString()); key = obj; break; } } if (this.SkipWhitespaceJSON() != ':') { this.RaiseError("Expected a ':' after a key"); } int oldCount = myHashMap.Count; // NOTE: Will overwrite existing value myHashMap[key] = this.NextJSONValue( this.SkipWhitespaceJSON(), nextchar, depth); int newCount = myHashMap.Count; if (!this.options.AllowDuplicateKeys && oldCount == newCount) { this.RaiseError("Duplicate key already exists"); return(null); } switch (nextchar[0]) { case ',': seenComma = true; break; case '}': return(CBORObject.FromRaw(myHashMap)); default: this.RaiseError("Expected a ',' or '}'"); break; } } }
private CBORObject NextJSONValue( int firstChar, int[] nextChar, int depth) { int c = firstChar; CBORObject obj = null; if (c < 0) { this.RaiseError("Unexpected end of data"); } switch (c) { case '"': { // Parse a string // The tokenizer already checked the string for invalid // surrogate pairs, so just call the CBORObject // constructor directly obj = CBORObject.FromRawUtf8(this.NextJSONString()); nextChar[0] = this.SkipWhitespaceJSON(); return(obj); } case '{': { // Parse an object obj = this.ParseJSONObject(depth + 1); nextChar[0] = this.SkipWhitespaceJSON(); return(obj); } case '[': { // Parse an array obj = this.ParseJSONArray(depth + 1); nextChar[0] = this.SkipWhitespaceJSON(); return(obj); } case 't': { // Parse true if (this.endPos - this.index <= 2 || this.bytes[this.index] != (byte)0x72 || this.bytes[this.index + 1] != (byte)0x75 || this.bytes[this.index + 2] != (byte)0x65) { this.RaiseError("Value can't be parsed."); } this.index += 3; nextChar[0] = this.SkipWhitespaceJSON(); return(CBORObject.True); } case 'f': { // Parse false if (this.endPos - this.index <= 3 || this.bytes[this.index] != (byte)0x61 || this.bytes[this.index + 1] != (byte)0x6c || this.bytes[this.index + 2] != (byte)0x73 || this.bytes[this.index + 3] != (byte)0x65) { this.RaiseError("Value can't be parsed."); } this.index += 4; nextChar[0] = this.SkipWhitespaceJSON(); return(CBORObject.False); } case 'n': { // Parse null if (this.endPos - this.index <= 2 || this.bytes[this.index] != (byte)0x75 || this.bytes[this.index + 1] != (byte)0x6c || this.bytes[this.index + 2] != (byte)0x6c) { this.RaiseError("Value can't be parsed."); } this.index += 3; nextChar[0] = this.SkipWhitespaceJSON(); return(CBORObject.Null); } case '-': { // Parse a negative number return(this.NextJSONNegativeNumber(nextChar)); } case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { // Parse a nonnegative number return(this.NextJSONNonnegativeNumber(c, nextChar)); } default: this.RaiseError("Value can't be parsed."); break; } return(null); }