Merge branch 'protocolbuffers:main' into patch-2

pull/13171/head
Xavier Bonaventura 2 years ago committed by GitHub
commit e3b2db7d8c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      .github/workflows/bazel_tests.yml
  2. 2
      .github/workflows/python_tests.yml
  3. 860
      upb/def.c
  4. 36
      upb/io/tokenizer.c
  5. 16
      upb/io/tokenizer.h
  6. 36
      upb/io/tokenizer_test.cc
  7. 5
      upb/msg.c
  8. 3
      upb/msg_internal.h
  9. 5
      upb/msg_test.proto
  10. 19
      upbc/BUILD
  11. 2
      upbc/common.cc
  12. 81
      upbc/names.cc
  13. 51
      upbc/names.h
  14. 159
      upbc/protoc-gen-upb.cc

@ -36,13 +36,13 @@ jobs:
with:
credentials_json: ${{ secrets.GOOGLE_CREDENTIALS }}
export_environment_variables: true
if: ${{ github.repository_owner == 'protocolbuffers' }}
if: ${{ github.event.pull_request.head.repo.full_name == 'protocolbuffers/upb' }}
- name: Set up Bazel read/write caching
run: echo "BAZEL_CACHE_AUTH=--google_default_credentials" >> $GITHUB_ENV
if: ${{ github.repository_owner == 'protocolbuffers' }}
if: ${{ github.event.pull_request.head.repo.full_name == 'protocolbuffers/upb' }}
- name: Set up Bazel read-only caching
run: echo "BAZEL_CACHE_AUTH=--remote_upload_local_results=false" >> $GITHUB_ENV
if: ${{ github.repository_owner != 'protocolbuffers' }}
if: ${{ github.event.pull_request.head.repo.full_name != 'protocolbuffers/upb' }}
- name: Setup Python venv
run: rm -rf /tmp/venv && python3 -m venv /tmp/venv
- name: Install dependencies

@ -13,7 +13,7 @@ jobs:
build_wheels:
name: Build Wheels
runs-on: ubuntu-latest
if: ${{ github.repository_owner == 'protocolbuffers' }}
if: ${{ github.event.pull_request.head.repo.full_name == 'protocolbuffers/upb' }}
env:
DOCKER_IMAGE: gcr.io/protobuf-build/bazel/linux@sha256:2bfd061284eff8234f2fcca16d71d43c69ccf3a22206628b54c204a6a9aac277
BAZEL_CACHE: --remote_cache=https://storage.googleapis.com/protobuf-bazel-cache --google_default_credentials

File diff suppressed because it is too large Load Diff

