00001
00002
00003
00004
00005
00006
00007
00008
00009 #include <Python.h>
00010 #include <stddef.h>
00011 #include <stdio.h>
00012 #include <ctype.h>
00013 #include <math.h>
00014
00015 typedef struct JSONData {
00016 char *str;
00017 char *end;
00018 char *ptr;
00019 int all_unicode;
00020 } JSONData;
00021
00022 static PyObject *encode_object(PyObject *object);
00023 static PyObject *encode_string(PyObject *object);
00024 static PyObject *encode_unicode(PyObject *object);
00025 static PyObject *encode_tuple(PyObject *object);
00026 static PyObject *encode_list(PyObject *object);
00027 static PyObject *encode_dict(PyObject *object);
00028
00029 static PyObject *decode_json(JSONData *jsondata);
00030 static PyObject *decode_null(JSONData *jsondata);
00031 static PyObject *decode_bool(JSONData *jsondata);
00032 static PyObject *decode_string(JSONData *jsondata);
00033 static PyObject *decode_inf(JSONData *jsondata);
00034 static PyObject *decode_nan(JSONData *jsondata);
00035 static PyObject *decode_number(JSONData *jsondata);
00036 static PyObject *decode_array(JSONData *jsondata);
00037 static PyObject *decode_object(JSONData *jsondata);
00038
00039 static PyObject *JSON_Error;
00040 static PyObject *JSON_EncodeError;
00041 static PyObject *JSON_DecodeError;
00042
00043 #if PY_VERSION_HEX < 0x02050000
00044 typedef int Py_ssize_t;
00045
00046 #define PY_SSIZE_T_MAX INT_MAX
00047 #define PY_SSIZE_T_MIN INT_MIN
00048
00049 #define SSIZE_T_F "%d"
00050 #else
00051 #define SSIZE_T_F "%zd"
00052 #endif
00053
00054 #define True 1
00055 #define False 0
00056
00057 #ifndef INFINITY
00058 #define INFINITY HUGE_VAL
00059 #endif
00060
00061 #ifndef NAN
00062 #define NAN (HUGE_VAL-HUGE_VAL)
00063 #endif
00064
00065 #ifndef Py_IS_NAN
00066 #define Py_IS_NAN(X) ((X) != (X))
00067 #endif
00068
00069 #define skipSpaces(d) while (*((d)->ptr) && isspace(*((d)->ptr))) (d)->ptr++
00070
00071
00072
00073 static void getRowAndCol(char *begin, char *current, int *row, int *col) {
00074 *col = 1;
00075 *row = 1;
00076 while (current > begin) {
00077 if (*current == '\n')
00078 (*row)++;
00079 if (*row < 2)
00080 (*col)++;
00081 current--;
00082 }
00083 }
00084 static PyObject *decode_null(JSONData *jsondata) {
00085 ptrdiff_t left;
00086
00087 left = jsondata->end-jsondata->ptr;
00088
00089 if (left >= 4 && strncmp(jsondata->ptr, "null", 4) == 0) {
00090 jsondata->ptr += 4;
00091 Py_INCREF(Py_None);
00092 return Py_None;
00093 } else {
00094 int row, col;
00095
00096 getRowAndCol(jsondata->str, jsondata->ptr, &row, &col);
00097 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);
00098 return NULL;
00099 }
00100 }
00101
00102 static PyObject *decode_bool(JSONData *jsondata) {
00103 ptrdiff_t left;
00104
00105 left = jsondata->end-jsondata->ptr;
00106
00107 if (left >= 4 && strncmp(jsondata->ptr, "true", 4) == 0) {
00108 jsondata->ptr += 4;
00109 Py_INCREF(Py_True);
00110 return Py_True;
00111 } else if (left >= 5 && strncmp(jsondata->ptr, "false", 5) == 0) {
00112 jsondata->ptr += 5;
00113 Py_INCREF(Py_False);
00114 return Py_False;
00115 } else {
00116 int row, col;
00117
00118 getRowAndCol(jsondata->str, jsondata->ptr, &row, &col);
00119 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);
00120 return NULL;
00121 }
00122 }
00123
00124 static PyObject *decode_string(JSONData *jsondata) {
00125 PyObject *object;
00126 int c, escaping, has_unicode, string_escape;
00127 Py_ssize_t len;
00128 char *ptr;
00129
00130
00131 escaping = has_unicode = string_escape = False;
00132 ptr = jsondata->ptr+1;
00133 while (True) {
00134 c = *ptr;
00135 if (c == 0) {
00136 int row, col;
00137
00138 getRowAndCol(jsondata->str, jsondata->ptr, &row, &col);
00139 PyErr_Format(JSON_DecodeError, "unterminated string starting at position "SSIZE_T_F"(row "SSIZE_T_F", col "SSIZE_T_F")",
00140 (Py_ssize_t)(jsondata->ptr-jsondata->str), (Py_ssize_t)row, (Py_ssize_t)col);
00141 return NULL;
00142 }
00143 if (!escaping) {
00144 if (c == '\\') {
00145 escaping = True;
00146 } else if (c == '"') {
00147 break;
00148 } else if (!isascii(c)) {
00149 has_unicode = True;
00150 }
00151 } else {
00152 switch (c) {
00153 case 'u':
00154 has_unicode = True;
00155 break;
00156 case '"':
00157 case 'r':
00158 case 'n':
00159 case 't':
00160 case 'b':
00161 case 'f':
00162 case '\\':
00163 string_escape = True;
00164 break;
00165 }
00166 escaping = False;
00167 }
00168 ptr++;
00169 }
00170
00171 len = ptr-jsondata->ptr-1;
00172
00173 if (has_unicode || jsondata->all_unicode)
00174 object = PyUnicode_DecodeUnicodeEscape(jsondata->ptr+1, len, NULL);
00175 else if (string_escape)
00176 object = PyString_DecodeEscape(jsondata->ptr+1, len, NULL, 0, NULL);
00177 else
00178 object = PyString_FromStringAndSize(jsondata->ptr+1, len);
00179
00180 if (object == NULL) {
00181 PyObject *type, *value, *tb, *reason;
00182
00183 PyErr_Fetch(&type, &value, &tb);
00184 if (type == NULL) {
00185 int row, col;
00186
00187 getRowAndCol(jsondata->str, jsondata->ptr, &row, &col);
00188 PyErr_Format(JSON_DecodeError, "invalid string starting at position "SSIZE_T_F"(row "SSIZE_T_F", col "SSIZE_T_F")",
00189 (Py_ssize_t)(jsondata->ptr-jsondata->str), (Py_ssize_t)row, (Py_ssize_t)col);
00190 } else {
00191 if (PyErr_GivenExceptionMatches(type, PyExc_UnicodeDecodeError)) {
00192 int row, col;
00193
00194 reason = PyObject_GetAttrString(value, "reason");
00195 getRowAndCol(jsondata->str, jsondata->ptr, &row, &col);
00196 PyErr_Format(JSON_DecodeError, "cannot decode string starting" " at position "SSIZE_T_F"(row "SSIZE_T_F", col "SSIZE_T_F"): %s",
00197 (Py_ssize_t)(jsondata->ptr-jsondata->str), (Py_ssize_t)row, (Py_ssize_t)col,
00198 reason ? PyString_AsString(reason) : "bad format");
00199 Py_XDECREF(reason);
00200 } else {
00201 int row, col;
00202
00203 getRowAndCol(jsondata->str, jsondata->ptr, &row, &col);
00204 PyErr_Format(JSON_DecodeError, "invalid string starting at position "SSIZE_T_F"(row "SSIZE_T_F", col "SSIZE_T_F")",
00205 (Py_ssize_t)(jsondata->ptr-jsondata->str), (Py_ssize_t)row, (Py_ssize_t)col);
00206 }
00207 }
00208 Py_XDECREF(type);
00209 Py_XDECREF(value);
00210 Py_XDECREF(tb);
00211 } else {
00212 jsondata->ptr = ptr+1;
00213 }
00214
00215 return object;
00216 }
00217
00218 static PyObject *decode_inf(JSONData *jsondata) {
00219 PyObject *object;
00220 ptrdiff_t left;
00221
00222 left = jsondata->end-jsondata->ptr;
00223
00224 if (left >= 8 && strncmp(jsondata->ptr, "Infinity", 8) == 0) {
00225 jsondata->ptr += 8;
00226 object = PyFloat_FromDouble(INFINITY);
00227 return object;
00228 } else if (left >= 9 && strncmp(jsondata->ptr, "+Infinity", 9) == 0) {
00229 jsondata->ptr += 9;
00230 object = PyFloat_FromDouble(INFINITY);
00231 return object;
00232 } else if (left >= 9 && strncmp(jsondata->ptr, "-Infinity", 9) == 0) {
00233 jsondata->ptr += 9;
00234 object = PyFloat_FromDouble(-INFINITY);
00235 return object;
00236 } else {
00237 int row, col;
00238
00239 getRowAndCol(jsondata->str, jsondata->ptr, &row, &col);
00240 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);
00241 return NULL;
00242 }
00243 }
00244
00245 static PyObject *decode_nan(JSONData *jsondata) {
00246 PyObject *object;
00247 ptrdiff_t left;
00248
00249 left = jsondata->end-jsondata->ptr;
00250
00251 if (left >= 3 && strncmp(jsondata->ptr, "NaN", 3) == 0) {
00252 jsondata->ptr += 3;
00253 object = PyFloat_FromDouble(NAN);
00254 return object;
00255 } else {
00256 int row, col;
00257 getRowAndCol(jsondata->str, jsondata->ptr, &row, &col);
00258 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);
00259 return NULL;
00260 }
00261 }
00262
00263 static PyObject *decode_number(JSONData *jsondata) {
00264 PyObject *object, *str;
00265 int c, is_float, should_stop;
00266 char *ptr;
00267
00268
00269 ptr = jsondata->ptr;
00270 is_float = should_stop = False;
00271 while (True) {
00272 c = *ptr;
00273 if (c == 0)
00274 break;
00275 switch (c) {
00276 case '0':
00277 case '1':
00278 case '2':
00279 case '3':
00280 case '4':
00281 case '5':
00282 case '6':
00283 case '7':
00284 case '8':
00285 case '9':
00286 case '-':
00287 case '+':
00288 break;
00289
00290 case '.':
00291 case 'e':
00292 case 'E':
00293 is_float = True;
00294 break;
00295
00296 default:
00297 should_stop = True;
00298 }
00299 if (should_stop) {
00300 break;
00301 }
00302 ptr++;
00303 }
00304
00305 str = PyString_FromStringAndSize(jsondata->ptr, ptr-jsondata->ptr);
00306 if (str == NULL)
00307 return NULL;
00308
00309 if (is_float) {
00310 object = PyFloat_FromString(str, NULL);
00311 } else {
00312 object = PyInt_FromString(PyString_AS_STRING(str), NULL, 10);
00313 }
00314
00315 Py_DECREF(str);
00316
00317 if (object == NULL) {
00318 int row, col;
00319
00320 getRowAndCol(jsondata->str, jsondata->ptr, &row, &col);
00321 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);
00322 } else {
00323 jsondata->ptr = ptr;
00324 }
00325
00326 return object;
00327 }
00328
00329 static PyObject *decode_array(JSONData *jsondata) {
00330 PyObject *object, *item;
00331 int c, expect_item, items, result;
00332 char *start;
00333
00334 object = PyList_New(0);
00335
00336 start = jsondata->ptr;
00337 jsondata->ptr++;
00338 expect_item = True;
00339 items = 0;
00340 while (True) {
00341 skipSpaces(jsondata);
00342 c = *jsondata->ptr;
00343 if (c == 0) {
00344 int row, col;
00345
00346 getRowAndCol(jsondata->str, jsondata->ptr, &row, &col);
00347 PyErr_Format(JSON_DecodeError, "unterminated array starting at position "SSIZE_T_F"(row "SSIZE_T_F", col "SSIZE_T_F")",
00348 (Py_ssize_t)(start-jsondata->str), (Py_ssize_t)row, (Py_ssize_t)col);
00349 goto failure;
00350 } else if (c == ']') {
00351 if (expect_item && items > 0) {
00352 int row, col;
00353
00354 getRowAndCol(jsondata->str, jsondata->ptr, &row, &col);
00355 PyErr_Format(JSON_DecodeError, "expecting array item at position "SSIZE_T_F"(row "SSIZE_T_F", col "SSIZE_T_F")",
00356 (Py_ssize_t)(jsondata->ptr-jsondata->str), (Py_ssize_t)row, (Py_ssize_t)col);
00357 goto failure;
00358 }
00359 jsondata->ptr++;
00360 break;
00361 } else if (c == ',') {
00362 if (expect_item) {
00363 int row, col;
00364
00365 getRowAndCol(jsondata->str, jsondata->ptr, &row, &col);
00366 PyErr_Format(JSON_DecodeError, "expecting array item at position "SSIZE_T_F"(row "SSIZE_T_F", col "SSIZE_T_F")",
00367 (Py_ssize_t)(jsondata->ptr-jsondata->str), (Py_ssize_t)row, (Py_ssize_t)col);
00368 goto failure;
00369 }
00370 expect_item = True;
00371 jsondata->ptr++;
00372 continue;
00373 } else {
00374 item = decode_json(jsondata);
00375 if (item == NULL)
00376 goto failure;
00377 result = PyList_Append(object, item);
00378 Py_DECREF(item);
00379 if (result == -1)
00380 goto failure;
00381 expect_item = False;
00382 items++;
00383 }
00384 }
00385
00386 return object;
00387
00388 failure:
00389 Py_DECREF(object);
00390 return NULL;
00391 }
00392
00393 static PyObject *decode_object(JSONData *jsondata) {
00394 PyObject *object, *key, *value;
00395 int c, expect_key, items, result;
00396 char *start;
00397
00398 object = PyDict_New();
00399
00400 expect_key = True;
00401 items = 0;
00402 start = jsondata->ptr;
00403 jsondata->ptr++;
00404
00405 while (True) {
00406 skipSpaces(jsondata);
00407 c = *jsondata->ptr;
00408 if (c == 0) {
00409 int row, col;
00410
00411 getRowAndCol(jsondata->str, jsondata->ptr, &row, &col);
00412 PyErr_Format(JSON_DecodeError, "unterminated object starting at position "SSIZE_T_F"(row "SSIZE_T_F", col "SSIZE_T_F")",
00413 (Py_ssize_t)(start-jsondata->str), (Py_ssize_t)row, (Py_ssize_t)col);
00414 goto failure;
00415 } else if (c == '}') {
00416 if (expect_key && items > 0) {
00417 int row, col;
00418
00419 getRowAndCol(jsondata->str, jsondata->ptr, &row, &col);
00420 PyErr_Format(JSON_DecodeError, "expecting object property name at position "SSIZE_T_F"(row "SSIZE_T_F", col "SSIZE_T_F")",
00421 (Py_ssize_t)(jsondata->ptr-jsondata->str), (Py_ssize_t)row, (Py_ssize_t)col);
00422 goto failure;
00423 }
00424 jsondata->ptr++;
00425 break;
00426 } else if (c == ',') {
00427 if (expect_key) {
00428 int row, col;
00429
00430 getRowAndCol(jsondata->str, jsondata->ptr, &row, &col);
00431 PyErr_Format(JSON_DecodeError, "expecting object property name at position "SSIZE_T_F"(row "SSIZE_T_F", col "SSIZE_T_F")",
00432 (Py_ssize_t)(jsondata->ptr-jsondata->str), (Py_ssize_t)row, (Py_ssize_t)col);
00433 goto failure;
00434 }
00435 expect_key = True;
00436 jsondata->ptr++;
00437 continue;
00438 } else {
00439 if (c != '"') {
00440 int row, col;
00441
00442 getRowAndCol(jsondata->str, jsondata->ptr, &row, &col);
00443 PyErr_Format(JSON_DecodeError, "expecting property name in object at position "SSIZE_T_F"(row "SSIZE_T_F", col "SSIZE_T_F")",
00444 (Py_ssize_t)(jsondata->ptr-jsondata->str), (Py_ssize_t)row, (Py_ssize_t)col);
00445 goto failure;
00446 }
00447
00448 key = decode_json(jsondata);
00449 if (key == NULL)
00450 goto failure;
00451
00452 skipSpaces(jsondata);
00453 if (*jsondata->ptr != ':') {
00454 int row, col;
00455
00456 getRowAndCol(jsondata->str, jsondata->ptr, &row, &col);
00457 PyErr_Format(JSON_DecodeError, "missing colon after object property name at position "SSIZE_T_F"(row "SSIZE_T_F", col "SSIZE_T_F")",
00458 (Py_ssize_t)(jsondata->ptr-jsondata->str), (Py_ssize_t)row, (Py_ssize_t)col);
00459 Py_DECREF(key);
00460 goto failure;
00461 } else {
00462 jsondata->ptr++;
00463 }
00464
00465 value = decode_json(jsondata);
00466 if (value == NULL) {
00467 Py_DECREF(key);
00468 goto failure;
00469 }
00470
00471 result = PyDict_SetItem(object, key, value);
00472 Py_DECREF(key);
00473 Py_DECREF(value);
00474 if (result == -1)
00475 goto failure;
00476 expect_key = False;
00477 items++;
00478 }
00479 }
00480
00481 return object;
00482
00483 failure:
00484 Py_DECREF(object);
00485 return NULL;
00486 }
00487
00488 static PyObject *decode_json(JSONData *jsondata) {
00489 PyObject *object;
00490
00491 skipSpaces(jsondata);
00492 switch (*jsondata->ptr) {
00493 case 0:
00494 PyErr_SetString(JSON_DecodeError, "empty JSON description");
00495 return NULL;
00496
00497 case '{':
00498 object = decode_object(jsondata);
00499 break;
00500
00501 case '[':
00502 object = decode_array(jsondata);
00503 break;
00504
00505 case '"':
00506 object = decode_string(jsondata);
00507 break;
00508
00509 case 't':
00510 case 'f':
00511 object = decode_bool(jsondata);
00512 break;
00513
00514 case 'n':
00515 object = decode_null(jsondata);
00516 break;
00517
00518 case 'N':
00519 object = decode_nan(jsondata);
00520 break;
00521
00522 case 'I':
00523 object = decode_inf(jsondata);
00524 break;
00525
00526 case '+':
00527 case '-':
00528 if (*(jsondata->ptr+1) == 'I') {
00529 object = decode_inf(jsondata);
00530 } else {
00531 object = decode_number(jsondata);
00532 }
00533 break;
00534
00535 case '0':
00536 case '1':
00537 case '2':
00538 case '3':
00539 case '4':
00540 case '5':
00541 case '6':
00542 case '7':
00543 case '8':
00544 case '9':
00545 object = decode_number(jsondata);
00546 break;
00547
00548 default:
00549 PyErr_SetString(JSON_DecodeError, "cannot parse JSON description");
00550 return NULL;
00551 }
00552
00553 return object;
00554 }
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566 static PyObject *encode_string(PyObject *string) {
00567 register PyStringObject *op = (PyStringObject *)string;
00568 size_t newsize = 2+6*op->ob_size;
00569 PyObject *v;
00570
00571 if (op->ob_size > (PY_SSIZE_T_MAX-2)/6) {
00572 PyErr_SetString(PyExc_OverflowError, "string is too large to make repr");
00573 return NULL;
00574 }
00575 v = PyString_FromStringAndSize((char *)NULL, newsize);
00576 if (v == NULL) {
00577 return NULL;
00578 } else {
00579 register Py_ssize_t i;
00580 register char c;
00581 register char *p;
00582 int quote;
00583
00584 quote = '"';
00585
00586 p = PyString_AS_STRING(v);
00587 *p++ = quote;
00588 for (i = 0; i < op->ob_size; i++) {
00589
00590
00591 assert(newsize-(p-PyString_AS_STRING(v)) >= 7);
00592 c = op->ob_sval[i];
00593 if (c == quote || c == '\\')
00594 *p++ = '\\', *p++ = c;
00595 else if (c == '\t')
00596 *p++ = '\\', *p++ = 't';
00597 else if (c == '\n')
00598 *p++ = '\\', *p++ = 'n';
00599 else if (c == '\r')
00600 *p++ = '\\', *p++ = 'r';
00601 else if (c == '\f')
00602 *p++ = '\\', *p++ = 'f';
00603 else if (c == '\b')
00604 *p++ = '\\', *p++ = 'b';
00605 else if (c < ' ' || c >= 0x7f) {
00606
00607
00608
00609 sprintf(p, "\\u%04x", c&0xff);
00610 p += 6;
00611 }
00612 else
00613 *p++ = c;
00614 }
00615 assert(newsize-(p-PyString_AS_STRING(v)) >= 1);
00616 *p++ = quote;
00617 *p = '\0';
00618 _PyString_Resize(&v, (int) (p-PyString_AS_STRING(v)));
00619 return v;
00620 }
00621 }
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631 static PyObject *encode_unicode(PyObject *unicode) {
00632 PyObject *repr;
00633 Py_UNICODE *s;
00634 Py_ssize_t size;
00635 char *p;
00636 static const char *hexdigit = "0123456789abcdef";
00637
00638 s = PyUnicode_AS_UNICODE(unicode);
00639 size = PyUnicode_GET_SIZE(unicode);
00640
00641 if (size > (PY_SSIZE_T_MAX-2-1)/6) {
00642 PyErr_SetString(PyExc_OverflowError, "unicode object is too large to make repr");
00643 return NULL;
00644 }
00645
00646 repr = PyString_FromStringAndSize(NULL, 2+6*size+1);
00647 if (repr == NULL)
00648 return NULL;
00649
00650 p = PyString_AS_STRING(repr);
00651
00652 *p++ = '"';
00653
00654 while (size-- > 0) {
00655 Py_UNICODE ch = *s++;
00656
00657
00658 if ((ch == (Py_UNICODE)PyString_AS_STRING(repr)[0] || ch == '\\')) {
00659 *p++ = '\\';
00660 *p++ = (char)ch;
00661 continue;
00662 #ifdef Py_UNICODE_WIDE
00663
00664 } else if (ch >= 0x10000) {
00665 int offset = p-PyString_AS_STRING(repr);
00666
00667
00668 if (offset+12 > PyString_GET_SIZE(repr)) {
00669 if (_PyString_Resize(&repr, PyString_GET_SIZE(repr)+100))
00670 return NULL;
00671 p = PyString_AS_STRING(repr)+offset;
00672 }
00673
00674 *p++ = '\\';
00675 *p++ = 'U';
00676 *p++ = hexdigit[(ch>>28)&0x0000000F];
00677 *p++ = hexdigit[(ch>>24)&0x0000000F];
00678 *p++ = hexdigit[(ch>>20)&0x0000000F];
00679 *p++ = hexdigit[(ch>>16)&0x0000000F];
00680 *p++ = hexdigit[(ch>>12)&0x0000000F];
00681 *p++ = hexdigit[(ch>>8)&0x0000000F];
00682 *p++ = hexdigit[(ch>>4)&0x0000000F];
00683 *p++ = hexdigit[ch&0x0000000F];
00684 continue;
00685 #endif
00686
00687 } else if (ch >= 0xD800 && ch < 0xDC00) {
00688 Py_UNICODE ch2;
00689 Py_UCS4 ucs;
00690
00691 ch2 = *s++;
00692 size--;
00693 if (ch2 >= 0xDC00 && ch2 <= 0xDFFF) {
00694 ucs = (((ch&0x03FF)<<10)|(ch2&0x03FF))+0x00010000;
00695 *p++ = '\\';
00696 *p++ = 'U';
00697 *p++ = hexdigit[(ucs>>28)&0x0000000F];
00698 *p++ = hexdigit[(ucs>>24)&0x0000000F];
00699 *p++ = hexdigit[(ucs>>20)&0x0000000F];
00700 *p++ = hexdigit[(ucs>>16)&0x0000000F];
00701 *p++ = hexdigit[(ucs>>12)&0x0000000F];
00702 *p++ = hexdigit[(ucs>>8)&0x0000000F];
00703 *p++ = hexdigit[(ucs>>4)&0x0000000F];
00704 *p++ = hexdigit[ucs&0x0000000F];
00705 continue;
00706 }
00707
00708 s--;
00709 size++;
00710
00711 } if (ch >= 256) {
00712 *p++ = '\\';
00713 *p++ = 'u';
00714 *p++ = hexdigit[(ch>>12)&0x000F];
00715 *p++ = hexdigit[(ch>>8)&0x000F];
00716 *p++ = hexdigit[(ch>>4)&0x000F];
00717 *p++ = hexdigit[ch&0x000F];
00718
00719 } else if (ch == '\t') {
00720 *p++ = '\\';
00721 *p++ = 't';
00722 } else if (ch == '\n') {
00723 *p++ = '\\';
00724 *p++ = 'n';
00725 } else if (ch == '\r') {
00726 *p++ = '\\';
00727 *p++ = 'r';
00728 } else if (ch == '\f') {
00729 *p++ = '\\';
00730 *p++ = 'f';
00731 } else if (ch == '\b') {
00732 *p++ = '\\';
00733 *p++ = 'b';
00734 }
00735
00736
00737 else if (ch < ' ' || ch >= 0x7F) {
00738 *p++ = '\\';
00739 *p++ = 'u';
00740 *p++ = '0';
00741 *p++ = '0';
00742 *p++ = hexdigit[(ch>>4)&0x000F];
00743 *p++ = hexdigit[ch&0x000F];
00744 }
00745
00746
00747 else
00748 *p++ = (char)ch;
00749 }
00750
00751 *p++ = PyString_AS_STRING(repr)[0];
00752
00753 *p = '\0';
00754 _PyString_Resize(&repr, p-PyString_AS_STRING(repr));
00755 return repr;
00756 }
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766 static PyObject *encode_tuple(PyObject *tuple) {
00767 Py_ssize_t i, n;
00768 PyObject *s, *temp;
00769 PyObject *pieces, *result = NULL;
00770 PyTupleObject *v = (PyTupleObject *)tuple;
00771
00772 n = v->ob_size;
00773 if (n == 0)
00774 return PyString_FromString("[]");
00775
00776 pieces = PyTuple_New(n);
00777 if (pieces == NULL)
00778 return NULL;
00779
00780
00781 for (i = 0; i < n; ++i) {
00782 s = encode_object(v->ob_item[i]);
00783 if (s == NULL)
00784 goto Done;
00785 PyTuple_SET_ITEM(pieces, i, s);
00786 }
00787
00788
00789 assert(n > 0);
00790 s = PyString_FromString("[");
00791 if (s == NULL)
00792 goto Done;
00793 temp = PyTuple_GET_ITEM(pieces, 0);
00794 PyString_ConcatAndDel(&s, temp);
00795 PyTuple_SET_ITEM(pieces, 0, s);
00796 if (s == NULL)
00797 goto Done;
00798
00799 s = PyString_FromString("]");
00800 if (s == NULL)
00801 goto Done;
00802 temp = PyTuple_GET_ITEM(pieces, n-1);
00803 PyString_ConcatAndDel(&temp, s);
00804 PyTuple_SET_ITEM(pieces, n-1, temp);
00805 if (temp == NULL)
00806 goto Done;
00807
00808
00809 s = PyString_FromString(", ");
00810 if (s == NULL)
00811 goto Done;
00812 result = _PyString_Join(s, pieces);
00813 Py_DECREF(s);
00814
00815 Done:
00816 Py_DECREF(pieces);
00817 return result;
00818 }
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829 static PyObject *encode_list(PyObject *list) {
00830 Py_ssize_t i;
00831 PyObject *s, *temp;
00832 PyObject *pieces = NULL, *result = NULL;
00833 PyListObject *v = (PyListObject *)list;
00834
00835 i = Py_ReprEnter((PyObject *)v);
00836 if (i != 0) {
00837 if (i > 0) {
00838 PyErr_SetString(JSON_EncodeError, "a list with references to itself is not JSON encodable");
00839 }
00840 return NULL;
00841 }
00842
00843 if (v->ob_size == 0) {
00844 result = PyString_FromString("[]");
00845 goto Done;
00846 }
00847
00848 pieces = PyList_New(0);
00849 if (pieces == NULL)
00850 goto Done;
00851
00852
00853
00854 for (i = 0; i < v->ob_size; ++i) {
00855 int status;
00856 s = encode_object(v->ob_item[i]);
00857 if (s == NULL)
00858 goto Done;
00859 status = PyList_Append(pieces, s);
00860 Py_DECREF(s);
00861 if (status < 0)
00862 goto Done;
00863 }
00864
00865
00866 assert(PyList_GET_SIZE(pieces) > 0);
00867 s = PyString_FromString("[");
00868 if (s == NULL)
00869 goto Done;
00870 temp = PyList_GET_ITEM(pieces, 0);
00871 PyString_ConcatAndDel(&s, temp);
00872 PyList_SET_ITEM(pieces, 0, s);
00873 if (s == NULL)
00874 goto Done;
00875
00876 s = PyString_FromString("]");
00877 if (s == NULL)
00878 goto Done;
00879 temp = PyList_GET_ITEM(pieces, PyList_GET_SIZE(pieces)-1);
00880 PyString_ConcatAndDel(&temp, s);
00881 PyList_SET_ITEM(pieces, PyList_GET_SIZE(pieces)-1, temp);
00882 if (temp == NULL)
00883 goto Done;
00884
00885
00886 s = PyString_FromString(", ");
00887 if (s == NULL)
00888 goto Done;
00889 result = _PyString_Join(s, pieces);
00890 Py_DECREF(s);
00891
00892 Done:
00893 Py_XDECREF(pieces);
00894 Py_ReprLeave((PyObject *)v);
00895 return result;
00896 }
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908 static PyObject *encode_dict(PyObject *dict) {
00909 Py_ssize_t i;
00910 PyObject *s, *temp, *colon = NULL;
00911 PyObject *pieces = NULL, *result = NULL;
00912 PyObject *key, *value;
00913 PyDictObject *mp = (PyDictObject *)dict;
00914
00915 i = Py_ReprEnter((PyObject *)mp);
00916 if (i != 0) {
00917 if (i > 0) {
00918 PyErr_SetString(JSON_EncodeError, "a dict with references to "
00919 "itself is not JSON encodable");
00920 }
00921 return NULL;
00922 }
00923
00924 if (mp->ma_used == 0) {
00925 result = PyString_FromString("{}");
00926 goto Done;
00927 }
00928
00929 pieces = PyList_New(0);
00930 if (pieces == NULL)
00931 goto Done;
00932
00933 colon = PyString_FromString(": ");
00934 if (colon == NULL)
00935 goto Done;
00936
00937
00938
00939 i = 0;
00940 while (PyDict_Next((PyObject *)mp, &i, &key, &value)) {
00941 int status;
00942
00943 if (!PyString_Check(key) && !PyUnicode_Check(key)) {
00944 PyErr_SetString(JSON_EncodeError, "JSON encodable dictionaries must have string/unicode keys");
00945 goto Done;
00946 }
00947
00948
00949 Py_INCREF(value);
00950 s = encode_object(key);
00951 PyString_Concat(&s, colon);
00952 PyString_ConcatAndDel(&s, encode_object(value));
00953 Py_DECREF(value);
00954 if (s == NULL)
00955 goto Done;
00956 status = PyList_Append(pieces, s);
00957 Py_DECREF(s);
00958 if (status < 0)
00959 goto Done;
00960 }
00961
00962
00963 assert(PyList_GET_SIZE(pieces) > 0);
00964 s = PyString_FromString("{");
00965 if (s == NULL)
00966 goto Done;
00967 temp = PyList_GET_ITEM(pieces, 0);
00968 PyString_ConcatAndDel(&s, temp);
00969 PyList_SET_ITEM(pieces, 0, s);
00970 if (s == NULL)
00971 goto Done;
00972
00973 s = PyString_FromString("}");
00974 if (s == NULL)
00975 goto Done;
00976 temp = PyList_GET_ITEM(pieces, PyList_GET_SIZE(pieces)-1);
00977 PyString_ConcatAndDel(&temp, s);
00978 PyList_SET_ITEM(pieces, PyList_GET_SIZE(pieces)-1, temp);
00979 if (temp == NULL)
00980 goto Done;
00981
00982
00983 s = PyString_FromString(", ");
00984 if (s == NULL)
00985 goto Done;
00986 result = _PyString_Join(s, pieces);
00987 Py_DECREF(s);
00988
00989 Done:
00990 Py_XDECREF(pieces);
00991 Py_XDECREF(colon);
00992 Py_ReprLeave((PyObject *)mp);
00993 return result;
00994 }
00995
00996 static PyObject *encode_object(PyObject *object) {
00997 if (object == Py_True) {
00998 return PyString_FromString("true");
00999 } else if (object == Py_False) {
01000 return PyString_FromString("false");
01001 } else if (object == Py_None) {
01002 return PyString_FromString("null");
01003 } else if (PyString_Check(object)) {
01004 return encode_string(object);
01005 } else if (PyUnicode_Check(object)) {
01006 return encode_unicode(object);
01007 } else if (PyFloat_Check(object)) {
01008 double val = PyFloat_AS_DOUBLE(object);
01009 if (Py_IS_NAN(val)) {
01010 return PyString_FromString("NaN");
01011 } else if (Py_IS_INFINITY(val)) {
01012 if (val > 0) {
01013 return PyString_FromString("Infinity");
01014 } else {
01015 return PyString_FromString("-Infinity");
01016 }
01017 } else {
01018 return PyObject_Str(object);
01019 }
01020 } else if (PyInt_Check(object) || PyLong_Check(object)) {
01021 return PyObject_Str(object);
01022 } else if (PyList_Check(object)) {
01023 return encode_list(object);
01024 } else if (PyTuple_Check(object)) {
01025 return encode_tuple(object);
01026 } else if (PyDict_Check(object)) {
01027 return encode_dict(object);
01028 } else {
01029 PyErr_SetString(JSON_EncodeError, "object is not JSON encodable");
01030 return NULL;
01031 }
01032 }
01033
01034
01035
01036 static PyObject *JSON_encode(PyObject *self, PyObject *object) {
01037 return encode_object(object);
01038 }
01039
01040
01041
01042 static PyObject *JSON_decode(PyObject *self, PyObject *args, PyObject *kwargs) {
01043 static char *kwlist[] = { "json", "all_unicode", NULL };
01044 int all_unicode = False;
01045 PyObject *object, *string, *str;
01046 JSONData jsondata;
01047
01048 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:decode", kwlist, &string, &all_unicode))
01049 return NULL;
01050
01051 if (PyUnicode_Check(string)) {
01052 str = PyUnicode_AsRawUnicodeEscapeString(string);
01053 if (str == NULL) {
01054 return NULL;
01055 }
01056 } else {
01057 Py_INCREF(string);
01058 str = string;
01059 }
01060
01061 if (PyString_AsStringAndSize(str, &(jsondata.str), NULL) == -1) {
01062 Py_DECREF(str);
01063 return NULL;
01064 }
01065
01066 jsondata.ptr = jsondata.str;
01067 jsondata.end = jsondata.str+strlen(jsondata.str);
01068 jsondata.all_unicode = all_unicode;
01069
01070 object = decode_json(&jsondata);
01071
01072 if (object != NULL) {
01073 skipSpaces(&jsondata);
01074 if (jsondata.ptr < jsondata.end) {
01075 PyErr_Format(JSON_DecodeError, "extra data after JSON description at position "SSIZE_T_F, (Py_ssize_t)(jsondata.ptr-jsondata.str));
01076 Py_DECREF(str);
01077 Py_DECREF(object);
01078 return NULL;
01079 }
01080 }
01081
01082 Py_DECREF(str);
01083
01084 return object;
01085 }
01086
01087
01088
01089 static PyMethodDef cjson_methods[] = {
01090 { "encode", (PyCFunction)JSON_encode, METH_O,
01091 PyDoc_STR("encode(object) -> generate the JSON representation for object.") },
01092
01093 { "decode", (PyCFunction)JSON_decode, METH_VARARGS|METH_KEYWORDS,
01094 PyDoc_STR("decode(string, all_unicode=False) -> parse the JSON representation into\n"
01095 "python objects. The optional argument `all_unicode', specifies how to\n"
01096 "convert the strings in the JSON representation into python objects.\n"
01097 "If it is False (default), it will return strings everywhere possible\n"
01098 "and unicode objects only where necessary, else it will return unicode\n"
01099 "objects everywhere (this is slower).") },
01100
01101 { NULL, NULL, 0, NULL }
01102 };
01103
01104 PyDoc_STRVAR(module_doc, "Fast JSON encoder/decoder module.");
01105
01106
01107 #define MODULE_VERSION "1.0.5"
01108 PyMODINIT_FUNC initcjson(void) {
01109 PyObject *m;
01110
01111 m = Py_InitModule3("cjson", cjson_methods, module_doc);
01112
01113 if (m == NULL)
01114 return;
01115
01116 JSON_Error = PyErr_NewException("cjson.Error", NULL, NULL);
01117 if (JSON_Error == NULL)
01118 return;
01119 Py_INCREF(JSON_Error);
01120 PyModule_AddObject(m, "Error", JSON_Error);
01121
01122 JSON_EncodeError = PyErr_NewException("cjson.EncodeError", JSON_Error, NULL);
01123 if (JSON_EncodeError == NULL)
01124 return;
01125 Py_INCREF(JSON_EncodeError);
01126 PyModule_AddObject(m, "EncodeError", JSON_EncodeError);
01127
01128 JSON_DecodeError = PyErr_NewException("cjson.DecodeError", JSON_Error, NULL);
01129 if (JSON_DecodeError == NULL)
01130 return;
01131 Py_INCREF(JSON_DecodeError);
01132 PyModule_AddObject(m, "DecodeError", JSON_DecodeError);
01133
01134
01135 PyModule_AddStringConstant(m, "__version__", MODULE_VERSION);
01136 }