Merge branch 'arrayapi' into defcleanup

pull/13171/head
Joshua Haberman 6 years ago
commit e13e1c46ae
  1. 2
      tests/pb/test_decoder.cc
  2. 751
      tools/dump_cinit.lua
  3. 2
      upb/def.c
  4. 577
      upb/json/parser.c
  5. 161
      upb/json/parser.rl
  6. 73
      upb/json/printer.c
  7. 4
      upb/pb/compile_decoder.c
  8. 1
      upb/upb.h

@ -980,7 +980,7 @@ void test_valid() {
LINE("%u:{")
LINE(" <")
LINE(" %u:(5)\"abcde")
LINE(" %u:\"")
LINE(" %u:\"")
LINE(" >")
LINE("}")
LINE(">"), msg_fn, UPB_DESCRIPTOR_TYPE_STRING,

@ -0,0 +1,751 @@
--[[
Routines for dumping internal data structures into C initializers
that can be compiled into a .o file.
--]]
local upbtable = require "upb.table"
local upb = require "upb"
local export = {}
-- A tiny little abstraction that decouples the dump_* functions from
-- what they're writing to (appending to a string, writing to file I/O, etc).
-- This could possibly matter since naive string building is O(n^2) in the
-- number of appends.
function export.str_appender()
local str = ""
local function append(fmt, ...)
str = str .. string.format(fmt, ...)
end
local function get()
return str
end
return append, get
end
function export.file_appender(file)
local f = file
local function append(fmt, ...)
f:write(string.format(fmt, ...))
end
return append
end
function handler_types(base)
local ret = {}
for k, _ in pairs(base) do
if string.find(k, "^" .. "HANDLER_") then
ret[#ret + 1] = k
end
end
return ret
end
function octchar(num)
assert(num < 8)
local idx = num + 1 -- 1-based index
return string.sub("01234567", idx, idx)
end
function c_escape(num)
assert(num < 256)
return string.format("\\%s%s%s",
octchar(math.floor(num / 64)),
octchar(math.floor(num / 8) % 8),
octchar(num % 8));
end
-- const(f, label) -> UPB_LABEL_REPEATED, where f:label() == upb.LABEL_REPEATED
function const(obj, name, base)
local val = obj[name]
base = base or upb
-- Support both f:label() and f.label.
if type(val) == "function" then
val = val(obj)
end
for k, v in pairs(base) do
if v == val and string.find(k, "^" .. string.upper(name)) then
return "UPB_" .. k
end
end
assert(false, "Couldn't find UPB_" .. string.upper(name) ..
" constant for value: " .. val)
end
function sortedkeys(tab)
arr = {}
for key in pairs(tab) do
arr[#arr + 1] = key
end
table.sort(arr)
return arr
end
function sorted_defs(defs)
local sorted = {}
for def in defs do
if def.type == deftype then
sorted[#sorted + 1] = def
end
end
table.sort(sorted,
function(a, b) return a:full_name() < b:full_name() end)
return sorted
end
function constlist(pattern)
local ret = {}
for k, v in pairs(upb) do
if string.find(k, "^" .. pattern) then
ret[k] = v
end
end
return ret
end
function boolstr(val)
if val == true then
return "true"
elseif val == false then
return "false"
else
assert(false, "Bad bool value: " .. tostring(val))
end
end
--[[
LinkTable: an object that tracks all linkable objects and their offsets to
facilitate linking.
--]]
local LinkTable = {}
function LinkTable:new(types)
local linktab = {
types = types,
table = {}, -- ptr -> {type, 0-based offset}
obj_arrays = {} -- Establishes the ordering for each object type
}
for type, _ in pairs(types) do
linktab.obj_arrays[type] = {}
end
setmetatable(linktab, {__index = LinkTable}) -- Inheritance
return linktab
end
-- Adds a new object to the sequence of objects of this type.
function LinkTable:add(objtype, ptr, obj)
obj = obj or ptr
assert(self.table[obj] == nil)
assert(self.types[objtype])
local arr = self.obj_arrays[objtype]
self.table[ptr] = {objtype, #arr}
arr[#arr + 1] = obj
end
-- Returns a C symbol name for the given objtype and offset.
function LinkTable:csym(objtype, offset)
local typestr = assert(self.types[objtype])
return string.format("%s[%d]", typestr, offset)
end
-- Returns the address of the given C object.
function LinkTable:addr(obj)
if obj == upbtable.NULL then
return "NULL"
else
local tabent = assert(self.table[obj], "unknown object: " .. tostring(obj))
return "&" .. self:csym(tabent[1], tabent[2])
end
end
-- Returns an array declarator indicating how many objects have been added.
function LinkTable:cdecl(objtype)
return self:csym(objtype, #self.obj_arrays[objtype])
end
function LinkTable:objs(objtype)
-- Return iterator function, allowing use as:
-- for obj in linktable:objs(type) do
-- -- ...
-- done
local array = self.obj_arrays[objtype]
local i = 0
return function()
i = i + 1
if array[i] then return array[i] end
end
end
function LinkTable:empty(objtype)
return #self.obj_arrays[objtype] == 0
end
--[[
Dumper: an object that can dump C initializers for several constructs.
Uses a LinkTable to resolve references when necessary.
--]]
local Dumper = {}
function Dumper:new(linktab)
local obj = {linktab = linktab}
setmetatable(obj, {__index = Dumper}) -- Inheritance
return obj
end
-- Dumps a upb_tabval, eg:
-- UPB_TABVALUE_INIT(5)
function Dumper:_value(val, upbtype)
if type(val) == "nil" then
return "UPB_TABVALUE_EMPTY_INIT"
elseif type(val) == "number" then
-- Use upbtype to disambiguate what kind of number it is.
if upbtype == upbtable.CTYPE_INT32 then
return string.format("UPB_TABVALUE_INT_INIT(%d)", val)
else
-- TODO(haberman): add support for these so we can properly support
-- default values.
error("Unsupported number type " .. upbtype)
end
elseif type(val) == "string" then
return string.format('UPB_TABVALUE_PTR_INIT("%s")', val)
else
-- We take this as an object reference that has an entry in the link table.
return string.format("UPB_TABVALUE_PTR_INIT(%s)", self.linktab:addr(val))
end
end
-- Dumps a table key.
function Dumper:tabkey(key)
if type(key) == "nil" then
return "UPB_TABKEY_NONE"
elseif type(key) == "string" then
local len = #key
local len1 = c_escape(len % 256)
local len2 = c_escape(math.floor(len / 256) % 256)
local len3 = c_escape(math.floor(len / (256 * 256)) % 256)
local len4 = c_escape(math.floor(len / (256 * 256 * 256)) % 256)
return string.format('UPB_TABKEY_STR("%s", "%s", "%s", "%s", "%s")',
len1, len2, len3, len4, key)
else
return string.format("UPB_TABKEY_NUM(%d)", key)
end
end
-- Dumps a table entry.
function Dumper:tabent(ent)
local key = self:tabkey(ent.key)
local val = self:_value(ent.value, ent.valtype)
local next = self.linktab:addr(ent.next)
return string.format(' {%s, %s, %s},\n', key, val, next)
end
-- Dumps an inttable array entry. This is almost the same as value() above,
-- except that nil values have a special value to indicate "empty".
function Dumper:arrayval(val)
if val.val then
return string.format(" %s,\n", self:_value(val.val, val.valtype))
else
return " UPB_TABVALUE_EMPTY_INIT,\n"
end
end
-- Dumps an initializer for the given strtable/inttable (respectively). Its
-- entries must have previously been added to the linktable.
function Dumper:strtable(t)
-- UPB_STRTABLE_INIT(count, mask, type, size_lg2, entries)
return string.format(
"UPB_STRTABLE_INIT(%d, %d, %s, %d, %s)",
t.count, t.mask, const(t, "ctype", upbtable) , t.size_lg2,
self.linktab:addr(t.entries[1].ptr))
end
function Dumper:inttable(t)
local lt = assert(self.linktab)
-- UPB_INTTABLE_INIT(count, mask, type, size_lg2, ent, a, asize, acount)
local entries = "NULL"
if #t.entries > 0 then
entries = lt:addr(t.entries[1].ptr)
end
return string.format(
"UPB_INTTABLE_INIT(%d, %d, %s, %d, %s, %s, %d, %d)",
t.count, t.mask, const(t, "ctype", upbtable), t.size_lg2, entries,
lt:addr(t.array[1].ptr), t.array_size, t.array_count)
end
-- A visitor for visiting all tables of a def. Used first to count entries
-- and later to dump them.
local function gettables(def)
if def:def_type() == upb.DEF_MSG then
return {int = upbtable.msgdef_itof(def), str = upbtable.msgdef_ntof(def)}
elseif def:def_type() == upb.DEF_ENUM then
return {int = upbtable.enumdef_iton(def), str = upbtable.enumdef_ntoi(def)}
end
end
local function emit_file_warning(filedef, append)
append('/* This file was generated by upbc (the upb compiler) from the input\n')
append(' * file:\n')
append(' *\n')
append(' * %s\n', filedef:name())
append(' *\n')
append(' * Do not edit -- your changes will be discarded when the file is\n')
append(' * regenerated. */\n\n')
end
local function join(...)
return table.concat({...}, ".")
end
local function split(str)
local ret = {}
for word in string.gmatch(str, "%w+") do
table.insert(ret, word)
end
return ret
end
local function to_cident(...)
return string.gsub(join(...), "[%./]", "_")
end
local function to_preproc(...)
return string.upper(to_cident(...))
end
-- Strips away last path element, ie:
-- foo.Bar.Baz -> foo.Bar
local function remove_name(name)
local package_end = 0
for i=1,string.len(name) do
if string.byte(name, i) == string.byte(".", 1) then
package_end = i - 1
end
end
return string.sub(name, 1, package_end)
end
local function start_namespace(package, append)
local package_components = split(package)
for _, component in ipairs(package_components) do
append("namespace %s {\n", component)
end
end
local function end_namespace(package, append)
local package_components = split(package)
for i=#package_components,1,-1 do
append("} /* namespace %s */\n", package_components[i])
end
end
local function well_known_type(m)
local type_map = {}
type_map["google.protobuf.Any"] = "UPB_WELLKNOWN_ANY"
type_map["google.protobuf.FieldMask"] = "UPB_WELLKNOWN_FIELDMASK"
type_map["google.protobuf.Duration"] = "UPB_WELLKNOWN_DURATION"
type_map["google.protobuf.Timestamp"] = "UPB_WELLKNOWN_TIMESTAMP"
type_map["google.protobuf.Value"] = "UPB_WELLKNOWN_VALUE"
type_map["google.protobuf.ListValue"] = "UPB_WELLKNOWN_LISTVALUE"
type_map["google.protobuf.Struct"] = "UPB_WELLKNOWN_STRUCT"
type_map["google.protobuf.DoubleValue"] = "UPB_WELLKNOWN_DOUBLEVALUE"
type_map["google.protobuf.FloatValue"] = "UPB_WELLKNOWN_FLOATVALUE"
type_map["google.protobuf.Int64Value"] = "UPB_WELLKNOWN_INT64VALUE"
type_map["google.protobuf.UInt64Value"] = "UPB_WELLKNOWN_UINT64VALUE"
type_map["google.protobuf.Int32Value"] = "UPB_WELLKNOWN_INT32VALUE"
type_map["google.protobuf.UInt32Value"] = "UPB_WELLKNOWN_UINT32VALUE"
type_map["google.protobuf.BoolValue"] = "UPB_WELLKNOWN_BOOLVALUE"
type_map["google.protobuf.StringValue"] = "UPB_WELLKNOWN_STRINGVALUE"
type_map["google.protobuf.BytesValue"] = "UPB_WELLKNOWN_BYTESVALUE"
local t = type_map[m:full_name()]
if (t == nil) then
t = "UPB_WELLKNOWN_UNSPECIFIED"
end
return t
end
--[[
Top-level, exported dumper functions
--]]
local function dump_defs_c(filedef, append)
local defs = {}
for def in filedef:defs(upb.DEF_ANY) do
defs[#defs + 1] = def
if (def:def_type() == upb.DEF_MSG) then
for field in def:fields() do
defs[#defs + 1] = field
end
end
end
-- Sort all defs by (type, name).
-- This gives us a linear ordering that we can use to create offsets into
-- shared arrays like REFTABLES, hash table entries, and arrays.
table.sort(defs, function(a, b)
if a:def_type() ~= b:def_type() then
return a:def_type() < b:def_type()
else
return a:full_name() < b:full_name() end
end
)
-- Perform pre-pass to build the link table.
local linktab = LinkTable:new{
[upb.DEF_MSG] = "msgs",
[upb.DEF_FIELD] = "fields",
[upb.DEF_ENUM] = "enums",
intentries = "intentries",
strentries = "strentries",
arrays = "arrays",
}
local reftable_count = 0
for _, def in ipairs(defs) do
assert(def:is_frozen(), "can only dump frozen defs.")
linktab:add(def:def_type(), def)
reftable_count = reftable_count + 2
local tables = gettables(def)
if tables then
for _, e in ipairs(tables.str.entries) do
linktab:add("strentries", e.ptr, e)
end
for _, e in ipairs(tables.int.entries) do
linktab:add("intentries", e.ptr, e)
end
for _, e in ipairs(tables.int.array) do
linktab:add("arrays", e.ptr, e)
end
end
end
-- Emit forward declarations.
emit_file_warning(filedef, append)
append('#include "upb/def.h"\n')
append('#include "upb/structdefs.int.h"\n\n')
append("static const upb_msgdef %s;\n", linktab:cdecl(upb.DEF_MSG))
append("static const upb_fielddef %s;\n", linktab:cdecl(upb.DEF_FIELD))
if not linktab:empty(upb.DEF_ENUM) then
append("static const upb_enumdef %s;\n", linktab:cdecl(upb.DEF_ENUM))
end
append("static const upb_tabent %s;\n", linktab:cdecl("strentries"))
if not linktab:empty("intentries") then
append("static const upb_tabent %s;\n", linktab:cdecl("intentries"))
end
append("static const upb_tabval %s;\n", linktab:cdecl("arrays"))
append("\n")
append("#ifdef UPB_DEBUG_REFS\n")
append("static upb_inttable reftables[%d];\n", reftable_count)
append("#endif\n")
append("\n")
-- Emit defs.
local dumper = Dumper:new(linktab)
local reftable = 0
append("static const upb_msgdef %s = {\n", linktab:cdecl(upb.DEF_MSG))
for m in linktab:objs(upb.DEF_MSG) do
local tables = gettables(m)
-- UPB_MSGDEF_INIT(name, selector_count, submsg_field_count, itof, ntof,
-- refs, ref2s)
append(' UPB_MSGDEF_INIT("%s", %d, %d, %s, %s, %s, %s, %s,' ..
' &reftables[%d], &reftables[%d]),\n',
m:full_name(),
upbtable.msgdef_selector_count(m),
upbtable.msgdef_submsg_field_count(m),
dumper:inttable(tables.int),
dumper:strtable(tables.str),
boolstr(m:_map_entry()),
const(m, "syntax"),
well_known_type(m),
reftable, reftable + 1)
reftable = reftable + 2
end
append("};\n\n")
append("static const upb_fielddef %s = {\n", linktab:cdecl(upb.DEF_FIELD))
for f in linktab:objs(upb.DEF_FIELD) do
local subdef = "NULL"
if f:has_subdef() then
subdef = string.format("(const upb_def*)(%s)", linktab:addr(f:subdef()))
end
local intfmt
if f:type() == upb.TYPE_UINT32 or
f:type() == upb.TYPE_INT32 or
f:type() == upb.TYPE_UINT64 or
f:type() == upb.TYPE_INT64 then
intfmt = const(f, "intfmt")
else
intfmt = "0"
end
-- UPB_FIELDDEF_INIT(label, type, intfmt, tagdelim, is_extension, lazy,
-- packed, name, num, msgdef, subdef, selector_base,
-- index, -- default_value)
append(' UPB_FIELDDEF_INIT(%s, %s, %s, %s, %s, %s, %s, "%s", %d, %s, ' ..
'%s, %d, %d, {0},' .. -- TODO: support default value
'&reftables[%d], &reftables[%d]),\n',
const(f, "label"), const(f, "type"), intfmt,
boolstr(f:istagdelim()), boolstr(f:is_extension()),
boolstr(f:lazy()), boolstr(f:packed()), f:name(), f:number(),
linktab:addr(f:containing_type()), subdef,
upbtable.fielddef_selector_base(f), f:index(),
reftable, reftable + 1
)
reftable = reftable + 2
end
append("};\n\n")
if not linktab:empty(upb.DEF_ENUM) then
append("static const upb_enumdef %s = {\n", linktab:cdecl(upb.DEF_ENUM))
for e in linktab:objs(upb.DEF_ENUM) do
local tables = gettables(e)
-- UPB_ENUMDEF_INIT(name, ntoi, iton, defaultval)
append(' UPB_ENUMDEF_INIT("%s", %s, %s, %d, ' ..
'&reftables[%d], &reftables[%d]),\n',
e:full_name(),
dumper:strtable(tables.str),
dumper:inttable(tables.int),
--e:default())
0,
reftable, reftable + 1)
reftable = reftable + 2
end
append("};\n\n")
end
append("static const upb_tabent %s = {\n", linktab:cdecl("strentries"))
for ent in linktab:objs("strentries") do
append(dumper:tabent(ent))
end
append("};\n\n");
if not linktab:empty("intentries") then
append("static const upb_tabent %s = {\n", linktab:cdecl("intentries"))
for ent in linktab:objs("intentries") do
append(dumper:tabent(ent))
end
append("};\n\n");
end
append("static const upb_tabval %s = {\n", linktab:cdecl("arrays"))
for ent in linktab:objs("arrays") do
append(dumper:arrayval(ent))
end
append("};\n\n");
append("#ifdef UPB_DEBUG_REFS\n")
append("static upb_inttable reftables[%d] = {\n", reftable_count)
for i = 1,reftable_count do
append(" UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),\n")
end
append("};\n")
append("#endif\n\n")
append("static const upb_msgdef *refm(const upb_msgdef *m, const void *owner) {\n")
append(" upb_msgdef_ref(m, owner);\n")
append(" return m;\n")
append("}\n\n")
append("static const upb_enumdef *refe(const upb_enumdef *e, const void *owner) {\n")
append(" upb_enumdef_ref(e, owner);\n")
append(" return e;\n")
append("}\n\n")
append("/* Public API. */\n")
for m in linktab:objs(upb.DEF_MSG) do
append("const upb_msgdef *upbdefs_%s_get(const void *owner)" ..
" { return refm(%s, owner); }\n",
to_cident(m:full_name()), linktab:addr(m))
end
append("\n")
for e in linktab:objs(upb.DEF_ENUM) do
append("const upb_enumdef *upbdefs_%s_get(const void *owner)" ..
" { return refe(%s, owner); }\n",
to_cident(e:full_name()), linktab:addr(e))
end
return linktab
end
local function dump_defs_for_type(format, defs, append)
local sorted = sorted_defs(defs)
for _, def in ipairs(sorted) do
append(format, to_cident(def:full_name()), def:full_name())
end
append("\n")
end
local function make_children_map(file)
-- Maps file:package() or msg:full_name() -> children.
local map = {}
for def in file:defs(upb.DEF_ANY) do
local container = remove_name(def:full_name())
if not map[container] then
map[container] = {}
end
table.insert(map[container], def)
end
-- Sort all the lists for a consistent ordering.
for name, children in pairs(map) do
table.sort(children, function(a, b) return a:name() < b:name() end)
end
return map
end
local print_classes
local function print_message(def, map, indent, append)
append("\n")
append("%sclass %s : public ::upb::reffed_ptr<const ::upb::MessageDef> {\n",
indent, def:name())
append("%s public:\n", indent)
append("%s %s(const ::upb::MessageDef* m, const void *ref_donor = NULL)\n",
indent, def:name())
append("%s : reffed_ptr(m, ref_donor) {\n", indent)
append("%s UPB_ASSERT(upbdefs_%s_is(m));\n", indent, to_cident(def:full_name()))
append("%s }\n", indent)
append("\n")
append("%s static %s get() {\n", indent, def:name())
append("%s const ::upb::MessageDef* m = upbdefs_%s_get(&m);\n", indent, to_cident(def:full_name()))
append("%s return %s(m, &m);\n", indent, def:name())
append("%s }\n", indent)
-- TODO(haberman): add fields
print_classes(def:full_name(), map, indent .. " ", append)
append("%s};\n", indent)
end
local function print_enum(def, indent, append)
append("\n")
append("%sclass %s : public ::upb::reffed_ptr<const ::upb::EnumDef> {\n",
indent, def:name())
append("%s public:\n", indent)
append("%s %s(const ::upb::EnumDef* e, const void *ref_donor = NULL)\n",
indent, def:name())
append("%s : reffed_ptr(e, ref_donor) {\n", indent)
append("%s UPB_ASSERT(upbdefs_%s_is(e));\n", indent, to_cident(def:full_name()))
append("%s }\n", indent)
append("%s static %s get() {\n", indent, def:name())
append("%s const ::upb::EnumDef* e = upbdefs_%s_get(&e);\n", indent, to_cident(def:full_name()))
append("%s return %s(e, &e);\n", indent, def:name())
append("%s }\n", indent)
append("%s};\n", indent)
end
function print_classes(name, map, indent, append)
if not map[name] then
return
end
for _, def in ipairs(map[name]) do
if def:def_type() == upb.DEF_MSG then
print_message(def, map, indent, append)
elseif def:def_type() == upb.DEF_ENUM then
print_enum(def, indent, append)
else
error("Unknown def type for " .. def:full_name())
end
end
end
local function dump_defs_h(file, append, linktab)
local basename_preproc = to_preproc(file:name())
append("/* This file contains accessors for a set of compiled-in defs.\n")
append(" * Note that unlike Google's protobuf, it does *not* define\n")
append(" * generated classes or any other kind of data structure for\n")
append(" * actually storing protobufs. It only contains *defs* which\n")
append(" * let you reflect over a protobuf *schema*.\n")
append(" */\n")
emit_file_warning(file, append)
append('#ifndef %s_UPB_H_\n', basename_preproc)
append('#define %s_UPB_H_\n\n', basename_preproc)
append('#include "upb/def.h"\n\n')
append('UPB_BEGIN_EXTERN_C\n\n')
-- Dump C enums for proto enums.
append("/* MessageDefs: call these functions to get a ref to a msgdef. */\n")
dump_defs_for_type(
"const upb_msgdef *upbdefs_%s_get(const void *owner);\n",
file:defs(upb.DEF_MSG), append)
append("/* EnumDefs: call these functions to get a ref to an enumdef. */\n")
dump_defs_for_type(
"const upb_enumdef *upbdefs_%s_get(const void *owner);\n",
file:defs(upb.DEF_ENUM), append)
append("/* Functions to test whether this message is of a certain type. */\n")
dump_defs_for_type(
"UPB_INLINE bool upbdefs_%s_is(const upb_msgdef *m) {\n" ..
" return strcmp(upb_msgdef_fullname(m), \"%s\") == 0;\n}\n",
file:defs(upb.DEF_MSG), append)
append("/* Functions to test whether this enum is of a certain type. */\n")
dump_defs_for_type(
"UPB_INLINE bool upbdefs_%s_is(const upb_enumdef *e) {\n" ..
" return strcmp(upb_enumdef_fullname(e), \"%s\") == 0;\n}\n",
file:defs(upb.DEF_ENUM), append)
append("\n")
-- fields
local fields = {}
for f in linktab:objs(upb.DEF_FIELD) do
local symname = f:containing_type():full_name() .. "." .. f:name()
fields[#fields + 1] = {to_cident(symname), f}
end
table.sort(fields, function(a, b) return a[1] < b[1] end)
append("/* Functions to get a fielddef from a msgdef reference. */\n")
for _, field in ipairs(fields) do
local f = field[2]
local msg_cident = to_cident(f:containing_type():full_name())
local field_cident = to_cident(f:name())
append("UPB_INLINE const upb_fielddef *upbdefs_%s_f_%s(const upb_msgdef *m) {" ..
" UPB_ASSERT(upbdefs_%s_is(m));" ..
" return upb_msgdef_itof(m, %d); }\n",
msg_cident, field_cident, msg_cident, f:number())
end
append('\nUPB_END_EXTERN_C\n\n')
-- C++ wrappers.
local children_map = make_children_map(file)
append("#ifdef __cplusplus\n\n")
append("namespace upbdefs {\n")
start_namespace(file:package(), append)
print_classes(file:package(), children_map, "", append)
append("\n")
end_namespace(file:package(), append)
append("} /* namespace upbdefs */\n\n")
append("#endif /* __cplusplus */\n")
append("\n")
append('#endif /* %s_UPB_H_ */\n', basename_preproc)
end
function export.dump_defs(filedef, append_h, append_c)
local linktab = dump_defs_c(filedef, append_c)
dump_defs_h(filedef, append_h, linktab)
end
return export

@ -311,6 +311,8 @@ static void assign_msg_wellknowntype(upb_msgdef *m) {
}
if (!strcmp(name, "google.protobuf.Any")) {
m->well_known_type = UPB_WELLKNOWN_ANY;
} else if (!strcmp(name, "google.protobuf.FieldMask")) {
m->well_known_type = UPB_WELLKNOWN_FIELDMASK;
} else if (!strcmp(name, "google.protobuf.Duration")) {
m->well_known_type = UPB_WELLKNOWN_DURATION;
} else if (!strcmp(name, "google.protobuf.Timestamp")) {

@ -63,6 +63,12 @@ static bool is_string_wrapper_object(upb_json_parser *p);
static bool does_string_wrapper_start(upb_json_parser *p);
static bool does_string_wrapper_end(upb_json_parser *p);
static bool is_fieldmask_object(upb_json_parser *p);
static bool does_fieldmask_start(upb_json_parser *p);
static bool does_fieldmask_end(upb_json_parser *p);
static void start_fieldmask_object(upb_json_parser *p);
static void end_fieldmask_object(upb_json_parser *p);
static void start_wrapper_object(upb_json_parser *p);
static void end_wrapper_object(upb_json_parser *p);
@ -1164,6 +1170,9 @@ static bool start_stringval(upb_json_parser *p) {
if (is_top_level(p)) {
if (is_string_wrapper_object(p)) {
start_wrapper_object(p);
} else if (is_wellknown_msg(p, UPB_WELLKNOWN_FIELDMASK)) {
start_fieldmask_object(p);
return true;
} else if (is_wellknown_msg(p, UPB_WELLKNOWN_TIMESTAMP) ||
is_wellknown_msg(p, UPB_WELLKNOWN_DURATION)) {
start_object(p);
@ -1177,6 +1186,12 @@ static bool start_stringval(upb_json_parser *p) {
return false;
}
start_wrapper_object(p);
} else if (does_fieldmask_start(p)) {
if (!start_subobject(p)) {
return false;
}
start_fieldmask_object(p);
return true;
} else if (is_wellknown_field(p, UPB_WELLKNOWN_TIMESTAMP) ||
is_wellknown_field(p, UPB_WELLKNOWN_DURATION)) {
if (!start_subobject(p)) {
@ -1317,8 +1332,13 @@ static bool end_stringval_nontop(upb_json_parser *p) {
case UPB_TYPE_STRING: {
upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR);
<<<<<<< HEAD
p->top--;
upb_sink_endstr(p->top->sink, sel);
=======
upb_sink_endstr(&p->top->sink, sel);
p->top--;
>>>>>>> arrayapi
break;
}
@ -1364,6 +1384,16 @@ static bool end_stringval_nontop(upb_json_parser *p) {
}
static bool end_stringval(upb_json_parser *p) {
/* FieldMask's stringvals have been ended when handling them. Only need to
* close FieldMask here.*/
if (does_fieldmask_end(p)) {
end_fieldmask_object(p);
if (!is_top_level(p)) {
end_subobject(p);
}
return true;
}
if (!end_stringval_nontop(p)) {
return false;
}
@ -1385,7 +1415,8 @@ static bool end_stringval(upb_json_parser *p) {
}
if (is_wellknown_msg(p, UPB_WELLKNOWN_TIMESTAMP) ||
is_wellknown_msg(p, UPB_WELLKNOWN_DURATION)) {
is_wellknown_msg(p, UPB_WELLKNOWN_DURATION) ||
is_wellknown_msg(p, UPB_WELLKNOWN_FIELDMASK)) {
end_object(p);
if (!is_top_level(p)) {
end_subobject(p);
@ -1639,6 +1670,75 @@ static bool end_timestamp_zone(upb_json_parser *p, const char *ptr) {
return true;
}
static void start_fieldmask_path_text(upb_json_parser *p, const char *ptr) {
capture_begin(p, ptr);
}
static bool end_fieldmask_path_text(upb_json_parser *p, const char *ptr) {
if (!capture_end(p, ptr)) {
return false;
}
}
static bool start_fieldmask_path(upb_json_parser *p) {
upb_jsonparser_frame *inner;
upb_selector_t sel;
if (!check_stack(p)) return false;
/* Start a new parser frame: parser frames correspond one-to-one with
* handler frames, and string events occur in a sub-frame. */
inner = p->top + 1;
sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSTR);
upb_sink_startstr(&p->top->sink, sel, 0, &inner->sink);
inner->m = p->top->m;
inner->f = p->top->f;
inner->name_table = NULL;
inner->is_map = false;
inner->is_mapentry = false;
inner->is_any = false;
inner->any_frame = NULL;
inner->is_unknown_field = false;
p->top = inner;
multipart_startaccum(p);
return true;
}
static bool lower_camel_push(
upb_json_parser *p, upb_selector_t sel, const char *ptr, size_t len) {
const char *limit = ptr + len;
bool first = true;
for (;ptr < limit; ptr++) {
if (*ptr >= 'A' && *ptr <= 'Z' && !first) {
char lower = tolower(*ptr);
upb_sink_putstring(&p->top->sink, sel, "_", 1, NULL);
upb_sink_putstring(&p->top->sink, sel, &lower, 1, NULL);
} else {
upb_sink_putstring(&p->top->sink, sel, ptr, 1, NULL);
}
first = false;
}
return true;
}
static bool end_fieldmask_path(upb_json_parser *p) {
upb_selector_t sel;
if (!lower_camel_push(
p, getsel_for_handlertype(p, UPB_HANDLER_STRING),
p->accumulated, p->accumulated_len)) {
return false;
}
sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR);
upb_sink_endstr(&p->top->sink, sel);
p->top--;
multipart_end(p);
return true;
}
static void start_member(upb_json_parser *p) {
UPB_ASSERT(!p->top->f);
multipart_startaccum(p);
@ -1696,7 +1796,11 @@ static bool parse_mapentry_key(upb_json_parser *p) {
sel = getsel_for_handlertype(p, UPB_HANDLER_STRING);
upb_sink_putstring(subsink, sel, buf, len, NULL);
sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR);
<<<<<<< HEAD
upb_sink_endstr(p->top->sink, sel);
=======
upb_sink_endstr(&subsink, sel);
>>>>>>> arrayapi
multipart_end(p);
break;
}
@ -2221,6 +2325,31 @@ static bool is_string_wrapper(const upb_msgdef *m) {
type == UPB_WELLKNOWN_BYTESVALUE;
}
static bool is_fieldmask(const upb_msgdef *m) {
upb_wellknowntype_t type = upb_msgdef_wellknowntype(m);
return type == UPB_WELLKNOWN_FIELDMASK;
}
static void start_fieldmask_object(upb_json_parser *p) {
const char *membername = "paths";
start_object(p);
/* Set up context for parsing value */
start_member(p);
capture_begin(p, membername);
capture_end(p, membername + 5);
end_membername(p);
start_array(p);
}
static void end_fieldmask_object(upb_json_parser *p) {
end_array(p);
end_member(p);
end_object(p);
}
static void start_wrapper_object(upb_json_parser *p) {
const char *membername = "value";
@ -2359,6 +2488,20 @@ static bool is_string_wrapper_object(upb_json_parser *p) {
return p->top->m != NULL && is_string_wrapper(p->top->m);
}
static bool does_fieldmask_start(upb_json_parser *p) {
return p->top->f != NULL &&
upb_fielddef_issubmsg(p->top->f) &&
is_fieldmask(upb_fielddef_msgsubdef(p->top->f));
}
static bool does_fieldmask_end(upb_json_parser *p) {
return p->top->m != NULL && is_fieldmask(p->top->m);
}
static bool is_fieldmask_object(upb_json_parser *p) {
return p->top->m != NULL && is_fieldmask(p->top->m);
}
#define CHECK_RETURN_TOP(x) if (!(x)) goto error
@ -2380,26 +2523,35 @@ static bool is_string_wrapper_object(upb_json_parser *p) {
* final state once, when the closing '"' is seen. */
<<<<<<< HEAD
#line 2542 "upb/json/parser.rl"
#line 2388 "upb/json/parser.c"
=======
#line 2730 "upb/json/parser.rl"
#line 2556 "upb/json/parser.c"
>>>>>>> arrayapi
static const char _json_actions[] = {
0, 1, 0, 1, 1, 1, 3, 1,
4, 1, 6, 1, 7, 1, 8, 1,
9, 1, 10, 1, 11, 1, 12, 1,
13, 1, 21, 1, 23, 1, 24, 1,
26, 1, 27, 1, 28, 1, 30, 1,
32, 1, 33, 1, 34, 1, 35, 1,
37, 1, 38, 2, 4, 9, 2, 5,
6, 2, 7, 3, 2, 7, 9, 2,
14, 15, 2, 16, 17, 2, 18, 19,
2, 22, 20, 2, 24, 26, 2, 29,
2, 2, 30, 38, 2, 31, 20, 2,
33, 38, 2, 34, 38, 2, 35, 38,
2, 36, 25, 2, 37, 38, 4, 14,
15, 16, 17
13, 1, 24, 1, 26, 1, 28, 1,
29, 1, 31, 1, 32, 1, 33, 1,
35, 1, 37, 1, 38, 1, 39, 1,
40, 1, 42, 1, 43, 2, 4, 9,
2, 5, 6, 2, 7, 3, 2, 7,
9, 2, 14, 15, 2, 16, 17, 2,
18, 19, 2, 21, 23, 2, 22, 20,
2, 27, 25, 2, 29, 31, 2, 34,
2, 2, 35, 43, 2, 36, 25, 2,
38, 43, 2, 39, 43, 2, 40, 43,
2, 41, 30, 2, 42, 43, 3, 21,
23, 24, 4, 14, 15, 16, 17
};
static const short _json_key_offsets[] = {
@ -2412,12 +2564,12 @@ static const short _json_key_offsets[] = {
156, 158, 160, 162, 163, 165, 167, 168,
170, 172, 173, 175, 177, 178, 180, 182,
183, 185, 187, 191, 193, 195, 196, 197,
198, 199, 201, 206, 215, 216, 216, 216,
221, 226, 231, 232, 233, 234, 235, 235,
236, 237, 238, 238, 239, 240, 241, 241,
246, 247, 251, 256, 261, 266, 270, 270,
273, 276, 279, 282, 285, 288, 288, 288,
288, 288
198, 199, 201, 206, 208, 210, 212, 221,
222, 222, 222, 227, 232, 237, 238, 239,
240, 241, 241, 242, 243, 244, 244, 245,
246, 247, 247, 252, 253, 257, 262, 267,
272, 276, 276, 279, 282, 285, 288, 291,
294, 294, 294, 294, 294, 294
};
static const char _json_trans_keys[] = {
@ -2446,18 +2598,18 @@ static const char _json_trans_keys[] = {
57, 58, 48, 57, 48, 57, 58, 48,
57, 48, 57, 43, 45, 46, 90, 48,
57, 48, 57, 58, 48, 48, 34, 48,
57, 43, 45, 90, 48, 57, 34, 45,
91, 102, 110, 116, 123, 48, 57, 34,
32, 93, 125, 9, 13, 32, 44, 93,
9, 13, 32, 93, 125, 9, 13, 97,
108, 115, 101, 117, 108, 108, 114, 117,
101, 32, 34, 125, 9, 13, 34, 32,
58, 9, 13, 32, 93, 125, 9, 13,
32, 44, 125, 9, 13, 32, 44, 125,
9, 13, 32, 34, 9, 13, 32, 9,
13, 32, 9, 13, 32, 9, 13, 32,
57, 43, 45, 90, 48, 57, 34, 44,
34, 44, 34, 44, 34, 45, 91, 102,
110, 116, 123, 48, 57, 34, 32, 93,
125, 9, 13, 32, 44, 93, 9, 13,
32, 93, 125, 9, 13, 97, 108, 115,
101, 117, 108, 108, 114, 117, 101, 32,
34, 125, 9, 13, 34, 32, 58, 9,
13, 32, 93, 125, 9, 13, 32, 44,
125, 9, 13, 32, 44, 125, 9, 13,
32, 34, 9, 13, 32, 9, 13, 32,
9, 13, 32, 9, 13, 32, 9, 13,
0
32, 9, 13, 32, 9, 13, 0
};
static const char _json_single_lengths[] = {
@ -2470,12 +2622,12 @@ static const char _json_single_lengths[] = {
0, 0, 0, 1, 0, 0, 1, 0,
0, 1, 0, 0, 1, 0, 0, 1,
0, 0, 4, 0, 0, 1, 1, 1,
1, 0, 3, 7, 1, 0, 0, 3,
3, 3, 1, 1, 1, 1, 0, 1,
1, 1, 0, 1, 1, 1, 0, 3,
1, 2, 3, 3, 3, 2, 0, 1,
1, 1, 1, 1, 1, 0, 0, 0,
0, 0
1, 0, 3, 2, 2, 2, 7, 1,
0, 0, 3, 3, 3, 1, 1, 1,
1, 0, 1, 1, 1, 0, 1, 1,
1, 0, 3, 1, 2, 3, 3, 3,
2, 0, 1, 1, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0
};
static const char _json_range_lengths[] = {
@ -2488,12 +2640,12 @@ static const char _json_range_lengths[] = {
1, 1, 1, 0, 1, 1, 0, 1,
1, 0, 1, 1, 0, 1, 1, 0,
1, 1, 0, 1, 1, 0, 0, 0,
0, 1, 1, 1, 0, 0, 0, 1,
1, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1,
0, 1, 1, 1, 1, 1, 0, 1,
1, 1, 1, 1, 1, 0, 0, 0,
0, 0
0, 1, 1, 0, 0, 0, 1, 0,
0, 0, 1, 1, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 1, 1, 1, 1,
1, 0, 1, 1, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0
};
static const short _json_index_offsets[] = {
@ -2506,12 +2658,12 @@ static const short _json_index_offsets[] = {
166, 168, 170, 172, 174, 176, 178, 180,
182, 184, 186, 188, 190, 192, 194, 196,
198, 200, 202, 207, 209, 211, 213, 215,
217, 219, 221, 226, 235, 237, 238, 239,
244, 249, 254, 256, 258, 260, 262, 263,
265, 267, 269, 270, 272, 274, 276, 277,
282, 284, 288, 293, 298, 303, 307, 308,
311, 314, 317, 320, 323, 326, 327, 328,
329, 330
217, 219, 221, 226, 229, 232, 235, 244,
246, 247, 248, 253, 258, 263, 265, 267,
269, 271, 272, 274, 276, 278, 279, 281,
283, 285, 286, 291, 293, 297, 302, 307,
312, 316, 317, 320, 323, 326, 329, 332,
335, 336, 337, 338, 339, 340
};
static const unsigned char _json_indicies[] = {
@ -2543,64 +2695,67 @@ static const unsigned char _json_indicies[] = {
88, 1, 89, 89, 90, 91, 1, 92,
1, 93, 1, 94, 1, 95, 1, 96,
1, 97, 1, 98, 1, 99, 99, 100,
98, 1, 101, 102, 103, 104, 105, 106,
107, 102, 1, 108, 1, 109, 110, 112,
113, 1, 112, 111, 114, 115, 113, 114,
1, 115, 1, 1, 115, 111, 116, 1,
117, 1, 118, 1, 119, 1, 120, 121,
1, 122, 1, 123, 1, 124, 125, 1,
126, 1, 127, 1, 128, 129, 130, 131,
129, 1, 132, 1, 133, 134, 133, 1,
134, 1, 1, 134, 135, 136, 137, 138,
136, 1, 139, 140, 131, 139, 1, 140,
130, 140, 1, 141, 142, 142, 1, 143,
143, 1, 144, 144, 1, 145, 145, 1,
146, 146, 1, 147, 147, 1, 1, 1,
1, 1, 1, 0
98, 1, 102, 1, 101, 104, 105, 103,
1, 1, 101, 106, 107, 108, 109, 110,
111, 112, 107, 1, 113, 1, 114, 115,
117, 118, 1, 117, 116, 119, 120, 118,
119, 1, 120, 1, 1, 120, 116, 121,
1, 122, 1, 123, 1, 124, 1, 125,
126, 1, 127, 1, 128, 1, 129, 130,
1, 131, 1, 132, 1, 133, 134, 135,
136, 134, 1, 137, 1, 138, 139, 138,
1, 139, 1, 1, 139, 140, 141, 142,
143, 141, 1, 144, 145, 136, 144, 1,
145, 135, 145, 1, 146, 147, 147, 1,
148, 148, 1, 149, 149, 1, 150, 150,
1, 151, 151, 1, 152, 152, 1, 1,
1, 1, 1, 1, 1, 0
};
static const char _json_trans_targs[] = {
1, 0, 2, 104, 3, 6, 10, 13,
16, 103, 4, 3, 103, 4, 5, 7,
8, 9, 105, 11, 12, 106, 14, 15,
107, 16, 17, 108, 18, 18, 19, 20,
21, 22, 108, 21, 22, 24, 25, 31,
109, 26, 28, 27, 29, 30, 33, 110,
34, 33, 110, 34, 32, 35, 36, 37,
38, 39, 33, 110, 34, 41, 42, 46,
42, 46, 43, 45, 44, 111, 48, 49,
1, 0, 2, 107, 3, 6, 10, 13,
16, 106, 4, 3, 106, 4, 5, 7,
8, 9, 108, 11, 12, 109, 14, 15,
110, 16, 17, 111, 18, 18, 19, 20,
21, 22, 111, 21, 22, 24, 25, 31,
112, 26, 28, 27, 29, 30, 33, 113,
34, 33, 113, 34, 32, 35, 36, 37,
38, 39, 33, 113, 34, 41, 42, 46,
42, 46, 43, 45, 44, 114, 48, 49,
50, 51, 52, 53, 54, 55, 56, 57,
58, 59, 60, 61, 62, 63, 64, 65,
66, 67, 73, 72, 68, 69, 70, 71,
72, 112, 74, 67, 72, 76, 78, 79,
82, 87, 91, 95, 77, 113, 113, 80,
79, 77, 80, 81, 83, 84, 85, 86,
113, 88, 89, 90, 113, 92, 93, 94,
113, 95, 96, 102, 97, 97, 98, 99,
100, 101, 102, 100, 101, 113, 103, 103,
103, 103, 103, 103
72, 115, 74, 67, 72, 76, 116, 76,
116, 77, 79, 81, 82, 85, 90, 94,
98, 80, 117, 117, 83, 82, 80, 83,
84, 86, 87, 88, 89, 117, 91, 92,
93, 117, 95, 96, 97, 117, 98, 99,
105, 100, 100, 101, 102, 103, 104, 105,
103, 104, 117, 106, 106, 106, 106, 106,
106
};
static const char _json_trans_actions[] = {
0, 0, 84, 78, 33, 0, 0, 0,
96, 39, 25, 0, 35, 0, 0, 0,
0, 0, 92, 86, 35, 0, 0, 0,
104, 41, 27, 0, 37, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 72, 31, 27, 0, 0, 25,
29, 29, 75, 0, 0, 0, 0, 0,
0, 0, 80, 33, 29, 0, 0, 27,
31, 31, 83, 0, 0, 0, 0, 0,
3, 0, 0, 0, 0, 0, 5, 15,
0, 0, 51, 7, 13, 0, 54, 9,
9, 9, 57, 60, 11, 17, 17, 17,
0, 0, 53, 7, 13, 0, 56, 9,
9, 9, 59, 62, 11, 17, 17, 17,
0, 0, 0, 19, 0, 21, 23, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 102, 63, 102, 0, 0, 0, 0,
0, 69, 0, 66, 66, 84, 78, 33,
0, 0, 0, 96, 39, 49, 81, 25,
0, 35, 0, 0, 0, 0, 0, 0,
90, 0, 0, 0, 93, 0, 0, 0,
87, 0, 72, 31, 27, 0, 0, 25,
29, 29, 75, 0, 0, 99, 0, 37,
43, 45, 41, 47
0, 114, 65, 114, 0, 0, 0, 0,
0, 71, 0, 68, 68, 77, 25, 0,
110, 74, 92, 86, 35, 0, 0, 0,
104, 41, 51, 89, 27, 0, 37, 0,
0, 0, 0, 0, 0, 98, 0, 0,
0, 101, 0, 0, 0, 95, 0, 80,
33, 29, 0, 0, 27, 31, 31, 83,
0, 0, 107, 0, 39, 45, 47, 43,
49
};
static const char _json_eof_actions[] = {
@ -2617,8 +2772,8 @@ static const char _json_eof_actions[] = {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
37, 43, 45, 41, 47, 0, 0, 0,
0, 0
0, 0, 0, 39, 45, 47, 43, 49,
0, 0, 0, 0, 0, 0
};
static const int json_start = 1;
@ -2627,11 +2782,16 @@ static const int json_en_number_machine = 23;
static const int json_en_string_machine = 32;
static const int json_en_duration_machine = 40;
static const int json_en_timestamp_machine = 47;
static const int json_en_value_machine = 75;
static const int json_en_fieldmask_machine = 75;
static const int json_en_value_machine = 78;
static const int json_en_main = 1;
<<<<<<< HEAD
#line 2545 "upb/json/parser.rl"
=======
#line 2733 "upb/json/parser.rl"
>>>>>>> arrayapi
size_t parse(void *closure, const void *hd, const char *buf, size_t size,
const upb_bufhandle *handle) {
@ -2654,7 +2814,11 @@ size_t parse(void *closure, const void *hd, const char *buf, size_t size,
capture_resume(parser, buf);
<<<<<<< HEAD
#line 2658 "upb/json/parser.c"
=======
#line 2831 "upb/json/parser.c"
>>>>>>> arrayapi
{
int _klen;
unsigned int _trans;
@ -2729,6 +2893,7 @@ _match:
switch ( *_acts++ )
{
case 1:
<<<<<<< HEAD
#line 2393 "upb/json/parser.rl"
{ p--; {cs = stack[--top]; goto _again;} }
break;
@ -2806,22 +2971,132 @@ _match:
break;
case 20:
#line 2454 "upb/json/parser.rl"
=======
#line 2561 "upb/json/parser.rl"
{ p--; {cs = stack[--top]; goto _again;} }
break;
case 2:
#line 2563 "upb/json/parser.rl"
{ p--; {stack[top++] = cs; cs = 23;goto _again;} }
break;
case 3:
#line 2567 "upb/json/parser.rl"
{ start_text(parser, p); }
break;
case 4:
#line 2568 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_text(parser, p)); }
break;
case 5:
#line 2574 "upb/json/parser.rl"
{ start_hex(parser); }
break;
case 6:
#line 2575 "upb/json/parser.rl"
{ hexdigit(parser, p); }
break;
case 7:
#line 2576 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_hex(parser)); }
break;
case 8:
#line 2582 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(escape(parser, p)); }
break;
case 9:
#line 2588 "upb/json/parser.rl"
{ p--; {cs = stack[--top]; goto _again;} }
break;
case 10:
#line 2600 "upb/json/parser.rl"
{ start_duration_base(parser, p); }
break;
case 11:
#line 2601 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_duration_base(parser, p)); }
break;
case 12:
#line 2603 "upb/json/parser.rl"
{ p--; {cs = stack[--top]; goto _again;} }
break;
case 13:
#line 2608 "upb/json/parser.rl"
{ start_timestamp_base(parser, p); }
break;
case 14:
#line 2609 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_timestamp_base(parser, p)); }
break;
case 15:
#line 2611 "upb/json/parser.rl"
{ start_timestamp_fraction(parser, p); }
break;
case 16:
#line 2612 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_timestamp_fraction(parser, p)); }
break;
case 17:
#line 2614 "upb/json/parser.rl"
{ start_timestamp_zone(parser, p); }
break;
case 18:
#line 2615 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_timestamp_zone(parser, p)); }
break;
case 19:
#line 2617 "upb/json/parser.rl"
{ p--; {cs = stack[--top]; goto _again;} }
break;
case 20:
#line 2622 "upb/json/parser.rl"
{ start_fieldmask_path_text(parser, p); }
break;
case 21:
#line 2623 "upb/json/parser.rl"
{ end_fieldmask_path_text(parser, p); }
break;
case 22:
#line 2628 "upb/json/parser.rl"
{ start_fieldmask_path(parser); }
break;
case 23:
#line 2629 "upb/json/parser.rl"
{ end_fieldmask_path(parser); }
break;
case 24:
#line 2635 "upb/json/parser.rl"
{ p--; {cs = stack[--top]; goto _again;} }
break;
case 25:
#line 2640 "upb/json/parser.rl"
>>>>>>> arrayapi
{
if (is_wellknown_msg(parser, UPB_WELLKNOWN_TIMESTAMP)) {
{stack[top++] = cs; cs = 47;goto _again;}
} else if (is_wellknown_msg(parser, UPB_WELLKNOWN_DURATION)) {
{stack[top++] = cs; cs = 40;goto _again;}
} else if (is_wellknown_msg(parser, UPB_WELLKNOWN_FIELDMASK)) {
{stack[top++] = cs; cs = 75;goto _again;}
} else {
{stack[top++] = cs; cs = 32;goto _again;}
}
}
break;
<<<<<<< HEAD
case 21:
#line 2465 "upb/json/parser.rl"
{ p--; {stack[top++] = cs; cs = 75;goto _again;} }
break;
case 22:
#line 2470 "upb/json/parser.rl"
=======
case 26:
#line 2653 "upb/json/parser.rl"
{ p--; {stack[top++] = cs; cs = 78;goto _again;} }
break;
case 27:
#line 2658 "upb/json/parser.rl"
>>>>>>> arrayapi
{
if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) {
start_any_member(parser, p);
@ -2830,12 +3105,21 @@ _match:
}
}
break;
<<<<<<< HEAD
case 23:
#line 2477 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_membername(parser)); }
break;
case 24:
#line 2480 "upb/json/parser.rl"
=======
case 28:
#line 2665 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_membername(parser)); }
break;
case 29:
#line 2668 "upb/json/parser.rl"
>>>>>>> arrayapi
{
if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) {
end_any_member(parser, p);
@ -2844,8 +3128,13 @@ _match:
}
}
break;
<<<<<<< HEAD
case 25:
#line 2491 "upb/json/parser.rl"
=======
case 30:
#line 2679 "upb/json/parser.rl"
>>>>>>> arrayapi
{
if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) {
start_any_object(parser, p);
@ -2854,8 +3143,13 @@ _match:
}
}
break;
<<<<<<< HEAD
case 26:
#line 2500 "upb/json/parser.rl"
=======
case 31:
#line 2688 "upb/json/parser.rl"
>>>>>>> arrayapi
{
if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) {
CHECK_RETURN_TOP(end_any_object(parser, p));
@ -2864,6 +3158,7 @@ _match:
}
}
break;
<<<<<<< HEAD
case 27:
#line 2512 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(start_array(parser)); }
@ -2913,6 +3208,57 @@ _match:
{ p--; {cs = stack[--top]; goto _again;} }
break;
#line 2916 "upb/json/parser.c"
=======
case 32:
#line 2700 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(start_array(parser)); }
break;
case 33:
#line 2704 "upb/json/parser.rl"
{ end_array(parser); }
break;
case 34:
#line 2709 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(start_number(parser, p)); }
break;
case 35:
#line 2710 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_number(parser, p)); }
break;
case 36:
#line 2712 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(start_stringval(parser)); }
break;
case 37:
#line 2713 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_stringval(parser)); }
break;
case 38:
#line 2715 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_bool(parser, true)); }
break;
case 39:
#line 2717 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_bool(parser, false)); }
break;
case 40:
#line 2719 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_null(parser)); }
break;
case 41:
#line 2721 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(start_subobject_full(parser)); }
break;
case 42:
#line 2722 "upb/json/parser.rl"
{ end_subobject_full(parser); }
break;
case 43:
#line 2727 "upb/json/parser.rl"
{ p--; {cs = stack[--top]; goto _again;} }
break;
#line 3111 "upb/json/parser.c"
>>>>>>> arrayapi
}
}
@ -2929,11 +3275,16 @@ _again:
while ( __nacts-- > 0 ) {
switch ( *__acts++ ) {
case 0:
<<<<<<< HEAD
#line 2391 "upb/json/parser.rl"
=======
#line 2559 "upb/json/parser.rl"
>>>>>>> arrayapi
{ p--; {cs = stack[--top]; if ( p == pe )
goto _test_eof;
goto _again;} }
break;
<<<<<<< HEAD
case 30:
#line 2522 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_number(parser, p)); }
@ -2955,6 +3306,29 @@ goto _again;} }
{ end_subobject_full(parser); }
break;
#line 2958 "upb/json/parser.c"
=======
case 35:
#line 2710 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_number(parser, p)); }
break;
case 38:
#line 2715 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_bool(parser, true)); }
break;
case 39:
#line 2717 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_bool(parser, false)); }
break;
case 40:
#line 2719 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_null(parser)); }
break;
case 42:
#line 2722 "upb/json/parser.rl"
{ end_subobject_full(parser); }
break;
#line 3153 "upb/json/parser.c"
>>>>>>> arrayapi
}
}
}
@ -2962,7 +3336,11 @@ goto _again;} }
_out: {}
}
<<<<<<< HEAD
#line 2567 "upb/json/parser.rl"
=======
#line 2755 "upb/json/parser.rl"
>>>>>>> arrayapi
if (p != pe) {
upb_status_seterrf(parser->status, "Parse error at '%.*s'\n", pe - p, p);
@ -2984,6 +3362,7 @@ static bool end(void *closure, const void *hd) {
/* Prevent compile warning on unused static constants. */
UPB_UNUSED(json_start);
UPB_UNUSED(json_en_duration_machine);
UPB_UNUSED(json_en_fieldmask_machine);
UPB_UNUSED(json_en_number_machine);
UPB_UNUSED(json_en_string_machine);
UPB_UNUSED(json_en_timestamp_machine);
@ -2992,7 +3371,7 @@ static bool end(void *closure, const void *hd) {
parse(parser, hd, &eof_ch, 0, NULL);
return parser->current_state >= 103;
return parser->current_state >= 106;
}
static void json_parser_reset(upb_json_parser *p) {
@ -3009,13 +3388,21 @@ static void json_parser_reset(upb_json_parser *p) {
/* Emit Ragel initialization of the parser. */
<<<<<<< HEAD
#line 3013 "upb/json/parser.c"
=======
#line 3210 "upb/json/parser.c"
>>>>>>> arrayapi
{
cs = json_start;
top = 0;
}
<<<<<<< HEAD
#line 2613 "upb/json/parser.rl"
=======
#line 2803 "upb/json/parser.rl"
>>>>>>> arrayapi
p->current_state = cs;
p->parser_top = top;
accumulate_clear(p);

@ -61,6 +61,12 @@ static bool is_string_wrapper_object(upb_json_parser *p);
static bool does_string_wrapper_start(upb_json_parser *p);
static bool does_string_wrapper_end(upb_json_parser *p);
static bool is_fieldmask_object(upb_json_parser *p);
static bool does_fieldmask_start(upb_json_parser *p);
static bool does_fieldmask_end(upb_json_parser *p);
static void start_fieldmask_object(upb_json_parser *p);
static void end_fieldmask_object(upb_json_parser *p);
static void start_wrapper_object(upb_json_parser *p);
static void end_wrapper_object(upb_json_parser *p);
@ -1162,6 +1168,9 @@ static bool start_stringval(upb_json_parser *p) {
if (is_top_level(p)) {
if (is_string_wrapper_object(p)) {
start_wrapper_object(p);
} else if (is_wellknown_msg(p, UPB_WELLKNOWN_FIELDMASK)) {
start_fieldmask_object(p);
return true;
} else if (is_wellknown_msg(p, UPB_WELLKNOWN_TIMESTAMP) ||
is_wellknown_msg(p, UPB_WELLKNOWN_DURATION)) {
start_object(p);
@ -1175,6 +1184,12 @@ static bool start_stringval(upb_json_parser *p) {
return false;
}
start_wrapper_object(p);
} else if (does_fieldmask_start(p)) {
if (!start_subobject(p)) {
return false;
}
start_fieldmask_object(p);
return true;
} else if (is_wellknown_field(p, UPB_WELLKNOWN_TIMESTAMP) ||
is_wellknown_field(p, UPB_WELLKNOWN_DURATION)) {
if (!start_subobject(p)) {
@ -1315,8 +1330,8 @@ static bool end_stringval_nontop(upb_json_parser *p) {
case UPB_TYPE_STRING: {
upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR);
p->top--;
upb_sink_endstr(p->top->sink, sel);
p->top--;
break;
}
@ -1362,6 +1377,16 @@ static bool end_stringval_nontop(upb_json_parser *p) {
}
static bool end_stringval(upb_json_parser *p) {
/* FieldMask's stringvals have been ended when handling them. Only need to
* close FieldMask here.*/
if (does_fieldmask_end(p)) {
end_fieldmask_object(p);
if (!is_top_level(p)) {
end_subobject(p);
}
return true;
}
if (!end_stringval_nontop(p)) {
return false;
}
@ -1383,7 +1408,8 @@ static bool end_stringval(upb_json_parser *p) {
}
if (is_wellknown_msg(p, UPB_WELLKNOWN_TIMESTAMP) ||
is_wellknown_msg(p, UPB_WELLKNOWN_DURATION)) {
is_wellknown_msg(p, UPB_WELLKNOWN_DURATION) ||
is_wellknown_msg(p, UPB_WELLKNOWN_FIELDMASK)) {
end_object(p);
if (!is_top_level(p)) {
end_subobject(p);
@ -1637,6 +1663,75 @@ static bool end_timestamp_zone(upb_json_parser *p, const char *ptr) {
return true;
}
static void start_fieldmask_path_text(upb_json_parser *p, const char *ptr) {
capture_begin(p, ptr);
}
static bool end_fieldmask_path_text(upb_json_parser *p, const char *ptr) {
if (!capture_end(p, ptr)) {
return false;
}
}
static bool start_fieldmask_path(upb_json_parser *p) {
upb_jsonparser_frame *inner;
upb_selector_t sel;
if (!check_stack(p)) return false;
/* Start a new parser frame: parser frames correspond one-to-one with
* handler frames, and string events occur in a sub-frame. */
inner = p->top + 1;
sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSTR);
upb_sink_startstr(&p->top->sink, sel, 0, &inner->sink);
inner->m = p->top->m;
inner->f = p->top->f;
inner->name_table = NULL;
inner->is_map = false;
inner->is_mapentry = false;
inner->is_any = false;
inner->any_frame = NULL;
inner->is_unknown_field = false;
p->top = inner;
multipart_startaccum(p);
return true;
}
static bool lower_camel_push(
upb_json_parser *p, upb_selector_t sel, const char *ptr, size_t len) {
const char *limit = ptr + len;
bool first = true;
for (;ptr < limit; ptr++) {
if (*ptr >= 'A' && *ptr <= 'Z' && !first) {
char lower = tolower(*ptr);
upb_sink_putstring(&p->top->sink, sel, "_", 1, NULL);
upb_sink_putstring(&p->top->sink, sel, &lower, 1, NULL);
} else {
upb_sink_putstring(&p->top->sink, sel, ptr, 1, NULL);
}
first = false;
}
return true;
}
static bool end_fieldmask_path(upb_json_parser *p) {
upb_selector_t sel;
if (!lower_camel_push(
p, getsel_for_handlertype(p, UPB_HANDLER_STRING),
p->accumulated, p->accumulated_len)) {
return false;
}
sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR);
upb_sink_endstr(&p->top->sink, sel);
p->top--;
multipart_end(p);
return true;
}
static void start_member(upb_json_parser *p) {
UPB_ASSERT(!p->top->f);
multipart_startaccum(p);
@ -1694,7 +1789,7 @@ static bool parse_mapentry_key(upb_json_parser *p) {
sel = getsel_for_handlertype(p, UPB_HANDLER_STRING);
upb_sink_putstring(subsink, sel, buf, len, NULL);
sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR);
upb_sink_endstr(p->top->sink, sel);
upb_sink_endstr(subsink, sel);
multipart_end(p);
break;
}
@ -2219,6 +2314,31 @@ static bool is_string_wrapper(const upb_msgdef *m) {
type == UPB_WELLKNOWN_BYTESVALUE;
}
static bool is_fieldmask(const upb_msgdef *m) {
upb_wellknowntype_t type = upb_msgdef_wellknowntype(m);
return type == UPB_WELLKNOWN_FIELDMASK;
}
static void start_fieldmask_object(upb_json_parser *p) {
const char *membername = "paths";
start_object(p);
/* Set up context for parsing value */
start_member(p);
capture_begin(p, membername);
capture_end(p, membername + 5);
end_membername(p);
start_array(p);
}
static void end_fieldmask_object(upb_json_parser *p) {
end_array(p);
end_member(p);
end_object(p);
}
static void start_wrapper_object(upb_json_parser *p) {
const char *membername = "value";
@ -2357,6 +2477,20 @@ static bool is_string_wrapper_object(upb_json_parser *p) {
return p->top->m != NULL && is_string_wrapper(p->top->m);
}
static bool does_fieldmask_start(upb_json_parser *p) {
return p->top->f != NULL &&
upb_fielddef_issubmsg(p->top->f) &&
is_fieldmask(upb_fielddef_msgsubdef(p->top->f));
}
static bool does_fieldmask_end(upb_json_parser *p) {
return p->top->m != NULL && is_fieldmask(p->top->m);
}
static bool is_fieldmask_object(upb_json_parser *p) {
return p->top->m != NULL && is_fieldmask(p->top->m);
}
#define CHECK_RETURN_TOP(x) if (!(x)) goto error
@ -2449,6 +2583,24 @@ static bool is_string_wrapper_object(upb_json_parser *p) {
@{ fhold; fret; }
;
fieldmask_path_text =
/[^",]/+
>{ start_fieldmask_path_text(parser, p); }
%{ end_fieldmask_path_text(parser, p); }
;
fieldmask_path =
fieldmask_path_text
>{ start_fieldmask_path(parser); }
%{ end_fieldmask_path(parser); }
;
fieldmask_machine :=
(fieldmask_path ("," fieldmask_path)*)?
'"'
@{ fhold; fret; }
;
string =
'"'
@{
@ -2456,6 +2608,8 @@ static bool is_string_wrapper_object(upb_json_parser *p) {
fcall timestamp_machine;
} else if (is_wellknown_msg(parser, UPB_WELLKNOWN_DURATION)) {
fcall duration_machine;
} else if (is_wellknown_msg(parser, UPB_WELLKNOWN_FIELDMASK)) {
fcall fieldmask_machine;
} else {
fcall string_machine;
}
@ -2585,6 +2739,7 @@ static bool end(void *closure, const void *hd) {
/* Prevent compile warning on unused static constants. */
UPB_UNUSED(json_start);
UPB_UNUSED(json_en_duration_machine);
UPB_UNUSED(json_en_fieldmask_machine);
UPB_UNUSED(json_en_number_machine);
UPB_UNUSED(json_en_string_machine);
UPB_UNUSED(json_en_timestamp_machine);

@ -748,6 +748,57 @@ static void *startseq_nokey(void *closure, const void *handler_data) {
return closure;
}
static void *startseq_fieldmask(void *closure, const void *handler_data) {
upb_json_printer *p = closure;
UPB_UNUSED(handler_data);
p->depth_++;
p->first_elem_[p->depth_] = true;
print_data(p, "\"", 1);
return closure;
}
static bool endseq_fieldmask(void *closure, const void *handler_data) {
upb_json_printer *p = closure;
UPB_UNUSED(handler_data);
p->depth_--;
print_data(p, "\"", 1);
return true;
}
static void *repeated_startstr_fieldmask(
void *closure, const void *handler_data,
size_t size_hint) {
upb_json_printer *p = closure;
UPB_UNUSED(handler_data);
UPB_UNUSED(size_hint);
print_comma(p);
return p;
}
static size_t repeated_str_fieldmask(
void *closure, const void *handler_data,
const char *str, size_t len,
const upb_bufhandle *handle) {
const char* limit = str + len;
bool upper = false;
size_t result_len = 0;
for (; str < limit; str++) {
if (*str == '_') {
upper = true;
continue;
}
if (upper && *str >= 'a' && *str <= 'z') {
char upper_char = toupper(*str);
CHK(putstr(closure, handler_data, &upper_char, 1, handle));
} else {
CHK(putstr(closure, handler_data, str, 1, handle));
}
upper = false;
result_len++;
}
return result_len;
}
static void *startmap_nokey(void *closure, const void *handler_data) {
upb_json_printer *p = closure;
UPB_UNUSED(handler_data);
@ -973,6 +1024,25 @@ void printer_sethandlers_any(const void *closure, upb_handlers *h) {
UPB_UNUSED(closure);
}
/* Set up handlers for a fieldmask submessage. */
void printer_sethandlers_fieldmask(const void *closure, upb_handlers *h) {
const upb_msgdef *md = upb_handlers_msgdef(h);
const upb_fielddef* f = upb_msgdef_itof(md, 1);
upb_handlerattr empty_attr = UPB_HANDLERATTR_INITIALIZER;
upb_handlers_setstartseq(h, f, startseq_fieldmask, &empty_attr);
upb_handlers_setendseq(h, f, endseq_fieldmask, &empty_attr);
upb_handlers_setstartmsg(h, printer_startmsg_noframe, &empty_attr);
upb_handlers_setendmsg(h, printer_endmsg_noframe, &empty_attr);
upb_handlers_setstartstr(h, f, repeated_startstr_fieldmask, &empty_attr);
upb_handlers_setstring(h, f, repeated_str_fieldmask, &empty_attr);
UPB_UNUSED(closure);
}
/* Set up handlers for a duration submessage. */
void printer_sethandlers_duration(const void *closure, upb_handlers *h) {
const upb_msgdef *md = upb_handlers_msgdef(h);
@ -1129,6 +1199,9 @@ void printer_sethandlers(const void *closure, upb_handlers *h) {
case UPB_WELLKNOWN_ANY:
printer_sethandlers_any(closure, h);
return;
case UPB_WELLKNOWN_FIELDMASK:
printer_sethandlers_fieldmask(closure, h);
return;
case UPB_WELLKNOWN_DURATION:
printer_sethandlers_duration(closure, h);
return;

@ -615,8 +615,8 @@ static void generate_delimfield(compiler *c, const upb_fielddef *f,
putop(c, OP_STARTSTR, getsel(f, UPB_HANDLER_STARTSTR));
/* Need to emit even if no handler to skip past the string. */
putop(c, OP_STRING, getsel(f, UPB_HANDLER_STRING));
putop(c, OP_POP);
maybeput(c, OP_ENDSTR, h, f, UPB_HANDLER_ENDSTR);
putop(c, OP_POP);
putop(c, OP_SETDELIM);
putop(c, OP_CHECKDELIM, LABEL_LOOPBREAK);
putchecktag(c, f, UPB_WIRE_TYPE_DELIMITED, LABEL_LOOPBREAK);
@ -631,8 +631,8 @@ static void generate_delimfield(compiler *c, const upb_fielddef *f,
putop(c, OP_PUSHLENDELIM);
putop(c, OP_STARTSTR, getsel(f, UPB_HANDLER_STARTSTR));
putop(c, OP_STRING, getsel(f, UPB_HANDLER_STRING));
putop(c, OP_POP);
maybeput(c, OP_ENDSTR, h, f, UPB_HANDLER_ENDSTR);
putop(c, OP_POP);
putop(c, OP_SETDELIM);
}
}

@ -419,6 +419,7 @@ typedef enum {
typedef enum {
UPB_WELLKNOWN_UNSPECIFIED,
UPB_WELLKNOWN_ANY,
UPB_WELLKNOWN_FIELDMASK,
UPB_WELLKNOWN_DURATION,
UPB_WELLKNOWN_TIMESTAMP,
/* number wrappers */

Loading…
Cancel
Save