/[jscoverage]/trunk/js/json.cpp
ViewVC logotype

Diff of /trunk/js/json.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 398 by siliconforks, Thu Oct 23 19:03:33 2008 UTC revision 399 by siliconforks, Tue Dec 9 03:37:47 2008 UTC
# Line 83  Line 83 
83      }      }
84    
85      if (!ok)      if (!ok)
86          JS_ReportError(cx, "Error parsing JSON.");          JS_ReportError(cx, "Error parsing JSON");
87    
88      return ok;      return ok;
89  }  }
90    
91  struct StringifyClosure  class StringifyClosure : JSAutoTempValueRooter
92  {  {
93      StringifyClosure(JSContext *aCx, jsval *str) : cx(aCx), s(str)  public:
94        StringifyClosure(JSContext *cx, size_t len, jsval *vec)
95            : JSAutoTempValueRooter(cx, len, vec), cx(cx), s(vec)
96      {      {
97      }      }
98    
# Line 98  Line 100 
100      jsval *s;      jsval *s;
101  };  };
102    
103  static  static JSBool
104  JSBool WriteCallback(const jschar *buf, uint32 len, void *data)  WriteCallback(const jschar *buf, uint32 len, void *data)
105  {  {
106      StringifyClosure *sc = static_cast<StringifyClosure*>(data);      StringifyClosure *sc = static_cast<StringifyClosure*>(data);
107      JSString *s1 = JSVAL_TO_STRING(*sc->s);      JSString *s1 = JSVAL_TO_STRING(sc->s[0]);
108      JSString *s2 = JS_NewUCStringCopyN(sc->cx, buf, len);      JSString *s2 = js_NewStringCopyN(sc->cx, buf, len);
109      if (!s2)      if (!s2)
110          return JS_FALSE;          return JS_FALSE;
111    
112        sc->s[1] = STRING_TO_JSVAL(s2);
113    
114      s1 = js_ConcatStrings(sc->cx, s1, s2);      s1 = js_ConcatStrings(sc->cx, s1, s2);
115      if (!s1)      if (!s1)
116          return JS_FALSE;          return JS_FALSE;
117    
118      *sc->s = STRING_TO_JSVAL(s1);      sc->s[0] = STRING_TO_JSVAL(s1);
119        sc->s[1] = JSVAL_VOID;
120    
121      return JS_TRUE;      return JS_TRUE;
122  }  }
123    
# Line 126  Line 132 
132          return JS_FALSE;          return JS_FALSE;
133    
134      // Only use objects and arrays as the root for now      // Only use objects and arrays as the root for now
135      jsval v = OBJECT_TO_JSVAL(obj);      *vp = OBJECT_TO_JSVAL(obj);
136      JSBool ok = js_TryJSON(cx, &v);      
137        JSBool ok = js_TryJSON(cx, vp);
138      JSType type;      JSType type;
139      if (!(ok && !JSVAL_IS_PRIMITIVE(v) &&      if (!ok ||
140            (type = JS_TypeOfValue(cx, v)) != JSTYPE_FUNCTION &&          JSVAL_IS_PRIMITIVE(*vp) ||
141            type != JSTYPE_XML)) {          ((type = JS_TypeOfValue(cx, *vp)) == JSTYPE_FUNCTION ||
142          JS_ReportError(cx, "Invalid argument.");          type == JSTYPE_XML)) {
143            JS_ReportError(cx, "Invalid argument");
144          return JS_FALSE;          return JS_FALSE;
145      }      }
146            
# Line 141  Line 149 
149          ok = JS_FALSE;          ok = JS_FALSE;
150    
151      if (ok) {      if (ok) {
152          jsval sv = STRING_TO_JSVAL(s);          jsval vec[2] = {STRING_TO_JSVAL(s), JSVAL_VOID};
153          StringifyClosure sc(cx, &sv);          StringifyClosure sc(cx, 2, vec);
154          JSAutoTempValueRooter tvr(cx, 1, sc.s);          JSAutoTempValueRooter resultTvr(cx, 1, sc.s);
155          ok = js_Stringify(cx, &v, NULL, &WriteCallback, &sc, 0);          ok = js_Stringify(cx, vp, NULL, &WriteCallback, &sc, 0);
156          *vp = *sc.s;          *vp = *sc.s;
157      }      }
158    
# Line 188  Line 196 
196          } else if (buf[i] <= 31 || buf[i] == 127) {          } else if (buf[i] <= 31 || buf[i] == 127) {
197              if (!callback(&buf[mark], i - mark, data) || !callback(unicodeEscape, 4, data))              if (!callback(&buf[mark], i - mark, data) || !callback(unicodeEscape, 4, data))
198                  return JS_FALSE;                  return JS_FALSE;
199              char ubuf[10];              char ubuf[3];
200              unsigned int len = JS_snprintf(ubuf, sizeof(ubuf), "%.2x", buf[i]);              size_t len = JS_snprintf(ubuf, sizeof(ubuf), "%.2x", buf[i]);
201              JS_ASSERT(len == 2);              JS_ASSERT(len == 2);
202              // TODO: don't allocate a JSString just to inflate (js_InflateStringToBuffer on static?)              jschar wbuf[3];
203              JSString *us = JS_NewStringCopyN(cx, ubuf, len);              size_t wbufSize = JS_ARRAY_LENGTH(wbuf);
204              if (!callback(JS_GetStringChars(us), len, data))              if (!js_InflateStringToBuffer(cx, ubuf, len, wbuf, &wbufSize) ||
205                    !callback(wbuf, wbufSize, data)) {
206                  return JS_FALSE;                  return JS_FALSE;
207                }
208              mark = i + 1;              mark = i + 1;
209          }          }
210      }      }
# Line 221  Line 231 
231      jschar output = jschar(isArray ? '[' : '{');      jschar output = jschar(isArray ? '[' : '{');
232      if (!callback(&output, 1, data))      if (!callback(&output, 1, data))
233          return JS_FALSE;          return JS_FALSE;
234        
235      JSObject *iterObj = NULL;      JSObject *iterObj = NULL;
236      jsint i = 0;      jsint i = 0;
237      jsuint length = 0;      jsuint length = 0;
238    
239      if (isArray) {      if (isArray) {
240          if (!JS_GetArrayLength(cx, obj, &length))          if (!js_GetLengthProperty(cx, obj, &length))
241              return JS_FALSE;              return JS_FALSE;
242      } else {      } else {
243          if (!js_ValueToIterator(cx, JSITER_ENUMERATE, vp))          if (!js_ValueToIterator(cx, JSITER_ENUMERATE, vp))
# Line 246  Line 256 
256          if (isArray) {          if (isArray) {
257              if ((jsuint)i >= length)              if ((jsuint)i >= length)
258                  break;                  break;
259              ok = JS_GetElement(cx, obj, i++, &outputValue);              ok = OBJ_GET_PROPERTY(cx, obj, INT_TO_JSID(i), &outputValue);
260                i++;
261          } else {          } else {
262              ok = js_CallIteratorNext(cx, iterObj, &key);              ok = js_CallIteratorNext(cx, iterObj, &key);
263              if (!ok)              if (!ok)
# Line 258  Line 269 
269              if (JSVAL_IS_STRING(key)) {              if (JSVAL_IS_STRING(key)) {
270                  ks = JSVAL_TO_STRING(key);                  ks = JSVAL_TO_STRING(key);
271              } else {              } else {
272                  ks = JS_ValueToString(cx, key);                  ks = js_ValueToString(cx, key);
273                  if (!ks) {                  if (!ks) {
274                      ok = JS_FALSE;                      ok = JS_FALSE;
275                      break;                      break;
# Line 305  Line 316 
316    
317          // If this isn't an array, we need to output a key          // If this isn't an array, we need to output a key
318          if (!isArray) {          if (!isArray) {
319              s = JS_ValueToString(cx, key);              s = js_ValueToString(cx, key);
320              if (!s) {              if (!s) {
321                  ok = JS_FALSE;                  ok = JS_FALSE;
322                  break;                  break;
# Line 323  Line 334 
334    
335          if (!JSVAL_IS_PRIMITIVE(outputValue)) {          if (!JSVAL_IS_PRIMITIVE(outputValue)) {
336              // recurse              // recurse
337            ok = js_Stringify(cx, &outputValue, replacer, callback, data, depth + 1);              ok = js_Stringify(cx, &outputValue, replacer, callback, data, depth + 1);
338          } else {          } else {
339              JSString *outputString;              JSString *outputString;
340              s = JS_ValueToString(cx, outputValue);              s = js_ValueToString(cx, outputValue);
341              if (!s) {              if (!s) {
342                  ok = JS_FALSE;                  ok = JS_FALSE;
343                  break;                  break;
# Line 336  Line 347 
347                  ok = write_string(cx, callback, data, JS_GetStringChars(s), JS_GetStringLength(s));                  ok = write_string(cx, callback, data, JS_GetStringChars(s), JS_GetStringLength(s));
348                  if (!ok)                  if (!ok)
349                      break;                      break;
350                    
351                  continue;                  continue;
352              }              }
353    
# Line 359  Line 370 
370                  break;                  break;
371              }              }
372    
373                if (!outputString) {
374                    ok = JS_FALSE;
375                    break;
376                }
377    
378              ok = callback(JS_GetStringChars(outputString), JS_GetStringLength(outputString), data);              ok = callback(JS_GetStringChars(outputString), JS_GetStringLength(outputString), data);
379          }          }
380      } while (ok);      } while (ok);
# Line 370  Line 386 
386      }      }
387    
388      if (!ok) {      if (!ok) {
389          JS_ReportError(cx, "Error during JSON encoding.");          JS_ReportError(cx, "Error during JSON encoding");
390          return JS_FALSE;          return JS_FALSE;
391      }      }
392    
# Line 381  Line 397 
397  }  }
398    
399  // helper to determine whether a character could be part of a number  // helper to determine whether a character could be part of a number
400  static JSBool IsNumChar(jschar c)  static JSBool IsNumChar(jschar c)
401  {  {
402      return ((c <= '9' && c >= '0') || c == '.' || c == '-' || c == '+' || c == 'e' || c == 'E');      return ((c <= '9' && c >= '0') || c == '.' || c == '-' || c == '+' || c == 'e' || c == 'E');
403  }  }
# Line 392  Line 408 
408      if (!cx)      if (!cx)
409          return NULL;          return NULL;
410    
411      JSObject *arr = JS_NewArrayObject(cx, 0, NULL);      JSObject *arr = js_NewArrayObject(cx, 0, NULL);
412      if (!arr)      if (!arr)
413          return NULL;          return NULL;
414    
415      JSONParser *jp = (JSONParser*) JS_malloc(cx, sizeof(JSONParser));      JSONParser *jp = (JSONParser*) JS_malloc(cx, sizeof(JSONParser));
416      if (!jp)      if (!jp)
417          return NULL;                  return NULL;
418      jp->buffer = NULL;      jp->buffer = NULL;
419    
420      jp->objectStack = arr;      jp->objectStack = arr;
421      if (!JS_AddRoot(cx, jp->objectStack))      if (!js_AddRoot(cx, &jp->objectStack, "JSON parse stack"))
422          goto bad;          goto bad;
423    
424      jp->hexChar = 0;      jp->hexChar = 0;
# Line 410  Line 426 
426      jp->statep = jp->stateStack;      jp->statep = jp->stateStack;
427      *jp->statep = JSON_PARSE_STATE_INIT;      *jp->statep = JSON_PARSE_STATE_INIT;
428      jp->rootVal = rootVal;      jp->rootVal = rootVal;
429      jp->objectKey = NULL;  
430        jp->objectKey = (JSStringBuffer*) JS_malloc(cx, sizeof(JSStringBuffer));
431        if (!jp->objectKey)
432            goto bad;
433        js_InitStringBuffer(jp->objectKey);
434        
435      jp->buffer = (JSStringBuffer*) JS_malloc(cx, sizeof(JSStringBuffer));      jp->buffer = (JSStringBuffer*) JS_malloc(cx, sizeof(JSStringBuffer));
436      if (!jp->buffer)      if (!jp->buffer)
437          goto bad;          goto bad;
# Line 429  Line 450 
450      if (!jp)      if (!jp)
451          return JS_TRUE;          return JS_TRUE;
452    
453        if (jp->objectKey)
454            js_FinishStringBuffer(jp->objectKey);
455        JS_free(cx, jp->objectKey);
456    
457      if (jp->buffer)      if (jp->buffer)
458          js_FinishStringBuffer(jp->buffer);          js_FinishStringBuffer(jp->buffer);
       
459      JS_free(cx, jp->buffer);      JS_free(cx, jp->buffer);
460      if (!JS_RemoveRoot(cx, jp->objectStack))      
461        if (!js_RemoveRoot(cx->runtime, &jp->objectStack))
462          return JS_FALSE;          return JS_FALSE;
463      JSBool ok = *jp->statep == JSON_PARSE_STATE_FINISHED;      JSBool ok = *jp->statep == JSON_PARSE_STATE_FINISHED;
464      JS_free(cx, jp);      JS_free(cx, jp);
# Line 441  Line 466 
466      return ok;      return ok;
467  }  }
468    
   
469  static JSBool  static JSBool
470  PushState(JSONParser *jp, JSONParserState state)  PushState(JSONParser *jp, JSONParserState state)
471  {  {
# Line 464  Line 488 
488      if (jp->statep < jp->stateStack) {      if (jp->statep < jp->stateStack) {
489          jp->statep = jp->stateStack;          jp->statep = jp->stateStack;
490          return JS_FALSE;          return JS_FALSE;
491      }      }
492    
493      if (*jp->statep == JSON_PARSE_STATE_INIT)      if (*jp->statep == JSON_PARSE_STATE_INIT)
494          *jp->statep = JSON_PARSE_STATE_FINISHED;          *jp->statep = JSON_PARSE_STATE_FINISHED;
# Line 476  Line 500 
500  PushValue(JSContext *cx, JSONParser *jp, JSObject *parent, jsval value)  PushValue(JSContext *cx, JSONParser *jp, JSObject *parent, jsval value)
501  {  {
502      JSAutoTempValueRooter tvr(cx, 1, &value);      JSAutoTempValueRooter tvr(cx, 1, &value);
503      
504      JSBool ok;      JSBool ok;
505      if (OBJ_IS_ARRAY(cx, parent)) {      if (OBJ_IS_ARRAY(cx, parent)) {
506          jsuint len;          jsuint len;
507          ok = JS_GetArrayLength(cx, parent, &len);          ok = js_GetLengthProperty(cx, parent, &len);
508          if (ok)          if (ok) {
509              ok = JS_SetElement(cx, parent, len, &value);              ok = OBJ_DEFINE_PROPERTY(cx, parent, INT_TO_JSID(len), value,
510                                         NULL, NULL, JSPROP_ENUMERATE, NULL);
511            }
512      } else {      } else {
513          ok = JS_DefineUCProperty(cx, parent, JS_GetStringChars(jp->objectKey),          ok = JS_DefineUCProperty(cx, parent, jp->objectKey->base,
514                                   JS_GetStringLength(jp->objectKey), value,                                   STRING_BUFFER_OFFSET(jp->objectKey), value,
515                                   NULL, NULL, JSPROP_ENUMERATE);                                   NULL, NULL, JSPROP_ENUMERATE);
516            js_FinishStringBuffer(jp->objectKey);
517            js_InitStringBuffer(jp->objectKey);
518      }      }
519    
520      return ok;      return ok;
# Line 496  Line 524 
524  PushObject(JSContext *cx, JSONParser *jp, JSObject *obj)  PushObject(JSContext *cx, JSONParser *jp, JSObject *obj)
525  {  {
526      jsuint len;      jsuint len;
527      if (!JS_GetArrayLength(cx, jp->objectStack, &len))      if (!js_GetLengthProperty(cx, jp->objectStack, &len))
528          return JS_FALSE;          return JS_FALSE;
529      if (len >= JSON_MAX_DEPTH)      if (len >= JSON_MAX_DEPTH)
530          return JS_FALSE; // decoding error          return JS_FALSE; // decoding error
531    
532      jsval v = OBJECT_TO_JSVAL(obj);      jsval v = OBJECT_TO_JSVAL(obj);
533        JSAutoTempValueRooter tvr(cx, v);
534    
535      // Check if this is the root object      // Check if this is the root object
536      if (len == 0) {      if (len == 0) {
537          *jp->rootVal = v;                  *jp->rootVal = v;
538          if (!JS_SetElement(cx, jp->objectStack, 0, jp->rootVal))          // This property must be enumerable to keep the array dense
539            if (!OBJ_DEFINE_PROPERTY(cx, jp->objectStack, INT_TO_JSID(0), *jp->rootVal,
540                                     NULL, NULL, JSPROP_ENUMERATE, NULL)) {
541              return JS_FALSE;              return JS_FALSE;
542            }
543          return JS_TRUE;          return JS_TRUE;
544      }      }
545    
546      jsval p;      jsval p;
547      if (!JS_GetElement(cx, jp->objectStack, len - 1, &p))      if (!OBJ_GET_PROPERTY(cx, jp->objectStack, INT_TO_JSID(len - 1), &p))
548          return JS_FALSE;          return JS_FALSE;
549    
550      JS_ASSERT(JSVAL_IS_OBJECT(p));      JS_ASSERT(JSVAL_IS_OBJECT(p));
551      JSObject *parent = JSVAL_TO_OBJECT(p);      JSObject *parent = JSVAL_TO_OBJECT(p);
552      if (!PushValue(cx, jp, parent, OBJECT_TO_JSVAL(obj)))      if (!PushValue(cx, jp, parent, OBJECT_TO_JSVAL(obj)))
553          return JS_FALSE;          return JS_FALSE;
554    
555      if (!JS_SetElement(cx, jp->objectStack, len, &v))      // This property must be enumerable to keep the array dense
556        if (!OBJ_DEFINE_PROPERTY(cx, jp->objectStack, INT_TO_JSID(len), v,
557                                 NULL, NULL, JSPROP_ENUMERATE, NULL)) {
558          return JS_FALSE;          return JS_FALSE;
559        }
560    
561      return JS_TRUE;      return JS_TRUE;
562  }  }
563    
564    static JSObject *
565    GetTopOfObjectStack(JSContext *cx, JSONParser *jp)
566    {
567        jsuint length;
568        if (!js_GetLengthProperty(cx, jp->objectStack, &length))
569            return NULL;
570        
571        jsval o;
572        if (!OBJ_GET_PROPERTY(cx, jp->objectStack, INT_TO_JSID(length - 1), &o))
573            return NULL;
574        
575        JS_ASSERT(!JSVAL_IS_PRIMITIVE(o));
576        return JSVAL_TO_OBJECT(o);
577    }
578    
579  static JSBool  static JSBool
580  OpenObject(JSContext *cx, JSONParser *jp)  OpenObject(JSContext *cx, JSONParser *jp)
581  {  {
582      JSObject *obj = JS_NewObject(cx, NULL, NULL, NULL);      JSObject *obj = js_NewObject(cx, &js_ObjectClass, NULL, NULL, 0);
583      if (!obj)      if (!obj)
584          return JS_FALSE;          return JS_FALSE;
585    
# Line 539  Line 590 
590  OpenArray(JSContext *cx, JSONParser *jp)  OpenArray(JSContext *cx, JSONParser *jp)
591  {  {
592      // Add an array to an existing array or object      // Add an array to an existing array or object
593      JSObject *arr = JS_NewArrayObject(cx, 0, NULL);      JSObject *arr = js_NewArrayObject(cx, 0, NULL);
594      if (!arr)      if (!arr)
595          return JS_FALSE;          return JS_FALSE;
596    
# Line 550  Line 601 
601  CloseObject(JSContext *cx, JSONParser *jp)  CloseObject(JSContext *cx, JSONParser *jp)
602  {  {
603      jsuint len;      jsuint len;
604      if (!JS_GetArrayLength(cx, jp->objectStack, &len))      if (!js_GetLengthProperty(cx, jp->objectStack, &len))
605          return JS_FALSE;          return JS_FALSE;
606      if (!JS_SetArrayLength(cx, jp->objectStack, len - 1))      if (!js_SetLengthProperty(cx, jp->objectStack, len - 1))
607          return JS_FALSE;          return JS_FALSE;
608    
609      return JS_TRUE;      return JS_TRUE;
# Line 561  Line 612 
612  static JSBool  static JSBool
613  CloseArray(JSContext *cx, JSONParser *jp)  CloseArray(JSContext *cx, JSONParser *jp)
614  {  {
615    return CloseObject(cx, jp);      return CloseObject(cx, jp);
616  }  }
617    
618  static JSBool  static JSBool
619  HandleNumber(JSContext *cx, JSONParser *jp, const jschar *buf, uint32 len)  HandleNumber(JSContext *cx, JSONParser *jp, const jschar *buf, uint32 len)
620  {  {
     JSBool ok;  
     jsuint length;  
     if (!JS_GetArrayLength(cx, jp->objectStack, &length))  
         return JS_FALSE;  
   
     jsval o;  
     if (!JS_GetElement(cx, jp->objectStack, length - 1, &o))  
         return JS_FALSE;  
     JS_ASSERT(JSVAL_IS_OBJECT(o));  
     JSObject *obj = JSVAL_TO_OBJECT(o);  
   
621      const jschar *ep;      const jschar *ep;
622      double val;          double val;
623      if (!js_strtod(cx, buf, buf + len, &ep, &val) || ep != buf + len)      if (!js_strtod(cx, buf, buf + len, &ep, &val) || ep != buf + len)
624          return JS_FALSE;          return JS_FALSE;
625    
626        JSBool ok;
627      jsval numVal;      jsval numVal;
628      if (JS_NewNumberValue(cx, val, &numVal))      JSObject *obj = GetTopOfObjectStack(cx, jp);
629        if (obj && JS_NewNumberValue(cx, val, &numVal))
630          ok = PushValue(cx, jp, obj, numVal);          ok = PushValue(cx, jp, obj, numVal);
631      else      else
632          ok = JS_FALSE; // decode error          ok = JS_FALSE; // decode error
# Line 595  Line 637 
637  static JSBool  static JSBool
638  HandleString(JSContext *cx, JSONParser *jp, const jschar *buf, uint32 len)  HandleString(JSContext *cx, JSONParser *jp, const jschar *buf, uint32 len)
639  {  {
640      jsuint length;      JSObject *obj = GetTopOfObjectStack(cx, jp);
641      if (!JS_GetArrayLength(cx, jp->objectStack, &length))      JSString *str = js_NewStringCopyN(cx, buf, len);
642          return JS_FALSE;      if (!obj || !str)
   
     jsval o;  
     if (!JS_GetElement(cx, jp->objectStack, length - 1, &o))  
         return JS_FALSE;  
     JS_ASSERT(JSVAL_IS_OBJECT(o));  
     JSObject *obj = JSVAL_TO_OBJECT(o);  
   
     JSString *str = JS_NewUCStringCopyN(cx, buf, len);  
     if (!str)  
643          return JS_FALSE;          return JS_FALSE;
644    
645      return PushValue(cx, jp, obj, STRING_TO_JSVAL(str));      return PushValue(cx, jp, obj, STRING_TO_JSVAL(str));
# Line 629  Line 662 
662      else      else
663          return JS_FALSE;          return JS_FALSE;
664    
665      jsuint length;      JSObject *obj = GetTopOfObjectStack(cx, jp);
666      if (!JS_GetArrayLength(cx, jp->objectStack, &length))      if (!obj)
         return JS_FALSE;  
   
     jsval o;  
     if (!JS_GetElement(cx, jp->objectStack, length - 1, &o))  
667          return JS_FALSE;          return JS_FALSE;
     JS_ASSERT(JSVAL_IS_OBJECT(o));  
     JSObject *obj = JSVAL_TO_OBJECT(o);  
668    
669      return PushValue(cx, jp, obj, keyword);      return PushValue(cx, jp, obj, keyword);
670  }  }
671    
672  static JSBool  static JSBool
673  HandleData(JSContext *cx, JSONParser *jp, JSONDataType type, const jschar *buf, uint32 len)  HandleData(JSContext *cx, JSONParser *jp, JSONDataType type)
674  {  {
675    JSBool ok = JS_FALSE;    JSBool ok = JS_FALSE;
676    
677      if (!STRING_BUFFER_OK(jp->buffer))
678          return JS_FALSE;
679    
680    switch (type) {    switch (type) {
681      case JSON_DATA_STRING:      case JSON_DATA_STRING:
682        ok = HandleString(cx, jp, buf, len);        ok = HandleString(cx, jp, jp->buffer->base, STRING_BUFFER_OFFSET(jp->buffer));
683        break;        break;
684    
685      case JSON_DATA_KEYSTRING:      case JSON_DATA_KEYSTRING:
686        jp->objectKey = JS_NewUCStringCopyN(cx, buf, len);        js_AppendUCString(jp->objectKey, jp->buffer->base, STRING_BUFFER_OFFSET(jp->buffer));
687        ok = JS_TRUE;        ok = STRING_BUFFER_OK(jp->objectKey);
688        break;        break;
689    
690      case JSON_DATA_NUMBER:      case JSON_DATA_NUMBER:
691        ok = HandleNumber(cx, jp, buf, len);        ok = HandleNumber(cx, jp, jp->buffer->base, STRING_BUFFER_OFFSET(jp->buffer));
692        break;        break;
693    
694      case JSON_DATA_KEYWORD:      case JSON_DATA_KEYWORD:
695        ok = HandleKeyword(cx, jp, buf, len);        ok = HandleKeyword(cx, jp, jp->buffer->base, STRING_BUFFER_OFFSET(jp->buffer));
696        break;        break;
697    
698      default:      default:
# Line 684  Line 714 
714          PushState(jp, JSON_PARSE_STATE_OBJECT_VALUE);          PushState(jp, JSON_PARSE_STATE_OBJECT_VALUE);
715      }      }
716    
717      for (i = 0; i < len; i++) {              for (i = 0; i < len; i++) {
718          jschar c = data[i];          jschar c = data[i];
719          switch (*jp->statep) {          switch (*jp->statep) {
720              case JSON_PARSE_STATE_VALUE :              case JSON_PARSE_STATE_VALUE :
# Line 692  Line 722 
722                      // empty array                      // empty array
723                      if (!PopState(jp))                      if (!PopState(jp))
724                          return JS_FALSE;                          return JS_FALSE;
725                      if (*jp->statep != JSON_PARSE_STATE_ARRAY)                      if (*jp->statep != JSON_PARSE_STATE_ARRAY)
726                          return JS_FALSE; // unexpected char                          return JS_FALSE; // unexpected char
727                      if (!CloseArray(cx, jp) || !PopState(jp))                      if (!CloseArray(cx, jp) || !PopState(jp))
728                          return JS_FALSE;                          return JS_FALSE;
# Line 707  Line 737 
737                  if (c == '"') {                  if (c == '"') {
738                      *jp->statep = JSON_PARSE_STATE_STRING;                      *jp->statep = JSON_PARSE_STATE_STRING;
739                      break;                      break;
740                  }                  }
741    
742                  if (IsNumChar(c)) {                  if (IsNumChar(c)) {
743                      *jp->statep = JSON_PARSE_STATE_NUMBER;                      *jp->statep = JSON_PARSE_STATE_NUMBER;
# Line 737  Line 767 
767                  break;                  break;
768    
769              case JSON_PARSE_STATE_OBJECT :              case JSON_PARSE_STATE_OBJECT :
770                  if (c == '}') {                                      if (c == '}') {
771                      if (!CloseObject(cx, jp) || !PopState(jp))                      if (!CloseObject(cx, jp) || !PopState(jp))
772                          return JS_FALSE;                          return JS_FALSE;
773                  } else if (c == ',') {                  } else if (c == ',') {
# Line 759  Line 789 
789                      return JS_FALSE; // unexpected                      return JS_FALSE; // unexpected
790                  }                  }
791                  break;                  break;
792    
793              case JSON_PARSE_STATE_OBJECT_PAIR :              case JSON_PARSE_STATE_OBJECT_PAIR :
794                  if (c == '"') {                  if (c == '"') {
795                      // we want to be waiting for a : when the string has been read                      // we want to be waiting for a : when the string has been read
# Line 773  Line 804 
804                    return JS_FALSE; // unexpected                    return JS_FALSE; // unexpected
805                  }                  }
806                  break;                  break;
807    
808              case JSON_PARSE_STATE_OBJECT_IN_PAIR:              case JSON_PARSE_STATE_OBJECT_IN_PAIR:
809                  if (c == ':') {                  if (c == ':') {
810                      *jp->statep = JSON_PARSE_STATE_VALUE;                      *jp->statep = JSON_PARSE_STATE_VALUE;
# Line 780  Line 812 
812                      return JS_FALSE; // unexpected                      return JS_FALSE; // unexpected
813                  }                  }
814                  break;                  break;
815    
816              case JSON_PARSE_STATE_STRING:              case JSON_PARSE_STATE_STRING:
817                  if (c == '"') {                  if (c == '"') {
818                      if (!PopState(jp))                      if (!PopState(jp))
# Line 790  Line 823 
823                      } else {                      } else {
824                          jdt = JSON_DATA_STRING;                          jdt = JSON_DATA_STRING;
825                      }                      }
826                      if (!HandleData(cx, jp, jdt, jp->buffer->base, STRING_BUFFER_OFFSET(jp->buffer)))                      if (!HandleData(cx, jp, jdt))
827                          return JS_FALSE;                          return JS_FALSE;
828                  } else if (c == '\\') {                  } else if (c == '\\') {
829                      *jp->statep = JSON_PARSE_STATE_STRING_ESCAPE;                      *jp->statep = JSON_PARSE_STATE_STRING_ESCAPE;
# Line 798  Line 831 
831                      js_AppendChar(jp->buffer, c);                      js_AppendChar(jp->buffer, c);
832                  }                  }
833                  break;                  break;
834            
835              case JSON_PARSE_STATE_STRING_ESCAPE:              case JSON_PARSE_STATE_STRING_ESCAPE:
836                  switch(c) {                  switch (c) {
837                      case '"':                      case '"':
838                      case '\\':                      case '\\':
839                      case '/':                      case '/':
# Line 824  Line 857 
857                  js_AppendChar(jp->buffer, c);                  js_AppendChar(jp->buffer, c);
858                  *jp->statep = JSON_PARSE_STATE_STRING;                  *jp->statep = JSON_PARSE_STATE_STRING;
859                  break;                  break;
860    
861              case JSON_PARSE_STATE_STRING_HEX:              case JSON_PARSE_STATE_STRING_HEX:
862                  if (('0' <= c) && (c <= '9'))                  if (('0' <= c) && (c <= '9'))
863                    jp->hexChar = (jp->hexChar << 4) | (c - '0');                    jp->hexChar = (jp->hexChar << 4) | (c - '0');
# Line 841  Line 875 
875                      *jp->statep = JSON_PARSE_STATE_STRING;                      *jp->statep = JSON_PARSE_STATE_STRING;
876                  }                  }
877                  break;                  break;
878    
879              case JSON_PARSE_STATE_KEYWORD:              case JSON_PARSE_STATE_KEYWORD:
880                  if (JS7_ISLET(c)) {                  if (JS7_ISLET(c)) {
881                      js_AppendChar(jp->buffer, c);                      js_AppendChar(jp->buffer, c);
882                  } else {                  } else {
883                      // this character isn't part of the keyword, process it again                      // this character isn't part of the keyword, process it again
884                      i--;                      i--;
885                      if(!PopState(jp))                      if (!PopState(jp))
886                          return JS_FALSE;                          return JS_FALSE;
887                    
888                      if (!HandleData(cx, jp, JSON_DATA_KEYWORD, jp->buffer->base, STRING_BUFFER_OFFSET(jp->buffer)))                      if (!HandleData(cx, jp, JSON_DATA_KEYWORD))
889                          return JS_FALSE;                          return JS_FALSE;
890                  }                  }
891                  break;                  break;
892    
893              case JSON_PARSE_STATE_NUMBER:              case JSON_PARSE_STATE_NUMBER:
894                  if (IsNumChar(c)) {                  if (IsNumChar(c)) {
895                      js_AppendChar(jp->buffer, c);                      js_AppendChar(jp->buffer, c);
896                  } else {                  } else {
897                      // this character isn't part of the number, process it again                      // this character isn't part of the number, process it again
898                      i--;                      i--;
899                      if(!PopState(jp))                      if (!PopState(jp))
900                          return JS_FALSE;                          return JS_FALSE;
901                      if (!HandleData(cx, jp, JSON_DATA_NUMBER, jp->buffer->base, STRING_BUFFER_OFFSET(jp->buffer)))                      if (!HandleData(cx, jp, JSON_DATA_NUMBER))
902                          return JS_FALSE;                          return JS_FALSE;
903                  }                  }
904                  break;                  break;
905    
906              case JSON_PARSE_STATE_FINISHED:              case JSON_PARSE_STATE_FINISHED:
907                  if (!JS_ISXMLSPACE(c))                  if (!JS_ISXMLSPACE(c))
908                    return JS_FALSE; // extra input                    return JS_FALSE; // extra input
909    
910                  break;                  break;
911    
912              default:              default:
913                  JS_NOT_REACHED("Invalid JSON parser state");                  JS_NOT_REACHED("Invalid JSON parser state");
914        }        }
# Line 906  Line 944 
944      if (!JSON)      if (!JSON)
945          return NULL;          return NULL;
946      if (!JS_DefineProperty(cx, obj, js_JSON_str, OBJECT_TO_JSVAL(JSON),      if (!JS_DefineProperty(cx, obj, js_JSON_str, OBJECT_TO_JSVAL(JSON),
947                             JS_PropertyStub, JS_PropertyStub, JSPROP_ENUMERATE))                             JS_PropertyStub, JS_PropertyStub, 0))
948          return NULL;          return NULL;
949    
950      if (!JS_DefineFunctions(cx, JSON, json_static_methods))      if (!JS_DefineFunctions(cx, JSON, json_static_methods))

Legend:
Removed from v.398  
changed lines
  Added in v.399

  ViewVC Help
Powered by ViewVC 1.1.24