翻译自Java原版
正在开发测试中,先贴上Parser类代码。
class JsonParser {
private:
char COLON = ':';
public:
JsonParser() {}
void* parse() {
CharsRange trimmedJson = CharsRange::newRange(0, jsonStr.size()).trim();
return processValue(trimmedJson);
}
map<string, void*> processPlainObject(CharsRange range) {
list<Property> properties = processProperties(CharsRange::newRange(range.start + 1, range.end - 1));
map<string, void*> objectMap;
list<Property>::iterator prop;
for(prop = properties.begin() ; prop != properties.end() ; prop++) {
objectMap.insert(pair<string, void *>(prop->name, prop->value));
}
return objectMap;
}
list<Property> processProperties(CharsRange range) {
list<Property> properties;
int nameStartMark = range.start;
for (int curPos = range.start; curPos < range.end; curPos++) {
char ch = jsonStr.at(curPos);
if (ch == COLON) {
CharsRange nameToken = CharsRange::newRange(nameStartMark, curPos).trim();
int readCursor = 0;
void* value = genValue(range, ++curPos, &readCursor);
curPos = readCursor + 1;
nameStartMark = curPos;
string name = genName(nameToken);
properties.push_back(Property::of(name, value));
}
}
return properties;
}
void* genValue(CharsRange range, int curPos, int *readCursor) {
CharsRange valueSegment = findNextValue(CharsRange::newRange(curPos, range.end), readCursor);
return processValue(valueSegment);
}
string genName(CharsRange nameToken) {
bool hasQuote = jsonStr.at(nameToken.start) == '"' || jsonStr.at(nameToken.end) == '"';
int start = hasQuote ? nameToken.start + 1 : nameToken.start;
int end = hasQuote ? nameToken.end - 1 : nameToken.end;
return CharsRange::newRange(start, end).toString();
}
list<void*> processArray(CharsRange range) {
return processElements(CharsRange::newRange(range.start + 1, range.end - 1));
}
list<void*> processElements(CharsRange range) {
list<void*> objList;
int elementStartMark = range.start;
for (int i = range.start; i < range.end; i++) {
int readCursor = 0;
void * elementValue = genValue(range, elementStartMark, &readCursor);
objList.push_back(elementValue);
i = readCursor;
elementStartMark = i + 1;
}
return objList;
}
/**
* @param chars
* @return value segment trimmed.
*/
CharsRange findNextValue(CharsRange chars, int *readCursor) {
CharsRange trimChars = chars.trimLeft();
if (trimChars.relativeChar(0) == '{') {
return completeSymbolPair(trimChars, readCursor, "{}");
} else if (trimChars.relativeChar(0) == '[') {
return completeSymbolPair(trimChars, readCursor, "[]");
} else {
int i;
for (i = trimChars.start + 1; i < trimChars.end; i++) {
char ch = jsonStr.at(i);
if (ch == ',') {
break;
}
}
readCursor = &i;
return CharsRange::newRange(trimChars.start, i).trim();
}
}
CharsRange completeSymbolPair(CharsRange trimChars, int *readCursor, string symbolPair) {
int leftSymbol = symbolPair.at(0);
int rightSymbol = symbolPair.at(1);
int symbolsScore = 1;
int i;
CharsRange valueSegment(0,0);
for (i = trimChars.start + 1; i < trimChars.end; i++) {
char ch = jsonStr.at(i);
if (ch == leftSymbol) {
symbolsScore++;
} else if (ch == rightSymbol) {
symbolsScore--;
}
if (symbolsScore == 0) {
valueSegment = CharsRange::newRange(trimChars.start, i + 1);
break;
}
}
for (; i < trimChars.end; i++) {
char chx = jsonStr.at(i);
if (chx == ',') {
break;
}
}
readCursor = &i;
return valueSegment;
}
void* processValue(CharsRange valueSegment) {
void* value;
if (valueSegment.relativeChar(0) == '"') {
string rng = CharsRange::newRange(valueSegment.start + 1, valueSegment.end - 1).toString().data();
value = &rng;
} else if (valueSegment.relativeChar(0) == '{') {
map<string, void*> obj = processPlainObject(valueSegment);
value = &obj;
} else if (valueSegment.relativeChar(0) == '[') {
list<void*> objLst = processArray(valueSegment);
value = &objLst;
} else if (valueSegment.equalsString("true")) {
bool ret = true;
value = &ret;
} else if (valueSegment.equalsString("false")) {
bool ret = false;
value = &ret;
} else if (valueSegment.equalsString("null")) {
value = NULL;
} else {
int ret = atoi(valueSegment.toString().data());
value = &ret;
}
return value;
}
};