2008-08-22 20:38:05 +00:00
|
|
|
// Protocol Buffers - Google's data interchange format
|
2013-11-18 20:25:34 -05:00
|
|
|
// Copyright 2008 Google Inc. All rights reserved.
|
2008-08-22 20:38:05 +00:00
|
|
|
// http://code.google.com/p/protobuf/
|
|
|
|
//
|
2013-11-18 20:25:34 -05:00
|
|
|
// Redistribution and use in source and binary forms, with or without
|
|
|
|
// modification, are permitted provided that the following conditions are
|
|
|
|
// met:
|
2008-08-22 20:38:05 +00:00
|
|
|
//
|
2013-11-18 20:25:34 -05:00
|
|
|
// * Redistributions of source code must retain the above copyright
|
|
|
|
// notice, this list of conditions and the following disclaimer.
|
|
|
|
// * Redistributions in binary form must reproduce the above
|
|
|
|
// copyright notice, this list of conditions and the following disclaimer
|
|
|
|
// in the documentation and/or other materials provided with the
|
|
|
|
// distribution.
|
|
|
|
// * Neither the name of Google Inc. nor the names of its
|
|
|
|
// contributors may be used to endorse or promote products derived from
|
|
|
|
// this software without specific prior written permission.
|
2008-08-22 20:38:05 +00:00
|
|
|
//
|
2013-11-18 20:25:34 -05:00
|
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
|
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
|
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
|
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
|
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
|
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
|
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
|
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
2008-08-22 20:38:05 +00:00
|
|
|
|
|
|
|
// Author: kenton@google.com (Kenton Varda)
|
|
|
|
// Based on original Protocol Buffers design by
|
|
|
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
|
|
|
|
2013-11-18 20:25:34 -05:00
|
|
|
// Copyright (c) 2008-2013, Dave Benson. All rights reserved.
|
|
|
|
//
|
|
|
|
// Redistribution and use in source and binary forms, with or without
|
|
|
|
// modification, are permitted provided that the following conditions are
|
|
|
|
// met:
|
|
|
|
//
|
|
|
|
// * Redistributions of source code must retain the above copyright
|
|
|
|
// notice, this list of conditions and the following disclaimer.
|
|
|
|
//
|
|
|
|
// * Redistributions in binary form must reproduce the above
|
|
|
|
// copyright notice, this list of conditions and the following disclaimer
|
|
|
|
// in the documentation and/or other materials provided with the
|
|
|
|
// distribution.
|
|
|
|
//
|
|
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
|
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
|
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
|
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
|
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
|
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
|
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
|
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
|
2008-08-22 20:38:05 +00:00
|
|
|
// Modified to implement C code by Dave Benson.
|
|
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
#include <map>
|
2018-08-13 21:26:00 -04:00
|
|
|
#include <memory>
|
2013-11-16 17:11:48 -05:00
|
|
|
#include <protoc-c/c_message.h>
|
|
|
|
#include <protoc-c/c_enum.h>
|
|
|
|
#include <protoc-c/c_extension.h>
|
|
|
|
#include <protoc-c/c_helpers.h>
|
2008-08-22 20:38:05 +00:00
|
|
|
#include <google/protobuf/io/printer.h>
|
|
|
|
#include <google/protobuf/io/coded_stream.h>
|
|
|
|
#include <google/protobuf/wire_format.h>
|
2021-03-19 18:54:16 -07:00
|
|
|
#include <protobuf-c/protobuf-c.pb.h>
|
2008-08-22 20:38:05 +00:00
|
|
|
|
|
|
|
namespace google {
|
|
|
|
namespace protobuf {
|
|
|
|
namespace compiler {
|
|
|
|
namespace c {
|
|
|
|
|
|
|
|
// ===================================================================
|
|
|
|
|
|
|
|
MessageGenerator::MessageGenerator(const Descriptor* descriptor,
|
2020-10-16 16:35:43 -07:00
|
|
|
const std::string& dllexport_decl)
|
2008-08-22 20:38:05 +00:00
|
|
|
: descriptor_(descriptor),
|
|
|
|
dllexport_decl_(dllexport_decl),
|
|
|
|
field_generators_(descriptor),
|
2018-08-13 21:26:00 -04:00
|
|
|
nested_generators_(new std::unique_ptr<MessageGenerator>[
|
2008-08-22 20:38:05 +00:00
|
|
|
descriptor->nested_type_count()]),
|
2018-08-13 21:26:00 -04:00
|
|
|
enum_generators_(new std::unique_ptr<EnumGenerator>[
|
2008-08-22 20:38:05 +00:00
|
|
|
descriptor->enum_type_count()]),
|
2018-08-13 21:26:00 -04:00
|
|
|
extension_generators_(new std::unique_ptr<ExtensionGenerator>[
|
2008-08-22 20:38:05 +00:00
|
|
|
descriptor->extension_count()]) {
|
|
|
|
|
|
|
|
for (int i = 0; i < descriptor->nested_type_count(); i++) {
|
|
|
|
nested_generators_[i].reset(
|
|
|
|
new MessageGenerator(descriptor->nested_type(i), dllexport_decl));
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < descriptor->enum_type_count(); i++) {
|
|
|
|
enum_generators_[i].reset(
|
|
|
|
new EnumGenerator(descriptor->enum_type(i), dllexport_decl));
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < descriptor->extension_count(); i++) {
|
|
|
|
extension_generators_[i].reset(
|
|
|
|
new ExtensionGenerator(descriptor->extension(i), dllexport_decl));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
MessageGenerator::~MessageGenerator() {}
|
|
|
|
|
|
|
|
void MessageGenerator::
|
|
|
|
GenerateStructTypedef(io::Printer* printer) {
|
2020-05-13 15:10:33 -07:00
|
|
|
printer->Print("typedef struct $classname$ $classname$;\n",
|
2021-03-21 19:46:21 -07:00
|
|
|
"classname", FullNameToC(descriptor_->full_name(), descriptor_->file()));
|
2008-08-22 20:38:05 +00:00
|
|
|
|
|
|
|
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
|
|
|
|
nested_generators_[i]->GenerateStructTypedef(printer);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void MessageGenerator::
|
|
|
|
GenerateEnumDefinitions(io::Printer* printer) {
|
|
|
|
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
|
|
|
|
nested_generators_[i]->GenerateEnumDefinitions(printer);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < descriptor_->enum_type_count(); i++) {
|
|
|
|
enum_generators_[i]->GenerateDefinition(printer);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void MessageGenerator::
|
|
|
|
GenerateStructDefinition(io::Printer* printer) {
|
|
|
|
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
|
|
|
|
nested_generators_[i]->GenerateStructDefinition(printer);
|
|
|
|
}
|
|
|
|
|
2020-10-16 16:35:43 -07:00
|
|
|
std::map<std::string, std::string> vars;
|
2021-03-21 19:46:21 -07:00
|
|
|
vars["classname"] = FullNameToC(descriptor_->full_name(), descriptor_->file());
|
|
|
|
vars["lcclassname"] = FullNameToLower(descriptor_->full_name(), descriptor_->file());
|
|
|
|
vars["ucclassname"] = FullNameToUpper(descriptor_->full_name(), descriptor_->file());
|
2008-08-22 20:38:05 +00:00
|
|
|
vars["field_count"] = SimpleItoa(descriptor_->field_count());
|
|
|
|
if (dllexport_decl_.empty()) {
|
|
|
|
vars["dllexport"] = "";
|
|
|
|
} else {
|
|
|
|
vars["dllexport"] = dllexport_decl_ + " ";
|
|
|
|
}
|
|
|
|
|
2014-11-04 00:37:45 -08:00
|
|
|
// Generate the case enums for unions
|
|
|
|
for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
|
|
|
|
const OneofDescriptor *oneof = descriptor_->oneof_decl(i);
|
2017-02-25 15:39:44 -05:00
|
|
|
vars["opt_comma"] = ",";
|
|
|
|
|
2021-03-21 18:10:26 -07:00
|
|
|
vars["oneofname"] = CamelToUpper(oneof->name());
|
2021-03-21 19:46:21 -07:00
|
|
|
vars["foneofname"] = FullNameToC(oneof->full_name(), oneof->file());
|
2014-11-04 00:37:45 -08:00
|
|
|
|
|
|
|
printer->Print("typedef enum {\n");
|
|
|
|
printer->Indent();
|
|
|
|
printer->Print(vars, "$ucclassname$__$oneofname$__NOT_SET = 0,\n");
|
|
|
|
for (int j = 0; j < oneof->field_count(); j++) {
|
|
|
|
const FieldDescriptor *field = oneof->field(j);
|
2021-03-21 18:10:26 -07:00
|
|
|
vars["fieldname"] = CamelToUpper(field->name());
|
2014-11-04 00:37:45 -08:00
|
|
|
vars["fieldnum"] = SimpleItoa(field->number());
|
2016-06-16 23:59:23 -07:00
|
|
|
bool isLast = j == oneof->field_count() - 1;
|
|
|
|
if (isLast) {
|
|
|
|
vars["opt_comma"] = "";
|
|
|
|
}
|
|
|
|
printer->Print(vars, "$ucclassname$__$oneofname$_$fieldname$ = $fieldnum$$opt_comma$\n");
|
2014-11-04 00:37:45 -08:00
|
|
|
}
|
2020-05-12 12:20:35 -07:00
|
|
|
printer->Print(vars, " PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE($ucclassname$__$oneofname$__CASE)\n");
|
2014-11-04 00:37:45 -08:00
|
|
|
printer->Outdent();
|
|
|
|
printer->Print(vars, "} $foneofname$Case;\n\n");
|
|
|
|
}
|
|
|
|
|
2014-12-16 18:12:54 -08:00
|
|
|
SourceLocation msgSourceLoc;
|
|
|
|
descriptor_->GetSourceLocation(&msgSourceLoc);
|
|
|
|
PrintComment (printer, msgSourceLoc.leading_comments);
|
|
|
|
|
2021-03-20 17:10:13 -07:00
|
|
|
const ProtobufCMessageOptions opt =
|
|
|
|
descriptor_->options().GetExtension(pb_c_msg);
|
|
|
|
vars["base"] = opt.base_field_name();
|
|
|
|
|
2008-08-22 20:38:05 +00:00
|
|
|
printer->Print(vars,
|
2020-05-13 15:10:33 -07:00
|
|
|
"struct $dllexport$ $classname$\n"
|
2008-08-22 20:38:05 +00:00
|
|
|
"{\n"
|
2021-03-20 17:10:13 -07:00
|
|
|
" ProtobufCMessage $base$;\n");
|
2008-08-22 20:38:05 +00:00
|
|
|
|
|
|
|
// Generate fields.
|
|
|
|
printer->Indent();
|
|
|
|
for (int i = 0; i < descriptor_->field_count(); i++) {
|
|
|
|
const FieldDescriptor *field = descriptor_->field(i);
|
2014-11-04 00:37:45 -08:00
|
|
|
if (field->containing_oneof() == NULL) {
|
2014-12-16 18:12:54 -08:00
|
|
|
SourceLocation fieldSourceLoc;
|
|
|
|
field->GetSourceLocation(&fieldSourceLoc);
|
|
|
|
|
|
|
|
PrintComment (printer, fieldSourceLoc.leading_comments);
|
|
|
|
PrintComment (printer, fieldSourceLoc.trailing_comments);
|
2014-11-04 00:37:45 -08:00
|
|
|
field_generators_.get(field).GenerateStructMembers(printer);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Generate unions from oneofs.
|
|
|
|
for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
|
|
|
|
const OneofDescriptor *oneof = descriptor_->oneof_decl(i);
|
2021-03-21 18:10:26 -07:00
|
|
|
vars["oneofname"] = CamelToLower(oneof->name());
|
2021-03-21 19:46:21 -07:00
|
|
|
vars["foneofname"] = FullNameToC(oneof->full_name(), oneof->file());
|
2014-11-04 00:37:45 -08:00
|
|
|
|
|
|
|
printer->Print(vars, "$foneofname$Case $oneofname$_case;\n");
|
|
|
|
|
|
|
|
printer->Print("union {\n");
|
|
|
|
printer->Indent();
|
|
|
|
for (int j = 0; j < oneof->field_count(); j++) {
|
|
|
|
const FieldDescriptor *field = oneof->field(j);
|
2014-12-16 18:12:54 -08:00
|
|
|
SourceLocation fieldSourceLoc;
|
|
|
|
field->GetSourceLocation(&fieldSourceLoc);
|
|
|
|
|
|
|
|
PrintComment (printer, fieldSourceLoc.leading_comments);
|
|
|
|
PrintComment (printer, fieldSourceLoc.trailing_comments);
|
2014-11-04 00:37:45 -08:00
|
|
|
field_generators_.get(field).GenerateStructMembers(printer);
|
|
|
|
}
|
|
|
|
printer->Outdent();
|
|
|
|
printer->Print(vars, "};\n");
|
2008-08-22 20:38:05 +00:00
|
|
|
}
|
|
|
|
printer->Outdent();
|
|
|
|
|
2008-08-25 17:50:52 +00:00
|
|
|
printer->Print(vars, "};\n");
|
2008-08-23 19:59:17 +00:00
|
|
|
|
2008-11-30 06:10:28 +00:00
|
|
|
for (int i = 0; i < descriptor_->field_count(); i++) {
|
|
|
|
const FieldDescriptor *field = descriptor_->field(i);
|
|
|
|
if (field->has_default_value()) {
|
|
|
|
field_generators_.get(field).GenerateDefaultValueDeclarations(printer);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-08-23 19:59:17 +00:00
|
|
|
printer->Print(vars, "#define $ucclassname$__INIT \\\n"
|
2008-08-25 17:50:52 +00:00
|
|
|
" { PROTOBUF_C_MESSAGE_INIT (&$lcclassname$__descriptor) \\\n ");
|
2008-08-23 19:59:17 +00:00
|
|
|
for (int i = 0; i < descriptor_->field_count(); i++) {
|
|
|
|
const FieldDescriptor *field = descriptor_->field(i);
|
2014-11-04 00:37:45 -08:00
|
|
|
if (field->containing_oneof() == NULL) {
|
|
|
|
printer->Print(", ");
|
|
|
|
field_generators_.get(field).GenerateStaticInit(printer);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
|
|
|
|
const OneofDescriptor *oneof = descriptor_->oneof_decl(i);
|
2021-03-21 19:46:21 -07:00
|
|
|
vars["foneofname"] = FullNameToUpper(oneof->full_name(), oneof->file());
|
2014-11-04 00:37:45 -08:00
|
|
|
// Initialize the case enum
|
|
|
|
printer->Print(vars, ", $foneofname$__NOT_SET");
|
2016-02-02 14:09:23 +01:00
|
|
|
// Initialize the union
|
|
|
|
printer->Print(", {0}");
|
2008-08-23 19:59:17 +00:00
|
|
|
}
|
2008-08-25 17:50:52 +00:00
|
|
|
printer->Print(" }\n\n\n");
|
2008-08-23 19:59:17 +00:00
|
|
|
|
2008-08-22 20:38:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MessageGenerator::
|
2021-03-20 16:57:34 -07:00
|
|
|
GenerateHelperFunctionDeclarations(io::Printer* printer,
|
|
|
|
bool is_pack_deep,
|
|
|
|
bool gen_pack,
|
|
|
|
bool gen_init)
|
2008-08-22 20:38:05 +00:00
|
|
|
{
|
2021-03-20 16:57:34 -07:00
|
|
|
const ProtobufCMessageOptions opt =
|
|
|
|
descriptor_->options().GetExtension(pb_c_msg);
|
|
|
|
|
|
|
|
// Override parent settings, if needed
|
|
|
|
if (opt.has_gen_pack_helpers())
|
|
|
|
gen_pack = opt.gen_pack_helpers();
|
|
|
|
if (opt.has_gen_init_helpers())
|
|
|
|
gen_init = opt.gen_init_helpers();
|
|
|
|
|
2009-10-28 04:25:43 +00:00
|
|
|
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
|
2021-03-20 16:57:34 -07:00
|
|
|
bool nested_pack = !is_pack_deep ? opt.gen_pack_helpers() : gen_pack;
|
|
|
|
nested_generators_[i]->GenerateHelperFunctionDeclarations(printer, true,
|
|
|
|
nested_pack,
|
|
|
|
gen_init);
|
2009-10-28 04:25:43 +00:00
|
|
|
}
|
|
|
|
|
2020-10-16 16:35:43 -07:00
|
|
|
std::map<std::string, std::string> vars;
|
2021-03-21 19:46:21 -07:00
|
|
|
vars["classname"] = FullNameToC(descriptor_->full_name(), descriptor_->file());
|
|
|
|
vars["lcclassname"] = FullNameToLower(descriptor_->full_name(), descriptor_->file());
|
2021-03-20 16:57:34 -07:00
|
|
|
if (gen_init) {
|
|
|
|
printer->Print(vars,
|
2008-08-22 20:38:05 +00:00
|
|
|
"/* $classname$ methods */\n"
|
2008-11-30 06:22:21 +00:00
|
|
|
"void $lcclassname$__init\n"
|
|
|
|
" ($classname$ *message);\n"
|
2009-10-28 04:25:43 +00:00
|
|
|
);
|
2021-03-20 16:57:34 -07:00
|
|
|
}
|
|
|
|
if (gen_pack) {
|
2009-10-28 04:25:43 +00:00
|
|
|
printer->Print(vars,
|
2008-08-22 20:38:05 +00:00
|
|
|
"size_t $lcclassname$__get_packed_size\n"
|
|
|
|
" (const $classname$ *message);\n"
|
|
|
|
"size_t $lcclassname$__pack\n"
|
|
|
|
" (const $classname$ *message,\n"
|
2008-08-24 18:37:43 +00:00
|
|
|
" uint8_t *out);\n"
|
2008-08-22 20:38:05 +00:00
|
|
|
"size_t $lcclassname$__pack_to_buffer\n"
|
|
|
|
" (const $classname$ *message,\n"
|
|
|
|
" ProtobufCBuffer *buffer);\n"
|
|
|
|
"$classname$ *\n"
|
|
|
|
" $lcclassname$__unpack\n"
|
|
|
|
" (ProtobufCAllocator *allocator,\n"
|
|
|
|
" size_t len,\n"
|
2008-08-24 18:37:43 +00:00
|
|
|
" const uint8_t *data);\n"
|
2008-08-22 20:38:05 +00:00
|
|
|
"void $lcclassname$__free_unpacked\n"
|
|
|
|
" ($classname$ *message,\n"
|
|
|
|
" ProtobufCAllocator *allocator);\n"
|
|
|
|
);
|
2009-10-28 04:25:43 +00:00
|
|
|
}
|
2008-08-22 20:38:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MessageGenerator::
|
|
|
|
GenerateDescriptorDeclarations(io::Printer* printer) {
|
|
|
|
printer->Print("extern const ProtobufCMessageDescriptor $name$__descriptor;\n",
|
2021-03-21 19:46:21 -07:00
|
|
|
"name", FullNameToLower(descriptor_->full_name(), descriptor_->file()));
|
2008-08-22 20:38:05 +00:00
|
|
|
|
|
|
|
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
|
|
|
|
nested_generators_[i]->GenerateDescriptorDeclarations(printer);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < descriptor_->enum_type_count(); i++) {
|
|
|
|
enum_generators_[i]->GenerateDescriptorDeclarations(printer);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void MessageGenerator::GenerateClosureTypedef(io::Printer* printer)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
|
|
|
|
nested_generators_[i]->GenerateClosureTypedef(printer);
|
|
|
|
}
|
2020-10-16 16:35:43 -07:00
|
|
|
std::map<std::string, std::string> vars;
|
2021-03-21 19:46:21 -07:00
|
|
|
vars["name"] = FullNameToC(descriptor_->full_name(), descriptor_->file());
|
2008-08-22 20:38:05 +00:00
|
|
|
printer->Print(vars,
|
2008-08-26 14:45:34 +00:00
|
|
|
"typedef void (*$name$_Closure)\n"
|
2008-08-22 20:38:05 +00:00
|
|
|
" (const $name$ *message,\n"
|
2008-08-26 14:45:34 +00:00
|
|
|
" void *closure_data);\n");
|
2008-08-22 20:38:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
compare_pfields_by_number (const void *a, const void *b)
|
|
|
|
{
|
|
|
|
const FieldDescriptor *pa = *(const FieldDescriptor **)a;
|
|
|
|
const FieldDescriptor *pb = *(const FieldDescriptor **)b;
|
|
|
|
if (pa->number() < pb->number()) return -1;
|
|
|
|
if (pa->number() > pb->number()) return +1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MessageGenerator::
|
2021-03-20 16:57:34 -07:00
|
|
|
GenerateHelperFunctionDefinitions(io::Printer* printer,
|
|
|
|
bool is_pack_deep,
|
|
|
|
bool gen_pack,
|
|
|
|
bool gen_init)
|
2008-08-22 20:38:05 +00:00
|
|
|
{
|
2021-03-20 16:57:34 -07:00
|
|
|
const ProtobufCMessageOptions opt =
|
|
|
|
descriptor_->options().GetExtension(pb_c_msg);
|
|
|
|
|
|
|
|
// Override parent settings, if needed
|
|
|
|
if (opt.has_gen_pack_helpers())
|
|
|
|
gen_pack = opt.gen_pack_helpers();
|
|
|
|
if (opt.has_gen_init_helpers())
|
|
|
|
gen_init = opt.gen_init_helpers();
|
|
|
|
|
2009-10-28 04:25:43 +00:00
|
|
|
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
|
2021-03-20 16:57:34 -07:00
|
|
|
bool nested_pack = !is_pack_deep ? opt.gen_pack_helpers() : gen_pack;
|
|
|
|
nested_generators_[i]->GenerateHelperFunctionDefinitions(printer, true,
|
|
|
|
nested_pack,
|
|
|
|
gen_init);
|
2009-10-28 04:25:43 +00:00
|
|
|
}
|
|
|
|
|
2020-10-16 16:35:43 -07:00
|
|
|
std::map<std::string, std::string> vars;
|
2021-03-21 19:46:21 -07:00
|
|
|
vars["classname"] = FullNameToC(descriptor_->full_name(), descriptor_->file());
|
|
|
|
vars["lcclassname"] = FullNameToLower(descriptor_->full_name(), descriptor_->file());
|
|
|
|
vars["ucclassname"] = FullNameToUpper(descriptor_->full_name(), descriptor_->file());
|
2021-03-20 17:10:13 -07:00
|
|
|
vars["base"] = opt.base_field_name();
|
2021-03-20 16:57:34 -07:00
|
|
|
if (gen_init) {
|
|
|
|
printer->Print(vars,
|
2008-11-30 06:22:21 +00:00
|
|
|
"void $lcclassname$__init\n"
|
|
|
|
" ($classname$ *message)\n"
|
|
|
|
"{\n"
|
2016-09-07 15:18:41 +02:00
|
|
|
" static const $classname$ init_value = $ucclassname$__INIT;\n"
|
2008-11-30 06:22:21 +00:00
|
|
|
" *message = init_value;\n"
|
2008-12-17 16:40:48 +00:00
|
|
|
"}\n");
|
2021-03-20 16:57:34 -07:00
|
|
|
}
|
|
|
|
if (gen_pack) {
|
2009-10-28 04:25:43 +00:00
|
|
|
printer->Print(vars,
|
2008-08-22 20:38:05 +00:00
|
|
|
"size_t $lcclassname$__get_packed_size\n"
|
|
|
|
" (const $classname$ *message)\n"
|
|
|
|
"{\n"
|
2021-03-20 17:10:13 -07:00
|
|
|
" assert(message->$base$.descriptor == &$lcclassname$__descriptor);\n"
|
2008-10-08 02:22:40 +00:00
|
|
|
" return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));\n"
|
2008-08-22 20:38:05 +00:00
|
|
|
"}\n"
|
|
|
|
"size_t $lcclassname$__pack\n"
|
|
|
|
" (const $classname$ *message,\n"
|
2008-08-24 18:37:43 +00:00
|
|
|
" uint8_t *out)\n"
|
2008-08-22 20:38:05 +00:00
|
|
|
"{\n"
|
2021-03-20 17:10:13 -07:00
|
|
|
" assert(message->$base$.descriptor == &$lcclassname$__descriptor);\n"
|
2008-10-08 02:22:40 +00:00
|
|
|
" return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);\n"
|
2008-08-22 20:38:05 +00:00
|
|
|
"}\n"
|
|
|
|
"size_t $lcclassname$__pack_to_buffer\n"
|
|
|
|
" (const $classname$ *message,\n"
|
|
|
|
" ProtobufCBuffer *buffer)\n"
|
|
|
|
"{\n"
|
2021-03-20 17:10:13 -07:00
|
|
|
" assert(message->$base$.descriptor == &$lcclassname$__descriptor);\n"
|
2008-10-08 02:22:40 +00:00
|
|
|
" return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);\n"
|
2008-08-22 20:38:05 +00:00
|
|
|
"}\n"
|
|
|
|
"$classname$ *\n"
|
|
|
|
" $lcclassname$__unpack\n"
|
|
|
|
" (ProtobufCAllocator *allocator,\n"
|
|
|
|
" size_t len,\n"
|
2008-08-24 18:37:43 +00:00
|
|
|
" const uint8_t *data)\n"
|
2008-08-22 20:38:05 +00:00
|
|
|
"{\n"
|
|
|
|
" return ($classname$ *)\n"
|
|
|
|
" protobuf_c_message_unpack (&$lcclassname$__descriptor,\n"
|
|
|
|
" allocator, len, data);\n"
|
|
|
|
"}\n"
|
|
|
|
"void $lcclassname$__free_unpacked\n"
|
|
|
|
" ($classname$ *message,\n"
|
|
|
|
" ProtobufCAllocator *allocator)\n"
|
|
|
|
"{\n"
|
2017-02-25 19:58:34 +00:00
|
|
|
" if(!message)\n"
|
|
|
|
" return;\n"
|
2021-03-20 17:10:13 -07:00
|
|
|
" assert(message->$base$.descriptor == &$lcclassname$__descriptor);\n"
|
2008-08-22 20:38:05 +00:00
|
|
|
" protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);\n"
|
|
|
|
"}\n"
|
|
|
|
);
|
2009-10-28 04:25:43 +00:00
|
|
|
}
|
2008-08-22 20:38:05 +00:00
|
|
|
}
|
|
|
|
|
2008-11-30 06:10:28 +00:00
|
|
|
void MessageGenerator::
|
2021-03-20 16:57:34 -07:00
|
|
|
GenerateMessageDescriptor(io::Printer* printer, bool gen_init) {
|
2020-10-16 16:35:43 -07:00
|
|
|
std::map<std::string, std::string> vars;
|
2008-11-30 06:10:28 +00:00
|
|
|
vars["fullname"] = descriptor_->full_name();
|
2021-03-21 19:46:21 -07:00
|
|
|
vars["classname"] = FullNameToC(descriptor_->full_name(), descriptor_->file());
|
|
|
|
vars["lcclassname"] = FullNameToLower(descriptor_->full_name(), descriptor_->file());
|
2008-11-30 06:10:28 +00:00
|
|
|
vars["shortname"] = ToCamel(descriptor_->name());
|
|
|
|
vars["n_fields"] = SimpleItoa(descriptor_->field_count());
|
|
|
|
vars["packagename"] = descriptor_->file()->package();
|
|
|
|
|
2015-10-30 15:54:00 -07:00
|
|
|
bool optimize_code_size = descriptor_->file()->options().has_optimize_for() &&
|
2015-02-14 17:17:10 -08:00
|
|
|
descriptor_->file()->options().optimize_for() ==
|
2015-10-30 15:54:00 -07:00
|
|
|
FileOptions_OptimizeMode_CODE_SIZE;
|
2015-02-14 17:17:10 -08:00
|
|
|
|
2021-03-20 16:57:34 -07:00
|
|
|
const ProtobufCMessageOptions opt =
|
|
|
|
descriptor_->options().GetExtension(pb_c_msg);
|
|
|
|
// Override parent settings, if needed
|
|
|
|
if (opt.has_gen_init_helpers())
|
|
|
|
gen_init = opt.gen_init_helpers();
|
|
|
|
|
2008-11-30 06:10:28 +00:00
|
|
|
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
|
2021-03-20 16:57:34 -07:00
|
|
|
nested_generators_[i]->GenerateMessageDescriptor(printer, gen_init);
|
2008-11-30 06:10:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < descriptor_->enum_type_count(); i++) {
|
|
|
|
enum_generators_[i]->GenerateEnumDescriptor(printer);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < descriptor_->field_count(); i++) {
|
|
|
|
const FieldDescriptor *fd = descriptor_->field(i);
|
|
|
|
if (fd->has_default_value()) {
|
|
|
|
field_generators_.get(fd).GenerateDefaultValueImplementations(printer);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < descriptor_->field_count(); i++) {
|
|
|
|
const FieldDescriptor *fd = descriptor_->field(i);
|
2021-03-20 17:35:21 -07:00
|
|
|
const ProtobufCFieldOptions opt = fd->options().GetExtension(pb_c_field);
|
2008-11-30 06:10:28 +00:00
|
|
|
if (fd->has_default_value()) {
|
|
|
|
|
|
|
|
bool already_defined = false;
|
|
|
|
vars["name"] = fd->name();
|
2008-12-17 16:46:13 +00:00
|
|
|
vars["lcname"] = CamelToLower(fd->name());
|
2008-11-30 06:10:28 +00:00
|
|
|
vars["maybe_static"] = "static ";
|
|
|
|
vars["field_dv_ctype_suffix"] = "";
|
|
|
|
vars["default_value"] = field_generators_.get(fd).GetDefaultValue();
|
|
|
|
switch (fd->cpp_type()) {
|
|
|
|
case FieldDescriptor::CPPTYPE_INT32:
|
|
|
|
vars["field_dv_ctype"] = "int32_t";
|
|
|
|
break;
|
|
|
|
case FieldDescriptor::CPPTYPE_INT64:
|
|
|
|
vars["field_dv_ctype"] = "int64_t";
|
|
|
|
break;
|
|
|
|
case FieldDescriptor::CPPTYPE_UINT32:
|
|
|
|
vars["field_dv_ctype"] = "uint32_t";
|
|
|
|
break;
|
|
|
|
case FieldDescriptor::CPPTYPE_UINT64:
|
|
|
|
vars["field_dv_ctype"] = "uint64_t";
|
|
|
|
break;
|
|
|
|
case FieldDescriptor::CPPTYPE_FLOAT:
|
|
|
|
vars["field_dv_ctype"] = "float";
|
|
|
|
break;
|
|
|
|
case FieldDescriptor::CPPTYPE_DOUBLE:
|
|
|
|
vars["field_dv_ctype"] = "double";
|
|
|
|
break;
|
|
|
|
case FieldDescriptor::CPPTYPE_BOOL:
|
|
|
|
vars["field_dv_ctype"] = "protobuf_c_boolean";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FieldDescriptor::CPPTYPE_MESSAGE:
|
|
|
|
// NOTE: not supported by protobuf
|
|
|
|
vars["maybe_static"] = "";
|
|
|
|
vars["field_dv_ctype"] = "{ ... }";
|
2023-07-02 19:35:43 -04:00
|
|
|
GOOGLE_LOG(FATAL) << "Messages can't have default values!";
|
2008-11-30 06:10:28 +00:00
|
|
|
break;
|
|
|
|
case FieldDescriptor::CPPTYPE_STRING:
|
2021-03-20 17:35:21 -07:00
|
|
|
if (fd->type() == FieldDescriptor::TYPE_BYTES || opt.string_as_bytes())
|
2008-11-30 06:10:28 +00:00
|
|
|
{
|
|
|
|
vars["field_dv_ctype"] = "ProtobufCBinaryData";
|
|
|
|
}
|
|
|
|
else /* STRING type */
|
|
|
|
{
|
|
|
|
already_defined = true;
|
|
|
|
vars["maybe_static"] = "";
|
|
|
|
vars["field_dv_ctype"] = "char";
|
|
|
|
vars["field_dv_ctype_suffix"] = "[]";
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case FieldDescriptor::CPPTYPE_ENUM:
|
|
|
|
{
|
|
|
|
const EnumValueDescriptor *vd = fd->default_value_enum();
|
2021-03-21 19:46:21 -07:00
|
|
|
vars["field_dv_ctype"] = FullNameToC(vd->type()->full_name(), vd->type()->file());
|
2008-11-30 06:10:28 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
2023-07-02 19:35:43 -04:00
|
|
|
GOOGLE_LOG(FATAL) << "Unknown CPPTYPE";
|
2008-11-30 06:10:28 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (!already_defined)
|
2008-12-17 16:46:13 +00:00
|
|
|
printer->Print(vars, "$maybe_static$const $field_dv_ctype$ $lcclassname$__$lcname$__default_value$field_dv_ctype_suffix$ = $default_value$;\n");
|
2008-11-30 06:10:28 +00:00
|
|
|
}
|
|
|
|
}
|
2008-08-22 20:38:05 +00:00
|
|
|
|
2011-03-10 19:12:35 +00:00
|
|
|
if ( descriptor_->field_count() ) {
|
2008-08-22 20:38:05 +00:00
|
|
|
printer->Print(vars,
|
2008-11-30 06:10:28 +00:00
|
|
|
"static const ProtobufCFieldDescriptor $lcclassname$__field_descriptors[$n_fields$] =\n"
|
|
|
|
"{\n");
|
2008-08-22 20:38:05 +00:00
|
|
|
printer->Indent();
|
|
|
|
const FieldDescriptor **sorted_fields = new const FieldDescriptor *[descriptor_->field_count()];
|
|
|
|
for (int i = 0; i < descriptor_->field_count(); i++) {
|
|
|
|
sorted_fields[i] = descriptor_->field(i);
|
|
|
|
}
|
|
|
|
qsort (sorted_fields, descriptor_->field_count(),
|
2008-11-30 06:10:28 +00:00
|
|
|
sizeof (const FieldDescriptor *),
|
|
|
|
compare_pfields_by_number);
|
2008-08-22 20:38:05 +00:00
|
|
|
for (int i = 0; i < descriptor_->field_count(); i++) {
|
|
|
|
const FieldDescriptor *field = sorted_fields[i];
|
|
|
|
field_generators_.get(field).GenerateDescriptorInitializer(printer);
|
|
|
|
}
|
|
|
|
printer->Outdent();
|
2008-11-30 06:10:28 +00:00
|
|
|
printer->Print(vars, "};\n");
|
2008-08-22 20:38:05 +00:00
|
|
|
|
2015-10-30 15:54:00 -07:00
|
|
|
if (!optimize_code_size) {
|
2015-02-14 17:17:10 -08:00
|
|
|
NameIndex *field_indices = new NameIndex [descriptor_->field_count()];
|
|
|
|
for (int i = 0; i < descriptor_->field_count(); i++) {
|
|
|
|
field_indices[i].name = sorted_fields[i]->name().c_str();
|
|
|
|
field_indices[i].index = i;
|
|
|
|
}
|
|
|
|
qsort (field_indices, descriptor_->field_count(), sizeof (NameIndex),
|
|
|
|
compare_name_indices_by_name);
|
|
|
|
printer->Print(vars, "static const unsigned $lcclassname$__field_indices_by_name[] = {\n");
|
|
|
|
for (int i = 0; i < descriptor_->field_count(); i++) {
|
|
|
|
vars["index"] = SimpleItoa(field_indices[i].index);
|
|
|
|
vars["name"] = field_indices[i].name;
|
|
|
|
printer->Print(vars, " $index$, /* field[$index$] = $name$ */\n");
|
|
|
|
}
|
|
|
|
printer->Print("};\n");
|
|
|
|
delete[] field_indices;
|
2008-08-27 02:14:42 +00:00
|
|
|
}
|
|
|
|
|
2008-08-22 20:38:05 +00:00
|
|
|
// create range initializers
|
|
|
|
int *values = new int[descriptor_->field_count()];
|
|
|
|
for (int i = 0; i < descriptor_->field_count(); i++) {
|
|
|
|
values[i] = sorted_fields[i]->number();
|
|
|
|
}
|
|
|
|
int n_ranges = WriteIntRanges(printer,
|
2008-11-30 06:10:28 +00:00
|
|
|
descriptor_->field_count(), values,
|
|
|
|
vars["lcclassname"] + "__number_ranges");
|
2008-08-22 20:38:05 +00:00
|
|
|
delete [] values;
|
|
|
|
delete [] sorted_fields;
|
|
|
|
|
|
|
|
vars["n_ranges"] = SimpleItoa(n_ranges);
|
2011-03-10 19:12:35 +00:00
|
|
|
} else {
|
|
|
|
/* MS compiler can't handle arrays with zero size and empty
|
|
|
|
* initialization list. Furthermore it is an extension of GCC only but
|
|
|
|
* not a standard. */
|
|
|
|
vars["n_ranges"] = "0";
|
|
|
|
printer->Print(vars,
|
|
|
|
"#define $lcclassname$__field_descriptors NULL\n"
|
|
|
|
"#define $lcclassname$__field_indices_by_name NULL\n"
|
|
|
|
"#define $lcclassname$__number_ranges NULL\n");
|
|
|
|
}
|
2015-02-14 17:17:10 -08:00
|
|
|
|
|
|
|
printer->Print(vars,
|
|
|
|
"const ProtobufCMessageDescriptor $lcclassname$__descriptor =\n"
|
|
|
|
"{\n"
|
|
|
|
" PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,\n");
|
2015-10-30 15:54:00 -07:00
|
|
|
if (optimize_code_size) {
|
|
|
|
printer->Print(" NULL,NULL,NULL,NULL, /* CODE_SIZE */\n");
|
2015-02-14 17:17:10 -08:00
|
|
|
} else {
|
|
|
|
printer->Print(vars,
|
|
|
|
" \"$fullname$\",\n"
|
|
|
|
" \"$shortname$\",\n"
|
|
|
|
" \"$classname$\",\n"
|
|
|
|
" \"$packagename$\",\n");
|
|
|
|
}
|
|
|
|
printer->Print(vars,
|
|
|
|
" sizeof($classname$),\n"
|
|
|
|
" $n_fields$,\n"
|
|
|
|
" $lcclassname$__field_descriptors,\n");
|
2015-10-30 15:54:00 -07:00
|
|
|
if (optimize_code_size) {
|
|
|
|
printer->Print(" NULL, /* CODE_SIZE */\n");
|
2015-02-14 17:17:10 -08:00
|
|
|
} else {
|
|
|
|
printer->Print(vars,
|
|
|
|
" $lcclassname$__field_indices_by_name,\n");
|
|
|
|
}
|
2008-08-22 20:38:05 +00:00
|
|
|
printer->Print(vars,
|
2015-02-14 17:17:10 -08:00
|
|
|
" $n_ranges$,"
|
2021-03-20 16:57:34 -07:00
|
|
|
" $lcclassname$__number_ranges,\n");
|
|
|
|
if (gen_init) {
|
|
|
|
printer->Print(vars,
|
|
|
|
" (ProtobufCMessageInit) $lcclassname$__init,\n");
|
|
|
|
} else {
|
|
|
|
printer->Print(vars,
|
|
|
|
" NULL, /* gen_init_helpers = false */\n");
|
|
|
|
}
|
|
|
|
printer->Print(vars,
|
2015-02-14 17:17:10 -08:00
|
|
|
" NULL,NULL,NULL /* reserved[123] */\n"
|
|
|
|
"};\n");
|
2008-08-22 20:38:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace c
|
|
|
|
} // namespace compiler
|
|
|
|
} // namespace protobuf
|
|
|
|
} // namespace google
|