json: Optimize writing a bit.
This improves the responsiveness of certain APIs.
This commit is contained in:
parent
ccea863f00
commit
fc8ad3b47b
7 changed files with 121 additions and 91 deletions
|
@ -91,7 +91,7 @@ void WebSocketCPUStatus(DebuggerRequest &req) {
|
||||||
json.writeBool("stepping", PSP_IsInited() && Core_IsStepping() && coreState != CORE_POWERDOWN);
|
json.writeBool("stepping", PSP_IsInited() && Core_IsStepping() && coreState != CORE_POWERDOWN);
|
||||||
json.writeBool("paused", GetUIState() != UISTATE_INGAME);
|
json.writeBool("paused", GetUIState() != UISTATE_INGAME);
|
||||||
// Avoid NULL deference.
|
// Avoid NULL deference.
|
||||||
json.writeFloat("pc", PSP_IsInited() ? currentMIPS->pc : 0);
|
json.writeUint("pc", PSP_IsInited() ? currentMIPS->pc : 0);
|
||||||
// A double ought to be good enough for a 156 day debug session.
|
// A double ought to be good enough for a 156 day debug session.
|
||||||
json.writeFloat("ticks", PSP_IsInited() ? CoreTiming::GetTicks() : 0);
|
json.writeFloat("ticks", PSP_IsInited() ? CoreTiming::GetTicks() : 0);
|
||||||
}
|
}
|
||||||
|
@ -131,11 +131,11 @@ void WebSocketCPUGetAllRegs(DebuggerRequest &req) {
|
||||||
json.pushArray("uintValues");
|
json.pushArray("uintValues");
|
||||||
// Writing as floating point to avoid negatives. Actually double, so safe.
|
// Writing as floating point to avoid negatives. Actually double, so safe.
|
||||||
for (int r = 0; r < total; ++r)
|
for (int r = 0; r < total; ++r)
|
||||||
json.writeFloat(currentDebugMIPS->GetRegValue(c, r));
|
json.writeUint(currentDebugMIPS->GetRegValue(c, r));
|
||||||
if (c == 0) {
|
if (c == 0) {
|
||||||
json.writeFloat(currentDebugMIPS->GetPC());
|
json.writeUint(currentDebugMIPS->GetPC());
|
||||||
json.writeFloat(currentDebugMIPS->GetHi());
|
json.writeUint(currentDebugMIPS->GetHi());
|
||||||
json.writeFloat(currentDebugMIPS->GetLo());
|
json.writeUint(currentDebugMIPS->GetLo());
|
||||||
}
|
}
|
||||||
json.pop();
|
json.pop();
|
||||||
|
|
||||||
|
@ -267,7 +267,7 @@ void WebSocketCPUGetReg(DebuggerRequest &req) {
|
||||||
JsonWriter &json = req.Respond();
|
JsonWriter &json = req.Respond();
|
||||||
json.writeInt("category", cat);
|
json.writeInt("category", cat);
|
||||||
json.writeInt("register", reg);
|
json.writeInt("register", reg);
|
||||||
json.writeFloat("uintValue", val);
|
json.writeUint("uintValue", val);
|
||||||
json.writeString("floatValue", RegValueAsFloat(val));
|
json.writeString("floatValue", RegValueAsFloat(val));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -335,7 +335,7 @@ void WebSocketCPUSetReg(DebuggerRequest &req) {
|
||||||
// Repeat it back just to avoid confusion on how it parsed.
|
// Repeat it back just to avoid confusion on how it parsed.
|
||||||
json.writeInt("category", cat);
|
json.writeInt("category", cat);
|
||||||
json.writeInt("register", reg);
|
json.writeInt("register", reg);
|
||||||
json.writeFloat("uintValue", val);
|
json.writeUint("uintValue", val);
|
||||||
json.writeString("floatValue", RegValueAsFloat(val));
|
json.writeString("floatValue", RegValueAsFloat(val));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -368,6 +368,6 @@ void WebSocketCPUEvaluate(DebuggerRequest &req) {
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonWriter &json = req.Respond();
|
JsonWriter &json = req.Respond();
|
||||||
json.writeFloat("uintValue", val);
|
json.writeUint("uintValue", val);
|
||||||
json.writeString("floatValue", RegValueAsFloat(val));
|
json.writeString("floatValue", RegValueAsFloat(val));
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,17 +63,17 @@ void WebSocketDisasmState::WriteDisasmLine(JsonWriter &json, const DisassemblyLi
|
||||||
else if (l.type == DISTYPE_OTHER)
|
else if (l.type == DISTYPE_OTHER)
|
||||||
json.writeString("type", "other");
|
json.writeString("type", "other");
|
||||||
|
|
||||||
json.writeFloat("address", addr);
|
json.writeUint("address", addr);
|
||||||
json.writeInt("addressSize", l.totalSize);
|
json.writeInt("addressSize", l.totalSize);
|
||||||
json.writeFloat("encoding", Memory::IsValidAddress(addr) ? Memory::Read_Instruction(addr).encoding : 0);
|
json.writeUint("encoding", Memory::IsValidAddress(addr) ? Memory::Read_Instruction(addr).encoding : 0);
|
||||||
if (l.totalSize >= 8 && Memory::IsValidRange(addr, l.totalSize)) {
|
if (l.totalSize >= 8 && Memory::IsValidRange(addr, l.totalSize)) {
|
||||||
json.pushArray("macroEncoding");
|
json.pushArray("macroEncoding");
|
||||||
for (u32 off = 0; off < l.totalSize; off += 4) {
|
for (u32 off = 0; off < l.totalSize; off += 4) {
|
||||||
json.writeFloat(Memory::Read_Instruction(addr + off).encoding);
|
json.writeUint(Memory::Read_Instruction(addr + off).encoding);
|
||||||
}
|
}
|
||||||
json.pop();
|
json.pop();
|
||||||
} else {
|
} else {
|
||||||
json.writeRaw("macroEncoding", "null");
|
json.writeNull("macroEncoding");
|
||||||
}
|
}
|
||||||
int c = currentDebugMIPS->getColor(addr) & 0x00FFFFFF;
|
int c = currentDebugMIPS->getColor(addr) & 0x00FFFFFF;
|
||||||
json.writeString("backgroundColor", StringFromFormat("#%02x%02x%02x", c & 0xFF, (c >> 8) & 0xFF, c >> 16));
|
json.writeString("backgroundColor", StringFromFormat("#%02x%02x%02x", c & 0xFF, (c >> 8) & 0xFF, c >> 16));
|
||||||
|
@ -82,7 +82,7 @@ void WebSocketDisasmState::WriteDisasmLine(JsonWriter &json, const DisassemblyLi
|
||||||
|
|
||||||
const std::string addressSymbol = g_symbolMap->GetLabelString(addr);
|
const std::string addressSymbol = g_symbolMap->GetLabelString(addr);
|
||||||
if (addressSymbol.empty())
|
if (addressSymbol.empty())
|
||||||
json.writeRaw("symbol", "null");
|
json.writeNull("symbol");
|
||||||
else
|
else
|
||||||
json.writeString("symbol", addressSymbol);
|
json.writeString("symbol", addressSymbol);
|
||||||
|
|
||||||
|
@ -95,10 +95,10 @@ void WebSocketDisasmState::WriteDisasmLine(JsonWriter &json, const DisassemblyLi
|
||||||
if (cond)
|
if (cond)
|
||||||
json.writeString("expression", cond->expressionString);
|
json.writeString("expression", cond->expressionString);
|
||||||
else
|
else
|
||||||
json.writeRaw("expression", "null");
|
json.writeNull("expression");
|
||||||
json.pop();
|
json.pop();
|
||||||
} else {
|
} else {
|
||||||
json.writeRaw("breakpoint", "null");
|
json.writeNull("breakpoint");
|
||||||
}
|
}
|
||||||
|
|
||||||
json.writeBool("isCurrentPC", currentDebugMIPS->GetPC() == addr);
|
json.writeBool("isCurrentPC", currentDebugMIPS->GetPC() == addr);
|
||||||
|
@ -107,70 +107,70 @@ void WebSocketDisasmState::WriteDisasmLine(JsonWriter &json, const DisassemblyLi
|
||||||
std::string targetSymbol;
|
std::string targetSymbol;
|
||||||
if (!l.info.isBranchToRegister) {
|
if (!l.info.isBranchToRegister) {
|
||||||
targetSymbol = g_symbolMap->GetLabelString(l.info.branchTarget);
|
targetSymbol = g_symbolMap->GetLabelString(l.info.branchTarget);
|
||||||
json.writeFloat("targetAddress", l.info.branchTarget);
|
json.writeUint("targetAddress", l.info.branchTarget);
|
||||||
json.writeRaw("register", "null");
|
json.writeNull("register");
|
||||||
} else {
|
} else {
|
||||||
json.writeRaw("targetAddress", "null");
|
json.writeNull("targetAddress");
|
||||||
json.writeInt("register", l.info.branchRegisterNum);
|
json.writeInt("register", l.info.branchRegisterNum);
|
||||||
}
|
}
|
||||||
json.writeBool("isLinked", l.info.isLinkedBranch);
|
json.writeBool("isLinked", l.info.isLinkedBranch);
|
||||||
json.writeBool("isLikely", l.info.isLikelyBranch);
|
json.writeBool("isLikely", l.info.isLikelyBranch);
|
||||||
if (targetSymbol.empty())
|
if (targetSymbol.empty())
|
||||||
json.writeRaw("symbol", "null");
|
json.writeNull("symbol");
|
||||||
else
|
else
|
||||||
json.writeString("symbol", targetSymbol);
|
json.writeString("symbol", targetSymbol);
|
||||||
json.pop();
|
json.pop();
|
||||||
} else {
|
} else {
|
||||||
json.writeRaw("branch", "null");
|
json.writeNull("branch");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (l.info.hasRelevantAddress) {
|
if (l.info.hasRelevantAddress) {
|
||||||
json.pushDict("relevantData");
|
json.pushDict("relevantData");
|
||||||
json.writeFloat("address", l.info.relevantAddress);
|
json.writeUint("address", l.info.relevantAddress);
|
||||||
if (Memory::IsValidRange(l.info.relevantAddress, 4))
|
if (Memory::IsValidRange(l.info.relevantAddress, 4))
|
||||||
json.writeFloat("uintValue", Memory::ReadUnchecked_U32(l.info.relevantAddress));
|
json.writeUint("uintValue", Memory::ReadUnchecked_U32(l.info.relevantAddress));
|
||||||
else
|
else
|
||||||
json.writeRaw("uintValue", "null");
|
json.writeNull("uintValue");
|
||||||
json.pop();
|
json.pop();
|
||||||
} else {
|
} else {
|
||||||
json.writeRaw("relevantData", "null");
|
json.writeNull("relevantData");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (l.info.isConditional)
|
if (l.info.isConditional)
|
||||||
json.writeBool("conditionMet", l.info.conditionMet);
|
json.writeBool("conditionMet", l.info.conditionMet);
|
||||||
else
|
else
|
||||||
json.writeRaw("conditionMet", "null");
|
json.writeNull("conditionMet");
|
||||||
|
|
||||||
if (l.info.isDataAccess) {
|
if (l.info.isDataAccess) {
|
||||||
json.pushDict("dataAccess");
|
json.pushDict("dataAccess");
|
||||||
json.writeFloat("address", l.info.dataAddress);
|
json.writeUint("address", l.info.dataAddress);
|
||||||
json.writeInt("size", l.info.dataSize);
|
json.writeInt("size", l.info.dataSize);
|
||||||
|
|
||||||
std::string dataSymbol = g_symbolMap->GetLabelString(l.info.dataAddress);
|
std::string dataSymbol = g_symbolMap->GetLabelString(l.info.dataAddress);
|
||||||
std::string valueSymbol;
|
std::string valueSymbol;
|
||||||
if (!Memory::IsValidRange(l.info.dataAddress, l.info.dataSize))
|
if (!Memory::IsValidRange(l.info.dataAddress, l.info.dataSize))
|
||||||
json.writeRaw("uintValue", "null");
|
json.writeNull("uintValue");
|
||||||
else if (l.info.dataSize == 1)
|
else if (l.info.dataSize == 1)
|
||||||
json.writeFloat("uintValue", Memory::ReadUnchecked_U8(l.info.dataAddress));
|
json.writeUint("uintValue", Memory::ReadUnchecked_U8(l.info.dataAddress));
|
||||||
else if (l.info.dataSize == 2)
|
else if (l.info.dataSize == 2)
|
||||||
json.writeFloat("uintValue", Memory::ReadUnchecked_U16(l.info.dataAddress));
|
json.writeUint("uintValue", Memory::ReadUnchecked_U16(l.info.dataAddress));
|
||||||
else if (l.info.dataSize >= 4) {
|
else if (l.info.dataSize >= 4) {
|
||||||
u32 data = Memory::ReadUnchecked_U32(l.info.dataAddress);
|
u32 data = Memory::ReadUnchecked_U32(l.info.dataAddress);
|
||||||
valueSymbol = g_symbolMap->GetLabelString(data);
|
valueSymbol = g_symbolMap->GetLabelString(data);
|
||||||
json.writeFloat("uintValue", data);
|
json.writeUint("uintValue", data);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!dataSymbol.empty())
|
if (!dataSymbol.empty())
|
||||||
json.writeString("symbol", dataSymbol);
|
json.writeString("symbol", dataSymbol);
|
||||||
else
|
else
|
||||||
json.writeRaw("symbol", "null");
|
json.writeNull("symbol");
|
||||||
if (!valueSymbol.empty())
|
if (!valueSymbol.empty())
|
||||||
json.writeString("valueSymbol", valueSymbol);
|
json.writeString("valueSymbol", valueSymbol);
|
||||||
else
|
else
|
||||||
json.writeRaw("valueSymbol", "null");
|
json.writeNull("valueSymbol");
|
||||||
json.pop();
|
json.pop();
|
||||||
} else {
|
} else {
|
||||||
json.writeRaw("dataAccess", "null");
|
json.writeNull("dataAccess");
|
||||||
}
|
}
|
||||||
|
|
||||||
json.pop();
|
json.pop();
|
||||||
|
@ -178,8 +178,8 @@ void WebSocketDisasmState::WriteDisasmLine(JsonWriter &json, const DisassemblyLi
|
||||||
|
|
||||||
void WebSocketDisasmState::WriteBranchGuide(JsonWriter &json, const BranchLine &l) {
|
void WebSocketDisasmState::WriteBranchGuide(JsonWriter &json, const BranchLine &l) {
|
||||||
json.pushDict();
|
json.pushDict();
|
||||||
json.writeFloat("top", l.first);
|
json.writeUint("top", l.first);
|
||||||
json.writeFloat("bottom", l.second);
|
json.writeUint("bottom", l.second);
|
||||||
if (l.type == LINE_UP)
|
if (l.type == LINE_UP)
|
||||||
json.writeString("direction", "up");
|
json.writeString("direction", "up");
|
||||||
else if (l.type == LINE_DOWN)
|
else if (l.type == LINE_DOWN)
|
||||||
|
@ -279,8 +279,8 @@ void WebSocketDisasmState::Disasm(DebuggerRequest &req) {
|
||||||
|
|
||||||
JsonWriter &json = req.Respond();
|
JsonWriter &json = req.Respond();
|
||||||
json.pushDict("range");
|
json.pushDict("range");
|
||||||
json.writeFloat("start", start);
|
json.writeUint("start", start);
|
||||||
json.writeFloat("end", end);
|
json.writeUint("end", end);
|
||||||
json.pop();
|
json.pop();
|
||||||
|
|
||||||
json.pushArray("lines");
|
json.pushArray("lines");
|
||||||
|
|
|
@ -34,7 +34,7 @@ struct GameStatusEvent {
|
||||||
j.writeString("title", g_paramSFO.GetValueString("TITLE"));
|
j.writeString("title", g_paramSFO.GetValueString("TITLE"));
|
||||||
j.pop();
|
j.pop();
|
||||||
} else {
|
} else {
|
||||||
j.writeRaw("game", "null");
|
j.writeNull("game");
|
||||||
}
|
}
|
||||||
j.end();
|
j.end();
|
||||||
return j.str();
|
return j.str();
|
||||||
|
|
|
@ -46,7 +46,7 @@ void WebSocketGameStatus(DebuggerRequest &req) {
|
||||||
json.writeString("title", g_paramSFO.GetValueString("TITLE"));
|
json.writeString("title", g_paramSFO.GetValueString("TITLE"));
|
||||||
json.pop();
|
json.pop();
|
||||||
} else {
|
} else {
|
||||||
json.writeRaw("game", "null");
|
json.writeNull("game");
|
||||||
}
|
}
|
||||||
json.writeBool("paused", GetUIState() == UISTATE_PAUSEMENU);
|
json.writeBool("paused", GetUIState() == UISTATE_PAUSEMENU);
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ struct CPUSteppingEvent {
|
||||||
JsonWriter j;
|
JsonWriter j;
|
||||||
j.begin();
|
j.begin();
|
||||||
j.writeString("event", "cpu.stepping");
|
j.writeString("event", "cpu.stepping");
|
||||||
j.writeFloat("pc", currentMIPS->pc);
|
j.writeUint("pc", currentMIPS->pc);
|
||||||
// A double ought to be good enough for a 156 day debug session.
|
// A double ought to be good enough for a 156 day debug session.
|
||||||
j.writeFloat("ticks", CoreTiming::GetTicks());
|
j.writeFloat("ticks", CoreTiming::GetTicks());
|
||||||
j.end();
|
j.end();
|
||||||
|
|
|
@ -84,10 +84,10 @@ void JsonWriter::pushDict() {
|
||||||
stack_.push_back(StackEntry(DICT));
|
stack_.push_back(StackEntry(DICT));
|
||||||
}
|
}
|
||||||
|
|
||||||
void JsonWriter::pushDict(const char *name) {
|
void JsonWriter::pushDict(const std::string &name) {
|
||||||
str_ << comma() << indent() << "\"";
|
str_ << comma() << indent() << "\"";
|
||||||
writeEscapedString(name);
|
writeEscapedString(name);
|
||||||
str_ << "\": {";
|
str_ << (pretty_ ? "\": {" : "\":{");
|
||||||
stack_.back().first = false;
|
stack_.back().first = false;
|
||||||
stack_.push_back(StackEntry(DICT));
|
stack_.push_back(StackEntry(DICT));
|
||||||
}
|
}
|
||||||
|
@ -98,10 +98,10 @@ void JsonWriter::pushArray() {
|
||||||
stack_.push_back(StackEntry(ARRAY));
|
stack_.push_back(StackEntry(ARRAY));
|
||||||
}
|
}
|
||||||
|
|
||||||
void JsonWriter::pushArray(const char *name) {
|
void JsonWriter::pushArray(const std::string &name) {
|
||||||
str_ << comma() << indent() << "\"";
|
str_ << comma() << indent() << "\"";
|
||||||
writeEscapedString(name);
|
writeEscapedString(name);
|
||||||
str_ << "\": [";
|
str_ << (pretty_ ? "\": [" : "\":[");
|
||||||
stack_.push_back(StackEntry(ARRAY));
|
stack_.push_back(StackEntry(ARRAY));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,10 +110,10 @@ void JsonWriter::writeBool(bool value) {
|
||||||
stack_.back().first = false;
|
stack_.back().first = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JsonWriter::writeBool(const char *name, bool value) {
|
void JsonWriter::writeBool(const std::string &name, bool value) {
|
||||||
str_ << comma() << indent() << "\"";
|
str_ << comma() << indent() << "\"";
|
||||||
writeEscapedString(name);
|
writeEscapedString(name);
|
||||||
str_ << "\": " << (value ? "true" : "false");
|
str_ << (pretty_ ? "\": " : "\":") << (value ? "true" : "false");
|
||||||
stack_.back().first = false;
|
stack_.back().first = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,10 +122,22 @@ void JsonWriter::writeInt(int value) {
|
||||||
stack_.back().first = false;
|
stack_.back().first = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JsonWriter::writeInt(const char *name, int value) {
|
void JsonWriter::writeInt(const std::string &name, int value) {
|
||||||
str_ << comma() << indent() << "\"";
|
str_ << comma() << indent() << "\"";
|
||||||
writeEscapedString(name);
|
writeEscapedString(name);
|
||||||
str_ << "\": " << value;
|
str_ << (pretty_ ? "\": " : "\":") << value;
|
||||||
|
stack_.back().first = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void JsonWriter::writeUint(uint32_t value) {
|
||||||
|
str_ << arrayComma() << arrayIndent() << value;
|
||||||
|
stack_.back().first = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void JsonWriter::writeUint(const std::string &name, uint32_t value) {
|
||||||
|
str_ << comma() << indent() << "\"";
|
||||||
|
writeEscapedString(name);
|
||||||
|
str_ << (pretty_ ? "\": " : "\":") << value;
|
||||||
stack_.back().first = false;
|
stack_.back().first = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,10 +150,10 @@ void JsonWriter::writeFloat(double value) {
|
||||||
stack_.back().first = false;
|
stack_.back().first = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JsonWriter::writeFloat(const char *name, double value) {
|
void JsonWriter::writeFloat(const std::string &name, double value) {
|
||||||
str_ << comma() << indent() << "\"";
|
str_ << comma() << indent() << "\"";
|
||||||
writeEscapedString(name);
|
writeEscapedString(name);
|
||||||
str_ << "\": ";
|
str_ << (pretty_ ? "\": " : "\":");
|
||||||
if (std::isfinite(value))
|
if (std::isfinite(value))
|
||||||
str_ << value;
|
str_ << value;
|
||||||
else
|
else
|
||||||
|
@ -149,14 +161,14 @@ void JsonWriter::writeFloat(const char *name, double value) {
|
||||||
stack_.back().first = false;
|
stack_.back().first = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JsonWriter::writeString(const char *value) {
|
void JsonWriter::writeString(const std::string &value) {
|
||||||
str_ << arrayComma() << arrayIndent() << "\"";
|
str_ << arrayComma() << arrayIndent() << "\"";
|
||||||
writeEscapedString(value);
|
writeEscapedString(value);
|
||||||
str_ << "\"";
|
str_ << "\"";
|
||||||
stack_.back().first = false;
|
stack_.back().first = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JsonWriter::writeString(const char *name, const char *value) {
|
void JsonWriter::writeString(const std::string &name, const std::string &value) {
|
||||||
str_ << comma() << indent() << "\"";
|
str_ << comma() << indent() << "\"";
|
||||||
writeEscapedString(name);
|
writeEscapedString(name);
|
||||||
str_ << (pretty_ ? "\": \"" : "\":\"");
|
str_ << (pretty_ ? "\": \"" : "\":\"");
|
||||||
|
@ -165,12 +177,12 @@ void JsonWriter::writeString(const char *name, const char *value) {
|
||||||
stack_.back().first = false;
|
stack_.back().first = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JsonWriter::writeRaw(const char *value) {
|
void JsonWriter::writeRaw(const std::string &value) {
|
||||||
str_ << arrayComma() << arrayIndent() << value;
|
str_ << arrayComma() << arrayIndent() << value;
|
||||||
stack_.back().first = false;
|
stack_.back().first = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JsonWriter::writeRaw(const char *name, const char *value) {
|
void JsonWriter::writeRaw(const std::string &name, const std::string &value) {
|
||||||
str_ << comma() << indent() << "\"";
|
str_ << comma() << indent() << "\"";
|
||||||
writeEscapedString(name);
|
writeEscapedString(name);
|
||||||
str_ << (pretty_ ? "\": " : "\":");
|
str_ << (pretty_ ? "\": " : "\":");
|
||||||
|
@ -178,6 +190,18 @@ void JsonWriter::writeRaw(const char *name, const char *value) {
|
||||||
stack_.back().first = false;
|
stack_.back().first = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void JsonWriter::writeNull() {
|
||||||
|
str_ << arrayComma() << arrayIndent() << "null";
|
||||||
|
stack_.back().first = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void JsonWriter::writeNull(const std::string &name) {
|
||||||
|
str_ << comma() << indent() << "\"";
|
||||||
|
writeEscapedString(name);
|
||||||
|
str_ << (pretty_ ? "\": " : "\":") << "null";
|
||||||
|
stack_.back().first = false;
|
||||||
|
}
|
||||||
|
|
||||||
void JsonWriter::pop() {
|
void JsonWriter::pop() {
|
||||||
BlockType type = stack_.back().type;
|
BlockType type = stack_.back().type;
|
||||||
stack_.pop_back();
|
stack_.pop_back();
|
||||||
|
@ -197,33 +221,53 @@ void JsonWriter::pop() {
|
||||||
stack_.back().first = false;
|
stack_.back().first = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JsonWriter::writeEscapedString(const char *str) {
|
void JsonWriter::writeEscapedString(const std::string &str) {
|
||||||
size_t pos = 0;
|
size_t pos = 0;
|
||||||
size_t len = strlen(str);
|
const size_t len = str.size();
|
||||||
|
|
||||||
auto update = [&](size_t current, size_t skip = 0) {
|
auto update = [&](size_t current, size_t skip = 0) {
|
||||||
size_t end = current;
|
size_t end = current;
|
||||||
if (pos < end)
|
if (pos < end)
|
||||||
str_ << std::string(str + pos, end - pos);
|
str_ << str.substr(pos, end - pos);
|
||||||
pos = end + skip;
|
pos = end + skip;
|
||||||
};
|
};
|
||||||
|
|
||||||
for (size_t i = 0; i < len; ++i) {
|
for (size_t i = 0; i < len; ++i) {
|
||||||
if (str[i] == '\\' || str[i] == '"' || str[i] == '/') {
|
switch (str[i]) {
|
||||||
|
case '\\':
|
||||||
|
case '"':
|
||||||
|
case '/':
|
||||||
update(i);
|
update(i);
|
||||||
str_ << '\\';
|
str_ << '\\';
|
||||||
} else if (str[i] == '\r') {
|
break;
|
||||||
|
|
||||||
|
case '\r':
|
||||||
update(i, 1);
|
update(i, 1);
|
||||||
str_ << "\\r";
|
str_ << "\\r";
|
||||||
} else if (str[i] == '\n') {
|
break;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '\n':
|
||||||
update(i, 1);
|
update(i, 1);
|
||||||
str_ << "\\n";
|
str_ << "\\n";
|
||||||
} else if (str[i] == '\t') {
|
break;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '\t':
|
||||||
update(i, 1);
|
update(i, 1);
|
||||||
str_ << "\\t";
|
str_ << "\\t";
|
||||||
} else if (str[i] < 32) {
|
break;
|
||||||
|
|
||||||
|
case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 11:
|
||||||
|
case 12: case 14: case 15: case 16: case 17: case 18: case 19: case 20:
|
||||||
|
case 21: case 22: case 23: case 24: case 25: case 26: case 27: case 28:
|
||||||
|
case 29: case 30: case 31:
|
||||||
update(i, 1);
|
update(i, 1);
|
||||||
str_ << "\\u" << std::hex << std::setw(4) << std::setfill('0') << (int)str[i] << std::dec << std::setw(0);
|
str_ << "\\u" << std::hex << std::setw(4) << std::setfill('0') << (int)str[i] << std::dec << std::setw(0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -273,7 +317,7 @@ std::string json_stringify(const JsonNode *node) {
|
||||||
static void json_stringify_object(JsonWriter &writer, const JsonNode *node) {
|
static void json_stringify_object(JsonWriter &writer, const JsonNode *node) {
|
||||||
switch (node->value.getTag()) {
|
switch (node->value.getTag()) {
|
||||||
case JSON_NULL:
|
case JSON_NULL:
|
||||||
writer.writeRaw(node->key, "null");
|
writer.writeNull(node->key);
|
||||||
break;
|
break;
|
||||||
case JSON_STRING:
|
case JSON_STRING:
|
||||||
writer.writeString(node->key, node->value.toString());
|
writer.writeString(node->key, node->value.toString());
|
||||||
|
|
|
@ -22,38 +22,24 @@ public:
|
||||||
void beginRaw();
|
void beginRaw();
|
||||||
void end();
|
void end();
|
||||||
void pushDict();
|
void pushDict();
|
||||||
void pushDict(const char *name);
|
void pushDict(const std::string &name);
|
||||||
void pushArray();
|
void pushArray();
|
||||||
void pushArray(const char *name);
|
void pushArray(const std::string &name);
|
||||||
void pop();
|
void pop();
|
||||||
void writeBool(bool value);
|
void writeBool(bool value);
|
||||||
void writeBool(const char *name, bool value);
|
void writeBool(const std::string &name, bool value);
|
||||||
void writeInt(int value);
|
void writeInt(int value);
|
||||||
void writeInt(const char *name, int value);
|
void writeInt(const std::string &name, int value);
|
||||||
|
void writeUint(uint32_t value);
|
||||||
|
void writeUint(const std::string &name, uint32_t value);
|
||||||
void writeFloat(double value);
|
void writeFloat(double value);
|
||||||
void writeFloat(const char *name, double value);
|
void writeFloat(const std::string &name, double value);
|
||||||
void writeString(const char *value);
|
void writeString(const std::string &value);
|
||||||
void writeString(const char *name, const char *value);
|
void writeString(const std::string &name, const std::string &value);
|
||||||
void writeString(const std::string &value) {
|
void writeRaw(const std::string &value);
|
||||||
writeString(value.c_str());
|
void writeRaw(const std::string &name, const std::string &value);
|
||||||
}
|
void writeNull();
|
||||||
void writeString(const char *name, const std::string &value) {
|
void writeNull(const std::string &name);
|
||||||
writeString(name, value.c_str());
|
|
||||||
}
|
|
||||||
void writeString(const std::string &name, const std::string &value) {
|
|
||||||
writeString(name.c_str(), value.c_str());
|
|
||||||
}
|
|
||||||
void writeRaw(const char *value);
|
|
||||||
void writeRaw(const char *name, const char *value);
|
|
||||||
void writeRaw(const std::string &value) {
|
|
||||||
writeRaw(value.c_str());
|
|
||||||
}
|
|
||||||
void writeRaw(const char *name, const std::string &value) {
|
|
||||||
writeRaw(name, value.c_str());
|
|
||||||
}
|
|
||||||
void writeRaw(const std::string &name, const std::string &value) {
|
|
||||||
writeRaw(name.c_str(), value.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string str() const {
|
std::string str() const {
|
||||||
return str_.str();
|
return str_.str();
|
||||||
|
@ -76,7 +62,7 @@ private:
|
||||||
const char *arrayComma() const;
|
const char *arrayComma() const;
|
||||||
const char *indent() const;
|
const char *indent() const;
|
||||||
const char *arrayIndent() const;
|
const char *arrayIndent() const;
|
||||||
void writeEscapedString(const char *s);
|
void writeEscapedString(const std::string &s);
|
||||||
|
|
||||||
enum BlockType {
|
enum BlockType {
|
||||||
ARRAY,
|
ARRAY,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue