Bug 1418847 - Morph struct PrefParserState into class Parser. r=glandium

This patch makes it a proper class, and moves existing functions into it.

MozReview-Commit-ID: 5pbT3ljq44R

--HG--
extra : rebase_source : ac7ba98f9d39b3cd6f71498a5e108cb6757034e0
This commit is contained in:
Nicholas Nethercote 2017-11-19 20:10:07 +11:00
parent c9eb43789d
commit 8098ada3c9

View File

@ -1058,45 +1058,77 @@ PREF_ReaderCallback(void* aClosure,
// The pref name and value must be copied by the implementor of the callback
// if they are needed beyond the scope of the callback function.
//
// |aClosure| is user data passed to PREF_InitParseState.
// |aPref| is the preference name.
// |aClosure| is user data passed previously to Parser's constructor.
// |aPrefName| is the preference name.
// |aValue| is the preference value.
// |aType| is the preference type.
// |aIsDefault| indicates if it's a default preference.
// |aIsSticky| indicates if it's a sticky preference.
typedef void (*PrefReader)(void* aClosure,
const char* aPref,
const char* aPrefName,
PrefValue aValue,
PrefType aType,
bool aIsDefault,
bool aIsSticky);
// Report any errors or warnings we encounter during parsing.
typedef void (*PrefParseErrorReporter)(const char* aMessage,
int aLine,
bool aError);
typedef void (*ParseErrorReporter)(const char* aMessage,
int aLine,
bool aError);
struct PrefParseState
class Parser
{
PrefReader mReader;
PrefParseErrorReporter mReporter;
void* mClosure;
int mState; // PREF_PARSE_...
int mNextState; // sometimes used...
const char* mStrMatch; // string to match
int mStrIndex; // next char of smatch to check;
// also, counter in \u parsing
char16_t mUtf16[2]; // parsing UTF16 (\u) escape
int mEscLen; // length in mEscTmp
char mEscTmp[6]; // raw escape to put back if err
char mQuoteChar; // char delimiter for quotations
char* mLb; // line buffer (only allocation)
char* mLbCur; // line buffer cursor
char* mLbEnd; // line buffer end
char* mVb; // value buffer (ptr into mLb)
Maybe<PrefType> mVtype; // pref value type
bool mIsDefault; // true if (default) pref
bool mIsSticky; // true if (sticky) pref
public:
Parser(PrefReader aReader, ParseErrorReporter aReporter, void* aClosure)
: mReader(aReader)
, mClosure(aClosure)
, mReporter(aReporter)
, mState()
, mNextState()
, mStrMatch()
, mStrIndex()
, mUtf16()
, mEscLen()
, mEscTmp()
, mQuoteChar()
, mLb()
, mLbCur()
, mLbEnd()
, mVb()
, mVtype()
, mIsDefault()
, mIsSticky()
{
}
~Parser() { free(mLb); }
bool Parse(const char* aBuf, int aBufLen);
bool GrowBuf();
void ReportProblem(const char* aMessage, int aLine, bool aError);
private:
PrefReader mReader; // called for each preference
void* mClosure; // closure data for mReader
ParseErrorReporter mReporter; // called for warnings/errors
int mState; // PREF_PARSE_...
int mNextState; // sometimes used...
const char* mStrMatch; // string to match
int mStrIndex; // next char of smatch to check;
// also, counter in \u parsing
char16_t mUtf16[2]; // parsing UTF16 (\u) escape
int mEscLen; // length in mEscTmp
char mEscTmp[6]; // raw escape to put back if err
char mQuoteChar; // char delimiter for quotations
char* mLb; // line buffer (only allocation)
char* mLbCur; // line buffer cursor
char* mLbEnd; // line buffer end
char* mVb; // value buffer (ptr into mLb)
Maybe<PrefType> mVtype; // pref value type
bool mIsDefault; // true if (default) pref
bool mIsSticky; // true if (sticky) pref
};
// Pref parser states.
@ -1134,26 +1166,23 @@ static const char kFalse[] = "false";
// This function will increase the size of the buffer owned by the given pref
// parse state. We currently use a simple doubling algorithm, but the only hard
// requirement is that it increase the buffer by at least the size of the
// aPS->mEscTmp buffer used for escape processing (currently 6 bytes).
// mEscTmp buffer used for escape processing (currently 6 bytes).
//
// The buffer is used to store partial pref lines. It is freed when the parse
// state is destroyed.
//
// @param aPS
// parse state instance
//
// This function updates all pointers that reference an address within mLb
// since realloc may relocate the buffer.
//
// @return false if insufficient memory.
static bool
pref_GrowBuf(PrefParseState* aPS)
// Returns false on failure.
bool
Parser::GrowBuf()
{
int bufLen, curPos, valPos;
bufLen = aPS->mLbEnd - aPS->mLb;
curPos = aPS->mLbCur - aPS->mLb;
valPos = aPS->mVb - aPS->mLb;
bufLen = mLbEnd - mLb;
curPos = mLbCur - mLb;
valPos = mVb - mLb;
if (bufLen == 0) {
bufLen = 128; // default buffer size
@ -1161,27 +1190,24 @@ pref_GrowBuf(PrefParseState* aPS)
bufLen <<= 1; // double buffer size
}
aPS->mLb = (char*)realloc(aPS->mLb, bufLen);
if (!aPS->mLb) {
mLb = (char*)realloc(mLb, bufLen);
if (!mLb) {
return false;
}
aPS->mLbCur = aPS->mLb + curPos;
aPS->mLbEnd = aPS->mLb + bufLen;
aPS->mVb = aPS->mLb + valPos;
mLbCur = mLb + curPos;
mLbEnd = mLb + bufLen;
mVb = mLb + valPos;
return true;
}
// Report an error or a warning. If not specified, just dump to stderr.
static void
pref_ReportParseProblem(PrefParseState& aPS,
const char* aMessage,
int aLine,
bool aError)
void
Parser::ReportProblem(const char* aMessage, int aLine, bool aError)
{
if (aPS.mReporter) {
aPS.mReporter(aMessage, aLine, aError);
if (mReporter) {
mReporter(aMessage, aLine, aError);
} else {
printf_stderr("**** Preference parsing %s (line %d) = %s **\n",
(aError ? "error" : "warning"),
@ -1190,39 +1216,9 @@ pref_ReportParseProblem(PrefParseState& aPS,
}
}
// Initialize a PrefParseState instance.
//
// |aPS| is the PrefParseState instance.
// |aReader| is the PrefReader callback function, which will be called once for
// each preference name value pair extracted.
// |aReporter| is the PrefParseErrorReporter callback function, which will be
// called if we encounter any errors (stop) or warnings (continue) during
// parsing.
// |aClosure| is extra data passed to |aReader|.
static void
PREF_InitParseState(PrefParseState* aPS,
PrefReader aReader,
PrefParseErrorReporter aReporter,
void* aClosure)
{
memset(aPS, 0, sizeof(*aPS));
aPS->mReader = aReader;
aPS->mClosure = aClosure;
aPS->mReporter = aReporter;
}
// Release any memory in use by the PrefParseState instance.
static void
PREF_FinalizeParseState(PrefParseState* aPS)
{
if (aPS->mLb) {
free(aPS->mLb);
}
}
// Parse a buffer containing some portion of a preference file. This function
// may be called repeatedly as new data is made available. The PrefReader
// callback function passed PREF_InitParseState will be called as preference
// callback function passed to Parser's constructor will be called as preference
// name value pairs are extracted from the data. Returns false if buffer
// contains malformed content.
//
@ -1246,8 +1242,8 @@ PREF_FinalizeParseState(PrefParseState* aPS)
// comment-line = <C++ style comment line>
// bcomment-line = <bourne-shell style comment line>
//
static bool
PREF_ParseBuf(PrefParseState* aPS, const char* aBuf, int aBufLen)
bool
Parser::Parse(const char* aBuf, int aBufLen)
{
const char* end;
char c;
@ -1257,7 +1253,7 @@ PREF_ParseBuf(PrefParseState* aPS, const char* aBuf, int aBufLen)
// The line number is currently only used for the error/warning reporting.
int lineNum = 0;
state = aPS->mState;
state = mState;
for (end = aBuf + aBufLen; aBuf != end; ++aBuf) {
c = *aBuf;
if (c == '\r' || c == '\n' || c == 0x1A) {
@ -1267,12 +1263,12 @@ PREF_ParseBuf(PrefParseState* aPS, const char* aBuf, int aBufLen)
switch (state) {
// initial state
case PREF_PARSE_INIT:
if (aPS->mLbCur != aPS->mLb) { // reset state
aPS->mLbCur = aPS->mLb;
aPS->mVb = nullptr;
aPS->mVtype = Nothing();
aPS->mIsDefault = false;
aPS->mIsSticky = false;
if (mLbCur != mLb) { // reset state
mLbCur = mLb;
mVb = nullptr;
mVtype = Nothing();
mIsDefault = false;
mIsSticky = false;
}
switch (c) {
case '/': // begin comment block or line?
@ -1285,14 +1281,14 @@ PREF_ParseBuf(PrefParseState* aPS, const char* aBuf, int aBufLen)
case 's': // indicating sticky_pref
case 'p': // indicating pref
if (c == 'u') {
aPS->mStrMatch = kUserPref;
mStrMatch = kUserPref;
} else if (c == 's') {
aPS->mStrMatch = kStickyPref;
mStrMatch = kStickyPref;
} else {
aPS->mStrMatch = kPref;
mStrMatch = kPref;
}
aPS->mStrIndex = 1;
aPS->mNextState = PREF_PARSE_UNTIL_OPEN_PAREN;
mStrIndex = 1;
mNextState = PREF_PARSE_UNTIL_OPEN_PAREN;
state = PREF_PARSE_MATCH_STRING;
break;
// else skip char
@ -1301,15 +1297,15 @@ PREF_ParseBuf(PrefParseState* aPS, const char* aBuf, int aBufLen)
// string matching
case PREF_PARSE_MATCH_STRING:
if (c == aPS->mStrMatch[aPS->mStrIndex++]) {
if (c == mStrMatch[mStrIndex++]) {
// If we've matched all characters, then move to next state.
if (aPS->mStrMatch[aPS->mStrIndex] == '\0') {
state = aPS->mNextState;
aPS->mNextState = PREF_PARSE_INIT; // reset next state
if (mStrMatch[mStrIndex] == '\0') {
state = mNextState;
mNextState = PREF_PARSE_INIT; // reset next state
}
// else wait for next char
} else {
pref_ReportParseProblem(*aPS, "non-matching string", lineNum, true);
ReportProblem("non-matching string", lineNum, true);
NS_WARNING("malformed pref file");
return false;
}
@ -1318,35 +1314,33 @@ PREF_ParseBuf(PrefParseState* aPS, const char* aBuf, int aBufLen)
// quoted string parsing
case PREF_PARSE_QUOTED_STRING:
// we assume that the initial quote has already been consumed
if (aPS->mLbCur == aPS->mLbEnd && !pref_GrowBuf(aPS)) {
if (mLbCur == mLbEnd && !GrowBuf()) {
return false; // out of memory
}
if (c == '\\') {
state = PREF_PARSE_ESC_SEQUENCE;
} else if (c == aPS->mQuoteChar) {
*aPS->mLbCur++ = '\0';
state = aPS->mNextState;
aPS->mNextState = PREF_PARSE_INIT; // reset next state
} else if (c == mQuoteChar) {
*mLbCur++ = '\0';
state = mNextState;
mNextState = PREF_PARSE_INIT; // reset next state
} else {
*aPS->mLbCur++ = c;
*mLbCur++ = c;
}
break;
// name parsing
case PREF_PARSE_UNTIL_NAME:
if (c == '\"' || c == '\'') {
aPS->mIsDefault =
(aPS->mStrMatch == kPref || aPS->mStrMatch == kStickyPref);
aPS->mIsSticky = (aPS->mStrMatch == kStickyPref);
aPS->mQuoteChar = c;
aPS->mNextState = PREF_PARSE_UNTIL_COMMA; // return here when done
mIsDefault = (mStrMatch == kPref || mStrMatch == kStickyPref);
mIsSticky = (mStrMatch == kStickyPref);
mQuoteChar = c;
mNextState = PREF_PARSE_UNTIL_COMMA; // return here when done
state = PREF_PARSE_QUOTED_STRING;
} else if (c == '/') { // allow embedded comment
aPS->mNextState = state; // return here when done with comment
} else if (c == '/') { // allow embedded comment
mNextState = state; // return here when done with comment
state = PREF_PARSE_COMMENT_MAYBE_START;
} else if (!isspace(c)) {
pref_ReportParseProblem(
*aPS, "need space, comment or quote", lineNum, true);
ReportProblem("need space, comment or quote", lineNum, true);
NS_WARNING("malformed pref file");
return false;
}
@ -1355,14 +1349,13 @@ PREF_ParseBuf(PrefParseState* aPS, const char* aBuf, int aBufLen)
// parse until we find a comma separating name and value
case PREF_PARSE_UNTIL_COMMA:
if (c == ',') {
aPS->mVb = aPS->mLbCur;
mVb = mLbCur;
state = PREF_PARSE_UNTIL_VALUE;
} else if (c == '/') { // allow embedded comment
aPS->mNextState = state; // return here when done with comment
} else if (c == '/') { // allow embedded comment
mNextState = state; // return here when done with comment
state = PREF_PARSE_COMMENT_MAYBE_START;
} else if (!isspace(c)) {
pref_ReportParseProblem(
*aPS, "need space, comment or comma", lineNum, true);
ReportProblem("need space, comment or comma", lineNum, true);
NS_WARNING("malformed pref file");
return false;
}
@ -1373,31 +1366,30 @@ PREF_ParseBuf(PrefParseState* aPS, const char* aBuf, int aBufLen)
// The pref value type is unknown. So, we scan for the first character
// of the value, and determine the type from that.
if (c == '\"' || c == '\'') {
aPS->mVtype = Some(PrefType::String);
aPS->mQuoteChar = c;
aPS->mNextState = PREF_PARSE_UNTIL_CLOSE_PAREN;
mVtype = Some(PrefType::String);
mQuoteChar = c;
mNextState = PREF_PARSE_UNTIL_CLOSE_PAREN;
state = PREF_PARSE_QUOTED_STRING;
} else if (c == 't' || c == 'f') {
aPS->mVb = (char*)(c == 't' ? kTrue : kFalse);
aPS->mVtype = Some(PrefType::Bool);
aPS->mStrMatch = aPS->mVb;
aPS->mStrIndex = 1;
aPS->mNextState = PREF_PARSE_UNTIL_CLOSE_PAREN;
mVb = (char*)(c == 't' ? kTrue : kFalse);
mVtype = Some(PrefType::Bool);
mStrMatch = mVb;
mStrIndex = 1;
mNextState = PREF_PARSE_UNTIL_CLOSE_PAREN;
state = PREF_PARSE_MATCH_STRING;
} else if (isdigit(c) || (c == '-') || (c == '+')) {
aPS->mVtype = Some(PrefType::Int);
mVtype = Some(PrefType::Int);
// write c to line buffer...
if (aPS->mLbCur == aPS->mLbEnd && !pref_GrowBuf(aPS)) {
if (mLbCur == mLbEnd && !GrowBuf()) {
return false; // out of memory
}
*aPS->mLbCur++ = c;
*mLbCur++ = c;
state = PREF_PARSE_INT_VALUE;
} else if (c == '/') { // allow embedded comment
aPS->mNextState = state; // return here when done with comment
} else if (c == '/') { // allow embedded comment
mNextState = state; // return here when done with comment
state = PREF_PARSE_COMMENT_MAYBE_START;
} else if (!isspace(c)) {
pref_ReportParseProblem(
*aPS, "need value, comment or space", lineNum, true);
ReportProblem("need value, comment or space", lineNum, true);
NS_WARNING("malformed pref file");
return false;
}
@ -1405,23 +1397,22 @@ PREF_ParseBuf(PrefParseState* aPS, const char* aBuf, int aBufLen)
case PREF_PARSE_INT_VALUE:
// grow line buffer if necessary...
if (aPS->mLbCur == aPS->mLbEnd && !pref_GrowBuf(aPS)) {
if (mLbCur == mLbEnd && !GrowBuf()) {
return false; // out of memory
}
if (isdigit(c)) {
*aPS->mLbCur++ = c;
*mLbCur++ = c;
} else {
*aPS->mLbCur++ = '\0'; // stomp null terminator; we are done.
*mLbCur++ = '\0'; // stomp null terminator; we are done.
if (c == ')') {
state = PREF_PARSE_UNTIL_SEMICOLON;
} else if (c == '/') { // allow embedded comment
aPS->mNextState = PREF_PARSE_UNTIL_CLOSE_PAREN;
mNextState = PREF_PARSE_UNTIL_CLOSE_PAREN;
state = PREF_PARSE_COMMENT_MAYBE_START;
} else if (isspace(c)) {
state = PREF_PARSE_UNTIL_CLOSE_PAREN;
} else {
pref_ReportParseProblem(
*aPS, "while parsing integer", lineNum, true);
ReportProblem("while parsing integer", lineNum, true);
NS_WARNING("malformed pref file");
return false;
}
@ -1439,8 +1430,7 @@ PREF_ParseBuf(PrefParseState* aPS, const char* aBuf, int aBufLen)
break;
default:
// pref file is malformed
pref_ReportParseProblem(
*aPS, "while parsing comment", lineNum, true);
ReportProblem("while parsing comment", lineNum, true);
NS_WARNING("malformed pref file");
return false;
}
@ -1455,8 +1445,8 @@ PREF_ParseBuf(PrefParseState* aPS, const char* aBuf, int aBufLen)
case PREF_PARSE_COMMENT_BLOCK_MAYBE_END:
switch (c) {
case '/':
state = aPS->mNextState;
aPS->mNextState = PREF_PARSE_INIT;
state = mNextState;
mNextState = PREF_PARSE_INIT;
break;
case '*': // stay in this state
break;
@ -1484,26 +1474,25 @@ PREF_ParseBuf(PrefParseState* aPS, const char* aBuf, int aBufLen)
break;
case 'x': // hex escape -- always interpreted as Latin-1
case 'u': // UTF16 escape
aPS->mEscTmp[0] = c;
aPS->mEscLen = 1;
aPS->mUtf16[0] = aPS->mUtf16[1] = 0;
aPS->mStrIndex =
(c == 'x') ? HEX_ESC_NUM_DIGITS : UTF16_ESC_NUM_DIGITS;
mEscTmp[0] = c;
mEscLen = 1;
mUtf16[0] = mUtf16[1] = 0;
mStrIndex = (c == 'x') ? HEX_ESC_NUM_DIGITS : UTF16_ESC_NUM_DIGITS;
state = PREF_PARSE_HEX_ESCAPE;
continue;
default:
pref_ReportParseProblem(
*aPS, "preserving unexpected JS escape sequence", lineNum, false);
ReportProblem(
"preserving unexpected JS escape sequence", lineNum, false);
NS_WARNING("preserving unexpected JS escape sequence");
// Invalid escape sequence so we do have to write more than one
// character. Grow line buffer if necessary...
if ((aPS->mLbCur + 1) == aPS->mLbEnd && !pref_GrowBuf(aPS)) {
if ((mLbCur + 1) == mLbEnd && !GrowBuf()) {
return false; // out of memory
}
*aPS->mLbCur++ = '\\'; // preserve the escape sequence
*mLbCur++ = '\\'; // preserve the escape sequence
break;
}
*aPS->mLbCur++ = c;
*mLbCur++ = c;
state = PREF_PARSE_QUOTED_STRING;
break;
@ -1517,18 +1506,15 @@ PREF_ParseBuf(PrefParseState* aPS, const char* aBuf, int aBufLen)
udigit = (c - 'a') + 10;
} else {
// bad escape sequence found, write out broken escape as-is
pref_ReportParseProblem(*aPS,
"preserving invalid or incomplete hex escape",
lineNum,
false);
ReportProblem(
"preserving invalid or incomplete hex escape", lineNum, false);
NS_WARNING("preserving invalid or incomplete hex escape");
*aPS->mLbCur++ = '\\'; // original escape slash
if ((aPS->mLbCur + aPS->mEscLen) >= aPS->mLbEnd &&
!pref_GrowBuf(aPS)) {
*mLbCur++ = '\\'; // original escape slash
if ((mLbCur + mEscLen) >= mLbEnd && !GrowBuf()) {
return false;
}
for (int i = 0; i < aPS->mEscLen; ++i) {
*aPS->mLbCur++ = aPS->mEscTmp[i];
for (int i = 0; i < mEscLen; ++i) {
*mLbCur++ = mEscTmp[i];
}
// Push the non-hex character back for re-parsing. (++aBuf at the top
@ -1539,58 +1525,58 @@ PREF_ParseBuf(PrefParseState* aPS, const char* aBuf, int aBufLen)
}
// have a digit
aPS->mEscTmp[aPS->mEscLen++] = c; // preserve it
aPS->mUtf16[1] <<= BITS_PER_HEX_DIGIT;
aPS->mUtf16[1] |= udigit;
aPS->mStrIndex--;
if (aPS->mStrIndex == 0) {
mEscTmp[mEscLen++] = c; // preserve it
mUtf16[1] <<= BITS_PER_HEX_DIGIT;
mUtf16[1] |= udigit;
mStrIndex--;
if (mStrIndex == 0) {
// we have the full escape, convert to UTF8
int utf16len = 0;
if (aPS->mUtf16[0]) {
if (mUtf16[0]) {
// already have a high surrogate, this is a two char seq
utf16len = 2;
} else if (0xD800 == (0xFC00 & aPS->mUtf16[1])) {
} else if (0xD800 == (0xFC00 & mUtf16[1])) {
// a high surrogate, can't convert until we have the low
aPS->mUtf16[0] = aPS->mUtf16[1];
aPS->mUtf16[1] = 0;
mUtf16[0] = mUtf16[1];
mUtf16[1] = 0;
state = PREF_PARSE_UTF16_LOW_SURROGATE;
break;
} else {
// a single mUtf16 character
aPS->mUtf16[0] = aPS->mUtf16[1];
mUtf16[0] = mUtf16[1];
utf16len = 1;
}
// The actual conversion.
// Make sure there's room, 6 bytes is max utf8 len (in theory; 4
// bytes covers the actual mUtf16 range).
if (aPS->mLbCur + 6 >= aPS->mLbEnd && !pref_GrowBuf(aPS)) {
if (mLbCur + 6 >= mLbEnd && !GrowBuf()) {
return false;
}
ConvertUTF16toUTF8 converter(aPS->mLbCur);
converter.write(aPS->mUtf16, utf16len);
aPS->mLbCur += converter.Size();
ConvertUTF16toUTF8 converter(mLbCur);
converter.write(mUtf16, utf16len);
mLbCur += converter.Size();
state = PREF_PARSE_QUOTED_STRING;
}
break;
// looking for beginning of mUtf16 low surrogate
case PREF_PARSE_UTF16_LOW_SURROGATE:
if (aPS->mStrIndex == 0 && c == '\\') {
++aPS->mStrIndex;
} else if (aPS->mStrIndex == 1 && c == 'u') {
if (mStrIndex == 0 && c == '\\') {
++mStrIndex;
} else if (mStrIndex == 1 && c == 'u') {
// escape sequence is correct, now parse hex
aPS->mStrIndex = UTF16_ESC_NUM_DIGITS;
aPS->mEscTmp[0] = 'u';
aPS->mEscLen = 1;
mStrIndex = UTF16_ESC_NUM_DIGITS;
mEscTmp[0] = 'u';
mEscLen = 1;
state = PREF_PARSE_HEX_ESCAPE;
} else {
// Didn't find expected low surrogate. Ignore high surrogate (it
// would just get converted to nothing anyway) and start over with
// this character.
--aBuf;
if (aPS->mStrIndex == 1) {
if (mStrIndex == 1) {
state = PREF_PARSE_ESC_SEQUENCE;
} else {
state = PREF_PARSE_QUOTED_STRING;
@ -1605,11 +1591,11 @@ PREF_ParseBuf(PrefParseState* aPS, const char* aBuf, int aBufLen)
if (c == '(') {
state = PREF_PARSE_UNTIL_NAME;
} else if (c == '/') {
aPS->mNextState = state; // return here when done with comment
mNextState = state; // return here when done with comment
state = PREF_PARSE_COMMENT_MAYBE_START;
} else if (!isspace(c)) {
pref_ReportParseProblem(
*aPS, "need space, comment or open parentheses", lineNum, true);
ReportProblem(
"need space, comment or open parentheses", lineNum, true);
NS_WARNING("malformed pref file");
return false;
}
@ -1620,11 +1606,11 @@ PREF_ParseBuf(PrefParseState* aPS, const char* aBuf, int aBufLen)
if (c == ')') {
state = PREF_PARSE_UNTIL_SEMICOLON;
} else if (c == '/') {
aPS->mNextState = state; // return here when done with comment
mNextState = state; // return here when done with comment
state = PREF_PARSE_COMMENT_MAYBE_START;
} else if (!isspace(c)) {
pref_ReportParseProblem(
*aPS, "need space, comment or closing parentheses", lineNum, true);
ReportProblem(
"need space, comment or closing parentheses", lineNum, true);
NS_WARNING("malformed pref file");
return false;
}
@ -1637,23 +1623,22 @@ PREF_ParseBuf(PrefParseState* aPS, const char* aBuf, int aBufLen)
PrefValue value;
switch (*aPS->mVtype) {
switch (*mVtype) {
case PrefType::String:
value.mStringVal = aPS->mVb;
value.mStringVal = mVb;
break;
case PrefType::Int:
if ((aPS->mVb[0] == '-' || aPS->mVb[0] == '+') &&
aPS->mVb[1] == '\0') {
pref_ReportParseProblem(*aPS, "invalid integer value", 0, true);
if ((mVb[0] == '-' || mVb[0] == '+') && mVb[1] == '\0') {
ReportProblem("invalid integer value", 0, true);
NS_WARNING("malformed integer value");
return false;
}
value.mIntVal = atoi(aPS->mVb);
value.mIntVal = atoi(mVb);
break;
case PrefType::Bool:
value.mBoolVal = (aPS->mVb == kTrue);
value.mBoolVal = (mVb == kTrue);
break;
default:
@ -1661,20 +1646,14 @@ PREF_ParseBuf(PrefParseState* aPS, const char* aBuf, int aBufLen)
}
// We've extracted a complete name/value pair.
aPS->mReader(aPS->mClosure,
aPS->mLb,
value,
*aPS->mVtype,
aPS->mIsDefault,
aPS->mIsSticky);
mReader(mClosure, mLb, value, *mVtype, mIsDefault, mIsSticky);
state = PREF_PARSE_INIT;
} else if (c == '/') {
aPS->mNextState = state; // return here when done with comment
mNextState = state; // return here when done with comment
state = PREF_PARSE_COMMENT_MAYBE_START;
} else if (!isspace(c)) {
pref_ReportParseProblem(
*aPS, "need space, comment or semicolon", lineNum, true);
ReportProblem("need space, comment or semicolon", lineNum, true);
NS_WARNING("malformed pref file");
return false;
}
@ -1685,13 +1664,13 @@ PREF_ParseBuf(PrefParseState* aPS, const char* aBuf, int aBufLen)
// Need to handle mac, unix, or dos line endings. PREF_PARSE_INIT will
// eat the next \n in case we have \r\n.
if (c == '\r' || c == '\n' || c == 0x1A) {
state = aPS->mNextState;
aPS->mNextState = PREF_PARSE_INIT; // reset next state
state = mNextState;
mNextState = PREF_PARSE_INIT; // reset next state
}
break;
}
}
aPS->mState = state;
mState = state;
return true;
}
@ -4119,13 +4098,11 @@ Preferences::WritePrefFile(nsIFile* aFile, SaveMethod aSaveMethod)
static nsresult
openPrefFile(nsIFile* aFile)
{
PrefParseState ps;
PREF_InitParseState(&ps, PREF_ReaderCallback, ReportToConsole, nullptr);
auto cleanup = MakeScopeExit([&]() { PREF_FinalizeParseState(&ps); });
nsCString data;
MOZ_TRY_VAR(data, URLPreloader::ReadFile(aFile));
if (!PREF_ParseBuf(&ps, data.get(), data.Length())) {
Parser parser(PREF_ReaderCallback, ReportToConsole, nullptr);
if (!parser.Parse(data.get(), data.Length())) {
return NS_ERROR_FILE_CORRUPTED;
}
@ -4296,10 +4273,8 @@ pref_ReadPrefFromJar(nsZipArchive* aJarReader, const char* aName)
MOZ_TRY_VAR(manifest,
URLPreloader::ReadZip(aJarReader, nsDependentCString(aName)));
PrefParseState ps;
PREF_InitParseState(&ps, PREF_ReaderCallback, ReportToConsole, nullptr);
PREF_ParseBuf(&ps, manifest.get(), manifest.Length());
PREF_FinalizeParseState(&ps);
Parser parser(PREF_ReaderCallback, ReportToConsole, nullptr);
parser.Parse(manifest.get(), manifest.Length());
return NS_OK;
}