src/json.c

changeset 1667
608cc0b25352
parent 1654
5ab3fe0b7859
child 1668
3ffdfe1776b4
equal deleted inserted replaced
1665:b79405fbf91d 1667:608cc0b25352
94 94
95 return type; 95 return type;
96 } 96 }
97 97
98 static CxJsonToken token_create(CxJson *json, bool isstring, size_t start, size_t end) { 98 static CxJsonToken token_create(CxJson *json, bool isstring, size_t start, size_t end) {
99 cxmutstr str = cx_mutstrn(json->buffer.space + start, end - start); 99 cxmutstr buf_str = cx_mutstrn(json->buffer.space + start, end - start);
100 bool allocated = false; 100 cxmutstr str;
101 if (json->uncompleted.tokentype != CX_JSON_NO_TOKEN) { 101 bool allocated;
102 if (json->uncompleted_tokentype != CX_JSON_NO_TOKEN) {
102 allocated = true; 103 allocated = true;
103 str = cx_strcat_m(json->uncompleted.content, 1, str); 104 str = json->uncompleted_content;
104 if (str.ptr == NULL) { // LCOV_EXCL_START 105 if (cx_strcat(&str, 1, buf_str)) {
105 return (CxJsonToken){CX_JSON_NO_TOKEN, false, {NULL, 0}}; 106 return (CxJsonToken){CX_JSON_NO_TOKEN, false, {NULL, 0}}; // LCOV_EXCL_LINE
106 } // LCOV_EXCL_STOP 107 }
107 } 108 json->uncompleted_content = (cxmutstr){NULL, 0};
108 json->uncompleted = (CxJsonToken){0}; 109 json->uncompleted_tokentype = CX_JSON_NO_TOKEN;
110 } else {
111 allocated = false;
112 str = buf_str;
113 }
109 CxJsonTokenType ttype; 114 CxJsonTokenType ttype;
110 if (isstring) { 115 if (isstring) {
111 ttype = CX_JSON_TOKEN_STRING; 116 ttype = CX_JSON_TOKEN_STRING;
112 } else { 117 } else {
113 cxstring s = cx_strcast(str); 118 if (!cx_strcmp(str, "true") || !cx_strcmp(str, "false")
114 if (!cx_strcmp(s, "true") || !cx_strcmp(s, "false") 119 || !cx_strcmp(str, "null")) {
115 || !cx_strcmp(s, "null")) {
116 ttype = CX_JSON_TOKEN_LITERAL; 120 ttype = CX_JSON_TOKEN_LITERAL;
117 } else { 121 } else {
118 ttype = token_numbertype(str.ptr, str.length); 122 ttype = token_numbertype(str.ptr, str.length);
119 } 123 }
120 } 124 }
160 } 164 }
161 165
162 static enum cx_json_status token_parse_next(CxJson *json, CxJsonToken *result) { 166 static enum cx_json_status token_parse_next(CxJson *json, CxJsonToken *result) {
163 // check if there is data in the buffer 167 // check if there is data in the buffer
164 if (cxBufferEof(&json->buffer)) { 168 if (cxBufferEof(&json->buffer)) {
165 return json->uncompleted.tokentype == CX_JSON_NO_TOKEN ? 169 return json->uncompleted_tokentype == CX_JSON_NO_TOKEN ?
166 CX_JSON_NO_DATA : CX_JSON_INCOMPLETE_DATA; 170 CX_JSON_NO_DATA : CX_JSON_INCOMPLETE_DATA;
167 } 171 }
168 172
169 // current token type and start index 173 // current token type and start index
170 CxJsonTokenType ttype = json->uncompleted.tokentype; 174 CxJsonTokenType ttype = json->uncompleted_tokentype;
171 size_t token_part_start = json->buffer.pos; 175 size_t token_part_start = json->buffer.pos;
172 176
173 bool escape_end_of_string = ttype == CX_JSON_TOKEN_STRING 177 bool escape_end_of_string = ttype == CX_JSON_TOKEN_STRING
174 && json->uncompleted.content.ptr[json->uncompleted.content.length-1] == '\\'; 178 && json->uncompleted_content.ptr[json->uncompleted_content.length-1] == '\\';
175 179
176 for (size_t i = json->buffer.pos; i < json->buffer.size; i++) { 180 for (size_t i = json->buffer.pos; i < json->buffer.size; i++) {
177 char c = json->buffer.space[i]; 181 char c = json->buffer.space[i];
178 if (ttype != CX_JSON_TOKEN_STRING) { 182 if (ttype != CX_JSON_TOKEN_STRING) {
179 // currently non-string token 183 // currently non-string token
230 234
231 if (ttype == CX_JSON_NO_TOKEN) { 235 if (ttype == CX_JSON_NO_TOKEN) {
232 return CX_JSON_NO_DATA; 236 return CX_JSON_NO_DATA;
233 } else { 237 } else {
234 // uncompleted token 238 // uncompleted token
235 size_t uncompleted_len = json->buffer.size - token_part_start; 239 cxstring uncompleted = cx_strn(json->buffer.space + token_part_start, json->buffer.size - token_part_start);
236 if (json->uncompleted.tokentype == CX_JSON_NO_TOKEN) { 240 if (json->uncompleted_tokentype == CX_JSON_NO_TOKEN) {
237 // current token is uncompleted 241 assert(json->uncompleted_content.ptr == NULL);
238 // save current token content 242 json->uncompleted_content = cx_strdup(uncompleted);
239 CxJsonToken uncompleted = { 243 if (json->uncompleted_content.ptr == NULL) {
240 ttype, true,
241 cx_strdup(cx_strn(json->buffer.space + token_part_start, uncompleted_len))
242 };
243 if (uncompleted.content.ptr == NULL) {
244 return CX_JSON_BUFFER_ALLOC_FAILED; // LCOV_EXCL_LINE 244 return CX_JSON_BUFFER_ALLOC_FAILED; // LCOV_EXCL_LINE
245 } 245 }
246 json->uncompleted = uncompleted; 246 json->uncompleted_tokentype = ttype;
247 } else { 247 } else {
248 // previously we also had an uncompleted token 248 // previously we also had an uncompleted token
249 // combine the uncompleted token with the current token 249 // combine the uncompleted token with the current token
250 assert(json->uncompleted.allocated); 250 if (cx_strcat(&json->uncompleted_content, 1, uncompleted)) {
251 cxmutstr str = cx_strcat_m(json->uncompleted.content, 1,
252 cx_strn(json->buffer.space + token_part_start, uncompleted_len));
253 if (str.ptr == NULL) {
254 return CX_JSON_BUFFER_ALLOC_FAILED; // LCOV_EXCL_LINE 251 return CX_JSON_BUFFER_ALLOC_FAILED; // LCOV_EXCL_LINE
255 } 252 }
256 json->uncompleted.content = str;
257 } 253 }
258 // advance the buffer position - we saved the stuff in the uncompleted token 254 // advance the buffer position - we saved the stuff in the uncompleted token
259 json->buffer.pos += uncompleted_len; 255 json->buffer.pos += uncompleted.length;
260 return CX_JSON_INCOMPLETE_DATA; 256 return CX_JSON_INCOMPLETE_DATA;
261 } 257 }
262 } 258 }
263 259
264 // converts a Unicode codepoint to utf8 260 // converts a Unicode codepoint to utf8
562 if (json->vbuf.data != json->vbuf_internal) { 558 if (json->vbuf.data != json->vbuf_internal) {
563 cx_array_free(json->vbuf); 559 cx_array_free(json->vbuf);
564 } 560 }
565 cxJsonValueFree(json->parsed); 561 cxJsonValueFree(json->parsed);
566 json->parsed = NULL; 562 json->parsed = NULL;
567 token_destroy(&json->uncompleted); 563 json->uncompleted_tokentype = CX_JSON_NO_TOKEN;
564 cx_strfree(&json->uncompleted_content);
568 cx_strfree_a(json->allocator, &json->uncompleted_member_name); 565 cx_strfree_a(json->allocator, &json->uncompleted_member_name);
569 } 566 }
570 567
571 void cxJsonReset(CxJson *json) { 568 void cxJsonReset(CxJson *json) {
572 const CxAllocator *allocator = json->allocator; 569 const CxAllocator *allocator = json->allocator;

mercurial