mirror of
https://github.com/google/flatbuffers.git
synced 2026-06-10 07:06:26 +00:00
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:
@@ -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
|
||||
|
||||
@@ -115,6 +115,17 @@ static std::string TokenToString(int t) {
|
||||
}
|
||||
}
|
||||
|
||||
// Parses exactly nibbles worth of hex digits into a number, or error.
|
||||
int64_t Parser::ParseHexNum(int nibbles) {
|
||||
for (int i = 0; i < nibbles; i++)
|
||||
if (!isxdigit(cursor_[i]))
|
||||
Error("escape code must be followed by " + NumToString(nibbles) +
|
||||
" hex digits");
|
||||
auto val = StringToInt(cursor_, 16);
|
||||
cursor_ += nibbles;
|
||||
return val;
|
||||
}
|
||||
|
||||
void Parser::Next() {
|
||||
doc_comment_.clear();
|
||||
bool seen_newline = false;
|
||||
@@ -142,8 +153,21 @@ void Parser::Next() {
|
||||
case 'n': attribute_ += '\n'; cursor_++; break;
|
||||
case 't': attribute_ += '\t'; cursor_++; break;
|
||||
case 'r': attribute_ += '\r'; cursor_++; break;
|
||||
case 'b': attribute_ += '\b'; cursor_++; break;
|
||||
case 'f': attribute_ += '\f'; cursor_++; break;
|
||||
case '\"': attribute_ += '\"'; cursor_++; break;
|
||||
case '\\': attribute_ += '\\'; cursor_++; break;
|
||||
case '/': attribute_ += '/'; cursor_++; break;
|
||||
case 'x': { // Not in the JSON standard
|
||||
cursor_++;
|
||||
attribute_ += static_cast<char>(ParseHexNum(2));
|
||||
break;
|
||||
}
|
||||
case 'u': {
|
||||
cursor_++;
|
||||
ToUTF8(static_cast<int>(ParseHexNum(4)), &attribute_);
|
||||
break;
|
||||
}
|
||||
default: Error("unknown escape code in string constant"); break;
|
||||
}
|
||||
} else { // printable chars + UTF-8 bytes
|
||||
|
||||
Reference in New Issue
Block a user