From 7c541f0ba649353fd1fd901c38dd4ff999c946a0 Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Sat, 12 Mar 2022 16:37:16 -0800 Subject: [PATCH] (NFC) Refactored upbc header generation into smaller methods. This is in anticipation of a larger upcoming refactor. --- upbc/protoc-gen-upb.cc | 598 +++++++++++++++++++++++------------------ 1 file changed, 333 insertions(+), 265 deletions(-) diff --git a/upbc/protoc-gen-upb.cc b/upbc/protoc-gen-upb.cc index 7e52153baf..6e82f392aa 100644 --- a/upbc/protoc-gen-upb.cc +++ b/upbc/protoc-gen-upb.cc @@ -418,294 +418,362 @@ void GenerateExtensionInHeader(const protobuf::FieldDescriptor* ext, } } -void GenerateMessageInHeader(const protobuf::Descriptor* message, - Output& output) { - MessageLayout layout(message); +void GenerateMessageFunctionsInHeader(const protobuf::Descriptor* message, + Output& output) { + output( + R"cc( + UPB_INLINE $0* $0_new(upb_Arena* arena) { + return ($0*)_upb_Message_New(&$1, arena); + } + UPB_INLINE $0* $0_parse(const char* buf, size_t size, upb_Arena* arena) { + $0* ret = $0_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, ret, &$1, NULL, 0, arena) != kUpb_DecodeStatus_Ok) { + return NULL; + } + return ret; + } + UPB_INLINE $0* $0_parse_ex(const char* buf, size_t size, + const upb_ExtensionRegistry* extreg, + int options, upb_Arena* arena) { + $0* ret = $0_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, ret, &$1, extreg, options, arena) != + kUpb_DecodeStatus_Ok) { + return NULL; + } + return ret; + } + UPB_INLINE char* $0_serialize(const $0* msg, upb_Arena* arena, size_t* len) { + return upb_Encode(msg, &$1, 0, arena, len); + } + UPB_INLINE char* $0_serialize_ex(const $0* msg, int options, + upb_Arena* arena, size_t* len) { + return upb_Encode(msg, &$1, options, arena, len); + } + )cc", + MessageName(message), MessageInit(message)); +} - output("/* $0 */\n\n", message->full_name()); - std::string msg_name = ToCIdent(message->full_name()); +void GenerateOneofInHeader(const protobuf::OneofDescriptor* oneof, + const MessageLayout& layout, + absl::string_view msg_name, Output& output) { + std::string fullname = ToCIdent(oneof->full_name()); + output("typedef enum {\n"); + for (int j = 0; j < oneof->field_count(); j++) { + const protobuf::FieldDescriptor* field = oneof->field(j); + output(" $0_$1 = $2,\n", fullname, field->name(), field->number()); + } + output( + " $0_NOT_SET = 0\n" + "} $0_oneofcases;\n", + fullname); + output( + "UPB_INLINE $0_oneofcases $1_$2_case(const $1* msg) { " + "return ($0_oneofcases)*UPB_PTR_AT(msg, $3, int32_t); }\n" + "\n", + fullname, msg_name, oneof->name(), + GetSizeInit(layout.GetOneofCaseOffset(oneof))); +} - if (!message->options().map_entry()) { +void GenerateHazzer(const protobuf::FieldDescriptor* field, + const MessageLayout& layout, absl::string_view msg_name, + Output& output) { + if (layout.HasHasbit(field)) { + output( + "UPB_INLINE bool $0_has_$1(const $0 *msg) { " + "return _upb_hasbit(msg, $2); }\n", + msg_name, field->name(), layout.GetHasbitIndex(field)); + } else if (field->real_containing_oneof()) { + output( + "UPB_INLINE bool $0_has_$1(const $0 *msg) { " + "return _upb_getoneofcase(msg, $2) == $3; }\n", + msg_name, field->name(), + GetSizeInit(layout.GetOneofCaseOffset(field->real_containing_oneof())), + field->number()); + } else if (field->message_type()) { + output( + "UPB_INLINE bool $0_has_$1(const $0 *msg) { " + "return _upb_has_submsg_nohasbit(msg, $2); }\n", + msg_name, field->name(), GetSizeInit(layout.GetFieldOffset(field))); + } +} + +void GenerateMapGetters(const protobuf::FieldDescriptor* field, + const MessageLayout& layout, absl::string_view msg_name, + Output& output) { + const protobuf::Descriptor* entry = field->message_type(); + const protobuf::FieldDescriptor* key = entry->FindFieldByNumber(1); + const protobuf::FieldDescriptor* val = entry->FindFieldByNumber(2); + output( + "UPB_INLINE size_t $0_$1_size(const $0 *msg) {" + "return _upb_msg_map_size(msg, $2); }\n", + msg_name, field->name(), GetSizeInit(layout.GetFieldOffset(field))); + output( + "UPB_INLINE bool $0_$1_get(const $0 *msg, $2 key, $3 *val) { " + "return _upb_msg_map_get(msg, $4, &key, $5, val, $6); }\n", + msg_name, field->name(), CType(key), CType(val), + GetSizeInit(layout.GetFieldOffset(field)), + key->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING + ? "0" + : "sizeof(key)", + val->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING + ? "0" + : "sizeof(*val)"); + output( + "UPB_INLINE $0 $1_$2_next(const $1 *msg, size_t* iter) { " + "return ($0)_upb_msg_map_next(msg, $3, iter); }\n", + CTypeConst(field), msg_name, field->name(), + GetSizeInit(layout.GetFieldOffset(field))); +} + +void GenerateMapEntryGetters(const protobuf::FieldDescriptor* field, + absl::string_view msg_name, Output& output) { + output( + "UPB_INLINE $0 $1_$2(const $1 *msg) {\n" + " $3 ret;\n" + " _upb_msg_map_$2(msg, &ret, $4);\n" + " return ret;\n" + "}\n", + CTypeConst(field), msg_name, field->name(), CType(field), + field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING + ? "0" + : "sizeof(ret)"); +} + +void GenerateRepeatedGetters(const protobuf::FieldDescriptor* field, + const MessageLayout& layout, + absl::string_view msg_name, Output& output) { + output( + "UPB_INLINE $0 const* $1_$2(const $1 *msg, size_t *len) { " + "return ($0 const*)_upb_array_accessor(msg, $3, len); }\n", + CTypeConst(field), msg_name, field->name(), + GetSizeInit(layout.GetFieldOffset(field))); +} + +void GenerateOneofGetters(const protobuf::FieldDescriptor* field, + const MessageLayout& layout, + absl::string_view msg_name, Output& output) { + output( + "UPB_INLINE $0 $1_$2(const $1 *msg) { " + "return UPB_READ_ONEOF(msg, $0, $3, $4, $5, $6); }\n", + CTypeConst(field), msg_name, field->name(), + GetSizeInit(layout.GetFieldOffset(field)), + GetSizeInit(layout.GetOneofCaseOffset(field->real_containing_oneof())), + field->number(), FieldDefault(field)); +} + +void GenerateScalarGetters(const protobuf::FieldDescriptor* field, + const MessageLayout& layout, + absl::string_view msg_name, Output& output) { + if (HasNonZeroDefault(field)) { output( R"cc( - UPB_INLINE $0* $0_new(upb_Arena* arena) { - return ($0*)_upb_Message_New(&$1, arena); - } - UPB_INLINE $0* $0_parse(const char* buf, size_t size, upb_Arena* arena) { - $0* ret = $0_new(arena); - if (!ret) return NULL; - if (upb_Decode(buf, size, ret, &$1, NULL, 0, arena) != kUpb_DecodeStatus_Ok) { - return NULL; - } - return ret; - } - UPB_INLINE $0* $0_parse_ex(const char* buf, size_t size, - const upb_ExtensionRegistry* extreg, - int options, upb_Arena* arena) { - $0* ret = $0_new(arena); - if (!ret) return NULL; - if (upb_Decode(buf, size, ret, &$1, extreg, options, arena) != - kUpb_DecodeStatus_Ok) { - return NULL; - } - return ret; + UPB_INLINE $0 $1_$2(const $1* msg) { + return $1_has_$2(msg) ? *UPB_PTR_AT(msg, $3, $0) : $4; } - UPB_INLINE char* $0_serialize(const $0* msg, upb_Arena* arena, size_t* len) { - return upb_Encode(msg, &$1, 0, arena, len); - } - UPB_INLINE char* $0_serialize_ex(const $0* msg, int options, - upb_Arena* arena, size_t* len) { - return upb_Encode(msg, &$1, options, arena, len); + )cc", + CTypeConst(field), msg_name, field->name(), + GetSizeInit(layout.GetFieldOffset(field)), FieldDefault(field)); + } else { + output( + R"cc( + UPB_INLINE $0 $1_$2(const $1* msg) { + return *UPB_PTR_AT(msg, $3, $0); } )cc", - MessageName(message), MessageInit(message)); + CTypeConst(field), msg_name, field->name(), + GetSizeInit(layout.GetFieldOffset(field))); } +} - for (int i = 0; i < message->real_oneof_decl_count(); i++) { - const protobuf::OneofDescriptor* oneof = message->oneof_decl(i); - std::string fullname = ToCIdent(oneof->full_name()); - output("typedef enum {\n"); - for (int j = 0; j < oneof->field_count(); j++) { - const protobuf::FieldDescriptor* field = oneof->field(j); - output(" $0_$1 = $2,\n", fullname, field->name(), field->number()); - } +void GenerateGetters(const protobuf::FieldDescriptor* field, + const MessageLayout& layout, absl::string_view msg_name, + Output& output) { + if (field->is_map()) { + GenerateMapGetters(field, layout, msg_name, output); + } else if (field->containing_type()->options().map_entry()) { + GenerateMapEntryGetters(field, msg_name, output); + } else if (field->is_repeated()) { + GenerateRepeatedGetters(field, layout, msg_name, output); + } else if (field->real_containing_oneof()) { + GenerateOneofGetters(field, layout, msg_name, output); + } else { + GenerateScalarGetters(field, layout, msg_name, output); + } +} + +void GenerateMapSetters(const protobuf::FieldDescriptor* field, + const MessageLayout& layout, absl::string_view msg_name, + Output& output) { + const protobuf::Descriptor* entry = field->message_type(); + const protobuf::FieldDescriptor* key = entry->FindFieldByNumber(1); + const protobuf::FieldDescriptor* val = entry->FindFieldByNumber(2); + output( + "UPB_INLINE void $0_$1_clear($0 *msg) { _upb_msg_map_clear(msg, " + "$2); " + "}\n", + msg_name, field->name(), GetSizeInit(layout.GetFieldOffset(field))); + output( + "UPB_INLINE bool $0_$1_set($0 *msg, $2 key, $3 val, upb_Arena *a) " + "{ " + "return _upb_msg_map_set(msg, $4, &key, $5, &val, $6, a); }\n", + msg_name, field->name(), CType(key), CType(val), + GetSizeInit(layout.GetFieldOffset(field)), + key->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING + ? "0" + : "sizeof(key)", + val->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING + ? "0" + : "sizeof(val)"); + output( + "UPB_INLINE bool $0_$1_delete($0 *msg, $2 key) { " + "return _upb_msg_map_delete(msg, $3, &key, $4); }\n", + msg_name, field->name(), CType(key), + GetSizeInit(layout.GetFieldOffset(field)), + key->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING + ? "0" + : "sizeof(key)"); + output( + "UPB_INLINE $0 $1_$2_nextmutable($1 *msg, size_t* iter) { " + "return ($0)_upb_msg_map_next(msg, $3, iter); }\n", + CType(field), msg_name, field->name(), + GetSizeInit(layout.GetFieldOffset(field))); +} + +void GenerateRepeatedSetters(const protobuf::FieldDescriptor* field, + const MessageLayout& layout, + absl::string_view msg_name, Output& output) { + output( + "UPB_INLINE $0* $1_mutable_$2($1 *msg, size_t *len) {\n" + " return ($0*)_upb_array_mutable_accessor(msg, $3, len);\n" + "}\n", + CType(field), msg_name, field->name(), + GetSizeInit(layout.GetFieldOffset(field))); + output( + "UPB_INLINE $0* $1_resize_$2($1 *msg, size_t len, " + "upb_Arena *arena) {\n" + " return ($0*)_upb_Array_Resize_accessor2(msg, $3, len, $4, " + "arena);\n" + "}\n", + CType(field), msg_name, field->name(), + GetSizeInit(layout.GetFieldOffset(field)), SizeLg2(field)); + if (field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_MESSAGE) { output( - " $0_NOT_SET = 0\n" - "} $0_oneofcases;\n", - fullname); + "UPB_INLINE struct $0* $1_add_$2($1 *msg, upb_Arena *arena) {\n" + " struct $0* sub = (struct $0*)_upb_Message_New(&$3, arena);\n" + " bool ok = _upb_Array_Append_accessor2(\n" + " msg, $4, $5, &sub, arena);\n" + " if (!ok) return NULL;\n" + " return sub;\n" + "}\n", + MessageName(field->message_type()), msg_name, field->name(), + MessageInit(field->message_type()), + GetSizeInit(layout.GetFieldOffset(field)), SizeLg2(field)); + } else { output( - "UPB_INLINE $0_oneofcases $1_$2_case(const $1* msg) { " - "return ($0_oneofcases)*UPB_PTR_AT(msg, $3, int32_t); }\n" - "\n", - fullname, msg_name, oneof->name(), - GetSizeInit(layout.GetOneofCaseOffset(oneof))); + "UPB_INLINE bool $1_add_$2($1 *msg, $0 val, upb_Arena *arena) {\n" + " return _upb_Array_Append_accessor2(msg, $3, $4, &val,\n" + " arena);\n" + "}\n", + CType(field), msg_name, field->name(), + GetSizeInit(layout.GetFieldOffset(field)), SizeLg2(field)); } +} - // Generate const methods. +void GenerateNonRepeatedSetters(const protobuf::FieldDescriptor* field, + const MessageLayout& layout, + absl::string_view msg_name, Output& output) { + if (field == field->containing_type()->map_key()) { + // Key cannot be mutated. + return; + } - for (auto field : FieldNumberOrder(message)) { - // Generate hazzer (if any). - if (layout.HasHasbit(field)) { - output( - "UPB_INLINE bool $0_has_$1(const $0 *msg) { " - "return _upb_hasbit(msg, $2); }\n", - msg_name, field->name(), layout.GetHasbitIndex(field)); - } else if (field->real_containing_oneof()) { - output( - "UPB_INLINE bool $0_has_$1(const $0 *msg) { " - "return _upb_getoneofcase(msg, $2) == $3; }\n", - msg_name, field->name(), - GetSizeInit( - layout.GetOneofCaseOffset(field->real_containing_oneof())), - field->number()); - } else if (field->message_type()) { - output( - "UPB_INLINE bool $0_has_$1(const $0 *msg) { " - "return _upb_has_submsg_nohasbit(msg, $2); }\n", - msg_name, field->name(), GetSizeInit(layout.GetFieldOffset(field))); - } + // The common function signature for all setters. Varying + // implementations follow. + output("UPB_INLINE void $0_set_$1($0 *msg, $2 value) {\n", msg_name, + field->name(), CType(field)); - // Generate getter. - if (field->is_map()) { - const protobuf::Descriptor* entry = field->message_type(); - const protobuf::FieldDescriptor* key = entry->FindFieldByNumber(1); - const protobuf::FieldDescriptor* val = entry->FindFieldByNumber(2); - output( - "UPB_INLINE size_t $0_$1_size(const $0 *msg) {" - "return _upb_msg_map_size(msg, $2); }\n", - msg_name, field->name(), GetSizeInit(layout.GetFieldOffset(field))); - output( - "UPB_INLINE bool $0_$1_get(const $0 *msg, $2 key, $3 *val) { " - "return _upb_msg_map_get(msg, $4, &key, $5, val, $6); }\n", - msg_name, field->name(), CType(key), CType(val), - GetSizeInit(layout.GetFieldOffset(field)), - key->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING - ? "0" - : "sizeof(key)", - val->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING - ? "0" - : "sizeof(*val)"); - output( - "UPB_INLINE $0 $1_$2_next(const $1 *msg, size_t* iter) { " - "return ($0)_upb_msg_map_next(msg, $3, iter); }\n", - CTypeConst(field), msg_name, field->name(), - GetSizeInit(layout.GetFieldOffset(field))); - } else if (message->options().map_entry()) { - output( - "UPB_INLINE $0 $1_$2(const $1 *msg) {\n" - " $3 ret;\n" - " _upb_msg_map_$2(msg, &ret, $4);\n" - " return ret;\n" - "}\n", - CTypeConst(field), msg_name, field->name(), CType(field), - field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING - ? "0" - : "sizeof(ret)"); - } else if (field->is_repeated()) { - output( - "UPB_INLINE $0 const* $1_$2(const $1 *msg, size_t *len) { " - "return ($0 const*)_upb_array_accessor(msg, $3, len); }\n", - CTypeConst(field), msg_name, field->name(), - GetSizeInit(layout.GetFieldOffset(field))); - } else if (field->real_containing_oneof()) { - output( - "UPB_INLINE $0 $1_$2(const $1 *msg) { " - "return UPB_READ_ONEOF(msg, $0, $3, $4, $5, $6); }\n", - CTypeConst(field), msg_name, field->name(), - GetSizeInit(layout.GetFieldOffset(field)), - GetSizeInit( - layout.GetOneofCaseOffset(field->real_containing_oneof())), - field->number(), FieldDefault(field)); - } else { - if (HasNonZeroDefault(field)) { - output( - R"cc( - UPB_INLINE $0 $1_$2(const $1* msg) { - return $1_has_$2(msg) ? *UPB_PTR_AT(msg, $3, $0) : $4; - } - )cc", - CTypeConst(field), msg_name, field->name(), - GetSizeInit(layout.GetFieldOffset(field)), FieldDefault(field)); - } else { - output( - R"cc( - UPB_INLINE $0 $1_$2(const $1* msg) { - return *UPB_PTR_AT(msg, $3, $0); - } - )cc", - CTypeConst(field), msg_name, field->name(), - GetSizeInit(layout.GetFieldOffset(field))); - } + if (field == field->containing_type()->map_value()) { + output( + " _upb_msg_map_set_value(msg, &value, $0);\n" + "}\n", + field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING + ? "0" + : "sizeof(" + CType(field) + ")"); + } else if (field->real_containing_oneof()) { + output( + " UPB_WRITE_ONEOF(msg, $0, $1, value, $2, $3);\n" + "}\n", + CType(field), GetSizeInit(layout.GetFieldOffset(field)), + GetSizeInit(layout.GetOneofCaseOffset(field->real_containing_oneof())), + field->number()); + } else { + if (MessageLayout::HasHasbit(field)) { + output(" _upb_sethas(msg, $0);\n", layout.GetHasbitIndex(field)); } + output( + " *UPB_PTR_AT(msg, $1, $0) = value;\n" + "}\n", + CType(field), GetSizeInit(layout.GetFieldOffset(field))); } - output("\n"); + // Message fields also have a Msg_mutable_foo() accessor that will create + // the sub-message if it doesn't already exist. + if (field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_MESSAGE && + !field->containing_type()->options().map_entry()) { + output( + "UPB_INLINE struct $0* $1_mutable_$2($1 *msg, upb_Arena *arena) " + "{\n" + " struct $0* sub = (struct $0*)$1_$2(msg);\n" + " if (sub == NULL) {\n" + " sub = (struct $0*)_upb_Message_New(&$3, arena);\n" + " if (!sub) return NULL;\n" + " $1_set_$2(msg, sub);\n" + " }\n" + " return sub;\n" + "}\n", + MessageName(field->message_type()), msg_name, field->name(), + MessageInit(field->message_type())); + } +} + +void GenerateSetters(const protobuf::FieldDescriptor* field, + const MessageLayout& layout, absl::string_view msg_name, + Output& output) { + if (field->is_map()) { + GenerateMapSetters(field, layout, msg_name, output); + } else if (field->is_repeated()) { + GenerateRepeatedSetters(field, layout, msg_name, output); + } else { + GenerateNonRepeatedSetters(field, layout, msg_name, output); + } +} + +void GenerateMessageInHeader(const protobuf::Descriptor* message, + Output& output) { + MessageLayout layout(message); - // Generate mutable methods. + output("/* $0 */\n\n", message->full_name()); + std::string msg_name = ToCIdent(message->full_name()); + + if (!message->options().map_entry()) { + GenerateMessageFunctionsInHeader(message, output); + } + + for (int i = 0; i < message->real_oneof_decl_count(); i++) { + GenerateOneofInHeader(message->oneof_decl(i), layout, msg_name, output); + } for (auto field : FieldNumberOrder(message)) { - if (field->is_map()) { - // TODO(haberman): add map-based mutators. - const protobuf::Descriptor* entry = field->message_type(); - const protobuf::FieldDescriptor* key = entry->FindFieldByNumber(1); - const protobuf::FieldDescriptor* val = entry->FindFieldByNumber(2); - output( - "UPB_INLINE void $0_$1_clear($0 *msg) { _upb_msg_map_clear(msg, $2); " - "}\n", - msg_name, field->name(), GetSizeInit(layout.GetFieldOffset(field))); - output( - "UPB_INLINE bool $0_$1_set($0 *msg, $2 key, $3 val, upb_Arena *a) { " - "return _upb_msg_map_set(msg, $4, &key, $5, &val, $6, a); }\n", - msg_name, field->name(), CType(key), CType(val), - GetSizeInit(layout.GetFieldOffset(field)), - key->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING - ? "0" - : "sizeof(key)", - val->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING - ? "0" - : "sizeof(val)"); - output( - "UPB_INLINE bool $0_$1_delete($0 *msg, $2 key) { " - "return _upb_msg_map_delete(msg, $3, &key, $4); }\n", - msg_name, field->name(), CType(key), - GetSizeInit(layout.GetFieldOffset(field)), - key->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING - ? "0" - : "sizeof(key)"); - output( - "UPB_INLINE $0 $1_$2_nextmutable($1 *msg, size_t* iter) { " - "return ($0)_upb_msg_map_next(msg, $3, iter); }\n", - CType(field), msg_name, field->name(), - GetSizeInit(layout.GetFieldOffset(field))); - } else if (field->is_repeated()) { - output( - "UPB_INLINE $0* $1_mutable_$2($1 *msg, size_t *len) {\n" - " return ($0*)_upb_array_mutable_accessor(msg, $3, len);\n" - "}\n", - CType(field), msg_name, field->name(), - GetSizeInit(layout.GetFieldOffset(field))); - output( - "UPB_INLINE $0* $1_resize_$2($1 *msg, size_t len, " - "upb_Arena *arena) {\n" - " return ($0*)_upb_Array_Resize_accessor2(msg, $3, len, $4, " - "arena);\n" - "}\n", - CType(field), msg_name, field->name(), - GetSizeInit(layout.GetFieldOffset(field)), SizeLg2(field)); - if (field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_MESSAGE) { - output( - "UPB_INLINE struct $0* $1_add_$2($1 *msg, upb_Arena *arena) {\n" - " struct $0* sub = (struct $0*)_upb_Message_New(&$3, arena);\n" - " bool ok = _upb_Array_Append_accessor2(\n" - " msg, $4, $5, &sub, arena);\n" - " if (!ok) return NULL;\n" - " return sub;\n" - "}\n", - MessageName(field->message_type()), msg_name, field->name(), - MessageInit(field->message_type()), - GetSizeInit(layout.GetFieldOffset(field)), SizeLg2(field)); - } else { - output( - "UPB_INLINE bool $1_add_$2($1 *msg, $0 val, upb_Arena *arena) {\n" - " return _upb_Array_Append_accessor2(msg, $3, $4, &val,\n" - " arena);\n" - "}\n", - CType(field), msg_name, field->name(), - GetSizeInit(layout.GetFieldOffset(field)), SizeLg2(field)); - } - } else { - // Non-repeated field. - if (message->options().map_entry() && field->name() == "key") { - // Key cannot be mutated. - continue; - } + GenerateHazzer(field, layout, msg_name, output); + GenerateGetters(field, layout, msg_name, output); + } - // The common function signature for all setters. Varying implementations - // follow. - output("UPB_INLINE void $0_set_$1($0 *msg, $2 value) {\n", msg_name, - field->name(), CType(field)); - - if (message->options().map_entry()) { - output( - " _upb_msg_map_set_value(msg, &value, $0);\n" - "}\n", - field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING - ? "0" - : "sizeof(" + CType(field) + ")"); - } else if (field->real_containing_oneof()) { - output( - " UPB_WRITE_ONEOF(msg, $0, $1, value, $2, $3);\n" - "}\n", - CType(field), GetSizeInit(layout.GetFieldOffset(field)), - GetSizeInit( - layout.GetOneofCaseOffset(field->real_containing_oneof())), - field->number()); - } else { - if (MessageLayout::HasHasbit(field)) { - output(" _upb_sethas(msg, $0);\n", layout.GetHasbitIndex(field)); - } - output( - " *UPB_PTR_AT(msg, $1, $0) = value;\n" - "}\n", - CType(field), GetSizeInit(layout.GetFieldOffset(field))); - } + output("\n"); - if (field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_MESSAGE && - !message->options().map_entry()) { - output( - "UPB_INLINE struct $0* $1_mutable_$2($1 *msg, upb_Arena *arena) {\n" - " struct $0* sub = (struct $0*)$1_$2(msg);\n" - " if (sub == NULL) {\n" - " sub = (struct $0*)_upb_Message_New(&$3, arena);\n" - " if (!sub) return NULL;\n" - " $1_set_$2(msg, sub);\n" - " }\n" - " return sub;\n" - "}\n", - MessageName(field->message_type()), msg_name, field->name(), - MessageInit(field->message_type())); - } - } + for (auto field : FieldNumberOrder(message)) { + GenerateSetters(field, layout, msg_name, output); } output("\n");