summaryrefslogtreecommitdiff
path: root/upbc
diff options
context:
space:
mode:
authorJoshua Haberman <jhaberman@gmail.com>2019-01-29 08:26:00 -0800
committerGitHub <noreply@github.com>2019-01-29 08:26:00 -0800
commit2b62fbce6734eb672ae6ff6fcf258bfff4267ae8 (patch)
treec39dd54ef29a0b6610ebd4794b1646c83c66357a /upbc
parentc7870e0f77d6331babfdb89f8c83e4e0279b5e70 (diff)
parent3d931557907307ecc19b74e8f3188301b149e99a (diff)
Merge pull request #145 from haberman/arrayapi
Generated code API changes for array and hazzers.
Diffstat (limited to 'upbc')
-rw-r--r--upbc/generator.cc209
-rw-r--r--upbc/message_layout.cc16
-rw-r--r--upbc/message_layout.h5
3 files changed, 182 insertions, 48 deletions
diff --git a/upbc/generator.cc b/upbc/generator.cc
index 0f7d14d..42e249e 100644
--- a/upbc/generator.cc
+++ b/upbc/generator.cc
@@ -177,19 +177,23 @@ std::string GetSizeInit(const MessageLayout::Size& size) {
return absl::Substitute("UPB_SIZE($0, $1)", size.size32, size.size64);
}
+std::string MessageName(const protobuf::Descriptor* descriptor) {
+ return ToCIdent(descriptor->full_name());
+}
+
+std::string MessageInit(const protobuf::Descriptor* descriptor) {
+ return MessageName(descriptor) + "_msginit";
+}
+
std::string CTypeInternal(const protobuf::FieldDescriptor* field,
bool is_const) {
std::string maybe_const = is_const ? "const " : "";
- if (field->label() == protobuf::FieldDescriptor::LABEL_REPEATED) {
- return maybe_const + "upb_array*";
- }
-
switch (field->cpp_type()) {
case protobuf::FieldDescriptor::CPPTYPE_MESSAGE: {
std::string maybe_struct =
field->file() != field->message_type()->file() ? "struct " : "";
- return maybe_const + maybe_struct +
- ToCIdent(field->message_type()->full_name()) + "*";
+ return maybe_const + maybe_struct + MessageName(field->message_type()) +
+ "*";
}
case protobuf::FieldDescriptor::CPPTYPE_ENUM:
return ToCIdent(field->enum_type()->full_name());
@@ -208,7 +212,35 @@ std::string CTypeInternal(const protobuf::FieldDescriptor* field,
case protobuf::FieldDescriptor::CPPTYPE_UINT64:
return "uint64_t";
case protobuf::FieldDescriptor::CPPTYPE_STRING:
- return "upb_stringview";
+ return "upb_strview";
+ default:
+ fprintf(stderr, "Unexpected type");
+ abort();
+ }
+}
+
+std::string UpbType(const protobuf::FieldDescriptor* field) {
+ switch (field->cpp_type()) {
+ case protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
+ return "UPB_TYPE_MESSAGE";
+ case protobuf::FieldDescriptor::CPPTYPE_ENUM:
+ return "UPB_TYPE_ENUM";
+ case protobuf::FieldDescriptor::CPPTYPE_BOOL:
+ return "UPB_TYPE_BOOL";
+ case protobuf::FieldDescriptor::CPPTYPE_FLOAT:
+ return "UPB_TYPE_FLOAT";
+ case protobuf::FieldDescriptor::CPPTYPE_INT32:
+ return "UPB_TYPE_INT32";
+ case protobuf::FieldDescriptor::CPPTYPE_UINT32:
+ return "UPB_TYPE_UINT32";
+ case protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
+ return "UPB_TYPE_DOUBLE";
+ case protobuf::FieldDescriptor::CPPTYPE_INT64:
+ return "UPB_TYPE_INT64";
+ case protobuf::FieldDescriptor::CPPTYPE_UINT64:
+ return "UPB_TYPE_UINT64";
+ case protobuf::FieldDescriptor::CPPTYPE_STRING:
+ return "UPB_TYPE_STRING";
default:
fprintf(stderr, "Unexpected type");
abort();
@@ -220,7 +252,7 @@ std::string FieldDefault(const protobuf::FieldDescriptor* field) {
case protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
return "NULL";
case protobuf::FieldDescriptor::CPPTYPE_STRING:
- return absl::Substitute("upb_stringview_make(\"$0\", strlen(\"$0\"))",
+ return absl::Substitute("upb_strview_make(\"$0\", strlen(\"$0\"))",
absl::CEscape(field->default_value_string()));
case protobuf::FieldDescriptor::CPPTYPE_INT32:
return absl::StrCat(field->default_value_int32());
@@ -290,20 +322,19 @@ void GenerateMessageInHeader(const protobuf::Descriptor* message, Output& output
output("/* $0 */\n\n", message->full_name());
std::string msgname = ToCIdent(message->full_name());
output(
- "extern const upb_msglayout $0_msginit;\n"
"UPB_INLINE $0 *$0_new(upb_arena *arena) {\n"
- " return ($0 *)upb_msg_new(&$0_msginit, arena);\n"
+ " return ($0 *)upb_msg_new(&$1, arena);\n"
"}\n"
- "UPB_INLINE $0 *$0_parsenew(upb_stringview buf, upb_arena *arena) {\n"
+ "UPB_INLINE $0 *$0_parsenew(upb_strview buf, upb_arena *arena) {\n"
" $0 *ret = $0_new(arena);\n"
- " return (ret && upb_decode(buf, ret, &$0_msginit)) ? ret : NULL;\n"
+ " return (ret && upb_decode(buf, ret, &$1)) ? ret : NULL;\n"
"}\n"
"UPB_INLINE char *$0_serialize(const $0 *msg, upb_arena *arena, size_t "
"*len) {\n"
- " return upb_encode(msg, &$0_msginit, arena, len);\n"
+ " return upb_encode(msg, &$1, arena, len);\n"
"}\n"
"\n",
- msgname);
+ MessageName(message), MessageInit(message));
for (int i = 0; i < message->oneof_decl_count(); i++) {
const protobuf::OneofDescriptor* oneof = message->oneof_decl(i);
@@ -326,32 +357,122 @@ void GenerateMessageInHeader(const protobuf::Descriptor* message, Output& output
}
for (auto field : FieldNumberOrder(message)) {
- output("UPB_INLINE $0 $1_$2(const $1 *msg) {", CTypeConst(field), msgname,
- field->name());
- if (field->containing_oneof()) {
- output(" return UPB_READ_ONEOF(msg, $0, $1, $2, $3, $4); }\n",
- CTypeConst(field), GetSizeInit(layout.GetFieldOffset(field)),
- GetSizeInit(layout.GetOneofCaseOffset(field->containing_oneof())),
- field->number(), FieldDefault(field));
+
+ if (layout.HasHasbit(field)) {
+ output(
+ "UPB_INLINE bool $0_has_$1(const $0 *msg) { "
+ "return _upb_has_field(msg, $2); }\n",
+ msgname, field->name(), layout.GetHasbitIndex(field));
+ } else if (field->containing_oneof()) {
+ output(
+ "UPB_INLINE bool $0_has_$1(const $0 *msg) { "
+ "return _upb_has_oneof_field(msg, $2, $3); }\n",
+ msgname, field->name(),
+ GetSizeInit(layout.GetOneofCaseOffset(field->containing_oneof())),
+ field->number());
+ }
+
+ 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), msgname, field->name(),
+ GetSizeInit(layout.GetFieldOffset(field)));
+ } else if (field->containing_oneof()) {
+ output(
+ "UPB_INLINE $0 $1_$2(const $1 *msg) { "
+ "return UPB_READ_ONEOF(msg, $0, $3, $4, $5, $6); }\n",
+ CTypeConst(field), msgname, field->name(),
+ GetSizeInit(layout.GetFieldOffset(field)),
+ GetSizeInit(layout.GetOneofCaseOffset(field->containing_oneof())),
+ field->number(), FieldDefault(field));
} else {
- output(" return UPB_FIELD_AT(msg, $0, $1); }\n", CTypeConst(field),
- GetSizeInit(layout.GetFieldOffset(field)));
+ output(
+ "UPB_INLINE $0 $1_$2(const $1 *msg) { "
+ "return UPB_FIELD_AT(msg, $0, $3); }\n",
+ CTypeConst(field), msgname, field->name(),
+ GetSizeInit(layout.GetFieldOffset(field)));
}
}
output("\n");
for (auto field : FieldNumberOrder(message)) {
- output("UPB_INLINE void $0_set_$1($0 *msg, $2 value) { ", msgname,
- field->name(), CType(field));
- if (field->containing_oneof()) {
- output("UPB_WRITE_ONEOF(msg, $0, $1, value, $2, $3); }\n", CType(field),
- GetSizeInit(layout.GetFieldOffset(field)),
- GetSizeInit(layout.GetOneofCaseOffset(field->containing_oneof())),
- field->number());
+ 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), msgname, 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_accessor(msg, $3, len, $4, $5, "
+ "arena);\n"
+ "}\n",
+ CType(field), msgname, field->name(),
+ GetSizeInit(layout.GetFieldOffset(field)),
+ GetSizeInit(MessageLayout::SizeOfUnwrapped(field).size),
+ UpbType(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_msg_new(&$3, arena);\n"
+ " bool ok = _upb_array_append_accessor(\n"
+ " msg, $4, $5, $6, &sub, arena);\n"
+ " if (!ok) return NULL;\n"
+ " return sub;\n"
+ "}\n",
+ MessageName(field->message_type()), msgname, field->name(),
+ MessageInit(field->message_type()),
+ GetSizeInit(layout.GetFieldOffset(field)),
+ GetSizeInit(MessageLayout::SizeOfUnwrapped(field).size),
+ UpbType(field));
+ } else {
+ output(
+ "UPB_INLINE bool $1_add_$2($1 *msg, $0 val, upb_arena *arena) {\n"
+ " return _upb_array_append_accessor(\n"
+ " msg, $3, $4, $5, &val, arena);\n"
+ "}\n",
+ CType(field), msgname, field->name(),
+ GetSizeInit(layout.GetFieldOffset(field)),
+ GetSizeInit(MessageLayout::SizeOfUnwrapped(field).size),
+ UpbType(field));
+ }
} else {
- output("UPB_FIELD_AT(msg, $0, $1) = value; }\n", CType(field),
- GetSizeInit(layout.GetFieldOffset(field)));
+ output("UPB_INLINE void $0_set_$1($0 *msg, $2 value) {\n", msgname,
+ field->name(), CType(field));
+ if (field->containing_oneof()) {
+ output(
+ " UPB_WRITE_ONEOF(msg, $0, $1, value, $2, $3);\n"
+ "}\n",
+ CType(field), GetSizeInit(layout.GetFieldOffset(field)),
+ GetSizeInit(layout.GetOneofCaseOffset(field->containing_oneof())),
+ field->number());
+ } else {
+ if (MessageLayout::HasHasbit(field)) {
+ output(" _upb_sethas(msg, $0);\n", layout.GetHasbitIndex(field));
+ }
+ output(
+ " UPB_FIELD_AT(msg, $0, $1) = value;\n"
+ "}\n",
+ CType(field), GetSizeInit(layout.GetFieldOffset(field)));
+ }
+ if (field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_MESSAGE) {
+ 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_msg_new(&$3, arena);\n"
+ " if (!sub) return NULL;\n"
+ " $1_set_$2(msg, sub);\n"
+ " }\n"
+ " return sub;\n"
+ "}\n",
+ MessageName(field->message_type()), msgname, field->name(),
+ MessageInit(field->message_type()));
+ }
}
}
@@ -363,6 +484,7 @@ void WriteHeader(const protobuf::FileDescriptor* file, Output& output) {
output(
"#ifndef $0_UPB_H_\n"
"#define $0_UPB_H_\n\n"
+ "#include \"upb/generated_util.h\"\n\n"
"#include \"upb/msg.h\"\n\n"
"#include \"upb/decode.h\"\n"
"#include \"upb/encode.h\"\n"
@@ -376,21 +498,27 @@ void WriteHeader(const protobuf::FileDescriptor* file, Output& output) {
}
for (auto message : SortedMessages(file)) {
output("typedef struct $0 $0;\n", ToCIdent(message->full_name()));
- };
+ }
+ for (auto message : SortedMessages(file)) {
+ output("extern const upb_msglayout $0;\n", MessageInit(message));
+ }
// Forward-declare types not in this file, but used as submessages.
- std::set<std::string> forward_names;
+ std::set<const protobuf::Descriptor*> forward_messages;
for (auto message : SortedMessages(file)) {
for (int i = 0; i < message->field_count(); i++) {
const protobuf::FieldDescriptor* field = message->field(i);
if (field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_MESSAGE &&
- field->file() != message->file()) {
- forward_names.insert(ToCIdent(field->message_type()->full_name()));
+ field->file() != field->message_type()->file()) {
+ forward_messages.insert(field->message_type());
}
}
}
- for (const auto& name : forward_names) {
- output("struct $0;\n", name);
+ for (const auto& descriptor : forward_messages) {
+ output("struct $0;\n", MessageName(descriptor));
+ }
+ for (const auto& descriptor : forward_messages) {
+ output("extern const upb_msglayout $0;\n", MessageInit(descriptor));
}
output(
@@ -458,8 +586,7 @@ void WriteSource(const protobuf::FileDescriptor* file, Output& output) {
submsg_indexes.end()) {
continue;
}
- output(" &$0_msginit,\n",
- ToCIdent(submsg->message_type()->full_name()));
+ output(" &$0,\n", MessageInit(submsg->message_type()));
submsg_indexes[submsg->message_type()] = i++;
}
@@ -504,7 +631,7 @@ void WriteSource(const protobuf::FileDescriptor* file, Output& output) {
output("};\n\n");
}
- output("const upb_msglayout $0_msginit = {\n", msgname);
+ output("const upb_msglayout $0 = {\n", MessageInit(message));
output(" $0,\n", submsgs_array_ref);
output(" $0,\n", fields_array_ref);
output(" $0, $1, $2,\n", GetSizeInit(layout.message_size()),
diff --git a/upbc/message_layout.cc b/upbc/message_layout.cc
index b6614f0..5956424 100644
--- a/upbc/message_layout.cc
+++ b/upbc/message_layout.cc
@@ -30,16 +30,20 @@ bool MessageLayout::HasHasbit(const protobuf::FieldDescriptor* field) {
MessageLayout::SizeAndAlign MessageLayout::SizeOf(
const protobuf::FieldDescriptor* field) {
- if (field->label() == protobuf::FieldDescriptor::LABEL_REPEATED ||
- field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_MESSAGE) {
- return {{4, 8}, {4, 8}};
+ if (field->is_repeated()) {
+ return {{4, 8}, {4, 8}}; // Pointer to array object.
+ } else {
+ return SizeOfUnwrapped(field);
}
+}
+MessageLayout::SizeAndAlign MessageLayout::SizeOfUnwrapped(
+ const protobuf::FieldDescriptor* field) {
switch (field->cpp_type()) {
+ case protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
+ return {{4, 8}, {4, 8}}; // Pointer to message.
case protobuf::FieldDescriptor::CPPTYPE_STRING:
- // upb_stringview
- // return {{8, 16}, {4, 8}};
- return {{8, 16}, {8, 16}};
+ return {{8, 16}, {4, 8}}; // upb_stringview
case protobuf::FieldDescriptor::CPPTYPE_BOOL:
return {{1, 1}, {1, 1}};
case protobuf::FieldDescriptor::CPPTYPE_FLOAT:
diff --git a/upbc/message_layout.h b/upbc/message_layout.h
index bdcc336..a4cb289 100644
--- a/upbc/message_layout.h
+++ b/upbc/message_layout.h
@@ -60,6 +60,8 @@ class MessageLayout {
Size message_size() const { return size_; }
static bool HasHasbit(const google::protobuf::FieldDescriptor* field);
+ static SizeAndAlign SizeOfUnwrapped(
+ const google::protobuf::FieldDescriptor* field);
private:
void ComputeLayout(const google::protobuf::Descriptor* descriptor);
@@ -87,7 +89,8 @@ class MessageLayout {
}
static SizeAndAlign SizeOf(const google::protobuf::FieldDescriptor* field);
- static int64_t FieldLayoutRank(const google::protobuf::FieldDescriptor* field);
+ static int64_t FieldLayoutRank(
+ const google::protobuf::FieldDescriptor* field);
std::unordered_map<const google::protobuf::FieldDescriptor*, Size>
field_offsets_;
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback