Crossfire Server, Trunk
cjson.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2006-2007 Dan Pascu.
3  * Author: Dan Pascu <dan@ag-projects.com>
4  *
5  * Fast JSON encoder/decoder implementation for Python
6  * This file is under GPL licence
7  */
8 
9 #include <cfpython.h>
10 #include <Python.h>
11 #include <stddef.h>
12 #include <stdio.h>
13 #include <ctype.h>
14 #include <math.h>
15 
16 typedef struct JSONData {
17  char *str; /* the actual json string */
18  char *end; /* pointer to the string end */
19  char *ptr; /* pointer to the current parsing position */
20  int all_unicode; /* make all output strings unicode if true */
21 } JSONData;
22 
23 static PyObject *encode_object(PyObject *object);
24 static PyObject *encode_string(PyObject *object);
25 static PyObject *encode_unicode(PyObject *object);
26 static PyObject *encode_tuple(PyObject *object);
27 static PyObject *encode_list(PyObject *object);
28 static PyObject *encode_dict(PyObject *object);
29 
30 static PyObject *decode_json(JSONData *jsondata);
31 static PyObject *decode_null(JSONData *jsondata);
32 static PyObject *decode_bool(JSONData *jsondata);
33 static PyObject *decode_string(JSONData *jsondata);
34 static PyObject *decode_inf(JSONData *jsondata);
35 static PyObject *decode_nan(JSONData *jsondata);
36 static PyObject *decode_number(JSONData *jsondata);
37 static PyObject *decode_array(JSONData *jsondata);
38 static PyObject *decode_object(JSONData *jsondata);
39 
40 static PyObject *JSON_Error;
41 static PyObject *JSON_EncodeError;
42 static PyObject *JSON_DecodeError;
43 
44 #if PY_VERSION_HEX < 0x02050000
45 typedef int Py_ssize_t;
46 
47 #define PY_SSIZE_T_MAX INT_MAX
48 #define PY_SSIZE_T_MIN INT_MIN
49 
50 #define SSIZE_T_F "%d"
51 #else
52 #define SSIZE_T_F "%zd"
53 #endif
54 
55 #define True 1
56 #define False 0
57 
58 #ifndef INFINITY
59 #define INFINITY HUGE_VAL
60 #endif
61 
62 #ifndef NAN
63 #define NAN (HUGE_VAL-HUGE_VAL)
64 #endif
65 
66 #ifndef Py_IS_NAN
67 #define Py_IS_NAN(X) ((X) != (X))
68 #endif
69 
70 #define skipSpaces(d) while (*((d)->ptr) && isspace(*((d)->ptr))) (d)->ptr++
71 
72 /* ------------------------------ Utility ----------------------------- */
73 
75 static PyObject* cjson_PyObject_Str(PyObject* obj) {
76  PyObject *tmp_str, *result;
77  tmp_str = PyObject_Str(obj);
78  if (!tmp_str)
79  return NULL;
80  result = PyUnicode_AsUTF8String(tmp_str);
81  Py_DECREF(tmp_str);
82  return result;
83 }
84 
85 /* ------------------------------ Decoding ----------------------------- */
86 
87 static void getRowAndCol(char *begin, char *current, int *row, int *col) {
88  *col = 1;
89  *row = 1;
90  while (current > begin) {
91  if (*current == '\n')
92  (*row)++;
93  if (*row < 2)
94  (*col)++;
95  current--;
96  }
97 }
98 static PyObject *decode_null(JSONData *jsondata) {
99  ptrdiff_t left;
100 
101  left = jsondata->end-jsondata->ptr;
102 
103  if (left >= 4 && strncmp(jsondata->ptr, "null", 4) == 0) {
104  jsondata->ptr += 4;
105  Py_INCREF(Py_None);
106  return Py_None;
107  } else {
108  int row, col;
109 
110  getRowAndCol(jsondata->str, jsondata->ptr, &row, &col);
111  PyErr_Format(JSON_DecodeError, "cannot parse JSON description: %.20s" "(row " SSIZE_T_F ", col " SSIZE_T_F ")", jsondata->ptr, (Py_ssize_t)row, (Py_ssize_t)col);
112  return NULL;
113  }
114 }
115 
116 static PyObject *decode_bool(JSONData *jsondata) {
117  ptrdiff_t left;
118 
119  left = jsondata->end-jsondata->ptr;
120 
121  if (left >= 4 && strncmp(jsondata->ptr, "true", 4) == 0) {
122  jsondata->ptr += 4;
123  Py_INCREF(Py_True);
124  return Py_True;
125  } else if (left >= 5 && strncmp(jsondata->ptr, "false", 5) == 0) {
126  jsondata->ptr += 5;
127  Py_INCREF(Py_False);
128  return Py_False;
129  } else {
130  int row, col;
131 
132  getRowAndCol(jsondata->str, jsondata->ptr, &row, &col);
133  PyErr_Format(JSON_DecodeError, "cannot parse JSON description: %.20s" "(row " SSIZE_T_F ", col " SSIZE_T_F ")", jsondata->ptr, (Py_ssize_t)row, (Py_ssize_t)col);
134  return NULL;
135  }
136 }
137 
138 static PyObject *decode_string(JSONData *jsondata) {
139  PyObject *object;
140  int c, escaping, has_unicode, string_escape;
141  Py_ssize_t len;
142  char *ptr;
143 
144  /* look for the closing quote */
145  escaping = has_unicode = string_escape = False;
146  ptr = jsondata->ptr+1;
147  while (True) {
148  c = *ptr;
149  if (c == 0) {
150  int row, col;
151 
152  getRowAndCol(jsondata->str, jsondata->ptr, &row, &col);
153  PyErr_Format(JSON_DecodeError, "unterminated string starting at position " SSIZE_T_F "(row " SSIZE_T_F ", col " SSIZE_T_F ")",
154  (Py_ssize_t)(jsondata->ptr-jsondata->str), (Py_ssize_t)row, (Py_ssize_t)col);
155  return NULL;
156  }
157  if (!escaping) {
158  if (c == '\\') {
159  escaping = True;
160  } else if (c == '"') {
161  break;
162  } else if (!isascii(c)) {
163  has_unicode = True;
164  }
165  } else {
166  switch (c) {
167  case 'u':
168  has_unicode = True;
169  break;
170  case '"':
171  case 'r':
172  case 'n':
173  case 't':
174  case 'b':
175  case 'f':
176  case '\\':
177  string_escape = True;
178  break;
179  }
180  escaping = False;
181  }
182  ptr++;
183  }
184 
185  len = ptr-jsondata->ptr-1;
186 
187  if (has_unicode || jsondata->all_unicode)
188  object = PyUnicode_DecodeUnicodeEscape(jsondata->ptr+1, len, NULL);
189  else if (string_escape)
190  object = PyBytes_DecodeEscape(jsondata->ptr+1, len, NULL, 0, NULL);
191  else
192  object = PyBytes_FromStringAndSize(jsondata->ptr+1, len);
193 
194  if (object == NULL) {
195  PyObject *type, *value, *tb, *reason;
196 
197  PyErr_Fetch(&type, &value, &tb);
198  if (type == NULL) {
199  int row, col;
200 
201  getRowAndCol(jsondata->str, jsondata->ptr, &row, &col);
202  PyErr_Format(JSON_DecodeError, "invalid string starting at position " SSIZE_T_F "(row " SSIZE_T_F ", col " SSIZE_T_F ")",
203  (Py_ssize_t)(jsondata->ptr-jsondata->str), (Py_ssize_t)row, (Py_ssize_t)col);
204  } else {
205  if (PyErr_GivenExceptionMatches(type, PyExc_UnicodeDecodeError)) {
206  int row, col;
207 
208  reason = PyObject_GetAttrString(value, "reason");
209  /* If we are using Python3 we need to convert to bytes here. */
210  if (reason && PyUnicode_Check(reason)) {
211  PyObject * bytes_reason = PyUnicode_AsUTF8String(reason);
212  Py_DECREF(reason);
213  reason = bytes_reason;
214  }
215  getRowAndCol(jsondata->str, jsondata->ptr, &row, &col);
216  PyErr_Format(JSON_DecodeError, "cannot decode string starting" " at position " SSIZE_T_F "(row " SSIZE_T_F ", col " SSIZE_T_F "): %s",
217  (Py_ssize_t)(jsondata->ptr-jsondata->str), (Py_ssize_t)row, (Py_ssize_t)col,
218  reason ? PyBytes_AsString(reason) : "bad format");
219  Py_XDECREF(reason);
220  } else {
221  int row, col;
222 
223  getRowAndCol(jsondata->str, jsondata->ptr, &row, &col);
224  PyErr_Format(JSON_DecodeError, "invalid string starting at position " SSIZE_T_F "(row " SSIZE_T_F ", col " SSIZE_T_F ")",
225  (Py_ssize_t)(jsondata->ptr-jsondata->str), (Py_ssize_t)row, (Py_ssize_t)col);
226  }
227  }
228  Py_XDECREF(type);
229  Py_XDECREF(value);
230  Py_XDECREF(tb);
231  } else {
232  jsondata->ptr = ptr+1;
233  }
234 
235  return object;
236 }
237 
238 static PyObject *decode_inf(JSONData *jsondata) {
239  PyObject *object;
240  ptrdiff_t left;
241 
242  left = jsondata->end-jsondata->ptr;
243 
244  if (left >= 8 && strncmp(jsondata->ptr, "Infinity", 8) == 0) {
245  jsondata->ptr += 8;
246  object = PyFloat_FromDouble(INFINITY);
247  return object;
248  } else if (left >= 9 && strncmp(jsondata->ptr, "+Infinity", 9) == 0) {
249  jsondata->ptr += 9;
250  object = PyFloat_FromDouble(INFINITY);
251  return object;
252  } else if (left >= 9 && strncmp(jsondata->ptr, "-Infinity", 9) == 0) {
253  jsondata->ptr += 9;
254  object = PyFloat_FromDouble(-INFINITY);
255  return object;
256  } else {
257  int row, col;
258 
259  getRowAndCol(jsondata->str, jsondata->ptr, &row, &col);
260  PyErr_Format(JSON_DecodeError, "cannot parse JSON description: %.20s (row " SSIZE_T_F ", col " SSIZE_T_F ")", jsondata->ptr, (Py_ssize_t)row, (Py_ssize_t)col);
261  return NULL;
262  }
263 }
264 
265 static PyObject *decode_nan(JSONData *jsondata) {
266  PyObject *object;
267  ptrdiff_t left;
268 
269  left = jsondata->end-jsondata->ptr;
270 
271  if (left >= 3 && strncmp(jsondata->ptr, "NaN", 3) == 0) {
272  jsondata->ptr += 3;
273  object = PyFloat_FromDouble(NAN);
274  return object;
275  } else {
276  int row, col;
277  getRowAndCol(jsondata->str, jsondata->ptr, &row, &col);
278  PyErr_Format(JSON_DecodeError, "cannot parse JSON description: %.20s(row " SSIZE_T_F ", col " SSIZE_T_F ")", jsondata->ptr, (Py_ssize_t)row, (Py_ssize_t)col);
279  return NULL;
280  }
281 }
282 
283 static PyObject *decode_number(JSONData *jsondata) {
284  PyObject *object, *str;
285  int c, is_float, should_stop;
286  char *ptr;
287 
288  /* check if we got a floating point number */
289  ptr = jsondata->ptr;
290  is_float = should_stop = False;
291  while (True) {
292  c = *ptr;
293  if (c == 0)
294  break;
295  switch (c) {
296  case '0':
297  case '1':
298  case '2':
299  case '3':
300  case '4':
301  case '5':
302  case '6':
303  case '7':
304  case '8':
305  case '9':
306  case '-':
307  case '+':
308  break;
309 
310  case '.':
311  case 'e':
312  case 'E':
313  is_float = True;
314  break;
315 
316  default:
317  should_stop = True;
318  }
319  if (should_stop) {
320  break;
321  }
322  ptr++;
323  }
324 
325  str = PyBytes_FromStringAndSize(jsondata->ptr, ptr-jsondata->ptr);
326  if (str == NULL)
327  return NULL;
328 
329  if (is_float) {
330  object = PyFloat_FromString(str);
331  } else {
332  object = PyLong_FromString(PyBytes_AS_STRING(str), NULL, 10);
333  }
334 
335  Py_DECREF(str);
336 
337  if (object == NULL) {
338  int row, col;
339 
340  getRowAndCol(jsondata->str, jsondata->ptr, &row, &col);
341  PyErr_Format(JSON_DecodeError, "invalid number starting at position " SSIZE_T_F "(row " SSIZE_T_F ", col " SSIZE_T_F ")", (Py_ssize_t)(jsondata->ptr-jsondata->str), (Py_ssize_t)row, (Py_ssize_t)col);
342  } else {
343  jsondata->ptr = ptr;
344  }
345 
346  return object;
347 }
348 
349 static PyObject *decode_array(JSONData *jsondata) {
350  PyObject *object, *item;
351  int c, expect_item, items, result;
352  char *start;
353 
354  object = PyList_New(0);
355 
356  start = jsondata->ptr;
357  jsondata->ptr++;
358  expect_item = True;
359  items = 0;
360  while (True) {
361  skipSpaces(jsondata);
362  c = *jsondata->ptr;
363  if (c == 0) {
364  int row, col;
365 
366  getRowAndCol(jsondata->str, jsondata->ptr, &row, &col);
367  PyErr_Format(JSON_DecodeError, "unterminated array starting at position " SSIZE_T_F "(row " SSIZE_T_F ", col " SSIZE_T_F ")",
368  (Py_ssize_t)(start-jsondata->str), (Py_ssize_t)row, (Py_ssize_t)col);
369  goto failure;
370  } else if (c == ']') {
371  if (expect_item && items > 0) {
372  int row, col;
373 
374  getRowAndCol(jsondata->str, jsondata->ptr, &row, &col);
375  PyErr_Format(JSON_DecodeError, "expecting array item at position " SSIZE_T_F "(row " SSIZE_T_F ", col " SSIZE_T_F ")",
376  (Py_ssize_t)(jsondata->ptr-jsondata->str), (Py_ssize_t)row, (Py_ssize_t)col);
377  goto failure;
378  }
379  jsondata->ptr++;
380  break;
381  } else if (c == ',') {
382  if (expect_item) {
383  int row, col;
384 
385  getRowAndCol(jsondata->str, jsondata->ptr, &row, &col);
386  PyErr_Format(JSON_DecodeError, "expecting array item at position " SSIZE_T_F "(row " SSIZE_T_F ", col " SSIZE_T_F ")",
387  (Py_ssize_t)(jsondata->ptr-jsondata->str), (Py_ssize_t)row, (Py_ssize_t)col);
388  goto failure;
389  }
390  expect_item = True;
391  jsondata->ptr++;
392  continue;
393  } else {
394  item = decode_json(jsondata);
395  if (item == NULL)
396  goto failure;
397  result = PyList_Append(object, item);
398  Py_DECREF(item);
399  if (result == -1)
400  goto failure;
401  expect_item = False;
402  items++;
403  }
404  }
405 
406  return object;
407 
408 failure:
409  Py_DECREF(object);
410  return NULL;
411 }
412 
413 static PyObject *decode_object(JSONData *jsondata) {
414  PyObject *object, *key, *value;
415  int c, expect_key, items, result;
416  char *start;
417 
418  object = PyDict_New();
419 
420  expect_key = True;
421  items = 0;
422  start = jsondata->ptr;
423  jsondata->ptr++;
424 
425  while (True) {
426  skipSpaces(jsondata);
427  c = *jsondata->ptr;
428  if (c == 0) {
429  int row, col;
430 
431  getRowAndCol(jsondata->str, jsondata->ptr, &row, &col);
432  PyErr_Format(JSON_DecodeError, "unterminated object starting at position " SSIZE_T_F "(row " SSIZE_T_F ", col " SSIZE_T_F ")",
433  (Py_ssize_t)(start-jsondata->str), (Py_ssize_t)row, (Py_ssize_t)col);
434  goto failure;
435  } else if (c == '}') {
436  if (expect_key && items > 0) {
437  int row, col;
438 
439  getRowAndCol(jsondata->str, jsondata->ptr, &row, &col);
440  PyErr_Format(JSON_DecodeError, "expecting object property name at position " SSIZE_T_F "(row " SSIZE_T_F ", col " SSIZE_T_F ")",
441  (Py_ssize_t)(jsondata->ptr-jsondata->str), (Py_ssize_t)row, (Py_ssize_t)col);
442  goto failure;
443  }
444  jsondata->ptr++;
445  break;
446  } else if (c == ',') {
447  if (expect_key) {
448  int row, col;
449 
450  getRowAndCol(jsondata->str, jsondata->ptr, &row, &col);
451  PyErr_Format(JSON_DecodeError, "expecting object property name at position " SSIZE_T_F "(row " SSIZE_T_F ", col " SSIZE_T_F ")",
452  (Py_ssize_t)(jsondata->ptr-jsondata->str), (Py_ssize_t)row, (Py_ssize_t)col);
453  goto failure;
454  }
455  expect_key = True;
456  jsondata->ptr++;
457  continue;
458  } else {
459  if (c != '"') {
460  int row, col;
461 
462  getRowAndCol(jsondata->str, jsondata->ptr, &row, &col);
463  PyErr_Format(JSON_DecodeError, "expecting property name in object at position " SSIZE_T_F "(row " SSIZE_T_F ", col " SSIZE_T_F ")",
464  (Py_ssize_t)(jsondata->ptr-jsondata->str), (Py_ssize_t)row, (Py_ssize_t)col);
465  goto failure;
466  }
467 
468  key = decode_json(jsondata);
469  if (key == NULL)
470  goto failure;
471 
472  skipSpaces(jsondata);
473  if (*jsondata->ptr != ':') {
474  int row, col;
475 
476  getRowAndCol(jsondata->str, jsondata->ptr, &row, &col);
477  PyErr_Format(JSON_DecodeError, "missing colon after object property name at position " SSIZE_T_F "(row " SSIZE_T_F ", col " SSIZE_T_F ")",
478  (Py_ssize_t)(jsondata->ptr-jsondata->str), (Py_ssize_t)row, (Py_ssize_t)col);
479  Py_DECREF(key);
480  goto failure;
481  } else {
482  jsondata->ptr++;
483  }
484 
485  value = decode_json(jsondata);
486  if (value == NULL) {
487  Py_DECREF(key);
488  goto failure;
489  }
490 
491  result = PyDict_SetItem(object, key, value);
492  Py_DECREF(key);
493  Py_DECREF(value);
494  if (result == -1)
495  goto failure;
496  expect_key = False;
497  items++;
498  }
499  }
500 
501  return object;
502 
503 failure:
504  Py_DECREF(object);
505  return NULL;
506 }
507 
508 static PyObject *decode_json(JSONData *jsondata) {
509  PyObject *object;
510 
511  skipSpaces(jsondata);
512  switch (*jsondata->ptr) {
513  case 0:
514  PyErr_SetString(JSON_DecodeError, "empty JSON description");
515  return NULL;
516 
517  case '{':
518  object = decode_object(jsondata);
519  break;
520 
521  case '[':
522  object = decode_array(jsondata);
523  break;
524 
525  case '"':
526  object = decode_string(jsondata);
527  break;
528 
529  case 't':
530  case 'f':
531  object = decode_bool(jsondata);
532  break;
533 
534  case 'n':
535  object = decode_null(jsondata);
536  break;
537 
538  case 'N':
539  object = decode_nan(jsondata);
540  break;
541 
542  case 'I':
543  object = decode_inf(jsondata);
544  break;
545 
546  case '+':
547  case '-':
548  if (*(jsondata->ptr+1) == 'I') {
549  object = decode_inf(jsondata);
550  } else {
551  object = decode_number(jsondata);
552  }
553  break;
554 
555  case '0':
556  case '1':
557  case '2':
558  case '3':
559  case '4':
560  case '5':
561  case '6':
562  case '7':
563  case '8':
564  case '9':
565  object = decode_number(jsondata);
566  break;
567 
568  default:
569  PyErr_SetString(JSON_DecodeError, "cannot parse JSON description");
570  return NULL;
571  }
572 
573  return object;
574 }
575 
576 /* ------------------------------ Encoding ----------------------------- */
577 
578 /*
579  * This function is an almost verbatim copy of PyString_Repr() from
580  * Python's stringobject.c with the following differences:
581  *
582  * - it always quotes the output using double quotes.
583  * - it also quotes \b and \f
584  * - it replaces any non ASCII character hh with \u00hh instead of \xhh
585  */
586 static PyObject *encode_string(PyObject *string) {
587  register PyBytesObject *op = (PyBytesObject *)string;
588  size_t newsize = 2+6*Py_SIZE(op);
589  PyObject *v;
590 
591  if (Py_SIZE(op) > (PY_SSIZE_T_MAX-2)/6) {
592  PyErr_SetString(PyExc_OverflowError, "string is too large to make repr");
593  return NULL;
594  }
595  v = PyBytes_FromStringAndSize((char *)NULL, newsize);
596  if (v == NULL) {
597  return NULL;
598  } else {
599  register Py_ssize_t i;
600  register char c;
601  register char *p;
602  int quote;
603 
604  quote = '"';
605 
606  p = PyBytes_AS_STRING(v);
607  *p++ = quote;
608  for (i = 0; i < Py_SIZE(op); i++) {
609  /* There's at least enough room for a hex escape
610  and a closing quote. */
611  assert(newsize-(p-PyBytes_AS_STRING(v)) >= 7);
612  c = op->ob_sval[i];
613  if (c == quote || c == '\\')
614  *p++ = '\\', *p++ = c;
615  else if (c == '\t')
616  *p++ = '\\', *p++ = 't';
617  else if (c == '\n')
618  *p++ = '\\', *p++ = 'n';
619  else if (c == '\r')
620  *p++ = '\\', *p++ = 'r';
621  else if (c == '\f')
622  *p++ = '\\', *p++ = 'f';
623  else if (c == '\b')
624  *p++ = '\\', *p++ = 'b';
625  else if (c < ' ' || c >= 0x7f) {
626  /* For performance, we don't want to call
627  * PyOS_snprintf here (extra layers of
628  * function call). */
629  sprintf(p, "\\u%04x", c&0xff);
630  p += 6;
631  }
632  else
633  *p++ = c;
634  }
635  assert(newsize-(p-PyBytes_AS_STRING(v)) >= 1);
636  *p++ = quote;
637  *p = '\0';
638  _PyBytes_Resize(&v, (int) (p-PyBytes_AS_STRING(v)));
639  return v;
640  }
641 }
642 
643 /*
644  * This function is an almost verbatim copy of unicodeescape_string() from
645  * Python's unicodeobject.c with the following differences:
646  *
647  * - it always quotes the output using double quotes.
648  * - it uses \u00hh instead of \xhh in output.
649  * - it also quotes \b and \f
650  */
651 static PyObject *encode_unicode(PyObject *unicode) {
652  PyObject *repr;
653  Py_UNICODE *s;
654  Py_ssize_t size;
655  char *p;
656  static const char *hexdigit = "0123456789abcdef";
657 #ifdef Py_UNICODE_WIDE
658  static const Py_ssize_t expandsize = 10;
659 #else
660  static const Py_ssize_t expandsize = 6;
661 #endif
662 
663  s = PyUnicode_AS_UNICODE(unicode);
664  size = PyUnicode_GET_SIZE(unicode);
665 
666  if (size > (PY_SSIZE_T_MAX-2-1)/expandsize) {
667  PyErr_SetString(PyExc_OverflowError, "unicode object is too large to make repr");
668  return NULL;
669  }
670 
671  repr = PyByteArray_FromStringAndSize(NULL,
672  2
673  + expandsize*size
674  + 1);
675  if (repr == NULL)
676  return NULL;
677 
678  p = PyByteArray_AS_STRING(repr);
679 
680  *p++ = '"';
681 
682  while (size-- > 0) {
683  Py_UNICODE ch = *s++;
684 
685  /* Escape quotes */
686  if ((ch == (Py_UNICODE)PyByteArray_AS_STRING(repr)[0] || ch == '\\')) {
687  *p++ = '\\';
688  *p++ = (char)ch;
689  continue;
690  }
691 #ifdef Py_UNICODE_WIDE
692  /* Map 21-bit characters to '\U00xxxxxx' */
693  else if (ch >= 0x10000) {
694  *p++ = '\\';
695  *p++ = 'U';
696  *p++ = hexdigit[(ch>>28)&0x0000000F];
697  *p++ = hexdigit[(ch>>24)&0x0000000F];
698  *p++ = hexdigit[(ch>>20)&0x0000000F];
699  *p++ = hexdigit[(ch>>16)&0x0000000F];
700  *p++ = hexdigit[(ch>>12)&0x0000000F];
701  *p++ = hexdigit[(ch>>8)&0x0000000F];
702  *p++ = hexdigit[(ch>>4)&0x0000000F];
703  *p++ = hexdigit[ch&0x0000000F];
704  continue;
705  }
706 #else
707  /* Map UTF-16 surrogate pairs to Unicode \UXXXXXXXX escapes */
708  else if (ch >= 0xD800 && ch < 0xDC00) {
709  Py_UNICODE ch2;
710  Py_UCS4 ucs;
711 
712  ch2 = *s++;
713  size--;
714  if (ch2 >= 0xDC00 && ch2 <= 0xDFFF) {
715  ucs = (((ch&0x03FF)<<10)|(ch2&0x03FF))+0x00010000;
716  *p++ = '\\';
717  *p++ = 'U';
718  *p++ = hexdigit[(ucs>>28)&0x0000000F];
719  *p++ = hexdigit[(ucs>>24)&0x0000000F];
720  *p++ = hexdigit[(ucs>>20)&0x0000000F];
721  *p++ = hexdigit[(ucs>>16)&0x0000000F];
722  *p++ = hexdigit[(ucs>>12)&0x0000000F];
723  *p++ = hexdigit[(ucs>>8)&0x0000000F];
724  *p++ = hexdigit[(ucs>>4)&0x0000000F];
725  *p++ = hexdigit[ucs&0x0000000F];
726  continue;
727  }
728  /* Fall through: isolated surrogates are copied as-is */
729  s--;
730  size++;
731  }
732 #endif
733  /* Map 16-bit characters to '\uxxxx' */
734  if (ch >= 256) {
735  *p++ = '\\';
736  *p++ = 'u';
737  *p++ = hexdigit[(ch>>12)&0x000F];
738  *p++ = hexdigit[(ch>>8)&0x000F];
739  *p++ = hexdigit[(ch>>4)&0x000F];
740  *p++ = hexdigit[ch&0x000F];
741  /* Map special whitespace to '\t', \n', '\r', '\f', '\b' */
742  } else if (ch == '\t') {
743  *p++ = '\\';
744  *p++ = 't';
745  } else if (ch == '\n') {
746  *p++ = '\\';
747  *p++ = 'n';
748  } else if (ch == '\r') {
749  *p++ = '\\';
750  *p++ = 'r';
751  } else if (ch == '\f') {
752  *p++ = '\\';
753  *p++ = 'f';
754  } else if (ch == '\b') {
755  *p++ = '\\';
756  *p++ = 'b';
757  }
758 
759  /* Map non-printable US ASCII to '\u00hh' */
760  else if (ch < ' ' || ch >= 0x7F) {
761  *p++ = '\\';
762  *p++ = 'u';
763  *p++ = '0';
764  *p++ = '0';
765  *p++ = hexdigit[(ch>>4)&0x000F];
766  *p++ = hexdigit[ch&0x000F];
767  }
768 
769  /* Copy everything else as-is */
770  else
771  *p++ = (char)ch;
772  }
773 
774  *p++ = PyByteArray_AS_STRING(repr)[0];
775 
776  *p = '\0';
777  {
778  PyObject *result = PyBytes_FromStringAndSize(PyByteArray_AS_STRING(repr),
779  p - PyByteArray_AS_STRING(repr));
780  Py_DECREF(repr);
781  return result;
782  }
783 }
784 
785 /*
786  * This function is an almost verbatim copy of tuplerepr() from
787  * Python's tupleobject.c with the following differences:
788  *
789  * - it uses encode_object() to get the object's JSON reprezentation.
790  * - it uses [] as decorations isntead of () (to masquerade as a JSON array).
791  */
792 
793 static PyObject *encode_tuple(PyObject *tuple) {
794  Py_ssize_t i, n;
795  PyObject *s, *temp;
796  PyObject *pieces, *result = NULL;
797  PyTupleObject *v = (PyTupleObject *)tuple;
798 
799  n = Py_SIZE(v);
800  if (n == 0)
801  return PyBytes_FromString("[]");
802 
803  pieces = PyTuple_New(n);
804  if (pieces == NULL)
805  return NULL;
806 
807  /* Do repr() on each element. */
808  for (i = 0; i < n; ++i) {
809  s = encode_object(v->ob_item[i]);
810  if (s == NULL)
811  goto Done;
812  PyTuple_SET_ITEM(pieces, i, s);
813  }
814 
815  /* Add "[]" decorations to the first and last items. */
816  assert(n > 0);
817  s = PyBytes_FromString("[");
818  if (s == NULL)
819  goto Done;
820  temp = PyTuple_GET_ITEM(pieces, 0);
821  PyBytes_ConcatAndDel(&s, temp);
822  PyTuple_SET_ITEM(pieces, 0, s);
823  if (s == NULL)
824  goto Done;
825 
826  s = PyBytes_FromString("]");
827  if (s == NULL)
828  goto Done;
829  temp = PyTuple_GET_ITEM(pieces, n-1);
830  PyBytes_ConcatAndDel(&temp, s);
831  PyTuple_SET_ITEM(pieces, n-1, temp);
832  if (temp == NULL)
833  goto Done;
834 
835  /* Paste them all together with ", " between. */
836  s = PyBytes_FromString(", ");
837  if (s == NULL)
838  goto Done;
839  result = _PyBytes_Join(s, pieces);
840  Py_DECREF(s);
841 
842 Done:
843  Py_DECREF(pieces);
844  return result;
845 }
846 
847 /*
848  * This function is an almost verbatim copy of list_repr() from
849  * Python's listobject.c with the following differences:
850  *
851  * - it uses encode_object() to get the object's JSON reprezentation.
852  * - it doesn't use the ellipsis to represent a list with references
853  * to itself, instead it raises an exception as such lists cannot be
854  * represented in JSON.
855  */
856 static PyObject *encode_list(PyObject *list) {
857  Py_ssize_t i;
858  PyObject *s, *temp;
859  PyObject *pieces = NULL, *result = NULL;
860  PyListObject *v = (PyListObject *)list;
861 
862  i = Py_ReprEnter((PyObject *)v);
863  if (i != 0) {
864  if (i > 0) {
865  PyErr_SetString(JSON_EncodeError, "a list with references to itself is not JSON encodable");
866  }
867  return NULL;
868  }
869 
870  if (Py_SIZE(v) == 0) {
871  result = PyBytes_FromString("[]");
872  goto Done;
873  }
874 
875  pieces = PyList_New(0);
876  if (pieces == NULL)
877  goto Done;
878 
879  /* Do repr() on each element. Note that this may mutate the list,
880  * so must refetch the list size on each iteration. */
881  for (i = 0; i < Py_SIZE(v); ++i) {
882  int status;
883  s = encode_object(v->ob_item[i]);
884  if (s == NULL)
885  goto Done;
886  status = PyList_Append(pieces, s);
887  Py_DECREF(s); /* append created a new ref */
888  if (status < 0)
889  goto Done;
890  }
891 
892  /* Add "[]" decorations to the first and last items. */
893  assert(PyList_GET_SIZE(pieces) > 0);
894  s = PyBytes_FromString("[");
895  if (s == NULL)
896  goto Done;
897  temp = PyList_GET_ITEM(pieces, 0);
898  PyBytes_ConcatAndDel(&s, temp);
899  PyList_SET_ITEM(pieces, 0, s);
900  if (s == NULL)
901  goto Done;
902 
903  s = PyBytes_FromString("]");
904  if (s == NULL)
905  goto Done;
906  temp = PyList_GET_ITEM(pieces, PyList_GET_SIZE(pieces)-1);
907  PyBytes_ConcatAndDel(&temp, s);
908  PyList_SET_ITEM(pieces, PyList_GET_SIZE(pieces)-1, temp);
909  if (temp == NULL)
910  goto Done;
911 
912  /* Paste them all together with ", " between. */
913  s = PyBytes_FromString(", ");
914  if (s == NULL)
915  goto Done;
916  result = _PyBytes_Join(s, pieces);
917  Py_DECREF(s);
918 
919 Done:
920  Py_XDECREF(pieces);
921  Py_ReprLeave((PyObject *)v);
922  return result;
923 }
924 
925 /*
926  * This function is an almost verbatim copy of dict_repr() from
927  * Python's dictobject.c with the following differences:
928  *
929  * - it uses encode_object() to get the object's JSON reprezentation.
930  * - only accept strings for keys.
931  * - it doesn't use the ellipsis to represent a dictionary with references
932  * to itself, instead it raises an exception as such dictionaries cannot
933  * be represented in JSON.
934  */
935 static PyObject *encode_dict(PyObject *dict) {
936  Py_ssize_t i;
937  PyObject *s, *temp, *colon = NULL;
938  PyObject *pieces = NULL, *result = NULL;
939  PyObject *key, *value;
940  PyDictObject *mp = (PyDictObject *)dict;
941 
942  i = Py_ReprEnter((PyObject *)mp);
943  if (i != 0) {
944  if (i > 0) {
945  PyErr_SetString(JSON_EncodeError, "a dict with references to "
946  "itself is not JSON encodable");
947  }
948  return NULL;
949  }
950 
951  if (mp->ma_used == 0) {
952  result = PyBytes_FromString("{}");
953  goto Done;
954  }
955 
956  pieces = PyList_New(0);
957  if (pieces == NULL)
958  goto Done;
959 
960  colon = PyBytes_FromString(": ");
961  if (colon == NULL)
962  goto Done;
963 
964  /* Do repr() on each key+value pair, and insert ": " between them.
965  * Note that repr may mutate the dict. */
966  i = 0;
967  while (PyDict_Next((PyObject *)mp, &i, &key, &value)) {
968  int status;
969 
970  if (!PyBytes_Check(key) && !PyUnicode_Check(key)) {
971  PyErr_SetString(JSON_EncodeError, "JSON encodable dictionaries must have string/unicode keys");
972  goto Done;
973  }
974 
975  /* Prevent repr from deleting value during key format. */
976  Py_INCREF(value);
977  s = encode_object(key);
978  PyBytes_Concat(&s, colon);
979  PyBytes_ConcatAndDel(&s, encode_object(value));
980  Py_DECREF(value);
981  if (s == NULL)
982  goto Done;
983  status = PyList_Append(pieces, s);
984  Py_DECREF(s); /* append created a new ref */
985  if (status < 0)
986  goto Done;
987  }
988 
989  /* Add "{}" decorations to the first and last items. */
990  assert(PyList_GET_SIZE(pieces) > 0);
991  s = PyBytes_FromString("{");
992  if (s == NULL)
993  goto Done;
994  temp = PyList_GET_ITEM(pieces, 0);
995  PyBytes_ConcatAndDel(&s, temp);
996  PyList_SET_ITEM(pieces, 0, s);
997  if (s == NULL)
998  goto Done;
999 
1000  s = PyBytes_FromString("}");
1001  if (s == NULL)
1002  goto Done;
1003  temp = PyList_GET_ITEM(pieces, PyList_GET_SIZE(pieces)-1);
1004  PyBytes_ConcatAndDel(&temp, s);
1005  PyList_SET_ITEM(pieces, PyList_GET_SIZE(pieces)-1, temp);
1006  if (temp == NULL)
1007  goto Done;
1008 
1009  /* Paste them all together with ", " between. */
1010  s = PyBytes_FromString(", ");
1011  if (s == NULL)
1012  goto Done;
1013  result = _PyBytes_Join(s, pieces);
1014  Py_DECREF(s);
1015 
1016 Done:
1017  Py_XDECREF(pieces);
1018  Py_XDECREF(colon);
1019  Py_ReprLeave((PyObject *)mp);
1020  return result;
1021 }
1022 
1023 static PyObject *encode_object(PyObject *object) {
1024  if (object == Py_True) {
1025  return PyBytes_FromString("true");
1026  } else if (object == Py_False) {
1027  return PyBytes_FromString("false");
1028  } else if (object == Py_None) {
1029  return PyBytes_FromString("null");
1030  } else if (PyBytes_Check(object)) {
1031  return encode_string(object);
1032  } else if (PyUnicode_Check(object)) {
1033  return encode_unicode(object);
1034  } else if (PyFloat_Check(object)) {
1035  double val = PyFloat_AS_DOUBLE(object);
1036  if (Py_IS_NAN(val)) {
1037  return PyBytes_FromString("NaN");
1038  } else if (Py_IS_INFINITY(val)) {
1039  if (val > 0) {
1040  return PyBytes_FromString("Infinity");
1041  } else {
1042  return PyBytes_FromString("-Infinity");
1043  }
1044  } else {
1045  return cjson_PyObject_Str(object);
1046  }
1047  }
1048  else if (PyLong_Check(object)) {
1049  return cjson_PyObject_Str(object);
1050  }
1051  else if (PyList_Check(object)) {
1052  return encode_list(object);
1053  } else if (PyTuple_Check(object)) {
1054  return encode_tuple(object);
1055  } else if (PyDict_Check(object)) { /* use PyMapping_Check(object) instead? -Dan */
1056  return encode_dict(object);
1057  } else {
1058  PyErr_SetString(JSON_EncodeError, "object is not JSON encodable");
1059  return NULL;
1060  }
1061 }
1062 
1063 /* Encode object into its JSON representation */
1064 
1065 static PyObject *JSON_encode(PyObject *self, PyObject *object) {
1066  (void)self;
1067  return encode_object(object);
1068 }
1069 
1070 /* Decode JSON representation into pyhton objects */
1071 
1072 static PyObject *JSON_decode(PyObject *self, PyObject *args, PyObject *kwargs) {
1073  static char *kwlist[] = { "json", "all_unicode", NULL };
1074  int all_unicode = True; /* by default return unicode always */
1075  PyObject *object, *string, *str;
1076  JSONData jsondata;
1077  (void)self;
1078 
1079  if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:decode", kwlist, &string, &all_unicode))
1080  return NULL;
1081 
1082  if (PyUnicode_Check(string)) {
1083  // PyUnicode_EncodeRawUnicodeEscape() is deprecated as of Python 3.3, scheduled for removal in Python 3.11
1084 #ifndef IS_PY3K3
1085  /* HACK: Workaround for crash bug in Python3's PyUnicode_AsRawUnicodeEscapeString... */
1086  str = PyUnicode_EncodeRawUnicodeEscape(PyUnicode_AS_UNICODE(string),
1087  PyUnicode_GET_SIZE(string));
1088 #else
1089  // The Python docs recommend using PyUnicode_AsRawUnicodeEscapeString() or PyUnicode_AsEncodedString() over PyUnicode_EncodeRawUnicodeEscape().
1090  str = PyUnicode_AsRawUnicodeEscapeString(string);
1091 #endif
1092  if (str == NULL) {
1093  return NULL;
1094  }
1095  } else {
1096  Py_INCREF(string);
1097  str = string;
1098  }
1099 
1100  if (PyBytes_AsStringAndSize(str, &(jsondata.str), NULL) == -1) {
1101  Py_DECREF(str);
1102  return NULL; /* not a string object or it contains null bytes */
1103  }
1104 
1105  jsondata.ptr = jsondata.str;
1106  jsondata.end = jsondata.str+strlen(jsondata.str);
1107  jsondata.all_unicode = all_unicode;
1108 
1109  object = decode_json(&jsondata);
1110 
1111  if (object != NULL) {
1112  skipSpaces(&jsondata);
1113  if (jsondata.ptr < jsondata.end) {
1114  PyErr_Format(JSON_DecodeError, "extra data after JSON description at position " SSIZE_T_F, (Py_ssize_t)(jsondata.ptr-jsondata.str));
1115  Py_DECREF(str);
1116  Py_DECREF(object);
1117  return NULL;
1118  }
1119  }
1120 
1121  Py_DECREF(str);
1122 
1123  return object;
1124 }
1125 
1126 /* List of functions defined in the module */
1127 
1128 static PyMethodDef cjson_methods[] = {
1129  { "encode", (PyCFunction)JSON_encode, METH_O,
1130  PyDoc_STR("encode(object) -> generate the JSON representation for object.") },
1131 
1132 /* On Python 3.x we normally want Unicode. */
1133  { "decode", (PyCFunction)JSON_decode, METH_VARARGS|METH_KEYWORDS,
1134  PyDoc_STR("decode(string, all_unicode=True) -> parse the JSON representation into\n"
1135  "python objects. The optional argument `all_unicode', specifies how to\n"
1136  "convert the strings in the JSON representation into python objects.\n"
1137  "If it is False (default on Python 2.x), it will return strings/bytes\n"
1138  "everywhere possible and unicode objects only where necessary, else\n"
1139  "it will return unicode objects everywhere (this is slower, but default\n"
1140  "on Python 3.x).")
1141  },
1142  { NULL, NULL, 0, NULL } /* sentinel */
1143 };
1144 
1145 PyDoc_STRVAR(module_doc, "Fast JSON encoder/decoder module.");
1146 
1147 #define MODULE_VERSION "1.0.5"
1148 
1149 static void initcjson_shared(PyObject *m) {
1150  JSON_Error = PyErr_NewException("cjson.Error", NULL, NULL);
1151  if (JSON_Error == NULL)
1152  return;
1153  Py_INCREF(JSON_Error);
1154  PyModule_AddObject(m, "Error", JSON_Error);
1155 
1156  JSON_EncodeError = PyErr_NewException("cjson.EncodeError", JSON_Error, NULL);
1157  if (JSON_EncodeError == NULL)
1158  return;
1159  Py_INCREF(JSON_EncodeError);
1160  PyModule_AddObject(m, "EncodeError", JSON_EncodeError);
1161 
1162  JSON_DecodeError = PyErr_NewException("cjson.DecodeError", JSON_Error, NULL);
1163  if (JSON_DecodeError == NULL)
1164  return;
1165  Py_INCREF(JSON_DecodeError);
1166  PyModule_AddObject(m, "DecodeError", JSON_DecodeError);
1167 
1168  /* Module version (the MODULE_VERSION macro is defined by setup.py) */
1169  PyModule_AddStringConstant(m, "__version__", MODULE_VERSION);
1170 }
1171 
1172 
1173 static PyModuleDef cjsonModule = {
1174  PyModuleDef_HEAD_INIT,
1175  "cjson", /* m_name */
1176  module_doc, /* m_doc */
1177  -1, /* m_size */
1178  cjson_methods, /* m_methods */
1179  NULL, /* m_reload */
1180  NULL, /* m_traverse */
1181  NULL, /* m_clear */
1182  NULL /* m_free */
1183 };
1184 
1185 PyObject* PyInit_cjson(void)
1186 {
1187  PyObject *m;
1188 
1189  m = PyModule_Create(&cjsonModule);
1190 
1191  if (m == NULL)
1192  return NULL;
1193 
1195 
1196  return m;
1197 }
MODULE_VERSION
#define MODULE_VERSION
Definition: cjson.cpp:1147
PY_SSIZE_T_MAX
#define PY_SSIZE_T_MAX
Definition: cjson.cpp:47
object
struct obj object
getRowAndCol
static void getRowAndCol(char *begin, char *current, int *row, int *col)
Definition: cjson.cpp:87
encode_object
static PyObject * encode_object(PyObject *object)
Definition: cjson.cpp:1023
PyInit_cjson
PyObject * PyInit_cjson(void)
Definition: cjson.cpp:1185
Py_ssize_t
int Py_ssize_t
Definition: cjson.cpp:45
JSON_Error
static PyObject * JSON_Error
Definition: cjson.cpp:40
JSONData
Definition: cjson.cpp:16
c
static event_registration c
Definition: citylife.cpp:425
SSIZE_T_F
#define SSIZE_T_F
Definition: cjson.cpp:50
guildoracle.list
list
Definition: guildoracle.py:87
JSON_decode
static PyObject * JSON_decode(PyObject *self, PyObject *args, PyObject *kwargs)
Definition: cjson.cpp:1072
skipSpaces
#define skipSpaces(d)
Definition: cjson.cpp:70
JSONData::ptr
char * ptr
Definition: cjson.cpp:19
encode_list
static PyObject * encode_list(PyObject *object)
Definition: cjson.cpp:856
decode_nan
static PyObject * decode_nan(JSONData *jsondata)
Definition: cjson.cpp:265
obj
Definition: object.h:280
decode_inf
static PyObject * decode_inf(JSONData *jsondata)
Definition: cjson.cpp:238
cjson_methods
static PyMethodDef cjson_methods[]
Definition: cjson.cpp:1128
m
static event_registration m
Definition: citylife.cpp:425
JSON_EncodeError
static PyObject * JSON_EncodeError
Definition: cjson.cpp:41
decode_string
static PyObject * decode_string(JSONData *jsondata)
Definition: cjson.cpp:138
make_face_from_files.args
args
Definition: make_face_from_files.py:31
rotate-tower.result
bool result
Definition: rotate-tower.py:13
NAN
#define NAN
Definition: cjson.cpp:63
JSON_encode
static PyObject * JSON_encode(PyObject *self, PyObject *object)
Definition: cjson.cpp:1065
make_face_from_files.str
str
Definition: make_face_from_files.py:24
False
#define False
Definition: cjson.cpp:56
JSONData::all_unicode
int all_unicode
Definition: cjson.cpp:20
cfpython.h
PyDoc_STRVAR
PyDoc_STRVAR(module_doc, "Fast JSON encoder/decoder module.")
cjson_PyObject_Str
static PyObject * cjson_PyObject_Str(PyObject *obj)
Definition: cjson.cpp:75
nlohmann::detail::void
j template void())
Definition: json.hpp:4099
decode_array
static PyObject * decode_array(JSONData *jsondata)
Definition: cjson.cpp:349
JSON_DecodeError
static PyObject * JSON_DecodeError
Definition: cjson.cpp:42
JSONData
struct JSONData JSONData
autojail.dict
dict
Definition: autojail.py:7
decode_object
static PyObject * decode_object(JSONData *jsondata)
Definition: cjson.cpp:413
encode_dict
static PyObject * encode_dict(PyObject *object)
Definition: cjson.cpp:935
item
Definition: item.py:1
decode_number
static PyObject * decode_number(JSONData *jsondata)
Definition: cjson.cpp:283
give.op
op
Definition: give.py:33
decode_null
static PyObject * decode_null(JSONData *jsondata)
Definition: cjson.cpp:98
autojail.value
value
Definition: autojail.py:6
encode_tuple
static PyObject * encode_tuple(PyObject *object)
Definition: cjson.cpp:793
JSONData::str
char * str
Definition: cjson.cpp:17
INFINITY
#define INFINITY
Definition: cjson.cpp:59
True
#define True
Definition: cjson.cpp:55
initcjson_shared
static void initcjson_shared(PyObject *m)
Definition: cjson.cpp:1149
castle_read.key
key
Definition: castle_read.py:64
encode_string
static PyObject * encode_string(PyObject *object)
Definition: cjson.cpp:586
cjsonModule
static PyModuleDef cjsonModule
Definition: cjson.cpp:1173
Py_IS_NAN
#define Py_IS_NAN(X)
Definition: cjson.cpp:67
say.item
dictionary item
Definition: say.py:149
JSONData::end
char * end
Definition: cjson.cpp:18
decode_json
static PyObject * decode_json(JSONData *jsondata)
Definition: cjson.cpp:508
replace.current
current
Definition: replace.py:64
guildbuy.temp
def temp
Definition: guildbuy.py:26
encode_unicode
static PyObject * encode_unicode(PyObject *object)
Definition: cjson.cpp:651
takeitem.status
status
Definition: takeitem.py:35
decode_bool
static PyObject * decode_bool(JSONData *jsondata)
Definition: cjson.cpp:116
is_valid_types_gen.type
list type
Definition: is_valid_types_gen.py:25