The KPN SenML library helps you create and parse senml documents in both json and cbor format. The library can be used for sending sensor data and receiving actuator commands.

Committer:
kpniot
Date:
Sat May 19 17:35:20 2018 +0000
Revision:
0:a9259748d982
first commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kpniot 0:a9259748d982 1 /**The MIT License (MIT)
kpniot 0:a9259748d982 2
kpniot 0:a9259748d982 3 Copyright (c) 2015 by Daniel Eichhorn
kpniot 0:a9259748d982 4
kpniot 0:a9259748d982 5 Permission is hereby granted, free of charge, to any person obtaining a copy
kpniot 0:a9259748d982 6 of this software and associated documentation files (the "Software"), to deal
kpniot 0:a9259748d982 7 in the Software without restriction, including without limitation the rights
kpniot 0:a9259748d982 8 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
kpniot 0:a9259748d982 9 copies of the Software, and to permit persons to whom the Software is
kpniot 0:a9259748d982 10 furnished to do so, subject to the following conditions:
kpniot 0:a9259748d982 11
kpniot 0:a9259748d982 12 The above copyright notice and this permission notice shall be included in all
kpniot 0:a9259748d982 13 copies or substantial portions of the Software.
kpniot 0:a9259748d982 14
kpniot 0:a9259748d982 15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
kpniot 0:a9259748d982 16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
kpniot 0:a9259748d982 17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
kpniot 0:a9259748d982 18 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
kpniot 0:a9259748d982 19 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
kpniot 0:a9259748d982 20 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
kpniot 0:a9259748d982 21 SOFTWARE.
kpniot 0:a9259748d982 22
kpniot 0:a9259748d982 23 See more at http://blog.squix.ch and https://github.com/squix78/json-streaming-parser
kpniot 0:a9259748d982 24 */
kpniot 0:a9259748d982 25
kpniot 0:a9259748d982 26 #include "senml_JsonStreamingParser.h"
kpniot 0:a9259748d982 27
kpniot 0:a9259748d982 28 JsonStreamingParser::JsonStreamingParser(): stackPos(0), bufferPos(0), unicodeEscapeBufferPos(0),
kpniot 0:a9259748d982 29 unicodeBufferPos(0), characterCounter(0), unicodeHighSurrogate(0) {
kpniot 0:a9259748d982 30 reset();
kpniot 0:a9259748d982 31 }
kpniot 0:a9259748d982 32
kpniot 0:a9259748d982 33 void JsonStreamingParser::reset() {
kpniot 0:a9259748d982 34 state = STATE_START_DOCUMENT;
kpniot 0:a9259748d982 35 bufferPos = 0;
kpniot 0:a9259748d982 36 unicodeEscapeBufferPos = 0;
kpniot 0:a9259748d982 37 unicodeBufferPos = 0;
kpniot 0:a9259748d982 38 characterCounter = 0;
kpniot 0:a9259748d982 39 }
kpniot 0:a9259748d982 40
kpniot 0:a9259748d982 41 void JsonStreamingParser::setListener(JsonListener* listener) {
kpniot 0:a9259748d982 42 myListener = listener;
kpniot 0:a9259748d982 43 }
kpniot 0:a9259748d982 44
kpniot 0:a9259748d982 45 void JsonStreamingParser::parse(char c) {
kpniot 0:a9259748d982 46 //System.out.print(c);
kpniot 0:a9259748d982 47 // valid whitespace characters in JSON (from RFC4627 for JSON) include:
kpniot 0:a9259748d982 48 // space, horizontal tab, line feed or new line, and carriage return.
kpniot 0:a9259748d982 49 // thanks:
kpniot 0:a9259748d982 50 // http://stackoverflow.com/questions/16042274/definition-of-whitespace-in-json
kpniot 0:a9259748d982 51 if ((c == ' ' || c == '\t' || c == '\n' || c == '\r')
kpniot 0:a9259748d982 52 && !(state == STATE_IN_STRING || state == STATE_UNICODE || state == STATE_START_ESCAPE
kpniot 0:a9259748d982 53 || state == STATE_IN_NUMBER || state == STATE_START_DOCUMENT)) {
kpniot 0:a9259748d982 54 return;
kpniot 0:a9259748d982 55 }
kpniot 0:a9259748d982 56 switch (state) {
kpniot 0:a9259748d982 57 case STATE_IN_STRING:
kpniot 0:a9259748d982 58 if (c == '"') {
kpniot 0:a9259748d982 59 endString();
kpniot 0:a9259748d982 60 } else if (c == '\\') {
kpniot 0:a9259748d982 61 state = STATE_START_ESCAPE;
kpniot 0:a9259748d982 62 } else if ((c < 0x1f) || (c == 0x7f)) {
kpniot 0:a9259748d982 63 //throw new RuntimeException("Unescaped control character encountered: " + c + " at position" + characterCounter);
kpniot 0:a9259748d982 64 } else {
kpniot 0:a9259748d982 65 buffer[bufferPos] = c;
kpniot 0:a9259748d982 66 increaseBufferPointer();
kpniot 0:a9259748d982 67 }
kpniot 0:a9259748d982 68 break;
kpniot 0:a9259748d982 69 case STATE_IN_ARRAY:
kpniot 0:a9259748d982 70 if (c == ']') {
kpniot 0:a9259748d982 71 endArray();
kpniot 0:a9259748d982 72 } else {
kpniot 0:a9259748d982 73 startValue(c);
kpniot 0:a9259748d982 74 }
kpniot 0:a9259748d982 75 break;
kpniot 0:a9259748d982 76 case STATE_IN_OBJECT:
kpniot 0:a9259748d982 77 if (c == '}') {
kpniot 0:a9259748d982 78 endObject();
kpniot 0:a9259748d982 79 } else if (c == '"') {
kpniot 0:a9259748d982 80 startKey();
kpniot 0:a9259748d982 81 } else {
kpniot 0:a9259748d982 82 //throw new RuntimeException("Start of string expected for object key. Instead got: " + c + " at position" + characterCounter);
kpniot 0:a9259748d982 83 }
kpniot 0:a9259748d982 84 break;
kpniot 0:a9259748d982 85 case STATE_END_KEY:
kpniot 0:a9259748d982 86 if (c != ':') {
kpniot 0:a9259748d982 87 //throw new RuntimeException("Expected ':' after key. Instead got " + c + " at position" + characterCounter);
kpniot 0:a9259748d982 88 }
kpniot 0:a9259748d982 89 state = STATE_AFTER_KEY;
kpniot 0:a9259748d982 90 break;
kpniot 0:a9259748d982 91 case STATE_AFTER_KEY:
kpniot 0:a9259748d982 92 startValue(c);
kpniot 0:a9259748d982 93 break;
kpniot 0:a9259748d982 94 case STATE_START_ESCAPE:
kpniot 0:a9259748d982 95 processEscapeCharacters(c);
kpniot 0:a9259748d982 96 break;
kpniot 0:a9259748d982 97 case STATE_UNICODE:
kpniot 0:a9259748d982 98 processUnicodeCharacter(c);
kpniot 0:a9259748d982 99 break;
kpniot 0:a9259748d982 100 case STATE_UNICODE_SURROGATE:
kpniot 0:a9259748d982 101 unicodeEscapeBuffer[unicodeEscapeBufferPos] = c;
kpniot 0:a9259748d982 102 unicodeEscapeBufferPos++;
kpniot 0:a9259748d982 103 if (unicodeEscapeBufferPos == 2) {
kpniot 0:a9259748d982 104 endUnicodeSurrogateInterstitial();
kpniot 0:a9259748d982 105 }
kpniot 0:a9259748d982 106 break;
kpniot 0:a9259748d982 107 case STATE_AFTER_VALUE: {
kpniot 0:a9259748d982 108 // not safe for size == 0!!!
kpniot 0:a9259748d982 109 int within = stack[stackPos - 1];
kpniot 0:a9259748d982 110 if (within == STACK_OBJECT) {
kpniot 0:a9259748d982 111 if (c == '}') {
kpniot 0:a9259748d982 112 endObject();
kpniot 0:a9259748d982 113 } else if (c == ',') {
kpniot 0:a9259748d982 114 state = STATE_IN_OBJECT;
kpniot 0:a9259748d982 115 } else {
kpniot 0:a9259748d982 116 //throw new RuntimeException("Expected ',' or '}' while parsing object. Got: " + c + ". " + characterCounter);
kpniot 0:a9259748d982 117 }
kpniot 0:a9259748d982 118 } else if (within == STACK_ARRAY) {
kpniot 0:a9259748d982 119 if (c == ']') {
kpniot 0:a9259748d982 120 endArray();
kpniot 0:a9259748d982 121 } else if (c == ',') {
kpniot 0:a9259748d982 122 state = STATE_IN_ARRAY;
kpniot 0:a9259748d982 123 } else {
kpniot 0:a9259748d982 124 //throw new RuntimeException("Expected ',' or ']' while parsing array. Got: " + c + ". " + characterCounter);
kpniot 0:a9259748d982 125
kpniot 0:a9259748d982 126 }
kpniot 0:a9259748d982 127 } else {
kpniot 0:a9259748d982 128 //throw new RuntimeException("Finished a literal, but unclear what state to move to. Last state: " + characterCounter);
kpniot 0:a9259748d982 129 }
kpniot 0:a9259748d982 130 }break;
kpniot 0:a9259748d982 131 case STATE_IN_NUMBER:
kpniot 0:a9259748d982 132 if (c >= '0' && c <= '9') {
kpniot 0:a9259748d982 133 buffer[bufferPos] = c;
kpniot 0:a9259748d982 134 increaseBufferPointer();
kpniot 0:a9259748d982 135 } else if (c == '.') {
kpniot 0:a9259748d982 136 if (doesCharArrayContain(buffer, bufferPos, '.')) {
kpniot 0:a9259748d982 137 //throw new RuntimeException("Cannot have multiple decimal points in a number. " + characterCounter);
kpniot 0:a9259748d982 138 } else if (doesCharArrayContain(buffer, bufferPos, 'e')) {
kpniot 0:a9259748d982 139 //throw new RuntimeException("Cannot have a decimal point in an exponent." + characterCounter);
kpniot 0:a9259748d982 140 }
kpniot 0:a9259748d982 141 buffer[bufferPos] = c;
kpniot 0:a9259748d982 142 increaseBufferPointer();
kpniot 0:a9259748d982 143 } else if (c == 'e' || c == 'E') {
kpniot 0:a9259748d982 144 if (doesCharArrayContain(buffer, bufferPos, 'e')) {
kpniot 0:a9259748d982 145 //throw new RuntimeException("Cannot have multiple exponents in a number. " + characterCounter);
kpniot 0:a9259748d982 146 }
kpniot 0:a9259748d982 147 buffer[bufferPos] = c;
kpniot 0:a9259748d982 148 increaseBufferPointer();
kpniot 0:a9259748d982 149 } else if (c == '+' || c == '-') {
kpniot 0:a9259748d982 150 char last = buffer[bufferPos - 1];
kpniot 0:a9259748d982 151 if (!(last == 'e' || last == 'E')) {
kpniot 0:a9259748d982 152 //throw new RuntimeException("Can only have '+' or '-' after the 'e' or 'E' in a number." + characterCounter);
kpniot 0:a9259748d982 153 }
kpniot 0:a9259748d982 154 buffer[bufferPos] = c;
kpniot 0:a9259748d982 155 increaseBufferPointer();
kpniot 0:a9259748d982 156 } else {
kpniot 0:a9259748d982 157 endNumber();
kpniot 0:a9259748d982 158 // we have consumed one beyond the end of the number
kpniot 0:a9259748d982 159 parse(c);
kpniot 0:a9259748d982 160 }
kpniot 0:a9259748d982 161 break;
kpniot 0:a9259748d982 162 case STATE_IN_TRUE:
kpniot 0:a9259748d982 163 buffer[bufferPos] = c;
kpniot 0:a9259748d982 164 increaseBufferPointer();
kpniot 0:a9259748d982 165 if (bufferPos == 4) {
kpniot 0:a9259748d982 166 endTrue();
kpniot 0:a9259748d982 167 }
kpniot 0:a9259748d982 168 break;
kpniot 0:a9259748d982 169 case STATE_IN_FALSE:
kpniot 0:a9259748d982 170 buffer[bufferPos] = c;
kpniot 0:a9259748d982 171 increaseBufferPointer();
kpniot 0:a9259748d982 172 if (bufferPos == 5) {
kpniot 0:a9259748d982 173 endFalse();
kpniot 0:a9259748d982 174 }
kpniot 0:a9259748d982 175 break;
kpniot 0:a9259748d982 176 case STATE_IN_NULL:
kpniot 0:a9259748d982 177 buffer[bufferPos] = c;
kpniot 0:a9259748d982 178 increaseBufferPointer();
kpniot 0:a9259748d982 179 if (bufferPos == 4) {
kpniot 0:a9259748d982 180 endNull();
kpniot 0:a9259748d982 181 }
kpniot 0:a9259748d982 182 break;
kpniot 0:a9259748d982 183 case STATE_START_DOCUMENT:
kpniot 0:a9259748d982 184 //myListener->startDocument();
kpniot 0:a9259748d982 185 if (c == '[') {
kpniot 0:a9259748d982 186 startArray();
kpniot 0:a9259748d982 187 } else if (c == '{') {
kpniot 0:a9259748d982 188 startObject();
kpniot 0:a9259748d982 189 } else {
kpniot 0:a9259748d982 190 // throw new ParsingError($this->_line_number,
kpniot 0:a9259748d982 191 // $this->_char_number,
kpniot 0:a9259748d982 192 // "Document must start with object or array.");
kpniot 0:a9259748d982 193 }
kpniot 0:a9259748d982 194 break;
kpniot 0:a9259748d982 195 //case STATE_DONE:
kpniot 0:a9259748d982 196 // throw new ParsingError($this->_line_number, $this->_char_number,
kpniot 0:a9259748d982 197 // "Expected end of document.");
kpniot 0:a9259748d982 198 //default:
kpniot 0:a9259748d982 199 // throw new ParsingError($this->_line_number, $this->_char_number,
kpniot 0:a9259748d982 200 // "Internal error. Reached an unknown state: ".$this->_state);
kpniot 0:a9259748d982 201 }
kpniot 0:a9259748d982 202 characterCounter++;
kpniot 0:a9259748d982 203 }
kpniot 0:a9259748d982 204
kpniot 0:a9259748d982 205 void JsonStreamingParser::increaseBufferPointer() {
kpniot 0:a9259748d982 206 bufferPos = min(bufferPos + 1, BUFFER_MAX_LENGTH - 1);
kpniot 0:a9259748d982 207 }
kpniot 0:a9259748d982 208
kpniot 0:a9259748d982 209 void JsonStreamingParser::endString() {
kpniot 0:a9259748d982 210 int popped = stack[stackPos - 1];
kpniot 0:a9259748d982 211 stackPos--;
kpniot 0:a9259748d982 212 if (popped == STACK_KEY) {
kpniot 0:a9259748d982 213 buffer[bufferPos] = '\0';
kpniot 0:a9259748d982 214 myListener->key(String(buffer));
kpniot 0:a9259748d982 215 state = STATE_END_KEY;
kpniot 0:a9259748d982 216 } else if (popped == STACK_STRING) {
kpniot 0:a9259748d982 217 buffer[bufferPos] = '\0';
kpniot 0:a9259748d982 218 myListener->value(String(buffer));
kpniot 0:a9259748d982 219 state = STATE_AFTER_VALUE;
kpniot 0:a9259748d982 220 } else {
kpniot 0:a9259748d982 221 // throw new ParsingError($this->_line_number, $this->_char_number,
kpniot 0:a9259748d982 222 // "Unexpected end of string.");
kpniot 0:a9259748d982 223 }
kpniot 0:a9259748d982 224 bufferPos = 0;
kpniot 0:a9259748d982 225 }
kpniot 0:a9259748d982 226 void JsonStreamingParser::startValue(char c) {
kpniot 0:a9259748d982 227 if (c == '[') {
kpniot 0:a9259748d982 228 startArray();
kpniot 0:a9259748d982 229 } else if (c == '{') {
kpniot 0:a9259748d982 230 startObject();
kpniot 0:a9259748d982 231 } else if (c == '"') {
kpniot 0:a9259748d982 232 startString();
kpniot 0:a9259748d982 233 } else if (isDigit(c)) {
kpniot 0:a9259748d982 234 startNumber(c);
kpniot 0:a9259748d982 235 } else if (c == 't') {
kpniot 0:a9259748d982 236 state = STATE_IN_TRUE;
kpniot 0:a9259748d982 237 buffer[bufferPos] = c;
kpniot 0:a9259748d982 238 increaseBufferPointer();
kpniot 0:a9259748d982 239 } else if (c == 'f') {
kpniot 0:a9259748d982 240 state = STATE_IN_FALSE;
kpniot 0:a9259748d982 241 buffer[bufferPos] = c;
kpniot 0:a9259748d982 242 increaseBufferPointer();
kpniot 0:a9259748d982 243 } else if (c == 'n') {
kpniot 0:a9259748d982 244 state = STATE_IN_NULL;
kpniot 0:a9259748d982 245 buffer[bufferPos] = c;
kpniot 0:a9259748d982 246 increaseBufferPointer();
kpniot 0:a9259748d982 247 } else {
kpniot 0:a9259748d982 248 // throw new ParsingError($this->_line_number, $this->_char_number,
kpniot 0:a9259748d982 249 // "Unexpected character for value: ".$c);
kpniot 0:a9259748d982 250 }
kpniot 0:a9259748d982 251 }
kpniot 0:a9259748d982 252
kpniot 0:a9259748d982 253 bool JsonStreamingParser::isDigit(char c) {
kpniot 0:a9259748d982 254 // Only concerned with the first character in a number.
kpniot 0:a9259748d982 255 return (c >= '0' && c <= '9') || c == '-';
kpniot 0:a9259748d982 256 }
kpniot 0:a9259748d982 257
kpniot 0:a9259748d982 258 void JsonStreamingParser::endArray() {
kpniot 0:a9259748d982 259 int popped = stack[stackPos - 1];
kpniot 0:a9259748d982 260 stackPos--;
kpniot 0:a9259748d982 261 if (popped != STACK_ARRAY) {
kpniot 0:a9259748d982 262 // throw new ParsingError($this->_line_number, $this->_char_number,
kpniot 0:a9259748d982 263 // "Unexpected end of array encountered.");
kpniot 0:a9259748d982 264 }
kpniot 0:a9259748d982 265 //myListener->endArray();
kpniot 0:a9259748d982 266 state = STATE_AFTER_VALUE;
kpniot 0:a9259748d982 267 if (stackPos == 0) {
kpniot 0:a9259748d982 268 endDocument();
kpniot 0:a9259748d982 269 }
kpniot 0:a9259748d982 270 }
kpniot 0:a9259748d982 271
kpniot 0:a9259748d982 272 void JsonStreamingParser::startKey() {
kpniot 0:a9259748d982 273 stack[stackPos] = STACK_KEY;
kpniot 0:a9259748d982 274 stackPos++;
kpniot 0:a9259748d982 275 state = STATE_IN_STRING;
kpniot 0:a9259748d982 276 }
kpniot 0:a9259748d982 277
kpniot 0:a9259748d982 278 void JsonStreamingParser::endObject() {
kpniot 0:a9259748d982 279 int popped = stack[stackPos];
kpniot 0:a9259748d982 280 stackPos--;
kpniot 0:a9259748d982 281 if (popped != STACK_OBJECT) {
kpniot 0:a9259748d982 282 // throw new ParsingError($this->_line_number, $this->_char_number,
kpniot 0:a9259748d982 283 // "Unexpected end of object encountered.");
kpniot 0:a9259748d982 284 }
kpniot 0:a9259748d982 285 //myListener->endObject();
kpniot 0:a9259748d982 286 state = STATE_AFTER_VALUE;
kpniot 0:a9259748d982 287 if (stackPos == 0) {
kpniot 0:a9259748d982 288 endDocument();
kpniot 0:a9259748d982 289 }
kpniot 0:a9259748d982 290 }
kpniot 0:a9259748d982 291
kpniot 0:a9259748d982 292 void JsonStreamingParser::processEscapeCharacters(char c) {
kpniot 0:a9259748d982 293 if (c == '"') {
kpniot 0:a9259748d982 294 buffer[bufferPos] = '"';
kpniot 0:a9259748d982 295 increaseBufferPointer();
kpniot 0:a9259748d982 296 } else if (c == '\\') {
kpniot 0:a9259748d982 297 buffer[bufferPos] = '\\';
kpniot 0:a9259748d982 298 increaseBufferPointer();
kpniot 0:a9259748d982 299 } else if (c == '/') {
kpniot 0:a9259748d982 300 buffer[bufferPos] = '/';
kpniot 0:a9259748d982 301 increaseBufferPointer();
kpniot 0:a9259748d982 302 } else if (c == 'b') {
kpniot 0:a9259748d982 303 buffer[bufferPos] = 0x08;
kpniot 0:a9259748d982 304 increaseBufferPointer();
kpniot 0:a9259748d982 305 } else if (c == 'f') {
kpniot 0:a9259748d982 306 buffer[bufferPos] = '\f';
kpniot 0:a9259748d982 307 increaseBufferPointer();
kpniot 0:a9259748d982 308 } else if (c == 'n') {
kpniot 0:a9259748d982 309 buffer[bufferPos] = '\n';
kpniot 0:a9259748d982 310 increaseBufferPointer();
kpniot 0:a9259748d982 311 } else if (c == 'r') {
kpniot 0:a9259748d982 312 buffer[bufferPos] = '\r';
kpniot 0:a9259748d982 313 increaseBufferPointer();
kpniot 0:a9259748d982 314 } else if (c == 't') {
kpniot 0:a9259748d982 315 buffer[bufferPos] = '\t';
kpniot 0:a9259748d982 316 increaseBufferPointer();
kpniot 0:a9259748d982 317 } else if (c == 'u') {
kpniot 0:a9259748d982 318 state = STATE_UNICODE;
kpniot 0:a9259748d982 319 } else {
kpniot 0:a9259748d982 320 // throw new ParsingError($this->_line_number, $this->_char_number,
kpniot 0:a9259748d982 321 // "Expected escaped character after backslash. Got: ".$c);
kpniot 0:a9259748d982 322 }
kpniot 0:a9259748d982 323 if (state != STATE_UNICODE) {
kpniot 0:a9259748d982 324 state = STATE_IN_STRING;
kpniot 0:a9259748d982 325 }
kpniot 0:a9259748d982 326 }
kpniot 0:a9259748d982 327
kpniot 0:a9259748d982 328 void JsonStreamingParser::processUnicodeCharacter(char c) {
kpniot 0:a9259748d982 329 if (!isHexCharacter(c)) {
kpniot 0:a9259748d982 330 // throw new ParsingError($this->_line_number, $this->_char_number,
kpniot 0:a9259748d982 331 // "Expected hex character for escaped Unicode character. Unicode parsed: "
kpniot 0:a9259748d982 332 // . implode($this->_unicode_buffer) . " and got: ".$c);
kpniot 0:a9259748d982 333 }
kpniot 0:a9259748d982 334
kpniot 0:a9259748d982 335 unicodeBuffer[unicodeBufferPos] = c;
kpniot 0:a9259748d982 336 unicodeBufferPos++;
kpniot 0:a9259748d982 337
kpniot 0:a9259748d982 338 if (unicodeBufferPos == 4) {
kpniot 0:a9259748d982 339 int codepoint = getHexArrayAsDecimal(unicodeBuffer, unicodeBufferPos);
kpniot 0:a9259748d982 340 endUnicodeCharacter(codepoint);
kpniot 0:a9259748d982 341 return;
kpniot 0:a9259748d982 342 /*if (codepoint >= 0xD800 && codepoint < 0xDC00) {
kpniot 0:a9259748d982 343 unicodeHighSurrogate = codepoint;
kpniot 0:a9259748d982 344 unicodeBufferPos = 0;
kpniot 0:a9259748d982 345 state = STATE_UNICODE_SURROGATE;
kpniot 0:a9259748d982 346 } else if (codepoint >= 0xDC00 && codepoint <= 0xDFFF) {
kpniot 0:a9259748d982 347 if (unicodeHighSurrogate == -1) {
kpniot 0:a9259748d982 348 // throw new ParsingError($this->_line_number,
kpniot 0:a9259748d982 349 // $this->_char_number,
kpniot 0:a9259748d982 350 // "Missing high surrogate for Unicode low surrogate.");
kpniot 0:a9259748d982 351 }
kpniot 0:a9259748d982 352 int combinedCodePoint = ((unicodeHighSurrogate - 0xD800) * 0x400) + (codepoint - 0xDC00) + 0x10000;
kpniot 0:a9259748d982 353 endUnicodeCharacter(combinedCodePoint);
kpniot 0:a9259748d982 354 } else if (unicodeHighSurrogate != -1) {
kpniot 0:a9259748d982 355 // throw new ParsingError($this->_line_number,
kpniot 0:a9259748d982 356 // $this->_char_number,
kpniot 0:a9259748d982 357 // "Invalid low surrogate following Unicode high surrogate.");
kpniot 0:a9259748d982 358 endUnicodeCharacter(codepoint);
kpniot 0:a9259748d982 359 } else {
kpniot 0:a9259748d982 360 endUnicodeCharacter(codepoint);
kpniot 0:a9259748d982 361 }*/
kpniot 0:a9259748d982 362 }
kpniot 0:a9259748d982 363 }
kpniot 0:a9259748d982 364 bool JsonStreamingParser::isHexCharacter(char c) {
kpniot 0:a9259748d982 365 return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
kpniot 0:a9259748d982 366 }
kpniot 0:a9259748d982 367
kpniot 0:a9259748d982 368 int JsonStreamingParser::getHexArrayAsDecimal(char hexArray[], int length) {
kpniot 0:a9259748d982 369 int result = 0;
kpniot 0:a9259748d982 370 for (int i = 0; i < length; i++) {
kpniot 0:a9259748d982 371 char current = hexArray[length - i - 1];
kpniot 0:a9259748d982 372 int value = 0;
kpniot 0:a9259748d982 373 if (current >= 'a' && current <= 'f') {
kpniot 0:a9259748d982 374 value = current - 'a' + 10;
kpniot 0:a9259748d982 375 } else if (current >= 'A' && current <= 'F') {
kpniot 0:a9259748d982 376 value = current - 'A' + 10;
kpniot 0:a9259748d982 377 } else if (current >= '0' && current <= '9') {
kpniot 0:a9259748d982 378 value = current - '0';
kpniot 0:a9259748d982 379 }
kpniot 0:a9259748d982 380 result += value * 16^i;
kpniot 0:a9259748d982 381 }
kpniot 0:a9259748d982 382 return result;
kpniot 0:a9259748d982 383 }
kpniot 0:a9259748d982 384
kpniot 0:a9259748d982 385 bool JsonStreamingParser::doesCharArrayContain(char myArray[], int length, char c) {
kpniot 0:a9259748d982 386 for (int i = 0; i < length; i++) {
kpniot 0:a9259748d982 387 if (myArray[i] == c) {
kpniot 0:a9259748d982 388 return true;
kpniot 0:a9259748d982 389 }
kpniot 0:a9259748d982 390 }
kpniot 0:a9259748d982 391 return false;
kpniot 0:a9259748d982 392 }
kpniot 0:a9259748d982 393
kpniot 0:a9259748d982 394 void JsonStreamingParser::endUnicodeSurrogateInterstitial() {
kpniot 0:a9259748d982 395 char unicodeEscape = unicodeEscapeBuffer[unicodeEscapeBufferPos - 1];
kpniot 0:a9259748d982 396 if (unicodeEscape != 'u') {
kpniot 0:a9259748d982 397 // throw new ParsingError($this->_line_number, $this->_char_number,
kpniot 0:a9259748d982 398 // "Expected '\\u' following a Unicode high surrogate. Got: " .
kpniot 0:a9259748d982 399 // $unicode_escape);
kpniot 0:a9259748d982 400 }
kpniot 0:a9259748d982 401 unicodeBufferPos = 0;
kpniot 0:a9259748d982 402 unicodeEscapeBufferPos = 0;
kpniot 0:a9259748d982 403 state = STATE_UNICODE;
kpniot 0:a9259748d982 404 }
kpniot 0:a9259748d982 405
kpniot 0:a9259748d982 406 void JsonStreamingParser::endNumber() {
kpniot 0:a9259748d982 407 buffer[bufferPos] = '\0';
kpniot 0:a9259748d982 408 String value = String(buffer);
kpniot 0:a9259748d982 409 //float result = 0.0;
kpniot 0:a9259748d982 410 //if (doesCharArrayContain(buffer, bufferPos, '.')) {
kpniot 0:a9259748d982 411 // result = value.toFloat();
kpniot 0:a9259748d982 412 //} else {
kpniot 0:a9259748d982 413 // needed special treatment in php, maybe not in Java and c
kpniot 0:a9259748d982 414 // result = value.toFloat();
kpniot 0:a9259748d982 415 //}
kpniot 0:a9259748d982 416 myListener->value(value.c_str());
kpniot 0:a9259748d982 417 bufferPos = 0;
kpniot 0:a9259748d982 418 state = STATE_AFTER_VALUE;
kpniot 0:a9259748d982 419 }
kpniot 0:a9259748d982 420
kpniot 0:a9259748d982 421 int JsonStreamingParser::convertDecimalBufferToInt(char myArray[], int length) {
kpniot 0:a9259748d982 422 int result = 0;
kpniot 0:a9259748d982 423 for (int i = 0; i < length; i++) {
kpniot 0:a9259748d982 424 char current = myArray[length - i - 1];
kpniot 0:a9259748d982 425 result += (current - '0') * 10;
kpniot 0:a9259748d982 426 }
kpniot 0:a9259748d982 427 return result;
kpniot 0:a9259748d982 428 }
kpniot 0:a9259748d982 429
kpniot 0:a9259748d982 430 void JsonStreamingParser::endDocument() {
kpniot 0:a9259748d982 431 //myListener->endDocument();
kpniot 0:a9259748d982 432 state = STATE_DONE;
kpniot 0:a9259748d982 433 }
kpniot 0:a9259748d982 434
kpniot 0:a9259748d982 435 void JsonStreamingParser::endTrue() {
kpniot 0:a9259748d982 436 buffer[bufferPos] = '\0';
kpniot 0:a9259748d982 437 String value = String(buffer);
kpniot 0:a9259748d982 438 if (value == "true") {
kpniot 0:a9259748d982 439
kpniot 0:a9259748d982 440 } else {
kpniot 0:a9259748d982 441 // throw new ParsingError($this->_line_number, $this->_char_number,
kpniot 0:a9259748d982 442 // "Expected 'true'. Got: ".$true);
kpniot 0:a9259748d982 443 }
kpniot 0:a9259748d982 444 bufferPos = 0;
kpniot 0:a9259748d982 445 state = STATE_AFTER_VALUE;
kpniot 0:a9259748d982 446 }
kpniot 0:a9259748d982 447
kpniot 0:a9259748d982 448 void JsonStreamingParser::endFalse() {
kpniot 0:a9259748d982 449 buffer[bufferPos] = '\0';
kpniot 0:a9259748d982 450 String value = String(buffer);
kpniot 0:a9259748d982 451 if (value == "false") {
kpniot 0:a9259748d982 452 myListener->value("false");
kpniot 0:a9259748d982 453 } else {
kpniot 0:a9259748d982 454 // throw new ParsingError($this->_line_number, $this->_char_number,
kpniot 0:a9259748d982 455 // "Expected 'true'. Got: ".$true);
kpniot 0:a9259748d982 456 }
kpniot 0:a9259748d982 457 bufferPos = 0;
kpniot 0:a9259748d982 458 state = STATE_AFTER_VALUE;
kpniot 0:a9259748d982 459 }
kpniot 0:a9259748d982 460
kpniot 0:a9259748d982 461 void JsonStreamingParser::endNull() {
kpniot 0:a9259748d982 462 buffer[bufferPos] = '\0';
kpniot 0:a9259748d982 463 String value = String(buffer);
kpniot 0:a9259748d982 464 if (value == "null") {
kpniot 0:a9259748d982 465 myListener->value("null");
kpniot 0:a9259748d982 466 } else {
kpniot 0:a9259748d982 467 // throw new ParsingError($this->_line_number, $this->_char_number,
kpniot 0:a9259748d982 468 // "Expected 'true'. Got: ".$true);
kpniot 0:a9259748d982 469 }
kpniot 0:a9259748d982 470 bufferPos = 0;
kpniot 0:a9259748d982 471 state = STATE_AFTER_VALUE;
kpniot 0:a9259748d982 472 }
kpniot 0:a9259748d982 473
kpniot 0:a9259748d982 474 void JsonStreamingParser::startArray() {
kpniot 0:a9259748d982 475 //myListener->startArray();
kpniot 0:a9259748d982 476 state = STATE_IN_ARRAY;
kpniot 0:a9259748d982 477 stack[stackPos] = STACK_ARRAY;
kpniot 0:a9259748d982 478 stackPos++;
kpniot 0:a9259748d982 479 }
kpniot 0:a9259748d982 480
kpniot 0:a9259748d982 481 void JsonStreamingParser::startObject() {
kpniot 0:a9259748d982 482 //myListener->startObject();
kpniot 0:a9259748d982 483 state = STATE_IN_OBJECT;
kpniot 0:a9259748d982 484 stack[stackPos] = STACK_OBJECT;
kpniot 0:a9259748d982 485 stackPos++;
kpniot 0:a9259748d982 486 }
kpniot 0:a9259748d982 487
kpniot 0:a9259748d982 488 void JsonStreamingParser::startString() {
kpniot 0:a9259748d982 489 stack[stackPos] = STACK_STRING;
kpniot 0:a9259748d982 490 stackPos++;
kpniot 0:a9259748d982 491 state = STATE_IN_STRING;
kpniot 0:a9259748d982 492 }
kpniot 0:a9259748d982 493
kpniot 0:a9259748d982 494 void JsonStreamingParser::startNumber(char c) {
kpniot 0:a9259748d982 495 state = STATE_IN_NUMBER;
kpniot 0:a9259748d982 496 buffer[bufferPos] = c;
kpniot 0:a9259748d982 497 increaseBufferPointer();
kpniot 0:a9259748d982 498 }
kpniot 0:a9259748d982 499
kpniot 0:a9259748d982 500 void JsonStreamingParser::endUnicodeCharacter(int codepoint) {
kpniot 0:a9259748d982 501 buffer[bufferPos] = convertCodepointToCharacter(codepoint);
kpniot 0:a9259748d982 502 increaseBufferPointer();
kpniot 0:a9259748d982 503 unicodeBufferPos = 0;
kpniot 0:a9259748d982 504 unicodeHighSurrogate = -1;
kpniot 0:a9259748d982 505 state = STATE_IN_STRING;
kpniot 0:a9259748d982 506 }
kpniot 0:a9259748d982 507
kpniot 0:a9259748d982 508 char JsonStreamingParser::convertCodepointToCharacter(int num) {
kpniot 0:a9259748d982 509 if (num <= 0x7F)
kpniot 0:a9259748d982 510 return (char) (num);
kpniot 0:a9259748d982 511 // if(num<=0x7FF) return (char)((num>>6)+192) + (char)((num&63)+128);
kpniot 0:a9259748d982 512 // if(num<=0xFFFF) return
kpniot 0:a9259748d982 513 // chr((num>>12)+224).chr(((num>>6)&63)+128).chr((num&63)+128);
kpniot 0:a9259748d982 514 // if(num<=0x1FFFFF) return
kpniot 0:a9259748d982 515 // chr((num>>18)+240).chr(((num>>12)&63)+128).chr(((num>>6)&63)+128).chr((num&63)+128);
kpniot 0:a9259748d982 516 return ' ';
kpniot 0:a9259748d982 517 }
kpniot 0:a9259748d982 518
kpniot 0:a9259748d982 519
kpniot 0:a9259748d982 520
kpniot 0:a9259748d982 521
kpniot 0:a9259748d982 522
kpniot 0:a9259748d982 523
kpniot 0:a9259748d982 524
kpniot 0:a9259748d982 525