This commit is contained in:
Wouter van Oortmerssen
2016-08-08 12:17:10 -07:00
14 changed files with 455 additions and 140 deletions

View File

@@ -106,6 +106,9 @@ static void Error(const std::string &err, bool usage, bool show_exe_name) {
" --version Print the version number of flatc and exit.\n"
" --strict-json Strict JSON: field names must be / will be quoted,\n"
" no trailing commas in tables/vectors.\n"
" --allow-non-utf8 Pass non-UTF-8 input through parser and emit nonstandard\n"
" \\x escapes in JSON. (Default is to raise parse error on\n"
" non-UTF-8 input.)\n"
" --defaults-json Output fields whose value is the default when\n"
" writing JSON\n"
" --unknown-json Allow fields in JSON that are not defined in the\n"
@@ -184,6 +187,8 @@ int main(int argc, const char *argv[]) {
conform_to_schema = argv[argi];
} else if(arg == "--strict-json") {
opts.strict_json = true;
} else if(arg == "--allow-non-utf8") {
opts.allow_non_utf8 = true;
} else if(arg == "--no-js-exports") {
opts.skip_js_exports = true;
} else if(arg == "--defaults-json") {

View File

@@ -126,7 +126,7 @@ static void NewRootTypeFromBuffer(const StructDef &struct_def,
code += " {\n";
code += "\tn := flatbuffers.GetUOffsetT(buf[offset:])\n";
code += "\tx := &" + struct_def.name + "{}\n";
code += "\tx.Init(buf, n + offset)\n";
code += "\tx.Init(buf, n+offset)\n";
code += "\treturn x\n";
code += "}\n\n";
}
@@ -178,9 +178,10 @@ static void GetScalarFieldOfStruct(const StructDef &struct_def,
std::string getter = GenGetter(field.value.type);
GenReceiver(struct_def, code_ptr);
code += " " + MakeCamel(field.name);
code += "() " + TypeName(field) + " { return " + getter;
code += "() " + TypeName(field) + " {\n";
code +="\treturn " + getter;
code += "(rcv._tab.Pos + flatbuffers.UOffsetT(";
code += NumToString(field.value.offset) + ")) }\n";
code += NumToString(field.value.offset) + "))\n}\n";
}
// Get the value of a table's scalar.
@@ -212,7 +213,7 @@ static void GetStructFieldOfStruct(const StructDef &struct_def,
code += "\tif obj == nil {\n";
code += "\t\tobj = new(" + TypeName(field) + ")\n";
code += "\t}\n";
code += "\tobj.Init(rcv._tab.Bytes, rcv._tab.Pos + ";
code += "\tobj.Init(rcv._tab.Bytes, rcv._tab.Pos+";
code += NumToString(field.value.offset) + ")";
code += "\n\treturn obj\n";
code += "}\n";
@@ -287,9 +288,9 @@ static void GetMemberOfVectorOfStruct(const StructDef &struct_def,
if (!(vectortype.struct_def->fixed)) {
code += "\t\tx = rcv._tab.Indirect(x)\n";
}
code += "\tif obj == nil {\n";
code += "\t\tobj = new(" + TypeName(field) + ")\n";
code += "\t}\n";
code += "\t\tif obj == nil {\n";
code += "\t\t\tobj = new(" + TypeName(field) + ")\n";
code += "\t\t}\n";
code += "\t\tobj.Init(rcv._tab.Bytes, x)\n";
code += "\t\treturn true\n\t}\n";
code += "\treturn false\n";
@@ -310,7 +311,7 @@ static void GetMemberOfVectorOfNonStruct(const StructDef &struct_def,
code += OffsetPrefix(field);
code += "\t\ta := rcv._tab.Vector(o)\n";
code += "\t\treturn " + GenGetter(field.value.type) + "(";
code += "a + flatbuffers.UOffsetT(j * ";
code += "a + flatbuffers.UOffsetT(j*";
code += NumToString(InlineSize(vectortype)) + "))\n";
code += "\t}\n";
if (vectortype.base_type == BASE_TYPE_STRING) {
@@ -326,7 +327,10 @@ static void BeginBuilderArgs(const StructDef &struct_def,
std::string *code_ptr) {
std::string &code = *code_ptr;
code += "\n";
if (code.substr(code.length() - 2) != "\n\n") {
// a previous mutate has not put an extra new line
code += "\n";
}
code += "func Create" + struct_def.name;
code += "(builder *flatbuffers.Builder";
}
@@ -368,20 +372,20 @@ static void StructBuilderBody(const StructDef &struct_def,
const char *nameprefix,
std::string *code_ptr) {
std::string &code = *code_ptr;
code += " builder.Prep(" + NumToString(struct_def.minalign) + ", ";
code += "\tbuilder.Prep(" + NumToString(struct_def.minalign) + ", ";
code += NumToString(struct_def.bytesize) + ")\n";
for (auto it = struct_def.fields.vec.rbegin();
it != struct_def.fields.vec.rend();
++it) {
auto &field = **it;
if (field.padding)
code += " builder.Pad(" + NumToString(field.padding) + ")\n";
code += "\tbuilder.Pad(" + NumToString(field.padding) + ")\n";
if (IsStruct(field.value.type)) {
StructBuilderBody(*field.value.type.struct_def,
(nameprefix + (field.name + "_")).c_str(),
code_ptr);
} else {
code += " builder.Prepend" + GenMethod(field) + "(";
code += "\tbuilder.Prepend" + GenMethod(field) + "(";
code += nameprefix + MakeCamel(field.name, false) + ")\n";
}
}
@@ -389,7 +393,7 @@ static void StructBuilderBody(const StructDef &struct_def,
static void EndBuilderBody(std::string *code_ptr) {
std::string &code = *code_ptr;
code += " return builder.Offset()\n";
code += "\treturn builder.Offset()\n";
code += "}\n";
}
@@ -398,10 +402,10 @@ static void GetStartOfTable(const StructDef &struct_def,
std::string *code_ptr) {
std::string &code = *code_ptr;
code += "func " + struct_def.name + "Start";
code += "(builder *flatbuffers.Builder) { ";
code += "builder.StartObject(";
code += "(builder *flatbuffers.Builder) {\n";
code += "\tbuilder.StartObject(";
code += NumToString(struct_def.fields.vec.size());
code += ") }\n";
code += ")\n}\n";
}
// Set the value of a table's field.
@@ -418,8 +422,8 @@ static void BuildFieldOfTable(const StructDef &struct_def,
} else {
code += GenTypeBasic(field.value.type);
}
code += ") ";
code += "{ builder.Prepend";
code += ") {\n";
code += "\tbuilder.Prepend";
code += GenMethod(field) + "Slot(";
code += NumToString(offset) + ", ";
if (!IsScalar(field.value.type.base_type) && (!struct_def.fixed)) {
@@ -430,7 +434,7 @@ static void BuildFieldOfTable(const StructDef &struct_def,
code += MakeCamel(field.name, false);
}
code += ", " + field.value.constant;
code += ") }\n";
code += ")\n}\n";
}
// Set the value of one of the members of a table's vector.
@@ -441,7 +445,7 @@ static void BuildVectorOfTable(const StructDef &struct_def,
code += "func " + struct_def.name + "Start";
code += MakeCamel(field.name);
code += "Vector(builder *flatbuffers.Builder, numElems int) ";
code += "flatbuffers.UOffsetT { return builder.StartVector(";
code += "flatbuffers.UOffsetT {\n\treturn builder.StartVector(";
auto vector_type = field.value.type.VectorType();
auto alignment = InlineAlignment(vector_type);
auto elem_size = InlineSize(vector_type);
@@ -456,7 +460,7 @@ static void GetEndOffsetOnTable(const StructDef &struct_def,
std::string &code = *code_ptr;
code += "func " + struct_def.name + "End";
code += "(builder *flatbuffers.Builder) flatbuffers.UOffsetT ";
code += "{ return builder.EndObject() }\n";
code += "{\n\treturn builder.EndObject()\n}\n";
}
// Generate the receiver for function signatures.
@@ -521,9 +525,9 @@ static void MutateScalarFieldOfStruct(const StructDef &struct_def,
std::string setter = "rcv._tab.Mutate" + type;
GenReceiver(struct_def, code_ptr);
code += " Mutate" + MakeCamel(field.name);
code += "(n " + TypeName(field) + ") bool { return " + setter;
code += "(rcv._tab.Pos + flatbuffers.UOffsetT(";
code += NumToString(field.value.offset) + "), n) }\n\n";
code += "(n " + TypeName(field) + ") bool {\n\treturn " + setter;
code += "(rcv._tab.Pos+flatbuffers.UOffsetT(";
code += NumToString(field.value.offset) + "), n)\n}\n\n";
}
// Mutate the value of a table's scalar.
@@ -732,7 +736,7 @@ class GoGenerator : public BaseGenerator {
if (needs_imports) {
code += "import (\n";
code += "\tflatbuffers \"github.com/google/flatbuffers/go\"\n";
code += ")\n";
code += ")\n\n";
}
}

View File

@@ -93,7 +93,7 @@ template<typename T> void PrintVector(const Vector<T> &v, Type type,
text += "]";
}
static void EscapeString(const String &s, std::string *_text) {
static void EscapeString(const String &s, std::string *_text, const IDLOptions& opts) {
std::string &text = *_text;
text += "\"";
for (uoffset_t i = 0; i < s.size(); i++) {
@@ -113,17 +113,32 @@ static void EscapeString(const String &s, std::string *_text) {
// 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);
if (ucc < 0) {
if (opts.allow_non_utf8) {
text += "\\x";
text += IntToStringHex(static_cast<uint8_t>(c), 2);
} else {
// We previously checked for non-UTF-8 and returned a parse error,
// so we shouldn't reach here.
assert(0);
}
} else {
if (ucc <= 0xFFFF) {
// Parses as Unicode within JSON's \uXXXX range, so use that.
text += "\\u";
text += IntToStringHex(ucc, 4);
} else if (ucc <= 0x10FFFF) {
// Encode Unicode SMP values to a surrogate pair using two \u escapes.
uint32_t base = ucc - 0x10000;
uint16_t highSurrogate = (base >> 10) + 0xD800;
uint16_t lowSurrogate = (base & 0x03FF) + 0xDC00;
text += "\\u";
text += IntToStringHex(highSurrogate, 4);
text += "\\u";
text += IntToStringHex(lowSurrogate, 4);
}
// Skip past characters recognized.
i = static_cast<uoffset_t>(utf8 - s.c_str() - 1);
} 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;
@@ -157,7 +172,7 @@ template<> void Print<const void *>(const void *val,
_text);
break;
case BASE_TYPE_STRING: {
EscapeString(*reinterpret_cast<const String *>(val), _text);
EscapeString(*reinterpret_cast<const String *>(val), _text, opts);
break;
}
case BASE_TYPE_VECTOR:

View File

@@ -61,6 +61,17 @@ static_assert(BASE_TYPE_UNION ==
#define NEXT() ECHECK(Next())
#define EXPECT(tok) ECHECK(Expect(tok))
static bool ValidateUTF8(const std::string &str) {
const char *s = &str[0];
const char * const sEnd = s + str.length();
while (s < sEnd) {
if (FromUTF8(&s) < 0) {
return false;
}
}
return true;
}
CheckedError Parser::Error(const std::string &msg) {
error_ = file_being_parsed_.length() ? AbsolutePath(file_being_parsed_) : "";
#ifdef _WIN32
@@ -320,6 +331,9 @@ CheckedError Parser::Next() {
"illegal Unicode sequence (unpaired high surrogate)");
}
cursor_++;
if (!opts.allow_non_utf8 && !ValidateUTF8(attribute_)) {
return Error("illegal UTF-8 sequence");
}
token_ = kTokenStringConstant;
return NoError();
}