mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-09-11 15:13:37 +02:00
json: Escape strings in the json writer.
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
#include <iomanip>
|
||||
#include "json/json_writer.h"
|
||||
|
||||
JsonWriter::JsonWriter() {
|
||||
JsonWriter::JsonWriter(int flags) {
|
||||
pretty_ = (flags & PRETTY) != 0;
|
||||
str_.imbue(std::locale::classic());
|
||||
}
|
||||
|
||||
JsonWriter::~JsonWriter() {
|
||||
@@ -13,15 +16,24 @@ void JsonWriter::begin() {
|
||||
|
||||
void JsonWriter::end() {
|
||||
pop();
|
||||
str_ << "\n";
|
||||
if (pretty_)
|
||||
str_ << "\n";
|
||||
}
|
||||
|
||||
const char *JsonWriter::indent(int n) const {
|
||||
static const char * const whitespace = " ";
|
||||
if (!pretty_)
|
||||
return "";
|
||||
static const char * const whitespace = " ";
|
||||
if (n > 32) {
|
||||
// Avoid crash.
|
||||
return whitespace;
|
||||
}
|
||||
return whitespace + (32 - n);
|
||||
}
|
||||
|
||||
const char *JsonWriter::indent() const {
|
||||
if (!pretty_)
|
||||
return "";
|
||||
int amount = (int)stack_.size() + 1;
|
||||
amount *= 2; // 2-space indent.
|
||||
return indent(amount);
|
||||
@@ -37,7 +49,7 @@ const char *JsonWriter::comma() const {
|
||||
if (stack_.back().first) {
|
||||
return "";
|
||||
} else {
|
||||
return ",";
|
||||
return ",\n";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,17 +57,21 @@ const char *JsonWriter::arrayComma() const {
|
||||
if (stack_.back().first) {
|
||||
return "\n";
|
||||
} else {
|
||||
return ", ";
|
||||
return pretty_ ? ", " : ",";
|
||||
}
|
||||
}
|
||||
|
||||
void JsonWriter::pushDict(const char *name) {
|
||||
str_ << comma() << "\n" << indent() << "\"" << name << "\": {";
|
||||
str_ << comma() << indent() << "\"";
|
||||
writeEscapedString(name);
|
||||
str_ << "\": {";
|
||||
stack_.push_back(StackEntry(DICT));
|
||||
}
|
||||
|
||||
void JsonWriter::pushArray(const char *name) {
|
||||
str_ << comma() << "\n" << indent() << "\"" << name << "\": [";
|
||||
str_ << comma() << indent() << "\"";
|
||||
writeEscapedString(name);
|
||||
str_ << "\": [";
|
||||
stack_.push_back(StackEntry(ARRAY));
|
||||
}
|
||||
|
||||
@@ -65,7 +81,9 @@ void JsonWriter::writeBool(bool value) {
|
||||
}
|
||||
|
||||
void JsonWriter::writeBool(const char *name, bool value) {
|
||||
str_ << comma() << "\n" << indent() << "\"" << name << "\": " << (value ? "true" : "false");
|
||||
str_ << comma() << indent() << "\"";
|
||||
writeEscapedString(name);
|
||||
str_ << "\": " << (value ? "true" : "false");
|
||||
stack_.back().first = false;
|
||||
}
|
||||
|
||||
@@ -75,7 +93,9 @@ void JsonWriter::writeInt(int value) {
|
||||
}
|
||||
|
||||
void JsonWriter::writeInt(const char *name, int value) {
|
||||
str_ << comma() << "\n" << indent() << "\"" << name << "\": " << value;
|
||||
str_ << comma() << indent() << "\"";
|
||||
writeEscapedString(name);
|
||||
str_ << "\": " << value;
|
||||
stack_.back().first = false;
|
||||
}
|
||||
|
||||
@@ -85,31 +105,78 @@ void JsonWriter::writeFloat(double value) {
|
||||
}
|
||||
|
||||
void JsonWriter::writeFloat(const char *name, double value) {
|
||||
str_ << comma() << "\n" << indent() << "\"" << name << "\": " << value;
|
||||
str_ << comma() << indent() << "\"";
|
||||
writeEscapedString(name);
|
||||
str_ << "\": " << value;
|
||||
stack_.back().first = false;
|
||||
}
|
||||
|
||||
void JsonWriter::writeString(const char *value) {
|
||||
str_ << arrayComma() << arrayIndent() << "\"" << value << "\"";
|
||||
str_ << arrayComma() << arrayIndent() << "\"";
|
||||
writeEscapedString(value);
|
||||
str_ << "\"";
|
||||
stack_.back().first = false;
|
||||
}
|
||||
|
||||
void JsonWriter::writeString(const char *name, const char *value) {
|
||||
str_ << comma() << "\n" << indent() << "\"" << name << "\": \"" << value << "\"";
|
||||
str_ << comma() << indent() << "\"";
|
||||
writeEscapedString(name);
|
||||
str_ << "\": \"";
|
||||
writeEscapedString(value);
|
||||
str_ << "\"";
|
||||
stack_.back().first = false;
|
||||
}
|
||||
|
||||
void JsonWriter::pop() {
|
||||
BlockType type = stack_.back().type;
|
||||
stack_.pop_back();
|
||||
if (pretty_)
|
||||
str_ << "\n" << indent();
|
||||
switch (type) {
|
||||
case ARRAY:
|
||||
str_ << "\n" << indent() << "]";
|
||||
str_ << "]";
|
||||
break;
|
||||
case DICT:
|
||||
str_ << "\n" << indent() << "}";
|
||||
str_ << "}";
|
||||
break;
|
||||
}
|
||||
if (stack_.size() > 0)
|
||||
stack_.back().first = false;
|
||||
}
|
||||
|
||||
void JsonWriter::writeEscapedString(const char *str) {
|
||||
size_t pos = 0;
|
||||
size_t len = strlen(str);
|
||||
|
||||
auto update = [&](size_t current, size_t skip = 0) {
|
||||
size_t end = current;
|
||||
if (pos < end)
|
||||
str_ << std::string(str + pos, end - pos);
|
||||
pos = end + skip;
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
if (str[i] == '\\' || str[i] == '"' || str[i] == '/') {
|
||||
update(i);
|
||||
str_ << '\\';
|
||||
} else if (str[i] == '\r') {
|
||||
update(i, 1);
|
||||
str_ << "\\r";
|
||||
} else if (str[i] == '\n') {
|
||||
update(i, 1);
|
||||
str_ << "\\n";
|
||||
} else if (str[i] == '\t') {
|
||||
update(i, 1);
|
||||
str_ << "\\t";
|
||||
} else if (str[i] < 32) {
|
||||
update(i, 1);
|
||||
str_ << "\\u" << std::hex << std::setw(4) << std::setfill('0') << (int)str[i] << std::dec << std::setw(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (pos != 0) {
|
||||
update(len);
|
||||
} else {
|
||||
str_ << str;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
class JsonWriter {
|
||||
public:
|
||||
JsonWriter();
|
||||
JsonWriter(int flags = NORMAL);
|
||||
~JsonWriter();
|
||||
void begin();
|
||||
void end();
|
||||
@@ -31,17 +31,33 @@ public:
|
||||
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());
|
||||
}
|
||||
|
||||
std::string str() const {
|
||||
return str_.str();
|
||||
}
|
||||
|
||||
enum {
|
||||
NORMAL = 0,
|
||||
PRETTY = 1,
|
||||
};
|
||||
|
||||
private:
|
||||
const char *indent(int n) const;
|
||||
const char *comma() const;
|
||||
const char *arrayComma() const;
|
||||
const char *indent() const;
|
||||
const char *arrayIndent() const;
|
||||
void writeEscapedString(const char *s);
|
||||
|
||||
enum BlockType {
|
||||
ARRAY,
|
||||
DICT,
|
||||
@@ -53,4 +69,5 @@ private:
|
||||
};
|
||||
std::vector<StackEntry> stack_;
|
||||
std::ostringstream str_;
|
||||
bool pretty_;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user