json: Optimize writing a bit.

This improves the responsiveness of certain APIs.
This commit is contained in:
Unknown W. Brackets 2018-04-30 20:38:39 -07:00
parent ccea863f00
commit fc8ad3b47b
7 changed files with 121 additions and 91 deletions

View File

@ -91,7 +91,7 @@ void WebSocketCPUStatus(DebuggerRequest &req) {
json.writeBool("stepping", PSP_IsInited() && Core_IsStepping() && coreState != CORE_POWERDOWN);
json.writeBool("paused", GetUIState() != UISTATE_INGAME);
// 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.
json.writeFloat("ticks", PSP_IsInited() ? CoreTiming::GetTicks() : 0);
}
@ -131,11 +131,11 @@ void WebSocketCPUGetAllRegs(DebuggerRequest &req) {
json.pushArray("uintValues");
// Writing as floating point to avoid negatives. Actually double, so safe.
for (int r = 0; r < total; ++r)
json.writeFloat(currentDebugMIPS->GetRegValue(c, r));
json.writeUint(currentDebugMIPS->GetRegValue(c, r));
if (c == 0) {
json.writeFloat(currentDebugMIPS->GetPC());
json.writeFloat(currentDebugMIPS->GetHi());
json.writeFloat(currentDebugMIPS->GetLo());
json.writeUint(currentDebugMIPS->GetPC());
json.writeUint(currentDebugMIPS->GetHi());
json.writeUint(currentDebugMIPS->GetLo());
}
json.pop();
@ -267,7 +267,7 @@ void WebSocketCPUGetReg(DebuggerRequest &req) {
JsonWriter &json = req.Respond();
json.writeInt("category", cat);
json.writeInt("register", reg);
json.writeFloat("uintValue", val);
json.writeUint("uintValue", 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.
json.writeInt("category", cat);
json.writeInt("register", reg);
json.writeFloat("uintValue", val);
json.writeUint("uintValue", val);
json.writeString("floatValue", RegValueAsFloat(val));
}
@ -368,6 +368,6 @@ void WebSocketCPUEvaluate(DebuggerRequest &req) {
}
JsonWriter &json = req.Respond();
json.writeFloat("uintValue", val);
json.writeUint("uintValue", val);
json.writeString("floatValue", RegValueAsFloat(val));
}

View File

@ -63,17 +63,17 @@ void WebSocketDisasmState::WriteDisasmLine(JsonWriter &json, const DisassemblyLi
else if (l.type == DISTYPE_OTHER)
json.writeString("type", "other");
json.writeFloat("address", addr);
json.writeUint("address", addr);
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)) {
json.pushArray("macroEncoding");
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();
} else {
json.writeRaw("macroEncoding", "null");
json.writeNull("macroEncoding");
}
int c = currentDebugMIPS->getColor(addr) & 0x00FFFFFF;
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);
if (addressSymbol.empty())
json.writeRaw("symbol", "null");
json.writeNull("symbol");
else
json.writeString("symbol", addressSymbol);
@ -95,10 +95,10 @@ void WebSocketDisasmState::WriteDisasmLine(JsonWriter &json, const DisassemblyLi
if (cond)
json.writeString("expression", cond->expressionString);
else
json.writeRaw("expression", "null");
json.writeNull("expression");
json.pop();
} else {
json.writeRaw("breakpoint", "null");
json.writeNull("breakpoint");
}
json.writeBool("isCurrentPC", currentDebugMIPS->GetPC() == addr);
@ -107,70 +107,70 @@ void WebSocketDisasmState::WriteDisasmLine(JsonWriter &json, const DisassemblyLi
std::string targetSymbol;
if (!l.info.isBranchToRegister) {
targetSymbol = g_symbolMap->GetLabelString(l.info.branchTarget);
json.writeFloat("targetAddress", l.info.branchTarget);
json.writeRaw("register", "null");
json.writeUint("targetAddress", l.info.branchTarget);
json.writeNull("register");
} else {
json.writeRaw("targetAddress", "null");
json.writeNull("targetAddress");
json.writeInt("register", l.info.branchRegisterNum);
}
json.writeBool("isLinked", l.info.isLinkedBranch);
json.writeBool("isLikely", l.info.isLikelyBranch);
if (targetSymbol.empty())
json.writeRaw("symbol", "null");
json.writeNull("symbol");
else
json.writeString("symbol", targetSymbol);
json.pop();
} else {
json.writeRaw("branch", "null");
json.writeNull("branch");
}
if (l.info.hasRelevantAddress) {
json.pushDict("relevantData");
json.writeFloat("address", l.info.relevantAddress);
json.writeUint("address", l.info.relevantAddress);
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
json.writeRaw("uintValue", "null");
json.writeNull("uintValue");
json.pop();
} else {
json.writeRaw("relevantData", "null");
json.writeNull("relevantData");
}
if (l.info.isConditional)
json.writeBool("conditionMet", l.info.conditionMet);
else
json.writeRaw("conditionMet", "null");
json.writeNull("conditionMet");
if (l.info.isDataAccess) {
json.pushDict("dataAccess");
json.writeFloat("address", l.info.dataAddress);
json.writeUint("address", l.info.dataAddress);
json.writeInt("size", l.info.dataSize);
std::string dataSymbol = g_symbolMap->GetLabelString(l.info.dataAddress);
std::string valueSymbol;
if (!Memory::IsValidRange(l.info.dataAddress, l.info.dataSize))
json.writeRaw("uintValue", "null");
json.writeNull("uintValue");
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)
json.writeFloat("uintValue", Memory::ReadUnchecked_U16(l.info.dataAddress));
json.writeUint("uintValue", Memory::ReadUnchecked_U16(l.info.dataAddress));
else if (l.info.dataSize >= 4) {
u32 data = Memory::ReadUnchecked_U32(l.info.dataAddress);
valueSymbol = g_symbolMap->GetLabelString(data);
json.writeFloat("uintValue", data);
json.writeUint("uintValue", data);
}
if (!dataSymbol.empty())
json.writeString("symbol", dataSymbol);
else
json.writeRaw("symbol", "null");
json.writeNull("symbol");
if (!valueSymbol.empty())
json.writeString("valueSymbol", valueSymbol);
else
json.writeRaw("valueSymbol", "null");
json.writeNull("valueSymbol");
json.pop();
} else {
json.writeRaw("dataAccess", "null");
json.writeNull("dataAccess");
}
json.pop();
@ -178,8 +178,8 @@ void WebSocketDisasmState::WriteDisasmLine(JsonWriter &json, const DisassemblyLi
void WebSocketDisasmState::WriteBranchGuide(JsonWriter &json, const BranchLine &l) {
json.pushDict();
json.writeFloat("top", l.first);
json.writeFloat("bottom", l.second);
json.writeUint("top", l.first);
json.writeUint("bottom", l.second);
if (l.type == LINE_UP)
json.writeString("direction", "up");
else if (l.type == LINE_DOWN)
@ -279,8 +279,8 @@ void WebSocketDisasmState::Disasm(DebuggerRequest &req) {
JsonWriter &json = req.Respond();
json.pushDict("range");
json.writeFloat("start", start);
json.writeFloat("end", end);
json.writeUint("start", start);
json.writeUint("end", end);
json.pop();
json.pushArray("lines");

View File

@ -34,7 +34,7 @@ struct GameStatusEvent {
j.writeString("title", g_paramSFO.GetValueString("TITLE"));
j.pop();
} else {
j.writeRaw("game", "null");
j.writeNull("game");
}
j.end();
return j.str();

View File

@ -46,7 +46,7 @@ void WebSocketGameStatus(DebuggerRequest &req) {
json.writeString("title", g_paramSFO.GetValueString("TITLE"));
json.pop();
} else {
json.writeRaw("game", "null");
json.writeNull("game");
}
json.writeBool("paused", GetUIState() == UISTATE_PAUSEMENU);
}

View File

@ -27,7 +27,7 @@ struct CPUSteppingEvent {
JsonWriter j;
j.begin();
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.
j.writeFloat("ticks", CoreTiming::GetTicks());
j.end();

View File

@ -84,10 +84,10 @@ void JsonWriter::pushDict() {
stack_.push_back(StackEntry(DICT));
}
void JsonWriter::pushDict(const char *name) {
void JsonWriter::pushDict(const std::string &name) {
str_ << comma() << indent() << "\"";
writeEscapedString(name);
str_ << "\": {";
str_ << (pretty_ ? "\": {" : "\":{");
stack_.back().first = false;
stack_.push_back(StackEntry(DICT));
}
@ -98,10 +98,10 @@ void JsonWriter::pushArray() {
stack_.push_back(StackEntry(ARRAY));
}
void JsonWriter::pushArray(const char *name) {
void JsonWriter::pushArray(const std::string &name) {
str_ << comma() << indent() << "\"";
writeEscapedString(name);
str_ << "\": [";
str_ << (pretty_ ? "\": [" : "\":[");
stack_.push_back(StackEntry(ARRAY));
}
@ -110,10 +110,10 @@ void JsonWriter::writeBool(bool value) {
stack_.back().first = false;
}
void JsonWriter::writeBool(const char *name, bool value) {
void JsonWriter::writeBool(const std::string &name, bool value) {
str_ << comma() << indent() << "\"";
writeEscapedString(name);
str_ << "\": " << (value ? "true" : "false");
str_ << (pretty_ ? "\": " : "\":") << (value ? "true" : "false");
stack_.back().first = false;
}
@ -122,10 +122,22 @@ void JsonWriter::writeInt(int value) {
stack_.back().first = false;
}
void JsonWriter::writeInt(const char *name, int value) {
void JsonWriter::writeInt(const std::string &name, int value) {
str_ << comma() << indent() << "\"";
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;
}
@ -138,10 +150,10 @@ void JsonWriter::writeFloat(double value) {
stack_.back().first = false;
}
void JsonWriter::writeFloat(const char *name, double value) {
void JsonWriter::writeFloat(const std::string &name, double value) {
str_ << comma() << indent() << "\"";
writeEscapedString(name);
str_ << "\": ";
str_ << (pretty_ ? "\": " : "\":");
if (std::isfinite(value))
str_ << value;
else
@ -149,14 +161,14 @@ void JsonWriter::writeFloat(const char *name, double value) {
stack_.back().first = false;
}
void JsonWriter::writeString(const char *value) {
void JsonWriter::writeString(const std::string &value) {
str_ << arrayComma() << arrayIndent() << "\"";
writeEscapedString(value);
str_ << "\"";
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() << "\"";
writeEscapedString(name);
str_ << (pretty_ ? "\": \"" : "\":\"");
@ -165,12 +177,12 @@ void JsonWriter::writeString(const char *name, const char *value) {
stack_.back().first = false;
}
void JsonWriter::writeRaw(const char *value) {
void JsonWriter::writeRaw(const std::string &value) {
str_ << arrayComma() << arrayIndent() << value;
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() << "\"";
writeEscapedString(name);
str_ << (pretty_ ? "\": " : "\":");
@ -178,6 +190,18 @@ void JsonWriter::writeRaw(const char *name, const char *value) {
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() {
BlockType type = stack_.back().type;
stack_.pop_back();
@ -197,33 +221,53 @@ void JsonWriter::pop() {
stack_.back().first = false;
}
void JsonWriter::writeEscapedString(const char *str) {
void JsonWriter::writeEscapedString(const std::string &str) {
size_t pos = 0;
size_t len = strlen(str);
const size_t len = str.size();
auto update = [&](size_t current, size_t skip = 0) {
size_t end = current;
if (pos < end)
str_ << std::string(str + pos, end - pos);
str_ << str.substr(pos, end - pos);
pos = end + skip;
};
for (size_t i = 0; i < len; ++i) {
if (str[i] == '\\' || str[i] == '"' || str[i] == '/') {
switch (str[i]) {
case '\\':
case '"':
case '/':
update(i);
str_ << '\\';
} else if (str[i] == '\r') {
break;
case '\r':
update(i, 1);
str_ << "\\r";
} else if (str[i] == '\n') {
break;
break;
case '\n':
update(i, 1);
str_ << "\\n";
} else if (str[i] == '\t') {
break;
break;
case '\t':
update(i, 1);
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);
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) {
switch (node->value.getTag()) {
case JSON_NULL:
writer.writeRaw(node->key, "null");
writer.writeNull(node->key);
break;
case JSON_STRING:
writer.writeString(node->key, node->value.toString());

View File

@ -22,38 +22,24 @@ public:
void beginRaw();
void end();
void pushDict();
void pushDict(const char *name);
void pushDict(const std::string &name);
void pushArray();
void pushArray(const char *name);
void pushArray(const std::string &name);
void pop();
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(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(const char *name, double value);
void writeString(const char *value);
void writeString(const char *name, const char *value);
void writeString(const std::string &value) {
writeString(value.c_str());
}
void writeString(const char *name, const std::string &value) {
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());
}
void writeFloat(const std::string &name, double value);
void writeString(const std::string &value);
void writeString(const std::string &name, const std::string &value);
void writeRaw(const std::string &value);
void writeRaw(const std::string &name, const std::string &value);
void writeNull();
void writeNull(const std::string &name);
std::string str() const {
return str_.str();
@ -76,7 +62,7 @@ private:
const char *arrayComma() const;
const char *indent() const;
const char *arrayIndent() const;
void writeEscapedString(const char *s);
void writeEscapedString(const std::string &s);
enum BlockType {
ARRAY,