Support all JSON escape codes (including \u) for parsing & text gen.

Bug: 16624362
Change-Id: Ia09ea404c0c11dd1dc6993a8cbd155bf8152b65f
Tested: on Windows & Linux.
This commit is contained in:
Wouter van Oortmerssen
2014-08-20 13:22:16 -07:00
parent f7b0d130b6
commit ebac1e1940
8 changed files with 172 additions and 27 deletions

View File

@@ -28,8 +28,12 @@ static void GenStruct(const StructDef &struct_def, const Table *table,
// If indentation is less than 0, that indicates we don't want any newlines
// either.
const char *NewLine(int indent_step) {
return indent_step >= 0 ? "\n" : "";
const char *NewLine(const GeneratorOptions &opts) {
return opts.indent_step >= 0 ? "\n" : "";
}
int Indent(const GeneratorOptions &opts) {
return std::max(opts.indent_step, 0);
}
// Output an identifier with or without quotes depending on strictness.
@@ -65,21 +69,21 @@ template<typename T> void PrintVector(const Vector<T> &v, Type type,
std::string *_text) {
std::string &text = *_text;
text += "[";
text += NewLine(opts.indent_step);
text += NewLine(opts);
for (uoffset_t i = 0; i < v.Length(); i++) {
if (i) {
text += ",";
text += NewLine(opts.indent_step);
text += NewLine(opts);
}
text.append(indent + opts.indent_step, ' ');
text.append(indent + Indent(opts), ' ');
if (IsStruct(type))
Print(v.GetStructFromOffset(i * type.struct_def->bytesize), type,
indent + opts.indent_step, nullptr, opts, _text);
indent + Indent(opts), nullptr, opts, _text);
else
Print(v.Get(i), type, indent + opts.indent_step, nullptr,
Print(v.Get(i), type, indent + Indent(opts), nullptr,
opts, _text);
}
text += NewLine(opts.indent_step);
text += NewLine(opts);
text.append(indent, ' ');
text += "]";
}
@@ -93,15 +97,28 @@ static void EscapeString(const String &s, std::string *_text) {
case '\n': text += "\\n"; break;
case '\t': text += "\\t"; break;
case '\r': text += "\\r"; break;
case '\b': text += "\\b"; break;
case '\f': text += "\\f"; break;
case '\"': text += "\\\""; break;
case '\\': text += "\\\\"; break;
default:
if (c >= ' ' && c <= '~') {
text += c;
} else {
auto u = static_cast<unsigned char>(c);
text += "\\x";
text += IntToStringHex(u);
// Not printable ASCII data. Let's see if it's valid UTF-8 first:
const char *utf8 = s.c_str() + i;
int ucc = FromUTF8(&utf8);
if (ucc >= 0x80 && ucc <= 0xFFFF) {
// Parses as Unicode within JSON's \uXXXX range, so use that.
text += "\\u";
text += IntToStringHex(ucc, 4);
i = utf8 - s.c_str() - 1; // Skip past characters recognized.
} else {
// It's either unprintable ASCII, arbitrary binary, or Unicode data
// that doesn't fit \uXXXX, so use \xXX escape code instead.
text += "\\x";
text += IntToStringHex(static_cast<uint8_t>(c), 2);
}
}
break;
}
@@ -202,15 +219,15 @@ static void GenStruct(const StructDef &struct_def, const Table *table,
if (fieldout++) {
text += ",";
}
text += NewLine(opts.indent_step);
text.append(indent + opts.indent_step, ' ');
text += NewLine(opts);
text.append(indent + Indent(opts), ' ');
OutputIdentifier(fd.name, opts, _text);
text += ": ";
switch (fd.value.type.base_type) {
#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE) \
case BASE_TYPE_ ## ENUM: \
GenField<CTYPE>(fd, table, struct_def.fixed, \
opts, indent + opts.indent_step, _text); \
opts, indent + Indent(opts), _text); \
break;
FLATBUFFERS_GEN_TYPES_SCALAR(FLATBUFFERS_TD)
#undef FLATBUFFERS_TD
@@ -219,7 +236,7 @@ static void GenStruct(const StructDef &struct_def, const Table *table,
case BASE_TYPE_ ## ENUM:
FLATBUFFERS_GEN_TYPES_POINTER(FLATBUFFERS_TD)
#undef FLATBUFFERS_TD
GenFieldOffset(fd, table, struct_def.fixed, indent + opts.indent_step,
GenFieldOffset(fd, table, struct_def.fixed, indent + Indent(opts),
union_sd, opts, _text);
break;
}
@@ -231,7 +248,7 @@ static void GenStruct(const StructDef &struct_def, const Table *table,
}
}
}
text += NewLine(opts.indent_step);
text += NewLine(opts);
text.append(indent, ' ');
text += "}";
}
@@ -247,7 +264,7 @@ void GenerateText(const Parser &parser, const void *flatbuffer,
0,
opts,
_text);
text += NewLine(opts.indent_step);
text += NewLine(opts);
}
} // namespace flatbuffers