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:282
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
n
based on the size of the this randomly makes land number of spaces randomly lower or higher The default is Note that this is run also based on the the altitude amount will likely be less So if you do something like l and n
Definition: land.6.txt:25
quote
TIPS on SURVIVING Crossfire is populated with a wealth of different monsters These monsters can have varying immunities and attack types In some of them can be quite a bit smarter than others It will be important for new players to learn the abilities of different monsters and learn just how much it will take to kill them This section discusses how monsters can interact with players Most monsters in the game are out to mindlessly kill and destroy the players These monsters will help boost a player s after he kills them When fighting a large amount of monsters in a single attempt to find a narrower hallway so that you are not being attacked from all sides Charging into a room full of Beholders for instance would not be open the door and fight them one at a time For there are several maps designed for them Find these areas and clear them out All throughout these a player can find signs and books which they can read by stepping onto them and hitting A to apply the book sign These messages will help the player to learn the system One more always keep an eye on your food If your food drops to your character will soon so BE CAREFUL ! NPCs Non Player Character are special monsters which have intelligence Players may be able to interact with these monsters to help solve puzzles and find items of interest To speak with a monster you suspect to be a simply move to an adjacent square to them and push the double quote
Definition: survival-guide.txt:34
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
encode_list
static PyObject * encode_list(PyObject *object)
Definition: cjson.cpp:857
JSONData::end
char * end
Definition: cjson.cpp:19
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
JSONData
Definition: cjson.cpp:17
make_face_from_files.args
args
Definition: make_face_from_files.py:37
rotate-tower.result
bool result
Definition: rotate-tower.py:13
JSONData::all_unicode
int all_unicode
Definition: cjson.cpp:21
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:30
False
#define False
Definition: cjson.cpp:57
cfpython.h
JSONData::str
char * str
Definition: cjson.cpp:18
JSONData::ptr
char * ptr
Definition: cjson.cpp:20
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
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
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