|
|
|
@ -186,6 +186,80 @@ local function field_layout_rank(field) |
|
|
|
|
return (rank * 2^29) + field:number() |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
local function sizeof(field) |
|
|
|
|
if field:label() == upb.LABEL_REPEATED or |
|
|
|
|
field:type() == upb.TYPE_MESSAGE then |
|
|
|
|
return {4, 8} |
|
|
|
|
elseif field:type() == upb.TYPE_STRING or field:type() == upb.TYPE_BYTES then |
|
|
|
|
-- upb_stringview |
|
|
|
|
return {8, 16} |
|
|
|
|
elseif field:type() == upb.TYPE_BOOL then |
|
|
|
|
return {1, 1} |
|
|
|
|
elseif field:type() == upb.TYPE_FLOAT or |
|
|
|
|
field:type() == upb.TYPE_INT32 or |
|
|
|
|
field:type() == upb.TYPE_UINT32 then |
|
|
|
|
return {4, 4} |
|
|
|
|
else |
|
|
|
|
return {8, 8} |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
local function sizemax(size, max) |
|
|
|
|
max[1] = math.max(max[1], size[1]) |
|
|
|
|
max[2] = math.max(max[2], size[2]) |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
local function alignup(val, align) |
|
|
|
|
val[1] = math.ceil(val[1] / align[1]) * align[1] |
|
|
|
|
val[2] = math.ceil(val[2] / align[2]) * align[2] |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
local function copysize(size) |
|
|
|
|
return {size[1], size[2]} |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
local function place(offset, size, max) |
|
|
|
|
alignup(offset, size) |
|
|
|
|
local ret = copysize(offset) |
|
|
|
|
|
|
|
|
|
-- add size |
|
|
|
|
offset[1] = offset[1] + size[1] |
|
|
|
|
offset[2] = offset[2] + size[2] |
|
|
|
|
|
|
|
|
|
-- track max size |
|
|
|
|
sizemax(size, max) |
|
|
|
|
|
|
|
|
|
return ret |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
local function get_field_layout_order(msg) |
|
|
|
|
local field_order = {} |
|
|
|
|
|
|
|
|
|
-- Sort fields by rank. |
|
|
|
|
for field in msg:fields() do |
|
|
|
|
table.insert(field_order, field) |
|
|
|
|
end |
|
|
|
|
table.sort(field_order, function(a, b) |
|
|
|
|
return field_layout_rank(a) < field_layout_rank(b) |
|
|
|
|
end) |
|
|
|
|
|
|
|
|
|
return field_order |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
local function get_oneof_layout_order(msg) |
|
|
|
|
local oneof_order = {} |
|
|
|
|
|
|
|
|
|
-- Sort oneofs by name. |
|
|
|
|
for oneof in msg:oneofs() do |
|
|
|
|
table.insert(oneof_order, oneof) |
|
|
|
|
end |
|
|
|
|
table.sort(oneof_order, function(a, b) |
|
|
|
|
return a:name() < b:name() |
|
|
|
|
end) |
|
|
|
|
|
|
|
|
|
return oneof_order |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
local function has_hasbit(field) |
|
|
|
|
if field:containing_type():file():syntax() == upb.SYNTAX_PROTO2 then |
|
|
|
|
return field:label() ~= upb.LABEL_REPEATED and not field:containing_oneof() |
|
|
|
@ -194,6 +268,65 @@ local function has_hasbit(field) |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
local function get_message_layout(msg) |
|
|
|
|
local hasbit_count = 0 |
|
|
|
|
local hasbit_indexes = {} |
|
|
|
|
local field_order = get_field_layout_order(msg) |
|
|
|
|
local maxsize = {0, 0} |
|
|
|
|
|
|
|
|
|
-- Count hasbits. |
|
|
|
|
for _, field in ipairs(field_order) do |
|
|
|
|
if has_hasbit(field) then |
|
|
|
|
hasbit_indexes[field] = hasbit_count |
|
|
|
|
hasbit_count = hasbit_count + 1 |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
-- Place hasbits at the beginning. |
|
|
|
|
local offset = math.ceil(hasbit_count / 8) |
|
|
|
|
offset = {offset, offset} -- 32, 64 bit |
|
|
|
|
local offsets = {} |
|
|
|
|
|
|
|
|
|
-- Place non-oneof fields. |
|
|
|
|
for _, field in ipairs(field_order) do |
|
|
|
|
if not field:containing_oneof() then |
|
|
|
|
offsets[field] = place(offset, sizeof(field), maxsize) |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
-- Place oneof fields. |
|
|
|
|
for oneof in msg:oneofs() do |
|
|
|
|
local oneof_maxsize = {0, 0} |
|
|
|
|
-- Calculate max size. |
|
|
|
|
for field in oneof:fields() do |
|
|
|
|
local size = sizeof(field) |
|
|
|
|
sizemax(size, oneof_maxsize) |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
-- Place discriminator enum and data. |
|
|
|
|
local data = place(offset, oneof_maxsize, maxsize) |
|
|
|
|
local case = place(offset, {4, 4}, maxsize) |
|
|
|
|
offsets[oneof] = {data, case} |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
-- Align overall size up to max size. |
|
|
|
|
alignup(offset, maxsize) |
|
|
|
|
local size = copysize(offset) |
|
|
|
|
|
|
|
|
|
-- Place oneof defaults. |
|
|
|
|
for oneof in msg:oneofs() do |
|
|
|
|
for field in oneof:fields() do |
|
|
|
|
offsets[field] = place(offset, sizeof(field), maxsize) |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
return hasbit_indexes, offsets, size |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
function get_sizeinit(size) |
|
|
|
|
return string.format("UPB_SIZE(%s, %s)", size[1], size[2]) |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
local function write_h_file(filedef, append) |
|
|
|
|
emit_file_warning(filedef, append) |
|
|
|
|
local basename_preproc = to_preproc(filedef:name()) |
|
|
|
@ -201,18 +334,32 @@ local function write_h_file(filedef, append) |
|
|
|
|
append('#define %s_UPB_H_\n\n', basename_preproc) |
|
|
|
|
|
|
|
|
|
append('#include "upb/msg.h"\n\n') |
|
|
|
|
append('#include "upb/decode.h"\n') |
|
|
|
|
append('#include "upb/encode.h"\n') |
|
|
|
|
append('#include "upb/port_def.inc"\n') |
|
|
|
|
|
|
|
|
|
append('UPB_BEGIN_EXTERN_C\n\n') |
|
|
|
|
|
|
|
|
|
-- Forward-declare types defined in this file. |
|
|
|
|
for msg in filedef:defs(upb.DEF_MSG) do |
|
|
|
|
-- TODO(haberman): forward declare C++ type names so we can use |
|
|
|
|
-- UPB_DECLARE_TYPE(). |
|
|
|
|
local msgname = to_cident(msg:full_name()) |
|
|
|
|
append('struct %s;\n', msgname) |
|
|
|
|
append('typedef struct %s %s;\n', msgname, msgname) |
|
|
|
|
append('typedef struct %s { int a; } %s;\n', msgname, msgname) |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
-- Forward-declare types not in this file, but used as submessages. |
|
|
|
|
for msg in filedef:defs(upb.DEF_MSG) do |
|
|
|
|
for field in msg:fields() do |
|
|
|
|
if field:type() == upb.TYPE_MESSAGE and |
|
|
|
|
field:subdef():file() ~= filedef then |
|
|
|
|
-- Forward declaration for message type declared in another file. |
|
|
|
|
append('struct %s;\n', to_cident(field:subdef():full_name())) |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
append('\n') |
|
|
|
|
append("/* Enums */\n\n") |
|
|
|
|
|
|
|
|
|
for _, def in ipairs(sorted_defs(filedef:defs(upb.DEF_ENUM))) do |
|
|
|
|
local cident = to_cident(def:full_name()) |
|
|
|
|
append('typedef enum {\n') |
|
|
|
@ -221,54 +368,78 @@ local function write_h_file(filedef, append) |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
for msg in filedef:defs(upb.DEF_MSG) do |
|
|
|
|
local hasbit_indexes, offsets, size = get_message_layout(msg) |
|
|
|
|
|
|
|
|
|
append("/* %s */\n\n", msg:full_name()) |
|
|
|
|
|
|
|
|
|
local msgname = to_cident(msg:full_name()) |
|
|
|
|
append('/* %s */\n', msgname) |
|
|
|
|
append('extern const upb_msglayout %s_msginit;\n', msgname) |
|
|
|
|
append('%s *%s_new(upb_env *env);\n', msgname, msgname) |
|
|
|
|
append('%s *%s_parsenew(upb_stringview buf, upb_env *env);\n', |
|
|
|
|
append('UPB_INLINE %s *%s_new(upb_arena *arena) {\n', msgname, msgname) |
|
|
|
|
append(' return upb_msg_new(&%s_msginit, arena);\n', msgname) |
|
|
|
|
append('}\n') |
|
|
|
|
append('UPB_INLINE %s *%s_parsenew(upb_stringview buf, upb_arena *arena) {\n', |
|
|
|
|
msgname, msgname) |
|
|
|
|
append('char *%s_serialize(%s *msg, upb_env *env, size_t *len);\n', |
|
|
|
|
append(' %s *ret = %s_new(arena);\n', msgname, msgname) |
|
|
|
|
append(' return (ret && upb_decode(buf, ret, &%s_msginit)) ? ret : NULL;\n', msgname) |
|
|
|
|
append('}\n') |
|
|
|
|
append('UPB_INLINE char *%s_serialize(const %s *msg, upb_arena *arena, size_t *len) {\n', |
|
|
|
|
msgname, msgname) |
|
|
|
|
append('void %s_free(%s *msg, upb_env *env);\n', msgname, msgname) |
|
|
|
|
append(' return upb_encode(msg, &%s_msginit, arena, len);\n', msgname) |
|
|
|
|
append('}\n') |
|
|
|
|
append('\n') |
|
|
|
|
|
|
|
|
|
append('/* getters. */\n') |
|
|
|
|
local setters, get_setters = dump_cinit.str_appender() |
|
|
|
|
for field in msg:fields() do |
|
|
|
|
local fieldname = to_cident(field:name()) |
|
|
|
|
if field:type() == upb.TYPE_MESSAGE and |
|
|
|
|
field:subdef():file() ~= filedef then |
|
|
|
|
-- Forward declaration for message type declared in another file. |
|
|
|
|
append('struct %s;\n', to_cident(field:subdef():full_name())) |
|
|
|
|
end |
|
|
|
|
append('%s %s_%s(const %s *msg);\n', |
|
|
|
|
ctype(field, true), msgname, fieldname, msgname) |
|
|
|
|
setters('void %s_set_%s(%s *msg, %s value);\n', |
|
|
|
|
msgname, fieldname, msgname, ctype(field)) |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
for oneof in msg:oneofs() do |
|
|
|
|
local fullname = to_cident(oneof:containing_type():full_name() .. "." .. oneof:name()) |
|
|
|
|
local offset = offsets[oneof] |
|
|
|
|
append('typedef enum {\n') |
|
|
|
|
for field in oneof:fields() do |
|
|
|
|
append(' %s = %d,\n', fullname .. "_" .. field:name(), field:number()) |
|
|
|
|
end |
|
|
|
|
append(' %s_NOT_SET = 0,\n', fullname) |
|
|
|
|
append('} %s_oneofcases;\n', fullname) |
|
|
|
|
append('%s_oneofcases %s_case(const %s *msg);\n', fullname, fullname, msgname) |
|
|
|
|
append('UPB_INLINE %s_oneofcases %s_%s_case(const %s* msg) { ' .. |
|
|
|
|
'return UPB_FIELD_AT(msg, int, %s); }\n', |
|
|
|
|
fullname, msgname, oneof:name(), msgname, get_sizeinit(offset[2])) |
|
|
|
|
append('\n') |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
append('\n') |
|
|
|
|
append('/* setters. */\n') |
|
|
|
|
append(get_setters()) |
|
|
|
|
for field in msg:fields() do |
|
|
|
|
append('UPB_INLINE %s %s_%s(const %s *msg) {', |
|
|
|
|
ctype(field, true), msgname, field:name(), msgname) |
|
|
|
|
if field:containing_oneof() then |
|
|
|
|
local offset = offsets[field:containing_oneof()] |
|
|
|
|
append(' return UPB_READ_ONEOF(msg, %s, %s, %s, %s, %s); }\n', |
|
|
|
|
ctype(field, true), get_sizeinit(offset[1]), |
|
|
|
|
get_sizeinit(offset[2]), field:number(), field_default(field)) |
|
|
|
|
else |
|
|
|
|
append(' return UPB_FIELD_AT(msg, %s, %s); }\n', |
|
|
|
|
ctype(field, true), get_sizeinit(offsets[field])) |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
append('\n') |
|
|
|
|
append('\n') |
|
|
|
|
|
|
|
|
|
for field in msg:fields() do |
|
|
|
|
append('UPB_INLINE void %s_set_%s(%s *msg, %s value) { ', |
|
|
|
|
msgname, field:name(), msgname, ctype(field)) |
|
|
|
|
if field:containing_oneof() then |
|
|
|
|
local offset = offsets[field:containing_oneof()] |
|
|
|
|
append('UPB_WRITE_ONEOF(msg, %s, %s, value, %s, %s); }\n', |
|
|
|
|
ctype(field), get_sizeinit(offset[1]), get_sizeinit(offset[2]), |
|
|
|
|
field:number()) |
|
|
|
|
else |
|
|
|
|
append('UPB_FIELD_AT(msg, %s, %s) = value; }\n', |
|
|
|
|
ctype(field), get_sizeinit(offsets[field])) |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
append('\n\n') |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
append('UPB_END_EXTERN_C') |
|
|
|
|
append('UPB_END_EXTERN_C\n') |
|
|
|
|
|
|
|
|
|
append('\n') |
|
|
|
|
append('#include "upb/port_undef.inc"\n'); |
|
|
|
|
append('\n') |
|
|
|
|
|
|
|
|
|
append('#endif /* %s_UPB_H_ */\n', basename_preproc) |
|
|
|
@ -278,17 +449,16 @@ local function write_c_file(filedef, hfilename, append) |
|
|
|
|
emit_file_warning(filedef, append) |
|
|
|
|
|
|
|
|
|
append('#include <stddef.h>\n') |
|
|
|
|
append('#include "upb/decode.h"\n') |
|
|
|
|
append('#include "upb/encode.h"\n') |
|
|
|
|
append('#include "upb/msg.h"\n') |
|
|
|
|
append('#include "upb/upb.h"\n') |
|
|
|
|
append('#include "%s"\n\n', hfilename) |
|
|
|
|
append('#include "%s"\n', hfilename) |
|
|
|
|
|
|
|
|
|
for dep in filedef:dependencies() do |
|
|
|
|
local outbase = strip_proto(dep:name()) |
|
|
|
|
append('#include "%s.upb.h"\n', outbase) |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
append('\n') |
|
|
|
|
append('#include "upb/port_def.inc"\n') |
|
|
|
|
append('\n') |
|
|
|
|
|
|
|
|
|
for msg in filedef:defs(upb.DEF_MSG) do |
|
|
|
@ -301,79 +471,31 @@ local function write_c_file(filedef, hfilename, append) |
|
|
|
|
local submsg_count = 0 |
|
|
|
|
local submsg_set = {} |
|
|
|
|
local submsg_indexes = {} |
|
|
|
|
local hasbit_count = 0 |
|
|
|
|
local hasbit_indexes = {} |
|
|
|
|
local hasbit_indexes, offsets, size = get_message_layout(msg) |
|
|
|
|
local oneofs_layout_order = get_oneof_layout_order(msg) |
|
|
|
|
local oneof_count = 0 |
|
|
|
|
local oneof_indexes = {} |
|
|
|
|
|
|
|
|
|
-- Create a layout order for oneofs. |
|
|
|
|
local oneofs_layout_order = {} |
|
|
|
|
for oneof in msg:oneofs() do |
|
|
|
|
table.insert(oneofs_layout_order, oneof) |
|
|
|
|
end |
|
|
|
|
table.sort(oneofs_layout_order, function(a, b) |
|
|
|
|
return a:name() < b:name() |
|
|
|
|
end) |
|
|
|
|
|
|
|
|
|
for _, oneof in ipairs(oneofs_layout_order) do |
|
|
|
|
oneof_indexes[oneof] = oneof_count |
|
|
|
|
oneof_count = oneof_count + 1 |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
-- Create a layout order for fields. We use this order for the struct and |
|
|
|
|
-- for offsets, but our list of fields we keep in field number order. |
|
|
|
|
local fields_layout_order = {} |
|
|
|
|
for field in msg:fields() do |
|
|
|
|
table.insert(fields_layout_order, field) |
|
|
|
|
end |
|
|
|
|
table.sort(fields_layout_order, function(a, b) |
|
|
|
|
return field_layout_rank(a) < field_layout_rank(b) |
|
|
|
|
end) |
|
|
|
|
|
|
|
|
|
-- Another sorted array in field number order. |
|
|
|
|
local fields_number_order = {} |
|
|
|
|
for field in msg:fields() do |
|
|
|
|
table.insert(fields_number_order, field) |
|
|
|
|
end |
|
|
|
|
table.sort(fields_number_order, function(a, b) |
|
|
|
|
return a:number() < b:number() |
|
|
|
|
end) |
|
|
|
|
|
|
|
|
|
append('struct %s {\n', msgname) |
|
|
|
|
|
|
|
|
|
-- Non-oneof fields. |
|
|
|
|
for _, field in ipairs(fields_layout_order) do |
|
|
|
|
for field in msg:fields() do |
|
|
|
|
field_count = field_count + 1 |
|
|
|
|
|
|
|
|
|
table.insert(fields_number_order, field) |
|
|
|
|
if field:type() == upb.TYPE_MESSAGE then |
|
|
|
|
submsg_count = submsg_count + 1 |
|
|
|
|
submsg_set[field:subdef()] = true |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
if field:containing_oneof() then |
|
|
|
|
-- Handled below. |
|
|
|
|
else |
|
|
|
|
if has_hasbit(field) then |
|
|
|
|
hasbit_indexes[field] = hasbit_count |
|
|
|
|
hasbit_count = hasbit_count + 1 |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
append(' %s %s;\n', ctype(field), field:name()) |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
-- Oneof fields. |
|
|
|
|
for oneof in msg:oneofs() do |
|
|
|
|
local fullname = to_cident(oneof:containing_type():full_name() .. "." .. oneof:name()) |
|
|
|
|
append(' union {\n') |
|
|
|
|
for field in oneof:fields() do |
|
|
|
|
append(' %s %s;\n', ctype(field), field:name()) |
|
|
|
|
end |
|
|
|
|
append(' } %s;\n', oneof:name()) |
|
|
|
|
append(' %s_oneofcases %s_case;\n', fullname, oneof:name()) |
|
|
|
|
end |
|
|
|
|
table.sort(fields_number_order, function(a, b) |
|
|
|
|
return a:number() < b:number() |
|
|
|
|
end) |
|
|
|
|
|
|
|
|
|
append('};\n\n') |
|
|
|
|
for _, oneof in ipairs(oneofs_layout_order) do |
|
|
|
|
oneof_indexes[oneof] = oneof_count |
|
|
|
|
oneof_count = oneof_count + 1 |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
if oneof_count > 0 then |
|
|
|
|
local oneofs_array_name = msgname .. "_oneofs" |
|
|
|
@ -381,8 +503,8 @@ local function write_c_file(filedef, hfilename, append) |
|
|
|
|
append('static const upb_msglayout_oneof %s[%s] = {\n', |
|
|
|
|
oneofs_array_name, oneof_count) |
|
|
|
|
for _, oneof in ipairs(oneofs_layout_order) do |
|
|
|
|
append(' {offsetof(%s, %s), offsetof(%s, %s_case)},\n', |
|
|
|
|
msgname, oneof:name(), msgname, oneof:name()) |
|
|
|
|
local offset = offsets[oneof] |
|
|
|
|
append(' {%s, %s},\n', get_sizeinit(offset[1]), get_sizeinit(offset[2])) |
|
|
|
|
end |
|
|
|
|
append('};\n\n') |
|
|
|
|
end |
|
|
|
@ -426,10 +548,9 @@ local function write_c_file(filedef, hfilename, append) |
|
|
|
|
if field:containing_oneof() then |
|
|
|
|
oneof_index = oneof_indexes[field:containing_oneof()] |
|
|
|
|
end |
|
|
|
|
append(' {%s, offsetof(%s, %s), %s, %s, %s, %s, %s},\n', |
|
|
|
|
append(' {%s, %s, %s, %s, %s, %s, %s},\n', |
|
|
|
|
field:number(), |
|
|
|
|
msgname, |
|
|
|
|
(field:containing_oneof() and field:containing_oneof():name()) or field:name(), |
|
|
|
|
get_sizeinit(offsets[field]), |
|
|
|
|
hasbit_indexes[field] or "UPB_NO_HASBIT", |
|
|
|
|
oneof_index, |
|
|
|
|
submsg_index, |
|
|
|
@ -444,67 +565,18 @@ local function write_c_file(filedef, hfilename, append) |
|
|
|
|
append(' %s,\n', fields_array_ref) |
|
|
|
|
append(' %s,\n', oneofs_array_ref) |
|
|
|
|
append(' NULL, /* TODO. default_msg */\n') |
|
|
|
|
append(' UPB_ALIGNED_SIZEOF(%s), %s, %s, %s, %s\n', |
|
|
|
|
msgname, field_count, |
|
|
|
|
0, -- TODO: oneof_count |
|
|
|
|
append(' %s, %s, %s, %s, %s\n', |
|
|
|
|
get_sizeinit(size), field_count, |
|
|
|
|
oneof_count, |
|
|
|
|
'false', -- TODO: extendable |
|
|
|
|
msg:file():syntax() == upb.SYNTAX_PROTO2 |
|
|
|
|
) |
|
|
|
|
append('};\n\n') |
|
|
|
|
|
|
|
|
|
append('%s *%s_new(upb_env *env) {\n', msgname, msgname) |
|
|
|
|
append(' %s *msg = upb_env_malloc(env, sizeof(*msg));\n', |
|
|
|
|
msgname) |
|
|
|
|
append(' memset(msg, 0, sizeof(*msg)); /* TODO: defaults */\n') |
|
|
|
|
append(' return msg;\n') |
|
|
|
|
append('}\n') |
|
|
|
|
|
|
|
|
|
append('%s *%s_parsenew(upb_stringview buf, upb_env *env) {\n', |
|
|
|
|
msgname, msgname) |
|
|
|
|
append(' %s *msg = %s_new(env);\n', msgname, msgname) |
|
|
|
|
append(' if (upb_decode(buf, msg, &%s_msginit, env)) {\n', msgname) |
|
|
|
|
append(' return msg;\n') |
|
|
|
|
append(' } else {\n') |
|
|
|
|
append(' return NULL;\n') |
|
|
|
|
append(' }\n') |
|
|
|
|
append('}\n') |
|
|
|
|
|
|
|
|
|
append('char *%s_serialize(%s *msg, upb_env *env, size_t *size) {\n', |
|
|
|
|
msgname, msgname) |
|
|
|
|
append(' return upb_encode(msg, &%s_msginit, env, size);\n', msgname) |
|
|
|
|
append('}\n') |
|
|
|
|
|
|
|
|
|
for field in msg:fields() do |
|
|
|
|
append('%s %s_%s(const %s *msg) {\n', |
|
|
|
|
ctype(field, true), msgname, field:name(), msgname); |
|
|
|
|
if field:containing_oneof() then |
|
|
|
|
local oneof = field:containing_oneof() |
|
|
|
|
append(' return msg->%s_case == %s ? msg->%s.%s : %s;\n', |
|
|
|
|
oneof:name(), field:number(), oneof:name(), field:name(), |
|
|
|
|
field_default(field)) |
|
|
|
|
else |
|
|
|
|
append(' return msg->%s;\n', field:name()) |
|
|
|
|
end |
|
|
|
|
append('}\n') |
|
|
|
|
append('void %s_set_%s(%s *msg, %s value) {\n', |
|
|
|
|
msgname, field:name(), msgname, ctype(field)); |
|
|
|
|
if field:containing_oneof() then |
|
|
|
|
local oneof = field:containing_oneof() |
|
|
|
|
append(' msg->%s.%s = value;\n', oneof:name(), field:name()) |
|
|
|
|
append(' msg->%s_case = %s;\n', oneof:name(), field:number()) |
|
|
|
|
else |
|
|
|
|
append(' msg->%s = value;\n', field:name()) |
|
|
|
|
end |
|
|
|
|
append('}\n') |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
for oneof in msg:oneofs() do |
|
|
|
|
local fullname = to_cident(oneof:containing_type():full_name() .. "." .. oneof:name()) |
|
|
|
|
append('%s_oneofcases %s_case(const %s *msg) {\n', fullname, fullname, msgname) |
|
|
|
|
append(' return msg->%s_case;\n', oneof:name()) |
|
|
|
|
append('}\n') |
|
|
|
|
end |
|
|
|
|
append('};\n\n') |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
append('#include "upb/port_undef.inc"\n') |
|
|
|
|
append('\n') |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
function export.write_gencode(filedef, hfilename, append_h, append_c) |
|
|
|
|