ultrajsondec.c
Go to the documentation of this file.
00001 /*
00002 Copyright (c) 2011-2012, ESN Social Software AB and Jonas Tarnstrom
00003 All rights reserved.
00004 
00005 Redistribution and use in source and binary forms, with or without
00006 modification, are permitted provided that the following conditions are met:
00007     * Redistributions of source code must retain the above copyright
00008       notice, this list of conditions and the following disclaimer.
00009     * Redistributions in binary form must reproduce the above copyright
00010       notice, this list of conditions and the following disclaimer in the
00011       documentation and/or other materials provided with the distribution.
00012     * Neither the name of the ESN Social Software AB nor the
00013       names of its contributors may be used to endorse or promote products
00014       derived from this software without specific prior written permission.
00015 
00016 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00017 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00018 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00019 DISCLAIMED. IN NO EVENT SHALL ESN SOCIAL SOFTWARE AB OR JONAS TARNSTROM BE LIABLE 
00020 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00021 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00022 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00023 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00024 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00025 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00026 
00027 Portions of code from:
00028 MODP_ASCII - Ascii transformations (upper/lower, etc)
00029 http://code.google.com/p/stringencoders/
00030 Copyright (c) 2007  Nick Galbreath -- nickg [at] modp [dot] com. All rights reserved.
00031 
00032 */
00033 
00034 #include "ultrajson.h"
00035 #include <math.h>
00036 #include <assert.h>
00037 #include <string.h>
00038 #include <limits.h>
00039 #include <wchar.h>
00040 
00041 struct DecoderState
00042 {
00043     char *start;
00044     char *end;
00045     wchar_t *escStart;
00046     wchar_t *escEnd;
00047     int escHeap;
00048     int lastType;
00049     JSONObjectDecoder *dec;
00050 };
00051 
00052 JSOBJ FASTCALL_MSVC decode_any( struct DecoderState *ds) FASTCALL_ATTR;
00053 typedef JSOBJ (*PFN_DECODER)( struct DecoderState *ds);
00054 #define RETURN_JSOBJ_NULLCHECK(_expr) return(_expr);
00055 
00056 double createDouble(double intNeg, double intValue, double frcValue, int frcDecimalCount)
00057 {
00058     static const double g_pow10[] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 10000000000, 100000000000, 1000000000000, 10000000000000, 100000000000000, 1000000000000000};
00059 
00060     return (intValue + (frcValue / g_pow10[frcDecimalCount])) * intNeg;
00061 }
00062 
00063 static JSOBJ SetError( struct DecoderState *ds, int offset, const char *message)
00064 {
00065     ds->dec->errorOffset = ds->start + offset;
00066     ds->dec->errorStr = (char *) message;
00067     return NULL;
00068 }
00069 
00070 static void ClearError( struct DecoderState *ds)
00071 {
00072     ds->dec->errorOffset = 0;
00073     ds->dec->errorStr = NULL;
00074 }
00075 
00076 FASTCALL_ATTR JSOBJ FASTCALL_MSVC decode_numeric ( struct DecoderState *ds)
00077 {
00078 #ifdef JSON_DECODE_NUMERIC_AS_DOUBLE
00079     double intNeg = 1;
00080     double intValue;
00081 #else
00082     int intNeg = 1;
00083     JSLONG intValue;
00084 #endif
00085 
00086     double expNeg;
00087     int chr;
00088     int decimalCount = 0;
00089     double frcValue = 0.0;
00090     double expValue;
00091     char *offset = ds->start;
00092 
00093     if (*(offset) == '-')
00094     {
00095         offset ++;
00096         intNeg = -1;
00097     }
00098 
00099     // Scan integer part
00100     intValue = 0;
00101 
00102     while (1)
00103     {
00104         chr = (int) (unsigned char) *(offset);
00105 
00106         switch (chr)
00107         {
00108         case '0':
00109         case '1':
00110         case '2':
00111         case '3':
00112         case '4':
00113         case '5':
00114         case '6':
00115         case '7':
00116         case '8':
00117         case '9':
00118             //FIXME: Check for arithemtic overflow here
00119             //PERF: Don't do 64-bit arithmetic here unless we know we have to
00120 #ifdef JSON_DECODE_NUMERIC_AS_DOUBLE
00121             intValue = intValue * 10.0 + (double) (chr - 48);
00122 #else
00123             intValue = intValue * 10LL + (JSLONG) (chr - 48);
00124 #endif
00125             offset ++;
00126             break;
00127 
00128         case '.':
00129             offset ++;
00130             goto DECODE_FRACTION;
00131             break;
00132 
00133         case 'e':
00134         case 'E':
00135             offset ++;
00136             goto DECODE_EXPONENT;
00137             break;
00138 
00139         default:
00140             goto BREAK_INT_LOOP;
00141             break;
00142         }
00143     }
00144 
00145 BREAK_INT_LOOP:
00146 
00147     ds->lastType = JT_INT;
00148     ds->start = offset;
00149 
00150     //If input string is LONGLONG_MIN here the value is already negative so we should not flip it
00151 
00152 #ifdef JSON_DECODE_NUMERIC_AS_DOUBLE
00153 #else
00154     if (intValue < 0)
00155     {
00156         intNeg = 1;
00157     }
00158 #endif
00159 
00160     //dbg1 = (intValue * intNeg);
00161     //dbg2 = (JSLONG) dbg1;
00162 
00163 #ifdef JSON_DECODE_NUMERIC_AS_DOUBLE
00164     if (intValue > (double) INT_MAX || intValue < (double) INT_MIN)
00165 #else
00166     if ( (intValue >> 31))
00167 #endif
00168     {   
00169         RETURN_JSOBJ_NULLCHECK(ds->dec->newLong( (JSINT64) (intValue * (JSINT64) intNeg)));
00170     }
00171     else
00172     {
00173         RETURN_JSOBJ_NULLCHECK(ds->dec->newInt( (JSINT32) (intValue * intNeg)));
00174     }
00175 
00176 
00177 
00178 DECODE_FRACTION:
00179 
00180     // Scan fraction part
00181     frcValue = 0.0;
00182     while (1)
00183     {
00184         chr = (int) (unsigned char) *(offset);
00185 
00186         switch (chr)
00187         {
00188         case '0':
00189         case '1':
00190         case '2':
00191         case '3':
00192         case '4':
00193         case '5':
00194         case '6':
00195         case '7':
00196         case '8':
00197         case '9':
00198             if (decimalCount < JSON_DOUBLE_MAX_DECIMALS)
00199             {
00200                 frcValue = frcValue * 10.0 + (double) (chr - 48);
00201                 decimalCount ++;
00202             }
00203             offset ++;
00204             break;
00205 
00206         case 'e':
00207         case 'E':
00208             offset ++;
00209             goto DECODE_EXPONENT;
00210             break;
00211 
00212         default:
00213             goto BREAK_FRC_LOOP;
00214         }
00215     }
00216 
00217 BREAK_FRC_LOOP:
00218 
00219     if (intValue < 0)
00220     {
00221         intNeg = 1;
00222     }
00223 
00224     //FIXME: Check for arithemtic overflow here
00225     ds->lastType = JT_DOUBLE;
00226     ds->start = offset;
00227     RETURN_JSOBJ_NULLCHECK(ds->dec->newDouble (createDouble( (double) intNeg, (double) intValue, frcValue, decimalCount)));
00228 
00229 DECODE_EXPONENT:
00230     expNeg = 1.0;
00231 
00232     if (*(offset) == '-')
00233     {
00234         expNeg = -1.0;
00235         offset ++;
00236     }
00237     else
00238     if (*(offset) == '+')
00239     {
00240         expNeg = +1.0;
00241         offset ++;
00242     }
00243 
00244     expValue = 0.0;
00245 
00246     while (1)
00247     {
00248         chr = (int) (unsigned char) *(offset);
00249 
00250         switch (chr)
00251         {
00252         case '0':
00253         case '1':
00254         case '2':
00255         case '3':
00256         case '4':
00257         case '5':
00258         case '6':
00259         case '7':
00260         case '8':
00261         case '9':
00262             expValue = expValue * 10.0 + (double) (chr - 48);
00263             offset ++;
00264             break;
00265 
00266         default:
00267             goto BREAK_EXP_LOOP;
00268 
00269         }
00270     }
00271 
00272 BREAK_EXP_LOOP:
00273 
00274 #ifdef JSON_DECODE_NUMERIC_AS_DOUBLE
00275 #else
00276     if (intValue < 0)
00277     {
00278         intNeg = 1;
00279     }
00280 #endif
00281     
00282     //FIXME: Check for arithemtic overflow here
00283     ds->lastType = JT_DOUBLE;
00284     ds->start = offset;
00285     RETURN_JSOBJ_NULLCHECK(ds->dec->newDouble (createDouble( (double) intNeg, (double) intValue , frcValue, decimalCount) * pow(10.0, expValue * expNeg)));
00286 }
00287 
00288 FASTCALL_ATTR JSOBJ FASTCALL_MSVC decode_true ( struct DecoderState *ds) 
00289 {
00290     char *offset = ds->start;
00291     offset ++;
00292 
00293     if (*(offset++) != 'r')
00294         goto SETERROR;
00295     if (*(offset++) != 'u')
00296         goto SETERROR;
00297     if (*(offset++) != 'e')
00298         goto SETERROR;
00299 
00300     ds->lastType = JT_TRUE;
00301     ds->start = offset;
00302     RETURN_JSOBJ_NULLCHECK(ds->dec->newTrue());
00303 
00304 SETERROR:
00305     return SetError(ds, -1, "Unexpected character found when decoding 'true'");
00306 }
00307 
00308 FASTCALL_ATTR JSOBJ FASTCALL_MSVC decode_false ( struct DecoderState *ds) 
00309 {
00310     char *offset = ds->start;
00311     offset ++;
00312 
00313     if (*(offset++) != 'a')
00314         goto SETERROR;
00315     if (*(offset++) != 'l')
00316         goto SETERROR;
00317     if (*(offset++) != 's')
00318         goto SETERROR;
00319     if (*(offset++) != 'e')
00320         goto SETERROR;
00321 
00322     ds->lastType = JT_FALSE;
00323     ds->start = offset;
00324     RETURN_JSOBJ_NULLCHECK(ds->dec->newFalse());
00325 
00326 SETERROR:
00327     return SetError(ds, -1, "Unexpected character found when decoding 'false'");
00328 
00329 }
00330 
00331 
00332 FASTCALL_ATTR JSOBJ FASTCALL_MSVC decode_null ( struct DecoderState *ds) 
00333 {
00334     char *offset = ds->start;
00335     offset ++;
00336 
00337     if (*(offset++) != 'u')
00338         goto SETERROR;
00339     if (*(offset++) != 'l')
00340         goto SETERROR;
00341     if (*(offset++) != 'l')
00342         goto SETERROR;
00343 
00344     ds->lastType = JT_NULL;
00345     ds->start = offset;
00346     RETURN_JSOBJ_NULLCHECK(ds->dec->newNull());
00347 
00348 SETERROR:
00349     return SetError(ds, -1, "Unexpected character found when decoding 'null'");
00350 }
00351 
00352 FASTCALL_ATTR void FASTCALL_MSVC SkipWhitespace(struct DecoderState *ds) 
00353 {
00354     char *offset = ds->start;
00355 
00356     while (1)
00357     {
00358         switch (*offset)
00359         {
00360         case ' ':
00361         case '\t':
00362         case '\r':
00363         case '\n':
00364             offset ++;
00365             break;
00366 
00367         default:
00368             ds->start = offset;
00369             return;
00370         }
00371     }
00372 }
00373 
00374 
00375 enum DECODESTRINGSTATE
00376 {
00377     DS_ISNULL = 0x32,
00378     DS_ISQUOTE,
00379     DS_ISESCAPE,
00380     DS_UTFLENERROR,
00381 
00382 };
00383 
00384 static const JSUINT8 g_decoderLookup[256] = 
00385 {
00386 /* 0x00 */ DS_ISNULL, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
00387 /* 0x10 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
00388 /* 0x20 */ 1, 1, DS_ISQUOTE, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
00389 /* 0x30 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
00390 /* 0x40 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
00391 /* 0x50 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, DS_ISESCAPE, 1, 1, 1,
00392 /* 0x60 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
00393 /* 0x70 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
00394 /* 0x80 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
00395 /* 0x90 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
00396 /* 0xa0 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
00397 /* 0xb0 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
00398 /* 0xc0 */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 
00399 /* 0xd0 */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
00400 /* 0xe0 */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 
00401 /* 0xf0 */ 4, 4, 4, 4, 4, 4, 4, 4, DS_UTFLENERROR, DS_UTFLENERROR, DS_UTFLENERROR, DS_UTFLENERROR, DS_UTFLENERROR, DS_UTFLENERROR, DS_UTFLENERROR, DS_UTFLENERROR, 
00402 };
00403 
00404 
00405 FASTCALL_ATTR JSOBJ FASTCALL_MSVC decode_string ( struct DecoderState *ds)
00406 {
00407     JSUTF16 sur[2] = { 0 };
00408     int iSur = 0;
00409     int index;
00410     wchar_t *escOffset;
00411     size_t escLen = (ds->escEnd - ds->escStart);
00412     JSUINT8 *inputOffset;
00413     JSUINT8 oct;
00414     JSUTF32 ucs;
00415     ds->lastType = JT_INVALID;
00416     ds->start ++;
00417 
00418     if ( (ds->end - ds->start) > escLen)
00419     {
00420         size_t newSize = (ds->end - ds->start);
00421 
00422         if (ds->escHeap)
00423         {
00424             ds->escStart = (wchar_t *) ds->dec->realloc (ds->escStart, newSize * sizeof(wchar_t));
00425             if (!ds->escStart)
00426             {
00427                 return SetError(ds, -1, "Could not reserve memory block");
00428             }
00429         }
00430         else
00431         {
00432             wchar_t *oldStart = ds->escStart;
00433             ds->escHeap = 1;
00434             ds->escStart = (wchar_t *) ds->dec->malloc (newSize * sizeof(wchar_t));
00435             if (!ds->escStart)
00436             {
00437                 return SetError(ds, -1, "Could not reserve memory block");
00438             }
00439             memcpy (ds->escStart, oldStart, escLen * sizeof(wchar_t));
00440         }
00441 
00442         ds->escEnd = ds->escStart + newSize;
00443     }
00444 
00445     escOffset = ds->escStart;
00446     inputOffset = ds->start;
00447 
00448     while(1)
00449     {
00450         switch (g_decoderLookup[(JSUINT8)(*inputOffset)])
00451         {
00452         case DS_ISNULL:
00453             return SetError(ds, -1, "Unmatched ''\"' when when decoding 'string'");
00454 
00455         case DS_ISQUOTE:
00456             ds->lastType = JT_UTF8;
00457             inputOffset ++;
00458             ds->start += ( (char *) inputOffset - (ds->start));
00459             RETURN_JSOBJ_NULLCHECK(ds->dec->newString(ds->escStart, escOffset));
00460 
00461         case DS_UTFLENERROR:
00462             return SetError (ds, -1, "Invalid UTF-8 sequence length when decoding 'string'");
00463 
00464         case DS_ISESCAPE:
00465             inputOffset ++;
00466             switch (*inputOffset)
00467             {
00468             case '\\': *(escOffset++) = L'\\'; inputOffset++; continue;
00469             case '\"': *(escOffset++) = L'\"'; inputOffset++; continue;
00470             case '/':  *(escOffset++) = L'/';  inputOffset++; continue;
00471             case 'b':  *(escOffset++) = L'\b'; inputOffset++; continue;
00472             case 'f':  *(escOffset++) = L'\f'; inputOffset++; continue;
00473             case 'n':  *(escOffset++) = L'\n'; inputOffset++; continue;
00474             case 'r':  *(escOffset++) = L'\r'; inputOffset++; continue;
00475             case 't':  *(escOffset++) = L'\t'; inputOffset++; continue;
00476 
00477             case 'u':
00478                 {
00479                     int index;
00480                     inputOffset ++;
00481 
00482                     for (index = 0; index < 4; index ++)
00483                     {
00484                         switch (*inputOffset)
00485                         {
00486                         case '\0':  return SetError (ds, -1, "Unterminated unicode escape sequence when decoding 'string'");
00487                         default:        return SetError (ds, -1, "Unexpected character in unicode escape sequence when decoding 'string'");
00488 
00489                         case '0':
00490                         case '1':
00491                         case '2':
00492                         case '3':
00493                         case '4':
00494                         case '5':
00495                         case '6':
00496                         case '7':
00497                         case '8':
00498                         case '9':
00499                             sur[iSur] = (sur[iSur] << 4) + (JSUTF16) (*inputOffset - '0');
00500                             break;
00501 
00502                         case 'a':
00503                         case 'b':
00504                         case 'c':
00505                         case 'd':
00506                         case 'e':
00507                         case 'f':
00508                             sur[iSur] = (sur[iSur] << 4) + 10 + (JSUTF16) (*inputOffset - 'a');
00509                             break;
00510 
00511                         case 'A':
00512                         case 'B':
00513                         case 'C':
00514                         case 'D':
00515                         case 'E':
00516                         case 'F':
00517                             sur[iSur] = (sur[iSur] << 4) + 10 + (JSUTF16) (*inputOffset - 'A');
00518                             break;
00519                         }
00520 
00521                         inputOffset ++;
00522                     }
00523 
00524 
00525                     if (iSur == 0)
00526                     {
00527                         if((sur[iSur] & 0xfc00) == 0xd800)
00528                         {
00529                             // First of a surrogate pair, continue parsing
00530                             iSur ++;
00531                             break;
00532                         } 
00533                         (*escOffset++) = (wchar_t) sur[iSur];
00534                         iSur = 0;
00535                     }
00536                     else
00537                     {
00538                         // Decode pair
00539                         if ((sur[1] & 0xfc00) != 0xdc00)
00540                         {
00541                             return SetError (ds, -1, "Unpaired high surrogate when decoding 'string'");
00542                         }
00543 
00544 #if WCHAR_MAX == 0xffff
00545                         (*escOffset++) = (wchar_t) sur[0];
00546                         (*escOffset++) = (wchar_t) sur[1];
00547 #else
00548                         (*escOffset++) = (wchar_t) 0x10000 + (((sur[0] - 0xd800) << 10) | (sur[1] - 0xdc00));
00549 #endif
00550                         iSur = 0;
00551                     }
00552                     break;
00553                 }
00554 
00555             case '\0': return SetError(ds, -1, "Unterminated escape sequence when decoding 'string'");
00556             default: return SetError(ds, -1, "Unrecognized escape sequence when decoding 'string'");
00557             }
00558             break;
00559 
00560         case 1:
00561             *(escOffset++) = (wchar_t) (*inputOffset++); 
00562             break;
00563 
00564         case 2:
00565         {
00566             ucs = (*inputOffset++) & 0x1f;
00567             ucs <<= 6;
00568             if (((*inputOffset) & 0x80) != 0x80)
00569             {
00570                 return SetError(ds, -1, "Invalid octet in UTF-8 sequence when decoding 'string'");
00571             }
00572             ucs |= (*inputOffset++) & 0x3f;
00573             if (ucs < 0x80) return SetError (ds, -1, "Overlong 2 byte UTF-8 sequence detected when decoding 'string'");
00574             *(escOffset++) = (wchar_t) ucs;
00575             break;
00576         }
00577 
00578         case 3:
00579         {
00580             JSUTF32 ucs = 0;
00581             ucs |= (*inputOffset++) & 0x0f;
00582 
00583             for (index = 0; index < 2; index ++)
00584             {
00585                 ucs <<= 6;
00586                 oct = (*inputOffset++);
00587 
00588                 if ((oct & 0x80) != 0x80)
00589                 {
00590                     return SetError(ds, -1, "Invalid octet in UTF-8 sequence when decoding 'string'");
00591                 }
00592 
00593                 ucs |= oct & 0x3f;
00594             }
00595 
00596             if (ucs < 0x800) return SetError (ds, -1, "Overlong 3 byte UTF-8 sequence detected when encoding string");
00597             *(escOffset++) = (wchar_t) ucs;
00598             break;
00599         }
00600 
00601         case 4:
00602         {
00603             JSUTF32 ucs = 0;
00604             ucs |= (*inputOffset++) & 0x07;
00605 
00606             for (index = 0; index < 3; index ++)
00607             {
00608                 ucs <<= 6;
00609                 oct = (*inputOffset++);
00610 
00611                 if ((oct & 0x80) != 0x80)
00612                 {
00613                     return SetError(ds, -1, "Invalid octet in UTF-8 sequence when decoding 'string'");
00614                 }
00615 
00616                 ucs |= oct & 0x3f;
00617             }
00618 
00619             if (ucs < 0x10000) return SetError (ds, -1, "Overlong 4 byte UTF-8 sequence detected when decoding 'string'");
00620 
00621             #if WCHAR_MAX == 0xffff
00622             if (ucs >= 0x10000)
00623             {
00624                 ucs -= 0x10000;
00625                 *(escOffset++) = (ucs >> 10) + 0xd800;
00626                 *(escOffset++) = (ucs & 0x3ff) + 0xdc00;
00627             }
00628             else
00629             {
00630                 *(escOffset++) = (wchar_t) ucs;
00631             }
00632             #else
00633             *(escOffset++) = (wchar_t) ucs;
00634             #endif
00635             break;
00636         }
00637         }
00638     }
00639 }
00640 
00641 FASTCALL_ATTR JSOBJ FASTCALL_MSVC decode_array( struct DecoderState *ds)
00642 {
00643     JSOBJ itemValue;
00644     JSOBJ newObj = ds->dec->newArray();
00645     int len = 0;
00646 
00647     ds->lastType = JT_INVALID;
00648     ds->start ++;
00649     
00650 
00651     while (1)//(*ds->start) != '\0')
00652     {
00653         SkipWhitespace(ds);
00654 
00655         itemValue = decode_any(ds);
00656 
00657         if (itemValue == NULL)
00658         {
00659             switch (*(ds->start++))
00660             {
00661                 case ']':
00662                     if (len > 0)
00663                     {
00664                         ds->dec->releaseObject(newObj);
00665                         return SetError(ds, -1, "Unexpected trailing comma in array");
00666                     }
00667                     // We end up here when decoding empty lists "[]"
00668                     ClearError(ds);
00669                     return newObj;
00670 
00671                 default:
00672                     ds->dec->releaseObject(newObj);
00673                     return SetError(ds, -1, "Unexpected character in found when decoding array value");
00674             }
00675         
00676         
00677             ds->dec->releaseObject(newObj);
00678             return NULL;
00679         }
00680 
00681         ds->dec->arrayAddItem (newObj, itemValue);
00682 
00683         SkipWhitespace(ds);
00684 
00685         switch (*(ds->start++))
00686         {
00687             case ']':
00688                 return newObj;
00689 
00690             case ',':
00691                 break;
00692 
00693             default:
00694                 ds->dec->releaseObject(newObj);
00695                 return SetError(ds, -1, "Unexpected character in found when decoding array value");
00696         }
00697         
00698         len ++;
00699     }
00700 
00701     ds->dec->releaseObject(newObj);
00702     return SetError(ds, -1, "Unmatched ']' when decoding 'array'");
00703 }
00704 
00705 
00706 
00707 FASTCALL_ATTR JSOBJ FASTCALL_MSVC decode_object( struct DecoderState *ds)
00708 {
00709     JSOBJ itemName;
00710     JSOBJ itemValue;
00711     JSOBJ newObj = ds->dec->newObject();
00712 
00713     ds->start ++;
00714 
00715     while (1)
00716     {
00717         SkipWhitespace(ds);
00718 
00719         if ((*ds->start) == '}')
00720         {
00721             ds->start ++;
00722             return newObj;
00723         }
00724 
00725         ds->lastType = JT_INVALID;
00726         itemName = decode_any(ds);
00727 
00728         if (itemName == NULL)
00729         {
00730             ds->dec->releaseObject(newObj);
00731             return NULL;
00732         }
00733 
00734         if (ds->lastType != JT_UTF8)
00735         {
00736             ds->dec->releaseObject(newObj);
00737             ds->dec->releaseObject(itemName);
00738             return SetError(ds, -1, "Key name of object must be 'string' when decoding 'object'");
00739         }
00740 
00741         SkipWhitespace(ds);
00742 
00743         if (*(ds->start++) != ':')
00744         {
00745             ds->dec->releaseObject(newObj);
00746             ds->dec->releaseObject(itemName);
00747             return SetError(ds, -1, "No ':' found when decoding object value");
00748         }
00749 
00750         SkipWhitespace(ds);
00751 
00752         itemValue = decode_any(ds);
00753 
00754         if (itemValue == NULL)
00755         {
00756             ds->dec->releaseObject(newObj);
00757             ds->dec->releaseObject(itemName);
00758             return NULL;
00759         }
00760 
00761         ds->dec->objectAddKey (newObj, itemName, itemValue);
00762 
00763         SkipWhitespace(ds);
00764 
00765         switch (*(ds->start++))
00766         {
00767             case '}':
00768                 return newObj;
00769 
00770             case ',':
00771                 break;
00772 
00773             default:
00774                 ds->dec->releaseObject(newObj);
00775                 return SetError(ds, -1, "Unexpected character in found when decoding object value");
00776         }
00777     }
00778 
00779     ds->dec->releaseObject(newObj);
00780     return SetError(ds, -1, "Unmatched '}' when decoding object");
00781 }
00782 
00783 FASTCALL_ATTR JSOBJ FASTCALL_MSVC decode_any(struct DecoderState *ds)
00784 {
00785     while (1)
00786     {
00787         switch (*ds->start)
00788         {
00789             case '\"': 
00790                 return decode_string (ds);
00791             case '0': 
00792             case '1':
00793             case '2': 
00794             case '3': 
00795             case '4': 
00796             case '5':
00797             case '6': 
00798             case '7': 
00799             case '8': 
00800             case '9': 
00801             case '-': 
00802                 return decode_numeric (ds);
00803 
00804             case '[':   return decode_array (ds);
00805             case '{': return decode_object (ds);
00806             case 't': return decode_true (ds);
00807             case 'f': return decode_false (ds);
00808             case 'n': return decode_null (ds);
00809 
00810             case ' ':
00811             case '\t':
00812             case '\r':
00813             case '\n':
00814                 // White space
00815                 ds->start ++;
00816                 break;
00817                 
00818             default:
00819                 return SetError(ds, -1, "Expected object or value");
00820         }
00821     }
00822 }
00823 
00824 
00825 JSOBJ JSON_DecodeObject(JSONObjectDecoder *dec, const char *buffer, size_t cbBuffer)
00826 {
00827 
00828     /*
00829     FIXME: Base the size of escBuffer of that of cbBuffer so that the unicode escaping doesn't run into the wall each time */
00830     struct DecoderState ds;
00831     wchar_t escBuffer[(JSON_MAX_STACK_BUFFER_SIZE / sizeof(wchar_t))];
00832     JSOBJ ret;
00833     
00834     ds.start = (char *) buffer;
00835     ds.end = ds.start + cbBuffer;
00836 
00837     ds.escStart = escBuffer;
00838     ds.escEnd = ds.escStart + (JSON_MAX_STACK_BUFFER_SIZE / sizeof(wchar_t));
00839     ds.escHeap = 0;
00840     ds.dec = dec;
00841     ds.dec->errorStr = NULL;
00842     ds.dec->errorOffset = NULL;
00843 
00844     ds.dec = dec;
00845 
00846     ret = decode_any (&ds);
00847     
00848     if (ds.escHeap)
00849     {
00850         dec->free(ds.escStart);
00851     }
00852 
00853     if (ds.start != ds.end && ret)
00854     {
00855         dec->releaseObject(ret);    
00856         return SetError(&ds, -1, "Trailing data");
00857     }
00858 
00859     return ret;
00860 }


rosbridge_library
Author(s): Jonathan Mace
autogenerated on Thu Jan 2 2014 11:53:35