Bug 1023778 part 1 - Add JSONParserBase base class. r=Waldo

This commit is contained in:
Jan de Mooij 2014-06-13 17:21:37 +02:00
parent fcbaa23ac2
commit 5ec377d208
4 changed files with 77 additions and 59 deletions

View File

@ -174,7 +174,7 @@ TryEvalJSON(JSContext *cx, JSScript *callerScript,
if (cp == end) {
bool isArray = (chars[0] == '[');
JSONParser parser(cx, isArray ? chars : chars + 1U, isArray ? length : length - 2,
JSONParser::NoError);
JSONParserBase::NoError);
RootedValue tmp(cx);
if (!parser.parse(&tmp))
return EvalJSON_Failure;

View File

@ -576,7 +576,7 @@ AutoGCRooter::trace(JSTracer *trc)
}
case JSONPARSER:
static_cast<js::JSONParser *>(this)->trace(trc);
static_cast<js::JSONParserBase *>(this)->trace(trc);
return;
case CUSTOM:

View File

@ -23,7 +23,7 @@ using namespace js;
using mozilla::RangedPtr;
JSONParser::~JSONParser()
JSONParserBase::~JSONParserBase()
{
for (size_t i = 0; i < stack.length(); i++) {
if (stack[i].state == FinishArrayElement)
@ -40,7 +40,7 @@ JSONParser::~JSONParser()
}
void
JSONParser::trace(JSTracer *trc)
JSONParserBase::trace(JSTracer *trc)
{
for (size_t i = 0; i < stack.length(); i++) {
if (stack[i].state == FinishArrayElement) {
@ -97,13 +97,13 @@ JSONParser::error(const char *msg)
}
bool
JSONParser::errorReturn()
JSONParserBase::errorReturn()
{
return errorHandling == NoError;
}
template<JSONParser::StringType ST>
JSONParser::Token
template<JSONParserBase::StringType ST>
JSONParserBase::Token
JSONParser::readString()
{
JS_ASSERT(current < end);
@ -236,7 +236,7 @@ JSONParser::readString()
return token(Error);
}
JSONParser::Token
JSONParserBase::Token
JSONParser::readNumber()
{
JS_ASSERT(current < end);
@ -341,7 +341,7 @@ IsJSONWhitespace(jschar c)
return c == '\t' || c == '\r' || c == '\n' || c == ' ';
}
JSONParser::Token
JSONParserBase::Token
JSONParser::advance()
{
while (current < end && IsJSONWhitespace(*current))
@ -422,7 +422,7 @@ JSONParser::advance()
}
}
JSONParser::Token
JSONParserBase::Token
JSONParser::advanceAfterObjectOpen()
{
JS_ASSERT(current[-1] == '{');
@ -473,7 +473,7 @@ AssertPastValue(const RangedPtr<const jschar> current)
JS7_ISDEC(current[-1]));
}
JSONParser::Token
JSONParserBase::Token
JSONParser::advanceAfterArrayElement()
{
AssertPastValue(current);
@ -499,7 +499,7 @@ JSONParser::advanceAfterArrayElement()
return token(Error);
}
JSONParser::Token
JSONParserBase::Token
JSONParser::advancePropertyName()
{
JS_ASSERT(current[-1] == ',');
@ -518,7 +518,7 @@ JSONParser::advancePropertyName()
return token(Error);
}
JSONParser::Token
JSONParserBase::Token
JSONParser::advancePropertyColon()
{
JS_ASSERT(current[-1] == '"');
@ -539,7 +539,7 @@ JSONParser::advancePropertyColon()
return token(Error);
}
JSONParser::Token
JSONParserBase::Token
JSONParser::advanceAfterProperty()
{
AssertPastValue(current);
@ -566,7 +566,7 @@ JSONParser::advanceAfterProperty()
}
JSObject *
JSONParser::createFinishedObject(PropertyVector &properties)
JSONParserBase::createFinishedObject(PropertyVector &properties)
{
/*
* Look for an existing cached type and shape for objects with this set of
@ -611,7 +611,7 @@ JSONParser::createFinishedObject(PropertyVector &properties)
}
inline bool
JSONParser::finishObject(MutableHandleValue vp, PropertyVector &properties)
JSONParserBase::finishObject(MutableHandleValue vp, PropertyVector &properties)
{
JS_ASSERT(&properties == &stack.back().properties());
@ -627,7 +627,7 @@ JSONParser::finishObject(MutableHandleValue vp, PropertyVector &properties)
}
inline bool
JSONParser::finishArray(MutableHandleValue vp, ElementVector &elements)
JSONParserBase::finishArray(MutableHandleValue vp, ElementVector &elements)
{
JS_ASSERT(&elements == &stack.back().elements());

View File

@ -16,20 +16,21 @@
namespace js {
class MOZ_STACK_CLASS JSONParser : private JS::AutoGCRooter
// JSONParser base class. JSONParser is templatized to work on either Latin1
// or TwoByte input strings, JSONParserBase holds all state and methods that
// can be shared between the two encodings.
class MOZ_STACK_CLASS JSONParserBase : private JS::AutoGCRooter
{
public:
enum ErrorHandling { RaiseError, NoError };
private:
/* Data members */
JSContext * const cx;
JS::ConstTwoByteChars current;
const JS::ConstTwoByteChars begin, end;
Value v;
protected:
JSContext * const cx;
const ErrorHandling errorHandling;
enum Token { String, Number, True, False, Null,
@ -105,17 +106,9 @@ class MOZ_STACK_CLASS JSONParser : private JS::AutoGCRooter
Token lastToken;
#endif
public:
/* Public API */
/* Create a parser for the provided JSON data. */
JSONParser(JSContext *cx, JS::ConstTwoByteChars data, size_t length,
ErrorHandling errorHandling = RaiseError)
: AutoGCRooter(cx, JSONPARSER),
JSONParserBase(JSContext *cx, ErrorHandling errorHandling)
: JS::AutoGCRooter(cx, JSONPARSER),
cx(cx),
current(data),
begin(data),
end((data + length).get(), data.get(), length),
errorHandling(errorHandling),
stack(cx),
freeElements(cx),
@ -123,25 +116,9 @@ class MOZ_STACK_CLASS JSONParser : private JS::AutoGCRooter
#ifdef DEBUG
, lastToken(Error)
#endif
{
JS_ASSERT(current <= end);
}
{}
~JSONParserBase();
~JSONParser();
/*
* Parse the JSON data specified at construction time. If it parses
* successfully, store the prescribed value in *vp and return true. If an
* internal error (e.g. OOM) occurs during parsing, return false.
* Otherwise, if invalid input was specifed but no internal error occurred,
* behavior depends upon the error handling specified at construction: if
* error handling is RaiseError then throw a SyntaxError and return false,
* otherwise return true and set *vp to |undefined|. (JSON syntax can't
* represent |undefined|, so the JSON data couldn't have specified it.)
*/
bool parse(MutableHandleValue vp);
private:
Value numberValue() const {
JS_ASSERT(lastToken == Number);
JS_ASSERT(v.isNumber());
@ -185,6 +162,55 @@ class MOZ_STACK_CLASS JSONParser : private JS::AutoGCRooter
}
enum StringType { PropertyName, LiteralValue };
bool errorReturn();
bool finishObject(MutableHandleValue vp, PropertyVector &properties);
bool finishArray(MutableHandleValue vp, ElementVector &elements);
private:
friend void AutoGCRooter::trace(JSTracer *trc);
void trace(JSTracer *trc);
JSObject *createFinishedObject(PropertyVector &properties);
JSONParserBase(const JSONParserBase &other) MOZ_DELETE;
void operator=(const JSONParserBase &other) MOZ_DELETE;
};
class MOZ_STACK_CLASS JSONParser : public JSONParserBase
{
private:
JS::ConstTwoByteChars current;
const JS::ConstTwoByteChars begin, end;
public:
/* Public API */
/* Create a parser for the provided JSON data. */
JSONParser(JSContext *cx, JS::ConstTwoByteChars data, size_t length,
ErrorHandling errorHandling = RaiseError)
: JSONParserBase(cx, errorHandling),
current(data),
begin(data),
end((data + length).get(), data.get(), length)
{
JS_ASSERT(current <= end);
}
/*
* Parse the JSON data specified at construction time. If it parses
* successfully, store the prescribed value in *vp and return true. If an
* internal error (e.g. OOM) occurs during parsing, return false.
* Otherwise, if invalid input was specifed but no internal error occurred,
* behavior depends upon the error handling specified at construction: if
* error handling is RaiseError then throw a SyntaxError and return false,
* otherwise return true and set *vp to |undefined|. (JSON syntax can't
* represent |undefined|, so the JSON data couldn't have specified it.)
*/
bool parse(MutableHandleValue vp);
private:
template<StringType ST> Token readString();
Token readNumber();
@ -197,17 +223,9 @@ class MOZ_STACK_CLASS JSONParser : private JS::AutoGCRooter
Token advanceAfterArrayElement();
void error(const char *msg);
bool errorReturn();
JSObject *createFinishedObject(PropertyVector &properties);
bool finishObject(MutableHandleValue vp, PropertyVector &properties);
bool finishArray(MutableHandleValue vp, ElementVector &elements);
void getTextPosition(uint32_t *column, uint32_t *line);
friend void AutoGCRooter::trace(JSTracer *trc);
void trace(JSTracer *trc);
private:
JSONParser(const JSONParser &other) MOZ_DELETE;
void operator=(const JSONParser &other) MOZ_DELETE;