mirror of
https://github.com/protocolbuffers/protobuf
synced 2026-08-26 02:23:14 -04:00
177 lines
5.5 KiB
C++
177 lines
5.5 KiB
C++
// 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 <cstddef>
|
|
#include <string>
|
|
|
|
#include "google/protobuf/descriptor.upb.h"
|
|
#include "absl/strings/escaping.h"
|
|
#include "absl/strings/str_format.h"
|
|
#include "absl/strings/str_join.h"
|
|
#include "absl/strings/string_view.h"
|
|
#include "absl/types/span.h"
|
|
#include "google/protobuf/compiler/code_generator.h"
|
|
#include "google/protobuf/io/printer.h"
|
|
#include "upb/mem/arena.hpp"
|
|
#include "upb/reflection/def.hpp"
|
|
#include "upb/util/def_to_proto.h"
|
|
#include "upb_generator/common/names.h"
|
|
#include "upb_generator/minitable/names.h"
|
|
#include "upb_generator/reflection/context.h"
|
|
#include "upb_generator/reflection/header.h"
|
|
#include "upb_generator/reflection/names.h"
|
|
|
|
namespace upb::generator::reflection {
|
|
namespace {
|
|
|
|
using Sub = google::protobuf::io::Printer::Sub;
|
|
|
|
static std::string DefSourceFilename(upb::FileDefPtr file) {
|
|
return StripExtension(file.name()) + ".upbdefs.c";
|
|
}
|
|
|
|
void WriteIncludes(upb::FileDefPtr file, Context& ctx) {
|
|
ctx.Emit(
|
|
{
|
|
{"def_header_filename", DefHeaderFilename(file)},
|
|
{"mini_table_header_filename", MiniTableHeaderFilename(file.name())},
|
|
},
|
|
R"(
|
|
#include "upb/reflection/def.h"
|
|
#include "$def_header_filename$"
|
|
#include "$mini_table_header_filename$"
|
|
)");
|
|
}
|
|
|
|
void WriteDefPoolFwdDecls(upb::FileDefPtr file, Context& ctx) {
|
|
if (file.dependency_count() == 0) return;
|
|
|
|
for (int i = 0; i < file.dependency_count(); i++) {
|
|
ctx.Emit(
|
|
{{"dllexport_decl", ctx.options().dllexport_decl},
|
|
{"def_init_symbol", ReflectionFileSymbol(file.dependency(i).name())}},
|
|
R"cc(
|
|
extern$ dllexport_decl$ _upb_DefPool_Init $def_init_symbol$;
|
|
)cc");
|
|
}
|
|
|
|
ctx.Emit("\n");
|
|
}
|
|
|
|
void WriteStringArrayLine(absl::string_view data, Context& ctx) {
|
|
std::string line = absl::StrJoin(data, ", ", [](std::string* out, char ch) {
|
|
absl::StrAppendFormat(out, "'%v'",
|
|
absl::CEscape(absl::string_view(&ch, 1)));
|
|
});
|
|
ctx.Emit({{"line", line}},
|
|
R"cc(
|
|
$line$,
|
|
)cc");
|
|
}
|
|
|
|
void WriteStringArray(absl::string_view data, Context& ctx) {
|
|
const size_t kMaxLineLength = 12;
|
|
for (size_t i = 0; i < data.size(); i += kMaxLineLength) {
|
|
WriteStringArrayLine(data.substr(i, kMaxLineLength), ctx);
|
|
}
|
|
}
|
|
|
|
void WriteDescriptor(upb::FileDefPtr file, Context& ctx) {
|
|
upb::Arena arena;
|
|
google_protobuf_FileDescriptorProto* file_proto =
|
|
upb_FileDef_ToProto(file.ptr(), arena.ptr());
|
|
size_t serialized_size;
|
|
const char* serialized = google_protobuf_FileDescriptorProto_serialize(
|
|
file_proto, arena.ptr(), &serialized_size);
|
|
absl::string_view file_data(serialized, serialized_size);
|
|
|
|
ctx.Emit(
|
|
{{"serialized_size", file_data.size()},
|
|
{"defpool_init_name", ReflectionFileSymbol(file.name())},
|
|
{"contents", [&] { WriteStringArray(file_data, ctx); }}},
|
|
R"cc(
|
|
static const char descriptor_$defpool_init_name$[$serialized_size$] = {
|
|
$contents$,
|
|
};
|
|
)cc");
|
|
ctx.Emit("\n");
|
|
}
|
|
|
|
void WriteDependencies(upb::FileDefPtr file, Context& ctx) {
|
|
auto write_dep = [&](int i) {
|
|
ctx.Emit({{"sym", ReflectionFileSymbol(file.dependency(i).name())}},
|
|
R"cc(
|
|
&$sym$,
|
|
)cc");
|
|
};
|
|
|
|
auto write_deps = [&] {
|
|
for (int i = 0; i < file.dependency_count(); i++) write_dep(i);
|
|
};
|
|
|
|
ctx.Emit({{"dep_count", file.dependency_count() + 1},
|
|
{"defpool_init_name", ReflectionFileSymbol(file.name())},
|
|
{google::protobuf::io::Printer::Sub("deps", write_deps).WithSuffix(",")}},
|
|
R"cc(
|
|
static _upb_DefPool_Init* deps_$defpool_init_name$[$dep_count$] = {
|
|
$deps$,
|
|
NULL,
|
|
};
|
|
)cc");
|
|
ctx.Emit("\n");
|
|
}
|
|
|
|
void WriteDefPoolInitStruct(upb::FileDefPtr file, Context& ctx) {
|
|
ctx.Emit(
|
|
{
|
|
{"defpool_init_name", ReflectionFileSymbol(file.name())},
|
|
{"file_name", file.name()},
|
|
{"mini_table_file_var_name", MiniTableFileVarName(file.name())},
|
|
},
|
|
R"cc(
|
|
_upb_DefPool_Init $defpool_init_name$ = {
|
|
deps_$defpool_init_name$,
|
|
&$mini_table_file_var_name$,
|
|
"$file_name$",
|
|
UPB_STRINGVIEW_INIT(descriptor_$defpool_init_name$,
|
|
sizeof(descriptor_$defpool_init_name$)),
|
|
};
|
|
)cc");
|
|
}
|
|
|
|
void WriteDefPoolInit(upb::FileDefPtr file, Context& ctx) {
|
|
WriteDefPoolFwdDecls(file, ctx);
|
|
WriteDescriptor(file, ctx);
|
|
WriteDependencies(file, ctx);
|
|
WriteDefPoolInitStruct(file, ctx);
|
|
}
|
|
|
|
void WriteDefSource(upb::FileDefPtr file, Context& ctx) {
|
|
ctx.Emit(
|
|
{
|
|
{Sub("file_warning", FileWarning(file.name())).WithSuffix(";")},
|
|
{Sub("includes", [&] { WriteIncludes(file, ctx); }).WithSuffix(";")},
|
|
{Sub("def_pool_init", [&] { WriteDefPoolInit(file, ctx); })
|
|
.WithSuffix(";")},
|
|
},
|
|
R"cc(
|
|
$file_warning$;
|
|
$includes$;
|
|
|
|
$def_pool_init$;
|
|
)cc");
|
|
}
|
|
|
|
} // namespace
|
|
|
|
void GenerateReflectionSource(upb::FileDefPtr file, const Options& options,
|
|
google::protobuf::compiler::GeneratorContext* context) {
|
|
Context c_context(options, context->Open(DefSourceFilename(file)));
|
|
WriteDefSource(file, c_context);
|
|
}
|
|
|
|
} // namespace upb::generator::reflection
|