LCOV - code coverage report
Current view: top level - js/src/vm - JSONParser.h (source / functions) Hit Total Coverage
Test: output.info Lines: 61 63 96.8 %
Date: 2017-07-14 16:53:18 Functions: 22 26 84.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2             :  * vim: set ts=8 sts=4 et sw=4 tw=99:
       3             :  * This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #ifndef vm_JSONParser_h
       8             : #define vm_JSONParser_h
       9             : 
      10             : #include "mozilla/Attributes.h"
      11             : #include "mozilla/Range.h"
      12             : 
      13             : #include "jspubtd.h"
      14             : 
      15             : #include "ds/IdValuePair.h"
      16             : #include "vm/String.h"
      17             : 
      18             : namespace js {
      19             : 
      20             : // JSONParser base class. JSONParser is templatized to work on either Latin1
      21             : // or TwoByte input strings, JSONParserBase holds all state and methods that
      22             : // can be shared between the two encodings.
      23             : class MOZ_STACK_CLASS JSONParserBase
      24             : {
      25             :   public:
      26             :     enum ErrorHandling { RaiseError, NoError };
      27             : 
      28             :   private:
      29             :     /* Data members */
      30             :     Value v;
      31             : 
      32             :   protected:
      33             :     JSContext * const cx;
      34             : 
      35             :     const ErrorHandling errorHandling;
      36             : 
      37             :     enum Token { String, Number, True, False, Null,
      38             :                  ArrayOpen, ArrayClose,
      39             :                  ObjectOpen, ObjectClose,
      40             :                  Colon, Comma,
      41             :                  OOM, Error };
      42             : 
      43             :     // State related to the parser's current position. At all points in the
      44             :     // parse this keeps track of the stack of arrays and objects which have
      45             :     // been started but not finished yet. The actual JS object is not
      46             :     // allocated until the literal is closed, so that the result can be sized
      47             :     // according to its contents and have its type and shape filled in using
      48             :     // caches.
      49             : 
      50             :     // State for an array that is currently being parsed. This includes all
      51             :     // elements that have been seen so far.
      52             :     typedef Vector<Value, 20> ElementVector;
      53             : 
      54             :     // State for an object that is currently being parsed. This includes all
      55             :     // the key/value pairs that have been seen so far.
      56             :     typedef Vector<IdValuePair, 10> PropertyVector;
      57             : 
      58             :     // Possible states the parser can be in between values.
      59             :     enum ParserState {
      60             :         // An array element has just being parsed.
      61             :         FinishArrayElement,
      62             : 
      63             :         // An object property has just been parsed.
      64             :         FinishObjectMember,
      65             : 
      66             :         // At the start of the parse, before any values have been processed.
      67             :         JSONValue
      68             :     };
      69             : 
      70             :     // Stack element for an in progress array or object.
      71             :     struct StackEntry {
      72         167 :         ElementVector& elements() {
      73         167 :             MOZ_ASSERT(state == FinishArrayElement);
      74         167 :             return * static_cast<ElementVector*>(vector);
      75             :         }
      76             : 
      77         505 :         PropertyVector& properties() {
      78         505 :             MOZ_ASSERT(state == FinishObjectMember);
      79         505 :             return * static_cast<PropertyVector*>(vector);
      80             :         }
      81             : 
      82          48 :         explicit StackEntry(ElementVector* elements)
      83          48 :           : state(FinishArrayElement), vector(elements)
      84          48 :         {}
      85             : 
      86          53 :         explicit StackEntry(PropertyVector* properties)
      87          53 :           : state(FinishObjectMember), vector(properties)
      88          53 :         {}
      89             : 
      90             :         ParserState state;
      91             : 
      92             :       private:
      93             :         void* vector;
      94             :     };
      95             : 
      96             :     // All in progress arrays and objects being parsed, in order from outermost
      97             :     // to innermost.
      98             :     Vector<StackEntry, 10> stack;
      99             : 
     100             :     // Unused element and property vectors for previous in progress arrays and
     101             :     // objects. These vectors are not freed until the end of the parse to avoid
     102             :     // unnecessary freeing and allocation.
     103             :     Vector<ElementVector*, 5> freeElements;
     104             :     Vector<PropertyVector*, 5> freeProperties;
     105             : 
     106             : #ifdef DEBUG
     107             :     Token lastToken;
     108             : #endif
     109             : 
     110          10 :     JSONParserBase(JSContext* cx, ErrorHandling errorHandling)
     111          10 :       : cx(cx),
     112             :         errorHandling(errorHandling),
     113             :         stack(cx),
     114             :         freeElements(cx),
     115             :         freeProperties(cx)
     116             : #ifdef DEBUG
     117          10 :       , lastToken(Error)
     118             : #endif
     119          10 :     {}
     120             :     ~JSONParserBase();
     121             : 
     122             :     // Allow move construction for use with Rooted.
     123          10 :     JSONParserBase(JSONParserBase&& other)
     124          10 :       : v(other.v),
     125          10 :         cx(other.cx),
     126          10 :         errorHandling(other.errorHandling),
     127          10 :         stack(mozilla::Move(other.stack)),
     128          10 :         freeElements(mozilla::Move(other.freeElements)),
     129          10 :         freeProperties(mozilla::Move(other.freeProperties))
     130             : #ifdef DEBUG
     131          60 :       , lastToken(mozilla::Move(other.lastToken))
     132             : #endif
     133          10 :     {}
     134             : 
     135             : 
     136          28 :     Value numberValue() const {
     137          28 :         MOZ_ASSERT(lastToken == Number);
     138          28 :         MOZ_ASSERT(v.isNumber());
     139          28 :         return v;
     140             :     }
     141             : 
     142         351 :     Value stringValue() const {
     143         351 :         MOZ_ASSERT(lastToken == String);
     144         351 :         MOZ_ASSERT(v.isString());
     145         351 :         return v;
     146             :     }
     147             : 
     148         226 :     JSAtom* atomValue() const {
     149         226 :         Value strval = stringValue();
     150         226 :         return &strval.toString()->asAtom();
     151             :     }
     152             : 
     153         740 :     Token token(Token t) {
     154         740 :         MOZ_ASSERT(t != String);
     155         740 :         MOZ_ASSERT(t != Number);
     156             : #ifdef DEBUG
     157         740 :         lastToken = t;
     158             : #endif
     159         740 :         return t;
     160             :     }
     161             : 
     162         351 :     Token stringToken(JSString* str) {
     163         351 :         this->v = StringValue(str);
     164             : #ifdef DEBUG
     165         351 :         lastToken = String;
     166             : #endif
     167         351 :         return String;
     168             :     }
     169             : 
     170          28 :     Token numberToken(double d) {
     171          28 :         this->v = NumberValue(d);
     172             : #ifdef DEBUG
     173          28 :         lastToken = Number;
     174             : #endif
     175          28 :         return Number;
     176             :     }
     177             : 
     178             :     enum StringType { PropertyName, LiteralValue };
     179             : 
     180             :     bool errorReturn();
     181             : 
     182             :     bool finishObject(MutableHandleValue vp, PropertyVector& properties);
     183             :     bool finishArray(MutableHandleValue vp, ElementVector& elements);
     184             : 
     185             :     void trace(JSTracer* trc);
     186             : 
     187             :   private:
     188             :     JSONParserBase(const JSONParserBase& other) = delete;
     189             :     void operator=(const JSONParserBase& other) = delete;
     190             : };
     191             : 
     192             : template <typename CharT>
     193          20 : class MOZ_STACK_CLASS JSONParser : public JSONParserBase
     194             : {
     195             :   private:
     196             :     typedef mozilla::RangedPtr<const CharT> CharPtr;
     197             : 
     198             :     CharPtr current;
     199             :     const CharPtr begin, end;
     200             : 
     201             :   public:
     202             :     /* Public API */
     203             : 
     204             :     /* Create a parser for the provided JSON data. */
     205          10 :     JSONParser(JSContext* cx, mozilla::Range<const CharT> data,
     206             :                ErrorHandling errorHandling = RaiseError)
     207             :       : JSONParserBase(cx, errorHandling),
     208             :         current(data.begin()),
     209             :         begin(current),
     210          10 :         end(data.end())
     211             :     {
     212          10 :         MOZ_ASSERT(current <= end);
     213          10 :     }
     214             : 
     215             :     /* Allow move construction for use with Rooted. */
     216          10 :     JSONParser(JSONParser&& other)
     217          10 :       : JSONParserBase(mozilla::Move(other)),
     218             :         current(other.current),
     219             :         begin(other.begin),
     220          10 :         end(other.end)
     221          10 :     {}
     222             : 
     223             :     /*
     224             :      * Parse the JSON data specified at construction time.  If it parses
     225             :      * successfully, store the prescribed value in *vp and return true.  If an
     226             :      * internal error (e.g. OOM) occurs during parsing, return false.
     227             :      * Otherwise, if invalid input was specifed but no internal error occurred,
     228             :      * behavior depends upon the error handling specified at construction: if
     229             :      * error handling is RaiseError then throw a SyntaxError and return false,
     230             :      * otherwise return true and set *vp to |undefined|.  (JSON syntax can't
     231             :      * represent |undefined|, so the JSON data couldn't have specified it.)
     232             :      */
     233             :     bool parse(MutableHandleValue vp);
     234             : 
     235           0 :     static void trace(JSONParser<CharT>* parser, JSTracer* trc) { parser->trace(trc); }
     236           0 :     void trace(JSTracer* trc) { JSONParserBase::trace(trc); }
     237             : 
     238             :   private:
     239             :     template<StringType ST> Token readString();
     240             : 
     241             :     Token readNumber();
     242             : 
     243             :     Token advance();
     244             :     Token advancePropertyName();
     245             :     Token advancePropertyColon();
     246             :     Token advanceAfterProperty();
     247             :     Token advanceAfterObjectOpen();
     248             :     Token advanceAfterArrayElement();
     249             : 
     250             :     void error(const char* msg);
     251             : 
     252             :     void getTextPosition(uint32_t* column, uint32_t* line);
     253             : 
     254             :   private:
     255             :     JSONParser(const JSONParser& other) = delete;
     256             :     void operator=(const JSONParser& other) = delete;
     257             : };
     258             : 
     259             : template <typename CharT, typename Wrapper>
     260          10 : class MutableWrappedPtrOperations<JSONParser<CharT>, Wrapper>
     261             :   : public WrappedPtrOperations<JSONParser<CharT>, Wrapper>
     262             : {
     263             :   public:
     264          10 :     bool parse(MutableHandleValue vp) {
     265          10 :         return static_cast<Wrapper*>(this)->get().parse(vp);
     266             :     }
     267             : };
     268             : 
     269             : } /* namespace js */
     270             : 
     271             : #endif /* vm_JSONParser_h */

Generated by: LCOV version 1.13