@ -30,6 +30,7 @@
#include <stdio.h>
#include "upb/internal/unicode.h"
#include "upb/io/string.h"
#include "upb/io/strtod.h"
// Must be included last.
@ -871,23 +872,25 @@ static const char* FetchUnicodePoint(const char* ptr, uint32_t* code_point) {
}
// The text string must begin and end with single or double quote characters.
void upb_Parse_StringAppend(const char* text, upb_String* output) {
upb_StringView upb_Parse_String(const char* text, upb_Arena* arena) {
const size_t size = strlen(text);
// Reminder: text[0] is always a quote character. (If text is
// empty, it's invalid, so we'll just return).
upb_String output;
upb_String_Init(&output, arena);
// Reminder: text[0] is always a quote character.
// (If text is empty, it's invalid, so we'll just return).
if (size == 0) {
fprintf(stderr,
"Tokenizer::ParseStringAppend() passed text that could not"
" have been tokenized as a string: %s",
text);
UPB_ASSERT(0);
return;
}
// Reserve room for new string.
const size_t new_len = size + upb_String_Size(output);
upb_String_Reserve(output, new_len);
const size_t new_len = size + upb_String_Size(&output);
upb_String_Reserve(&output, new_len);
// Loop through the string copying characters to "output" and
// interpreting escape sequences. Note that any invalid escape
@ -909,7 +912,7 @@ void upb_Parse_StringAppend(const char* text, upb_String* output) {
++ptr;
code = code * 8 + DigitValue(*ptr);
}
upb_String_PushBack(output, (char)code);
upb_String_PushBack(&output, (char)code);
} else if (*ptr == 'x') {
// A hex escape. May zero, one, or two digits. (The zero case
@ -923,29 +926,32 @@ void upb_Parse_StringAppend(const char* text, upb_String* output) {
++ptr;
code = code * 16 + DigitValue(*ptr);
}
upb_String_PushBack(output, (char)code);
upb_String_PushBack(&output, (char)code);
} else if (*ptr == 'u' || *ptr == 'U') {
uint32_t unicode;
const char* end = FetchUnicodePoint(ptr, &unicode);
if (end == ptr) {
// Failure: Just dump out what we saw, don't try to parse it.
upb_String_PushBack(output, *ptr);
upb_String_PushBack(&output, *ptr);
} else {
AppendUTF8(unicode, output);
AppendUTF8(unicode, &output);
ptr = end - 1; // Because we're about to ++ptr.
}
} else {
// Some other escape code.
upb_String_PushBack(output, TranslateEscape(*ptr));
upb_String_PushBack(&output, TranslateEscape(*ptr));
}
} else if (*ptr == text[0] && ptr[1] == '\0') {
// Ignore final quote matching the starting quote.
} else {
upb_String_PushBack(output, *ptr);
upb_String_PushBack(&output, *ptr);
}
}
return upb_StringView_FromDataAndSize(upb_String_Data(&output),
upb_String_Size(&output));
}
static bool AllInClass(bool (*f)(char), const char* text, int size) {
@ -955,11 +961,11 @@ static bool AllInClass(bool (*f)(char), const char* text, int size) {
return true;
}
bool upb_Tokenizer_IsIdentifier(const char* text, int size) {
bool upb_Tokenizer_IsIdentifier(const char* data, int size) {
// Mirrors IDENTIFIER definition in Tokenizer::Next() above.
if (size == 0) return false;
if (!upb_Tokenizer_IsLetter(text[0])) return false;
if (!AllInClass(upb_Tokenizer_IsAlphanumeric, text + 1, size - 1))
if (!upb_Tokenizer_IsLetter(data[0])) return false;
if (!AllInClass(upb_Tokenizer_IsAlphanumeric, data + 1, size - 1))
return false;
return true;
}

@ -30,8 +30,8 @@
#ifndef UPB_IO_TOKENIZER_H_
#define UPB_IO_TOKENIZER_H_
#include "upb/io/string.h"
#include "upb/io/zero_copy_input_stream.h"
#include "upb/string_view.h"
#include "upb/upb.h"
// Must be included last.
@ -123,6 +123,9 @@ int upb_Tokenizer_Line(const upb_Tokenizer* t);
int upb_Tokenizer_TextSize(const upb_Tokenizer* t);
const char* upb_Tokenizer_TextData(const upb_Tokenizer* t);
// External helper: validate an identifier.
bool upb_Tokenizer_IsIdentifier(const char* data, int size);
// Parses a TYPE_INTEGER token. Returns false if the result would be
// greater than max_value. Otherwise, returns true and sets *output to the
// result. If the text is not from a Token of type TYPE_INTEGER originally
@ -135,19 +138,10 @@ bool upb_Parse_Integer(const char* text, uint64_t max_value, uint64_t* output);
// result is undefined (possibly an assert failure).
double upb_Parse_Float(const char* text);
// Identical to ParseString (below), but appends to output.
void upb_Parse_StringAppend(const char* text, upb_String* output);
// Parses a TYPE_STRING token. This never fails, so long as the text actually
// comes from a TYPE_STRING token parsed by Tokenizer. If it doesn't, the
// result is undefined (possibly an assert failure).
UPB_INLINE void upb_Parse_String(const char* text, upb_String* output) {
upb_String_Clear(output);
upb_Parse_StringAppend(text, output);
}
// External helper: validate an identifier.
bool upb_Tokenizer_IsIdentifier(const char* text, int size);
upb_StringView upb_Parse_String(const char* text, upb_Arena* arena);
#ifdef __cplusplus
} /* extern "C" */

@ -32,6 +32,7 @@
#include "absl/strings/str_format.h"
#include "upb/internal/unicode.h"
#include "upb/io/chunked_input_stream.h"
#include "upb/io/string.h"
#include "upb/upb.hpp"
// Must be last.
@ -998,35 +999,30 @@ TEST_F(TokenizerTest, ParseString) {
};
upb::Arena arena;
upb_String result;
upb_String_Init(&result, arena.ptr());
for (int i = 0; i < sizeof(inputs) / sizeof(inputs[0]); i++) {
upb_Parse_String(inputs[i].data(), &result);
EXPECT_TRUE(StringEquals(upb_String_Data(&result), outputs[i].data()));
auto sv = upb_Parse_String(inputs[i].data(), arena.ptr());
EXPECT_TRUE(StringEquals(sv.data, outputs[i].data()));
}
// Test invalid strings that will never be tokenized as strings.
#ifdef GTEST_HAS_DEATH_TEST // death tests do not work on Windows yet
EXPECT_DEBUG_DEATH(
upb_Parse_String("", &result),
upb_Parse_String("", arena.ptr()),
"passed text that could not have been tokenized as a string");
#endif // GTEST_HAS_DEATH_TEST
}
TEST_F(TokenizerTest, ParseStringAppend) {
// Check that ParseString and ParseStringAppend differ.
upb::Arena arena;
upb_String output;
upb_String_Init(&output, arena.ptr());
upb_String_Assign(&output, "stuff+", 6);
upb_Parse_StringAppend("'hello'", &output);
auto sv = upb_Parse_String("'hello'", arena.ptr());
EXPECT_TRUE(StringEquals(sv.data, "hello"));
upb_String_Append(&output, sv.data, sv.size);
EXPECT_TRUE(StringEquals(upb_String_Data(&output), "stuff+hello"));
upb_Parse_String("'hello'", &output);
EXPECT_TRUE(StringEquals(upb_String_Data(&output), "hello"));
}
// -------------------------------------------------------------------
@ -1172,14 +1168,11 @@ static const char* kParseBenchmark[] = {
TEST(Benchmark, ParseStringAppendAccumulate) {
upb::Arena arena;
upb_String output;
upb_String_Init(&output, arena.ptr());
size_t outsize = 0;
int benchmark_len = arraysize(kParseBenchmark);
for (int i = 0; i < benchmark_len; i++) {
upb_Parse_StringAppend(kParseBenchmark[i], &output);
outsize += upb_String_Size(&output);
upb_String_Clear(&output);
auto sv = upb_Parse_String(kParseBenchmark[i], arena.ptr());
outsize += sv.size;
}
EXPECT_NE(0, outsize);
}
@ -1190,7 +1183,8 @@ TEST(Benchmark, ParseStringAppend) {
upb_String_Init(&output, arena.ptr());
int benchmark_len = arraysize(kParseBenchmark);
for (int i = 0; i < benchmark_len; i++) {
upb_Parse_StringAppend(kParseBenchmark[i], &output);
auto sv = upb_Parse_String(kParseBenchmark[i], arena.ptr());
upb_String_Append(&output, sv.data, sv.size);
}
EXPECT_NE(0, upb_String_Size(&output));
}
@ -1217,12 +1211,10 @@ static std::string DisplayHex(const std::string& data) {
static void ExpectFormat(const std::string& expectation,
const std::string& formatted) {
upb::Arena arena;
upb_String output;
upb_String_Init(&output, arena.ptr());
upb_Parse_String(formatted.data(), &output);
EXPECT_EQ(strcmp(upb_String_Data(&output), expectation.data()), 0)
auto sv = upb_Parse_String(formatted.data(), arena.ptr());
EXPECT_EQ(strcmp(sv.data, expectation.data()), 0)
<< ": Incorrectly parsed " << formatted << ":\nGot "
<< DisplayHex(output.data_) << "\nExpected " << DisplayHex(expectation);
<< DisplayHex(sv.data) << "\nExpected " << DisplayHex(expectation);
}
TEST(TokenizerHandlesUnicode, BMPCodes) {

@ -27,6 +27,8 @@
#include "upb/msg.h"
#include <math.h>
#include "upb/msg_internal.h"
// Must be last.
@ -309,3 +311,6 @@ bool _upb_mapsorter_pushmap(_upb_mapsorter* s, upb_FieldType key_type,
qsort(&s->entries[sorted->start], map_size, sizeof(*s->entries), compar);
return true;
}
const float kUpb_FltInfinity = INFINITY;
const double kUpb_Infinity = INFINITY;

@ -62,6 +62,9 @@ UPB_INLINE uint64_t _upb_UInt64_FromULL(unsigned long long v) {
return (uint64_t)v;
}
extern const float kUpb_FltInfinity;
extern const double kUpb_Infinity;
/** upb_MiniTable *************************************************************/
/* upb_MiniTable represents the memory layout of a given upb_MessageDef. The

@ -193,3 +193,8 @@ message TestMapFieldExtra {
}
map<int32, EnumMap> map_field = 1;
}
message TestNameConflict {
map<string, string> map_field = 1;
optional bool clear_map_field = 2;
}

@ -114,6 +114,24 @@ cc_library(
visibility = ["//third_party/upb/protos_generator:__pkg__"],
)
cc_library(
name = "names",
srcs = [
"names.cc",
],
hdrs = [
"names.h",
],
copts = UPB_DEFAULT_CPPOPTS,
visibility = ["//third_party/upb/protos_generator:__pkg__"],
deps = [
"@com_google_absl//absl/container:flat_hash_map",
"@com_google_absl//absl/strings",
"@com_google_protobuf//:protobuf",
"@com_google_protobuf//src/google/protobuf/compiler:code_generator",
],
)
cc_binary(
name = "protoc-gen-upb",
srcs = ["protoc-gen-upb.cc"],
@ -122,6 +140,7 @@ cc_binary(
deps = [
":common",
":file_layout",
":names",
"//:mini_table",
"//:port",
"//:upb",

@ -43,7 +43,7 @@ std::string StripExtension(absl::string_view fname) {
}
std::string ToCIdent(absl::string_view str) {
return absl::StrReplaceAll(str, {{".", "_"}, {"/", "_"}});
return absl::StrReplaceAll(str, {{".", "_"}, {"/", "_"}, {"-", "_"}});
}
std::string ToPreproc(absl::string_view str) {

@ -0,0 +1,81 @@
/*
* Copyright (c) 2007-2021, Google LLC
* 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.
* * Neither the name of Google LLC nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* 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 Google LLC 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.
*/
#include "upbc/names.h"
#include <string>
#include "google/protobuf/descriptor.h"
#include "absl/strings/match.h"
namespace upbc {
namespace protobuf = ::google::protobuf;
// List of generated accessor prefixes to check against.
// Example:
// optional repeated string phase = 236;
// optional bool clear_phase = 237;
static constexpr absl::string_view kAccessorPrefixes[] = {
"clear_",
"delete_",
"add_",
"resize_",
};
std::string ResolveFieldName(const protobuf::FieldDescriptor* field,
const NameToFieldDescriptorMap& field_names) {
absl::string_view field_name = field->name();
for (const auto prefix : kAccessorPrefixes) {
// If field name starts with a prefix such as clear_ and the proto
// contains a field name with trailing end, depending on type of field
// (repeated, map, message) we have a conflict to resolve.
if (absl::StartsWith(field_name, prefix)) {
auto match = field_names.find(field_name.substr(prefix.size()));
if (match != field_names.end()) {
const auto* candidate = match->second;
if (candidate->is_repeated() || candidate->is_map()) {
return absl::StrCat(field_name, "_");
}
}
}
}
return std::string(field_name);
}
// Returns field map by name to use for conflict checks.
NameToFieldDescriptorMap CreateFieldNameMap(
const protobuf::Descriptor* message) {
NameToFieldDescriptorMap field_names;
for (int i = 0; i < message->field_count(); i++) {
const protobuf::FieldDescriptor* field = message->field(i);
field_names.emplace(field->name(), field);
}
return field_names;
}
} // namespace upbc

@ -0,0 +1,51 @@
/*
* Copyright (c) 2009-2021, Google LLC
* 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.
* * Neither the name of Google LLC nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* 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 Google LLC 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.
*/
#ifndef UPB_PROTOS_GENERATOR_NAMES_H
#define UPB_PROTOS_GENERATOR_NAMES_H
#include <string>
#include "google/protobuf/descriptor.h"
#include "absl/container/flat_hash_map.h"
namespace upbc {
using NameToFieldDescriptorMap =
absl::flat_hash_map<absl::string_view, const google::protobuf::FieldDescriptor*>;
// Returns field name by resolving naming conflicts across
// proto field names (such as clear_ prefixes).
std::string ResolveFieldName(const google::protobuf::FieldDescriptor* field,
const NameToFieldDescriptorMap& field_names);
// Returns field map by name to use for conflict checks.
NameToFieldDescriptorMap CreateFieldNameMap(const google::protobuf::Descriptor* message);
} // namespace upbc
#endif // UPB_PROTOS_GENERATOR_NAMES_H

@ -38,6 +38,7 @@
#include "upb/upb.hpp"
#include "upbc/common.h"
#include "upbc/file_layout.h"
#include "upbc/names.h"
// Must be last.
#include "upb/port_def.inc"
@ -54,15 +55,17 @@ namespace protobuf = ::google::protobuf;
inline std::vector<const google::protobuf::FieldDescriptor*> FieldHotnessOrder(
const google::protobuf::Descriptor* message) {
std::vector<const google::protobuf::FieldDescriptor*> fields;
for (int i = 0; i < message->field_count(); i++) {
size_t field_count = message->field_count();
fields.reserve(field_count);
for (size_t i = 0; i < field_count; i++) {
fields.push_back(message->field(i));
}
std::sort(fields.begin(), fields.end(),
[](const google::protobuf::FieldDescriptor* a,
const google::protobuf::FieldDescriptor* b) {
return std::make_pair(!a->is_required(), a->number()) <
std::make_pair(!b->is_required(), b->number());
});
std::sort(
fields.begin(), fields.end(),
[](const google::protobuf::FieldDescriptor* a, const google::protobuf::FieldDescriptor* b) {
return std::make_pair(!a->is_required(), a->number()) <
std::make_pair(!b->is_required(), b->number());
});
return fields;
}
@ -190,6 +193,26 @@ bool HasNonZeroDefault(const protobuf::FieldDescriptor* field) {
return false;
}
std::string FloatToCLiteral(float value) {
if (value == std::numeric_limits<float>::infinity()) {
return "kUpb_FltInfinity";
} else if (value == -std::numeric_limits<float>::infinity()) {
return "-kUpb_FltInfinity";
} else {
return absl::StrCat(value);
}
}
std::string DoubleToCLiteral(double value) {
if (value == std::numeric_limits<double>::infinity()) {
return "kUpb_Infinity";
} else if (value == -std::numeric_limits<double>::infinity()) {
return "-kUpb_Infinity";
} else {
return absl::StrCat(value);
}
}
std::string FieldDefault(const protobuf::FieldDescriptor* field) {
switch (field->cpp_type()) {
case protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
@ -210,9 +233,9 @@ std::string FieldDefault(const protobuf::FieldDescriptor* field) {
return absl::Substitute("_upb_UInt64_FromULL($0ull)",
field->default_value_uint64());
case protobuf::FieldDescriptor::CPPTYPE_FLOAT:
return absl::StrCat(field->default_value_float());
return FloatToCLiteral(field->default_value_float());
case protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
return absl::StrCat(field->default_value_double());
return DoubleToCLiteral(field->default_value_double());
case protobuf::FieldDescriptor::CPPTYPE_BOOL:
return field->default_value_bool() ? "true" : "false";
case protobuf::FieldDescriptor::CPPTYPE_ENUM:
@ -380,7 +403,9 @@ void GenerateOneofInHeader(const protobuf::OneofDescriptor* oneof,
void GenerateHazzer(const protobuf::FieldDescriptor* field,
const FileLayout& layout, absl::string_view msg_name,
const NameToFieldDescriptorMap& field_names,
Output& output) {
std::string resolved_name = ResolveFieldName(field, field_names);
if (layout.HasHasbit(field)) {
output(
R"cc(
@ -388,7 +413,7 @@ void GenerateHazzer(const protobuf::FieldDescriptor* field,
return _upb_hasbit(msg, $2);
}
)cc",
msg_name, field->name(), layout.GetHasbitIndex(field));
msg_name, resolved_name, layout.GetHasbitIndex(field));
} else if (field->real_containing_oneof()) {
output(
R"cc(
@ -396,7 +421,7 @@ void GenerateHazzer(const protobuf::FieldDescriptor* field,
return _upb_getoneofcase(msg, $2) == $3;
}
)cc",
msg_name, field->name(),
msg_name, resolved_name,
layout.GetOneofCaseOffset(field->real_containing_oneof()),
field->number());
} else if (field->message_type()) {
@ -406,19 +431,20 @@ void GenerateHazzer(const protobuf::FieldDescriptor* field,
return _upb_has_submsg_nohasbit(msg, $2);
}
)cc",
msg_name, field->name(), layout.GetFieldOffset(field));
msg_name, resolved_name, layout.GetFieldOffset(field));
}
}
void GenerateClear(const protobuf::FieldDescriptor* field,
const FileLayout& layout, absl::string_view msg_name,
const NameToFieldDescriptorMap& field_names,
Output& output) {
if (field == field->containing_type()->map_key() ||
field == field->containing_type()->map_value()) {
// Cannot be cleared.
return;
}
std::string resolved_name = ResolveFieldName(field, field_names);
if (field->real_containing_oneof()) {
const protobuf::OneofDescriptor* oneof = field->real_containing_oneof();
std::string oneof_fullname = ToCIdent(oneof->full_name());
@ -432,7 +458,7 @@ void GenerateClear(const protobuf::FieldDescriptor* field,
UPB_WRITE_ONEOF(msg, $2, $3, $7, $4, $6_NOT_SET);
}
)cc",
msg_name, field->name(), CType(field), layout.GetFieldOffset(field),
msg_name, resolved_name, CType(field), layout.GetFieldOffset(field),
layout.GetOneofCaseOffset(field->real_containing_oneof()),
field->number(), oneof_fullname, default_value);
} else {
@ -445,7 +471,7 @@ void GenerateClear(const protobuf::FieldDescriptor* field,
_upb_clearhas(msg, $3);
}
)cc",
msg_name, field->name(), layout.GetFieldOffset(field),
msg_name, resolved_name, layout.GetFieldOffset(field),
layout.GetHasbitIndex(field));
} else {
output(
@ -454,7 +480,7 @@ void GenerateClear(const protobuf::FieldDescriptor* field,
*UPB_PTR_AT(msg, $2, const upb_Message*) = NULL;
}
)cc",
msg_name, field->name(), layout.GetFieldOffset(field));
msg_name, resolved_name, layout.GetFieldOffset(field));
}
} else if (layout.HasHasbit(field)) {
if (field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING) {
@ -465,7 +491,7 @@ void GenerateClear(const protobuf::FieldDescriptor* field,
_upb_clearhas(msg, $4);
}
)cc",
msg_name, field->name(), CType(field), layout.GetFieldOffset(field),
msg_name, resolved_name, CType(field), layout.GetFieldOffset(field),
layout.GetHasbitIndex(field));
} else {
output(
@ -475,7 +501,7 @@ void GenerateClear(const protobuf::FieldDescriptor* field,
_upb_clearhas(msg, $4);
}
)cc",
msg_name, field->name(), CType(field), layout.GetFieldOffset(field),
msg_name, resolved_name, CType(field), layout.GetFieldOffset(field),
layout.GetHasbitIndex(field));
}
} else {
@ -486,7 +512,7 @@ void GenerateClear(const protobuf::FieldDescriptor* field,
*UPB_PTR_AT(msg, $3, $2) = upb_StringView_FromDataAndSize(NULL, 0);
}
)cc",
msg_name, field->name(), CType(field),
msg_name, resolved_name, CType(field),
layout.GetFieldOffset(field));
} else {
output(
@ -495,7 +521,7 @@ void GenerateClear(const protobuf::FieldDescriptor* field,
*UPB_PTR_AT(msg, $3, $2) = 0;
}
)cc",
msg_name, field->name(), CType(field), layout.GetFieldOffset(field),
msg_name, resolved_name, CType(field), layout.GetFieldOffset(field),
layout.GetHasbitIndex(field));
}
}
@ -504,7 +530,9 @@ void GenerateClear(const protobuf::FieldDescriptor* field,
void GenerateRepeatedClear(const protobuf::FieldDescriptor* field,
const FileLayout& layout, absl::string_view msg_name,
const NameToFieldDescriptorMap& field_names,
Output& output) {
std::string resolved_name = ResolveFieldName(field, field_names);
if (layout.HasHasbit(field)) {
output(
R"cc(
@ -513,7 +541,7 @@ void GenerateRepeatedClear(const protobuf::FieldDescriptor* field,
_upb_clearhas(msg, $4);
}
)cc",
msg_name, field->name(), layout.GetFieldOffset(field),
msg_name, resolved_name, layout.GetFieldOffset(field),
layout.GetHasbitIndex(field));
} else {
output(
@ -522,30 +550,32 @@ void GenerateRepeatedClear(const protobuf::FieldDescriptor* field,
_upb_array_detach(msg, $2);
}
)cc",
msg_name, field->name(), layout.GetFieldOffset(field));
msg_name, resolved_name, layout.GetFieldOffset(field));
}
}
void GenerateMapGetters(const protobuf::FieldDescriptor* field,
const FileLayout& layout, absl::string_view msg_name,
const NameToFieldDescriptorMap& field_names,
Output& output) {
const protobuf::Descriptor* entry = field->message_type();
const protobuf::FieldDescriptor* key = entry->FindFieldByNumber(1);
const protobuf::FieldDescriptor* val = entry->FindFieldByNumber(2);
std::string resolved_name = ResolveFieldName(field, field_names);
output(
R"cc(
UPB_INLINE size_t $0_$1_size(const $0* msg) {
return _upb_msg_map_size(msg, $2);
}
)cc",
msg_name, field->name(), layout.GetFieldOffset(field));
msg_name, resolved_name, layout.GetFieldOffset(field));
output(
R"cc(
UPB_INLINE bool $0_$1_get(const $0* msg, $2 key, $3* val) {
return _upb_msg_map_get(msg, $4, &key, $5, val, $6);
}
)cc",
msg_name, field->name(), CType(key), CType(val),
msg_name, resolved_name, CType(key), CType(val),
layout.GetFieldOffset(field),
key->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING
? "0"
@ -559,7 +589,7 @@ void GenerateMapGetters(const protobuf::FieldDescriptor* field,
return ($0)_upb_msg_map_next(msg, $3, iter);
}
)cc",
CTypeConst(field), msg_name, field->name(), layout.GetFieldOffset(field));
CTypeConst(field), msg_name, resolved_name, layout.GetFieldOffset(field));
}
void GenerateMapEntryGetters(const protobuf::FieldDescriptor* field,
@ -580,18 +610,22 @@ void GenerateMapEntryGetters(const protobuf::FieldDescriptor* field,
void GenerateRepeatedGetters(const protobuf::FieldDescriptor* field,
const FileLayout& layout,
absl::string_view msg_name, Output& output) {
absl::string_view msg_name,
const NameToFieldDescriptorMap& field_names,
Output& output) {
output(
R"cc(
UPB_INLINE $0 const* $1_$2(const $1* msg, size_t* len) {
return ($0 const*)_upb_array_accessor(msg, $3, len);
}
)cc",
CTypeConst(field), msg_name, field->name(), layout.GetFieldOffset(field));
CTypeConst(field), msg_name, ResolveFieldName(field, field_names),
layout.GetFieldOffset(field));
}
void GenerateOneofGetters(const protobuf::FieldDescriptor* field,
const FileLayout& layout, absl::string_view msg_name,
const NameToFieldDescriptorMap& field_names,
Output& output) {
output(
R"cc(
@ -599,14 +633,17 @@ void GenerateOneofGetters(const protobuf::FieldDescriptor* field,
return UPB_READ_ONEOF(msg, $0, $3, $4, $5, $6);
}
)cc",
CTypeConst(field), msg_name, field->name(), layout.GetFieldOffset(field),
CTypeConst(field), msg_name, ResolveFieldName(field, field_names),
layout.GetFieldOffset(field),
layout.GetOneofCaseOffset(field->real_containing_oneof()),
field->number(), FieldDefault(field));
}
void GenerateScalarGetters(const protobuf::FieldDescriptor* field,
const FileLayout& layout, absl::string_view msg_name,
const NameToFieldDescriptorMap& field_names,
Output& output) {
std::string resolved_name = ResolveFieldName(field, field_names);
if (HasNonZeroDefault(field)) {
output(
R"cc(
@ -614,7 +651,7 @@ void GenerateScalarGetters(const protobuf::FieldDescriptor* field,
return $1_has_$2(msg) ? *UPB_PTR_AT(msg, $3, $0) : $4;
}
)cc",
CTypeConst(field), msg_name, field->name(),
CTypeConst(field), msg_name, resolved_name,
layout.GetFieldOffset(field), FieldDefault(field));
} else {
output(
@ -623,45 +660,48 @@ void GenerateScalarGetters(const protobuf::FieldDescriptor* field,
return *UPB_PTR_AT(msg, $3, $0);
}
)cc",
CTypeConst(field), msg_name, field->name(),
CTypeConst(field), msg_name, resolved_name,
layout.GetFieldOffset(field));
}
}
void GenerateGetters(const protobuf::FieldDescriptor* field,
const FileLayout& layout, absl::string_view msg_name,
const NameToFieldDescriptorMap& field_names,
Output& output) {
if (field->is_map()) {
GenerateMapGetters(field, layout, msg_name, output);
GenerateMapGetters(field, layout, msg_name, field_names, output);
} else if (field->containing_type()->options().map_entry()) {
GenerateMapEntryGetters(field, msg_name, output);
} else if (field->is_repeated()) {
GenerateRepeatedGetters(field, layout, msg_name, output);
GenerateRepeatedGetters(field, layout, msg_name, field_names, output);
} else if (field->real_containing_oneof()) {
GenerateOneofGetters(field, layout, msg_name, output);
GenerateOneofGetters(field, layout, msg_name, field_names, output);
} else {
GenerateScalarGetters(field, layout, msg_name, output);
GenerateScalarGetters(field, layout, msg_name, field_names, output);
}
}
void GenerateMapSetters(const protobuf::FieldDescriptor* field,
const FileLayout& layout, absl::string_view msg_name,
const NameToFieldDescriptorMap& field_names,
Output& output) {
const protobuf::Descriptor* entry = field->message_type();
const protobuf::FieldDescriptor* key = entry->FindFieldByNumber(1);
const protobuf::FieldDescriptor* val = entry->FindFieldByNumber(2);
std::string resolved_name = ResolveFieldName(field, field_names);
output(
R"cc(
UPB_INLINE void $0_$1_clear($0* msg) { _upb_msg_map_clear(msg, $2); }
)cc",
msg_name, field->name(), layout.GetFieldOffset(field));
msg_name, resolved_name, layout.GetFieldOffset(field));
output(
R"cc(
UPB_INLINE bool $0_$1_set($0* msg, $2 key, $3 val, upb_Arena* a) {
return _upb_msg_map_set(msg, $4, &key, $5, &val, $6, a);
}
)cc",
msg_name, field->name(), CType(key), CType(val),
msg_name, resolved_name, CType(key), CType(val),
layout.GetFieldOffset(field),
key->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING
? "0"
@ -675,7 +715,7 @@ void GenerateMapSetters(const protobuf::FieldDescriptor* field,
return _upb_msg_map_delete(msg, $3, &key, $4);
}
)cc",
msg_name, field->name(), CType(key), layout.GetFieldOffset(field),
msg_name, resolved_name, CType(key), layout.GetFieldOffset(field),
key->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING
? "0"
: "sizeof(key)");
@ -685,26 +725,29 @@ void GenerateMapSetters(const protobuf::FieldDescriptor* field,
return ($0)_upb_msg_map_next(msg, $3, iter);
}
)cc",
CType(field), msg_name, field->name(), layout.GetFieldOffset(field));
CType(field), msg_name, resolved_name, layout.GetFieldOffset(field));
}
void GenerateRepeatedSetters(const protobuf::FieldDescriptor* field,
const FileLayout& layout,
absl::string_view msg_name, Output& output) {
absl::string_view msg_name,
const NameToFieldDescriptorMap& field_names,
Output& output) {
std::string resolved_name = ResolveFieldName(field, field_names);
output(
R"cc(
UPB_INLINE $0* $1_mutable_$2($1* msg, size_t* len) {
return ($0*)_upb_array_mutable_accessor(msg, $3, len);
}
)cc",
CType(field), msg_name, field->name(), layout.GetFieldOffset(field));
CType(field), msg_name, resolved_name, layout.GetFieldOffset(field));
output(
R"cc(
UPB_INLINE $0* $1_resize_$2($1* msg, size_t len, upb_Arena* arena) {
return ($0*)_upb_Array_Resize_accessor2(msg, $3, len, $4, arena);
}
)cc",
CType(field), msg_name, field->name(), layout.GetFieldOffset(field),
CType(field), msg_name, resolved_name, layout.GetFieldOffset(field),
SizeLg2(field));
if (field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_MESSAGE) {
output(
@ -716,7 +759,7 @@ void GenerateRepeatedSetters(const protobuf::FieldDescriptor* field,
return sub;
}
)cc",
MessageName(field->message_type()), msg_name, field->name(),
MessageName(field->message_type()), msg_name, resolved_name,
MessageInit(field->message_type()), layout.GetFieldOffset(field),
SizeLg2(field));
} else {
@ -726,23 +769,25 @@ void GenerateRepeatedSetters(const protobuf::FieldDescriptor* field,
return _upb_Array_Append_accessor2(msg, $3, $4, &val, arena);
}
)cc",
CType(field), msg_name, field->name(), layout.GetFieldOffset(field),
CType(field), msg_name, resolved_name, layout.GetFieldOffset(field),
SizeLg2(field));
}
}
void GenerateNonRepeatedSetters(const protobuf::FieldDescriptor* field,
const FileLayout& layout,
absl::string_view msg_name, Output& output) {
absl::string_view msg_name,
const NameToFieldDescriptorMap& field_names,
Output& output) {
if (field == field->containing_type()->map_key()) {
// Key cannot be mutated.
return;
}
std::string resolved_name = ResolveFieldName(field, field_names);
// The common function signature for all setters. Varying
// implementations follow.
output("UPB_INLINE void $0_set_$1($0 *msg, $2 value) {\n", msg_name,
field->name(), CType(field));
resolved_name, CType(field));
if (field == field->containing_type()->map_value()) {
output(
@ -784,20 +829,21 @@ void GenerateNonRepeatedSetters(const protobuf::FieldDescriptor* field,
return sub;
}
)cc",
MessageName(field->message_type()), msg_name, field->name(),
MessageName(field->message_type()), msg_name, resolved_name,
MessageInit(field->message_type()));
}
}
void GenerateSetters(const protobuf::FieldDescriptor* field,
const FileLayout& layout, absl::string_view msg_name,
const NameToFieldDescriptorMap& field_names,
Output& output) {
if (field->is_map()) {
GenerateMapSetters(field, layout, msg_name, output);
GenerateMapSetters(field, layout, msg_name, field_names, output);
} else if (field->is_repeated()) {
GenerateRepeatedSetters(field, layout, msg_name, output);
GenerateRepeatedSetters(field, layout, msg_name, field_names, output);
} else {
GenerateNonRepeatedSetters(field, layout, msg_name, output);
GenerateNonRepeatedSetters(field, layout, msg_name, field_names, output);
}
}
@ -805,7 +851,6 @@ void GenerateMessageInHeader(const protobuf::Descriptor* message,
const FileLayout& layout, Output& output) {
output("/* $0 */\n\n", message->full_name());
std::string msg_name = ToCIdent(message->full_name());
if (!message->options().map_entry()) {
GenerateMessageFunctionsInHeader(message, output);
}
@ -814,20 +859,21 @@ void GenerateMessageInHeader(const protobuf::Descriptor* message,
GenerateOneofInHeader(message->oneof_decl(i), layout, msg_name, output);
}
auto field_names = CreateFieldNameMap(message);
for (auto field : FieldNumberOrder(message)) {
GenerateHazzer(field, layout, msg_name, output);
GenerateHazzer(field, layout, msg_name, field_names, output);
if (field->is_repeated()) {
GenerateRepeatedClear(field, layout, msg_name, output);
GenerateRepeatedClear(field, layout, msg_name, field_names, output);
} else {
GenerateClear(field, layout, msg_name, output);
GenerateClear(field, layout, msg_name, field_names, output);
}
GenerateGetters(field, layout, msg_name, output);
GenerateGetters(field, layout, msg_name, field_names, output);
}
output("\n");
for (auto field : FieldNumberOrder(message)) {
GenerateSetters(field, layout, msg_name, output);
GenerateSetters(field, layout, msg_name, field_names, output);
}
output("\n");
@ -934,7 +980,6 @@ void WriteHeader(const FileLayout& layout, Output& output) {
}
output("\n");
for (auto message : this_file_messages) {
GenerateMessageInHeader(message, layout, output);
}

Loading…
Cancel
Save