00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include "ultrajson.h"
00035 #include <stdio.h>
00036 #include <assert.h>
00037 #include <string.h>
00038 #include <stdlib.h>
00039 #include <math.h>
00040
00041 #include <float.h>
00042
00043 #ifndef TRUE
00044 #define TRUE 1
00045 #endif
00046 #ifndef FALSE
00047 #define FALSE 0
00048 #endif
00049
00050 static const double g_pow10[] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 10000000000, 100000000000, 1000000000000, 10000000000000, 100000000000000, 1000000000000000};
00051 static const char g_hexChars[] = "0123456789abcdef";
00052 static const char g_escapeChars[] = "0123456789\\b\\t\\n\\f\\r\\\"\\\\\\/";
00053
00054
00055
00056
00057
00058
00059
00060
00061 static const JSUINT8 g_asciiOutputTable[256] =
00062 {
00063 0, 30, 30, 30, 30, 30, 30, 30, 10, 12, 14, 30, 16, 18, 30, 30,
00064 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
00065 1, 1, 20, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 24,
00066 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
00067 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
00068 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 1, 1, 1,
00069 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
00070 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
00071 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
00072 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
00073 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
00074 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
00075 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
00076 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
00077 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
00078 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 1, 1
00079 };
00080
00081
00082 static void SetError (JSOBJ obj, JSONObjectEncoder *enc, const char *message)
00083 {
00084 enc->errorMsg = message;
00085 enc->errorObj = obj;
00086 }
00087
00088
00089
00090
00091 void Buffer_Realloc (JSONObjectEncoder *enc, size_t cbNeeded)
00092 {
00093 size_t curSize = enc->end - enc->start;
00094 size_t newSize = curSize * 2;
00095 size_t offset = enc->offset - enc->start;
00096
00097 while (newSize < curSize + cbNeeded)
00098 {
00099 newSize *= 2;
00100 }
00101
00102 if (enc->heap)
00103 {
00104 enc->start = (char *) enc->realloc (enc->start, newSize);
00105 if (!enc->start)
00106 {
00107 SetError (NULL, enc, "Could not reserve memory block");
00108 return;
00109 }
00110 }
00111 else
00112 {
00113 char *oldStart = enc->start;
00114 enc->heap = 1;
00115 enc->start = (char *) enc->malloc (newSize);
00116 if (!enc->start)
00117 {
00118 SetError (NULL, enc, "Could not reserve memory block");
00119 return;
00120 }
00121 memcpy (enc->start, oldStart, offset);
00122 }
00123 enc->offset = enc->start + offset;
00124 enc->end = enc->start + newSize;
00125 }
00126
00127 FASTCALL_ATTR INLINE_PREFIX void FASTCALL_MSVC Buffer_AppendShortHexUnchecked (char *outputOffset, unsigned short value)
00128 {
00129 *(outputOffset++) = g_hexChars[(value & 0xf000) >> 12];
00130 *(outputOffset++) = g_hexChars[(value & 0x0f00) >> 8];
00131 *(outputOffset++) = g_hexChars[(value & 0x00f0) >> 4];
00132 *(outputOffset++) = g_hexChars[(value & 0x000f) >> 0];
00133 }
00134
00135 int Buffer_EscapeStringUnvalidated (JSOBJ obj, JSONObjectEncoder *enc, const char *io, const char *end)
00136 {
00137 char *of = (char *) enc->offset;
00138
00139 while (1)
00140 {
00141 switch (*io)
00142 {
00143 case 0x00:
00144 if (io < end)
00145 {
00146 *(of++) = '\\';
00147 *(of++) = 'u';
00148 *(of++) = '0';
00149 *(of++) = '0';
00150 *(of++) = '0';
00151 *(of++) = '0';
00152 break;
00153 }
00154 else
00155 {
00156 enc->offset += (of - enc->offset);
00157 return TRUE;
00158 }
00159
00160 case '\"': (*of++) = '\\'; (*of++) = '\"'; break;
00161 case '\\': (*of++) = '\\'; (*of++) = '\\'; break;
00162 case '/': (*of++) = '\\'; (*of++) = '/'; break;
00163 case '\b': (*of++) = '\\'; (*of++) = 'b'; break;
00164 case '\f': (*of++) = '\\'; (*of++) = 'f'; break;
00165 case '\n': (*of++) = '\\'; (*of++) = 'n'; break;
00166 case '\r': (*of++) = '\\'; (*of++) = 'r'; break;
00167 case '\t': (*of++) = '\\'; (*of++) = 't'; break;
00168
00169 case 0x01:
00170 case 0x02:
00171 case 0x03:
00172 case 0x04:
00173 case 0x05:
00174 case 0x06:
00175 case 0x07:
00176 case 0x0b:
00177 case 0x0e:
00178 case 0x0f:
00179 case 0x10:
00180 case 0x11:
00181 case 0x12:
00182 case 0x13:
00183 case 0x14:
00184 case 0x15:
00185 case 0x16:
00186 case 0x17:
00187 case 0x18:
00188 case 0x19:
00189 case 0x1a:
00190 case 0x1b:
00191 case 0x1c:
00192 case 0x1d:
00193 case 0x1e:
00194 case 0x1f:
00195 *(of++) = '\\';
00196 *(of++) = 'u';
00197 *(of++) = '0';
00198 *(of++) = '0';
00199 *(of++) = g_hexChars[ (unsigned char) (((*io) & 0xf0) >> 4)];
00200 *(of++) = g_hexChars[ (unsigned char) ((*io) & 0x0f)];
00201 break;
00202
00203 default: (*of++) = (*io); break;
00204 }
00205
00206 io++;
00207 }
00208
00209 return FALSE;
00210 }
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221 int Buffer_EscapeStringValidated (JSOBJ obj, JSONObjectEncoder *enc, const char *io, const char *end)
00222 {
00223 JSUTF32 ucs;
00224 char *of = (char *) enc->offset;
00225
00226 while (1)
00227 {
00228
00229
00230 JSUINT8 utflen = g_asciiOutputTable[(unsigned char) *io];
00231
00232 switch (utflen)
00233 {
00234 case 0:
00235 {
00236 if (io < end)
00237 {
00238 *(of++) = '\\';
00239 *(of++) = 'u';
00240 *(of++) = '0';
00241 *(of++) = '0';
00242 *(of++) = '0';
00243 *(of++) = '0';
00244 io ++;
00245 continue;
00246 }
00247 else
00248 {
00249 enc->offset += (of - enc->offset);
00250 return TRUE;
00251 }
00252 }
00253
00254 case 1:
00255 {
00256 *(of++)= (*io++);
00257 continue;
00258 }
00259
00260 case 2:
00261 {
00262 JSUTF32 in;
00263 JSUTF16 in16;
00264
00265 if (end - io < 1)
00266 {
00267 enc->offset += (of - enc->offset);
00268 SetError (obj, enc, "Unterminated UTF-8 sequence when encoding string");
00269 return FALSE;
00270 }
00271
00272 memcpy(&in16, io, sizeof(JSUTF16));
00273 in = (JSUTF32) in16;
00274
00275 #ifdef __LITTLE_ENDIAN__
00276 ucs = ((in & 0x1f) << 6) | ((in >> 8) & 0x3f);
00277 #else
00278 ucs = ((in & 0x1f00) >> 2) | (in & 0x3f);
00279 #endif
00280
00281 if (ucs < 0x80)
00282 {
00283 enc->offset += (of - enc->offset);
00284 SetError (obj, enc, "Overlong 2 byte UTF-8 sequence detected when encoding string");
00285 return FALSE;
00286 }
00287
00288 io += 2;
00289 break;
00290 }
00291
00292 case 3:
00293 {
00294 JSUTF32 in;
00295 JSUTF16 in16;
00296 JSUINT8 in8;
00297
00298 if (end - io < 2)
00299 {
00300 enc->offset += (of - enc->offset);
00301 SetError (obj, enc, "Unterminated UTF-8 sequence when encoding string");
00302 return FALSE;
00303 }
00304
00305 memcpy(&in16, io, sizeof(JSUTF16));
00306 memcpy(&in8, io + 2, sizeof(JSUINT8));
00307 #ifdef __LITTLE_ENDIAN__
00308 in = (JSUTF32) in16;
00309 in |= in8 << 16;
00310 ucs = ((in & 0x0f) << 12) | ((in & 0x3f00) >> 2) | ((in & 0x3f0000) >> 16);
00311 #else
00312 in = in16 << 8;
00313 in |= in8;
00314 ucs = ((in & 0x0f0000) >> 4) | ((in & 0x3f00) >> 2) | (in & 0x3f);
00315 #endif
00316
00317
00318 if (ucs < 0x800)
00319 {
00320 enc->offset += (of - enc->offset);
00321 SetError (obj, enc, "Overlong 3 byte UTF-8 sequence detected when encoding string");
00322 return FALSE;
00323 }
00324
00325 io += 3;
00326 break;
00327 }
00328 case 4:
00329 {
00330 JSUTF32 in;
00331
00332 if (end - io < 3)
00333 {
00334 enc->offset += (of - enc->offset);
00335 SetError (obj, enc, "Unterminated UTF-8 sequence when encoding string");
00336 return FALSE;
00337 }
00338
00339 memcpy(&in, io, sizeof(JSUTF32));
00340 #ifdef __LITTLE_ENDIAN__
00341 ucs = ((in & 0x07) << 18) | ((in & 0x3f00) << 4) | ((in & 0x3f0000) >> 10) | ((in & 0x3f000000) >> 24);
00342 #else
00343 ucs = ((in & 0x07000000) >> 6) | ((in & 0x3f0000) >> 4) | ((in & 0x3f00) >> 2) | (in & 0x3f);
00344 #endif
00345 if (ucs < 0x10000)
00346 {
00347 enc->offset += (of - enc->offset);
00348 SetError (obj, enc, "Overlong 4 byte UTF-8 sequence detected when encoding string");
00349 return FALSE;
00350 }
00351
00352 io += 4;
00353 break;
00354 }
00355
00356
00357 case 5:
00358 case 6:
00359 enc->offset += (of - enc->offset);
00360 SetError (obj, enc, "Unsupported UTF-8 sequence length when encoding string");
00361 return FALSE;
00362
00363 case 30:
00364
00365 *(of++) = '\\';
00366 *(of++) = 'u';
00367 *(of++) = '0';
00368 *(of++) = '0';
00369 *(of++) = g_hexChars[ (unsigned char) (((*io) & 0xf0) >> 4)];
00370 *(of++) = g_hexChars[ (unsigned char) ((*io) & 0x0f)];
00371 io ++;
00372 continue;
00373
00374 case 10:
00375 case 12:
00376 case 14:
00377 case 16:
00378 case 18:
00379 case 20:
00380 case 22:
00381 case 24:
00382 *(of++) = *( (char *) (g_escapeChars + utflen + 0));
00383 *(of++) = *( (char *) (g_escapeChars + utflen + 1));
00384 io ++;
00385 continue;
00386 }
00387
00388
00389
00390 if (ucs >= 0x10000)
00391 {
00392 ucs -= 0x10000;
00393 *(of++) = '\\';
00394 *(of++) = 'u';
00395 Buffer_AppendShortHexUnchecked(of, (ucs >> 10) + 0xd800);
00396 of += 4;
00397
00398 *(of++) = '\\';
00399 *(of++) = 'u';
00400 Buffer_AppendShortHexUnchecked(of, (ucs & 0x3ff) + 0xdc00);
00401 of += 4;
00402 }
00403 else
00404 {
00405 *(of++) = '\\';
00406 *(of++) = 'u';
00407 Buffer_AppendShortHexUnchecked(of, ucs);
00408 of += 4;
00409 }
00410 }
00411
00412 return FALSE;
00413 }
00414
00415 #define Buffer_Reserve(__enc, __len) \
00416 if ((__enc)->end - (__enc)->offset < (__len)) \
00417 { \
00418 Buffer_Realloc((__enc), (__len));\
00419 } \
00420
00421
00422 #define Buffer_AppendCharUnchecked(__enc, __chr) \
00423 *((__enc)->offset++) = __chr; \
00424
00425 FASTCALL_ATTR INLINE_PREFIX void FASTCALL_MSVC strreverse(char* begin, char* end)
00426 {
00427 char aux;
00428 while (end > begin)
00429 aux = *end, *end-- = *begin, *begin++ = aux;
00430 }
00431
00432 void Buffer_AppendIntUnchecked(JSONObjectEncoder *enc, JSINT32 value)
00433 {
00434 char* wstr;
00435 JSUINT32 uvalue = (value < 0) ? -value : value;
00436
00437 wstr = enc->offset;
00438
00439
00440 do *wstr++ = (char)(48 + (uvalue % 10)); while(uvalue /= 10);
00441 if (value < 0) *wstr++ = '-';
00442
00443
00444 strreverse(enc->offset,wstr - 1);
00445 enc->offset += (wstr - (enc->offset));
00446 }
00447
00448 void Buffer_AppendLongUnchecked(JSONObjectEncoder *enc, JSINT64 value)
00449 {
00450 char* wstr;
00451 JSUINT64 uvalue = (value < 0) ? -value : value;
00452
00453 wstr = enc->offset;
00454
00455
00456 do *wstr++ = (char)(48 + (uvalue % 10ULL)); while(uvalue /= 10ULL);
00457 if (value < 0) *wstr++ = '-';
00458
00459
00460 strreverse(enc->offset,wstr - 1);
00461 enc->offset += (wstr - (enc->offset));
00462 }
00463
00464 int Buffer_AppendDoubleUnchecked(JSOBJ obj, JSONObjectEncoder *enc, double value)
00465 {
00466
00467 const double thres_max = (double) 1e16 - 1;
00468 int count;
00469 double diff = 0.0;
00470 char* str = enc->offset;
00471 char* wstr = str;
00472 unsigned long long whole;
00473 double tmp;
00474 unsigned long long frac;
00475 int neg;
00476 double pow10;
00477
00478 if (value == HUGE_VAL || value == -HUGE_VAL)
00479 {
00480 SetError (obj, enc, "Invalid Inf value when encoding double");
00481 return FALSE;
00482 }
00483 if (! (value == value))
00484 {
00485 SetError (obj, enc, "Invalid Nan value when encoding double");
00486 return FALSE;
00487 }
00488
00489
00490
00491
00492 neg = 0;
00493 if (value < 0)
00494 {
00495 neg = 1;
00496 value = -value;
00497 }
00498
00499 pow10 = g_pow10[enc->doublePrecision];
00500
00501 whole = (unsigned long long) value;
00502 tmp = (value - whole) * pow10;
00503 frac = (unsigned long long)(tmp);
00504 diff = tmp - frac;
00505
00506 if (diff > 0.5)
00507 {
00508 ++frac;
00509
00510 if (frac >= pow10)
00511 {
00512 frac = 0;
00513 ++whole;
00514 }
00515 }
00516 else
00517 if (diff == 0.5 && ((frac == 0) || (frac & 1)))
00518 {
00519
00520
00521 ++frac;
00522 }
00523
00524
00525
00526
00527
00528
00529
00530 if (value > thres_max)
00531 {
00532 enc->offset += sprintf(str, "%.15e", neg ? -value : value);
00533 return TRUE;
00534 }
00535
00536 if (enc->doublePrecision == 0)
00537 {
00538 diff = value - whole;
00539
00540 if (diff > 0.5)
00541 {
00542
00543 ++whole;
00544 }
00545 else
00546 if (diff == 0.5 && (whole & 1))
00547 {
00548
00549
00550 ++whole;
00551 }
00552
00553
00554 }
00555 else
00556 if (frac)
00557 {
00558 count = enc->doublePrecision;
00559
00560
00561
00562 while (!(frac % 10))
00563 {
00564 --count;
00565 frac /= 10;
00566 }
00567
00568
00569
00570 do
00571 {
00572 --count;
00573 *wstr++ = (char)(48 + (frac % 10));
00574 } while (frac /= 10);
00575
00576 while (count-- > 0)
00577 {
00578 *wstr++ = '0';
00579 }
00580
00581 *wstr++ = '.';
00582 }
00583 else
00584 {
00585 *wstr++ = '0';
00586 *wstr++ = '.';
00587 }
00588
00589
00590
00591
00592 do *wstr++ = (char)(48 + (whole % 10)); while (whole /= 10);
00593
00594 if (neg)
00595 {
00596 *wstr++ = '-';
00597 }
00598 strreverse(str, wstr-1);
00599 enc->offset += (wstr - (enc->offset));
00600
00601 return TRUE;
00602 }
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617 void encode(JSOBJ obj, JSONObjectEncoder *enc, const char *name, size_t cbName)
00618 {
00619 const char *value;
00620 char *objName;
00621 int count;
00622 JSOBJ iterObj;
00623 size_t szlen;
00624 JSONTypeContext tc;
00625
00626 if (enc->level > enc->recursionMax)
00627 {
00628 SetError (obj, enc, "Maximum recursion level reached");
00629 return;
00630 }
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643 Buffer_Reserve(enc, 256 + (((cbName / 4) + 1) * 12));
00644 if (enc->errorMsg)
00645 {
00646 return;
00647 }
00648
00649 if (name)
00650 {
00651 Buffer_AppendCharUnchecked(enc, '\"');
00652
00653 if (enc->forceASCII)
00654 {
00655 if (!Buffer_EscapeStringValidated(obj, enc, name, name + cbName))
00656 {
00657 return;
00658 }
00659 }
00660 else
00661 {
00662 if (!Buffer_EscapeStringUnvalidated(obj, enc, name, name + cbName))
00663 {
00664 return;
00665 }
00666 }
00667
00668
00669 Buffer_AppendCharUnchecked(enc, '\"');
00670
00671 Buffer_AppendCharUnchecked (enc, ':');
00672 #ifndef JSON_NO_EXTRA_WHITESPACE
00673 Buffer_AppendCharUnchecked (enc, ' ');
00674 #endif
00675 }
00676
00677 enc->beginTypeContext(obj, &tc);
00678
00679 switch (tc.type)
00680 {
00681 case JT_INVALID:
00682 return;
00683
00684 case JT_ARRAY:
00685 {
00686 count = 0;
00687 enc->iterBegin(obj, &tc);
00688
00689 Buffer_AppendCharUnchecked (enc, '[');
00690
00691 while (enc->iterNext(obj, &tc))
00692 {
00693 if (count > 0)
00694 {
00695 Buffer_AppendCharUnchecked (enc, ',');
00696 #ifndef JSON_NO_EXTRA_WHITESPACE
00697 Buffer_AppendCharUnchecked (buffer, ' ');
00698 #endif
00699 }
00700
00701 iterObj = enc->iterGetValue(obj, &tc);
00702
00703 enc->level ++;
00704 encode (iterObj, enc, NULL, 0);
00705 count ++;
00706 }
00707
00708 enc->iterEnd(obj, &tc);
00709 Buffer_AppendCharUnchecked (enc, ']');
00710 break;
00711 }
00712
00713 case JT_OBJECT:
00714 {
00715 count = 0;
00716 enc->iterBegin(obj, &tc);
00717
00718 Buffer_AppendCharUnchecked (enc, '{');
00719
00720 while (enc->iterNext(obj, &tc))
00721 {
00722 if (count > 0)
00723 {
00724 Buffer_AppendCharUnchecked (enc, ',');
00725 #ifndef JSON_NO_EXTRA_WHITESPACE
00726 Buffer_AppendCharUnchecked (enc, ' ');
00727 #endif
00728 }
00729
00730 iterObj = enc->iterGetValue(obj, &tc);
00731 objName = enc->iterGetName(obj, &tc, &szlen);
00732
00733 enc->level ++;
00734 encode (iterObj, enc, objName, szlen);
00735 count ++;
00736 }
00737
00738 enc->iterEnd(obj, &tc);
00739 Buffer_AppendCharUnchecked (enc, '}');
00740 break;
00741 }
00742
00743 case JT_LONG:
00744 {
00745 Buffer_AppendLongUnchecked (enc, enc->getLongValue(obj, &tc));
00746 break;
00747 }
00748
00749 case JT_INT:
00750 {
00751 Buffer_AppendIntUnchecked (enc, enc->getIntValue(obj, &tc));
00752 break;
00753 }
00754
00755 case JT_TRUE:
00756 {
00757 Buffer_AppendCharUnchecked (enc, 't');
00758 Buffer_AppendCharUnchecked (enc, 'r');
00759 Buffer_AppendCharUnchecked (enc, 'u');
00760 Buffer_AppendCharUnchecked (enc, 'e');
00761 break;
00762 }
00763
00764 case JT_FALSE:
00765 {
00766 Buffer_AppendCharUnchecked (enc, 'f');
00767 Buffer_AppendCharUnchecked (enc, 'a');
00768 Buffer_AppendCharUnchecked (enc, 'l');
00769 Buffer_AppendCharUnchecked (enc, 's');
00770 Buffer_AppendCharUnchecked (enc, 'e');
00771 break;
00772 }
00773
00774
00775 case JT_NULL:
00776 {
00777 Buffer_AppendCharUnchecked (enc, 'n');
00778 Buffer_AppendCharUnchecked (enc, 'u');
00779 Buffer_AppendCharUnchecked (enc, 'l');
00780 Buffer_AppendCharUnchecked (enc, 'l');
00781 break;
00782 }
00783
00784 case JT_DOUBLE:
00785 {
00786 if (!Buffer_AppendDoubleUnchecked (obj, enc, enc->getDoubleValue(obj, &tc)))
00787 {
00788 enc->endTypeContext(obj, &tc);
00789 enc->level --;
00790 return;
00791 }
00792 break;
00793 }
00794
00795 case JT_UTF8:
00796 {
00797 value = enc->getStringValue(obj, &tc, &szlen);
00798 Buffer_Reserve(enc, ((szlen / 4) + 1) * 12);
00799 if (enc->errorMsg)
00800 {
00801 enc->endTypeContext(obj, &tc);
00802 return;
00803 }
00804 Buffer_AppendCharUnchecked (enc, '\"');
00805
00806
00807 if (enc->forceASCII)
00808 {
00809 if (!Buffer_EscapeStringValidated(obj, enc, value, value + szlen))
00810 {
00811 enc->endTypeContext(obj, &tc);
00812 enc->level --;
00813 return;
00814 }
00815 }
00816 else
00817 {
00818 if (!Buffer_EscapeStringUnvalidated(obj, enc, value, value + szlen))
00819 {
00820 enc->endTypeContext(obj, &tc);
00821 enc->level --;
00822 return;
00823 }
00824 }
00825
00826 Buffer_AppendCharUnchecked (enc, '\"');
00827 break;
00828 }
00829 }
00830
00831 enc->endTypeContext(obj, &tc);
00832 enc->level --;
00833
00834 }
00835
00836 char *JSON_EncodeObject(JSOBJ obj, JSONObjectEncoder *enc, char *_buffer, size_t _cbBuffer)
00837 {
00838 enc->malloc = enc->malloc ? enc->malloc : malloc;
00839 enc->free = enc->free ? enc->free : free;
00840 enc->realloc = enc->realloc ? enc->realloc : realloc;
00841 enc->errorMsg = NULL;
00842 enc->errorObj = NULL;
00843 enc->level = 0;
00844
00845 if (enc->recursionMax < 1)
00846 {
00847 enc->recursionMax = JSON_MAX_RECURSION_DEPTH;
00848 }
00849
00850 if (enc->doublePrecision < 0 ||
00851 enc->doublePrecision > JSON_DOUBLE_MAX_DECIMALS)
00852 {
00853 enc->doublePrecision = JSON_DOUBLE_MAX_DECIMALS;
00854 }
00855
00856 if (_buffer == NULL)
00857 {
00858 _cbBuffer = 32768;
00859 enc->start = (char *) enc->malloc (_cbBuffer);
00860 if (!enc->start)
00861 {
00862 SetError(obj, enc, "Could not reserve memory block");
00863 return NULL;
00864 }
00865 enc->heap = 1;
00866 }
00867 else
00868 {
00869 enc->start = _buffer;
00870 enc->heap = 0;
00871 }
00872
00873 enc->end = enc->start + _cbBuffer;
00874 enc->offset = enc->start;
00875
00876
00877 encode (obj, enc, NULL, 0);
00878
00879 Buffer_Reserve(enc, 1);
00880 if (enc->errorMsg)
00881 {
00882 return NULL;
00883 }
00884 Buffer_AppendCharUnchecked(enc, '\0');
00885
00886 return enc->start;
00887 }