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