hpb_generator: abrogate output in favour of io::Printer

We unify hpb's impl to utilize Protobuf's canonical printer, as opposed to a bespoke solution.

- augment hpb::Context with EmitLegacy, which keeps the $* syntax while we convert. This allows for a far simpler transitional pathway, and we can incrementally port to .Emit() as we see fit. Of course, all new calls should use .Emit().
- use the Context to wrap io::Printer and any hpb-specific info (e.g. what backend we're using)

PiperOrigin-RevId: 686198921
pull/18811/head
Hong Shin 5 months ago committed by Copybara-Service
parent 5aa7abc659
commit 082cf000ef
  1. 52
      hpb_generator/context.h
  2. 220
      hpb_generator/gen_accessors.cc
  3. 13
      hpb_generator/gen_accessors.h
  4. 19
      hpb_generator/gen_enums.cc
  5. 4
      hpb_generator/gen_enums.h
  6. 24
      hpb_generator/gen_extensions.cc
  7. 10
      hpb_generator/gen_extensions.h
  8. 181
      hpb_generator/gen_messages.cc
  9. 6
      hpb_generator/gen_messages.h
  10. 56
      hpb_generator/gen_repeated_fields.cc
  11. 12
      hpb_generator/gen_repeated_fields.h
  12. 11
      hpb_generator/names.cc
  13. 6
      hpb_generator/names.h
  14. 59
      hpb_generator/output.cc
  15. 150
      hpb_generator/output.h
  16. 133
      hpb_generator/protoc-gen-hpb.cc

@ -9,13 +9,19 @@
#define GOOGLE_PROTOBUF_COMPILER_HPB_CONTEXT_H__
#include <memory>
#include <string>
#include <utility>
#include "absl/strings/ascii.h"
#include "absl/strings/str_replace.h"
#include "absl/strings/string_view.h"
#include "absl/strings/substitute.h"
#include "absl/types/source_location.h"
#include "absl/types/span.h"
#include "google/protobuf/descriptor.h"
#include "google/protobuf/io/printer.h"
#include "google/protobuf/io/zero_copy_stream.h"
#include "upb_generator/c/names.h"
namespace google::protobuf::hpb_generator {
enum class Backend { UPB, CPP };
@ -38,11 +44,8 @@ struct Options {
*/
class Context final {
public:
Context(std::unique_ptr<io::ZeroCopyOutputStream> stream,
const Options& options)
: stream_(std::move(stream)),
printer_(stream_.get()),
options_(options) {}
Context(io::ZeroCopyOutputStream* stream, const Options& options)
: stream_(stream), printer_(stream_), options_(options) {}
void Emit(absl::Span<const io::Printer::Sub> vars, absl::string_view format,
absl::SourceLocation loc = absl::SourceLocation::current()) {
@ -54,7 +57,16 @@ class Context final {
printer_.Emit(format, loc);
}
// TODO: b/373438292 - Remove EmitLegacy in favor of Emit.
// This is an interim solution while we migrate from Output to io::Printer
template <class... Arg>
void EmitLegacy(absl::string_view format, const Arg&... arg) {
auto res = absl::Substitute(format, arg...);
printer_.Emit(res, absl::SourceLocation::current());
}
const Options& options() { return options_; }
io::Printer& printer() { return printer_; }
Context(const Context&) = delete;
Context& operator=(const Context&) = delete;
@ -62,11 +74,39 @@ class Context final {
Context& operator=(Context&&) = delete;
private:
std::unique_ptr<io::ZeroCopyOutputStream> stream_;
io::ZeroCopyOutputStream* stream_;
io::Printer printer_;
const Options& options_;
};
// TODO: b/373438292 - re-house these 4 legacy funcs post io::Printer move
inline std::string MessageName(const google::protobuf::Descriptor* descriptor) {
return upb::generator::CApiMessageType(descriptor->full_name());
}
inline std::string ToCIdent(absl::string_view str) {
return absl::StrReplaceAll(str, {{".", "_"}, {"/", "_"}, {"-", "_"}});
}
inline std::string ToPreproc(absl::string_view str) {
return absl::AsciiStrToUpper(ToCIdent(str));
}
inline void EmitFileWarning(const google::protobuf::FileDescriptor* file, Context& ctx) {
ctx.EmitLegacy(
R"cc(
/* This file was generated by hpb_generator (Handle Protobuf) "
from the input
* file:
*
* $0
*
* Do not edit -- your changes will be discarded when the file is
* regenerated. */
)cc",
file->name());
ctx.Emit("\n");
}
} // namespace protobuf
} // namespace google::hpb_generator

@ -10,14 +10,15 @@
#include <string>
#include "absl/container/flat_hash_set.h"
#include "absl/strings/ascii.h"
#include "absl/strings/match.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "google/protobuf/compiler/hpb/context.h"
#include "google/protobuf/compiler/hpb/gen_repeated_fields.h"
#include "google/protobuf/compiler/hpb/gen_utils.h"
#include "google/protobuf/compiler/hpb/keywords.h"
#include "google/protobuf/compiler/hpb/names.h"
#include "google/protobuf/compiler/hpb/output.h"
#include "google/protobuf/descriptor.h"
#include "upb_generator/c/names.h"
#include "upb_generator/minitable/names.h"
@ -33,22 +34,21 @@ void WriteFieldAccessorHazzer(const protobuf::Descriptor* desc,
const protobuf::FieldDescriptor* field,
absl::string_view resolved_field_name,
absl::string_view resolved_upbc_name,
Output& output);
Context& ctx);
void WriteFieldAccessorClear(const protobuf::Descriptor* desc,
const protobuf::FieldDescriptor* field,
absl::string_view resolved_field_name,
absl::string_view resolved_upbc_name,
Output& output);
Context& ctx);
void WriteMapFieldAccessors(const protobuf::Descriptor* desc,
const protobuf::FieldDescriptor* field,
absl::string_view resolved_field_name,
absl::string_view resolved_upbc_name,
Output& output);
absl::string_view resolved_upbc_name, Context& ctx);
void WriteMapAccessorDefinitions(const protobuf::Descriptor* message,
const protobuf::FieldDescriptor* field,
absl::string_view resolved_field_name,
absl::string_view class_name, Output& output);
absl::string_view class_name, Context& ctx);
// Returns C++ class member name by resolving naming conflicts across
// proto field names (such as clear_ prefixes) and keyword collisions.
@ -75,55 +75,55 @@ NameToFieldDescriptorMap CreateFieldNameMap(
}
void WriteFieldAccessorsInHeader(const protobuf::Descriptor* desc,
Output& output) {
Context& ctx) {
// Generate const methods.
OutputIndenter i(output);
auto field_names = CreateFieldNameMap(desc);
auto mangler = CreateNameMangler(desc);
auto indent = ctx.printer().WithIndent();
for (const auto* field : FieldNumberOrder(desc)) {
std::string resolved_field_name = ResolveFieldName(field, field_names);
std::string resolved_upbc_name = mangler.ResolveFieldName(field->name());
WriteFieldAccessorHazzer(desc, field, resolved_field_name,
resolved_upbc_name, output);
resolved_upbc_name, ctx);
WriteFieldAccessorClear(desc, field, resolved_field_name,
resolved_upbc_name, output);
resolved_upbc_name, ctx);
if (field->is_map()) {
WriteMapFieldAccessors(desc, field, resolved_field_name,
resolved_upbc_name, output);
resolved_upbc_name, ctx);
} else if (desc->options().map_entry()) {
// TODO Implement map entry
} else if (field->is_repeated()) {
WriteRepeatedFieldsInMessageHeader(desc, field, resolved_field_name,
resolved_upbc_name, output);
resolved_upbc_name, ctx);
} else {
// non-repeated.
if (field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING) {
output(R"cc(
$0 $1() const;
void set_$1($0 value);
)cc",
CppConstType(field), resolved_field_name);
ctx.EmitLegacy(R"cc(
$0 $1() const;
void set_$1($0 value);
)cc",
CppConstType(field), resolved_field_name);
} else if (field->cpp_type() ==
protobuf::FieldDescriptor::CPPTYPE_MESSAGE) {
output(R"cc(
$1 $2() const;
$0 mutable_$2();
/**
* Re-points submessage to the given target.
*
* REQUIRES:
* - both messages must be in the same arena.
*/
void set_alias_$2($0 target);
)cc",
MessagePtrConstType(field, /* const */ false),
MessagePtrConstType(field, /* const */ true),
resolved_field_name);
ctx.EmitLegacy(R"cc(
$1 $2() const;
$0 mutable_$2();
/**
* Re-points submessage to the given target.
*
* REQUIRES:
* - both messages must be in the same arena.
*/
void set_alias_$2($0 target);
)cc",
MessagePtrConstType(field, /* const */ false),
MessagePtrConstType(field, /* const */ true),
resolved_field_name);
} else {
output(
ctx.EmitLegacy(
R"cc(
inline $0 $1() const { return $2_$3(msg_); }
inline void set_$1($0 value) { return $2_set_$3(msg_, value); }
@ -139,12 +139,12 @@ void WriteFieldAccessorHazzer(const protobuf::Descriptor* desc,
const protobuf::FieldDescriptor* field,
const absl::string_view resolved_field_name,
const absl::string_view resolved_upbc_name,
Output& output) {
Context& ctx) {
// Generate hazzer (if any).
if (field->has_presence()) {
// Has presence.
output("inline bool has_$0() const { return $1_has_$2(msg_); }\n",
resolved_field_name, MessageName(desc), resolved_upbc_name);
ctx.EmitLegacy("inline bool has_$0() const { return $1_has_$2(msg_); }\n",
resolved_field_name, MessageName(desc), resolved_upbc_name);
}
}
@ -152,10 +152,10 @@ void WriteFieldAccessorClear(const protobuf::Descriptor* desc,
const protobuf::FieldDescriptor* field,
const absl::string_view resolved_field_name,
const absl::string_view resolved_upbc_name,
Output& output) {
Context& ctx) {
if (field->has_presence()) {
output("void clear_$0() { $2_clear_$1(msg_); }\n", resolved_field_name,
resolved_upbc_name, MessageName(desc));
ctx.EmitLegacy("void clear_$0() { $2_clear_$1(msg_); }\n",
resolved_field_name, resolved_upbc_name, MessageName(desc));
}
}
@ -163,11 +163,11 @@ void WriteMapFieldAccessors(const protobuf::Descriptor* desc,
const protobuf::FieldDescriptor* field,
const absl::string_view resolved_field_name,
const absl::string_view resolved_upbc_name,
Output& output) {
Context& ctx) {
const protobuf::Descriptor* entry = field->message_type();
const protobuf::FieldDescriptor* key = entry->FindFieldByNumber(1);
const protobuf::FieldDescriptor* val = entry->FindFieldByNumber(2);
output(
ctx.EmitLegacy(
R"cc(
inline size_t $0_size() const { return $1_$3_size(msg_); }
inline void clear_$0() { $1_clear_$3(msg_); }
@ -177,7 +177,7 @@ void WriteMapFieldAccessors(const protobuf::Descriptor* desc,
resolved_upbc_name);
if (val->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_MESSAGE) {
output(
ctx.EmitLegacy(
R"cc(
bool set_$0($1 key, $3 value);
bool set_$0($1 key, $4 value);
@ -189,7 +189,7 @@ void WriteMapFieldAccessors(const protobuf::Descriptor* desc,
MessagePtrConstType(val, /* is_const */ true),
MessagePtrConstType(val, /* is_const */ false));
} else {
output(
ctx.EmitLegacy(
R"cc(
bool set_$0($1 key, $2 value);
absl::StatusOr<$2> get_$0($1 key);
@ -198,40 +198,40 @@ void WriteMapFieldAccessors(const protobuf::Descriptor* desc,
}
}
void WriteAccessorsInSource(const protobuf::Descriptor* desc, Output& output) {
void WriteAccessorsInSource(const protobuf::Descriptor* desc, Context& ctx) {
std::string class_name = ClassName(desc);
absl::StrAppend(&class_name, "Access");
output("namespace internal {\n");
ctx.Emit("namespace internal {\n");
const char arena_expression[] = "arena_";
auto field_names = CreateFieldNameMap(desc);
auto mangler = CreateNameMangler(desc);
// Generate const methods.
OutputIndenter i(output);
auto indent = ctx.printer().WithIndent();
for (const auto* field : FieldNumberOrder(desc)) {
std::string resolved_field_name = ResolveFieldName(field, field_names);
std::string resolved_upbc_name = mangler.ResolveFieldName(field->name());
if (field->is_map()) {
WriteMapAccessorDefinitions(desc, field, resolved_field_name, class_name,
output);
ctx);
} else if (desc->options().map_entry()) {
// TODO Implement map entry
} else if (field->is_repeated()) {
if (field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_MESSAGE) {
WriteRepeatedMessageAccessor(desc, field, resolved_field_name,
class_name, output);
class_name, ctx);
} else if (field->cpp_type() ==
protobuf::FieldDescriptor::CPPTYPE_STRING) {
WriteRepeatedStringAccessor(desc, field, resolved_field_name,
class_name, output);
class_name, ctx);
} else {
WriteRepeatedScalarAccessor(desc, field, resolved_field_name,
class_name, output);
class_name, ctx);
}
} else {
// non-repeated field.
if (field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING) {
output(
ctx.EmitLegacy(
R"cc(
$1 $0::$2() const {
return hpb::interop::upb::FromUpbStringView($3_$4(msg_));
@ -240,7 +240,7 @@ void WriteAccessorsInSource(const protobuf::Descriptor* desc, Output& output) {
class_name, CppConstType(field), resolved_field_name,
MessageName(desc), resolved_upbc_name);
// Set string.
output(
ctx.EmitLegacy(
R"cc(
void $0::set_$2($1 value) {
$4_set_$3(msg_, hpb::interop::upb::CopyToUpbStringView(value, $5));
@ -250,7 +250,7 @@ void WriteAccessorsInSource(const protobuf::Descriptor* desc, Output& output) {
resolved_upbc_name, MessageName(desc), arena_expression);
} else if (field->cpp_type() ==
protobuf::FieldDescriptor::CPPTYPE_MESSAGE) {
output(
ctx.EmitLegacy(
R"cc(
$1 $0::$2() const {
if (!has_$2()) {
@ -265,7 +265,7 @@ void WriteAccessorsInSource(const protobuf::Descriptor* desc, Output& output) {
MessageBaseType(field, /* maybe_const */ false),
resolved_upbc_name);
output(
ctx.EmitLegacy(
R"cc(
$1 $0::mutable_$2() {
return hpb::interop::upb::MakeHandle<$4>(
@ -286,15 +286,15 @@ void WriteAccessorsInSource(const protobuf::Descriptor* desc, Output& output) {
}
}
}
output("\n");
output("} // namespace internal\n\n");
ctx.Emit("\n");
ctx.Emit("} // namespace internal\n\n");
}
void WriteMapAccessorDefinitions(const protobuf::Descriptor* message,
const protobuf::FieldDescriptor* field,
const absl::string_view resolved_field_name,
const absl::string_view class_name,
Output& output) {
Context& ctx) {
const protobuf::Descriptor* entry = field->message_type();
const protobuf::FieldDescriptor* key = entry->FindFieldByNumber(1);
const protobuf::FieldDescriptor* val = entry->FindFieldByNumber(2);
@ -310,7 +310,7 @@ void WriteMapAccessorDefinitions(const protobuf::Descriptor* message,
"upb_StringView upb_key = {key.data(), key.size()};\n";
}
if (val->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_MESSAGE) {
output(
ctx.EmitLegacy(
R"cc(
bool $0::set_$1($2 key, $3 value) {
upb_Message* clone = upb_Message_DeepClone(
@ -325,7 +325,7 @@ void WriteMapAccessorDefinitions(const protobuf::Descriptor* message,
converted_key_name, upbc_name,
::upb::generator::MiniTableMessageVarName(
val->message_type()->full_name()));
output(
ctx.EmitLegacy(
R"cc(
bool $0::set_$1($2 key, $3 value) {
upb_Message* clone = upb_Message_DeepClone(
@ -340,7 +340,7 @@ void WriteMapAccessorDefinitions(const protobuf::Descriptor* message,
converted_key_name, upbc_name,
::upb::generator::MiniTableMessageVarName(
val->message_type()->full_name()));
output(
ctx.EmitLegacy(
R"cc(
bool $0::set_alias_$1($2 key, $3 value) {
$6return $4_$8_set(
@ -351,7 +351,7 @@ void WriteMapAccessorDefinitions(const protobuf::Descriptor* message,
MessagePtrConstType(val, /* is_const */ true), MessageName(message),
MessageName(val->message_type()), optional_conversion_code,
converted_key_name, upbc_name);
output(
ctx.EmitLegacy(
R"cc(
bool $0::set_alias_$1($2 key, $3 value) {
$6return $4_$8_set(
@ -362,7 +362,7 @@ void WriteMapAccessorDefinitions(const protobuf::Descriptor* message,
MessagePtrConstType(val, /* is_const */ false), MessageName(message),
MessageName(val->message_type()), optional_conversion_code,
converted_key_name, upbc_name);
output(
ctx.EmitLegacy(
R"cc(
absl::StatusOr<$3> $0::get_$1($2 key) {
$5* msg_value;
@ -378,7 +378,7 @@ void WriteMapAccessorDefinitions(const protobuf::Descriptor* message,
MessageName(val->message_type()),
QualifiedClassName(val->message_type()), optional_conversion_code,
converted_key_name, upbc_name);
output(
ctx.EmitLegacy(
R"cc(
void $0::delete_$1($2 key) { $6$4_$8_delete(msg_, $7); }
)cc",
@ -387,7 +387,7 @@ void WriteMapAccessorDefinitions(const protobuf::Descriptor* message,
MessageName(val->message_type()), optional_conversion_code,
converted_key_name, upbc_name);
} else if (val->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING) {
output(
ctx.EmitLegacy(
R"cc(
bool $0::set_$1($2 key, $3 value) {
$5return $4_$7_set(
@ -398,7 +398,7 @@ void WriteMapAccessorDefinitions(const protobuf::Descriptor* message,
class_name, resolved_field_name, CppConstType(key), CppConstType(val),
MessageName(message), optional_conversion_code, converted_key_name,
upbc_name);
output(
ctx.EmitLegacy(
R"cc(
absl::StatusOr<$3> $0::get_$1($2 key) {
upb_StringView value;
@ -412,7 +412,7 @@ void WriteMapAccessorDefinitions(const protobuf::Descriptor* message,
class_name, resolved_field_name, CppConstType(key), CppConstType(val),
MessageName(message), optional_conversion_code, converted_key_name,
upbc_name);
output(
ctx.EmitLegacy(
R"cc(
void $0::delete_$1($2 key) { $5$4_$7_delete(msg_, $6); }
)cc",
@ -420,7 +420,7 @@ void WriteMapAccessorDefinitions(const protobuf::Descriptor* message,
MessageName(message), optional_conversion_code, converted_key_name,
upbc_name);
} else {
output(
ctx.EmitLegacy(
R"cc(
bool $0::set_$1($2 key, $3 value) {
$5return $4_$7_set(msg_, $6, value, arena_);
@ -429,7 +429,7 @@ void WriteMapAccessorDefinitions(const protobuf::Descriptor* message,
class_name, resolved_field_name, CppConstType(key), CppConstType(val),
MessageName(message), optional_conversion_code, converted_key_name,
upbc_name);
output(
ctx.EmitLegacy(
R"cc(
absl::StatusOr<$3> $0::get_$1($2 key) {
$3 value;
@ -443,7 +443,7 @@ void WriteMapAccessorDefinitions(const protobuf::Descriptor* message,
class_name, resolved_field_name, CppConstType(key), CppConstType(val),
MessageName(message), optional_conversion_code, converted_key_name,
upbc_name);
output(
ctx.EmitLegacy(
R"cc(
void $0::delete_$1($2 key) { $5$4_$7_delete(msg_, $6); }
)cc",
@ -454,11 +454,11 @@ void WriteMapAccessorDefinitions(const protobuf::Descriptor* message,
}
void WriteUsingAccessorsInHeader(const protobuf::Descriptor* desc,
MessageClassType handle_type, Output& output) {
MessageClassType handle_type, Context& ctx) {
bool read_only = handle_type == MessageClassType::kMessageCProxy;
// Generate const methods.
OutputIndenter i(output);
auto indent = ctx.printer().WithIndent();
std::string class_name = ClassName(desc);
auto field_names = CreateFieldNameMap(desc);
@ -466,20 +466,22 @@ void WriteUsingAccessorsInHeader(const protobuf::Descriptor* desc,
std::string resolved_field_name = ResolveFieldName(field, field_names);
// Generate hazzer (if any).
if (field->has_presence()) {
output("using $0Access::has_$1;\n", class_name, resolved_field_name);
ctx.EmitLegacy("using $0Access::has_$1;\n", class_name,
resolved_field_name);
if (!read_only) {
output("using $0Access::clear_$1;\n", class_name, resolved_field_name);
ctx.EmitLegacy("using $0Access::clear_$1;\n", class_name,
resolved_field_name);
}
}
if (field->is_map()) {
output(
ctx.EmitLegacy(
R"cc(
using $0Access::$1_size;
using $0Access::get_$1;
)cc",
class_name, resolved_field_name);
if (!read_only) {
output(
ctx.EmitLegacy(
R"cc(
using $0Access::clear_$1;
using $0Access::delete_$1;
@ -489,7 +491,7 @@ void WriteUsingAccessorsInHeader(const protobuf::Descriptor* desc,
// only emit set_alias for maps when value is a message
if (field->message_type()->FindFieldByNumber(2)->cpp_type() ==
protobuf::FieldDescriptor::CPPTYPE_MESSAGE) {
output(
ctx.EmitLegacy(
R"cc(
using $0Access::set_alias_$1;
)cc",
@ -500,67 +502,73 @@ void WriteUsingAccessorsInHeader(const protobuf::Descriptor* desc,
// TODO Implement map entry
} else if (field->is_repeated()) {
WriteRepeatedFieldUsingAccessors(field, class_name, resolved_field_name,
output, read_only);
ctx, read_only);
} else {
if (field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_MESSAGE) {
output("using $0Access::$1;\n", ClassName(desc), resolved_field_name);
ctx.EmitLegacy("using $0Access::$1;\n", ClassName(desc),
resolved_field_name);
if (!read_only) {
output("using $0Access::mutable_$1;\n", class_name,
resolved_field_name);
output("using $0Access::set_alias_$1;\n", class_name,
resolved_field_name);
ctx.EmitLegacy("using $0Access::mutable_$1;\n", class_name,
resolved_field_name);
ctx.EmitLegacy("using $0Access::set_alias_$1;\n", class_name,
resolved_field_name);
}
} else {
output("using $0Access::$1;\n", class_name, resolved_field_name);
ctx.EmitLegacy("using $0Access::$1;\n", class_name,
resolved_field_name);
if (!read_only) {
output("using $0Access::set_$1;\n", class_name, resolved_field_name);
ctx.EmitLegacy("using $0Access::set_$1;\n", class_name,
resolved_field_name);
}
}
}
}
for (int i = 0; i < desc->real_oneof_decl_count(); ++i) {
const protobuf::OneofDescriptor* oneof = desc->oneof_decl(i);
output("using $0Access::$1_case;\n", class_name, oneof->name());
output("using $0Access::$1Case;\n", class_name,
ToCamelCase(oneof->name(), /*lower_first=*/false));
ctx.EmitLegacy("using $0Access::$1_case;\n", class_name, oneof->name());
ctx.EmitLegacy("using $0Access::$1Case;\n", class_name,
ToCamelCase(oneof->name(), /*lower_first=*/false));
for (int j = 0; j < oneof->field_count(); ++j) {
const protobuf::FieldDescriptor* field = oneof->field(j);
output("using $0Access::k$1;\n", class_name,
ToCamelCase(field->name(), /*lower_first=*/false),
field->number());
ctx.EmitLegacy("using $0Access::k$1;\n", class_name,
ToCamelCase(field->name(), /*lower_first=*/false),
field->number());
}
output("using $0Access::$1_NOT_SET;\n", class_name,
absl::AsciiStrToUpper(oneof->name()));
ctx.EmitLegacy("using $0Access::$1_NOT_SET;\n", class_name,
absl::AsciiStrToUpper(oneof->name()));
}
}
void WriteOneofAccessorsInHeader(const protobuf::Descriptor* desc,
Output& output) {
Context& ctx) {
// Generate const methods.
OutputIndenter i(output);
auto indent = ctx.printer().WithIndent();
std::string class_name = ClassName(desc);
auto field_names = CreateFieldNameMap(desc);
for (int i = 0; i < desc->real_oneof_decl_count(); ++i) {
const protobuf::OneofDescriptor* oneof = desc->oneof_decl(i);
output("enum $0Case {\n",
ToCamelCase(oneof->name(), /*lower_first=*/false));
ctx.EmitLegacy("enum $0Case {\n",
ToCamelCase(oneof->name(), /*lower_first=*/false));
for (int j = 0; j < oneof->field_count(); ++j) {
const protobuf::FieldDescriptor* field = oneof->field(j);
output(" k$0 = $1,\n", ToCamelCase(field->name(), /*lower_first=*/false),
field->number());
ctx.EmitLegacy(" k$0 = $1,\n",
ToCamelCase(field->name(), /*lower_first=*/false),
field->number());
}
output(" $0_NOT_SET = 0,\n", absl::AsciiStrToUpper(oneof->name()));
output("};\n\n");
output("$0Case $1_case() const {\n",
ToCamelCase(oneof->name(), /*lower_first=*/false), oneof->name());
ctx.EmitLegacy(" $0_NOT_SET = 0,\n", absl::AsciiStrToUpper(oneof->name()));
ctx.Emit("};\n\n");
ctx.EmitLegacy("$0Case $1_case() const {\n",
ToCamelCase(oneof->name(), /*lower_first=*/false),
oneof->name());
for (int j = 0; j < oneof->field_count(); ++j) {
const protobuf::FieldDescriptor* field = oneof->field(j);
std::string resolved_field_name = ResolveFieldName(field, field_names);
output(" if (has_$0()) { return k$1; }\n", resolved_field_name,
ToCamelCase(field->name(), /*lower_first=*/false));
ctx.EmitLegacy(" if (has_$0()) { return k$1; }\n", resolved_field_name,
ToCamelCase(field->name(), /*lower_first=*/false));
}
output(" return $0_NOT_SET;\n", absl::AsciiStrToUpper(oneof->name()));
output("}\n;");
ctx.EmitLegacy(" return $0_NOT_SET;\n",
absl::AsciiStrToUpper(oneof->name()));
ctx.Emit("}\n;");
}
}

@ -8,21 +8,22 @@
#ifndef PROTOBUF_COMPILER_HBP_GEN_ACCESSORS_H_
#define PROTOBUF_COMPILER_HBP_GEN_ACCESSORS_H_
#include "google/protobuf/descriptor.h"
#include "google/protobuf/compiler/hpb/context.h"
#include "google/protobuf/compiler/hpb/gen_utils.h"
#include "google/protobuf/compiler/hpb/output.h"
#include "google/protobuf/descriptor.h"
namespace google::protobuf::hpb_generator {
namespace protobuf = ::proto2;
void WriteFieldAccessorsInHeader(const protobuf::Descriptor* desc,
Output& output);
void WriteAccessorsInSource(const protobuf::Descriptor* desc, Output& output);
Context& ctx);
void WriteAccessorsInSource(const protobuf::Descriptor* desc, Context& ctx);
void WriteUsingAccessorsInHeader(const protobuf::Descriptor* desc,
MessageClassType handle_type, Output& output);
MessageClassType handle_type, Context& ctx);
void WriteOneofAccessorsInHeader(const protobuf::Descriptor* desc,
Output& output);
Context& ctx);
} // namespace protobuf
} // namespace google::hpb_generator

@ -13,6 +13,7 @@
#include <vector>
#include "google/protobuf/descriptor.pb.h"
#include "google/protobuf/compiler/hpb/context.h"
#include "google/protobuf/compiler/hpb/gen_utils.h"
#include "google/protobuf/compiler/hpb/names.h"
#include "google/protobuf/descriptor.h"
@ -78,7 +79,7 @@ std::string EnumValueSymbolInNameSpace(
}
}
void WriteEnumValues(const protobuf::EnumDescriptor* desc, Output& output) {
void WriteEnumValues(const protobuf::EnumDescriptor* desc, Context& ctx) {
std::vector<const protobuf::EnumValueDescriptor*> values;
auto value_count = desc->value_count();
values.reserve(value_count);
@ -93,21 +94,21 @@ void WriteEnumValues(const protobuf::EnumDescriptor* desc, Output& output) {
for (size_t i = 0; i < values.size(); i++) {
auto value = values[i];
output(" $0", EnumValueSymbolInNameSpace(desc, value));
output(" = $0", EnumInt32ToString(value->number()));
ctx.EmitLegacy(" $0", EnumValueSymbolInNameSpace(desc, value));
ctx.EmitLegacy(" = $0", EnumInt32ToString(value->number()));
if (i != values.size() - 1) {
output(",");
ctx.Emit(",");
}
output("\n");
ctx.Emit("\n");
}
}
void WriteEnumDeclarations(
const std::vector<const protobuf::EnumDescriptor*>& enums, Output& output) {
const std::vector<const protobuf::EnumDescriptor*>& enums, Context& ctx) {
for (auto enumdesc : enums) {
output("enum $0 : int {\n", EnumTypeName(enumdesc));
WriteEnumValues(enumdesc, output);
output("};\n\n");
ctx.EmitLegacy("enum $0 : int {\n", EnumTypeName(enumdesc));
WriteEnumValues(enumdesc, ctx);
ctx.Emit("};\n\n");
}
}

@ -8,8 +8,8 @@
#ifndef PROTOBUF_COMPILER_HBP_GEN_ENUMS_H_
#define PROTOBUF_COMPILER_HBP_GEN_ENUMS_H_
#include "google/protobuf/compiler/hpb/context.h"
#include "google/protobuf/descriptor.h"
#include "google/protobuf/compiler/hpb/output.h"
namespace google::protobuf::hpb_generator {
@ -20,7 +20,7 @@ std::string EnumValueSymbolInNameSpace(
const protobuf::EnumDescriptor* desc,
const protobuf::EnumValueDescriptor* value);
void WriteEnumDeclarations(
const std::vector<const protobuf::EnumDescriptor*>& enums, Output& output);
const std::vector<const protobuf::EnumDescriptor*>& enums, Context& ctx);
} // namespace protobuf
} // namespace google::hpb_generator

@ -8,8 +8,10 @@
#include "google/protobuf/compiler/hpb/gen_extensions.h"
#include "absl/strings/str_cat.h"
#include "google/protobuf/compiler/hpb/context.h"
#include "google/protobuf/compiler/hpb/gen_utils.h"
#include "google/protobuf/compiler/hpb/names.h"
#include "upb_generator/c/names.h"
namespace google::protobuf::hpb_generator {
@ -19,7 +21,7 @@ std::string ExtensionIdentifierBase(const protobuf::FieldDescriptor* ext) {
assert(ext->is_extension());
std::string ext_scope;
if (ext->extension_scope()) {
return MessageName(ext->extension_scope());
return upb::generator::CApiMessageType(ext->extension_scope()->full_name());
} else {
return ToCIdent(ext->file()->package());
}
@ -32,17 +34,17 @@ std::string ContainingTypeName(const protobuf::FieldDescriptor* ext) {
}
void WriteExtensionIdentifierHeader(const protobuf::FieldDescriptor* ext,
Output& output) {
Context& ctx) {
std::string mini_table_name =
absl::StrCat(ExtensionIdentifierBase(ext), "_", ext->name(), "_ext");
if (ext->extension_scope()) {
output(
ctx.EmitLegacy(
R"cc(
static const ::hpb::internal::ExtensionIdentifier<$0, $1> $2;
)cc",
ContainingTypeName(ext), CppTypeParameterName(ext), ext->name());
} else {
output(
ctx.EmitLegacy(
R"cc(
extern const ::hpb::internal::ExtensionIdentifier<$0, $1> $2;
)cc",
@ -52,27 +54,27 @@ void WriteExtensionIdentifierHeader(const protobuf::FieldDescriptor* ext,
void WriteExtensionIdentifiersHeader(
const std::vector<const protobuf::FieldDescriptor*>& extensions,
Output& output) {
Context& ctx) {
for (const auto* ext : extensions) {
if (!ext->extension_scope()) {
WriteExtensionIdentifierHeader(ext, output);
WriteExtensionIdentifierHeader(ext, ctx);
}
}
}
void WriteExtensionIdentifier(const protobuf::FieldDescriptor* ext,
Output& output) {
Context& ctx) {
std::string mini_table_name =
absl::StrCat(ExtensionIdentifierBase(ext), "_", ext->name(), "_ext");
if (ext->extension_scope()) {
output(
ctx.EmitLegacy(
R"cc(
const hpb::internal::ExtensionIdentifier<$0, $3> $4::$2(&$1);
)cc",
ContainingTypeName(ext), mini_table_name, ext->name(),
CppTypeParameterName(ext), ClassName(ext->extension_scope()));
} else {
output(
ctx.EmitLegacy(
R"cc(
const hpb::internal::ExtensionIdentifier<$0, $3> $2(&$1);
)cc",
@ -83,10 +85,10 @@ void WriteExtensionIdentifier(const protobuf::FieldDescriptor* ext,
void WriteExtensionIdentifiers(
const std::vector<const protobuf::FieldDescriptor*>& extensions,
Output& output) {
Context& ctx) {
for (const auto* ext : extensions) {
if (!ext->extension_scope()) {
WriteExtensionIdentifier(ext, output);
WriteExtensionIdentifier(ext, ctx);
}
}
}

@ -8,8 +8,8 @@
#ifndef PROTOBUF_COMPILER_HBP_GEN_EXTENSIONS_H_
#define PROTOBUF_COMPILER_HBP_GEN_EXTENSIONS_H_
#include "google/protobuf/compiler/hpb/context.h"
#include "google/protobuf/descriptor.h"
#include "google/protobuf/compiler/hpb/output.h"
namespace google::protobuf::hpb_generator {
@ -17,14 +17,14 @@ namespace protobuf = ::proto2;
void WriteExtensionIdentifiersHeader(
const std::vector<const protobuf::FieldDescriptor*>& extensions,
Output& output);
Context& ctx);
void WriteExtensionIdentifierHeader(const protobuf::FieldDescriptor* ext,
Output& output);
Context& ctx);
void WriteExtensionIdentifiers(
const std::vector<const protobuf::FieldDescriptor*>& extensions,
Output& output);
Context& ctx);
void WriteExtensionIdentifier(const protobuf::FieldDescriptor* ext,
Output& output);
Context& ctx);
} // namespace protobuf
} // namespace google::hpb_generator

@ -15,12 +15,12 @@
#include "absl/strings/ascii.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "google/protobuf/compiler/hpb/context.h"
#include "google/protobuf/compiler/hpb/gen_accessors.h"
#include "google/protobuf/compiler/hpb/gen_enums.h"
#include "google/protobuf/compiler/hpb/gen_extensions.h"
#include "google/protobuf/compiler/hpb/gen_utils.h"
#include "google/protobuf/compiler/hpb/names.h"
#include "google/protobuf/compiler/hpb/output.h"
#include "google/protobuf/descriptor.h"
#include "upb_generator/minitable/names.h"
@ -29,32 +29,32 @@ namespace google::protobuf::hpb_generator {
namespace protobuf = ::proto2;
void WriteModelAccessDeclaration(const protobuf::Descriptor* descriptor,
Output& output);
Context& ctx);
void WriteModelPublicDeclaration(
const protobuf::Descriptor* descriptor,
const std::vector<const protobuf::FieldDescriptor*>& file_exts,
const std::vector<const protobuf::EnumDescriptor*>& file_enums,
Output& output);
Context& ctx);
void WriteExtensionIdentifiersInClassHeader(
const protobuf::Descriptor* message,
const std::vector<const protobuf::FieldDescriptor*>& file_exts,
Output& output);
Context& ctx);
void WriteModelProxyDeclaration(const protobuf::Descriptor* descriptor,
Output& output);
Context& ctx);
void WriteModelCProxyDeclaration(const protobuf::Descriptor* descriptor,
Output& output);
Context& ctx);
void WriteInternalForwardDeclarationsInHeader(
const protobuf::Descriptor* message, Output& output);
const protobuf::Descriptor* message, Context& ctx);
void WriteDefaultInstanceHeader(const protobuf::Descriptor* message,
Output& output);
Context& ctx);
void WriteExtensionIdentifiersImplementation(
const protobuf::Descriptor* message,
const std::vector<const protobuf::FieldDescriptor*>& file_exts,
Output& output);
Context& ctx);
void WriteUsingEnumsInHeader(
const protobuf::Descriptor* message,
const std::vector<const protobuf::EnumDescriptor*>& file_enums,
Output& output);
Context& ctx);
// Writes message class declarations into .upb.proto.h.
//
@ -64,7 +64,7 @@ void WriteMessageClassDeclarations(
const protobuf::Descriptor* descriptor,
const std::vector<const protobuf::FieldDescriptor*>& file_exts,
const std::vector<const protobuf::EnumDescriptor*>& file_enums,
Output& output) {
Context& ctx) {
if (IsMapEntryMessage(descriptor)) {
// Skip map entry generation. Low level accessors for maps are
// generated that don't require a separate map type.
@ -72,23 +72,23 @@ void WriteMessageClassDeclarations(
}
// Forward declaration of Proto Class for GCC handling of free friend method.
output("class $0;\n", ClassName(descriptor));
output("namespace internal {\n\n");
WriteModelAccessDeclaration(descriptor, output);
output("\n");
WriteInternalForwardDeclarationsInHeader(descriptor, output);
output("\n");
output("} // namespace internal\n\n");
WriteModelPublicDeclaration(descriptor, file_exts, file_enums, output);
output("namespace internal {\n");
WriteModelCProxyDeclaration(descriptor, output);
WriteModelProxyDeclaration(descriptor, output);
output("} // namespace internal\n\n");
ctx.EmitLegacy("class $0;\n", ClassName(descriptor));
ctx.Emit("namespace internal {\n\n");
WriteModelAccessDeclaration(descriptor, ctx);
ctx.Emit("\n");
WriteInternalForwardDeclarationsInHeader(descriptor, ctx);
ctx.Emit("\n");
ctx.Emit("} // namespace internal\n\n");
WriteModelPublicDeclaration(descriptor, file_exts, file_enums, ctx);
ctx.Emit("namespace internal {\n");
WriteModelCProxyDeclaration(descriptor, ctx);
WriteModelProxyDeclaration(descriptor, ctx);
ctx.Emit("} // namespace internal\n\n");
}
void WriteModelAccessDeclaration(const protobuf::Descriptor* descriptor,
Output& output) {
output(
Context& ctx) {
ctx.EmitLegacy(
R"cc(
class $0Access {
public:
@ -102,10 +102,9 @@ void WriteModelAccessDeclaration(const protobuf::Descriptor* descriptor,
} // NOLINT
)cc",
ClassName(descriptor), MessageName(descriptor));
WriteFieldAccessorsInHeader(descriptor, output);
WriteOneofAccessorsInHeader(descriptor, output);
output.Indent();
output(
WriteFieldAccessorsInHeader(descriptor, ctx);
WriteOneofAccessorsInHeader(descriptor, ctx);
ctx.EmitLegacy(
R"cc(
private:
friend class $2;
@ -117,8 +116,7 @@ void WriteModelAccessDeclaration(const protobuf::Descriptor* descriptor,
)cc",
ClassName(descriptor), MessageName(descriptor),
QualifiedClassName(descriptor));
output.Outdent();
output("};\n");
ctx.Emit("};\n");
}
std::string UnderscoresToCamelCase(absl::string_view input,
@ -161,21 +159,21 @@ std::string FieldConstantName(const protobuf::FieldDescriptor* field) {
return result;
}
void WriteConstFieldNumbers(Output& output,
void WriteConstFieldNumbers(Context& ctx,
const protobuf::Descriptor* descriptor) {
for (auto field : FieldRange(descriptor)) {
output("static constexpr ::uint32_t $0 = $1;\n", FieldConstantName(field),
field->number());
ctx.EmitLegacy("static constexpr ::uint32_t $0 = $1;\n",
FieldConstantName(field), field->number());
}
output("\n\n");
ctx.Emit("\n\n");
}
void WriteModelPublicDeclaration(
const protobuf::Descriptor* descriptor,
const std::vector<const protobuf::FieldDescriptor*>& file_exts,
const std::vector<const protobuf::EnumDescriptor*>& file_enums,
Output& output) {
output(
Context& ctx) {
ctx.EmitLegacy(
R"cc(
class $0 final : private internal::$0Access {
public:
@ -207,28 +205,27 @@ void WriteModelPublicDeclaration(
::upb::generator::MiniTableMessageVarName(descriptor->full_name()),
MessageName(descriptor), QualifiedClassName(descriptor));
WriteUsingAccessorsInHeader(descriptor, MessageClassType::kMessage, output);
WriteUsingEnumsInHeader(descriptor, file_enums, output);
WriteDefaultInstanceHeader(descriptor, output);
WriteExtensionIdentifiersInClassHeader(descriptor, file_exts, output);
WriteUsingAccessorsInHeader(descriptor, MessageClassType::kMessage, ctx);
WriteUsingEnumsInHeader(descriptor, file_enums, ctx);
WriteDefaultInstanceHeader(descriptor, ctx);
WriteExtensionIdentifiersInClassHeader(descriptor, file_exts, ctx);
if (descriptor->extension_range_count()) {
// for typetrait checking
output("using ExtendableType = $0;\n", ClassName(descriptor));
ctx.EmitLegacy("using ExtendableType = $0;\n", ClassName(descriptor));
}
// Note: free function friends that are templates such as ::hpb::Parse
// require explicit <$2> type parameter in declaration to be able to compile
// with gcc otherwise the compiler will fail with
// "has not been declared within namespace" error. Even though there is a
// namespace qualifier, cross namespace matching fails.
output.Indent();
output(
ctx.EmitLegacy(
R"cc(
static const upb_MiniTable* minitable();
)cc",
ClassName(descriptor));
output("\n");
WriteConstFieldNumbers(output, descriptor);
output(
ctx.Emit("\n");
WriteConstFieldNumbers(ctx, descriptor);
ctx.EmitLegacy(
R"cc(
private:
const upb_Message* msg() const { return UPB_UPCAST(msg_); }
@ -257,14 +254,13 @@ void WriteModelPublicDeclaration(
)cc",
ClassName(descriptor), MessageName(descriptor),
QualifiedClassName(descriptor));
output.Outdent();
output("};\n\n");
ctx.Emit("};\n\n");
}
void WriteModelProxyDeclaration(const protobuf::Descriptor* descriptor,
Output& output) {
Context& ctx) {
// Foo::Proxy.
output(
ctx.EmitLegacy(
R"cc(
class $0Proxy final : private internal::$0Access {
public:
@ -285,11 +281,9 @@ void WriteModelProxyDeclaration(const protobuf::Descriptor* descriptor,
)cc",
ClassName(descriptor));
WriteUsingAccessorsInHeader(descriptor, MessageClassType::kMessageProxy,
output);
output("\n");
output.Indent(1);
output(
WriteUsingAccessorsInHeader(descriptor, MessageClassType::kMessageProxy, ctx);
ctx.Emit("\n");
ctx.EmitLegacy(
R"cc(
private:
upb_Message* msg() const { return UPB_UPCAST(msg_); }
@ -320,14 +314,13 @@ void WriteModelProxyDeclaration(const protobuf::Descriptor* descriptor,
)cc",
ClassName(descriptor), MessageName(descriptor),
QualifiedClassName(descriptor));
output.Outdent(1);
output("};\n\n");
ctx.Emit("};\n\n");
}
void WriteModelCProxyDeclaration(const protobuf::Descriptor* descriptor,
Output& output) {
Context& ctx) {
// Foo::CProxy.
output(
ctx.EmitLegacy(
R"cc(
class $0CProxy final : private internal::$0Access {
public:
@ -339,10 +332,9 @@ void WriteModelCProxyDeclaration(const protobuf::Descriptor* descriptor,
ClassName(descriptor), MessageName(descriptor));
WriteUsingAccessorsInHeader(descriptor, MessageClassType::kMessageCProxy,
output);
ctx);
output.Indent(1);
output(
ctx.EmitLegacy(
R"cc(
private:
using AsNonConst = $0Proxy;
@ -367,24 +359,23 @@ void WriteModelCProxyDeclaration(const protobuf::Descriptor* descriptor,
}
)cc",
ClassName(descriptor), MessageName(descriptor));
output.Outdent(1);
output("};\n\n");
ctx.Emit("};\n\n");
}
void WriteDefaultInstanceHeader(const protobuf::Descriptor* message,
Output& output) {
output(" static ::hpb::Ptr<const $0> default_instance();\n",
ClassName(message));
Context& ctx) {
ctx.EmitLegacy(" static ::hpb::Ptr<const $0> default_instance();\n",
ClassName(message));
}
void WriteMessageImplementation(
const protobuf::Descriptor* descriptor,
const std::vector<const protobuf::FieldDescriptor*>& file_exts,
Output& output) {
Context& ctx) {
bool message_is_map_entry = descriptor->options().map_entry();
if (!message_is_map_entry) {
// Constructor.
output(
ctx.EmitLegacy(
R"cc(
$0::$0() : $0Access() {
arena_ = owned_arena_.ptr();
@ -419,21 +410,21 @@ void WriteMessageImplementation(
ClassName(descriptor), MessageName(descriptor),
::upb::generator::MiniTableMessageVarName(descriptor->full_name()),
QualifiedClassName(descriptor));
output("\n");
ctx.Emit("\n");
// Minitable
output(
ctx.EmitLegacy(
R"cc(
const upb_MiniTable* $0::minitable() { return &$1; }
)cc",
ClassName(descriptor),
::upb::generator::MiniTableMessageVarName(descriptor->full_name()));
output("\n");
ctx.Emit("\n");
}
WriteAccessorsInSource(descriptor, output);
WriteAccessorsInSource(descriptor, ctx);
if (!message_is_map_entry) {
output(
ctx.EmitLegacy(
R"cc(
struct $0DefaultTypeInternal {
$1* msg;
@ -447,7 +438,7 @@ void WriteMessageImplementation(
)cc",
ClassName(descriptor), MessageName(descriptor));
output(
ctx.EmitLegacy(
R"cc(
::hpb::Ptr<const $0> $0::default_instance() {
return ::hpb::interop::upb::MakeCHandle<$0>(
@ -457,15 +448,15 @@ void WriteMessageImplementation(
)cc",
ClassName(descriptor));
WriteExtensionIdentifiersImplementation(descriptor, file_exts, output);
WriteExtensionIdentifiersImplementation(descriptor, file_exts, ctx);
}
}
void WriteInternalForwardDeclarationsInHeader(
const protobuf::Descriptor* message, Output& output) {
const protobuf::Descriptor* message, Context& ctx) {
// Write declaration for internal re-usable default_instance without
// leaking implementation.
output(
ctx.EmitLegacy(
R"cc(
struct $0DefaultTypeInternal;
extern $0DefaultTypeInternal _$0_default_instance_;
@ -476,11 +467,11 @@ void WriteInternalForwardDeclarationsInHeader(
void WriteExtensionIdentifiersInClassHeader(
const protobuf::Descriptor* message,
const std::vector<const protobuf::FieldDescriptor*>& file_exts,
Output& output) {
Context& ctx) {
for (auto* ext : file_exts) {
if (ext->extension_scope() &&
ext->extension_scope()->full_name() == message->full_name()) {
WriteExtensionIdentifierHeader(ext, output);
WriteExtensionIdentifierHeader(ext, ctx);
}
}
}
@ -488,11 +479,11 @@ void WriteExtensionIdentifiersInClassHeader(
void WriteExtensionIdentifiersImplementation(
const protobuf::Descriptor* message,
const std::vector<const protobuf::FieldDescriptor*>& file_exts,
Output& output) {
Context& ctx) {
for (auto* ext : file_exts) {
if (ext->extension_scope() &&
ext->extension_scope()->full_name() == message->full_name()) {
WriteExtensionIdentifier(ext, output);
WriteExtensionIdentifier(ext, ctx);
}
}
}
@ -500,7 +491,7 @@ void WriteExtensionIdentifiersImplementation(
void WriteUsingEnumsInHeader(
const protobuf::Descriptor* message,
const std::vector<const protobuf::EnumDescriptor*>& file_enums,
Output& output) {
Context& ctx) {
for (auto* enum_descriptor : file_enums) {
std::string enum_type_name = EnumTypeName(enum_descriptor);
std::string enum_resolved_type_name =
@ -514,23 +505,25 @@ void WriteUsingEnumsInHeader(
message->full_name()) {
continue;
}
output("using $0", enum_descriptor->name());
ctx.EmitLegacy("using $0", enum_descriptor->name());
if (enum_descriptor->options().deprecated()) {
output(" ABSL_DEPRECATED(\"Proto enum $0\")", enum_descriptor->name());
ctx.EmitLegacy(" ABSL_DEPRECATED(\"Proto enum $0\")",
enum_descriptor->name());
}
output(" = $0;", enum_resolved_type_name);
output("\n");
ctx.EmitLegacy(" = $0;", enum_resolved_type_name);
ctx.Emit("\n");
int value_count = enum_descriptor->value_count();
for (int i = 0; i < value_count; i++) {
output("static constexpr $0 $1", enum_descriptor->name(),
enum_descriptor->value(i)->name());
ctx.EmitLegacy("static constexpr $0 $1", enum_descriptor->name(),
enum_descriptor->value(i)->name());
if (enum_descriptor->options().deprecated() ||
enum_descriptor->value(i)->options().deprecated()) {
output(" ABSL_DEPRECATED(\"Proto enum value $0\") ",
enum_descriptor->value(i)->name());
ctx.EmitLegacy(" ABSL_DEPRECATED(\"Proto enum value $0\") ",
enum_descriptor->value(i)->name());
}
output(" = $0;\n", EnumValueSymbolInNameSpace(enum_descriptor,
enum_descriptor->value(i)));
ctx.EmitLegacy(" = $0;\n",
EnumValueSymbolInNameSpace(enum_descriptor,
enum_descriptor->value(i)));
}
}
}

@ -8,8 +8,8 @@
#ifndef PROTOBUF_COMPILER_HBP_GEN_MESSAGES_H_
#define PROTOBUF_COMPILER_HBP_GEN_MESSAGES_H_
#include "google/protobuf/compiler/hpb/context.h"
#include "google/protobuf/descriptor.h"
#include "google/protobuf/compiler/hpb/output.h"
namespace google::protobuf::hpb_generator {
namespace protobuf = ::proto2;
@ -18,11 +18,11 @@ void WriteMessageClassDeclarations(
const protobuf::Descriptor* descriptor,
const std::vector<const protobuf::FieldDescriptor*>& file_exts,
const std::vector<const protobuf::EnumDescriptor*>& file_enums,
Output& output);
Context& ctx);
void WriteMessageImplementation(
const protobuf::Descriptor* descriptor,
const std::vector<const protobuf::FieldDescriptor*>& file_exts,
Output& output);
Context& ctx);
} // namespace protobuf
} // namespace google::hpb_generator

@ -12,12 +12,12 @@
#include "google/protobuf/descriptor.pb.h"
#include "absl/strings/string_view.h"
#include "google/protobuf/compiler/hpb/context.h"
#include "google/protobuf/compiler/hpb/gen_accessors.h"
#include "google/protobuf/compiler/hpb/gen_enums.h"
#include "google/protobuf/compiler/hpb/gen_extensions.h"
#include "google/protobuf/compiler/hpb/gen_utils.h"
#include "google/protobuf/compiler/hpb/names.h"
#include "google/protobuf/compiler/hpb/output.h"
#include "google/protobuf/descriptor.h"
#include "upb_generator/c/names.h"
#include "upb_generator/common.h"
@ -31,16 +31,16 @@ namespace protobuf = ::proto2;
void WriteRepeatedFieldUsingAccessors(const protobuf::FieldDescriptor* field,
absl::string_view class_name,
absl::string_view resolved_field_name,
Output& output, bool read_only) {
Context& ctx, bool read_only) {
if (field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_MESSAGE) {
output(
ctx.EmitLegacy(
R"cc(
using $0Access::$1;
using $0Access::$1_size;
)cc",
class_name, resolved_field_name);
if (!read_only) {
output(
ctx.EmitLegacy(
R"cc(
using $0Access::add_$1;
using $0Access::add_alias_$1;
@ -49,14 +49,14 @@ void WriteRepeatedFieldUsingAccessors(const protobuf::FieldDescriptor* field,
class_name, resolved_field_name);
}
} else {
output(
ctx.EmitLegacy(
R"cc(
using $0Access::$1;
using $0Access::$1_size;
)cc",
class_name, resolved_field_name);
if (!read_only) {
output(
ctx.EmitLegacy(
R"cc(
using $0Access::add_$1;
using $0Access::mutable_$1;
@ -72,8 +72,8 @@ void WriteRepeatedFieldsInMessageHeader(const protobuf::Descriptor* desc,
const protobuf::FieldDescriptor* field,
absl::string_view resolved_field_name,
absl::string_view resolved_upbc_name,
Output& output) {
output(
Context& ctx) {
ctx.EmitLegacy(
R"cc(
inline size_t $1_size() const {
size_t len;
@ -84,7 +84,7 @@ void WriteRepeatedFieldsInMessageHeader(const protobuf::Descriptor* desc,
MessageName(desc), resolved_field_name, resolved_upbc_name);
if (field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_MESSAGE) {
output(
ctx.EmitLegacy(
R"cc(
$1 $2(size_t index) const;
const ::hpb::RepeatedField<const $4>::CProxy $2() const;
@ -105,7 +105,7 @@ void WriteRepeatedFieldsInMessageHeader(const protobuf::Descriptor* desc,
MessageBaseType(field, /* maybe_const */ false) // $4
);
} else if (field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING) {
output(
ctx.EmitLegacy(
R"cc(
$0 $1(size_t index) const;
const ::hpb::RepeatedField<$0>::CProxy $1() const;
@ -116,7 +116,7 @@ void WriteRepeatedFieldsInMessageHeader(const protobuf::Descriptor* desc,
)cc",
CppConstType(field), resolved_field_name);
} else {
output(
ctx.EmitLegacy(
R"cc(
$0 $1(size_t index) const;
const ::hpb::RepeatedField<$0>::CProxy $1() const;
@ -133,10 +133,10 @@ void WriteRepeatedMessageAccessor(const protobuf::Descriptor* message,
const protobuf::FieldDescriptor* field,
const absl::string_view resolved_field_name,
const absl::string_view class_name,
Output& output) {
Context& ctx) {
const char arena_expression[] = "arena_";
absl::string_view upbc_name = field->name();
output(
ctx.EmitLegacy(
R"cc(
$1 $0::$2(size_t index) const {
size_t len;
@ -149,7 +149,7 @@ void WriteRepeatedMessageAccessor(const protobuf::Descriptor* message,
class_name, MessagePtrConstType(field, /* is_const */ true),
resolved_field_name, MessageName(message),
MessageBaseType(field, /* maybe_const */ false), upbc_name);
output(
ctx.EmitLegacy(
R"cc(
absl::StatusOr<$1> $0::add_$2() {
auto new_msg = $3_add_$6(msg_, $5);
@ -176,7 +176,7 @@ void WriteRepeatedMessageAccessor(const protobuf::Descriptor* message,
MessageBaseType(field, /* maybe_const */ false), arena_expression,
upbc_name, ClassName(message), field->index(),
upb::generator::CApiMessageType(field->message_type()->full_name()));
output(
ctx.EmitLegacy(
R"cc(
$1 $0::mutable_$2(size_t index) const {
size_t len;
@ -189,7 +189,7 @@ void WriteRepeatedMessageAccessor(const protobuf::Descriptor* message,
resolved_field_name, MessageName(message),
MessageBaseType(field, /* maybe_const */ false), arena_expression,
upbc_name);
output(
ctx.EmitLegacy(
R"cc(
const ::hpb::RepeatedField<const $1>::CProxy $0::$2() const {
size_t size;
@ -216,9 +216,9 @@ void WriteRepeatedStringAccessor(const protobuf::Descriptor* message,
const protobuf::FieldDescriptor* field,
const absl::string_view resolved_field_name,
const absl::string_view class_name,
Output& output) {
Context& ctx) {
absl::string_view upbc_name = field->name();
output(
ctx.EmitLegacy(
R"cc(
$1 $0::$2(size_t index) const {
size_t len;
@ -229,14 +229,14 @@ void WriteRepeatedStringAccessor(const protobuf::Descriptor* message,
)cc",
class_name, CppConstType(field), resolved_field_name,
MessageName(message), upbc_name);
output(
ctx.EmitLegacy(
R"cc(
bool $0::resize_$1(size_t len) {
return $2_resize_$3(msg_, len, arena_);
}
)cc",
class_name, resolved_field_name, MessageName(message), upbc_name);
output(
ctx.EmitLegacy(
R"cc(
bool $0::add_$2($1 val) {
return $3_add_$4(msg_,
@ -246,7 +246,7 @@ void WriteRepeatedStringAccessor(const protobuf::Descriptor* message,
)cc",
class_name, CppConstType(field), resolved_field_name,
MessageName(message), upbc_name);
output(
ctx.EmitLegacy(
R"cc(
void $0::set_$2(size_t index, $1 val) {
size_t len;
@ -257,7 +257,7 @@ void WriteRepeatedStringAccessor(const protobuf::Descriptor* message,
)cc",
class_name, CppConstType(field), resolved_field_name,
MessageName(message), upbc_name);
output(
ctx.EmitLegacy(
R"cc(
const ::hpb::RepeatedField<$1>::CProxy $0::$2() const {
size_t size;
@ -284,9 +284,9 @@ void WriteRepeatedScalarAccessor(const protobuf::Descriptor* message,
const protobuf::FieldDescriptor* field,
const absl::string_view resolved_field_name,
const absl::string_view class_name,
Output& output) {
Context& ctx) {
absl::string_view upbc_name = field->name();
output(
ctx.EmitLegacy(
R"cc(
$1 $0::$2(size_t index) const {
size_t len;
@ -297,20 +297,20 @@ void WriteRepeatedScalarAccessor(const protobuf::Descriptor* message,
)cc",
class_name, CppConstType(field), resolved_field_name,
MessageName(message), upbc_name);
output(
ctx.EmitLegacy(
R"cc(
bool $0::resize_$1(size_t len) {
return $2_resize_$3(msg_, len, arena_);
}
)cc",
class_name, resolved_field_name, MessageName(message), upbc_name);
output(
ctx.EmitLegacy(
R"cc(
bool $0::add_$2($1 val) { return $3_add_$4(msg_, val, arena_); }
)cc",
class_name, CppConstType(field), resolved_field_name,
MessageName(message), upbc_name);
output(
ctx.EmitLegacy(
R"cc(
void $0::set_$2(size_t index, $1 val) {
size_t len;
@ -321,7 +321,7 @@ void WriteRepeatedScalarAccessor(const protobuf::Descriptor* message,
)cc",
class_name, CppConstType(field), resolved_field_name,
MessageName(message), upbc_name);
output(
ctx.EmitLegacy(
R"cc(
const ::hpb::RepeatedField<$1>::CProxy $0::$2() const {
size_t size;

@ -9,8 +9,8 @@
#define PROTOBUF_COMPILER_HBP_GEN_REPEATED_FIELDS_H_
#include "absl/strings/string_view.h"
#include "google/protobuf/compiler/hpb/context.h"
#include "google/protobuf/descriptor.h"
#include "google/protobuf/compiler/hpb/output.h"
namespace google::protobuf::hpb_generator {
@ -19,28 +19,28 @@ namespace protobuf = ::proto2;
void WriteRepeatedFieldUsingAccessors(const protobuf::FieldDescriptor* field,
absl::string_view class_name,
absl::string_view resolved_field_name,
Output& output, bool read_only);
Context& ctx, bool read_only);
void WriteRepeatedFieldsInMessageHeader(const protobuf::Descriptor* desc,
const protobuf::FieldDescriptor* field,
absl::string_view resolved_field_name,
absl::string_view resolved_upbc_name,
Output& output);
Context& ctx);
void WriteRepeatedMessageAccessor(const protobuf::Descriptor* message,
const protobuf::FieldDescriptor* field,
absl::string_view resolved_field_name,
absl::string_view class_name, Output& output);
absl::string_view class_name, Context& ctx);
void WriteRepeatedStringAccessor(const protobuf::Descriptor* message,
const protobuf::FieldDescriptor* field,
absl::string_view resolved_field_name,
absl::string_view class_name, Output& output);
absl::string_view class_name, Context& ctx);
void WriteRepeatedScalarAccessor(const protobuf::Descriptor* message,
const protobuf::FieldDescriptor* field,
absl::string_view resolved_field_name,
absl::string_view class_name, Output& output);
absl::string_view class_name, Context& ctx);
} // namespace protobuf
} // namespace google::hpb_generator

@ -11,6 +11,7 @@
#include "absl/strings/string_view.h"
#include "google/protobuf/compiler/code_generator.h"
#include "google/protobuf/compiler/hpb/context.h"
#include "google/protobuf/compiler/hpb/keywords.h"
namespace google::protobuf::hpb_generator {
@ -120,20 +121,22 @@ std::string CppHeaderFilename(const google::protobuf::FileDescriptor* file) {
return compiler::StripProto(file->name()) + ".upb.proto.h";
}
void WriteStartNamespace(const protobuf::FileDescriptor* file, Output& output) {
void WriteStartNamespace(const protobuf::FileDescriptor* file, Context& ctx) {
// Skip namespace generation if package name is not specified.
if (file->package().empty()) {
return;
}
output("namespace $0 {\n\n", NamespaceFromPackageName(file->package()));
ctx.EmitLegacy("namespace $0 {\n\n",
NamespaceFromPackageName(file->package()));
}
void WriteEndNamespace(const protobuf::FileDescriptor* file, Output& output) {
void WriteEndNamespace(const protobuf::FileDescriptor* file, Context& ctx) {
if (file->package().empty()) {
return;
}
output("} // namespace $0\n\n", NamespaceFromPackageName(file->package()));
ctx.EmitLegacy("} // namespace $0\n\n",
NamespaceFromPackageName(file->package()));
}
std::string CppConstType(const protobuf::FieldDescriptor* field) {

@ -11,7 +11,7 @@
#include <string>
#include "google/protobuf/descriptor.pb.h"
#include "google/protobuf/compiler/hpb/output.h"
#include "google/protobuf/compiler/hpb/context.h"
namespace google::protobuf::hpb_generator {
@ -28,8 +28,8 @@ std::string ForwardingHeaderFilename(const google::protobuf::FileDescriptor* fil
std::string UpbCFilename(const google::protobuf::FileDescriptor* file);
std::string CppHeaderFilename(const google::protobuf::FileDescriptor* file);
void WriteStartNamespace(const protobuf::FileDescriptor* file, Output& output);
void WriteEndNamespace(const protobuf::FileDescriptor* file, Output& output);
void WriteStartNamespace(const protobuf::FileDescriptor* file, Context& ctx);
void WriteEndNamespace(const protobuf::FileDescriptor* file, Context& ctx);
std::string CppConstType(const protobuf::FieldDescriptor* field);
std::string CppTypeParameterName(const protobuf::FieldDescriptor* field);

@ -1,59 +0,0 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2023 Google LLC. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
#include "google/protobuf/compiler/hpb/output.h"
#include <string>
#include "upb_generator/c/names.h"
#include "upb_generator/minitable/names.h"
namespace google::protobuf::hpb_generator {
namespace {
namespace protobuf = ::proto2;
} // namespace
std::string ToCIdent(absl::string_view str) {
return absl::StrReplaceAll(str, {{".", "_"}, {"/", "_"}, {"-", "_"}});
}
std::string ToPreproc(absl::string_view str) {
return absl::AsciiStrToUpper(ToCIdent(str));
}
void EmitFileWarning(const protobuf::FileDescriptor* file, Output& output) {
output(
R"cc(
/* This file was generated by hpb_generator (Handle Protobuf) "
from the input
* file:
*
* $0
*
* Do not edit -- your changes will be discarded when the file is
* regenerated. */
)cc",
file->name());
output("\n");
}
std::string MessageName(const protobuf::Descriptor* descriptor) {
return upb::generator::CApiMessageType(descriptor->full_name());
}
std::string FileLayoutName(const google::protobuf::FileDescriptor* file) {
return upb::generator::MiniTableFileVarName(file->name());
}
std::string CHeaderFilename(const google::protobuf::FileDescriptor* file) {
return upb::generator::CApiHeaderFilename(file->name());
}
} // namespace protobuf
} // namespace google::hpb_generator

@ -1,150 +0,0 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2023 Google LLC. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
#ifndef PROTOBUF_COMPILER_HBP_OUTPUT_H_
#define PROTOBUF_COMPILER_HBP_OUTPUT_H_
#include <vector>
#include "absl/log/absl_log.h"
#include "absl/strings/str_replace.h"
#include "absl/strings/substitute.h"
#include "google/protobuf/descriptor.h"
#include "google/protobuf/io/zero_copy_stream.h"
namespace google::protobuf::hpb_generator {
class Output {
public:
Output(google::protobuf::io::ZeroCopyOutputStream* stream) : stream_(stream) {}
~Output() { stream_->BackUp((int)buffer_size_); }
template <class... Arg>
void operator()(absl::string_view format, const Arg&... arg) {
Write(absl::Substitute(format, arg...));
}
// Indentation size in characters.
static constexpr size_t kIndentationSize = 2;
void Indent() { Indent(kIndentationSize); }
void Indent(size_t size) { indent_ += size; }
void Outdent() { Outdent(kIndentationSize); }
void Outdent(size_t size) {
if (indent_ < size) {
ABSL_LOG(FATAL) << "mismatched Output indent/unindent calls";
}
indent_ -= size;
}
private:
void Write(absl::string_view data) {
std::string stripped;
if (absl::StartsWith(data, "\n ")) {
size_t indent = data.substr(1).find_first_not_of(' ');
if (indent > indent_) {
indent -= indent_;
}
if (indent != absl::string_view::npos) {
// Remove indentation from all lines.
auto line_prefix = data.substr(0, indent + 1);
// The final line has an extra newline and is indented two less, eg.
// R"cc(
// UPB_INLINE $0 $1_$2(const $1 *msg) {
// return $1_has_$2(msg) ? *UPB_PTR_AT(msg, $3, $0) : $4;
// }
// )cc",
std::string last_line_prefix = std::string(line_prefix);
last_line_prefix.resize(last_line_prefix.size() - 2);
data.remove_prefix(line_prefix.size());
stripped = absl::StrReplaceAll(
data, {{line_prefix, "\n"}, {last_line_prefix, "\n"}});
data = stripped;
}
} else {
WriteIndent();
}
WriteRaw(data);
}
void WriteRaw(absl::string_view data) {
while (!data.empty()) {
RefreshOutput();
size_t to_write = std::min(data.size(), buffer_size_);
memcpy(output_buffer_, data.data(), to_write);
data.remove_prefix(to_write);
output_buffer_ += to_write;
buffer_size_ -= to_write;
}
}
void WriteIndent() {
if (indent_ == 0) {
return;
}
size_t size = indent_;
while (size > buffer_size_) {
if (buffer_size_ > 0) {
memset(output_buffer_, ' ', buffer_size_);
}
size -= buffer_size_;
buffer_size_ = 0;
RefreshOutput();
}
memset(output_buffer_, ' ', size);
output_buffer_ += size;
buffer_size_ -= size;
}
void RefreshOutput() {
while (buffer_size_ == 0) {
void* void_buffer;
int size;
if (!stream_->Next(&void_buffer, &size)) {
fprintf(stderr, "upb_generator: Failed to write to to output\n");
abort();
}
output_buffer_ = static_cast<char*>(void_buffer);
buffer_size_ = size;
}
}
google::protobuf::io::ZeroCopyOutputStream* stream_;
char* output_buffer_ = nullptr;
size_t buffer_size_ = 0;
// Current indentation size in characters.
size_t indent_ = 0;
friend class OutputIndenter;
};
class OutputIndenter {
public:
OutputIndenter(Output& output)
: OutputIndenter(output, Output::kIndentationSize) {}
OutputIndenter(Output& output, size_t indent_size)
: indent_size_(indent_size), output_(output) {
output.Indent(indent_size);
}
~OutputIndenter() { output_.Outdent(indent_size_); }
private:
size_t indent_size_;
Output& output_;
};
std::string ToCIdent(absl::string_view str);
std::string ToPreproc(absl::string_view str);
void EmitFileWarning(const google::protobuf::FileDescriptor* file, Output& output);
std::string MessageName(const google::protobuf::Descriptor* descriptor);
std::string FileLayoutName(const google::protobuf::FileDescriptor* file);
std::string CHeaderFilename(const google::protobuf::FileDescriptor* file);
} // namespace protobuf
} // namespace google::hpb_generator
#endif // PROTOBUF_COMPILER_HBP_OUTPUT_H_

@ -13,12 +13,12 @@
#include "google/protobuf/descriptor.pb.h"
#include "google/protobuf/compiler/code_generator.h"
#include "google/protobuf/compiler/hpb/context.h"
#include "google/protobuf/compiler/hpb/gen_enums.h"
#include "google/protobuf/compiler/hpb/gen_extensions.h"
#include "google/protobuf/compiler/hpb/gen_messages.h"
#include "google/protobuf/compiler/hpb/gen_utils.h"
#include "google/protobuf/compiler/hpb/names.h"
#include "google/protobuf/compiler/hpb/output.h"
#include "google/protobuf/compiler/plugin.h"
#include "google/protobuf/descriptor.h"
@ -30,21 +30,19 @@ namespace protobuf = ::proto2;
using FileDescriptor = ::google::protobuf::FileDescriptor;
using google::protobuf::Edition;
void WriteSource(const protobuf::FileDescriptor* file, Output& output,
void WriteSource(const protobuf::FileDescriptor* file, Context& ctx,
bool fasttable_enabled, bool strip_feature_includes);
void WriteHeader(const protobuf::FileDescriptor* file, Output& output,
void WriteHeader(const protobuf::FileDescriptor* file, Context& ctx,
bool strip_feature_includes);
void WriteForwardingHeader(const protobuf::FileDescriptor* file,
Output& output);
void WriteForwardingHeader(const protobuf::FileDescriptor* file, Context& ctx);
void WriteMessageImplementations(const protobuf::FileDescriptor* file,
Output& output);
Context& ctx);
void WriteTypedefForwardingHeader(
const protobuf::FileDescriptor* file,
const std::vector<const protobuf::Descriptor*>& file_messages,
Output& output);
Context& ctx);
void WriteHeaderMessageForwardDecls(const protobuf::FileDescriptor* file,
Output& output,
bool strip_feature_includes);
Context& ctx, bool strip_feature_includes);
class Generator : public protoc::CodeGenerator {
public:
@ -83,53 +81,53 @@ bool Generator::Generate(const protobuf::FileDescriptor* file,
// Write model.upb.fwd.h
std::unique_ptr<google::protobuf::io::ZeroCopyOutputStream> output_stream(
context->Open(ForwardingHeaderFilename(file)));
Output forwarding_header_output(output_stream.get());
WriteForwardingHeader(file, forwarding_header_output);
auto fwd_ctx = Context(output_stream.get(), Options{.backend = Backend::UPB});
WriteForwardingHeader(file, fwd_ctx);
// Write model.upb.proto.h
std::unique_ptr<google::protobuf::io::ZeroCopyOutputStream> header_output_stream(
context->Open(CppHeaderFilename(file)));
Output header_output(header_output_stream.get());
WriteHeader(file, header_output, strip_nonfunctional_codegen);
Context hdr_ctx(header_output_stream.get(), Options{.backend = Backend::UPB});
WriteHeader(file, hdr_ctx, strip_nonfunctional_codegen);
// Write model.upb.proto.cc
std::unique_ptr<google::protobuf::io::ZeroCopyOutputStream> cc_output_stream(
context->Open(CppSourceFilename(file)));
Output cc_output(cc_output_stream.get());
WriteSource(file, cc_output, fasttable_enabled, strip_nonfunctional_codegen);
auto cc_ctx =
Context(cc_output_stream.get(), Options{.backend = Backend::UPB});
WriteSource(file, cc_ctx, fasttable_enabled, strip_nonfunctional_codegen);
return true;
}
// The forwarding header defines Access/Proxy/CProxy for message classes
// used to include when referencing dependencies to prevent transitive
// dependency headers from being included.
void WriteForwardingHeader(const protobuf::FileDescriptor* file,
Output& output) {
EmitFileWarning(file, output);
output(
void WriteForwardingHeader(const protobuf::FileDescriptor* file, Context& ctx) {
EmitFileWarning(file, ctx);
ctx.EmitLegacy(
R"cc(
#ifndef $0_UPB_FWD_H_
#define $0_UPB_FWD_H_
)cc",
ToPreproc(file->name()));
output("\n");
ctx.Emit("\n");
for (int i = 0; i < file->public_dependency_count(); ++i) {
output("#include \"$0\"\n",
ForwardingHeaderFilename(file->public_dependency(i)));
ctx.EmitLegacy("#include \"$0\"\n",
ForwardingHeaderFilename(file->public_dependency(i)));
}
if (file->public_dependency_count() > 0) {
output("\n");
ctx.Emit("\n");
}
const std::vector<const protobuf::Descriptor*> this_file_messages =
SortedMessages(file);
WriteTypedefForwardingHeader(file, this_file_messages, output);
output("#endif /* $0_UPB_FWD_H_ */\n", ToPreproc(file->name()));
WriteTypedefForwardingHeader(file, this_file_messages, ctx);
ctx.EmitLegacy("#endif /* $0_UPB_FWD_H_ */\n", ToPreproc(file->name()));
}
void WriteHeader(const protobuf::FileDescriptor* file, Output& output,
void WriteHeader(const protobuf::FileDescriptor* file, Context& ctx,
bool strip_feature_includes) {
EmitFileWarning(file, output);
output(
EmitFileWarning(file, ctx);
ctx.EmitLegacy(
R"cc(
#ifndef $0_HPB_PROTO_H_
#define $0_HPB_PROTO_H_
@ -144,15 +142,16 @@ void WriteHeader(const protobuf::FileDescriptor* file, Output& output,
// Import headers for proto public dependencies.
for (int i = 0; i < file->public_dependency_count(); i++) {
if (i == 0) {
output("// Public Imports.\n");
ctx.Emit("// Public Imports.\n");
}
output("#include \"$0\"\n", CppHeaderFilename(file->public_dependency(i)));
ctx.EmitLegacy("#include \"$0\"\n",
CppHeaderFilename(file->public_dependency(i)));
if (i == file->public_dependency_count() - 1) {
output("\n");
ctx.Emit("\n");
}
}
output("#include \"upb/port/def.inc\"\n");
ctx.Emit("#include \"upb/port/def.inc\"\n");
const std::vector<const protobuf::Descriptor*> this_file_messages =
SortedMessages(file);
@ -160,42 +159,42 @@ void WriteHeader(const protobuf::FileDescriptor* file, Output& output,
SortedExtensions(file);
if (!this_file_messages.empty()) {
output("\n");
ctx.Emit("\n");
}
WriteHeaderMessageForwardDecls(file, output, strip_feature_includes);
WriteStartNamespace(file, output);
WriteHeaderMessageForwardDecls(file, ctx, strip_feature_includes);
WriteStartNamespace(file, ctx);
std::vector<const protobuf::EnumDescriptor*> this_file_enums =
SortedEnums(file);
// Write Class and Enums.
WriteEnumDeclarations(this_file_enums, output);
output("\n");
WriteEnumDeclarations(this_file_enums, ctx);
ctx.Emit("\n");
for (auto message : this_file_messages) {
WriteMessageClassDeclarations(message, this_file_exts, this_file_enums,
output);
ctx);
}
output("\n");
ctx.Emit("\n");
WriteExtensionIdentifiersHeader(this_file_exts, output);
output("\n");
WriteExtensionIdentifiersHeader(this_file_exts, ctx);
ctx.Emit("\n");
WriteEndNamespace(file, output);
WriteEndNamespace(file, ctx);
output("\n#include \"upb/port/undef.inc\"\n\n");
ctx.Emit("\n#include \"upb/port/undef.inc\"\n\n");
// End of "C" section.
output("#endif /* $0_HPB_PROTO_H_ */\n", ToPreproc(file->name()));
ctx.EmitLegacy("#endif /* $0_HPB_PROTO_H_ */\n", ToPreproc(file->name()));
}
// Writes a .upb.cc source file.
void WriteSource(const protobuf::FileDescriptor* file, Output& output,
void WriteSource(const protobuf::FileDescriptor* file, Context& ctx,
bool fasttable_enabled, bool strip_feature_includes) {
EmitFileWarning(file, output);
EmitFileWarning(file, ctx);
output(
ctx.EmitLegacy(
R"cc(
#include <stddef.h>
#include "absl/log/absl_check.h"
@ -210,40 +209,40 @@ void WriteSource(const protobuf::FileDescriptor* file, Output& output,
// Strip feature imports for editions codegen tests.
continue;
}
output("#include \"$0\"\n", CppHeaderFilename(file->dependency(i)));
ctx.EmitLegacy("#include \"$0\"\n", CppHeaderFilename(file->dependency(i)));
}
output("#include \"upb/port/def.inc\"\n");
ctx.EmitLegacy("#include \"upb/port/def.inc\"\n");
WriteStartNamespace(file, output);
WriteMessageImplementations(file, output);
WriteStartNamespace(file, ctx);
WriteMessageImplementations(file, ctx);
const std::vector<const protobuf::FieldDescriptor*> this_file_exts =
SortedExtensions(file);
WriteExtensionIdentifiers(this_file_exts, output);
WriteEndNamespace(file, output);
WriteExtensionIdentifiers(this_file_exts, ctx);
WriteEndNamespace(file, ctx);
output("#include \"upb/port/undef.inc\"\n\n");
ctx.Emit("#include \"upb/port/undef.inc\"\n\n");
}
void WriteMessageImplementations(const protobuf::FileDescriptor* file,
Output& output) {
Context& ctx) {
const std::vector<const protobuf::FieldDescriptor*> file_exts =
SortedExtensions(file);
const std::vector<const protobuf::Descriptor*> this_file_messages =
SortedMessages(file);
for (auto message : this_file_messages) {
WriteMessageImplementation(message, file_exts, output);
WriteMessageImplementation(message, file_exts, ctx);
}
}
void WriteTypedefForwardingHeader(
const protobuf::FileDescriptor* file,
const std::vector<const protobuf::Descriptor*>& file_messages,
Output& output) {
WriteStartNamespace(file, output);
Context& ctx) {
WriteStartNamespace(file, ctx);
// Forward-declare types defined in this file.
for (auto message : file_messages) {
output(
ctx.EmitLegacy(
R"cc(
class $0;
namespace internal {
@ -254,17 +253,16 @@ void WriteTypedefForwardingHeader(
)cc",
ClassName(message));
}
output("\n");
WriteEndNamespace(file, output);
ctx.Emit("\n");
WriteEndNamespace(file, ctx);
}
/// Writes includes for upb C minitables and fwd.h for transitive typedefs.
void WriteHeaderMessageForwardDecls(const protobuf::FileDescriptor* file,
Output& output,
bool strip_feature_includes) {
Context& ctx, bool strip_feature_includes) {
// Import forward-declaration of types defined in this file.
output("#include \"$0\"\n", UpbCFilename(file));
output("#include \"$0\"\n", ForwardingHeaderFilename(file));
ctx.EmitLegacy("#include \"$0\"\n", UpbCFilename(file));
ctx.EmitLegacy("#include \"$0\"\n", ForwardingHeaderFilename(file));
// Import forward-declaration of types in dependencies.
for (int i = 0; i < file->dependency_count(); ++i) {
if (strip_feature_includes &&
@ -272,9 +270,10 @@ void WriteHeaderMessageForwardDecls(const protobuf::FileDescriptor* file,
// Strip feature imports for editions codegen tests.
continue;
}
output("#include \"$0\"\n", ForwardingHeaderFilename(file->dependency(i)));
ctx.EmitLegacy("#include \"$0\"\n",
ForwardingHeaderFilename(file->dependency(i)));
}
output("\n");
ctx.Emit("\n");
}
} // namespace

Loading…
Cancel
Save