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  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  Py_ssize_t i;
607  char c;
608  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_ssize_t size, pos;
661  char *p;
662  static const char *hexdigit = "0123456789abcdef";
663  static const Py_ssize_t expandsize = 10;
664 
665  int kind = PyUnicode_KIND(unicode);
666  void *data = PyUnicode_DATA(unicode);
667  size = PyUnicode_GET_LENGTH(unicode);
668 
669  if (size > (PY_SSIZE_T_MAX-2-1)/expandsize) {
670  PyErr_SetString(PyExc_OverflowError, "unicode object is too large to make repr");
671  return NULL;
672  }
673 
674  repr = PyByteArray_FromStringAndSize(NULL,
675  2
676  + expandsize*size
677  + 1);
678  if (repr == NULL)
679  return NULL;
680 
681  p = PyByteArray_AS_STRING(repr);
682 
683  *p++ = '"';
684  pos = 0;
685 
686  const Py_UCS4 quote = PyByteArray_AS_STRING(repr)[0];
687 
688  while (pos < size) {
689  Py_UCS4 ch = PyUnicode_READ(kind, data, pos);
690  pos++;
691 
692  /* Escape quotes */
693  if ((ch == quote || ch == '\\')) {
694  *p++ = '\\';
695  *p++ = (char)ch;
696  continue;
697  }
698 
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  /* Map 16-bit characters to '\uxxxx' */
714  if (ch >= 256) {
715  *p++ = '\\';
716  *p++ = 'u';
717  *p++ = hexdigit[(ch>>12)&0x000F];
718  *p++ = hexdigit[(ch>>8)&0x000F];
719  *p++ = hexdigit[(ch>>4)&0x000F];
720  *p++ = hexdigit[ch&0x000F];
721  /* Map special whitespace to '\t', \n', '\r', '\f', '\b' */
722  } else if (ch == '\t') {
723  *p++ = '\\';
724  *p++ = 't';
725  } else if (ch == '\n') {
726  *p++ = '\\';
727  *p++ = 'n';
728  } else if (ch == '\r') {
729  *p++ = '\\';
730  *p++ = 'r';
731  } else if (ch == '\f') {
732  *p++ = '\\';
733  *p++ = 'f';
734  } else if (ch == '\b') {
735  *p++ = '\\';
736  *p++ = 'b';
737  }
738 
739  /* Map non-printable US ASCII to '\u00hh' */
740  else if (ch < ' ' || ch >= 0x7F) {
741  *p++ = '\\';
742  *p++ = 'u';
743  *p++ = '0';
744  *p++ = '0';
745  *p++ = hexdigit[(ch>>4)&0x000F];
746  *p++ = hexdigit[ch&0x000F];
747  }
748 
749  /* Copy everything else as-is */
750  else
751  *p++ = (char)ch;
752  }
753 
754  *p++ = PyByteArray_AS_STRING(repr)[0];
755 
756  *p = '\0';
757  {
758  PyObject *result = PyBytes_FromStringAndSize(PyByteArray_AS_STRING(repr),
759  p - PyByteArray_AS_STRING(repr));
760  Py_DECREF(repr);
761  return result;
762  }
763 }
764 
765 /*
766  * This function is an almost verbatim copy of tuplerepr() from
767  * Python's tupleobject.c with the following differences:
768  *
769  * - it uses encode_object() to get the object's JSON reprezentation.
770  * - it uses [] as decorations isntead of () (to masquerade as a JSON array).
771  */
772 
773 static PyObject *encode_tuple(PyObject *tuple) {
774  Py_ssize_t i, n;
775  PyObject *s, *temp;
776  PyObject *pieces, *result = NULL;
777  PyTupleObject *v = (PyTupleObject *)tuple;
778 
779  n = Py_SIZE(v);
780  if (n == 0)
781  return PyBytes_FromString("[]");
782 
783  pieces = PyTuple_New(n);
784  if (pieces == NULL)
785  return NULL;
786 
787  /* Do repr() on each element. */
788  for (i = 0; i < n; ++i) {
789  s = encode_object(v->ob_item[i]);
790  if (s == NULL)
791  goto Done;
792  PyTuple_SET_ITEM(pieces, i, s);
793  }
794 
795  /* Add "[]" decorations to the first and last items. */
796  assert(n > 0);
797  s = PyBytes_FromString("[");
798  if (s == NULL)
799  goto Done;
800  temp = PyTuple_GET_ITEM(pieces, 0);
801  PyBytes_ConcatAndDel(&s, temp);
802  PyTuple_SET_ITEM(pieces, 0, s);
803  if (s == NULL)
804  goto Done;
805 
806  s = PyBytes_FromString("]");
807  if (s == NULL)
808  goto Done;
809  temp = PyTuple_GET_ITEM(pieces, n-1);
810  PyBytes_ConcatAndDel(&temp, s);
811  PyTuple_SET_ITEM(pieces, n-1, temp);
812  if (temp == NULL)
813  goto Done;
814 
815  /* Paste them all together with ", " between. */
816  s = PyBytes_FromString(", ");
817  if (s == NULL)
818  goto Done;
819  result = _PyBytes_Join(s, pieces);
820  Py_DECREF(s);
821 
822 Done:
823  Py_DECREF(pieces);
824  return result;
825 }
826 
827 /*
828  * This function is an almost verbatim copy of list_repr() from
829  * Python's listobject.c with the following differences:
830  *
831  * - it uses encode_object() to get the object's JSON reprezentation.
832  * - it doesn't use the ellipsis to represent a list with references
833  * to itself, instead it raises an exception as such lists cannot be
834  * represented in JSON.
835  */
836 static PyObject *encode_list(PyObject *list) {
837  Py_ssize_t i;
838  PyObject *s, *temp;
839  PyObject *pieces = NULL, *result = NULL;
840  PyListObject *v = (PyListObject *)list;
841 
842  i = Py_ReprEnter((PyObject *)v);
843  if (i != 0) {
844  if (i > 0) {
845  PyErr_SetString(JSON_EncodeError, "a list with references to itself is not JSON encodable");
846  }
847  return NULL;
848  }
849 
850  if (Py_SIZE(v) == 0) {
851  result = PyBytes_FromString("[]");
852  goto Done;
853  }
854 
855  pieces = PyList_New(0);
856  if (pieces == NULL)
857  goto Done;
858 
859  /* Do repr() on each element. Note that this may mutate the list,
860  * so must refetch the list size on each iteration. */
861  for (i = 0; i < Py_SIZE(v); ++i) {
862  int status;
863  s = encode_object(v->ob_item[i]);
864  if (s == NULL)
865  goto Done;
866  status = PyList_Append(pieces, s);
867  Py_DECREF(s); /* append created a new ref */
868  if (status < 0)
869  goto Done;
870  }
871 
872  /* Add "[]" decorations to the first and last items. */
873  assert(PyList_GET_SIZE(pieces) > 0);
874  s = PyBytes_FromString("[");
875  if (s == NULL)
876  goto Done;
877  temp = PyList_GET_ITEM(pieces, 0);
878  PyBytes_ConcatAndDel(&s, temp);
879  PyList_SET_ITEM(pieces, 0, s);
880  if (s == NULL)
881  goto Done;
882 
883  s = PyBytes_FromString("]");
884  if (s == NULL)
885  goto Done;
886  temp = PyList_GET_ITEM(pieces, PyList_GET_SIZE(pieces)-1);
887  PyBytes_ConcatAndDel(&temp, s);
888  PyList_SET_ITEM(pieces, PyList_GET_SIZE(pieces)-1, temp);
889  if (temp == NULL)
890  goto Done;
891 
892  /* Paste them all together with ", " between. */
893  s = PyBytes_FromString(", ");
894  if (s == NULL)
895  goto Done;
896  result = _PyBytes_Join(s, pieces);
897  Py_DECREF(s);
898 
899 Done:
900  Py_XDECREF(pieces);
901  Py_ReprLeave((PyObject *)v);
902  return result;
903 }
904 
905 /*
906  * This function is an almost verbatim copy of dict_repr() from
907  * Python's dictobject.c with the following differences:
908  *
909  * - it uses encode_object() to get the object's JSON reprezentation.
910  * - only accept strings for keys.
911  * - it doesn't use the ellipsis to represent a dictionary with references
912  * to itself, instead it raises an exception as such dictionaries cannot
913  * be represented in JSON.
914  */
915 static PyObject *encode_dict(PyObject *dict) {
916  Py_ssize_t i;
917  PyObject *s, *temp, *colon = NULL;
918  PyObject *pieces = NULL, *result = NULL;
919  PyObject *key, *value;
920  PyDictObject *mp = (PyDictObject *)dict;
921 
922  i = Py_ReprEnter((PyObject *)mp);
923  if (i != 0) {
924  if (i > 0) {
925  PyErr_SetString(JSON_EncodeError, "a dict with references to "
926  "itself is not JSON encodable");
927  }
928  return NULL;
929  }
930 
931  if (mp->ma_used == 0) {
932  result = PyBytes_FromString("{}");
933  goto Done;
934  }
935 
936  pieces = PyList_New(0);
937  if (pieces == NULL)
938  goto Done;
939 
940  colon = PyBytes_FromString(": ");
941  if (colon == NULL)
942  goto Done;
943 
944  /* Do repr() on each key+value pair, and insert ": " between them.
945  * Note that repr may mutate the dict. */
946  i = 0;
947  while (PyDict_Next((PyObject *)mp, &i, &key, &value)) {
948  int status;
949 
950  if (!PyBytes_Check(key) && !PyUnicode_Check(key)) {
951  PyErr_SetString(JSON_EncodeError, "JSON encodable dictionaries must have string/unicode keys");
952  goto Done;
953  }
954 
955  /* Prevent repr from deleting value during key format. */
956  Py_INCREF(value);
957  s = encode_object(key);
958  PyBytes_Concat(&s, colon);
959  PyBytes_ConcatAndDel(&s, encode_object(value));
960  Py_DECREF(value);
961  if (s == NULL)
962  goto Done;
963  status = PyList_Append(pieces, s);
964  Py_DECREF(s); /* append created a new ref */
965  if (status < 0)
966  goto Done;
967  }
968 
969  /* Add "{}" decorations to the first and last items. */
970  assert(PyList_GET_SIZE(pieces) > 0);
971  s = PyBytes_FromString("{");
972  if (s == NULL)
973  goto Done;
974  temp = PyList_GET_ITEM(pieces, 0);
975  PyBytes_ConcatAndDel(&s, temp);
976  PyList_SET_ITEM(pieces, 0, s);
977  if (s == NULL)
978  goto Done;
979 
980  s = PyBytes_FromString("}");
981  if (s == NULL)
982  goto Done;
983  temp = PyList_GET_ITEM(pieces, PyList_GET_SIZE(pieces)-1);
984  PyBytes_ConcatAndDel(&temp, s);
985  PyList_SET_ITEM(pieces, PyList_GET_SIZE(pieces)-1, temp);
986  if (temp == NULL)
987  goto Done;
988 
989  /* Paste them all together with ", " between. */
990  s = PyBytes_FromString(", ");
991  if (s == NULL)
992  goto Done;
993  result = _PyBytes_Join(s, pieces);
994  Py_DECREF(s);
995 
996 Done:
997  Py_XDECREF(pieces);
998  Py_XDECREF(colon);
999  Py_ReprLeave((PyObject *)mp);
1000  return result;
1001 }
1002 
1003 static PyObject *encode_object(PyObject *object) {
1004  if (object == Py_True) {
1005  return PyBytes_FromString("true");
1006  } else if (object == Py_False) {
1007  return PyBytes_FromString("false");
1008  } else if (object == Py_None) {
1009  return PyBytes_FromString("null");
1010  } else if (PyBytes_Check(object)) {
1011  return encode_string(object);
1012  } else if (PyUnicode_Check(object)) {
1013  return encode_unicode(object);
1014  } else if (PyFloat_Check(object)) {
1015  double val = PyFloat_AS_DOUBLE(object);
1016  if (Py_IS_NAN(val)) {
1017  return PyBytes_FromString("NaN");
1018  } else if (Py_IS_INFINITY(val)) {
1019  if (val > 0) {
1020  return PyBytes_FromString("Infinity");
1021  } else {
1022  return PyBytes_FromString("-Infinity");
1023  }
1024  } else {
1025  return cjson_PyObject_Str(object);
1026  }
1027  }
1028  else if (PyLong_Check(object)) {
1029  return cjson_PyObject_Str(object);
1030  }
1031  else if (PyList_Check(object)) {
1032  return encode_list(object);
1033  } else if (PyTuple_Check(object)) {
1034  return encode_tuple(object);
1035  } else if (PyDict_Check(object)) { /* use PyMapping_Check(object) instead? -Dan */
1036  return encode_dict(object);
1037  } else {
1038  PyErr_SetString(JSON_EncodeError, "object is not JSON encodable");
1039  return NULL;
1040  }
1041 }
1042 
1043 /* Encode object into its JSON representation */
1044 
1045 static PyObject *JSON_encode(PyObject *self, PyObject *object) {
1046  (void)self;
1047  return encode_object(object);
1048 }
1049 
1050 /* Decode JSON representation into pyhton objects */
1051 
1052 static PyObject *JSON_decode(PyObject *self, PyObject *args, PyObject *kwargs) {
1053  static char *kwlist[] = { (char*)"json", (char*)"all_unicode", NULL };
1054  int all_unicode = True; /* by default return unicode always */
1055  PyObject *object, *string, *str;
1056  JSONData jsondata;
1057  (void)self;
1058 
1059  if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:decode", kwlist, &string, &all_unicode))
1060  return NULL;
1061 
1062  if (PyUnicode_Check(string)) {
1063  // PyUnicode_EncodeRawUnicodeEscape() is deprecated as of Python 3.3, scheduled for removal in Python 3.11
1064 #ifndef IS_PY3K3
1065  /* HACK: Workaround for crash bug in Python3's PyUnicode_AsRawUnicodeEscapeString... */
1066  str = PyUnicode_EncodeRawUnicodeEscape(PyUnicode_AS_UNICODE(string),
1067  PyUnicode_GET_SIZE(string));
1068 #else
1069  // The Python docs recommend using PyUnicode_AsRawUnicodeEscapeString() or PyUnicode_AsEncodedString() over PyUnicode_EncodeRawUnicodeEscape().
1070  str = PyUnicode_AsRawUnicodeEscapeString(string);
1071 #endif
1072  if (str == NULL) {
1073  return NULL;
1074  }
1075  } else {
1076  Py_INCREF(string);
1077  str = string;
1078  }
1079 
1080  if (PyBytes_AsStringAndSize(str, &(jsondata.str), NULL) == -1) {
1081  Py_DECREF(str);
1082  return NULL; /* not a string object or it contains null bytes */
1083  }
1084 
1085  jsondata.ptr = jsondata.str;
1086  jsondata.end = jsondata.str+strlen(jsondata.str);
1087  jsondata.all_unicode = all_unicode;
1088 
1089  object = decode_json(&jsondata);
1090 
1091  if (object != NULL) {
1092  skipSpaces(&jsondata);
1093  if (jsondata.ptr < jsondata.end) {
1094  PyErr_Format(JSON_DecodeError, "extra data after JSON description at position " SSIZE_T_F, (Py_ssize_t)(jsondata.ptr-jsondata.str));
1095  Py_DECREF(str);
1096  Py_DECREF(object);
1097  return NULL;
1098  }
1099  }
1100 
1101  Py_DECREF(str);
1102 
1103  return object;
1104 }
1105 
1106 /* List of functions defined in the module */
1107 
1108 static PyMethodDef cjson_methods[] = {
1109  { "encode", (PyCFunction)JSON_encode, METH_O,
1110  PyDoc_STR("encode(object) -> generate the JSON representation for object.") },
1111 
1112 /* On Python 3.x we normally want Unicode. */
1113  { "decode", (PyCFunction)JSON_decode, METH_VARARGS|METH_KEYWORDS,
1114  PyDoc_STR("decode(string, all_unicode=True) -> parse the JSON representation into\n"
1115  "python objects. The optional argument `all_unicode', specifies how to\n"
1116  "convert the strings in the JSON representation into python objects.\n"
1117  "If it is False (default on Python 2.x), it will return strings/bytes\n"
1118  "everywhere possible and unicode objects only where necessary, else\n"
1119  "it will return unicode objects everywhere (this is slower, but default\n"
1120  "on Python 3.x).")
1121  },
1122  { NULL, NULL, 0, NULL } /* sentinel */
1123 };
1124 
1125 PyDoc_STRVAR(module_doc, "Fast JSON encoder/decoder module.");
1126 
1127 #define MODULE_VERSION "1.0.5"
1128 
1129 static void initcjson_shared(PyObject *m) {
1130  JSON_Error = PyErr_NewException("cjson.Error", NULL, NULL);
1131  if (JSON_Error == NULL)
1132  return;
1133  Py_INCREF(JSON_Error);
1134  PyModule_AddObject(m, "Error", JSON_Error);
1135 
1136  JSON_EncodeError = PyErr_NewException("cjson.EncodeError", JSON_Error, NULL);
1137  if (JSON_EncodeError == NULL)
1138  return;
1139  Py_INCREF(JSON_EncodeError);
1140  PyModule_AddObject(m, "EncodeError", JSON_EncodeError);
1141 
1142  JSON_DecodeError = PyErr_NewException("cjson.DecodeError", JSON_Error, NULL);
1143  if (JSON_DecodeError == NULL)
1144  return;
1145  Py_INCREF(JSON_DecodeError);
1146  PyModule_AddObject(m, "DecodeError", JSON_DecodeError);
1147 
1148  /* Module version (the MODULE_VERSION macro is defined by setup.py) */
1149  PyModule_AddStringConstant(m, "__version__", MODULE_VERSION);
1150 }
1151 
1152 
1153 static PyModuleDef cjsonModule = {
1154  PyModuleDef_HEAD_INIT,
1155  "cjson", /* m_name */
1156  module_doc, /* m_doc */
1157  -1, /* m_size */
1158  cjson_methods, /* m_methods */
1159  NULL, /* m_reload */
1160  NULL, /* m_traverse */
1161  NULL, /* m_clear */
1162  NULL /* m_free */
1163 };
1164 
1165 PyObject* PyInit_cjson(void)
1166 {
1167  PyObject *m;
1168 
1169  m = PyModule_Create(&cjsonModule);
1170 
1171  if (m == NULL)
1172  return NULL;
1173 
1175 
1176  return m;
1177 }
1178 
1179 #ifdef IS_PY3K9
1180 #pragma GCC diagnostic pop
1181 #endif
MODULE_VERSION
#define MODULE_VERSION
Definition: cjson.cpp:1127
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:1003
PyInit_cjson
PyObject * PyInit_cjson(void)
Definition: cjson.cpp:1165
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:1052
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:836
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:1108
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:1045
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
navar-midane_time.data
data
Definition: navar-midane_time.py:11
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:915
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:773
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:1129
encode_string
static PyObject * encode_string(PyObject *object)
Definition: cjson.cpp:593
cjsonModule
static PyModuleDef cjsonModule
Definition: cjson.cpp:1153
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