mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-02-20 06:00:58 +00:00
json: Optimize writing a bit.
This improves the responsiveness of certain APIs.
This commit is contained in:
parent
ccea863f00
commit
fc8ad3b47b
@ -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));
|
||||
}
|
||||
|
@ -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");
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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());
|
||||
|
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user