#include "qjson.h" inline QChar readOne(QTextStream &in) { QChar ch; in >> ch; return ch; } JValue JParser::readValue() { if(ch=='{') { JObj obj; while(true) { do skipSpace(); //ch有三种可能 while(ch==','); if(ch=='}') return obj; QString key; if(ch == '"') key = readStr(); else if(ch!='n' || in.read(3)!="ull") throw QString("Unexpected char ")+ch+" (code "+ch+"): was expecting double-quote to start field name or null"; skipSpace(); if(ch != ':') throw QString("Unexpected char ")+ch+" (code "+ch+"): was expecting a colon to separate field name and value"; skipSpace(); obj.insert(key, readValue()); skipSpace(); //ch有两种可能 if(ch=='}') return obj; if(ch!=',') throw QString("Unexpected char ")+ch+"' (code "+ch+"): was expecting } to end Object or comma to separate Object entries"; } } if(ch=='[') { JArray list; while(true) { do skipSpace(); //ch有三种可能 while(ch==','); if(ch==']') return list; list->push_back(readValue()); skipSpace(); //ch有两种可能 if(ch==']') return list; if(ch!=',') throw QString("Unexpected char ")+ch+" (code "+ch+"): was expecting ] to end Array or comma to separate Array entries"; } } if(ch=='"') return readStr(); if((ch>='0' && ch<='9') || ch=='-') { QString buf; buf += ch; bool isInt = true; while(0 != (ch = readOne(in))) { if((ch>'*' && ch<':' && ch!=',' && ch!='/') || ch=='e' || ch=='E') { buf.append(ch); if(isInt && ch=='.') isInt = false; } else { bk = ch; break; } } bool ok; if(isInt) { auto num = buf.toLongLong(&ok); if(! ok) throw "Illegal number: "+buf; return num; } else { auto num = buf.toDouble(&ok); if(! ok) throw "Illegal number: "+buf; return num; } } if(ch=='n') { if(in.read(3)=="ull") return JValue(); else throw "Unexpected char n: expected null"; } if(ch=='t') { if(in.read(3)=="rue") return true; else throw "Unexpected char t: expected true"; } if(ch=='f') { if(in.read(4)=="alse") return false; else throw "Unexpected char f: expected false"; } throw QString("Unexpected char ")+ch+" (code "+ch+"): expected {}, [], \"string\", number, null, true or false"; } QString JParser::readStr() { QString buf; while((ch = readOne(in)) != '"') { if(ch==0) throw "Unexpected end-of-input: was expecting closing quote for string"; if(ch=='\\') { in>>ch; if(ch==0) throw "Unexpected end-of-input in char escape sequence"; if(ch=='"' || ch=='\\' || ch=='/') buf.append(ch); else if(ch=='n') buf.append('\n'); else if(ch=='r') buf.append('\r'); else if(ch=='t') buf.append('\t'); else if(ch=='f') buf.append('\f'); else if(ch=='b') buf.append('\b'); else if(ch=='u') { auto hex = in.read(4); if(hex.size()<4) throw "Unexpected end-of-input in char escape sequence"; bool ok; buf.append(hex.toUShort(&ok, 16)); if(! ok) throw "Illegal hex-digits in char escape sequence: \\u"+hex; } else throw QString("Unrecognized char-escape ")+ch+" (code "+ch+")"; } else buf.append(ch); } return buf; } void JParser::skipSpace() { if(bk.unicode()) { bk = QChar::Null; if(! ch.isSpace()) return; } in.skipWhiteSpace(); in >> ch; if(ch==0) throw "Unexpected end-of-input"; } void JOut::write(const JValue &value) { if(value.type==JValue::Null) out << "null"; else if(value.type==JValue::Str) writeStr(value.toStr()); else if(value.type==JValue::Obj) writeMap(value.toObj()); else if(value.type==JValue::Array) writeList(value.toArray()); else out << value.toStr(); out.flush(); } void JOut::writeStr(const QString &str) { out << '"'; QChar ch; for(int i=0; i