Line data Source code
1 : #include "Python.h"
2 : #include "structmember.h"
3 : #if PY_VERSION_HEX < 0x02060000 && !defined(Py_TYPE)
4 : #define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
5 : #endif
6 : #if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN)
7 : typedef int Py_ssize_t;
8 : #define PY_SSIZE_T_MAX INT_MAX
9 : #define PY_SSIZE_T_MIN INT_MIN
10 : #define PyInt_FromSsize_t PyInt_FromLong
11 : #define PyInt_AsSsize_t PyInt_AsLong
12 : #endif
13 : #ifndef Py_IS_FINITE
14 : #define Py_IS_FINITE(X) (!Py_IS_INFINITY(X) && !Py_IS_NAN(X))
15 : #endif
16 :
17 : #ifdef __GNUC__
18 : #define UNUSED __attribute__((__unused__))
19 : #else
20 : #define UNUSED
21 : #endif
22 :
23 : #define DEFAULT_ENCODING "utf-8"
24 :
25 : #define PyScanner_Check(op) PyObject_TypeCheck(op, &PyScannerType)
26 : #define PyScanner_CheckExact(op) (Py_TYPE(op) == &PyScannerType)
27 : #define PyEncoder_Check(op) PyObject_TypeCheck(op, &PyEncoderType)
28 : #define PyEncoder_CheckExact(op) (Py_TYPE(op) == &PyEncoderType)
29 :
30 : static PyTypeObject PyScannerType;
31 : static PyTypeObject PyEncoderType;
32 :
33 : typedef struct _PyScannerObject {
34 : PyObject_HEAD
35 : PyObject *encoding;
36 : PyObject *strict;
37 : PyObject *object_hook;
38 : PyObject *pairs_hook;
39 : PyObject *parse_float;
40 : PyObject *parse_int;
41 : PyObject *parse_constant;
42 : } PyScannerObject;
43 :
44 : static PyMemberDef scanner_members[] = {
45 : {"encoding", T_OBJECT, offsetof(PyScannerObject, encoding), READONLY, "encoding"},
46 : {"strict", T_OBJECT, offsetof(PyScannerObject, strict), READONLY, "strict"},
47 : {"object_hook", T_OBJECT, offsetof(PyScannerObject, object_hook), READONLY, "object_hook"},
48 : {"object_pairs_hook", T_OBJECT, offsetof(PyScannerObject, pairs_hook), READONLY, "object_pairs_hook"},
49 : {"parse_float", T_OBJECT, offsetof(PyScannerObject, parse_float), READONLY, "parse_float"},
50 : {"parse_int", T_OBJECT, offsetof(PyScannerObject, parse_int), READONLY, "parse_int"},
51 : {"parse_constant", T_OBJECT, offsetof(PyScannerObject, parse_constant), READONLY, "parse_constant"},
52 : {NULL}
53 : };
54 :
55 : typedef struct _PyEncoderObject {
56 : PyObject_HEAD
57 : PyObject *markers;
58 : PyObject *defaultfn;
59 : PyObject *encoder;
60 : PyObject *indent;
61 : PyObject *key_separator;
62 : PyObject *item_separator;
63 : PyObject *sort_keys;
64 : PyObject *skipkeys;
65 : int fast_encode;
66 : int allow_nan;
67 : } PyEncoderObject;
68 :
69 : static PyMemberDef encoder_members[] = {
70 : {"markers", T_OBJECT, offsetof(PyEncoderObject, markers), READONLY, "markers"},
71 : {"default", T_OBJECT, offsetof(PyEncoderObject, defaultfn), READONLY, "default"},
72 : {"encoder", T_OBJECT, offsetof(PyEncoderObject, encoder), READONLY, "encoder"},
73 : {"indent", T_OBJECT, offsetof(PyEncoderObject, indent), READONLY, "indent"},
74 : {"key_separator", T_OBJECT, offsetof(PyEncoderObject, key_separator), READONLY, "key_separator"},
75 : {"item_separator", T_OBJECT, offsetof(PyEncoderObject, item_separator), READONLY, "item_separator"},
76 : {"sort_keys", T_OBJECT, offsetof(PyEncoderObject, sort_keys), READONLY, "sort_keys"},
77 : {"skipkeys", T_OBJECT, offsetof(PyEncoderObject, skipkeys), READONLY, "skipkeys"},
78 : {NULL}
79 : };
80 :
81 : static Py_ssize_t
82 : ascii_escape_char(Py_UNICODE c, char *output, Py_ssize_t chars);
83 : static PyObject *
84 : ascii_escape_unicode(PyObject *pystr);
85 : static PyObject *
86 : ascii_escape_str(PyObject *pystr);
87 : static PyObject *
88 : py_encode_basestring_ascii(PyObject* self UNUSED, PyObject *pystr);
89 : void init_json(void);
90 : static PyObject *
91 : scan_once_str(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr);
92 : static PyObject *
93 : scan_once_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr);
94 : static PyObject *
95 : _build_rval_index_tuple(PyObject *rval, Py_ssize_t idx);
96 : static PyObject *
97 : scanner_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
98 : static int
99 : scanner_init(PyObject *self, PyObject *args, PyObject *kwds);
100 : static void
101 : scanner_dealloc(PyObject *self);
102 : static int
103 : scanner_clear(PyObject *self);
104 : static PyObject *
105 : encoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
106 : static int
107 : encoder_init(PyObject *self, PyObject *args, PyObject *kwds);
108 : static void
109 : encoder_dealloc(PyObject *self);
110 : static int
111 : encoder_clear(PyObject *self);
112 : static int
113 : encoder_listencode_list(PyEncoderObject *s, PyObject *rval, PyObject *seq, Py_ssize_t indent_level);
114 : static int
115 : encoder_listencode_obj(PyEncoderObject *s, PyObject *rval, PyObject *obj, Py_ssize_t indent_level);
116 : static int
117 : encoder_listencode_dict(PyEncoderObject *s, PyObject *rval, PyObject *dct, Py_ssize_t indent_level);
118 : static PyObject *
119 : _encoded_const(PyObject *obj);
120 : static void
121 : raise_errmsg(char *msg, PyObject *s, Py_ssize_t end);
122 : static PyObject *
123 : encoder_encode_string(PyEncoderObject *s, PyObject *obj);
124 : static int
125 : _convertPyInt_AsSsize_t(PyObject *o, Py_ssize_t *size_ptr);
126 : static PyObject *
127 : _convertPyInt_FromSsize_t(Py_ssize_t *size_ptr);
128 : static PyObject *
129 : encoder_encode_float(PyEncoderObject *s, PyObject *obj);
130 :
131 : #define S_CHAR(c) (c >= ' ' && c <= '~' && c != '\\' && c != '"')
132 : #define IS_WHITESPACE(c) (((c) == ' ') || ((c) == '\t') || ((c) == '\n') || ((c) == '\r'))
133 :
134 : #define MIN_EXPANSION 6
135 : #ifdef Py_UNICODE_WIDE
136 : #define MAX_EXPANSION (2 * MIN_EXPANSION)
137 : #else
138 : #define MAX_EXPANSION MIN_EXPANSION
139 : #endif
140 :
141 : static int
142 0 : _convertPyInt_AsSsize_t(PyObject *o, Py_ssize_t *size_ptr)
143 : {
144 : /* PyObject to Py_ssize_t converter */
145 0 : *size_ptr = PyInt_AsSsize_t(o);
146 0 : if (*size_ptr == -1 && PyErr_Occurred())
147 0 : return 0;
148 0 : return 1;
149 : }
150 :
151 : static PyObject *
152 0 : _convertPyInt_FromSsize_t(Py_ssize_t *size_ptr)
153 : {
154 : /* Py_ssize_t to PyObject converter */
155 0 : return PyInt_FromSsize_t(*size_ptr);
156 : }
157 :
158 : static Py_ssize_t
159 0 : ascii_escape_char(Py_UNICODE c, char *output, Py_ssize_t chars)
160 : {
161 : /* Escape unicode code point c to ASCII escape sequences
162 : in char *output. output must have at least 12 bytes unused to
163 : accommodate an escaped surrogate pair "\uXXXX\uXXXX" */
164 0 : output[chars++] = '\\';
165 0 : switch (c) {
166 0 : case '\\': output[chars++] = (char)c; break;
167 0 : case '"': output[chars++] = (char)c; break;
168 0 : case '\b': output[chars++] = 'b'; break;
169 0 : case '\f': output[chars++] = 'f'; break;
170 0 : case '\n': output[chars++] = 'n'; break;
171 0 : case '\r': output[chars++] = 'r'; break;
172 0 : case '\t': output[chars++] = 't'; break;
173 : default:
174 : #ifdef Py_UNICODE_WIDE
175 : if (c >= 0x10000) {
176 : /* UTF-16 surrogate pair */
177 : Py_UNICODE v = c - 0x10000;
178 : c = 0xd800 | ((v >> 10) & 0x3ff);
179 : output[chars++] = 'u';
180 : output[chars++] = "0123456789abcdef"[(c >> 12) & 0xf];
181 : output[chars++] = "0123456789abcdef"[(c >> 8) & 0xf];
182 : output[chars++] = "0123456789abcdef"[(c >> 4) & 0xf];
183 : output[chars++] = "0123456789abcdef"[(c ) & 0xf];
184 : c = 0xdc00 | (v & 0x3ff);
185 : output[chars++] = '\\';
186 : }
187 : #endif
188 0 : output[chars++] = 'u';
189 0 : output[chars++] = "0123456789abcdef"[(c >> 12) & 0xf];
190 0 : output[chars++] = "0123456789abcdef"[(c >> 8) & 0xf];
191 0 : output[chars++] = "0123456789abcdef"[(c >> 4) & 0xf];
192 0 : output[chars++] = "0123456789abcdef"[(c ) & 0xf];
193 : }
194 0 : return chars;
195 : }
196 :
197 : static PyObject *
198 0 : ascii_escape_unicode(PyObject *pystr)
199 : {
200 : /* Take a PyUnicode pystr and return a new ASCII-only escaped PyString */
201 : Py_ssize_t i;
202 : Py_ssize_t input_chars;
203 : Py_ssize_t output_size;
204 : Py_ssize_t max_output_size;
205 : Py_ssize_t chars;
206 : Py_ssize_t incr;
207 : PyObject *rval;
208 : char *output;
209 : Py_UNICODE *input_unicode;
210 :
211 0 : input_chars = PyUnicode_GET_SIZE(pystr);
212 0 : input_unicode = PyUnicode_AS_UNICODE(pystr);
213 :
214 0 : output_size = input_chars;
215 0 : incr = 2; /* for quotes */
216 : /* One char input can be up to 6 chars output, estimate 4 of these */
217 0 : incr += MIN_EXPANSION * 4;
218 0 : if (PY_SSIZE_T_MAX - incr < output_size) {
219 0 : PyErr_NoMemory();
220 0 : return NULL;
221 : }
222 0 : output_size += incr;
223 0 : if (PY_SSIZE_T_MAX / MAX_EXPANSION < input_chars ||
224 0 : PY_SSIZE_T_MAX - 2 < input_chars * MAX_EXPANSION)
225 0 : max_output_size = PY_SSIZE_T_MAX;
226 : else
227 0 : max_output_size = 2 + (input_chars * MAX_EXPANSION);
228 0 : rval = PyString_FromStringAndSize(NULL, output_size);
229 0 : if (rval == NULL) {
230 0 : return NULL;
231 : }
232 0 : output = PyString_AS_STRING(rval);
233 0 : chars = 0;
234 0 : output[chars++] = '"';
235 0 : for (i = 0; i < input_chars; i++) {
236 0 : Py_UNICODE c = input_unicode[i];
237 0 : if (S_CHAR(c)) {
238 0 : output[chars++] = (char)c;
239 : }
240 : else {
241 0 : chars = ascii_escape_char(c, output, chars);
242 : }
243 0 : if (output_size - chars < (1 + MAX_EXPANSION)) {
244 0 : if (output_size == PY_SSIZE_T_MAX) {
245 0 : Py_DECREF(rval);
246 0 : PyErr_NoMemory();
247 0 : return NULL;
248 : }
249 : /* There's more than four, so let's resize by a lot */
250 0 : if (PY_SSIZE_T_MAX / 2 >= output_size && output_size * 2 < max_output_size)
251 0 : output_size *= 2;
252 : else
253 0 : output_size = max_output_size;
254 0 : if (_PyString_Resize(&rval, output_size) == -1) {
255 0 : return NULL;
256 : }
257 0 : output = PyString_AS_STRING(rval);
258 : }
259 : }
260 0 : output[chars++] = '"';
261 0 : if (_PyString_Resize(&rval, chars) == -1) {
262 0 : return NULL;
263 : }
264 0 : return rval;
265 : }
266 :
267 : static PyObject *
268 0 : ascii_escape_str(PyObject *pystr)
269 : {
270 : /* Take a PyString pystr and return a new ASCII-only escaped PyString */
271 : Py_ssize_t i;
272 : Py_ssize_t input_chars;
273 : Py_ssize_t output_size;
274 : Py_ssize_t max_output_size;
275 : Py_ssize_t chars;
276 : Py_ssize_t incr;
277 : PyObject *rval;
278 : char *output;
279 : char *input_str;
280 :
281 0 : input_chars = PyString_GET_SIZE(pystr);
282 0 : input_str = PyString_AS_STRING(pystr);
283 :
284 : /* Fast path for a string that's already ASCII */
285 0 : for (i = 0; i < input_chars; i++) {
286 0 : Py_UNICODE c = (Py_UNICODE)(unsigned char)input_str[i];
287 0 : if (!S_CHAR(c)) {
288 : /* If we have to escape something, scan the string for unicode */
289 : Py_ssize_t j;
290 0 : for (j = i; j < input_chars; j++) {
291 0 : c = (Py_UNICODE)(unsigned char)input_str[j];
292 0 : if (c > 0x7f) {
293 : /* We hit a non-ASCII character, bail to unicode mode */
294 : PyObject *uni;
295 0 : uni = PyUnicode_DecodeUTF8(input_str, input_chars, "strict");
296 0 : if (uni == NULL) {
297 0 : return NULL;
298 : }
299 0 : rval = ascii_escape_unicode(uni);
300 0 : Py_DECREF(uni);
301 0 : return rval;
302 : }
303 : }
304 0 : break;
305 : }
306 : }
307 :
308 0 : output_size = input_chars;
309 0 : incr = 2; /* for quotes */
310 0 : if (i != input_chars) {
311 : /* One char input can be up to 6 chars output, estimate 4 of these */
312 0 : incr += MIN_EXPANSION * 4;
313 : }
314 0 : if (PY_SSIZE_T_MAX - incr < output_size) {
315 0 : PyErr_NoMemory();
316 0 : return NULL;
317 : }
318 0 : output_size += incr;
319 0 : if (PY_SSIZE_T_MAX / MIN_EXPANSION < input_chars ||
320 0 : PY_SSIZE_T_MAX - 2 < input_chars * MIN_EXPANSION)
321 0 : max_output_size = PY_SSIZE_T_MAX;
322 : else
323 0 : max_output_size = 2 + (input_chars * MIN_EXPANSION);
324 0 : rval = PyString_FromStringAndSize(NULL, output_size);
325 0 : if (rval == NULL) {
326 0 : return NULL;
327 : }
328 0 : output = PyString_AS_STRING(rval);
329 0 : output[0] = '"';
330 :
331 : /* We know that everything up to i is ASCII already */
332 0 : chars = i + 1;
333 0 : memcpy(&output[1], input_str, i);
334 :
335 0 : for (; i < input_chars; i++) {
336 0 : Py_UNICODE c = (Py_UNICODE)(unsigned char)input_str[i];
337 0 : if (S_CHAR(c)) {
338 0 : output[chars++] = (char)c;
339 : }
340 : else {
341 0 : chars = ascii_escape_char(c, output, chars);
342 : }
343 : /* An ASCII char can't possibly expand to a surrogate! */
344 0 : if (output_size - chars < (1 + MIN_EXPANSION)) {
345 0 : if (output_size == PY_SSIZE_T_MAX) {
346 0 : Py_DECREF(rval);
347 0 : PyErr_NoMemory();
348 0 : return NULL;
349 : }
350 : /* There's more than four, so let's resize by a lot */
351 0 : if (PY_SSIZE_T_MAX / 2 >= output_size && output_size * 2 < max_output_size)
352 0 : output_size *= 2;
353 : else
354 0 : output_size = max_output_size;
355 0 : if (_PyString_Resize(&rval, output_size) == -1) {
356 0 : return NULL;
357 : }
358 0 : output = PyString_AS_STRING(rval);
359 : }
360 : }
361 0 : output[chars++] = '"';
362 0 : if (_PyString_Resize(&rval, chars) == -1) {
363 0 : return NULL;
364 : }
365 0 : return rval;
366 : }
367 :
368 : static void
369 0 : raise_errmsg(char *msg, PyObject *s, Py_ssize_t end)
370 : {
371 : /* Use the Python function json.decoder.errmsg to raise a nice
372 : looking ValueError exception */
373 : static PyObject *errmsg_fn = NULL;
374 : PyObject *pymsg;
375 0 : if (errmsg_fn == NULL) {
376 0 : PyObject *decoder = PyImport_ImportModule("json.decoder");
377 0 : if (decoder == NULL)
378 0 : return;
379 0 : errmsg_fn = PyObject_GetAttrString(decoder, "errmsg");
380 0 : Py_DECREF(decoder);
381 0 : if (errmsg_fn == NULL)
382 0 : return;
383 : }
384 0 : pymsg = PyObject_CallFunction(errmsg_fn, "(zOO&)", msg, s, _convertPyInt_FromSsize_t, &end);
385 0 : if (pymsg) {
386 0 : PyErr_SetObject(PyExc_ValueError, pymsg);
387 0 : Py_DECREF(pymsg);
388 : }
389 : }
390 :
391 : static PyObject *
392 0 : join_list_unicode(PyObject *lst)
393 : {
394 : /* return u''.join(lst) */
395 : static PyObject *joinfn = NULL;
396 0 : if (joinfn == NULL) {
397 0 : PyObject *ustr = PyUnicode_FromUnicode(NULL, 0);
398 0 : if (ustr == NULL)
399 0 : return NULL;
400 :
401 0 : joinfn = PyObject_GetAttrString(ustr, "join");
402 0 : Py_DECREF(ustr);
403 0 : if (joinfn == NULL)
404 0 : return NULL;
405 : }
406 0 : return PyObject_CallFunctionObjArgs(joinfn, lst, NULL);
407 : }
408 :
409 : static PyObject *
410 0 : _build_rval_index_tuple(PyObject *rval, Py_ssize_t idx) {
411 : /* return (rval, idx) tuple, stealing reference to rval */
412 : PyObject *tpl;
413 : PyObject *pyidx;
414 : /*
415 : steal a reference to rval, returns (rval, idx)
416 : */
417 0 : if (rval == NULL) {
418 0 : return NULL;
419 : }
420 0 : pyidx = PyInt_FromSsize_t(idx);
421 0 : if (pyidx == NULL) {
422 0 : Py_DECREF(rval);
423 0 : return NULL;
424 : }
425 0 : tpl = PyTuple_New(2);
426 0 : if (tpl == NULL) {
427 0 : Py_DECREF(pyidx);
428 0 : Py_DECREF(rval);
429 0 : return NULL;
430 : }
431 0 : PyTuple_SET_ITEM(tpl, 0, rval);
432 0 : PyTuple_SET_ITEM(tpl, 1, pyidx);
433 0 : return tpl;
434 : }
435 :
436 : static PyObject *
437 0 : scanstring_str(PyObject *pystr, Py_ssize_t end, char *encoding, int strict, Py_ssize_t *next_end_ptr)
438 : {
439 : /* Read the JSON string from PyString pystr.
440 : end is the index of the first character after the quote.
441 : encoding is the encoding of pystr (must be an ASCII superset)
442 : if strict is zero then literal control characters are allowed
443 : *next_end_ptr is a return-by-reference index of the character
444 : after the end quote
445 :
446 : Return value is a new PyString (if ASCII-only) or PyUnicode
447 : */
448 : PyObject *rval;
449 0 : Py_ssize_t len = PyString_GET_SIZE(pystr);
450 0 : Py_ssize_t begin = end - 1;
451 : Py_ssize_t next;
452 0 : char *buf = PyString_AS_STRING(pystr);
453 0 : PyObject *chunks = PyList_New(0);
454 0 : if (chunks == NULL) {
455 0 : goto bail;
456 : }
457 0 : if (end < 0 || len <= end) {
458 0 : PyErr_SetString(PyExc_ValueError, "end is out of bounds");
459 0 : goto bail;
460 : }
461 : while (1) {
462 : /* Find the end of the string or the next escape */
463 0 : Py_UNICODE c = 0;
464 0 : PyObject *chunk = NULL;
465 0 : for (next = end; next < len; next++) {
466 0 : c = (unsigned char)buf[next];
467 0 : if (c == '"' || c == '\\') {
468 : break;
469 : }
470 0 : else if (strict && c <= 0x1f) {
471 0 : raise_errmsg("Invalid control character at", pystr, next);
472 0 : goto bail;
473 : }
474 : }
475 0 : if (!(c == '"' || c == '\\')) {
476 0 : raise_errmsg("Unterminated string starting at", pystr, begin);
477 0 : goto bail;
478 : }
479 : /* Pick up this chunk if it's not zero length */
480 0 : if (next != end) {
481 0 : PyObject *strchunk = PyString_FromStringAndSize(&buf[end], next - end);
482 0 : if (strchunk == NULL) {
483 0 : goto bail;
484 : }
485 0 : chunk = PyUnicode_FromEncodedObject(strchunk, encoding, NULL);
486 0 : Py_DECREF(strchunk);
487 0 : if (chunk == NULL) {
488 0 : goto bail;
489 : }
490 0 : if (PyList_Append(chunks, chunk)) {
491 0 : Py_DECREF(chunk);
492 0 : goto bail;
493 : }
494 0 : Py_DECREF(chunk);
495 : }
496 0 : next++;
497 0 : if (c == '"') {
498 0 : end = next;
499 0 : break;
500 : }
501 0 : if (next == len) {
502 0 : raise_errmsg("Unterminated string starting at", pystr, begin);
503 0 : goto bail;
504 : }
505 0 : c = buf[next];
506 0 : if (c != 'u') {
507 : /* Non-unicode backslash escapes */
508 0 : end = next + 1;
509 0 : switch (c) {
510 0 : case '"': break;
511 0 : case '\\': break;
512 0 : case '/': break;
513 0 : case 'b': c = '\b'; break;
514 0 : case 'f': c = '\f'; break;
515 0 : case 'n': c = '\n'; break;
516 0 : case 'r': c = '\r'; break;
517 0 : case 't': c = '\t'; break;
518 0 : default: c = 0;
519 : }
520 0 : if (c == 0) {
521 0 : raise_errmsg("Invalid \\escape", pystr, end - 2);
522 0 : goto bail;
523 : }
524 : }
525 : else {
526 0 : c = 0;
527 0 : next++;
528 0 : end = next + 4;
529 0 : if (end >= len) {
530 0 : raise_errmsg("Invalid \\uXXXX escape", pystr, next - 1);
531 0 : goto bail;
532 : }
533 : /* Decode 4 hex digits */
534 0 : for (; next < end; next++) {
535 0 : Py_UNICODE digit = buf[next];
536 0 : c <<= 4;
537 0 : switch (digit) {
538 : case '0': case '1': case '2': case '3': case '4':
539 : case '5': case '6': case '7': case '8': case '9':
540 0 : c |= (digit - '0'); break;
541 : case 'a': case 'b': case 'c': case 'd': case 'e':
542 : case 'f':
543 0 : c |= (digit - 'a' + 10); break;
544 : case 'A': case 'B': case 'C': case 'D': case 'E':
545 : case 'F':
546 0 : c |= (digit - 'A' + 10); break;
547 : default:
548 0 : raise_errmsg("Invalid \\uXXXX escape", pystr, end - 5);
549 0 : goto bail;
550 : }
551 : }
552 : #ifdef Py_UNICODE_WIDE
553 : /* Surrogate pair */
554 : if ((c & 0xfc00) == 0xd800 && end + 6 < len &&
555 : buf[next++] == '\\' &&
556 : buf[next++] == 'u') {
557 : Py_UNICODE c2 = 0;
558 : end += 6;
559 : /* Decode 4 hex digits */
560 : for (; next < end; next++) {
561 : Py_UNICODE digit = buf[next];
562 : c2 <<= 4;
563 : switch (digit) {
564 : case '0': case '1': case '2': case '3': case '4':
565 : case '5': case '6': case '7': case '8': case '9':
566 : c2 |= (digit - '0'); break;
567 : case 'a': case 'b': case 'c': case 'd': case 'e':
568 : case 'f':
569 : c2 |= (digit - 'a' + 10); break;
570 : case 'A': case 'B': case 'C': case 'D': case 'E':
571 : case 'F':
572 : c2 |= (digit - 'A' + 10); break;
573 : default:
574 : raise_errmsg("Invalid \\uXXXX escape", pystr, end - 5);
575 : goto bail;
576 : }
577 : }
578 : if ((c2 & 0xfc00) == 0xdc00)
579 : c = 0x10000 + (((c - 0xd800) << 10) | (c2 - 0xdc00));
580 : else
581 : end -= 6;
582 : }
583 : #endif
584 : }
585 0 : chunk = PyUnicode_FromUnicode(&c, 1);
586 0 : if (chunk == NULL) {
587 0 : goto bail;
588 : }
589 0 : if (PyList_Append(chunks, chunk)) {
590 0 : Py_DECREF(chunk);
591 0 : goto bail;
592 : }
593 0 : Py_DECREF(chunk);
594 0 : }
595 :
596 0 : rval = join_list_unicode(chunks);
597 0 : if (rval == NULL) {
598 0 : goto bail;
599 : }
600 0 : Py_CLEAR(chunks);
601 0 : *next_end_ptr = end;
602 0 : return rval;
603 : bail:
604 0 : *next_end_ptr = -1;
605 0 : Py_XDECREF(chunks);
606 0 : return NULL;
607 : }
608 :
609 :
610 : static PyObject *
611 0 : scanstring_unicode(PyObject *pystr, Py_ssize_t end, int strict, Py_ssize_t *next_end_ptr)
612 : {
613 : /* Read the JSON string from PyUnicode pystr.
614 : end is the index of the first character after the quote.
615 : if strict is zero then literal control characters are allowed
616 : *next_end_ptr is a return-by-reference index of the character
617 : after the end quote
618 :
619 : Return value is a new PyUnicode
620 : */
621 : PyObject *rval;
622 0 : Py_ssize_t len = PyUnicode_GET_SIZE(pystr);
623 0 : Py_ssize_t begin = end - 1;
624 : Py_ssize_t next;
625 0 : const Py_UNICODE *buf = PyUnicode_AS_UNICODE(pystr);
626 0 : PyObject *chunks = PyList_New(0);
627 0 : if (chunks == NULL) {
628 0 : goto bail;
629 : }
630 0 : if (end < 0 || len <= end) {
631 0 : PyErr_SetString(PyExc_ValueError, "end is out of bounds");
632 0 : goto bail;
633 : }
634 : while (1) {
635 : /* Find the end of the string or the next escape */
636 0 : Py_UNICODE c = 0;
637 0 : PyObject *chunk = NULL;
638 0 : for (next = end; next < len; next++) {
639 0 : c = buf[next];
640 0 : if (c == '"' || c == '\\') {
641 : break;
642 : }
643 0 : else if (strict && c <= 0x1f) {
644 0 : raise_errmsg("Invalid control character at", pystr, next);
645 0 : goto bail;
646 : }
647 : }
648 0 : if (!(c == '"' || c == '\\')) {
649 0 : raise_errmsg("Unterminated string starting at", pystr, begin);
650 0 : goto bail;
651 : }
652 : /* Pick up this chunk if it's not zero length */
653 0 : if (next != end) {
654 0 : chunk = PyUnicode_FromUnicode(&buf[end], next - end);
655 0 : if (chunk == NULL) {
656 0 : goto bail;
657 : }
658 0 : if (PyList_Append(chunks, chunk)) {
659 0 : Py_DECREF(chunk);
660 0 : goto bail;
661 : }
662 0 : Py_DECREF(chunk);
663 : }
664 0 : next++;
665 0 : if (c == '"') {
666 0 : end = next;
667 0 : break;
668 : }
669 0 : if (next == len) {
670 0 : raise_errmsg("Unterminated string starting at", pystr, begin);
671 0 : goto bail;
672 : }
673 0 : c = buf[next];
674 0 : if (c != 'u') {
675 : /* Non-unicode backslash escapes */
676 0 : end = next + 1;
677 0 : switch (c) {
678 0 : case '"': break;
679 0 : case '\\': break;
680 0 : case '/': break;
681 0 : case 'b': c = '\b'; break;
682 0 : case 'f': c = '\f'; break;
683 0 : case 'n': c = '\n'; break;
684 0 : case 'r': c = '\r'; break;
685 0 : case 't': c = '\t'; break;
686 0 : default: c = 0;
687 : }
688 0 : if (c == 0) {
689 0 : raise_errmsg("Invalid \\escape", pystr, end - 2);
690 0 : goto bail;
691 : }
692 : }
693 : else {
694 0 : c = 0;
695 0 : next++;
696 0 : end = next + 4;
697 0 : if (end >= len) {
698 0 : raise_errmsg("Invalid \\uXXXX escape", pystr, next - 1);
699 0 : goto bail;
700 : }
701 : /* Decode 4 hex digits */
702 0 : for (; next < end; next++) {
703 0 : Py_UNICODE digit = buf[next];
704 0 : c <<= 4;
705 0 : switch (digit) {
706 : case '0': case '1': case '2': case '3': case '4':
707 : case '5': case '6': case '7': case '8': case '9':
708 0 : c |= (digit - '0'); break;
709 : case 'a': case 'b': case 'c': case 'd': case 'e':
710 : case 'f':
711 0 : c |= (digit - 'a' + 10); break;
712 : case 'A': case 'B': case 'C': case 'D': case 'E':
713 : case 'F':
714 0 : c |= (digit - 'A' + 10); break;
715 : default:
716 0 : raise_errmsg("Invalid \\uXXXX escape", pystr, end - 5);
717 0 : goto bail;
718 : }
719 : }
720 : #ifdef Py_UNICODE_WIDE
721 : /* Surrogate pair */
722 : if ((c & 0xfc00) == 0xd800 && end + 6 < len &&
723 : buf[next++] == '\\' && buf[next++] == 'u') {
724 : Py_UNICODE c2 = 0;
725 : end += 6;
726 : /* Decode 4 hex digits */
727 : for (; next < end; next++) {
728 : Py_UNICODE digit = buf[next];
729 : c2 <<= 4;
730 : switch (digit) {
731 : case '0': case '1': case '2': case '3': case '4':
732 : case '5': case '6': case '7': case '8': case '9':
733 : c2 |= (digit - '0'); break;
734 : case 'a': case 'b': case 'c': case 'd': case 'e':
735 : case 'f':
736 : c2 |= (digit - 'a' + 10); break;
737 : case 'A': case 'B': case 'C': case 'D': case 'E':
738 : case 'F':
739 : c2 |= (digit - 'A' + 10); break;
740 : default:
741 : raise_errmsg("Invalid \\uXXXX escape", pystr, end - 5);
742 : goto bail;
743 : }
744 : }
745 : if ((c2 & 0xfc00) == 0xdc00)
746 : c = 0x10000 + (((c - 0xd800) << 10) | (c2 - 0xdc00));
747 : else
748 : end -= 6;
749 : }
750 : #endif
751 : }
752 0 : chunk = PyUnicode_FromUnicode(&c, 1);
753 0 : if (chunk == NULL) {
754 0 : goto bail;
755 : }
756 0 : if (PyList_Append(chunks, chunk)) {
757 0 : Py_DECREF(chunk);
758 0 : goto bail;
759 : }
760 0 : Py_DECREF(chunk);
761 0 : }
762 :
763 0 : rval = join_list_unicode(chunks);
764 0 : if (rval == NULL) {
765 0 : goto bail;
766 : }
767 0 : Py_DECREF(chunks);
768 0 : *next_end_ptr = end;
769 0 : return rval;
770 : bail:
771 0 : *next_end_ptr = -1;
772 0 : Py_XDECREF(chunks);
773 0 : return NULL;
774 : }
775 :
776 : PyDoc_STRVAR(pydoc_scanstring,
777 : "scanstring(basestring, end, encoding, strict=True) -> (str, end)\n"
778 : "\n"
779 : "Scan the string s for a JSON string. End is the index of the\n"
780 : "character in s after the quote that started the JSON string.\n"
781 : "Unescapes all valid JSON string escape sequences and raises ValueError\n"
782 : "on attempt to decode an invalid string. If strict is False then literal\n"
783 : "control characters are allowed in the string.\n"
784 : "\n"
785 : "Returns a tuple of the decoded string and the index of the character in s\n"
786 : "after the end quote."
787 : );
788 :
789 : static PyObject *
790 0 : py_scanstring(PyObject* self UNUSED, PyObject *args)
791 : {
792 : PyObject *pystr;
793 : PyObject *rval;
794 : Py_ssize_t end;
795 0 : Py_ssize_t next_end = -1;
796 0 : char *encoding = NULL;
797 0 : int strict = 1;
798 0 : if (!PyArg_ParseTuple(args, "OO&|zi:scanstring", &pystr, _convertPyInt_AsSsize_t, &end, &encoding, &strict)) {
799 0 : return NULL;
800 : }
801 0 : if (encoding == NULL) {
802 0 : encoding = DEFAULT_ENCODING;
803 : }
804 0 : if (PyString_Check(pystr)) {
805 0 : rval = scanstring_str(pystr, end, encoding, strict, &next_end);
806 : }
807 0 : else if (PyUnicode_Check(pystr)) {
808 0 : rval = scanstring_unicode(pystr, end, strict, &next_end);
809 : }
810 : else {
811 0 : PyErr_Format(PyExc_TypeError,
812 : "first argument must be a string, not %.80s",
813 0 : Py_TYPE(pystr)->tp_name);
814 0 : return NULL;
815 : }
816 0 : return _build_rval_index_tuple(rval, next_end);
817 : }
818 :
819 : PyDoc_STRVAR(pydoc_encode_basestring_ascii,
820 : "encode_basestring_ascii(basestring) -> str\n"
821 : "\n"
822 : "Return an ASCII-only JSON representation of a Python string"
823 : );
824 :
825 : static PyObject *
826 0 : py_encode_basestring_ascii(PyObject* self UNUSED, PyObject *pystr)
827 : {
828 : /* Return an ASCII-only JSON representation of a Python string */
829 : /* METH_O */
830 0 : if (PyString_Check(pystr)) {
831 0 : return ascii_escape_str(pystr);
832 : }
833 0 : else if (PyUnicode_Check(pystr)) {
834 0 : return ascii_escape_unicode(pystr);
835 : }
836 : else {
837 0 : PyErr_Format(PyExc_TypeError,
838 : "first argument must be a string, not %.80s",
839 0 : Py_TYPE(pystr)->tp_name);
840 0 : return NULL;
841 : }
842 : }
843 :
844 : static void
845 3 : scanner_dealloc(PyObject *self)
846 : {
847 : /* Deallocate scanner object */
848 3 : scanner_clear(self);
849 3 : Py_TYPE(self)->tp_free(self);
850 3 : }
851 :
852 : static int
853 18 : scanner_traverse(PyObject *self, visitproc visit, void *arg)
854 : {
855 : PyScannerObject *s;
856 : assert(PyScanner_Check(self));
857 18 : s = (PyScannerObject *)self;
858 18 : Py_VISIT(s->encoding);
859 18 : Py_VISIT(s->strict);
860 18 : Py_VISIT(s->object_hook);
861 18 : Py_VISIT(s->pairs_hook);
862 18 : Py_VISIT(s->parse_float);
863 18 : Py_VISIT(s->parse_int);
864 18 : Py_VISIT(s->parse_constant);
865 18 : return 0;
866 : }
867 :
868 : static int
869 3 : scanner_clear(PyObject *self)
870 : {
871 : PyScannerObject *s;
872 : assert(PyScanner_Check(self));
873 3 : s = (PyScannerObject *)self;
874 3 : Py_CLEAR(s->encoding);
875 3 : Py_CLEAR(s->strict);
876 3 : Py_CLEAR(s->object_hook);
877 3 : Py_CLEAR(s->pairs_hook);
878 3 : Py_CLEAR(s->parse_float);
879 3 : Py_CLEAR(s->parse_int);
880 3 : Py_CLEAR(s->parse_constant);
881 3 : return 0;
882 : }
883 :
884 : static PyObject *
885 0 : _parse_object_str(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr) {
886 : /* Read a JSON object from PyString pystr.
887 : idx is the index of the first character after the opening curly brace.
888 : *next_idx_ptr is a return-by-reference index to the first character after
889 : the closing curly brace.
890 :
891 : Returns a new PyObject (usually a dict, but object_hook can change that)
892 : */
893 0 : char *str = PyString_AS_STRING(pystr);
894 0 : Py_ssize_t end_idx = PyString_GET_SIZE(pystr) - 1;
895 : PyObject *rval;
896 : PyObject *pairs;
897 : PyObject *item;
898 0 : PyObject *key = NULL;
899 0 : PyObject *val = NULL;
900 0 : char *encoding = PyString_AS_STRING(s->encoding);
901 0 : int strict = PyObject_IsTrue(s->strict);
902 : Py_ssize_t next_idx;
903 :
904 0 : if (strict < 0)
905 0 : return NULL;
906 :
907 0 : pairs = PyList_New(0);
908 0 : if (pairs == NULL)
909 0 : return NULL;
910 :
911 : /* skip whitespace after { */
912 0 : while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
913 :
914 : /* only loop if the object is non-empty */
915 0 : if (idx <= end_idx && str[idx] != '}') {
916 0 : while (idx <= end_idx) {
917 : /* read key */
918 0 : if (str[idx] != '"') {
919 0 : raise_errmsg("Expecting property name", pystr, idx);
920 0 : goto bail;
921 : }
922 0 : key = scanstring_str(pystr, idx + 1, encoding, strict, &next_idx);
923 0 : if (key == NULL)
924 0 : goto bail;
925 0 : idx = next_idx;
926 :
927 : /* skip whitespace between key and : delimiter, read :, skip whitespace */
928 0 : while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
929 0 : if (idx > end_idx || str[idx] != ':') {
930 0 : raise_errmsg("Expecting : delimiter", pystr, idx);
931 0 : goto bail;
932 : }
933 0 : idx++;
934 0 : while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
935 :
936 : /* read any JSON data type */
937 0 : val = scan_once_str(s, pystr, idx, &next_idx);
938 0 : if (val == NULL)
939 0 : goto bail;
940 :
941 0 : item = PyTuple_Pack(2, key, val);
942 0 : if (item == NULL)
943 0 : goto bail;
944 0 : Py_CLEAR(key);
945 0 : Py_CLEAR(val);
946 0 : if (PyList_Append(pairs, item) == -1) {
947 0 : Py_DECREF(item);
948 0 : goto bail;
949 : }
950 0 : Py_DECREF(item);
951 0 : idx = next_idx;
952 :
953 : /* skip whitespace before } or , */
954 0 : while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
955 :
956 : /* bail if the object is closed or we didn't get the , delimiter */
957 0 : if (idx > end_idx) break;
958 0 : if (str[idx] == '}') {
959 0 : break;
960 : }
961 0 : else if (str[idx] != ',') {
962 0 : raise_errmsg("Expecting , delimiter", pystr, idx);
963 0 : goto bail;
964 : }
965 0 : idx++;
966 :
967 : /* skip whitespace after , delimiter */
968 0 : while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
969 : }
970 : }
971 : /* verify that idx < end_idx, str[idx] should be '}' */
972 0 : if (idx > end_idx || str[idx] != '}') {
973 0 : raise_errmsg("Expecting object", pystr, end_idx);
974 0 : goto bail;
975 : }
976 :
977 : /* if pairs_hook is not None: rval = object_pairs_hook(pairs) */
978 0 : if (s->pairs_hook != Py_None) {
979 0 : val = PyObject_CallFunctionObjArgs(s->pairs_hook, pairs, NULL);
980 0 : if (val == NULL)
981 0 : goto bail;
982 0 : Py_DECREF(pairs);
983 0 : *next_idx_ptr = idx + 1;
984 0 : return val;
985 : }
986 :
987 0 : rval = PyObject_CallFunctionObjArgs((PyObject *)(&PyDict_Type),
988 : pairs, NULL);
989 0 : if (rval == NULL)
990 0 : goto bail;
991 0 : Py_CLEAR(pairs);
992 :
993 : /* if object_hook is not None: rval = object_hook(rval) */
994 0 : if (s->object_hook != Py_None) {
995 0 : val = PyObject_CallFunctionObjArgs(s->object_hook, rval, NULL);
996 0 : if (val == NULL)
997 0 : goto bail;
998 0 : Py_DECREF(rval);
999 0 : rval = val;
1000 0 : val = NULL;
1001 : }
1002 0 : *next_idx_ptr = idx + 1;
1003 0 : return rval;
1004 : bail:
1005 0 : Py_XDECREF(key);
1006 0 : Py_XDECREF(val);
1007 0 : Py_XDECREF(pairs);
1008 0 : return NULL;
1009 : }
1010 :
1011 : static PyObject *
1012 0 : _parse_object_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr) {
1013 : /* Read a JSON object from PyUnicode pystr.
1014 : idx is the index of the first character after the opening curly brace.
1015 : *next_idx_ptr is a return-by-reference index to the first character after
1016 : the closing curly brace.
1017 :
1018 : Returns a new PyObject (usually a dict, but object_hook can change that)
1019 : */
1020 0 : Py_UNICODE *str = PyUnicode_AS_UNICODE(pystr);
1021 0 : Py_ssize_t end_idx = PyUnicode_GET_SIZE(pystr) - 1;
1022 : PyObject *rval;
1023 : PyObject *pairs;
1024 : PyObject *item;
1025 0 : PyObject *key = NULL;
1026 0 : PyObject *val = NULL;
1027 0 : int strict = PyObject_IsTrue(s->strict);
1028 : Py_ssize_t next_idx;
1029 :
1030 0 : if (strict < 0)
1031 0 : return NULL;
1032 :
1033 0 : pairs = PyList_New(0);
1034 0 : if (pairs == NULL)
1035 0 : return NULL;
1036 :
1037 : /* skip whitespace after { */
1038 0 : while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
1039 :
1040 : /* only loop if the object is non-empty */
1041 0 : if (idx <= end_idx && str[idx] != '}') {
1042 0 : while (idx <= end_idx) {
1043 : /* read key */
1044 0 : if (str[idx] != '"') {
1045 0 : raise_errmsg("Expecting property name enclosed in double quotes", pystr, idx);
1046 0 : goto bail;
1047 : }
1048 0 : key = scanstring_unicode(pystr, idx + 1, strict, &next_idx);
1049 0 : if (key == NULL)
1050 0 : goto bail;
1051 0 : idx = next_idx;
1052 :
1053 : /* skip whitespace between key and : delimiter, read :, skip whitespace */
1054 0 : while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
1055 0 : if (idx > end_idx || str[idx] != ':') {
1056 0 : raise_errmsg("Expecting ':' delimiter", pystr, idx);
1057 0 : goto bail;
1058 : }
1059 0 : idx++;
1060 0 : while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
1061 :
1062 : /* read any JSON term */
1063 0 : val = scan_once_unicode(s, pystr, idx, &next_idx);
1064 0 : if (val == NULL)
1065 0 : goto bail;
1066 :
1067 0 : item = PyTuple_Pack(2, key, val);
1068 0 : if (item == NULL)
1069 0 : goto bail;
1070 0 : Py_CLEAR(key);
1071 0 : Py_CLEAR(val);
1072 0 : if (PyList_Append(pairs, item) == -1) {
1073 0 : Py_DECREF(item);
1074 0 : goto bail;
1075 : }
1076 0 : Py_DECREF(item);
1077 0 : idx = next_idx;
1078 :
1079 : /* skip whitespace before } or , */
1080 0 : while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
1081 :
1082 : /* bail if the object is closed or we didn't get the , delimiter */
1083 0 : if (idx > end_idx) break;
1084 0 : if (str[idx] == '}') {
1085 0 : break;
1086 : }
1087 0 : else if (str[idx] != ',') {
1088 0 : raise_errmsg("Expecting ',' delimiter", pystr, idx);
1089 0 : goto bail;
1090 : }
1091 0 : idx++;
1092 :
1093 : /* skip whitespace after , delimiter */
1094 0 : while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
1095 : }
1096 : }
1097 :
1098 : /* verify that idx < end_idx, str[idx] should be '}' */
1099 0 : if (idx > end_idx || str[idx] != '}') {
1100 0 : raise_errmsg("Expecting object", pystr, end_idx);
1101 0 : goto bail;
1102 : }
1103 :
1104 : /* if pairs_hook is not None: rval = object_pairs_hook(pairs) */
1105 0 : if (s->pairs_hook != Py_None) {
1106 0 : val = PyObject_CallFunctionObjArgs(s->pairs_hook, pairs, NULL);
1107 0 : if (val == NULL)
1108 0 : goto bail;
1109 0 : Py_DECREF(pairs);
1110 0 : *next_idx_ptr = idx + 1;
1111 0 : return val;
1112 : }
1113 :
1114 0 : rval = PyObject_CallFunctionObjArgs((PyObject *)(&PyDict_Type),
1115 : pairs, NULL);
1116 0 : if (rval == NULL)
1117 0 : goto bail;
1118 0 : Py_CLEAR(pairs);
1119 :
1120 : /* if object_hook is not None: rval = object_hook(rval) */
1121 0 : if (s->object_hook != Py_None) {
1122 0 : val = PyObject_CallFunctionObjArgs(s->object_hook, rval, NULL);
1123 0 : if (val == NULL)
1124 0 : goto bail;
1125 0 : Py_DECREF(rval);
1126 0 : rval = val;
1127 0 : val = NULL;
1128 : }
1129 0 : *next_idx_ptr = idx + 1;
1130 0 : return rval;
1131 : bail:
1132 0 : Py_XDECREF(key);
1133 0 : Py_XDECREF(val);
1134 0 : Py_XDECREF(pairs);
1135 0 : return NULL;
1136 : }
1137 :
1138 : static PyObject *
1139 0 : _parse_array_str(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr) {
1140 : /* Read a JSON array from PyString pystr.
1141 : idx is the index of the first character after the opening brace.
1142 : *next_idx_ptr is a return-by-reference index to the first character after
1143 : the closing brace.
1144 :
1145 : Returns a new PyList
1146 : */
1147 0 : char *str = PyString_AS_STRING(pystr);
1148 0 : Py_ssize_t end_idx = PyString_GET_SIZE(pystr) - 1;
1149 0 : PyObject *val = NULL;
1150 0 : PyObject *rval = PyList_New(0);
1151 : Py_ssize_t next_idx;
1152 0 : if (rval == NULL)
1153 0 : return NULL;
1154 :
1155 : /* skip whitespace after [ */
1156 0 : while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
1157 :
1158 : /* only loop if the array is non-empty */
1159 0 : if (idx <= end_idx && str[idx] != ']') {
1160 0 : while (idx <= end_idx) {
1161 :
1162 : /* read any JSON term and de-tuplefy the (rval, idx) */
1163 0 : val = scan_once_str(s, pystr, idx, &next_idx);
1164 0 : if (val == NULL)
1165 0 : goto bail;
1166 :
1167 0 : if (PyList_Append(rval, val) == -1)
1168 0 : goto bail;
1169 :
1170 0 : Py_CLEAR(val);
1171 0 : idx = next_idx;
1172 :
1173 : /* skip whitespace between term and , */
1174 0 : while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
1175 :
1176 : /* bail if the array is closed or we didn't get the , delimiter */
1177 0 : if (idx > end_idx) break;
1178 0 : if (str[idx] == ']') {
1179 0 : break;
1180 : }
1181 0 : else if (str[idx] != ',') {
1182 0 : raise_errmsg("Expecting , delimiter", pystr, idx);
1183 0 : goto bail;
1184 : }
1185 0 : idx++;
1186 :
1187 : /* skip whitespace after , */
1188 0 : while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
1189 : }
1190 : }
1191 :
1192 : /* verify that idx < end_idx, str[idx] should be ']' */
1193 0 : if (idx > end_idx || str[idx] != ']') {
1194 0 : raise_errmsg("Expecting object", pystr, end_idx);
1195 0 : goto bail;
1196 : }
1197 0 : *next_idx_ptr = idx + 1;
1198 0 : return rval;
1199 : bail:
1200 0 : Py_XDECREF(val);
1201 0 : Py_DECREF(rval);
1202 0 : return NULL;
1203 : }
1204 :
1205 : static PyObject *
1206 0 : _parse_array_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr) {
1207 : /* Read a JSON array from PyString pystr.
1208 : idx is the index of the first character after the opening brace.
1209 : *next_idx_ptr is a return-by-reference index to the first character after
1210 : the closing brace.
1211 :
1212 : Returns a new PyList
1213 : */
1214 0 : Py_UNICODE *str = PyUnicode_AS_UNICODE(pystr);
1215 0 : Py_ssize_t end_idx = PyUnicode_GET_SIZE(pystr) - 1;
1216 0 : PyObject *val = NULL;
1217 0 : PyObject *rval = PyList_New(0);
1218 : Py_ssize_t next_idx;
1219 0 : if (rval == NULL)
1220 0 : return NULL;
1221 :
1222 : /* skip whitespace after [ */
1223 0 : while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
1224 :
1225 : /* only loop if the array is non-empty */
1226 0 : if (idx <= end_idx && str[idx] != ']') {
1227 0 : while (idx <= end_idx) {
1228 :
1229 : /* read any JSON term */
1230 0 : val = scan_once_unicode(s, pystr, idx, &next_idx);
1231 0 : if (val == NULL)
1232 0 : goto bail;
1233 :
1234 0 : if (PyList_Append(rval, val) == -1)
1235 0 : goto bail;
1236 :
1237 0 : Py_CLEAR(val);
1238 0 : idx = next_idx;
1239 :
1240 : /* skip whitespace between term and , */
1241 0 : while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
1242 :
1243 : /* bail if the array is closed or we didn't get the , delimiter */
1244 0 : if (idx > end_idx) break;
1245 0 : if (str[idx] == ']') {
1246 0 : break;
1247 : }
1248 0 : else if (str[idx] != ',') {
1249 0 : raise_errmsg("Expecting ',' delimiter", pystr, idx);
1250 0 : goto bail;
1251 : }
1252 0 : idx++;
1253 :
1254 : /* skip whitespace after , */
1255 0 : while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
1256 : }
1257 : }
1258 :
1259 : /* verify that idx < end_idx, str[idx] should be ']' */
1260 0 : if (idx > end_idx || str[idx] != ']') {
1261 0 : raise_errmsg("Expecting object", pystr, end_idx);
1262 0 : goto bail;
1263 : }
1264 0 : *next_idx_ptr = idx + 1;
1265 0 : return rval;
1266 : bail:
1267 0 : Py_XDECREF(val);
1268 0 : Py_DECREF(rval);
1269 0 : return NULL;
1270 : }
1271 :
1272 : static PyObject *
1273 0 : _parse_constant(PyScannerObject *s, char *constant, Py_ssize_t idx, Py_ssize_t *next_idx_ptr) {
1274 : /* Read a JSON constant from PyString pystr.
1275 : constant is the constant string that was found
1276 : ("NaN", "Infinity", "-Infinity").
1277 : idx is the index of the first character of the constant
1278 : *next_idx_ptr is a return-by-reference index to the first character after
1279 : the constant.
1280 :
1281 : Returns the result of parse_constant
1282 : */
1283 : PyObject *cstr;
1284 : PyObject *rval;
1285 : /* constant is "NaN", "Infinity", or "-Infinity" */
1286 0 : cstr = PyString_InternFromString(constant);
1287 0 : if (cstr == NULL)
1288 0 : return NULL;
1289 :
1290 : /* rval = parse_constant(constant) */
1291 0 : rval = PyObject_CallFunctionObjArgs(s->parse_constant, cstr, NULL);
1292 0 : idx += PyString_GET_SIZE(cstr);
1293 0 : Py_DECREF(cstr);
1294 0 : *next_idx_ptr = idx;
1295 0 : return rval;
1296 : }
1297 :
1298 : static PyObject *
1299 0 : _match_number_str(PyScannerObject *s, PyObject *pystr, Py_ssize_t start, Py_ssize_t *next_idx_ptr) {
1300 : /* Read a JSON number from PyString pystr.
1301 : idx is the index of the first character of the number
1302 : *next_idx_ptr is a return-by-reference index to the first character after
1303 : the number.
1304 :
1305 : Returns a new PyObject representation of that number:
1306 : PyInt, PyLong, or PyFloat.
1307 : May return other types if parse_int or parse_float are set
1308 : */
1309 0 : char *str = PyString_AS_STRING(pystr);
1310 0 : Py_ssize_t end_idx = PyString_GET_SIZE(pystr) - 1;
1311 0 : Py_ssize_t idx = start;
1312 0 : int is_float = 0;
1313 : PyObject *rval;
1314 : PyObject *numstr;
1315 :
1316 : /* read a sign if it's there, make sure it's not the end of the string */
1317 0 : if (str[idx] == '-') {
1318 0 : idx++;
1319 0 : if (idx > end_idx) {
1320 0 : PyErr_SetNone(PyExc_StopIteration);
1321 0 : return NULL;
1322 : }
1323 : }
1324 :
1325 : /* read as many integer digits as we find as long as it doesn't start with 0 */
1326 0 : if (str[idx] >= '1' && str[idx] <= '9') {
1327 0 : idx++;
1328 0 : while (idx <= end_idx && str[idx] >= '0' && str[idx] <= '9') idx++;
1329 : }
1330 : /* if it starts with 0 we only expect one integer digit */
1331 0 : else if (str[idx] == '0') {
1332 0 : idx++;
1333 : }
1334 : /* no integer digits, error */
1335 : else {
1336 0 : PyErr_SetNone(PyExc_StopIteration);
1337 0 : return NULL;
1338 : }
1339 :
1340 : /* if the next char is '.' followed by a digit then read all float digits */
1341 0 : if (idx < end_idx && str[idx] == '.' && str[idx + 1] >= '0' && str[idx + 1] <= '9') {
1342 0 : is_float = 1;
1343 0 : idx += 2;
1344 0 : while (idx <= end_idx && str[idx] >= '0' && str[idx] <= '9') idx++;
1345 : }
1346 :
1347 : /* if the next char is 'e' or 'E' then maybe read the exponent (or backtrack) */
1348 0 : if (idx < end_idx && (str[idx] == 'e' || str[idx] == 'E')) {
1349 :
1350 : /* save the index of the 'e' or 'E' just in case we need to backtrack */
1351 0 : Py_ssize_t e_start = idx;
1352 0 : idx++;
1353 :
1354 : /* read an exponent sign if present */
1355 0 : if (idx < end_idx && (str[idx] == '-' || str[idx] == '+')) idx++;
1356 :
1357 : /* read all digits */
1358 0 : while (idx <= end_idx && str[idx] >= '0' && str[idx] <= '9') idx++;
1359 :
1360 : /* if we got a digit, then parse as float. if not, backtrack */
1361 0 : if (str[idx - 1] >= '0' && str[idx - 1] <= '9') {
1362 0 : is_float = 1;
1363 : }
1364 : else {
1365 0 : idx = e_start;
1366 : }
1367 : }
1368 :
1369 : /* copy the section we determined to be a number */
1370 0 : numstr = PyString_FromStringAndSize(&str[start], idx - start);
1371 0 : if (numstr == NULL)
1372 0 : return NULL;
1373 0 : if (is_float) {
1374 : /* parse as a float using a fast path if available, otherwise call user defined method */
1375 0 : if (s->parse_float != (PyObject *)&PyFloat_Type) {
1376 0 : rval = PyObject_CallFunctionObjArgs(s->parse_float, numstr, NULL);
1377 : }
1378 : else {
1379 0 : double d = PyOS_string_to_double(PyString_AS_STRING(numstr),
1380 : NULL, NULL);
1381 0 : if (d == -1.0 && PyErr_Occurred())
1382 0 : return NULL;
1383 0 : rval = PyFloat_FromDouble(d);
1384 : }
1385 : }
1386 : else {
1387 : /* parse as an int using a fast path if available, otherwise call user defined method */
1388 0 : if (s->parse_int != (PyObject *)&PyInt_Type) {
1389 0 : rval = PyObject_CallFunctionObjArgs(s->parse_int, numstr, NULL);
1390 : }
1391 : else {
1392 0 : rval = PyInt_FromString(PyString_AS_STRING(numstr), NULL, 10);
1393 : }
1394 : }
1395 0 : Py_DECREF(numstr);
1396 0 : *next_idx_ptr = idx;
1397 0 : return rval;
1398 : }
1399 :
1400 : static PyObject *
1401 0 : _match_number_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t start, Py_ssize_t *next_idx_ptr) {
1402 : /* Read a JSON number from PyUnicode pystr.
1403 : idx is the index of the first character of the number
1404 : *next_idx_ptr is a return-by-reference index to the first character after
1405 : the number.
1406 :
1407 : Returns a new PyObject representation of that number:
1408 : PyInt, PyLong, or PyFloat.
1409 : May return other types if parse_int or parse_float are set
1410 : */
1411 0 : Py_UNICODE *str = PyUnicode_AS_UNICODE(pystr);
1412 0 : Py_ssize_t end_idx = PyUnicode_GET_SIZE(pystr) - 1;
1413 0 : Py_ssize_t idx = start;
1414 0 : int is_float = 0;
1415 : PyObject *rval;
1416 : PyObject *numstr;
1417 :
1418 : /* read a sign if it's there, make sure it's not the end of the string */
1419 0 : if (str[idx] == '-') {
1420 0 : idx++;
1421 0 : if (idx > end_idx) {
1422 0 : PyErr_SetNone(PyExc_StopIteration);
1423 0 : return NULL;
1424 : }
1425 : }
1426 :
1427 : /* read as many integer digits as we find as long as it doesn't start with 0 */
1428 0 : if (str[idx] >= '1' && str[idx] <= '9') {
1429 0 : idx++;
1430 0 : while (idx <= end_idx && str[idx] >= '0' && str[idx] <= '9') idx++;
1431 : }
1432 : /* if it starts with 0 we only expect one integer digit */
1433 0 : else if (str[idx] == '0') {
1434 0 : idx++;
1435 : }
1436 : /* no integer digits, error */
1437 : else {
1438 0 : PyErr_SetNone(PyExc_StopIteration);
1439 0 : return NULL;
1440 : }
1441 :
1442 : /* if the next char is '.' followed by a digit then read all float digits */
1443 0 : if (idx < end_idx && str[idx] == '.' && str[idx + 1] >= '0' && str[idx + 1] <= '9') {
1444 0 : is_float = 1;
1445 0 : idx += 2;
1446 0 : while (idx <= end_idx && str[idx] >= '0' && str[idx] <= '9') idx++;
1447 : }
1448 :
1449 : /* if the next char is 'e' or 'E' then maybe read the exponent (or backtrack) */
1450 0 : if (idx < end_idx && (str[idx] == 'e' || str[idx] == 'E')) {
1451 0 : Py_ssize_t e_start = idx;
1452 0 : idx++;
1453 :
1454 : /* read an exponent sign if present */
1455 0 : if (idx < end_idx && (str[idx] == '-' || str[idx] == '+')) idx++;
1456 :
1457 : /* read all digits */
1458 0 : while (idx <= end_idx && str[idx] >= '0' && str[idx] <= '9') idx++;
1459 :
1460 : /* if we got a digit, then parse as float. if not, backtrack */
1461 0 : if (str[idx - 1] >= '0' && str[idx - 1] <= '9') {
1462 0 : is_float = 1;
1463 : }
1464 : else {
1465 0 : idx = e_start;
1466 : }
1467 : }
1468 :
1469 : /* copy the section we determined to be a number */
1470 0 : numstr = PyUnicode_FromUnicode(&str[start], idx - start);
1471 0 : if (numstr == NULL)
1472 0 : return NULL;
1473 0 : if (is_float) {
1474 : /* parse as a float using a fast path if available, otherwise call user defined method */
1475 0 : if (s->parse_float != (PyObject *)&PyFloat_Type) {
1476 0 : rval = PyObject_CallFunctionObjArgs(s->parse_float, numstr, NULL);
1477 : }
1478 : else {
1479 0 : rval = PyFloat_FromString(numstr, NULL);
1480 : }
1481 : }
1482 : else {
1483 : /* no fast path for unicode -> int, just call */
1484 0 : rval = PyObject_CallFunctionObjArgs(s->parse_int, numstr, NULL);
1485 : }
1486 0 : Py_DECREF(numstr);
1487 0 : *next_idx_ptr = idx;
1488 0 : return rval;
1489 : }
1490 :
1491 : static PyObject *
1492 0 : scan_once_str(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr)
1493 : {
1494 : /* Read one JSON term (of any kind) from PyString pystr.
1495 : idx is the index of the first character of the term
1496 : *next_idx_ptr is a return-by-reference index to the first character after
1497 : the number.
1498 :
1499 : Returns a new PyObject representation of the term.
1500 : */
1501 : PyObject *res;
1502 : int strict;
1503 0 : char *str = PyString_AS_STRING(pystr);
1504 0 : Py_ssize_t length = PyString_GET_SIZE(pystr);
1505 0 : if (idx < 0) {
1506 0 : PyErr_SetString(PyExc_ValueError, "idx cannot be negative");
1507 0 : return NULL;
1508 : }
1509 0 : if (idx >= length) {
1510 0 : PyErr_SetNone(PyExc_StopIteration);
1511 0 : return NULL;
1512 : }
1513 0 : switch (str[idx]) {
1514 : case '"':
1515 : /* string */
1516 0 : strict = PyObject_IsTrue(s->strict);
1517 0 : if (strict < 0)
1518 0 : return NULL;
1519 0 : return scanstring_str(pystr, idx + 1,
1520 0 : PyString_AS_STRING(s->encoding), strict, next_idx_ptr);
1521 : case '{':
1522 : /* object */
1523 0 : if (Py_EnterRecursiveCall(" while decoding a JSON object "
1524 : "from a byte string"))
1525 0 : return NULL;
1526 0 : res = _parse_object_str(s, pystr, idx + 1, next_idx_ptr);
1527 0 : Py_LeaveRecursiveCall();
1528 0 : return res;
1529 : case '[':
1530 : /* array */
1531 0 : if (Py_EnterRecursiveCall(" while decoding a JSON array "
1532 : "from a byte string"))
1533 0 : return NULL;
1534 0 : res = _parse_array_str(s, pystr, idx + 1, next_idx_ptr);
1535 0 : Py_LeaveRecursiveCall();
1536 0 : return res;
1537 : case 'n':
1538 : /* null */
1539 0 : if ((idx + 3 < length) && str[idx + 1] == 'u' && str[idx + 2] == 'l' && str[idx + 3] == 'l') {
1540 0 : Py_INCREF(Py_None);
1541 0 : *next_idx_ptr = idx + 4;
1542 0 : return Py_None;
1543 : }
1544 0 : break;
1545 : case 't':
1546 : /* true */
1547 0 : if ((idx + 3 < length) && str[idx + 1] == 'r' && str[idx + 2] == 'u' && str[idx + 3] == 'e') {
1548 0 : Py_INCREF(Py_True);
1549 0 : *next_idx_ptr = idx + 4;
1550 0 : return Py_True;
1551 : }
1552 0 : break;
1553 : case 'f':
1554 : /* false */
1555 0 : if ((idx + 4 < length) && str[idx + 1] == 'a' && str[idx + 2] == 'l' && str[idx + 3] == 's' && str[idx + 4] == 'e') {
1556 0 : Py_INCREF(Py_False);
1557 0 : *next_idx_ptr = idx + 5;
1558 0 : return Py_False;
1559 : }
1560 0 : break;
1561 : case 'N':
1562 : /* NaN */
1563 0 : if ((idx + 2 < length) && str[idx + 1] == 'a' && str[idx + 2] == 'N') {
1564 0 : return _parse_constant(s, "NaN", idx, next_idx_ptr);
1565 : }
1566 0 : break;
1567 : case 'I':
1568 : /* Infinity */
1569 0 : if ((idx + 7 < length) && str[idx + 1] == 'n' && str[idx + 2] == 'f' && str[idx + 3] == 'i' && str[idx + 4] == 'n' && str[idx + 5] == 'i' && str[idx + 6] == 't' && str[idx + 7] == 'y') {
1570 0 : return _parse_constant(s, "Infinity", idx, next_idx_ptr);
1571 : }
1572 0 : break;
1573 : case '-':
1574 : /* -Infinity */
1575 0 : if ((idx + 8 < length) && str[idx + 1] == 'I' && str[idx + 2] == 'n' && str[idx + 3] == 'f' && str[idx + 4] == 'i' && str[idx + 5] == 'n' && str[idx + 6] == 'i' && str[idx + 7] == 't' && str[idx + 8] == 'y') {
1576 0 : return _parse_constant(s, "-Infinity", idx, next_idx_ptr);
1577 : }
1578 0 : break;
1579 : }
1580 : /* Didn't find a string, object, array, or named constant. Look for a number. */
1581 0 : return _match_number_str(s, pystr, idx, next_idx_ptr);
1582 : }
1583 :
1584 : static PyObject *
1585 0 : scan_once_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr)
1586 : {
1587 : /* Read one JSON term (of any kind) from PyUnicode pystr.
1588 : idx is the index of the first character of the term
1589 : *next_idx_ptr is a return-by-reference index to the first character after
1590 : the number.
1591 :
1592 : Returns a new PyObject representation of the term.
1593 : */
1594 : PyObject *res;
1595 : int strict;
1596 0 : Py_UNICODE *str = PyUnicode_AS_UNICODE(pystr);
1597 0 : Py_ssize_t length = PyUnicode_GET_SIZE(pystr);
1598 0 : if (idx < 0) {
1599 0 : PyErr_SetString(PyExc_ValueError, "idx cannot be negative");
1600 0 : return NULL;
1601 : }
1602 0 : if (idx >= length) {
1603 0 : PyErr_SetNone(PyExc_StopIteration);
1604 0 : return NULL;
1605 : }
1606 0 : switch (str[idx]) {
1607 : case '"':
1608 : /* string */
1609 0 : strict = PyObject_IsTrue(s->strict);
1610 0 : if (strict < 0)
1611 0 : return NULL;
1612 0 : return scanstring_unicode(pystr, idx + 1, strict, next_idx_ptr);
1613 : case '{':
1614 : /* object */
1615 0 : if (Py_EnterRecursiveCall(" while decoding a JSON object "
1616 : "from a unicode string"))
1617 0 : return NULL;
1618 0 : res = _parse_object_unicode(s, pystr, idx + 1, next_idx_ptr);
1619 0 : Py_LeaveRecursiveCall();
1620 0 : return res;
1621 : case '[':
1622 : /* array */
1623 0 : if (Py_EnterRecursiveCall(" while decoding a JSON array "
1624 : "from a unicode string"))
1625 0 : return NULL;
1626 0 : res = _parse_array_unicode(s, pystr, idx + 1, next_idx_ptr);
1627 0 : Py_LeaveRecursiveCall();
1628 0 : return res;
1629 : case 'n':
1630 : /* null */
1631 0 : if ((idx + 3 < length) && str[idx + 1] == 'u' && str[idx + 2] == 'l' && str[idx + 3] == 'l') {
1632 0 : Py_INCREF(Py_None);
1633 0 : *next_idx_ptr = idx + 4;
1634 0 : return Py_None;
1635 : }
1636 0 : break;
1637 : case 't':
1638 : /* true */
1639 0 : if ((idx + 3 < length) && str[idx + 1] == 'r' && str[idx + 2] == 'u' && str[idx + 3] == 'e') {
1640 0 : Py_INCREF(Py_True);
1641 0 : *next_idx_ptr = idx + 4;
1642 0 : return Py_True;
1643 : }
1644 0 : break;
1645 : case 'f':
1646 : /* false */
1647 0 : if ((idx + 4 < length) && str[idx + 1] == 'a' && str[idx + 2] == 'l' && str[idx + 3] == 's' && str[idx + 4] == 'e') {
1648 0 : Py_INCREF(Py_False);
1649 0 : *next_idx_ptr = idx + 5;
1650 0 : return Py_False;
1651 : }
1652 0 : break;
1653 : case 'N':
1654 : /* NaN */
1655 0 : if ((idx + 2 < length) && str[idx + 1] == 'a' && str[idx + 2] == 'N') {
1656 0 : return _parse_constant(s, "NaN", idx, next_idx_ptr);
1657 : }
1658 0 : break;
1659 : case 'I':
1660 : /* Infinity */
1661 0 : if ((idx + 7 < length) && str[idx + 1] == 'n' && str[idx + 2] == 'f' && str[idx + 3] == 'i' && str[idx + 4] == 'n' && str[idx + 5] == 'i' && str[idx + 6] == 't' && str[idx + 7] == 'y') {
1662 0 : return _parse_constant(s, "Infinity", idx, next_idx_ptr);
1663 : }
1664 0 : break;
1665 : case '-':
1666 : /* -Infinity */
1667 0 : if ((idx + 8 < length) && str[idx + 1] == 'I' && str[idx + 2] == 'n' && str[idx + 3] == 'f' && str[idx + 4] == 'i' && str[idx + 5] == 'n' && str[idx + 6] == 'i' && str[idx + 7] == 't' && str[idx + 8] == 'y') {
1668 0 : return _parse_constant(s, "-Infinity", idx, next_idx_ptr);
1669 : }
1670 0 : break;
1671 : }
1672 : /* Didn't find a string, object, array, or named constant. Look for a number. */
1673 0 : return _match_number_unicode(s, pystr, idx, next_idx_ptr);
1674 : }
1675 :
1676 : static PyObject *
1677 0 : scanner_call(PyObject *self, PyObject *args, PyObject *kwds)
1678 : {
1679 : /* Python callable interface to scan_once_{str,unicode} */
1680 : PyObject *pystr;
1681 : PyObject *rval;
1682 : Py_ssize_t idx;
1683 0 : Py_ssize_t next_idx = -1;
1684 : static char *kwlist[] = {"string", "idx", NULL};
1685 : PyScannerObject *s;
1686 : assert(PyScanner_Check(self));
1687 0 : s = (PyScannerObject *)self;
1688 0 : if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO&:scan_once", kwlist, &pystr, _convertPyInt_AsSsize_t, &idx))
1689 0 : return NULL;
1690 :
1691 0 : if (PyString_Check(pystr)) {
1692 0 : rval = scan_once_str(s, pystr, idx, &next_idx);
1693 : }
1694 0 : else if (PyUnicode_Check(pystr)) {
1695 0 : rval = scan_once_unicode(s, pystr, idx, &next_idx);
1696 : }
1697 : else {
1698 0 : PyErr_Format(PyExc_TypeError,
1699 : "first argument must be a string, not %.80s",
1700 0 : Py_TYPE(pystr)->tp_name);
1701 0 : return NULL;
1702 : }
1703 0 : return _build_rval_index_tuple(rval, next_idx);
1704 : }
1705 :
1706 : static PyObject *
1707 0 : scanner_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1708 : {
1709 : PyScannerObject *s;
1710 0 : s = (PyScannerObject *)type->tp_alloc(type, 0);
1711 0 : if (s != NULL) {
1712 0 : s->encoding = NULL;
1713 0 : s->strict = NULL;
1714 0 : s->object_hook = NULL;
1715 0 : s->pairs_hook = NULL;
1716 0 : s->parse_float = NULL;
1717 0 : s->parse_int = NULL;
1718 0 : s->parse_constant = NULL;
1719 : }
1720 0 : return (PyObject *)s;
1721 : }
1722 :
1723 : static int
1724 3 : scanner_init(PyObject *self, PyObject *args, PyObject *kwds)
1725 : {
1726 : /* Initialize Scanner object */
1727 : PyObject *ctx;
1728 : static char *kwlist[] = {"context", NULL};
1729 : PyScannerObject *s;
1730 :
1731 : assert(PyScanner_Check(self));
1732 3 : s = (PyScannerObject *)self;
1733 :
1734 3 : if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:make_scanner", kwlist, &ctx))
1735 0 : return -1;
1736 :
1737 : /* PyString_AS_STRING is used on encoding */
1738 3 : s->encoding = PyObject_GetAttrString(ctx, "encoding");
1739 3 : if (s->encoding == NULL)
1740 0 : goto bail;
1741 3 : if (s->encoding == Py_None) {
1742 3 : Py_DECREF(Py_None);
1743 3 : s->encoding = PyString_InternFromString(DEFAULT_ENCODING);
1744 : }
1745 0 : else if (PyUnicode_Check(s->encoding)) {
1746 0 : PyObject *tmp = PyUnicode_AsEncodedString(s->encoding, NULL, NULL);
1747 0 : Py_SETREF(s->encoding, tmp);
1748 : }
1749 3 : if (s->encoding == NULL)
1750 0 : goto bail;
1751 3 : if (!PyString_Check(s->encoding)) {
1752 0 : PyErr_Format(PyExc_TypeError,
1753 : "encoding must be a string, not %.80s",
1754 0 : Py_TYPE(s->encoding)->tp_name);
1755 0 : goto bail;
1756 : }
1757 :
1758 :
1759 : /* All of these will fail "gracefully" so we don't need to verify them */
1760 3 : s->strict = PyObject_GetAttrString(ctx, "strict");
1761 3 : if (s->strict == NULL)
1762 0 : goto bail;
1763 3 : s->object_hook = PyObject_GetAttrString(ctx, "object_hook");
1764 3 : if (s->object_hook == NULL)
1765 0 : goto bail;
1766 3 : s->pairs_hook = PyObject_GetAttrString(ctx, "object_pairs_hook");
1767 3 : if (s->pairs_hook == NULL)
1768 0 : goto bail;
1769 3 : s->parse_float = PyObject_GetAttrString(ctx, "parse_float");
1770 3 : if (s->parse_float == NULL)
1771 0 : goto bail;
1772 3 : s->parse_int = PyObject_GetAttrString(ctx, "parse_int");
1773 3 : if (s->parse_int == NULL)
1774 0 : goto bail;
1775 3 : s->parse_constant = PyObject_GetAttrString(ctx, "parse_constant");
1776 3 : if (s->parse_constant == NULL)
1777 0 : goto bail;
1778 :
1779 3 : return 0;
1780 :
1781 : bail:
1782 0 : Py_CLEAR(s->encoding);
1783 0 : Py_CLEAR(s->strict);
1784 0 : Py_CLEAR(s->object_hook);
1785 0 : Py_CLEAR(s->pairs_hook);
1786 0 : Py_CLEAR(s->parse_float);
1787 0 : Py_CLEAR(s->parse_int);
1788 0 : Py_CLEAR(s->parse_constant);
1789 0 : return -1;
1790 : }
1791 :
1792 : PyDoc_STRVAR(scanner_doc, "JSON scanner object");
1793 :
1794 : static
1795 : PyTypeObject PyScannerType = {
1796 : PyObject_HEAD_INIT(NULL)
1797 : 0, /* tp_internal */
1798 : "_json.Scanner", /* tp_name */
1799 : sizeof(PyScannerObject), /* tp_basicsize */
1800 : 0, /* tp_itemsize */
1801 : scanner_dealloc, /* tp_dealloc */
1802 : 0, /* tp_print */
1803 : 0, /* tp_getattr */
1804 : 0, /* tp_setattr */
1805 : 0, /* tp_compare */
1806 : 0, /* tp_repr */
1807 : 0, /* tp_as_number */
1808 : 0, /* tp_as_sequence */
1809 : 0, /* tp_as_mapping */
1810 : 0, /* tp_hash */
1811 : scanner_call, /* tp_call */
1812 : 0, /* tp_str */
1813 : 0,/* PyObject_GenericGetAttr, */ /* tp_getattro */
1814 : 0,/* PyObject_GenericSetAttr, */ /* tp_setattro */
1815 : 0, /* tp_as_buffer */
1816 : Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
1817 : scanner_doc, /* tp_doc */
1818 : scanner_traverse, /* tp_traverse */
1819 : scanner_clear, /* tp_clear */
1820 : 0, /* tp_richcompare */
1821 : 0, /* tp_weaklistoffset */
1822 : 0, /* tp_iter */
1823 : 0, /* tp_iternext */
1824 : 0, /* tp_methods */
1825 : scanner_members, /* tp_members */
1826 : 0, /* tp_getset */
1827 : 0, /* tp_base */
1828 : 0, /* tp_dict */
1829 : 0, /* tp_descr_get */
1830 : 0, /* tp_descr_set */
1831 : 0, /* tp_dictoffset */
1832 : scanner_init, /* tp_init */
1833 : 0,/* PyType_GenericAlloc, */ /* tp_alloc */
1834 : scanner_new, /* tp_new */
1835 : 0,/* PyObject_GC_Del, */ /* tp_free */
1836 : };
1837 :
1838 : static PyObject *
1839 0 : encoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1840 : {
1841 : PyEncoderObject *s;
1842 0 : s = (PyEncoderObject *)type->tp_alloc(type, 0);
1843 0 : if (s != NULL) {
1844 0 : s->markers = NULL;
1845 0 : s->defaultfn = NULL;
1846 0 : s->encoder = NULL;
1847 0 : s->indent = NULL;
1848 0 : s->key_separator = NULL;
1849 0 : s->item_separator = NULL;
1850 0 : s->sort_keys = NULL;
1851 0 : s->skipkeys = NULL;
1852 : }
1853 0 : return (PyObject *)s;
1854 : }
1855 :
1856 : static int
1857 0 : encoder_init(PyObject *self, PyObject *args, PyObject *kwds)
1858 : {
1859 : /* initialize Encoder object */
1860 : static char *kwlist[] = {"markers", "default", "encoder", "indent", "key_separator", "item_separator", "sort_keys", "skipkeys", "allow_nan", NULL};
1861 :
1862 : PyEncoderObject *s;
1863 : PyObject *markers, *defaultfn, *encoder, *indent, *key_separator;
1864 : PyObject *item_separator, *sort_keys, *skipkeys, *allow_nan_obj;
1865 : int allow_nan;
1866 :
1867 : assert(PyEncoder_Check(self));
1868 0 : s = (PyEncoderObject *)self;
1869 :
1870 0 : if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOOOOOOOO:make_encoder", kwlist,
1871 : &markers, &defaultfn, &encoder, &indent, &key_separator, &item_separator,
1872 : &sort_keys, &skipkeys, &allow_nan_obj))
1873 0 : return -1;
1874 :
1875 0 : allow_nan = PyObject_IsTrue(allow_nan_obj);
1876 0 : if (allow_nan < 0)
1877 0 : return -1;
1878 :
1879 0 : if (markers != Py_None && !PyDict_Check(markers)) {
1880 0 : PyErr_Format(PyExc_TypeError,
1881 : "make_encoder() argument 1 must be dict or None, "
1882 0 : "not %.200s", Py_TYPE(markers)->tp_name);
1883 0 : return -1;
1884 : }
1885 :
1886 0 : s->markers = markers;
1887 0 : s->defaultfn = defaultfn;
1888 0 : s->encoder = encoder;
1889 0 : s->indent = indent;
1890 0 : s->key_separator = key_separator;
1891 0 : s->item_separator = item_separator;
1892 0 : s->sort_keys = sort_keys;
1893 0 : s->skipkeys = skipkeys;
1894 0 : s->fast_encode = (PyCFunction_Check(s->encoder) && PyCFunction_GetFunction(s->encoder) == (PyCFunction)py_encode_basestring_ascii);
1895 0 : s->allow_nan = allow_nan;
1896 :
1897 0 : Py_INCREF(s->markers);
1898 0 : Py_INCREF(s->defaultfn);
1899 0 : Py_INCREF(s->encoder);
1900 0 : Py_INCREF(s->indent);
1901 0 : Py_INCREF(s->key_separator);
1902 0 : Py_INCREF(s->item_separator);
1903 0 : Py_INCREF(s->sort_keys);
1904 0 : Py_INCREF(s->skipkeys);
1905 0 : return 0;
1906 : }
1907 :
1908 : static PyObject *
1909 0 : encoder_call(PyObject *self, PyObject *args, PyObject *kwds)
1910 : {
1911 : /* Python callable interface to encode_listencode_obj */
1912 : static char *kwlist[] = {"obj", "_current_indent_level", NULL};
1913 : PyObject *obj;
1914 : PyObject *rval;
1915 : Py_ssize_t indent_level;
1916 : PyEncoderObject *s;
1917 : assert(PyEncoder_Check(self));
1918 0 : s = (PyEncoderObject *)self;
1919 0 : if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO&:_iterencode", kwlist,
1920 : &obj, _convertPyInt_AsSsize_t, &indent_level))
1921 0 : return NULL;
1922 0 : rval = PyList_New(0);
1923 0 : if (rval == NULL)
1924 0 : return NULL;
1925 0 : if (encoder_listencode_obj(s, rval, obj, indent_level)) {
1926 0 : Py_DECREF(rval);
1927 0 : return NULL;
1928 : }
1929 0 : return rval;
1930 : }
1931 :
1932 : static PyObject *
1933 0 : _encoded_const(PyObject *obj)
1934 : {
1935 : /* Return the JSON string representation of None, True, False */
1936 0 : if (obj == Py_None) {
1937 : static PyObject *s_null = NULL;
1938 0 : if (s_null == NULL) {
1939 0 : s_null = PyString_InternFromString("null");
1940 : }
1941 0 : Py_INCREF(s_null);
1942 0 : return s_null;
1943 : }
1944 0 : else if (obj == Py_True) {
1945 : static PyObject *s_true = NULL;
1946 0 : if (s_true == NULL) {
1947 0 : s_true = PyString_InternFromString("true");
1948 : }
1949 0 : Py_INCREF(s_true);
1950 0 : return s_true;
1951 : }
1952 0 : else if (obj == Py_False) {
1953 : static PyObject *s_false = NULL;
1954 0 : if (s_false == NULL) {
1955 0 : s_false = PyString_InternFromString("false");
1956 : }
1957 0 : Py_INCREF(s_false);
1958 0 : return s_false;
1959 : }
1960 : else {
1961 0 : PyErr_SetString(PyExc_ValueError, "not a const");
1962 0 : return NULL;
1963 : }
1964 : }
1965 :
1966 : static PyObject *
1967 0 : encoder_encode_float(PyEncoderObject *s, PyObject *obj)
1968 : {
1969 : /* Return the JSON representation of a PyFloat */
1970 0 : double i = PyFloat_AS_DOUBLE(obj);
1971 0 : if (!Py_IS_FINITE(i)) {
1972 0 : if (!s->allow_nan) {
1973 0 : PyErr_SetString(PyExc_ValueError, "Out of range float values are not JSON compliant");
1974 0 : return NULL;
1975 : }
1976 0 : if (i > 0) {
1977 0 : return PyString_FromString("Infinity");
1978 : }
1979 0 : else if (i < 0) {
1980 0 : return PyString_FromString("-Infinity");
1981 : }
1982 : else {
1983 0 : return PyString_FromString("NaN");
1984 : }
1985 : }
1986 : /* Make sure to use the base float class repr method */
1987 0 : return PyFloat_Type.tp_repr(obj);
1988 : }
1989 :
1990 : static PyObject *
1991 0 : encoder_encode_string(PyEncoderObject *s, PyObject *obj)
1992 : {
1993 : /* Return the JSON representation of a string */
1994 0 : if (s->fast_encode)
1995 0 : return py_encode_basestring_ascii(NULL, obj);
1996 : else
1997 0 : return PyObject_CallFunctionObjArgs(s->encoder, obj, NULL);
1998 : }
1999 :
2000 : static int
2001 0 : _steal_list_append(PyObject *lst, PyObject *stolen)
2002 : {
2003 : /* Append stolen and then decrement its reference count */
2004 0 : int rval = PyList_Append(lst, stolen);
2005 0 : Py_DECREF(stolen);
2006 0 : return rval;
2007 : }
2008 :
2009 : static int
2010 0 : encoder_listencode_obj(PyEncoderObject *s, PyObject *rval, PyObject *obj, Py_ssize_t indent_level)
2011 : {
2012 : /* Encode Python object obj to a JSON term, rval is a PyList */
2013 : PyObject *newobj;
2014 : int rv;
2015 :
2016 0 : if (obj == Py_None || obj == Py_True || obj == Py_False) {
2017 0 : PyObject *cstr = _encoded_const(obj);
2018 0 : if (cstr == NULL)
2019 0 : return -1;
2020 0 : return _steal_list_append(rval, cstr);
2021 : }
2022 0 : else if (PyString_Check(obj) || PyUnicode_Check(obj))
2023 : {
2024 0 : PyObject *encoded = encoder_encode_string(s, obj);
2025 0 : if (encoded == NULL)
2026 0 : return -1;
2027 0 : return _steal_list_append(rval, encoded);
2028 : }
2029 0 : else if (PyInt_Check(obj) || PyLong_Check(obj)) {
2030 0 : PyObject *encoded = PyObject_Str(obj);
2031 0 : if (encoded == NULL)
2032 0 : return -1;
2033 0 : return _steal_list_append(rval, encoded);
2034 : }
2035 0 : else if (PyFloat_Check(obj)) {
2036 0 : PyObject *encoded = encoder_encode_float(s, obj);
2037 0 : if (encoded == NULL)
2038 0 : return -1;
2039 0 : return _steal_list_append(rval, encoded);
2040 : }
2041 0 : else if (PyList_Check(obj) || PyTuple_Check(obj)) {
2042 0 : if (Py_EnterRecursiveCall(" while encoding a JSON object"))
2043 0 : return -1;
2044 0 : rv = encoder_listencode_list(s, rval, obj, indent_level);
2045 0 : Py_LeaveRecursiveCall();
2046 0 : return rv;
2047 : }
2048 0 : else if (PyDict_Check(obj)) {
2049 0 : if (Py_EnterRecursiveCall(" while encoding a JSON object"))
2050 0 : return -1;
2051 0 : rv = encoder_listencode_dict(s, rval, obj, indent_level);
2052 0 : Py_LeaveRecursiveCall();
2053 0 : return rv;
2054 : }
2055 : else {
2056 0 : PyObject *ident = NULL;
2057 0 : if (s->markers != Py_None) {
2058 : int has_key;
2059 0 : ident = PyLong_FromVoidPtr(obj);
2060 0 : if (ident == NULL)
2061 0 : return -1;
2062 0 : has_key = PyDict_Contains(s->markers, ident);
2063 0 : if (has_key) {
2064 0 : if (has_key != -1)
2065 0 : PyErr_SetString(PyExc_ValueError, "Circular reference detected");
2066 0 : Py_DECREF(ident);
2067 0 : return -1;
2068 : }
2069 0 : if (PyDict_SetItem(s->markers, ident, obj)) {
2070 0 : Py_DECREF(ident);
2071 0 : return -1;
2072 : }
2073 : }
2074 0 : newobj = PyObject_CallFunctionObjArgs(s->defaultfn, obj, NULL);
2075 0 : if (newobj == NULL) {
2076 0 : Py_XDECREF(ident);
2077 0 : return -1;
2078 : }
2079 :
2080 0 : if (Py_EnterRecursiveCall(" while encoding a JSON object"))
2081 0 : return -1;
2082 0 : rv = encoder_listencode_obj(s, rval, newobj, indent_level);
2083 0 : Py_LeaveRecursiveCall();
2084 :
2085 0 : Py_DECREF(newobj);
2086 0 : if (rv) {
2087 0 : Py_XDECREF(ident);
2088 0 : return -1;
2089 : }
2090 0 : if (ident != NULL) {
2091 0 : if (PyDict_DelItem(s->markers, ident)) {
2092 0 : Py_XDECREF(ident);
2093 0 : return -1;
2094 : }
2095 0 : Py_XDECREF(ident);
2096 : }
2097 0 : return rv;
2098 : }
2099 : }
2100 :
2101 : static int
2102 0 : encoder_listencode_dict(PyEncoderObject *s, PyObject *rval, PyObject *dct, Py_ssize_t indent_level)
2103 : {
2104 : /* Encode Python dict dct a JSON term, rval is a PyList */
2105 : static PyObject *open_dict = NULL;
2106 : static PyObject *close_dict = NULL;
2107 : static PyObject *empty_dict = NULL;
2108 0 : PyObject *kstr = NULL;
2109 0 : PyObject *ident = NULL;
2110 0 : PyObject *key = NULL;
2111 0 : PyObject *value = NULL;
2112 0 : PyObject *it = NULL;
2113 : int skipkeys;
2114 : Py_ssize_t idx;
2115 :
2116 0 : if (open_dict == NULL || close_dict == NULL || empty_dict == NULL) {
2117 0 : open_dict = PyString_InternFromString("{");
2118 0 : close_dict = PyString_InternFromString("}");
2119 0 : empty_dict = PyString_InternFromString("{}");
2120 0 : if (open_dict == NULL || close_dict == NULL || empty_dict == NULL)
2121 0 : return -1;
2122 : }
2123 0 : if (Py_SIZE(dct) == 0)
2124 0 : return PyList_Append(rval, empty_dict);
2125 :
2126 0 : if (s->markers != Py_None) {
2127 : int has_key;
2128 0 : ident = PyLong_FromVoidPtr(dct);
2129 0 : if (ident == NULL)
2130 0 : goto bail;
2131 0 : has_key = PyDict_Contains(s->markers, ident);
2132 0 : if (has_key) {
2133 0 : if (has_key != -1)
2134 0 : PyErr_SetString(PyExc_ValueError, "Circular reference detected");
2135 0 : goto bail;
2136 : }
2137 0 : if (PyDict_SetItem(s->markers, ident, dct)) {
2138 0 : goto bail;
2139 : }
2140 : }
2141 :
2142 0 : if (PyList_Append(rval, open_dict))
2143 0 : goto bail;
2144 :
2145 0 : if (s->indent != Py_None) {
2146 : /* TODO: DOES NOT RUN */
2147 0 : indent_level += 1;
2148 : /*
2149 : newline_indent = '\n' + (' ' * (_indent * _current_indent_level))
2150 : separator = _item_separator + newline_indent
2151 : buf += newline_indent
2152 : */
2153 : }
2154 :
2155 : /* TODO: C speedup not implemented for sort_keys */
2156 :
2157 0 : it = PyObject_GetIter(dct);
2158 0 : if (it == NULL)
2159 0 : goto bail;
2160 0 : skipkeys = PyObject_IsTrue(s->skipkeys);
2161 0 : if (skipkeys < 0)
2162 0 : goto bail;
2163 0 : idx = 0;
2164 0 : while ((key = PyIter_Next(it)) != NULL) {
2165 : PyObject *encoded;
2166 :
2167 0 : if (PyString_Check(key) || PyUnicode_Check(key)) {
2168 0 : Py_INCREF(key);
2169 0 : kstr = key;
2170 : }
2171 0 : else if (PyFloat_Check(key)) {
2172 0 : kstr = encoder_encode_float(s, key);
2173 0 : if (kstr == NULL)
2174 0 : goto bail;
2175 : }
2176 0 : else if (PyInt_Check(key) || PyLong_Check(key)) {
2177 0 : kstr = PyObject_Str(key);
2178 0 : if (kstr == NULL)
2179 0 : goto bail;
2180 : }
2181 0 : else if (key == Py_True || key == Py_False || key == Py_None) {
2182 0 : kstr = _encoded_const(key);
2183 0 : if (kstr == NULL)
2184 0 : goto bail;
2185 : }
2186 0 : else if (skipkeys) {
2187 0 : Py_DECREF(key);
2188 0 : continue;
2189 : }
2190 : else {
2191 : /* TODO: include repr of key */
2192 0 : PyErr_SetString(PyExc_TypeError, "keys must be a string");
2193 0 : goto bail;
2194 : }
2195 :
2196 0 : if (idx) {
2197 0 : if (PyList_Append(rval, s->item_separator))
2198 0 : goto bail;
2199 : }
2200 :
2201 0 : value = PyObject_GetItem(dct, key);
2202 0 : if (value == NULL)
2203 0 : goto bail;
2204 :
2205 0 : encoded = encoder_encode_string(s, kstr);
2206 0 : Py_CLEAR(kstr);
2207 0 : if (encoded == NULL)
2208 0 : goto bail;
2209 0 : if (PyList_Append(rval, encoded)) {
2210 0 : Py_DECREF(encoded);
2211 0 : goto bail;
2212 : }
2213 0 : Py_DECREF(encoded);
2214 0 : if (PyList_Append(rval, s->key_separator))
2215 0 : goto bail;
2216 0 : if (encoder_listencode_obj(s, rval, value, indent_level))
2217 0 : goto bail;
2218 0 : idx += 1;
2219 0 : Py_CLEAR(value);
2220 0 : Py_DECREF(key);
2221 : }
2222 0 : if (PyErr_Occurred())
2223 0 : goto bail;
2224 0 : Py_CLEAR(it);
2225 :
2226 0 : if (ident != NULL) {
2227 0 : if (PyDict_DelItem(s->markers, ident))
2228 0 : goto bail;
2229 0 : Py_CLEAR(ident);
2230 : }
2231 0 : if (s->indent != Py_None) {
2232 : /* TODO: DOES NOT RUN */
2233 : /*
2234 : indent_level -= 1;
2235 :
2236 : yield '\n' + (' ' * (_indent * _current_indent_level))
2237 : */
2238 : }
2239 0 : if (PyList_Append(rval, close_dict))
2240 0 : goto bail;
2241 0 : return 0;
2242 :
2243 : bail:
2244 0 : Py_XDECREF(it);
2245 0 : Py_XDECREF(key);
2246 0 : Py_XDECREF(value);
2247 0 : Py_XDECREF(kstr);
2248 0 : Py_XDECREF(ident);
2249 0 : return -1;
2250 : }
2251 :
2252 :
2253 : static int
2254 0 : encoder_listencode_list(PyEncoderObject *s, PyObject *rval, PyObject *seq, Py_ssize_t indent_level)
2255 : {
2256 : /* Encode Python list seq to a JSON term, rval is a PyList */
2257 : static PyObject *open_array = NULL;
2258 : static PyObject *close_array = NULL;
2259 : static PyObject *empty_array = NULL;
2260 0 : PyObject *ident = NULL;
2261 0 : PyObject *s_fast = NULL;
2262 : Py_ssize_t i;
2263 :
2264 0 : if (open_array == NULL || close_array == NULL || empty_array == NULL) {
2265 0 : open_array = PyString_InternFromString("[");
2266 0 : close_array = PyString_InternFromString("]");
2267 0 : empty_array = PyString_InternFromString("[]");
2268 0 : if (open_array == NULL || close_array == NULL || empty_array == NULL)
2269 0 : return -1;
2270 : }
2271 0 : ident = NULL;
2272 0 : s_fast = PySequence_Fast(seq, "_iterencode_list needs a sequence");
2273 0 : if (s_fast == NULL)
2274 0 : return -1;
2275 0 : if (PySequence_Fast_GET_SIZE(s_fast) == 0) {
2276 0 : Py_DECREF(s_fast);
2277 0 : return PyList_Append(rval, empty_array);
2278 : }
2279 :
2280 0 : if (s->markers != Py_None) {
2281 : int has_key;
2282 0 : ident = PyLong_FromVoidPtr(seq);
2283 0 : if (ident == NULL)
2284 0 : goto bail;
2285 0 : has_key = PyDict_Contains(s->markers, ident);
2286 0 : if (has_key) {
2287 0 : if (has_key != -1)
2288 0 : PyErr_SetString(PyExc_ValueError, "Circular reference detected");
2289 0 : goto bail;
2290 : }
2291 0 : if (PyDict_SetItem(s->markers, ident, seq)) {
2292 0 : goto bail;
2293 : }
2294 : }
2295 :
2296 0 : if (PyList_Append(rval, open_array))
2297 0 : goto bail;
2298 0 : if (s->indent != Py_None) {
2299 : /* TODO: DOES NOT RUN */
2300 0 : indent_level += 1;
2301 : /*
2302 : newline_indent = '\n' + (' ' * (_indent * _current_indent_level))
2303 : separator = _item_separator + newline_indent
2304 : buf += newline_indent
2305 : */
2306 : }
2307 0 : for (i = 0; i < PySequence_Fast_GET_SIZE(s_fast); i++) {
2308 0 : PyObject *obj = PySequence_Fast_GET_ITEM(s_fast, i);
2309 0 : if (i) {
2310 0 : if (PyList_Append(rval, s->item_separator))
2311 0 : goto bail;
2312 : }
2313 0 : if (encoder_listencode_obj(s, rval, obj, indent_level))
2314 0 : goto bail;
2315 : }
2316 0 : if (ident != NULL) {
2317 0 : if (PyDict_DelItem(s->markers, ident))
2318 0 : goto bail;
2319 0 : Py_CLEAR(ident);
2320 : }
2321 0 : if (s->indent != Py_None) {
2322 : /* TODO: DOES NOT RUN */
2323 : /*
2324 : indent_level -= 1;
2325 :
2326 : yield '\n' + (' ' * (_indent * _current_indent_level))
2327 : */
2328 : }
2329 0 : if (PyList_Append(rval, close_array))
2330 0 : goto bail;
2331 0 : Py_DECREF(s_fast);
2332 0 : return 0;
2333 :
2334 : bail:
2335 0 : Py_XDECREF(ident);
2336 0 : Py_DECREF(s_fast);
2337 0 : return -1;
2338 : }
2339 :
2340 : static void
2341 0 : encoder_dealloc(PyObject *self)
2342 : {
2343 : /* Deallocate Encoder */
2344 0 : encoder_clear(self);
2345 0 : Py_TYPE(self)->tp_free(self);
2346 0 : }
2347 :
2348 : static int
2349 0 : encoder_traverse(PyObject *self, visitproc visit, void *arg)
2350 : {
2351 : PyEncoderObject *s;
2352 : assert(PyEncoder_Check(self));
2353 0 : s = (PyEncoderObject *)self;
2354 0 : Py_VISIT(s->markers);
2355 0 : Py_VISIT(s->defaultfn);
2356 0 : Py_VISIT(s->encoder);
2357 0 : Py_VISIT(s->indent);
2358 0 : Py_VISIT(s->key_separator);
2359 0 : Py_VISIT(s->item_separator);
2360 0 : Py_VISIT(s->sort_keys);
2361 0 : Py_VISIT(s->skipkeys);
2362 0 : return 0;
2363 : }
2364 :
2365 : static int
2366 0 : encoder_clear(PyObject *self)
2367 : {
2368 : /* Deallocate Encoder */
2369 : PyEncoderObject *s;
2370 : assert(PyEncoder_Check(self));
2371 0 : s = (PyEncoderObject *)self;
2372 0 : Py_CLEAR(s->markers);
2373 0 : Py_CLEAR(s->defaultfn);
2374 0 : Py_CLEAR(s->encoder);
2375 0 : Py_CLEAR(s->indent);
2376 0 : Py_CLEAR(s->key_separator);
2377 0 : Py_CLEAR(s->item_separator);
2378 0 : Py_CLEAR(s->sort_keys);
2379 0 : Py_CLEAR(s->skipkeys);
2380 0 : return 0;
2381 : }
2382 :
2383 : PyDoc_STRVAR(encoder_doc, "_iterencode(obj, _current_indent_level) -> iterable");
2384 :
2385 : static
2386 : PyTypeObject PyEncoderType = {
2387 : PyObject_HEAD_INIT(NULL)
2388 : 0, /* tp_internal */
2389 : "_json.Encoder", /* tp_name */
2390 : sizeof(PyEncoderObject), /* tp_basicsize */
2391 : 0, /* tp_itemsize */
2392 : encoder_dealloc, /* tp_dealloc */
2393 : 0, /* tp_print */
2394 : 0, /* tp_getattr */
2395 : 0, /* tp_setattr */
2396 : 0, /* tp_compare */
2397 : 0, /* tp_repr */
2398 : 0, /* tp_as_number */
2399 : 0, /* tp_as_sequence */
2400 : 0, /* tp_as_mapping */
2401 : 0, /* tp_hash */
2402 : encoder_call, /* tp_call */
2403 : 0, /* tp_str */
2404 : 0, /* tp_getattro */
2405 : 0, /* tp_setattro */
2406 : 0, /* tp_as_buffer */
2407 : Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
2408 : encoder_doc, /* tp_doc */
2409 : encoder_traverse, /* tp_traverse */
2410 : encoder_clear, /* tp_clear */
2411 : 0, /* tp_richcompare */
2412 : 0, /* tp_weaklistoffset */
2413 : 0, /* tp_iter */
2414 : 0, /* tp_iternext */
2415 : 0, /* tp_methods */
2416 : encoder_members, /* tp_members */
2417 : 0, /* tp_getset */
2418 : 0, /* tp_base */
2419 : 0, /* tp_dict */
2420 : 0, /* tp_descr_get */
2421 : 0, /* tp_descr_set */
2422 : 0, /* tp_dictoffset */
2423 : encoder_init, /* tp_init */
2424 : 0, /* tp_alloc */
2425 : encoder_new, /* tp_new */
2426 : 0, /* tp_free */
2427 : };
2428 :
2429 : static PyMethodDef speedups_methods[] = {
2430 : {"encode_basestring_ascii",
2431 : (PyCFunction)py_encode_basestring_ascii,
2432 : METH_O,
2433 : pydoc_encode_basestring_ascii},
2434 : {"scanstring",
2435 : (PyCFunction)py_scanstring,
2436 : METH_VARARGS,
2437 : pydoc_scanstring},
2438 : {NULL, NULL, 0, NULL}
2439 : };
2440 :
2441 : PyDoc_STRVAR(module_doc,
2442 : "json speedups\n");
2443 :
2444 : void
2445 3 : init_json(void)
2446 : {
2447 : PyObject *m;
2448 3 : PyScannerType.tp_new = PyType_GenericNew;
2449 3 : if (PyType_Ready(&PyScannerType) < 0)
2450 0 : return;
2451 3 : PyEncoderType.tp_new = PyType_GenericNew;
2452 3 : if (PyType_Ready(&PyEncoderType) < 0)
2453 0 : return;
2454 3 : m = Py_InitModule3("_json", speedups_methods, module_doc);
2455 3 : if (m == NULL)
2456 0 : return;
2457 3 : Py_INCREF((PyObject*)&PyScannerType);
2458 3 : PyModule_AddObject(m, "make_scanner", (PyObject*)&PyScannerType);
2459 3 : Py_INCREF((PyObject*)&PyEncoderType);
2460 3 : PyModule_AddObject(m, "make_encoder", (PyObject*)&PyEncoderType);
2461 : }
|