1a372823aSPaolo Bonzini /* 2a372823aSPaolo Bonzini * JSON lexer 3a372823aSPaolo Bonzini * 4a372823aSPaolo Bonzini * Copyright IBM, Corp. 2009 5a372823aSPaolo Bonzini * 6a372823aSPaolo Bonzini * Authors: 7a372823aSPaolo Bonzini * Anthony Liguori <aliguori@us.ibm.com> 8a372823aSPaolo Bonzini * 9a372823aSPaolo Bonzini * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. 10a372823aSPaolo Bonzini * See the COPYING.LIB file in the top-level directory. 11a372823aSPaolo Bonzini * 12a372823aSPaolo Bonzini */ 13a372823aSPaolo Bonzini 14a372823aSPaolo Bonzini #include "qapi/qmp/qstring.h" 15a372823aSPaolo Bonzini #include "qapi/qmp/qlist.h" 16a372823aSPaolo Bonzini #include "qapi/qmp/qdict.h" 17a372823aSPaolo Bonzini #include "qapi/qmp/qint.h" 18a372823aSPaolo Bonzini #include "qemu-common.h" 19a372823aSPaolo Bonzini #include "qapi/qmp/json-lexer.h" 20a372823aSPaolo Bonzini 21a372823aSPaolo Bonzini #define MAX_TOKEN_SIZE (64ULL << 20) 22a372823aSPaolo Bonzini 23a372823aSPaolo Bonzini /* 24a372823aSPaolo Bonzini * \"([^\\\"]|(\\\"\\'\\\\\\/\\b\\f\\n\\r\\t\\u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]))*\" 25a372823aSPaolo Bonzini * '([^\\']|(\\\"\\'\\\\\\/\\b\\f\\n\\r\\t\\u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]))*' 26a372823aSPaolo Bonzini * 0|([1-9][0-9]*(.[0-9]+)?([eE]([-+])?[0-9]+)) 27a372823aSPaolo Bonzini * [{}\[\],:] 28a372823aSPaolo Bonzini * [a-z]+ 29a372823aSPaolo Bonzini * 30a372823aSPaolo Bonzini */ 31a372823aSPaolo Bonzini 32a372823aSPaolo Bonzini enum json_lexer_state { 33b8d3b1daSMarkus Armbruster IN_ERROR = 0, /* must really be 0, see json_lexer[] */ 34a372823aSPaolo Bonzini IN_DQ_UCODE3, 35a372823aSPaolo Bonzini IN_DQ_UCODE2, 36a372823aSPaolo Bonzini IN_DQ_UCODE1, 37a372823aSPaolo Bonzini IN_DQ_UCODE0, 38a372823aSPaolo Bonzini IN_DQ_STRING_ESCAPE, 39a372823aSPaolo Bonzini IN_DQ_STRING, 40a372823aSPaolo Bonzini IN_SQ_UCODE3, 41a372823aSPaolo Bonzini IN_SQ_UCODE2, 42a372823aSPaolo Bonzini IN_SQ_UCODE1, 43a372823aSPaolo Bonzini IN_SQ_UCODE0, 44a372823aSPaolo Bonzini IN_SQ_STRING_ESCAPE, 45a372823aSPaolo Bonzini IN_SQ_STRING, 46a372823aSPaolo Bonzini IN_ZERO, 47a372823aSPaolo Bonzini IN_DIGITS, 48a372823aSPaolo Bonzini IN_DIGIT, 49a372823aSPaolo Bonzini IN_EXP_E, 50a372823aSPaolo Bonzini IN_MANTISSA, 51a372823aSPaolo Bonzini IN_MANTISSA_DIGITS, 52a372823aSPaolo Bonzini IN_NONZERO_NUMBER, 53a372823aSPaolo Bonzini IN_NEG_NONZERO_NUMBER, 54a372823aSPaolo Bonzini IN_KEYWORD, 55a372823aSPaolo Bonzini IN_ESCAPE, 56a372823aSPaolo Bonzini IN_ESCAPE_L, 57a372823aSPaolo Bonzini IN_ESCAPE_LL, 58a372823aSPaolo Bonzini IN_ESCAPE_I, 59a372823aSPaolo Bonzini IN_ESCAPE_I6, 60a372823aSPaolo Bonzini IN_ESCAPE_I64, 61a372823aSPaolo Bonzini IN_WHITESPACE, 62a372823aSPaolo Bonzini IN_START, 63a372823aSPaolo Bonzini }; 64a372823aSPaolo Bonzini 65b8d3b1daSMarkus Armbruster QEMU_BUILD_BUG_ON((int)JSON_MIN <= (int)IN_START); 66b8d3b1daSMarkus Armbruster 67a372823aSPaolo Bonzini #define TERMINAL(state) [0 ... 0x7F] = (state) 68a372823aSPaolo Bonzini 69a372823aSPaolo Bonzini /* Return whether TERMINAL is a terminal state and the transition to it 70a372823aSPaolo Bonzini from OLD_STATE required lookahead. This happens whenever the table 71a372823aSPaolo Bonzini below uses the TERMINAL macro. */ 72a372823aSPaolo Bonzini #define TERMINAL_NEEDED_LOOKAHEAD(old_state, terminal) \ 73a372823aSPaolo Bonzini (json_lexer[(old_state)][0] == (terminal)) 74a372823aSPaolo Bonzini 75a372823aSPaolo Bonzini static const uint8_t json_lexer[][256] = { 76b8d3b1daSMarkus Armbruster /* Relies on default initialization to IN_ERROR! */ 77b8d3b1daSMarkus Armbruster 78a372823aSPaolo Bonzini /* double quote string */ 79a372823aSPaolo Bonzini [IN_DQ_UCODE3] = { 80a372823aSPaolo Bonzini ['0' ... '9'] = IN_DQ_STRING, 81a372823aSPaolo Bonzini ['a' ... 'f'] = IN_DQ_STRING, 82a372823aSPaolo Bonzini ['A' ... 'F'] = IN_DQ_STRING, 83a372823aSPaolo Bonzini }, 84a372823aSPaolo Bonzini [IN_DQ_UCODE2] = { 85a372823aSPaolo Bonzini ['0' ... '9'] = IN_DQ_UCODE3, 86a372823aSPaolo Bonzini ['a' ... 'f'] = IN_DQ_UCODE3, 87a372823aSPaolo Bonzini ['A' ... 'F'] = IN_DQ_UCODE3, 88a372823aSPaolo Bonzini }, 89a372823aSPaolo Bonzini [IN_DQ_UCODE1] = { 90a372823aSPaolo Bonzini ['0' ... '9'] = IN_DQ_UCODE2, 91a372823aSPaolo Bonzini ['a' ... 'f'] = IN_DQ_UCODE2, 92a372823aSPaolo Bonzini ['A' ... 'F'] = IN_DQ_UCODE2, 93a372823aSPaolo Bonzini }, 94a372823aSPaolo Bonzini [IN_DQ_UCODE0] = { 95a372823aSPaolo Bonzini ['0' ... '9'] = IN_DQ_UCODE1, 96a372823aSPaolo Bonzini ['a' ... 'f'] = IN_DQ_UCODE1, 97a372823aSPaolo Bonzini ['A' ... 'F'] = IN_DQ_UCODE1, 98a372823aSPaolo Bonzini }, 99a372823aSPaolo Bonzini [IN_DQ_STRING_ESCAPE] = { 100a372823aSPaolo Bonzini ['b'] = IN_DQ_STRING, 101a372823aSPaolo Bonzini ['f'] = IN_DQ_STRING, 102a372823aSPaolo Bonzini ['n'] = IN_DQ_STRING, 103a372823aSPaolo Bonzini ['r'] = IN_DQ_STRING, 104a372823aSPaolo Bonzini ['t'] = IN_DQ_STRING, 105a372823aSPaolo Bonzini ['/'] = IN_DQ_STRING, 106a372823aSPaolo Bonzini ['\\'] = IN_DQ_STRING, 107a372823aSPaolo Bonzini ['\''] = IN_DQ_STRING, 108a372823aSPaolo Bonzini ['\"'] = IN_DQ_STRING, 109a372823aSPaolo Bonzini ['u'] = IN_DQ_UCODE0, 110a372823aSPaolo Bonzini }, 111a372823aSPaolo Bonzini [IN_DQ_STRING] = { 112a372823aSPaolo Bonzini [1 ... 0xBF] = IN_DQ_STRING, 113a372823aSPaolo Bonzini [0xC2 ... 0xF4] = IN_DQ_STRING, 114a372823aSPaolo Bonzini ['\\'] = IN_DQ_STRING_ESCAPE, 115a372823aSPaolo Bonzini ['"'] = JSON_STRING, 116a372823aSPaolo Bonzini }, 117a372823aSPaolo Bonzini 118a372823aSPaolo Bonzini /* single quote string */ 119a372823aSPaolo Bonzini [IN_SQ_UCODE3] = { 120a372823aSPaolo Bonzini ['0' ... '9'] = IN_SQ_STRING, 121a372823aSPaolo Bonzini ['a' ... 'f'] = IN_SQ_STRING, 122a372823aSPaolo Bonzini ['A' ... 'F'] = IN_SQ_STRING, 123a372823aSPaolo Bonzini }, 124a372823aSPaolo Bonzini [IN_SQ_UCODE2] = { 125a372823aSPaolo Bonzini ['0' ... '9'] = IN_SQ_UCODE3, 126a372823aSPaolo Bonzini ['a' ... 'f'] = IN_SQ_UCODE3, 127a372823aSPaolo Bonzini ['A' ... 'F'] = IN_SQ_UCODE3, 128a372823aSPaolo Bonzini }, 129a372823aSPaolo Bonzini [IN_SQ_UCODE1] = { 130a372823aSPaolo Bonzini ['0' ... '9'] = IN_SQ_UCODE2, 131a372823aSPaolo Bonzini ['a' ... 'f'] = IN_SQ_UCODE2, 132a372823aSPaolo Bonzini ['A' ... 'F'] = IN_SQ_UCODE2, 133a372823aSPaolo Bonzini }, 134a372823aSPaolo Bonzini [IN_SQ_UCODE0] = { 135a372823aSPaolo Bonzini ['0' ... '9'] = IN_SQ_UCODE1, 136a372823aSPaolo Bonzini ['a' ... 'f'] = IN_SQ_UCODE1, 137a372823aSPaolo Bonzini ['A' ... 'F'] = IN_SQ_UCODE1, 138a372823aSPaolo Bonzini }, 139a372823aSPaolo Bonzini [IN_SQ_STRING_ESCAPE] = { 140a372823aSPaolo Bonzini ['b'] = IN_SQ_STRING, 141a372823aSPaolo Bonzini ['f'] = IN_SQ_STRING, 142a372823aSPaolo Bonzini ['n'] = IN_SQ_STRING, 143a372823aSPaolo Bonzini ['r'] = IN_SQ_STRING, 144a372823aSPaolo Bonzini ['t'] = IN_SQ_STRING, 145d5932334SPaolo Bonzini ['/'] = IN_SQ_STRING, 146d5932334SPaolo Bonzini ['\\'] = IN_SQ_STRING, 147a372823aSPaolo Bonzini ['\''] = IN_SQ_STRING, 148a372823aSPaolo Bonzini ['\"'] = IN_SQ_STRING, 149a372823aSPaolo Bonzini ['u'] = IN_SQ_UCODE0, 150a372823aSPaolo Bonzini }, 151a372823aSPaolo Bonzini [IN_SQ_STRING] = { 152a372823aSPaolo Bonzini [1 ... 0xBF] = IN_SQ_STRING, 153a372823aSPaolo Bonzini [0xC2 ... 0xF4] = IN_SQ_STRING, 154a372823aSPaolo Bonzini ['\\'] = IN_SQ_STRING_ESCAPE, 155a372823aSPaolo Bonzini ['\''] = JSON_STRING, 156a372823aSPaolo Bonzini }, 157a372823aSPaolo Bonzini 158a372823aSPaolo Bonzini /* Zero */ 159a372823aSPaolo Bonzini [IN_ZERO] = { 160a372823aSPaolo Bonzini TERMINAL(JSON_INTEGER), 161a372823aSPaolo Bonzini ['0' ... '9'] = IN_ERROR, 162a372823aSPaolo Bonzini ['.'] = IN_MANTISSA, 163a372823aSPaolo Bonzini }, 164a372823aSPaolo Bonzini 165a372823aSPaolo Bonzini /* Float */ 166a372823aSPaolo Bonzini [IN_DIGITS] = { 167a372823aSPaolo Bonzini TERMINAL(JSON_FLOAT), 168a372823aSPaolo Bonzini ['0' ... '9'] = IN_DIGITS, 169a372823aSPaolo Bonzini }, 170a372823aSPaolo Bonzini 171a372823aSPaolo Bonzini [IN_DIGIT] = { 172a372823aSPaolo Bonzini ['0' ... '9'] = IN_DIGITS, 173a372823aSPaolo Bonzini }, 174a372823aSPaolo Bonzini 175a372823aSPaolo Bonzini [IN_EXP_E] = { 176a372823aSPaolo Bonzini ['-'] = IN_DIGIT, 177a372823aSPaolo Bonzini ['+'] = IN_DIGIT, 178a372823aSPaolo Bonzini ['0' ... '9'] = IN_DIGITS, 179a372823aSPaolo Bonzini }, 180a372823aSPaolo Bonzini 181a372823aSPaolo Bonzini [IN_MANTISSA_DIGITS] = { 182a372823aSPaolo Bonzini TERMINAL(JSON_FLOAT), 183a372823aSPaolo Bonzini ['0' ... '9'] = IN_MANTISSA_DIGITS, 184a372823aSPaolo Bonzini ['e'] = IN_EXP_E, 185a372823aSPaolo Bonzini ['E'] = IN_EXP_E, 186a372823aSPaolo Bonzini }, 187a372823aSPaolo Bonzini 188a372823aSPaolo Bonzini [IN_MANTISSA] = { 189a372823aSPaolo Bonzini ['0' ... '9'] = IN_MANTISSA_DIGITS, 190a372823aSPaolo Bonzini }, 191a372823aSPaolo Bonzini 192a372823aSPaolo Bonzini /* Number */ 193a372823aSPaolo Bonzini [IN_NONZERO_NUMBER] = { 194a372823aSPaolo Bonzini TERMINAL(JSON_INTEGER), 195a372823aSPaolo Bonzini ['0' ... '9'] = IN_NONZERO_NUMBER, 196a372823aSPaolo Bonzini ['e'] = IN_EXP_E, 197a372823aSPaolo Bonzini ['E'] = IN_EXP_E, 198a372823aSPaolo Bonzini ['.'] = IN_MANTISSA, 199a372823aSPaolo Bonzini }, 200a372823aSPaolo Bonzini 201a372823aSPaolo Bonzini [IN_NEG_NONZERO_NUMBER] = { 202a372823aSPaolo Bonzini ['0'] = IN_ZERO, 203a372823aSPaolo Bonzini ['1' ... '9'] = IN_NONZERO_NUMBER, 204a372823aSPaolo Bonzini }, 205a372823aSPaolo Bonzini 206a372823aSPaolo Bonzini /* keywords */ 207a372823aSPaolo Bonzini [IN_KEYWORD] = { 208a372823aSPaolo Bonzini TERMINAL(JSON_KEYWORD), 209a372823aSPaolo Bonzini ['a' ... 'z'] = IN_KEYWORD, 210a372823aSPaolo Bonzini }, 211a372823aSPaolo Bonzini 212a372823aSPaolo Bonzini /* whitespace */ 213a372823aSPaolo Bonzini [IN_WHITESPACE] = { 214a372823aSPaolo Bonzini TERMINAL(JSON_SKIP), 215a372823aSPaolo Bonzini [' '] = IN_WHITESPACE, 216a372823aSPaolo Bonzini ['\t'] = IN_WHITESPACE, 217a372823aSPaolo Bonzini ['\r'] = IN_WHITESPACE, 218a372823aSPaolo Bonzini ['\n'] = IN_WHITESPACE, 219a372823aSPaolo Bonzini }, 220a372823aSPaolo Bonzini 221a372823aSPaolo Bonzini /* escape */ 222a372823aSPaolo Bonzini [IN_ESCAPE_LL] = { 223a372823aSPaolo Bonzini ['d'] = JSON_ESCAPE, 224a372823aSPaolo Bonzini }, 225a372823aSPaolo Bonzini 226a372823aSPaolo Bonzini [IN_ESCAPE_L] = { 227a372823aSPaolo Bonzini ['d'] = JSON_ESCAPE, 228a372823aSPaolo Bonzini ['l'] = IN_ESCAPE_LL, 229a372823aSPaolo Bonzini }, 230a372823aSPaolo Bonzini 231a372823aSPaolo Bonzini [IN_ESCAPE_I64] = { 232a372823aSPaolo Bonzini ['d'] = JSON_ESCAPE, 233a372823aSPaolo Bonzini }, 234a372823aSPaolo Bonzini 235a372823aSPaolo Bonzini [IN_ESCAPE_I6] = { 236a372823aSPaolo Bonzini ['4'] = IN_ESCAPE_I64, 237a372823aSPaolo Bonzini }, 238a372823aSPaolo Bonzini 239a372823aSPaolo Bonzini [IN_ESCAPE_I] = { 240a372823aSPaolo Bonzini ['6'] = IN_ESCAPE_I6, 241a372823aSPaolo Bonzini }, 242a372823aSPaolo Bonzini 243a372823aSPaolo Bonzini [IN_ESCAPE] = { 244a372823aSPaolo Bonzini ['d'] = JSON_ESCAPE, 245a372823aSPaolo Bonzini ['i'] = JSON_ESCAPE, 246a372823aSPaolo Bonzini ['p'] = JSON_ESCAPE, 247a372823aSPaolo Bonzini ['s'] = JSON_ESCAPE, 248a372823aSPaolo Bonzini ['f'] = JSON_ESCAPE, 249a372823aSPaolo Bonzini ['l'] = IN_ESCAPE_L, 250a372823aSPaolo Bonzini ['I'] = IN_ESCAPE_I, 251a372823aSPaolo Bonzini }, 252a372823aSPaolo Bonzini 253a372823aSPaolo Bonzini /* top level rule */ 254a372823aSPaolo Bonzini [IN_START] = { 255a372823aSPaolo Bonzini ['"'] = IN_DQ_STRING, 256a372823aSPaolo Bonzini ['\''] = IN_SQ_STRING, 257a372823aSPaolo Bonzini ['0'] = IN_ZERO, 258a372823aSPaolo Bonzini ['1' ... '9'] = IN_NONZERO_NUMBER, 259a372823aSPaolo Bonzini ['-'] = IN_NEG_NONZERO_NUMBER, 260*c5461660SMarkus Armbruster ['{'] = JSON_LCURLY, 261*c5461660SMarkus Armbruster ['}'] = JSON_RCURLY, 262*c5461660SMarkus Armbruster ['['] = JSON_LSQUARE, 263*c5461660SMarkus Armbruster [']'] = JSON_RSQUARE, 264*c5461660SMarkus Armbruster [','] = JSON_COMMA, 265*c5461660SMarkus Armbruster [':'] = JSON_COLON, 266a372823aSPaolo Bonzini ['a' ... 'z'] = IN_KEYWORD, 267a372823aSPaolo Bonzini ['%'] = IN_ESCAPE, 268a372823aSPaolo Bonzini [' '] = IN_WHITESPACE, 269a372823aSPaolo Bonzini ['\t'] = IN_WHITESPACE, 270a372823aSPaolo Bonzini ['\r'] = IN_WHITESPACE, 271a372823aSPaolo Bonzini ['\n'] = IN_WHITESPACE, 272a372823aSPaolo Bonzini }, 273a372823aSPaolo Bonzini }; 274a372823aSPaolo Bonzini 275a372823aSPaolo Bonzini void json_lexer_init(JSONLexer *lexer, JSONLexerEmitter func) 276a372823aSPaolo Bonzini { 277a372823aSPaolo Bonzini lexer->emit = func; 278a372823aSPaolo Bonzini lexer->state = IN_START; 279a372823aSPaolo Bonzini lexer->token = qstring_new(); 280a372823aSPaolo Bonzini lexer->x = lexer->y = 0; 281a372823aSPaolo Bonzini } 282a372823aSPaolo Bonzini 283a372823aSPaolo Bonzini static int json_lexer_feed_char(JSONLexer *lexer, char ch, bool flush) 284a372823aSPaolo Bonzini { 285a372823aSPaolo Bonzini int char_consumed, new_state; 286a372823aSPaolo Bonzini 287a372823aSPaolo Bonzini lexer->x++; 288a372823aSPaolo Bonzini if (ch == '\n') { 289a372823aSPaolo Bonzini lexer->x = 0; 290a372823aSPaolo Bonzini lexer->y++; 291a372823aSPaolo Bonzini } 292a372823aSPaolo Bonzini 293a372823aSPaolo Bonzini do { 294b8d3b1daSMarkus Armbruster assert(lexer->state <= ARRAY_SIZE(json_lexer)); 295a372823aSPaolo Bonzini new_state = json_lexer[lexer->state][(uint8_t)ch]; 296a372823aSPaolo Bonzini char_consumed = !TERMINAL_NEEDED_LOOKAHEAD(lexer->state, new_state); 297a372823aSPaolo Bonzini if (char_consumed) { 298a372823aSPaolo Bonzini qstring_append_chr(lexer->token, ch); 299a372823aSPaolo Bonzini } 300a372823aSPaolo Bonzini 301a372823aSPaolo Bonzini switch (new_state) { 302*c5461660SMarkus Armbruster case JSON_LCURLY: 303*c5461660SMarkus Armbruster case JSON_RCURLY: 304*c5461660SMarkus Armbruster case JSON_LSQUARE: 305*c5461660SMarkus Armbruster case JSON_RSQUARE: 306*c5461660SMarkus Armbruster case JSON_COLON: 307*c5461660SMarkus Armbruster case JSON_COMMA: 308a372823aSPaolo Bonzini case JSON_ESCAPE: 309a372823aSPaolo Bonzini case JSON_INTEGER: 310a372823aSPaolo Bonzini case JSON_FLOAT: 311a372823aSPaolo Bonzini case JSON_KEYWORD: 312a372823aSPaolo Bonzini case JSON_STRING: 313a372823aSPaolo Bonzini lexer->emit(lexer, lexer->token, new_state, lexer->x, lexer->y); 314a372823aSPaolo Bonzini /* fall through */ 315a372823aSPaolo Bonzini case JSON_SKIP: 316a372823aSPaolo Bonzini QDECREF(lexer->token); 317a372823aSPaolo Bonzini lexer->token = qstring_new(); 318a372823aSPaolo Bonzini new_state = IN_START; 319a372823aSPaolo Bonzini break; 320a372823aSPaolo Bonzini case IN_ERROR: 321a372823aSPaolo Bonzini /* XXX: To avoid having previous bad input leaving the parser in an 322a372823aSPaolo Bonzini * unresponsive state where we consume unpredictable amounts of 323a372823aSPaolo Bonzini * subsequent "good" input, percolate this error state up to the 324a372823aSPaolo Bonzini * tokenizer/parser by forcing a NULL object to be emitted, then 325a372823aSPaolo Bonzini * reset state. 326a372823aSPaolo Bonzini * 327a372823aSPaolo Bonzini * Also note that this handling is required for reliable channel 328a372823aSPaolo Bonzini * negotiation between QMP and the guest agent, since chr(0xFF) 329a372823aSPaolo Bonzini * is placed at the beginning of certain events to ensure proper 330a372823aSPaolo Bonzini * delivery when the channel is in an unknown state. chr(0xFF) is 331a372823aSPaolo Bonzini * never a valid ASCII/UTF-8 sequence, so this should reliably 332a372823aSPaolo Bonzini * induce an error/flush state. 333a372823aSPaolo Bonzini */ 334a372823aSPaolo Bonzini lexer->emit(lexer, lexer->token, JSON_ERROR, lexer->x, lexer->y); 335a372823aSPaolo Bonzini QDECREF(lexer->token); 336a372823aSPaolo Bonzini lexer->token = qstring_new(); 337a372823aSPaolo Bonzini new_state = IN_START; 338a372823aSPaolo Bonzini lexer->state = new_state; 339a372823aSPaolo Bonzini return 0; 340a372823aSPaolo Bonzini default: 341a372823aSPaolo Bonzini break; 342a372823aSPaolo Bonzini } 343a372823aSPaolo Bonzini lexer->state = new_state; 344a372823aSPaolo Bonzini } while (!char_consumed && !flush); 345a372823aSPaolo Bonzini 346a372823aSPaolo Bonzini /* Do not let a single token grow to an arbitrarily large size, 347a372823aSPaolo Bonzini * this is a security consideration. 348a372823aSPaolo Bonzini */ 349a372823aSPaolo Bonzini if (lexer->token->length > MAX_TOKEN_SIZE) { 350a372823aSPaolo Bonzini lexer->emit(lexer, lexer->token, lexer->state, lexer->x, lexer->y); 351a372823aSPaolo Bonzini QDECREF(lexer->token); 352a372823aSPaolo Bonzini lexer->token = qstring_new(); 353a372823aSPaolo Bonzini lexer->state = IN_START; 354a372823aSPaolo Bonzini } 355a372823aSPaolo Bonzini 356a372823aSPaolo Bonzini return 0; 357a372823aSPaolo Bonzini } 358a372823aSPaolo Bonzini 359a372823aSPaolo Bonzini int json_lexer_feed(JSONLexer *lexer, const char *buffer, size_t size) 360a372823aSPaolo Bonzini { 361a372823aSPaolo Bonzini size_t i; 362a372823aSPaolo Bonzini 363a372823aSPaolo Bonzini for (i = 0; i < size; i++) { 364a372823aSPaolo Bonzini int err; 365a372823aSPaolo Bonzini 366a372823aSPaolo Bonzini err = json_lexer_feed_char(lexer, buffer[i], false); 367a372823aSPaolo Bonzini if (err < 0) { 368a372823aSPaolo Bonzini return err; 369a372823aSPaolo Bonzini } 370a372823aSPaolo Bonzini } 371a372823aSPaolo Bonzini 372a372823aSPaolo Bonzini return 0; 373a372823aSPaolo Bonzini } 374a372823aSPaolo Bonzini 375a372823aSPaolo Bonzini int json_lexer_flush(JSONLexer *lexer) 376a372823aSPaolo Bonzini { 377a372823aSPaolo Bonzini return lexer->state == IN_START ? 0 : json_lexer_feed_char(lexer, 0, true); 378a372823aSPaolo Bonzini } 379a372823aSPaolo Bonzini 380a372823aSPaolo Bonzini void json_lexer_destroy(JSONLexer *lexer) 381a372823aSPaolo Bonzini { 382a372823aSPaolo Bonzini QDECREF(lexer->token); 383a372823aSPaolo Bonzini } 384