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