ruby_memprofiler_pprof 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/ext/ruby_memprofiler_pprof/backtrace.c +429 -0
- data/ext/ruby_memprofiler_pprof/collector.c +1055 -0
- data/ext/ruby_memprofiler_pprof/compat.c +182 -0
- data/ext/ruby_memprofiler_pprof/extconf.rb +72 -0
- data/ext/ruby_memprofiler_pprof/pprof.upb.c +170 -0
- data/ext/ruby_memprofiler_pprof/pprof.upb.h +848 -0
- data/ext/ruby_memprofiler_pprof/pprof_out.c +285 -0
- data/ext/ruby_memprofiler_pprof/ruby_memprofiler_pprof.c +11 -0
- data/ext/ruby_memprofiler_pprof/ruby_memprofiler_pprof.h +301 -0
- data/ext/ruby_memprofiler_pprof/strtab.c +391 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/BUILD +719 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/CONTRIBUTING.md +37 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/DESIGN.md +201 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/LICENSE +26 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/README.md +78 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/WORKSPACE +58 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/bazel/BUILD +53 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/bazel/amalgamate.py +129 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/bazel/build_defs.bzl +160 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/bazel/lua.BUILD +127 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/bazel/protobuf.patch +54 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/bazel/py_proto_library.bzl +137 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/bazel/python_downloads.bzl +84 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/bazel/system_python.bzl +101 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/bazel/upb_proto_library.bzl +388 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/bazel/workspace_deps.bzl +89 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/benchmarks/BUILD +252 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/benchmarks/BUILD.googleapis +54 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/benchmarks/benchmark.cc +333 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/benchmarks/build_defs.bzl +88 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/benchmarks/compare.py +118 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/benchmarks/descriptor.proto +888 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/benchmarks/descriptor_sv.proto +890 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/benchmarks/empty.proto +6 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/benchmarks/gen_protobuf_binary_cc.py +64 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/benchmarks/gen_synthetic_protos.py +118 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/benchmarks/gen_upb_binary_c.py +65 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/cmake/BUILD.bazel +102 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/cmake/README.md +23 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/cmake/build_defs.bzl +73 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/cmake/make_cmakelists.py +340 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/cmake/staleness_test.py +57 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/cmake/staleness_test_lib.py +186 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/docs/render.py +43 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/docs/style-guide.md +65 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/docs/vs-cpp-protos.md +255 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/docs/wrapping-upb.md +444 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/python/BUILD +216 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/python/convert.c +394 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/python/convert.h +63 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/python/descriptor.c +1694 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/python/descriptor.h +80 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/python/descriptor_containers.c +704 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/python/descriptor_containers.h +114 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/python/descriptor_pool.c +650 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/python/descriptor_pool.h +48 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/python/dist/BUILD.bazel +193 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/python/dist/dist.bzl +190 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/python/extension_dict.c +247 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/python/extension_dict.h +39 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/python/map.c +522 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/python/map.h +66 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/python/message.c +1909 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/python/message.h +101 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/python/minimal_test.py +183 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/BUILD +70 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/README.md +11 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/descriptor_database_test_wrapper.py +30 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/descriptor_pool_test_wrapper.py +45 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/descriptor_test_wrapper.py +46 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/generator_test_wrapper.py +30 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/json_format_test_wrapper.py +30 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/keywords_test_wrapper.py +30 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/message_factory_test_wrapper.py +37 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/message_test_wrapper.py +52 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/proto_builder_test_wrapper.py +32 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/pyproto_test_wrapper.bzl +36 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/reflection_test_wrapper.py +45 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/service_reflection_test_wrapper.py +30 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/symbol_database_test_wrapper.py +30 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/text_encoding_test_wrapper.py +30 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/text_format_test_wrapper.py +30 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/unknown_fields_test_wrapper.py +30 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/well_known_types_test_wrapper.py +36 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/wire_format_test_wrapper.py +30 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/python/protobuf.c +350 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/python/protobuf.h +230 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/python/py_extension.bzl +55 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/python/python_api.h +61 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/python/repeated.c +828 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/python/repeated.h +69 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/python/unknown_fields.c +404 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/python/unknown_fields.h +39 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/python/version_script.lds +6 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/third_party/lunit/LICENSE +32 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/third_party/lunit/README.google +9 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/third_party/lunit/console.lua +156 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/third_party/lunit/lunit.lua +725 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/third_party/utf8_range/BUILD +19 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/third_party/utf8_range/LICENSE +21 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/third_party/utf8_range/naive.c +92 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/third_party/utf8_range/range2-neon.c +157 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/third_party/utf8_range/range2-sse.c +170 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/third_party/utf8_range/utf8_range.h +9 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/bindings/lua/BUILD.bazel +129 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/bindings/lua/README.md +8 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/bindings/lua/def.c +939 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/bindings/lua/lua_proto_library.bzl +138 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/bindings/lua/main.c +83 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/bindings/lua/msg.c +1118 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/bindings/lua/test.proto +69 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/bindings/lua/test_upb.lua +846 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/bindings/lua/upb.c +258 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/bindings/lua/upb.h +132 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/bindings/lua/upb.lua +58 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/bindings/lua/upbc.cc +134 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/collections.c +192 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/collections.h +174 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/conformance_upb.c +346 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/conformance_upb_failures.txt +1 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/decode.c +1221 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/decode.h +94 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/decode_fast.c +1055 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/decode_fast.h +153 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/decode_internal.h +211 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/def.c +3262 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/def.h +414 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/def.hpp +438 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/empty.proto +1 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/encode.c +604 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/encode.h +71 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/fuzz/BUILD +13 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/fuzz/file_descriptor_parsenew_fuzzer.cc +43 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/json_decode.c +1509 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/json_decode.h +47 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/json_encode.c +776 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/json_encode.h +62 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/mini_table.c +1147 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/mini_table.h +189 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/mini_table.hpp +112 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/mini_table_accessors.c +363 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/mini_table_accessors.h +263 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/mini_table_accessors_internal.h +59 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/mini_table_accessors_test.cc +425 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/mini_table_test.cc +230 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/msg.c +428 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/msg.h +114 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/msg_internal.h +836 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/msg_test.cc +491 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/msg_test.proto +195 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/port_def.inc +261 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/port_undef.inc +62 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/reflection.c +323 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/reflection.h +109 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/reflection.hpp +37 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/table.c +926 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/table_internal.h +385 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/test.proto +74 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/test_cpp.cc +186 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/test_cpp.proto +12 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/test_generated_code.cc +977 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/test_table.cc +580 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/text_encode.c +472 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/text_encode.h +64 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/upb.c +362 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/upb.h +378 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/upb.hpp +115 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/upb_internal.h +68 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/BUILD +121 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/README.md +7 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/compare.c +300 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/compare.h +66 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/compare_test.cc +236 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/def_to_proto.c +572 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/def_to_proto.h +62 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/def_to_proto_public_import_test.proto +32 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/def_to_proto_regular_import_test.proto +36 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/def_to_proto_test.cc +143 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/def_to_proto_test.proto +119 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/def_to_proto_weak_import_test.proto +28 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/def_to_proto_wweak_import_test.proto +28 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/required_fields.c +311 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/required_fields.h +94 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/required_fields_test.cc +202 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/required_fields_test.proto +48 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upbc/BUILD +78 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upbc/common.cc +77 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upbc/common.h +112 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upbc/protoc-gen-upb.cc +1997 -0
- data/ext/ruby_memprofiler_pprof/vendor/upb/upbc/protoc-gen-upbdefs.cc +193 -0
- data/lib/ruby_memprofiler_pprof/atfork.rb +77 -0
- data/lib/ruby_memprofiler_pprof/block_flusher.rb +61 -0
- data/lib/ruby_memprofiler_pprof/file_flusher.rb +45 -0
- data/lib/ruby_memprofiler_pprof/profile_app.rb +30 -0
- data/lib/ruby_memprofiler_pprof/profile_data.rb +18 -0
- data/lib/ruby_memprofiler_pprof/version.rb +5 -0
- data/lib/ruby_memprofiler_pprof.rb +8 -0
- data/libexec/ruby_memprofiler_pprof_profile +16 -0
- metadata +257 -0
|
@@ -0,0 +1,1997 @@
|
|
|
1
|
+
// Copyright (c) 2009-2021, Google LLC
|
|
2
|
+
// All rights reserved.
|
|
3
|
+
//
|
|
4
|
+
// Redistribution and use in source and binary forms, with or without
|
|
5
|
+
// modification, are permitted provided that the following conditions are met:
|
|
6
|
+
// * Redistributions of source code must retain the above copyright
|
|
7
|
+
// notice, this list of conditions and the following disclaimer.
|
|
8
|
+
// * Redistributions in binary form must reproduce the above copyright
|
|
9
|
+
// notice, this list of conditions and the following disclaimer in the
|
|
10
|
+
// documentation and/or other materials provided with the distribution.
|
|
11
|
+
// * Neither the name of Google LLC nor the
|
|
12
|
+
// names of its contributors may be used to endorse or promote products
|
|
13
|
+
// derived from this software without specific prior written permission.
|
|
14
|
+
//
|
|
15
|
+
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
16
|
+
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
17
|
+
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
18
|
+
// ARE DISCLAIMED. IN NO EVENT SHALL Google LLC BE LIABLE FOR ANY DIRECT,
|
|
19
|
+
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
20
|
+
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
21
|
+
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
22
|
+
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
23
|
+
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
24
|
+
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
25
|
+
|
|
26
|
+
#include <memory>
|
|
27
|
+
|
|
28
|
+
#include "absl/container/flat_hash_map.h"
|
|
29
|
+
#include "absl/container/flat_hash_set.h"
|
|
30
|
+
#include "absl/strings/ascii.h"
|
|
31
|
+
#include "absl/strings/substitute.h"
|
|
32
|
+
#include "google/protobuf/compiler/code_generator.h"
|
|
33
|
+
#include "google/protobuf/compiler/plugin.h"
|
|
34
|
+
#include "google/protobuf/descriptor.h"
|
|
35
|
+
#include "google/protobuf/descriptor.pb.h"
|
|
36
|
+
#include "google/protobuf/wire_format.h"
|
|
37
|
+
#include "upb/mini_table.hpp"
|
|
38
|
+
#include "upb/upb.hpp"
|
|
39
|
+
#include "upbc/common.h"
|
|
40
|
+
|
|
41
|
+
// Must be last.
|
|
42
|
+
#include "upb/port_def.inc"
|
|
43
|
+
|
|
44
|
+
namespace upbc {
|
|
45
|
+
namespace {
|
|
46
|
+
|
|
47
|
+
namespace protoc = ::google::protobuf::compiler;
|
|
48
|
+
namespace protobuf = ::google::protobuf;
|
|
49
|
+
|
|
50
|
+
// Returns fields in order of "hotness", eg. how frequently they appear in
|
|
51
|
+
// serialized payloads. Ideally this will use a profile. When we don't have
|
|
52
|
+
// that, we assume that fields with smaller numbers are used more frequently.
|
|
53
|
+
inline std::vector<const google::protobuf::FieldDescriptor*> FieldHotnessOrder(
|
|
54
|
+
const google::protobuf::Descriptor* message) {
|
|
55
|
+
std::vector<const google::protobuf::FieldDescriptor*> fields;
|
|
56
|
+
for (int i = 0; i < message->field_count(); i++) {
|
|
57
|
+
fields.push_back(message->field(i));
|
|
58
|
+
}
|
|
59
|
+
std::sort(fields.begin(), fields.end(),
|
|
60
|
+
[](const google::protobuf::FieldDescriptor* a,
|
|
61
|
+
const google::protobuf::FieldDescriptor* b) {
|
|
62
|
+
return std::make_pair(!a->is_required(), a->number()) <
|
|
63
|
+
std::make_pair(!b->is_required(), b->number());
|
|
64
|
+
});
|
|
65
|
+
return fields;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
std::string SourceFilename(const google::protobuf::FileDescriptor* file) {
|
|
69
|
+
return StripExtension(file->name()) + ".upb.c";
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
std::string MessageInit(const protobuf::Descriptor* descriptor) {
|
|
73
|
+
return MessageName(descriptor) + "_msginit";
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
std::string EnumInit(const protobuf::EnumDescriptor* descriptor) {
|
|
77
|
+
return ToCIdent(descriptor->full_name()) + "_enuminit";
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
std::string ExtensionIdentBase(const protobuf::FieldDescriptor* ext) {
|
|
81
|
+
assert(ext->is_extension());
|
|
82
|
+
std::string ext_scope;
|
|
83
|
+
if (ext->extension_scope()) {
|
|
84
|
+
return MessageName(ext->extension_scope());
|
|
85
|
+
} else {
|
|
86
|
+
return ToCIdent(ext->file()->package());
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
std::string ExtensionLayout(const google::protobuf::FieldDescriptor* ext) {
|
|
91
|
+
return absl::StrCat(ExtensionIdentBase(ext), "_", ext->name(), "_ext");
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const char* kEnumsInit = "enums_layout";
|
|
95
|
+
const char* kExtensionsInit = "extensions_layout";
|
|
96
|
+
const char* kMessagesInit = "messages_layout";
|
|
97
|
+
|
|
98
|
+
void AddEnums(const protobuf::Descriptor* message,
|
|
99
|
+
std::vector<const protobuf::EnumDescriptor*>* enums) {
|
|
100
|
+
enums->reserve(enums->size() + message->enum_type_count());
|
|
101
|
+
for (int i = 0; i < message->enum_type_count(); i++) {
|
|
102
|
+
enums->push_back(message->enum_type(i));
|
|
103
|
+
}
|
|
104
|
+
for (int i = 0; i < message->nested_type_count(); i++) {
|
|
105
|
+
AddEnums(message->nested_type(i), enums);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
std::vector<const protobuf::EnumDescriptor*> SortedEnums(
|
|
110
|
+
const protobuf::FileDescriptor* file) {
|
|
111
|
+
std::vector<const protobuf::EnumDescriptor*> enums;
|
|
112
|
+
enums.reserve(file->enum_type_count());
|
|
113
|
+
for (int i = 0; i < file->enum_type_count(); i++) {
|
|
114
|
+
enums.push_back(file->enum_type(i));
|
|
115
|
+
}
|
|
116
|
+
for (int i = 0; i < file->message_type_count(); i++) {
|
|
117
|
+
AddEnums(file->message_type(i), &enums);
|
|
118
|
+
}
|
|
119
|
+
return enums;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
std::vector<uint32_t> SortedUniqueEnumNumbers(
|
|
123
|
+
const protobuf::EnumDescriptor* e) {
|
|
124
|
+
std::vector<uint32_t> values;
|
|
125
|
+
values.reserve(e->value_count());
|
|
126
|
+
for (int i = 0; i < e->value_count(); i++) {
|
|
127
|
+
values.push_back(static_cast<uint32_t>(e->value(i)->number()));
|
|
128
|
+
}
|
|
129
|
+
std::sort(values.begin(), values.end());
|
|
130
|
+
auto last = std::unique(values.begin(), values.end());
|
|
131
|
+
values.erase(last, values.end());
|
|
132
|
+
return values;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
void AddMessages(const protobuf::Descriptor* message,
|
|
136
|
+
std::vector<const protobuf::Descriptor*>* messages) {
|
|
137
|
+
messages->push_back(message);
|
|
138
|
+
for (int i = 0; i < message->nested_type_count(); i++) {
|
|
139
|
+
AddMessages(message->nested_type(i), messages);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Ordering must match upb/def.c!
|
|
144
|
+
//
|
|
145
|
+
// The ordering is significant because each upb_MessageDef* will point at the
|
|
146
|
+
// corresponding upb_MiniTable and we just iterate through the list without
|
|
147
|
+
// any search or lookup.
|
|
148
|
+
std::vector<const protobuf::Descriptor*> SortedMessages(
|
|
149
|
+
const protobuf::FileDescriptor* file) {
|
|
150
|
+
std::vector<const protobuf::Descriptor*> messages;
|
|
151
|
+
for (int i = 0; i < file->message_type_count(); i++) {
|
|
152
|
+
AddMessages(file->message_type(i), &messages);
|
|
153
|
+
}
|
|
154
|
+
return messages;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
void AddExtensionsFromMessage(
|
|
158
|
+
const protobuf::Descriptor* message,
|
|
159
|
+
std::vector<const protobuf::FieldDescriptor*>* exts) {
|
|
160
|
+
for (int i = 0; i < message->extension_count(); i++) {
|
|
161
|
+
exts->push_back(message->extension(i));
|
|
162
|
+
}
|
|
163
|
+
for (int i = 0; i < message->nested_type_count(); i++) {
|
|
164
|
+
AddExtensionsFromMessage(message->nested_type(i), exts);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Ordering must match upb/def.c!
|
|
169
|
+
//
|
|
170
|
+
// The ordering is significant because each upb_FieldDef* will point at the
|
|
171
|
+
// corresponding upb_MiniTable_Extension and we just iterate through the list
|
|
172
|
+
// without any search or lookup.
|
|
173
|
+
std::vector<const protobuf::FieldDescriptor*> SortedExtensions(
|
|
174
|
+
const protobuf::FileDescriptor* file) {
|
|
175
|
+
std::vector<const protobuf::FieldDescriptor*> ret;
|
|
176
|
+
for (int i = 0; i < file->extension_count(); i++) {
|
|
177
|
+
ret.push_back(file->extension(i));
|
|
178
|
+
}
|
|
179
|
+
for (int i = 0; i < file->message_type_count(); i++) {
|
|
180
|
+
AddExtensionsFromMessage(file->message_type(i), &ret);
|
|
181
|
+
}
|
|
182
|
+
return ret;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
std::vector<const protobuf::FieldDescriptor*> FieldNumberOrder(
|
|
186
|
+
const protobuf::Descriptor* message) {
|
|
187
|
+
std::vector<const protobuf::FieldDescriptor*> fields;
|
|
188
|
+
for (int i = 0; i < message->field_count(); i++) {
|
|
189
|
+
fields.push_back(message->field(i));
|
|
190
|
+
}
|
|
191
|
+
std::sort(fields.begin(), fields.end(),
|
|
192
|
+
[](const protobuf::FieldDescriptor* a,
|
|
193
|
+
const protobuf::FieldDescriptor* b) {
|
|
194
|
+
return a->number() < b->number();
|
|
195
|
+
});
|
|
196
|
+
return fields;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
std::string EnumValueSymbol(const protobuf::EnumValueDescriptor* value) {
|
|
200
|
+
return ToCIdent(value->full_name());
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
std::string CTypeInternal(const protobuf::FieldDescriptor* field,
|
|
204
|
+
bool is_const) {
|
|
205
|
+
std::string maybe_const = is_const ? "const " : "";
|
|
206
|
+
switch (field->cpp_type()) {
|
|
207
|
+
case protobuf::FieldDescriptor::CPPTYPE_MESSAGE: {
|
|
208
|
+
std::string maybe_struct =
|
|
209
|
+
field->file() != field->message_type()->file() ? "struct " : "";
|
|
210
|
+
return maybe_const + maybe_struct + MessageName(field->message_type()) +
|
|
211
|
+
"*";
|
|
212
|
+
}
|
|
213
|
+
case protobuf::FieldDescriptor::CPPTYPE_BOOL:
|
|
214
|
+
return "bool";
|
|
215
|
+
case protobuf::FieldDescriptor::CPPTYPE_FLOAT:
|
|
216
|
+
return "float";
|
|
217
|
+
case protobuf::FieldDescriptor::CPPTYPE_INT32:
|
|
218
|
+
case protobuf::FieldDescriptor::CPPTYPE_ENUM:
|
|
219
|
+
return "int32_t";
|
|
220
|
+
case protobuf::FieldDescriptor::CPPTYPE_UINT32:
|
|
221
|
+
return "uint32_t";
|
|
222
|
+
case protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
|
|
223
|
+
return "double";
|
|
224
|
+
case protobuf::FieldDescriptor::CPPTYPE_INT64:
|
|
225
|
+
return "int64_t";
|
|
226
|
+
case protobuf::FieldDescriptor::CPPTYPE_UINT64:
|
|
227
|
+
return "uint64_t";
|
|
228
|
+
case protobuf::FieldDescriptor::CPPTYPE_STRING:
|
|
229
|
+
return "upb_StringView";
|
|
230
|
+
default:
|
|
231
|
+
fprintf(stderr, "Unexpected type");
|
|
232
|
+
abort();
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
std::string SizeLg2(const protobuf::FieldDescriptor* field) {
|
|
237
|
+
switch (field->cpp_type()) {
|
|
238
|
+
case protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
|
|
239
|
+
return "UPB_SIZE(2, 3)";
|
|
240
|
+
case protobuf::FieldDescriptor::CPPTYPE_ENUM:
|
|
241
|
+
return std::to_string(2);
|
|
242
|
+
case protobuf::FieldDescriptor::CPPTYPE_BOOL:
|
|
243
|
+
return std::to_string(1);
|
|
244
|
+
case protobuf::FieldDescriptor::CPPTYPE_FLOAT:
|
|
245
|
+
return std::to_string(2);
|
|
246
|
+
case protobuf::FieldDescriptor::CPPTYPE_INT32:
|
|
247
|
+
return std::to_string(2);
|
|
248
|
+
case protobuf::FieldDescriptor::CPPTYPE_UINT32:
|
|
249
|
+
return std::to_string(2);
|
|
250
|
+
case protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
|
|
251
|
+
return std::to_string(3);
|
|
252
|
+
case protobuf::FieldDescriptor::CPPTYPE_INT64:
|
|
253
|
+
return std::to_string(3);
|
|
254
|
+
case protobuf::FieldDescriptor::CPPTYPE_UINT64:
|
|
255
|
+
return std::to_string(3);
|
|
256
|
+
case protobuf::FieldDescriptor::CPPTYPE_STRING:
|
|
257
|
+
return "UPB_SIZE(3, 4)";
|
|
258
|
+
default:
|
|
259
|
+
fprintf(stderr, "Unexpected type");
|
|
260
|
+
abort();
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
bool HasNonZeroDefault(const protobuf::FieldDescriptor* field) {
|
|
265
|
+
switch (field->cpp_type()) {
|
|
266
|
+
case protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
|
|
267
|
+
return false;
|
|
268
|
+
case protobuf::FieldDescriptor::CPPTYPE_STRING:
|
|
269
|
+
return !field->default_value_string().empty();
|
|
270
|
+
case protobuf::FieldDescriptor::CPPTYPE_INT32:
|
|
271
|
+
return field->default_value_int32() != 0;
|
|
272
|
+
case protobuf::FieldDescriptor::CPPTYPE_INT64:
|
|
273
|
+
return field->default_value_int64() != 0;
|
|
274
|
+
case protobuf::FieldDescriptor::CPPTYPE_UINT32:
|
|
275
|
+
return field->default_value_uint32() != 0;
|
|
276
|
+
case protobuf::FieldDescriptor::CPPTYPE_UINT64:
|
|
277
|
+
return field->default_value_uint64() != 0;
|
|
278
|
+
case protobuf::FieldDescriptor::CPPTYPE_FLOAT:
|
|
279
|
+
return field->default_value_float() != 0;
|
|
280
|
+
case protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
|
|
281
|
+
return field->default_value_double() != 0;
|
|
282
|
+
case protobuf::FieldDescriptor::CPPTYPE_BOOL:
|
|
283
|
+
return field->default_value_bool() != false;
|
|
284
|
+
case protobuf::FieldDescriptor::CPPTYPE_ENUM:
|
|
285
|
+
// Use a number instead of a symbolic name so that we don't require
|
|
286
|
+
// this enum's header to be included.
|
|
287
|
+
return field->default_value_enum()->number() != 0;
|
|
288
|
+
}
|
|
289
|
+
ABSL_ASSERT(false);
|
|
290
|
+
return false;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
std::string FieldDefault(const protobuf::FieldDescriptor* field) {
|
|
294
|
+
switch (field->cpp_type()) {
|
|
295
|
+
case protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
|
|
296
|
+
return "NULL";
|
|
297
|
+
case protobuf::FieldDescriptor::CPPTYPE_STRING:
|
|
298
|
+
return absl::Substitute("upb_StringView_FromString(\"$0\")",
|
|
299
|
+
absl::CEscape(field->default_value_string()));
|
|
300
|
+
case protobuf::FieldDescriptor::CPPTYPE_INT32:
|
|
301
|
+
return absl::Substitute("_upb_Int32_FromI($0)",
|
|
302
|
+
field->default_value_int32());
|
|
303
|
+
case protobuf::FieldDescriptor::CPPTYPE_INT64:
|
|
304
|
+
return absl::Substitute("_upb_Int64_FromLL($0ll)",
|
|
305
|
+
field->default_value_int64());
|
|
306
|
+
case protobuf::FieldDescriptor::CPPTYPE_UINT32:
|
|
307
|
+
return absl::Substitute("_upb_UInt32_FromU($0u)",
|
|
308
|
+
field->default_value_uint32());
|
|
309
|
+
case protobuf::FieldDescriptor::CPPTYPE_UINT64:
|
|
310
|
+
return absl::Substitute("_upb_UInt64_FromULL($0ull)",
|
|
311
|
+
field->default_value_uint64());
|
|
312
|
+
case protobuf::FieldDescriptor::CPPTYPE_FLOAT:
|
|
313
|
+
return absl::StrCat(field->default_value_float());
|
|
314
|
+
case protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
|
|
315
|
+
return absl::StrCat(field->default_value_double());
|
|
316
|
+
case protobuf::FieldDescriptor::CPPTYPE_BOOL:
|
|
317
|
+
return field->default_value_bool() ? "true" : "false";
|
|
318
|
+
case protobuf::FieldDescriptor::CPPTYPE_ENUM:
|
|
319
|
+
// Use a number instead of a symbolic name so that we don't require
|
|
320
|
+
// this enum's header to be included.
|
|
321
|
+
return absl::StrCat(field->default_value_enum()->number());
|
|
322
|
+
}
|
|
323
|
+
ABSL_ASSERT(false);
|
|
324
|
+
return "XXX";
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
std::string CType(const protobuf::FieldDescriptor* field) {
|
|
328
|
+
return CTypeInternal(field, false);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
std::string CTypeConst(const protobuf::FieldDescriptor* field) {
|
|
332
|
+
return CTypeInternal(field, true);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
336
|
+
// FilePlatformLayout
|
|
337
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
338
|
+
|
|
339
|
+
// FilePlatformLayout builds and vends upb MiniTables for a given platform (32
|
|
340
|
+
// or 64 bit).
|
|
341
|
+
class FilePlatformLayout {
|
|
342
|
+
public:
|
|
343
|
+
FilePlatformLayout(const protobuf::FileDescriptor* fd,
|
|
344
|
+
upb_MiniTablePlatform platform)
|
|
345
|
+
: platform_(platform) {
|
|
346
|
+
BuildMiniTables(fd);
|
|
347
|
+
BuildExtensions(fd);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
// Retrieves a upb MiniTable or Extension given a protobuf descriptor. The
|
|
351
|
+
// descriptor must be from this layout's file.
|
|
352
|
+
upb_MiniTable* GetMiniTable(const protobuf::Descriptor* m) const;
|
|
353
|
+
upb_MiniTable_Enum* GetEnumTable(const protobuf::EnumDescriptor* d) const;
|
|
354
|
+
const upb_MiniTable_Extension* GetExtension(
|
|
355
|
+
const protobuf::FieldDescriptor* fd) const;
|
|
356
|
+
|
|
357
|
+
// Get the initializer for the given sub-message/sub-enum link.
|
|
358
|
+
static std::string GetSub(upb_MiniTable_Sub sub);
|
|
359
|
+
|
|
360
|
+
private:
|
|
361
|
+
// Functions to build mini-tables for this file's messages and extensions.
|
|
362
|
+
void BuildMiniTables(const protobuf::FileDescriptor* fd);
|
|
363
|
+
void BuildExtensions(const protobuf::FileDescriptor* fd);
|
|
364
|
+
upb_MiniTable* MakeMiniTable(const protobuf::Descriptor* m);
|
|
365
|
+
upb_MiniTable* MakeRegularMiniTable(const protobuf::Descriptor* m);
|
|
366
|
+
upb_MiniTable_Enum* MakeMiniTableEnum(const protobuf::EnumDescriptor* d);
|
|
367
|
+
uint64_t GetMessageModifiers(const protobuf::Descriptor* m);
|
|
368
|
+
uint64_t GetFieldModifiers(const protobuf::FieldDescriptor* f);
|
|
369
|
+
void ResolveIntraFileReferences();
|
|
370
|
+
|
|
371
|
+
// When we are generating code, tables are linked to sub-tables via name (ie.
|
|
372
|
+
// a string) rather than by pointer. We need to emit an initializer like
|
|
373
|
+
// `&foo_sub_table`. To do this, we store `const char*` strings in all the
|
|
374
|
+
// links that would normally be pointers:
|
|
375
|
+
// field -> sub-message
|
|
376
|
+
// field -> enum table (proto2 only)
|
|
377
|
+
// extension -> extendee
|
|
378
|
+
//
|
|
379
|
+
// This requires a bit of reinterpret_cast<>(), but it's confined to a few
|
|
380
|
+
// functions. We tag the pointer so we know which member of the union to
|
|
381
|
+
// initialize.
|
|
382
|
+
enum SubTag {
|
|
383
|
+
kNull = 0,
|
|
384
|
+
kMessage = 1,
|
|
385
|
+
kEnum = 2,
|
|
386
|
+
kMask = 3,
|
|
387
|
+
};
|
|
388
|
+
|
|
389
|
+
static upb_MiniTable_Sub PackSub(const char* data, SubTag tag);
|
|
390
|
+
static bool IsNull(upb_MiniTable_Sub sub);
|
|
391
|
+
void SetSubTableStrings();
|
|
392
|
+
upb_MiniTable_Sub PackSubForField(const protobuf::FieldDescriptor* f,
|
|
393
|
+
const upb_MiniTable_Field* mt_f);
|
|
394
|
+
const char* AllocStr(absl::string_view str);
|
|
395
|
+
|
|
396
|
+
private:
|
|
397
|
+
using TableMap =
|
|
398
|
+
absl::flat_hash_map<const protobuf::Descriptor*, upb_MiniTable*>;
|
|
399
|
+
using EnumMap =
|
|
400
|
+
absl::flat_hash_map<const protobuf::EnumDescriptor*, upb_MiniTable_Enum*>;
|
|
401
|
+
using ExtensionMap = absl::flat_hash_map<const protobuf::FieldDescriptor*,
|
|
402
|
+
upb_MiniTable_Extension>;
|
|
403
|
+
upb::Arena arena_;
|
|
404
|
+
TableMap table_map_;
|
|
405
|
+
EnumMap enum_map_;
|
|
406
|
+
ExtensionMap extension_map_;
|
|
407
|
+
upb_MiniTablePlatform platform_;
|
|
408
|
+
};
|
|
409
|
+
|
|
410
|
+
upb_MiniTable* FilePlatformLayout::GetMiniTable(
|
|
411
|
+
const protobuf::Descriptor* m) const {
|
|
412
|
+
auto it = table_map_.find(m);
|
|
413
|
+
assert(it != table_map_.end());
|
|
414
|
+
return it->second;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
upb_MiniTable_Enum* FilePlatformLayout::GetEnumTable(
|
|
418
|
+
const protobuf::EnumDescriptor* d) const {
|
|
419
|
+
auto it = enum_map_.find(d);
|
|
420
|
+
assert(it != enum_map_.end());
|
|
421
|
+
return it->second;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
const upb_MiniTable_Extension* FilePlatformLayout::GetExtension(
|
|
425
|
+
const protobuf::FieldDescriptor* fd) const {
|
|
426
|
+
auto it = extension_map_.find(fd);
|
|
427
|
+
assert(it != extension_map_.end());
|
|
428
|
+
return &it->second;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
void FilePlatformLayout::ResolveIntraFileReferences() {
|
|
432
|
+
// This properly resolves references within a file, in order to set any
|
|
433
|
+
// necessary flags (eg. is a map).
|
|
434
|
+
for (const auto& pair : table_map_) {
|
|
435
|
+
upb_MiniTable* mt = pair.second;
|
|
436
|
+
// First we properly resolve for defs within the file.
|
|
437
|
+
for (const auto* f : FieldNumberOrder(pair.first)) {
|
|
438
|
+
if (f->message_type() && f->message_type()->file() == f->file()) {
|
|
439
|
+
// const_cast is safe because the mini-table is owned exclusively
|
|
440
|
+
// by us, and was allocated from an arena (known-writable memory).
|
|
441
|
+
upb_MiniTable_Field* mt_f = const_cast<upb_MiniTable_Field*>(
|
|
442
|
+
upb_MiniTable_FindFieldByNumber(mt, f->number()));
|
|
443
|
+
upb_MiniTable* sub_mt = GetMiniTable(f->message_type());
|
|
444
|
+
upb_MiniTable_SetSubMessage(mt, mt_f, sub_mt);
|
|
445
|
+
}
|
|
446
|
+
// We don't worry about enums here, because resolving an enum will
|
|
447
|
+
// never alter the mini-table.
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
upb_MiniTable_Sub FilePlatformLayout::PackSub(const char* data, SubTag tag) {
|
|
453
|
+
uintptr_t val = reinterpret_cast<uintptr_t>(data);
|
|
454
|
+
assert((val & kMask) == 0);
|
|
455
|
+
upb_MiniTable_Sub sub;
|
|
456
|
+
sub.submsg = reinterpret_cast<upb_MiniTable*>(val | tag);
|
|
457
|
+
return sub;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
bool FilePlatformLayout::IsNull(upb_MiniTable_Sub sub) {
|
|
461
|
+
return reinterpret_cast<uintptr_t>(sub.subenum) == 0;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
std::string FilePlatformLayout::GetSub(upb_MiniTable_Sub sub) {
|
|
465
|
+
uintptr_t as_int = reinterpret_cast<uintptr_t>(sub.submsg);
|
|
466
|
+
const char* str = reinterpret_cast<const char*>(as_int & ~SubTag::kMask);
|
|
467
|
+
switch (as_int & SubTag::kMask) {
|
|
468
|
+
case SubTag::kMessage:
|
|
469
|
+
return absl::Substitute("{.submsg = &$0}", str);
|
|
470
|
+
case SubTag::kEnum:
|
|
471
|
+
return absl::Substitute("{.subenum = &$0}", str);
|
|
472
|
+
default:
|
|
473
|
+
return std::string("{.submsg = NULL}");
|
|
474
|
+
}
|
|
475
|
+
return std::string("ERROR in GetSub");
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
void FilePlatformLayout::SetSubTableStrings() {
|
|
479
|
+
for (const auto& pair : table_map_) {
|
|
480
|
+
upb_MiniTable* mt = pair.second;
|
|
481
|
+
for (const auto* f : FieldNumberOrder(pair.first)) {
|
|
482
|
+
upb_MiniTable_Field* mt_f = const_cast<upb_MiniTable_Field*>(
|
|
483
|
+
upb_MiniTable_FindFieldByNumber(mt, f->number()));
|
|
484
|
+
assert(mt_f);
|
|
485
|
+
upb_MiniTable_Sub sub = PackSubForField(f, mt_f);
|
|
486
|
+
if (IsNull(sub)) continue;
|
|
487
|
+
// const_cast is safe because the mini-table is owned exclusively
|
|
488
|
+
// by us, and was allocated from an arena (known-writable memory).
|
|
489
|
+
*const_cast<upb_MiniTable_Sub*>(&mt->subs[mt_f->submsg_index]) = sub;
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
upb_MiniTable_Sub FilePlatformLayout::PackSubForField(
|
|
495
|
+
const protobuf::FieldDescriptor* f, const upb_MiniTable_Field* mt_f) {
|
|
496
|
+
if (mt_f->submsg_index == kUpb_NoSub) {
|
|
497
|
+
return PackSub(nullptr, SubTag::kNull);
|
|
498
|
+
} else if (f->message_type()) {
|
|
499
|
+
return PackSub(AllocStr(MessageInit(f->message_type())), SubTag::kMessage);
|
|
500
|
+
} else {
|
|
501
|
+
ABSL_ASSERT(f->enum_type());
|
|
502
|
+
return PackSub(AllocStr(EnumInit(f->enum_type())), SubTag::kEnum);
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
const char* FilePlatformLayout::AllocStr(absl::string_view str) {
|
|
507
|
+
char* ret =
|
|
508
|
+
static_cast<char*>(upb_Arena_Malloc(arena_.ptr(), str.size() + 1));
|
|
509
|
+
memcpy(ret, str.data(), str.size());
|
|
510
|
+
ret[str.size()] = '\0';
|
|
511
|
+
return ret;
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
void FilePlatformLayout::BuildMiniTables(const protobuf::FileDescriptor* fd) {
|
|
515
|
+
for (const auto& m : SortedMessages(fd)) {
|
|
516
|
+
table_map_[m] = MakeMiniTable(m);
|
|
517
|
+
}
|
|
518
|
+
for (const auto& e : SortedEnums(fd)) {
|
|
519
|
+
enum_map_[e] = MakeMiniTableEnum(e);
|
|
520
|
+
}
|
|
521
|
+
ResolveIntraFileReferences();
|
|
522
|
+
SetSubTableStrings();
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
void FilePlatformLayout::BuildExtensions(const protobuf::FileDescriptor* fd) {
|
|
526
|
+
std::vector<const protobuf::FieldDescriptor*> sorted = SortedExtensions(fd);
|
|
527
|
+
upb::Status status;
|
|
528
|
+
for (const auto* f : sorted) {
|
|
529
|
+
upb::MtDataEncoder e;
|
|
530
|
+
e.StartMessage(0);
|
|
531
|
+
e.PutField(static_cast<upb_FieldType>(f->type()), f->number(),
|
|
532
|
+
GetFieldModifiers(f));
|
|
533
|
+
upb_MiniTable_Extension& ext = extension_map_[f];
|
|
534
|
+
upb_MiniTable_Sub sub;
|
|
535
|
+
bool ok = upb_MiniTable_BuildExtension(e.data().data(), e.data().size(),
|
|
536
|
+
&ext, sub, status.ptr());
|
|
537
|
+
if (!ok) {
|
|
538
|
+
// TODO(haberman): Use ABSL CHECK() when it is available.
|
|
539
|
+
fprintf(stderr, "Error building mini-table: %s\n",
|
|
540
|
+
status.error_message());
|
|
541
|
+
}
|
|
542
|
+
ABSL_ASSERT(ok);
|
|
543
|
+
ext.extendee = reinterpret_cast<const upb_MiniTable*>(
|
|
544
|
+
AllocStr(MessageInit(f->containing_type())));
|
|
545
|
+
ext.sub = PackSubForField(f, &ext.field);
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
upb_MiniTable* FilePlatformLayout::MakeMiniTable(
|
|
550
|
+
const protobuf::Descriptor* m) {
|
|
551
|
+
if (m->options().message_set_wire_format()) {
|
|
552
|
+
return upb_MiniTable_BuildMessageSet(platform_, arena_.ptr());
|
|
553
|
+
} else if (m->options().map_entry()) {
|
|
554
|
+
return upb_MiniTable_BuildMapEntry(
|
|
555
|
+
static_cast<upb_FieldType>(m->map_key()->type()),
|
|
556
|
+
static_cast<upb_FieldType>(m->map_value()->type()),
|
|
557
|
+
m->map_value()->enum_type() &&
|
|
558
|
+
m->map_value()->enum_type()->file()->syntax() ==
|
|
559
|
+
protobuf::FileDescriptor::SYNTAX_PROTO3,
|
|
560
|
+
platform_, arena_.ptr());
|
|
561
|
+
} else {
|
|
562
|
+
return MakeRegularMiniTable(m);
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
upb_MiniTable* FilePlatformLayout::MakeRegularMiniTable(
|
|
567
|
+
const protobuf::Descriptor* m) {
|
|
568
|
+
upb::MtDataEncoder e;
|
|
569
|
+
e.StartMessage(GetMessageModifiers(m));
|
|
570
|
+
for (const auto* f : FieldNumberOrder(m)) {
|
|
571
|
+
e.PutField(static_cast<upb_FieldType>(f->type()), f->number(),
|
|
572
|
+
GetFieldModifiers(f));
|
|
573
|
+
}
|
|
574
|
+
for (int i = 0; i < m->real_oneof_decl_count(); i++) {
|
|
575
|
+
const protobuf::OneofDescriptor* oneof = m->oneof_decl(i);
|
|
576
|
+
e.StartOneof();
|
|
577
|
+
for (int j = 0; j < oneof->field_count(); j++) {
|
|
578
|
+
const protobuf::FieldDescriptor* f = oneof->field(j);
|
|
579
|
+
e.PutOneofField(f->number());
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
absl::string_view str = e.data();
|
|
583
|
+
upb::Status status;
|
|
584
|
+
upb_MiniTable* ret = upb_MiniTable_Build(str.data(), str.size(), platform_,
|
|
585
|
+
arena_.ptr(), status.ptr());
|
|
586
|
+
if (!ret) {
|
|
587
|
+
fprintf(stderr, "Error building mini-table: %s\n", status.error_message());
|
|
588
|
+
}
|
|
589
|
+
assert(ret);
|
|
590
|
+
return ret;
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
upb_MiniTable_Enum* FilePlatformLayout::MakeMiniTableEnum(
|
|
594
|
+
const protobuf::EnumDescriptor* d) {
|
|
595
|
+
upb::Arena arena;
|
|
596
|
+
upb::MtDataEncoder e;
|
|
597
|
+
|
|
598
|
+
e.StartEnum();
|
|
599
|
+
for (uint32_t i : SortedUniqueEnumNumbers(d)) {
|
|
600
|
+
e.PutEnumValue(i);
|
|
601
|
+
}
|
|
602
|
+
e.EndEnum();
|
|
603
|
+
|
|
604
|
+
absl::string_view str = e.data();
|
|
605
|
+
upb::Status status;
|
|
606
|
+
upb_MiniTable_Enum* ret = upb_MiniTable_BuildEnum(str.data(), str.size(),
|
|
607
|
+
arena_.ptr(), status.ptr());
|
|
608
|
+
if (!ret) {
|
|
609
|
+
fprintf(stderr, "Error building mini-table: %s\n", status.error_message());
|
|
610
|
+
}
|
|
611
|
+
assert(ret);
|
|
612
|
+
return ret;
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
uint64_t FilePlatformLayout::GetMessageModifiers(
|
|
616
|
+
const protobuf::Descriptor* m) {
|
|
617
|
+
uint64_t ret = 0;
|
|
618
|
+
|
|
619
|
+
if (m->file()->syntax() == protobuf::FileDescriptor::SYNTAX_PROTO3) {
|
|
620
|
+
ret |= kUpb_MessageModifier_ValidateUtf8;
|
|
621
|
+
ret |= kUpb_MessageModifier_DefaultIsPacked;
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
if (m->extension_range_count() > 0) {
|
|
625
|
+
ret |= kUpb_MessageModifier_IsExtendable;
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
assert(!m->options().map_entry());
|
|
629
|
+
return ret;
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
uint64_t FilePlatformLayout::GetFieldModifiers(
|
|
633
|
+
const protobuf::FieldDescriptor* f) {
|
|
634
|
+
uint64_t ret = 0;
|
|
635
|
+
|
|
636
|
+
if (f->is_repeated()) ret |= kUpb_FieldModifier_IsRepeated;
|
|
637
|
+
if (f->is_required()) ret |= kUpb_FieldModifier_IsRequired;
|
|
638
|
+
if (f->is_packed()) ret |= kUpb_FieldModifier_IsPacked;
|
|
639
|
+
if (f->enum_type() && f->enum_type()->file()->syntax() ==
|
|
640
|
+
protobuf::FileDescriptor::SYNTAX_PROTO2) {
|
|
641
|
+
ret |= kUpb_FieldModifier_IsClosedEnum;
|
|
642
|
+
}
|
|
643
|
+
if (f->is_optional() && !f->has_presence()) {
|
|
644
|
+
ret |= kUpb_FieldModifier_IsProto3Singular;
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
return ret;
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
651
|
+
// FileLayout
|
|
652
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
653
|
+
|
|
654
|
+
// FileLayout is a pair of platform layouts: one for 32-bit and one for 64-bit.
|
|
655
|
+
class FileLayout {
|
|
656
|
+
public:
|
|
657
|
+
FileLayout(const protobuf::FileDescriptor* fd)
|
|
658
|
+
: descriptor_(fd),
|
|
659
|
+
layout32_(fd, kUpb_MiniTablePlatform_32Bit),
|
|
660
|
+
layout64_(fd, kUpb_MiniTablePlatform_64Bit) {}
|
|
661
|
+
|
|
662
|
+
const protobuf::FileDescriptor* descriptor() const { return descriptor_; }
|
|
663
|
+
|
|
664
|
+
const upb_MiniTable* GetMiniTable32(const protobuf::Descriptor* m) const {
|
|
665
|
+
return layout32_.GetMiniTable(m);
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
const upb_MiniTable* GetMiniTable64(const protobuf::Descriptor* m) const {
|
|
669
|
+
return layout64_.GetMiniTable(m);
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
const upb_MiniTable_Enum* GetEnumTable(
|
|
673
|
+
const protobuf::EnumDescriptor* d) const {
|
|
674
|
+
return layout64_.GetEnumTable(d);
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
std::string GetFieldOffset(const protobuf::FieldDescriptor* f) const {
|
|
678
|
+
const upb_MiniTable_Field* f_32 = upb_MiniTable_FindFieldByNumber(
|
|
679
|
+
GetMiniTable32(f->containing_type()), f->number());
|
|
680
|
+
const upb_MiniTable_Field* f_64 = upb_MiniTable_FindFieldByNumber(
|
|
681
|
+
GetMiniTable64(f->containing_type()), f->number());
|
|
682
|
+
return absl::Substitute("UPB_SIZE($0, $1)", f_32->offset, f_64->offset);
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
std::string GetOneofCaseOffset(const protobuf::OneofDescriptor* o) const {
|
|
686
|
+
const protobuf::FieldDescriptor* f = o->field(0);
|
|
687
|
+
const upb_MiniTable_Field* f_32 = upb_MiniTable_FindFieldByNumber(
|
|
688
|
+
GetMiniTable32(f->containing_type()), f->number());
|
|
689
|
+
const upb_MiniTable_Field* f_64 = upb_MiniTable_FindFieldByNumber(
|
|
690
|
+
GetMiniTable64(f->containing_type()), f->number());
|
|
691
|
+
return absl::Substitute("UPB_SIZE($0, $1)", ~f_32->presence,
|
|
692
|
+
~f_64->presence);
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
std::string GetMessageSize(const protobuf::Descriptor* d) const {
|
|
696
|
+
return absl::Substitute("UPB_SIZE($0, $1)", GetMiniTable32(d)->size,
|
|
697
|
+
GetMiniTable64(d)->size);
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
int GetHasbitIndex(const protobuf::FieldDescriptor* f) const {
|
|
701
|
+
const upb_MiniTable_Field* f_64 = upb_MiniTable_FindFieldByNumber(
|
|
702
|
+
GetMiniTable64(f->containing_type()), f->number());
|
|
703
|
+
return f_64->presence;
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
bool HasHasbit(const protobuf::FieldDescriptor* f) const {
|
|
707
|
+
return GetHasbitIndex(f) > 0;
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
const upb_MiniTable_Extension* GetExtension(
|
|
711
|
+
const protobuf::FieldDescriptor* f) const {
|
|
712
|
+
return layout64_.GetExtension(f);
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
private:
|
|
716
|
+
const protobuf::FileDescriptor* descriptor_;
|
|
717
|
+
FilePlatformLayout layout32_;
|
|
718
|
+
FilePlatformLayout layout64_;
|
|
719
|
+
};
|
|
720
|
+
|
|
721
|
+
void DumpEnumValues(const protobuf::EnumDescriptor* desc, Output& output) {
|
|
722
|
+
std::vector<const protobuf::EnumValueDescriptor*> values;
|
|
723
|
+
for (int i = 0; i < desc->value_count(); i++) {
|
|
724
|
+
values.push_back(desc->value(i));
|
|
725
|
+
}
|
|
726
|
+
std::sort(values.begin(), values.end(),
|
|
727
|
+
[](const protobuf::EnumValueDescriptor* a,
|
|
728
|
+
const protobuf::EnumValueDescriptor* b) {
|
|
729
|
+
return a->number() < b->number();
|
|
730
|
+
});
|
|
731
|
+
|
|
732
|
+
for (size_t i = 0; i < values.size(); i++) {
|
|
733
|
+
auto value = values[i];
|
|
734
|
+
output(" $0 = $1", EnumValueSymbol(value), value->number());
|
|
735
|
+
if (i != values.size() - 1) {
|
|
736
|
+
output(",");
|
|
737
|
+
}
|
|
738
|
+
output("\n");
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
void GenerateExtensionInHeader(const protobuf::FieldDescriptor* ext,
|
|
743
|
+
Output& output) {
|
|
744
|
+
output(
|
|
745
|
+
R"cc(
|
|
746
|
+
UPB_INLINE bool $0_has_$1(const struct $2* msg) {
|
|
747
|
+
return _upb_Message_Getext(msg, &$3) != NULL;
|
|
748
|
+
}
|
|
749
|
+
)cc",
|
|
750
|
+
ExtensionIdentBase(ext), ext->name(), MessageName(ext->containing_type()),
|
|
751
|
+
ExtensionLayout(ext));
|
|
752
|
+
|
|
753
|
+
output(
|
|
754
|
+
R"cc(
|
|
755
|
+
UPB_INLINE void $0_clear_$1(struct $2* msg) {
|
|
756
|
+
_upb_Message_Clearext(msg, &$3);
|
|
757
|
+
}
|
|
758
|
+
)cc",
|
|
759
|
+
ExtensionIdentBase(ext), ext->name(), MessageName(ext->containing_type()),
|
|
760
|
+
ExtensionLayout(ext));
|
|
761
|
+
|
|
762
|
+
if (ext->is_repeated()) {
|
|
763
|
+
} else if (ext->message_type()) {
|
|
764
|
+
output(
|
|
765
|
+
R"cc(
|
|
766
|
+
UPB_INLINE $0 $1_$2(const struct $3* msg) {
|
|
767
|
+
const upb_Message_Extension* ext = _upb_Message_Getext(msg, &$4);
|
|
768
|
+
UPB_ASSERT(ext);
|
|
769
|
+
return *UPB_PTR_AT(&ext->data, 0, $0);
|
|
770
|
+
}
|
|
771
|
+
)cc",
|
|
772
|
+
CTypeConst(ext), ExtensionIdentBase(ext), ext->name(),
|
|
773
|
+
MessageName(ext->containing_type()), ExtensionLayout(ext),
|
|
774
|
+
FieldDefault(ext));
|
|
775
|
+
output(
|
|
776
|
+
R"cc(
|
|
777
|
+
UPB_INLINE void $1_set_$2(struct $3* msg, $0 ext, upb_Arena* arena) {
|
|
778
|
+
const upb_Message_Extension* msg_ext =
|
|
779
|
+
_upb_Message_GetOrCreateExtension(msg, &$4, arena);
|
|
780
|
+
UPB_ASSERT(msg_ext);
|
|
781
|
+
*UPB_PTR_AT(&msg_ext->data, 0, $0) = ext;
|
|
782
|
+
}
|
|
783
|
+
)cc",
|
|
784
|
+
CTypeConst(ext), ExtensionIdentBase(ext), ext->name(),
|
|
785
|
+
MessageName(ext->containing_type()), ExtensionLayout(ext),
|
|
786
|
+
FieldDefault(ext));
|
|
787
|
+
} else {
|
|
788
|
+
// Returns default if extension field is not a message.
|
|
789
|
+
output(
|
|
790
|
+
R"cc(
|
|
791
|
+
UPB_INLINE $0 $1_$2(const struct $3* msg) {
|
|
792
|
+
const upb_Message_Extension* ext = _upb_Message_Getext(msg, &$4);
|
|
793
|
+
return ext ? *UPB_PTR_AT(&ext->data, 0, $0) : $5;
|
|
794
|
+
}
|
|
795
|
+
)cc",
|
|
796
|
+
CTypeConst(ext), ExtensionIdentBase(ext), ext->name(),
|
|
797
|
+
MessageName(ext->containing_type()), ExtensionLayout(ext),
|
|
798
|
+
FieldDefault(ext));
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
void GenerateMessageFunctionsInHeader(const protobuf::Descriptor* message,
|
|
803
|
+
Output& output) {
|
|
804
|
+
output(
|
|
805
|
+
R"cc(
|
|
806
|
+
UPB_INLINE $0* $0_new(upb_Arena* arena) {
|
|
807
|
+
return ($0*)_upb_Message_New(&$1, arena);
|
|
808
|
+
}
|
|
809
|
+
UPB_INLINE $0* $0_parse(const char* buf, size_t size, upb_Arena* arena) {
|
|
810
|
+
$0* ret = $0_new(arena);
|
|
811
|
+
if (!ret) return NULL;
|
|
812
|
+
if (upb_Decode(buf, size, ret, &$1, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
|
|
813
|
+
return NULL;
|
|
814
|
+
}
|
|
815
|
+
return ret;
|
|
816
|
+
}
|
|
817
|
+
UPB_INLINE $0* $0_parse_ex(const char* buf, size_t size,
|
|
818
|
+
const upb_ExtensionRegistry* extreg,
|
|
819
|
+
int options, upb_Arena* arena) {
|
|
820
|
+
$0* ret = $0_new(arena);
|
|
821
|
+
if (!ret) return NULL;
|
|
822
|
+
if (upb_Decode(buf, size, ret, &$1, extreg, options, arena) !=
|
|
823
|
+
kUpb_DecodeStatus_Ok) {
|
|
824
|
+
return NULL;
|
|
825
|
+
}
|
|
826
|
+
return ret;
|
|
827
|
+
}
|
|
828
|
+
UPB_INLINE char* $0_serialize(const $0* msg, upb_Arena* arena, size_t* len) {
|
|
829
|
+
return upb_Encode(msg, &$1, 0, arena, len);
|
|
830
|
+
}
|
|
831
|
+
UPB_INLINE char* $0_serialize_ex(const $0* msg, int options,
|
|
832
|
+
upb_Arena* arena, size_t* len) {
|
|
833
|
+
return upb_Encode(msg, &$1, options, arena, len);
|
|
834
|
+
}
|
|
835
|
+
)cc",
|
|
836
|
+
MessageName(message), MessageInit(message));
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
void GenerateOneofInHeader(const protobuf::OneofDescriptor* oneof,
|
|
840
|
+
const FileLayout& layout, absl::string_view msg_name,
|
|
841
|
+
Output& output) {
|
|
842
|
+
std::string fullname = ToCIdent(oneof->full_name());
|
|
843
|
+
output("typedef enum {\n");
|
|
844
|
+
for (int j = 0; j < oneof->field_count(); j++) {
|
|
845
|
+
const protobuf::FieldDescriptor* field = oneof->field(j);
|
|
846
|
+
output(" $0_$1 = $2,\n", fullname, field->name(), field->number());
|
|
847
|
+
}
|
|
848
|
+
output(
|
|
849
|
+
" $0_NOT_SET = 0\n"
|
|
850
|
+
"} $0_oneofcases;\n",
|
|
851
|
+
fullname);
|
|
852
|
+
output(
|
|
853
|
+
R"cc(
|
|
854
|
+
UPB_INLINE $0_oneofcases $1_$2_case(const $1* msg) {
|
|
855
|
+
return ($0_oneofcases)*UPB_PTR_AT(msg, $3, int32_t);
|
|
856
|
+
}
|
|
857
|
+
)cc",
|
|
858
|
+
fullname, msg_name, oneof->name(), layout.GetOneofCaseOffset(oneof));
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
void GenerateHazzer(const protobuf::FieldDescriptor* field,
|
|
862
|
+
const FileLayout& layout, absl::string_view msg_name,
|
|
863
|
+
Output& output) {
|
|
864
|
+
if (layout.HasHasbit(field)) {
|
|
865
|
+
output(
|
|
866
|
+
R"cc(
|
|
867
|
+
UPB_INLINE bool $0_has_$1(const $0* msg) {
|
|
868
|
+
return _upb_hasbit(msg, $2);
|
|
869
|
+
}
|
|
870
|
+
)cc",
|
|
871
|
+
msg_name, field->name(), layout.GetHasbitIndex(field));
|
|
872
|
+
} else if (field->real_containing_oneof()) {
|
|
873
|
+
output(
|
|
874
|
+
R"cc(
|
|
875
|
+
UPB_INLINE bool $0_has_$1(const $0* msg) {
|
|
876
|
+
return _upb_getoneofcase(msg, $2) == $3;
|
|
877
|
+
}
|
|
878
|
+
)cc",
|
|
879
|
+
msg_name, field->name(),
|
|
880
|
+
layout.GetOneofCaseOffset(field->real_containing_oneof()),
|
|
881
|
+
field->number());
|
|
882
|
+
} else if (field->message_type()) {
|
|
883
|
+
output(
|
|
884
|
+
R"cc(
|
|
885
|
+
UPB_INLINE bool $0_has_$1(const $0* msg) {
|
|
886
|
+
return _upb_has_submsg_nohasbit(msg, $2);
|
|
887
|
+
}
|
|
888
|
+
)cc",
|
|
889
|
+
msg_name, field->name(), layout.GetFieldOffset(field));
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
void GenerateClear(const protobuf::FieldDescriptor* field,
|
|
894
|
+
const FileLayout& layout, absl::string_view msg_name,
|
|
895
|
+
Output& output) {
|
|
896
|
+
if (field == field->containing_type()->map_key() ||
|
|
897
|
+
field == field->containing_type()->map_value()) {
|
|
898
|
+
// Cannot be cleared.
|
|
899
|
+
return;
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
if (field->real_containing_oneof()) {
|
|
903
|
+
const protobuf::OneofDescriptor* oneof = field->real_containing_oneof();
|
|
904
|
+
std::string oneof_fullname = ToCIdent(oneof->full_name());
|
|
905
|
+
std::string default_value =
|
|
906
|
+
field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING
|
|
907
|
+
? "upb_StringView_FromDataAndSize(NULL, 0)"
|
|
908
|
+
: "0";
|
|
909
|
+
output(
|
|
910
|
+
R"cc(
|
|
911
|
+
UPB_INLINE void $0_clear_$1(const $0* msg) {
|
|
912
|
+
UPB_WRITE_ONEOF(msg, $2, $3, $7, $4, $6_NOT_SET);
|
|
913
|
+
}
|
|
914
|
+
)cc",
|
|
915
|
+
msg_name, field->name(), CType(field), layout.GetFieldOffset(field),
|
|
916
|
+
layout.GetOneofCaseOffset(field->real_containing_oneof()),
|
|
917
|
+
field->number(), oneof_fullname, default_value);
|
|
918
|
+
} else {
|
|
919
|
+
if (field->message_type()) {
|
|
920
|
+
output(
|
|
921
|
+
R"cc(
|
|
922
|
+
UPB_INLINE void $0_clear_$1(const $0* msg) {
|
|
923
|
+
*UPB_PTR_AT(msg, $2, const upb_Message*) = NULL;
|
|
924
|
+
}
|
|
925
|
+
)cc",
|
|
926
|
+
msg_name, field->name(), layout.GetFieldOffset(field));
|
|
927
|
+
} else if (layout.HasHasbit(field)) {
|
|
928
|
+
if (field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING) {
|
|
929
|
+
output(
|
|
930
|
+
R"cc(
|
|
931
|
+
UPB_INLINE void $0_clear_$1(const $0* msg) {
|
|
932
|
+
*UPB_PTR_AT(msg, $3, $2) = upb_StringView_FromDataAndSize(NULL, 0);
|
|
933
|
+
_upb_clearhas(msg, $4);
|
|
934
|
+
}
|
|
935
|
+
)cc",
|
|
936
|
+
msg_name, field->name(), CType(field), layout.GetFieldOffset(field),
|
|
937
|
+
layout.GetHasbitIndex(field));
|
|
938
|
+
} else {
|
|
939
|
+
output(
|
|
940
|
+
R"cc(
|
|
941
|
+
UPB_INLINE void $0_clear_$1(const $0* msg) {
|
|
942
|
+
*UPB_PTR_AT(msg, $3, $2) = 0;
|
|
943
|
+
_upb_clearhas(msg, $4);
|
|
944
|
+
}
|
|
945
|
+
)cc",
|
|
946
|
+
msg_name, field->name(), CType(field), layout.GetFieldOffset(field),
|
|
947
|
+
layout.GetHasbitIndex(field));
|
|
948
|
+
}
|
|
949
|
+
} else {
|
|
950
|
+
if (field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING) {
|
|
951
|
+
output(
|
|
952
|
+
R"cc(
|
|
953
|
+
UPB_INLINE void $0_clear_$1(const $0* msg) {
|
|
954
|
+
*UPB_PTR_AT(msg, $3, $2) = upb_StringView_FromDataAndSize(NULL, 0);
|
|
955
|
+
}
|
|
956
|
+
)cc",
|
|
957
|
+
msg_name, field->name(), CType(field),
|
|
958
|
+
layout.GetFieldOffset(field));
|
|
959
|
+
} else {
|
|
960
|
+
output(
|
|
961
|
+
R"cc(
|
|
962
|
+
UPB_INLINE void $0_clear_$1(const $0* msg) {
|
|
963
|
+
*UPB_PTR_AT(msg, $3, $2) = 0;
|
|
964
|
+
}
|
|
965
|
+
)cc",
|
|
966
|
+
msg_name, field->name(), CType(field), layout.GetFieldOffset(field),
|
|
967
|
+
layout.GetHasbitIndex(field));
|
|
968
|
+
}
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
void GenerateRepeatedClear(const protobuf::FieldDescriptor* field,
|
|
974
|
+
const FileLayout& layout, absl::string_view msg_name,
|
|
975
|
+
Output& output) {
|
|
976
|
+
output(
|
|
977
|
+
R"cc(
|
|
978
|
+
UPB_INLINE void $0_clear_$1(const $0* msg) {
|
|
979
|
+
_upb_array_detach(msg, $2);
|
|
980
|
+
}
|
|
981
|
+
)cc",
|
|
982
|
+
msg_name, field->name(), layout.GetFieldOffset(field));
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
void GenerateMapGetters(const protobuf::FieldDescriptor* field,
|
|
986
|
+
const FileLayout& layout, absl::string_view msg_name,
|
|
987
|
+
Output& output) {
|
|
988
|
+
const protobuf::Descriptor* entry = field->message_type();
|
|
989
|
+
const protobuf::FieldDescriptor* key = entry->FindFieldByNumber(1);
|
|
990
|
+
const protobuf::FieldDescriptor* val = entry->FindFieldByNumber(2);
|
|
991
|
+
output(
|
|
992
|
+
R"cc(
|
|
993
|
+
UPB_INLINE size_t $0_$1_size(const $0* msg) {
|
|
994
|
+
return _upb_msg_map_size(msg, $2);
|
|
995
|
+
}
|
|
996
|
+
)cc",
|
|
997
|
+
msg_name, field->name(), layout.GetFieldOffset(field));
|
|
998
|
+
output(
|
|
999
|
+
R"cc(
|
|
1000
|
+
UPB_INLINE bool $0_$1_get(const $0* msg, $2 key, $3* val) {
|
|
1001
|
+
return _upb_msg_map_get(msg, $4, &key, $5, val, $6);
|
|
1002
|
+
}
|
|
1003
|
+
)cc",
|
|
1004
|
+
msg_name, field->name(), CType(key), CType(val),
|
|
1005
|
+
layout.GetFieldOffset(field),
|
|
1006
|
+
key->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING
|
|
1007
|
+
? "0"
|
|
1008
|
+
: "sizeof(key)",
|
|
1009
|
+
val->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING
|
|
1010
|
+
? "0"
|
|
1011
|
+
: "sizeof(*val)");
|
|
1012
|
+
output(
|
|
1013
|
+
R"cc(
|
|
1014
|
+
UPB_INLINE $0 $1_$2_next(const $1* msg, size_t* iter) {
|
|
1015
|
+
return ($0)_upb_msg_map_next(msg, $3, iter);
|
|
1016
|
+
}
|
|
1017
|
+
)cc",
|
|
1018
|
+
CTypeConst(field), msg_name, field->name(), layout.GetFieldOffset(field));
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
void GenerateMapEntryGetters(const protobuf::FieldDescriptor* field,
|
|
1022
|
+
absl::string_view msg_name, Output& output) {
|
|
1023
|
+
output(
|
|
1024
|
+
R"cc(
|
|
1025
|
+
UPB_INLINE $0 $1_$2(const $1* msg) {
|
|
1026
|
+
$3 ret;
|
|
1027
|
+
_upb_msg_map_$2(msg, &ret, $4);
|
|
1028
|
+
return ret;
|
|
1029
|
+
}
|
|
1030
|
+
)cc",
|
|
1031
|
+
CTypeConst(field), msg_name, field->name(), CType(field),
|
|
1032
|
+
field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING
|
|
1033
|
+
? "0"
|
|
1034
|
+
: "sizeof(ret)");
|
|
1035
|
+
}
|
|
1036
|
+
|
|
1037
|
+
void GenerateRepeatedGetters(const protobuf::FieldDescriptor* field,
|
|
1038
|
+
const FileLayout& layout,
|
|
1039
|
+
absl::string_view msg_name, Output& output) {
|
|
1040
|
+
output(
|
|
1041
|
+
R"cc(
|
|
1042
|
+
UPB_INLINE $0 const* $1_$2(const $1* msg, size_t* len) {
|
|
1043
|
+
return ($0 const*)_upb_array_accessor(msg, $3, len);
|
|
1044
|
+
}
|
|
1045
|
+
)cc",
|
|
1046
|
+
CTypeConst(field), msg_name, field->name(), layout.GetFieldOffset(field));
|
|
1047
|
+
}
|
|
1048
|
+
|
|
1049
|
+
void GenerateOneofGetters(const protobuf::FieldDescriptor* field,
|
|
1050
|
+
const FileLayout& layout, absl::string_view msg_name,
|
|
1051
|
+
Output& output) {
|
|
1052
|
+
output(
|
|
1053
|
+
R"cc(
|
|
1054
|
+
UPB_INLINE $0 $1_$2(const $1* msg) {
|
|
1055
|
+
return UPB_READ_ONEOF(msg, $0, $3, $4, $5, $6);
|
|
1056
|
+
}
|
|
1057
|
+
)cc",
|
|
1058
|
+
CTypeConst(field), msg_name, field->name(), layout.GetFieldOffset(field),
|
|
1059
|
+
layout.GetOneofCaseOffset(field->real_containing_oneof()),
|
|
1060
|
+
field->number(), FieldDefault(field));
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1063
|
+
void GenerateScalarGetters(const protobuf::FieldDescriptor* field,
|
|
1064
|
+
const FileLayout& layout, absl::string_view msg_name,
|
|
1065
|
+
Output& output) {
|
|
1066
|
+
if (HasNonZeroDefault(field)) {
|
|
1067
|
+
output(
|
|
1068
|
+
R"cc(
|
|
1069
|
+
UPB_INLINE $0 $1_$2(const $1* msg) {
|
|
1070
|
+
return $1_has_$2(msg) ? *UPB_PTR_AT(msg, $3, $0) : $4;
|
|
1071
|
+
}
|
|
1072
|
+
)cc",
|
|
1073
|
+
CTypeConst(field), msg_name, field->name(),
|
|
1074
|
+
layout.GetFieldOffset(field), FieldDefault(field));
|
|
1075
|
+
} else {
|
|
1076
|
+
output(
|
|
1077
|
+
R"cc(
|
|
1078
|
+
UPB_INLINE $0 $1_$2(const $1* msg) {
|
|
1079
|
+
return *UPB_PTR_AT(msg, $3, $0);
|
|
1080
|
+
}
|
|
1081
|
+
)cc",
|
|
1082
|
+
CTypeConst(field), msg_name, field->name(),
|
|
1083
|
+
layout.GetFieldOffset(field));
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
void GenerateGetters(const protobuf::FieldDescriptor* field,
|
|
1088
|
+
const FileLayout& layout, absl::string_view msg_name,
|
|
1089
|
+
Output& output) {
|
|
1090
|
+
if (field->is_map()) {
|
|
1091
|
+
GenerateMapGetters(field, layout, msg_name, output);
|
|
1092
|
+
} else if (field->containing_type()->options().map_entry()) {
|
|
1093
|
+
GenerateMapEntryGetters(field, msg_name, output);
|
|
1094
|
+
} else if (field->is_repeated()) {
|
|
1095
|
+
GenerateRepeatedGetters(field, layout, msg_name, output);
|
|
1096
|
+
} else if (field->real_containing_oneof()) {
|
|
1097
|
+
GenerateOneofGetters(field, layout, msg_name, output);
|
|
1098
|
+
} else {
|
|
1099
|
+
GenerateScalarGetters(field, layout, msg_name, output);
|
|
1100
|
+
}
|
|
1101
|
+
}
|
|
1102
|
+
|
|
1103
|
+
void GenerateMapSetters(const protobuf::FieldDescriptor* field,
|
|
1104
|
+
const FileLayout& layout, absl::string_view msg_name,
|
|
1105
|
+
Output& output) {
|
|
1106
|
+
const protobuf::Descriptor* entry = field->message_type();
|
|
1107
|
+
const protobuf::FieldDescriptor* key = entry->FindFieldByNumber(1);
|
|
1108
|
+
const protobuf::FieldDescriptor* val = entry->FindFieldByNumber(2);
|
|
1109
|
+
output(
|
|
1110
|
+
R"cc(
|
|
1111
|
+
UPB_INLINE void $0_$1_clear($0* msg) { _upb_msg_map_clear(msg, $2); }
|
|
1112
|
+
)cc",
|
|
1113
|
+
msg_name, field->name(), layout.GetFieldOffset(field));
|
|
1114
|
+
output(
|
|
1115
|
+
R"cc(
|
|
1116
|
+
UPB_INLINE bool $0_$1_set($0* msg, $2 key, $3 val, upb_Arena* a) {
|
|
1117
|
+
return _upb_msg_map_set(msg, $4, &key, $5, &val, $6, a);
|
|
1118
|
+
}
|
|
1119
|
+
)cc",
|
|
1120
|
+
msg_name, field->name(), CType(key), CType(val),
|
|
1121
|
+
layout.GetFieldOffset(field),
|
|
1122
|
+
key->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING
|
|
1123
|
+
? "0"
|
|
1124
|
+
: "sizeof(key)",
|
|
1125
|
+
val->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING
|
|
1126
|
+
? "0"
|
|
1127
|
+
: "sizeof(val)");
|
|
1128
|
+
output(
|
|
1129
|
+
R"cc(
|
|
1130
|
+
UPB_INLINE bool $0_$1_delete($0* msg, $2 key) {
|
|
1131
|
+
return _upb_msg_map_delete(msg, $3, &key, $4);
|
|
1132
|
+
}
|
|
1133
|
+
)cc",
|
|
1134
|
+
msg_name, field->name(), CType(key), layout.GetFieldOffset(field),
|
|
1135
|
+
key->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING
|
|
1136
|
+
? "0"
|
|
1137
|
+
: "sizeof(key)");
|
|
1138
|
+
output(
|
|
1139
|
+
R"cc(
|
|
1140
|
+
UPB_INLINE $0 $1_$2_nextmutable($1* msg, size_t* iter) {
|
|
1141
|
+
return ($0)_upb_msg_map_next(msg, $3, iter);
|
|
1142
|
+
}
|
|
1143
|
+
)cc",
|
|
1144
|
+
CType(field), msg_name, field->name(), layout.GetFieldOffset(field));
|
|
1145
|
+
}
|
|
1146
|
+
|
|
1147
|
+
void GenerateRepeatedSetters(const protobuf::FieldDescriptor* field,
|
|
1148
|
+
const FileLayout& layout,
|
|
1149
|
+
absl::string_view msg_name, Output& output) {
|
|
1150
|
+
output(
|
|
1151
|
+
R"cc(
|
|
1152
|
+
UPB_INLINE $0* $1_mutable_$2($1* msg, size_t* len) {
|
|
1153
|
+
return ($0*)_upb_array_mutable_accessor(msg, $3, len);
|
|
1154
|
+
}
|
|
1155
|
+
)cc",
|
|
1156
|
+
CType(field), msg_name, field->name(), layout.GetFieldOffset(field));
|
|
1157
|
+
output(
|
|
1158
|
+
R"cc(
|
|
1159
|
+
UPB_INLINE $0* $1_resize_$2($1* msg, size_t len, upb_Arena* arena) {
|
|
1160
|
+
return ($0*)_upb_Array_Resize_accessor2(msg, $3, len, $4, arena);
|
|
1161
|
+
}
|
|
1162
|
+
)cc",
|
|
1163
|
+
CType(field), msg_name, field->name(), layout.GetFieldOffset(field),
|
|
1164
|
+
SizeLg2(field));
|
|
1165
|
+
if (field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_MESSAGE) {
|
|
1166
|
+
output(
|
|
1167
|
+
R"cc(
|
|
1168
|
+
UPB_INLINE struct $0* $1_add_$2($1* msg, upb_Arena* arena) {
|
|
1169
|
+
struct $0* sub = (struct $0*)_upb_Message_New(&$3, arena);
|
|
1170
|
+
bool ok = _upb_Array_Append_accessor2(msg, $4, $5, &sub, arena);
|
|
1171
|
+
if (!ok) return NULL;
|
|
1172
|
+
return sub;
|
|
1173
|
+
}
|
|
1174
|
+
)cc",
|
|
1175
|
+
MessageName(field->message_type()), msg_name, field->name(),
|
|
1176
|
+
MessageInit(field->message_type()), layout.GetFieldOffset(field),
|
|
1177
|
+
SizeLg2(field));
|
|
1178
|
+
} else {
|
|
1179
|
+
output(
|
|
1180
|
+
R"cc(
|
|
1181
|
+
UPB_INLINE bool $1_add_$2($1* msg, $0 val, upb_Arena* arena) {
|
|
1182
|
+
return _upb_Array_Append_accessor2(msg, $3, $4, &val, arena);
|
|
1183
|
+
}
|
|
1184
|
+
)cc",
|
|
1185
|
+
CType(field), msg_name, field->name(), layout.GetFieldOffset(field),
|
|
1186
|
+
SizeLg2(field));
|
|
1187
|
+
}
|
|
1188
|
+
}
|
|
1189
|
+
|
|
1190
|
+
void GenerateNonRepeatedSetters(const protobuf::FieldDescriptor* field,
|
|
1191
|
+
const FileLayout& layout,
|
|
1192
|
+
absl::string_view msg_name, Output& output) {
|
|
1193
|
+
if (field == field->containing_type()->map_key()) {
|
|
1194
|
+
// Key cannot be mutated.
|
|
1195
|
+
return;
|
|
1196
|
+
}
|
|
1197
|
+
|
|
1198
|
+
// The common function signature for all setters. Varying
|
|
1199
|
+
// implementations follow.
|
|
1200
|
+
output("UPB_INLINE void $0_set_$1($0 *msg, $2 value) {\n", msg_name,
|
|
1201
|
+
field->name(), CType(field));
|
|
1202
|
+
|
|
1203
|
+
if (field == field->containing_type()->map_value()) {
|
|
1204
|
+
output(
|
|
1205
|
+
" _upb_msg_map_set_value(msg, &value, $0);\n"
|
|
1206
|
+
"}\n",
|
|
1207
|
+
field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING
|
|
1208
|
+
? "0"
|
|
1209
|
+
: "sizeof(" + CType(field) + ")");
|
|
1210
|
+
} else if (field->real_containing_oneof()) {
|
|
1211
|
+
output(
|
|
1212
|
+
" UPB_WRITE_ONEOF(msg, $0, $1, value, $2, $3);\n"
|
|
1213
|
+
"}\n",
|
|
1214
|
+
CType(field), layout.GetFieldOffset(field),
|
|
1215
|
+
layout.GetOneofCaseOffset(field->real_containing_oneof()),
|
|
1216
|
+
field->number());
|
|
1217
|
+
} else {
|
|
1218
|
+
if (layout.HasHasbit(field)) {
|
|
1219
|
+
output(" _upb_sethas(msg, $0);\n", layout.GetHasbitIndex(field));
|
|
1220
|
+
}
|
|
1221
|
+
output(
|
|
1222
|
+
" *UPB_PTR_AT(msg, $1, $0) = value;\n"
|
|
1223
|
+
"}\n",
|
|
1224
|
+
CType(field), layout.GetFieldOffset(field));
|
|
1225
|
+
}
|
|
1226
|
+
|
|
1227
|
+
// Message fields also have a Msg_mutable_foo() accessor that will create
|
|
1228
|
+
// the sub-message if it doesn't already exist.
|
|
1229
|
+
if (field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_MESSAGE &&
|
|
1230
|
+
!field->containing_type()->options().map_entry()) {
|
|
1231
|
+
output(
|
|
1232
|
+
R"cc(
|
|
1233
|
+
UPB_INLINE struct $0* $1_mutable_$2($1* msg, upb_Arena* arena) {
|
|
1234
|
+
struct $0* sub = (struct $0*)$1_$2(msg);
|
|
1235
|
+
if (sub == NULL) {
|
|
1236
|
+
sub = (struct $0*)_upb_Message_New(&$3, arena);
|
|
1237
|
+
if (!sub) return NULL;
|
|
1238
|
+
$1_set_$2(msg, sub);
|
|
1239
|
+
}
|
|
1240
|
+
return sub;
|
|
1241
|
+
}
|
|
1242
|
+
)cc",
|
|
1243
|
+
MessageName(field->message_type()), msg_name, field->name(),
|
|
1244
|
+
MessageInit(field->message_type()));
|
|
1245
|
+
}
|
|
1246
|
+
}
|
|
1247
|
+
|
|
1248
|
+
void GenerateSetters(const protobuf::FieldDescriptor* field,
|
|
1249
|
+
const FileLayout& layout, absl::string_view msg_name,
|
|
1250
|
+
Output& output) {
|
|
1251
|
+
if (field->is_map()) {
|
|
1252
|
+
GenerateMapSetters(field, layout, msg_name, output);
|
|
1253
|
+
} else if (field->is_repeated()) {
|
|
1254
|
+
GenerateRepeatedSetters(field, layout, msg_name, output);
|
|
1255
|
+
} else {
|
|
1256
|
+
GenerateNonRepeatedSetters(field, layout, msg_name, output);
|
|
1257
|
+
}
|
|
1258
|
+
}
|
|
1259
|
+
|
|
1260
|
+
void GenerateMessageInHeader(const protobuf::Descriptor* message,
|
|
1261
|
+
const FileLayout& layout, Output& output) {
|
|
1262
|
+
output("/* $0 */\n\n", message->full_name());
|
|
1263
|
+
std::string msg_name = ToCIdent(message->full_name());
|
|
1264
|
+
|
|
1265
|
+
if (!message->options().map_entry()) {
|
|
1266
|
+
GenerateMessageFunctionsInHeader(message, output);
|
|
1267
|
+
}
|
|
1268
|
+
|
|
1269
|
+
for (int i = 0; i < message->real_oneof_decl_count(); i++) {
|
|
1270
|
+
GenerateOneofInHeader(message->oneof_decl(i), layout, msg_name, output);
|
|
1271
|
+
}
|
|
1272
|
+
|
|
1273
|
+
for (auto field : FieldNumberOrder(message)) {
|
|
1274
|
+
GenerateHazzer(field, layout, msg_name, output);
|
|
1275
|
+
if (field->is_repeated()) {
|
|
1276
|
+
GenerateRepeatedClear(field, layout, msg_name, output);
|
|
1277
|
+
} else {
|
|
1278
|
+
GenerateClear(field, layout, msg_name, output);
|
|
1279
|
+
}
|
|
1280
|
+
GenerateGetters(field, layout, msg_name, output);
|
|
1281
|
+
}
|
|
1282
|
+
|
|
1283
|
+
output("\n");
|
|
1284
|
+
|
|
1285
|
+
for (auto field : FieldNumberOrder(message)) {
|
|
1286
|
+
GenerateSetters(field, layout, msg_name, output);
|
|
1287
|
+
}
|
|
1288
|
+
|
|
1289
|
+
output("\n");
|
|
1290
|
+
}
|
|
1291
|
+
|
|
1292
|
+
void WriteHeader(const FileLayout& layout, Output& output) {
|
|
1293
|
+
const protobuf::FileDescriptor* file = layout.descriptor();
|
|
1294
|
+
EmitFileWarning(file, output);
|
|
1295
|
+
output(
|
|
1296
|
+
"#ifndef $0_UPB_H_\n"
|
|
1297
|
+
"#define $0_UPB_H_\n\n"
|
|
1298
|
+
"#include \"upb/msg_internal.h\"\n"
|
|
1299
|
+
"#include \"upb/decode.h\"\n"
|
|
1300
|
+
"#include \"upb/decode_fast.h\"\n"
|
|
1301
|
+
"#include \"upb/encode.h\"\n\n",
|
|
1302
|
+
ToPreproc(file->name()));
|
|
1303
|
+
|
|
1304
|
+
for (int i = 0; i < file->public_dependency_count(); i++) {
|
|
1305
|
+
if (i == 0) {
|
|
1306
|
+
output("/* Public Imports. */\n");
|
|
1307
|
+
}
|
|
1308
|
+
output("#include \"$0\"\n", HeaderFilename(file));
|
|
1309
|
+
if (i == file->public_dependency_count() - 1) {
|
|
1310
|
+
output("\n");
|
|
1311
|
+
}
|
|
1312
|
+
}
|
|
1313
|
+
|
|
1314
|
+
output(
|
|
1315
|
+
"#include \"upb/port_def.inc\"\n"
|
|
1316
|
+
"\n"
|
|
1317
|
+
"#ifdef __cplusplus\n"
|
|
1318
|
+
"extern \"C\" {\n"
|
|
1319
|
+
"#endif\n"
|
|
1320
|
+
"\n");
|
|
1321
|
+
|
|
1322
|
+
const std::vector<const protobuf::Descriptor*> this_file_messages =
|
|
1323
|
+
SortedMessages(file);
|
|
1324
|
+
const std::vector<const protobuf::FieldDescriptor*> this_file_exts =
|
|
1325
|
+
SortedExtensions(file);
|
|
1326
|
+
|
|
1327
|
+
// Forward-declare types defined in this file.
|
|
1328
|
+
for (auto message : this_file_messages) {
|
|
1329
|
+
output("struct $0;\n", ToCIdent(message->full_name()));
|
|
1330
|
+
}
|
|
1331
|
+
for (auto message : this_file_messages) {
|
|
1332
|
+
output("typedef struct $0 $0;\n", ToCIdent(message->full_name()));
|
|
1333
|
+
}
|
|
1334
|
+
for (auto message : this_file_messages) {
|
|
1335
|
+
output("extern const upb_MiniTable $0;\n", MessageInit(message));
|
|
1336
|
+
}
|
|
1337
|
+
for (auto ext : this_file_exts) {
|
|
1338
|
+
output("extern const upb_MiniTable_Extension $0;\n", ExtensionLayout(ext));
|
|
1339
|
+
}
|
|
1340
|
+
|
|
1341
|
+
// Forward-declare types not in this file, but used as submessages.
|
|
1342
|
+
// Order by full name for consistent ordering.
|
|
1343
|
+
std::map<std::string, const protobuf::Descriptor*> forward_messages;
|
|
1344
|
+
|
|
1345
|
+
for (auto* message : this_file_messages) {
|
|
1346
|
+
for (int i = 0; i < message->field_count(); i++) {
|
|
1347
|
+
const protobuf::FieldDescriptor* field = message->field(i);
|
|
1348
|
+
if (field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_MESSAGE &&
|
|
1349
|
+
field->file() != field->message_type()->file()) {
|
|
1350
|
+
forward_messages[field->message_type()->full_name()] =
|
|
1351
|
+
field->message_type();
|
|
1352
|
+
}
|
|
1353
|
+
}
|
|
1354
|
+
}
|
|
1355
|
+
for (auto ext : this_file_exts) {
|
|
1356
|
+
if (ext->file() != ext->containing_type()->file()) {
|
|
1357
|
+
forward_messages[ext->containing_type()->full_name()] =
|
|
1358
|
+
ext->containing_type();
|
|
1359
|
+
}
|
|
1360
|
+
}
|
|
1361
|
+
for (const auto& pair : forward_messages) {
|
|
1362
|
+
output("struct $0;\n", MessageName(pair.second));
|
|
1363
|
+
}
|
|
1364
|
+
for (const auto& pair : forward_messages) {
|
|
1365
|
+
output("extern const upb_MiniTable $0;\n", MessageInit(pair.second));
|
|
1366
|
+
}
|
|
1367
|
+
|
|
1368
|
+
if (!this_file_messages.empty()) {
|
|
1369
|
+
output("\n");
|
|
1370
|
+
}
|
|
1371
|
+
|
|
1372
|
+
std::vector<const protobuf::EnumDescriptor*> this_file_enums =
|
|
1373
|
+
SortedEnums(file);
|
|
1374
|
+
std::sort(
|
|
1375
|
+
this_file_enums.begin(), this_file_enums.end(),
|
|
1376
|
+
[](const protobuf::EnumDescriptor* a, const protobuf::EnumDescriptor* b) {
|
|
1377
|
+
return a->full_name() < b->full_name();
|
|
1378
|
+
});
|
|
1379
|
+
|
|
1380
|
+
for (auto enumdesc : this_file_enums) {
|
|
1381
|
+
output("typedef enum {\n");
|
|
1382
|
+
DumpEnumValues(enumdesc, output);
|
|
1383
|
+
output("} $0;\n\n", ToCIdent(enumdesc->full_name()));
|
|
1384
|
+
}
|
|
1385
|
+
|
|
1386
|
+
output("\n");
|
|
1387
|
+
|
|
1388
|
+
if (file->syntax() == protobuf::FileDescriptor::SYNTAX_PROTO2) {
|
|
1389
|
+
for (const auto* enumdesc : this_file_enums) {
|
|
1390
|
+
output("extern const upb_MiniTable_Enum $0;\n", EnumInit(enumdesc));
|
|
1391
|
+
}
|
|
1392
|
+
}
|
|
1393
|
+
|
|
1394
|
+
output("\n");
|
|
1395
|
+
|
|
1396
|
+
for (auto message : this_file_messages) {
|
|
1397
|
+
GenerateMessageInHeader(message, layout, output);
|
|
1398
|
+
}
|
|
1399
|
+
|
|
1400
|
+
for (auto ext : this_file_exts) {
|
|
1401
|
+
GenerateExtensionInHeader(ext, output);
|
|
1402
|
+
}
|
|
1403
|
+
|
|
1404
|
+
output("extern const upb_MiniTable_File $0;\n\n", FileLayoutName(file));
|
|
1405
|
+
|
|
1406
|
+
if (file->name() ==
|
|
1407
|
+
protobuf::FileDescriptorProto::descriptor()->file()->name()) {
|
|
1408
|
+
// This is gratuitously inefficient with how many times it rebuilds
|
|
1409
|
+
// MessageLayout objects for the same message. But we only do this for one
|
|
1410
|
+
// proto (descriptor.proto) so we don't worry about it.
|
|
1411
|
+
const protobuf::Descriptor* max32_message = nullptr;
|
|
1412
|
+
const protobuf::Descriptor* max64_message = nullptr;
|
|
1413
|
+
size_t max32 = 0;
|
|
1414
|
+
size_t max64 = 0;
|
|
1415
|
+
for (const auto* message : this_file_messages) {
|
|
1416
|
+
if (absl::EndsWith(message->name(), "Options")) {
|
|
1417
|
+
size_t size32 = layout.GetMiniTable32(message)->size;
|
|
1418
|
+
size_t size64 = layout.GetMiniTable64(message)->size;
|
|
1419
|
+
if (size32 > max32) {
|
|
1420
|
+
max32 = size32;
|
|
1421
|
+
max32_message = message;
|
|
1422
|
+
}
|
|
1423
|
+
if (size64 > max64) {
|
|
1424
|
+
max64 = size64;
|
|
1425
|
+
max64_message = message;
|
|
1426
|
+
}
|
|
1427
|
+
}
|
|
1428
|
+
}
|
|
1429
|
+
|
|
1430
|
+
output("/* Max size 32 is $0 */\n", max32_message->full_name());
|
|
1431
|
+
output("/* Max size 64 is $0 */\n", max64_message->full_name());
|
|
1432
|
+
output("#define _UPB_MAXOPT_SIZE UPB_SIZE($0, $1)\n\n", max32, max64);
|
|
1433
|
+
}
|
|
1434
|
+
|
|
1435
|
+
output(
|
|
1436
|
+
"#ifdef __cplusplus\n"
|
|
1437
|
+
"} /* extern \"C\" */\n"
|
|
1438
|
+
"#endif\n"
|
|
1439
|
+
"\n"
|
|
1440
|
+
"#include \"upb/port_undef.inc\"\n"
|
|
1441
|
+
"\n"
|
|
1442
|
+
"#endif /* $0_UPB_H_ */\n",
|
|
1443
|
+
ToPreproc(file->name()));
|
|
1444
|
+
}
|
|
1445
|
+
|
|
1446
|
+
typedef std::pair<std::string, uint64_t> TableEntry;
|
|
1447
|
+
|
|
1448
|
+
uint64_t GetEncodedTag(const protobuf::FieldDescriptor* field) {
|
|
1449
|
+
protobuf::internal::WireFormatLite::WireType wire_type =
|
|
1450
|
+
protobuf::internal::WireFormat::WireTypeForField(field);
|
|
1451
|
+
uint32_t unencoded_tag =
|
|
1452
|
+
protobuf::internal::WireFormatLite::MakeTag(field->number(), wire_type);
|
|
1453
|
+
uint8_t tag_bytes[10] = {0};
|
|
1454
|
+
protobuf::io::CodedOutputStream::WriteVarint32ToArray(unencoded_tag,
|
|
1455
|
+
tag_bytes);
|
|
1456
|
+
uint64_t encoded_tag = 0;
|
|
1457
|
+
memcpy(&encoded_tag, tag_bytes, sizeof(encoded_tag));
|
|
1458
|
+
// TODO: byte-swap for big endian.
|
|
1459
|
+
return encoded_tag;
|
|
1460
|
+
}
|
|
1461
|
+
|
|
1462
|
+
int GetTableSlot(const protobuf::FieldDescriptor* field) {
|
|
1463
|
+
uint64_t tag = GetEncodedTag(field);
|
|
1464
|
+
if (tag > 0x7fff) {
|
|
1465
|
+
// Tag must fit within a two-byte varint.
|
|
1466
|
+
return -1;
|
|
1467
|
+
}
|
|
1468
|
+
return (tag & 0xf8) >> 3;
|
|
1469
|
+
}
|
|
1470
|
+
|
|
1471
|
+
bool TryFillTableEntry(const FileLayout& layout,
|
|
1472
|
+
const protobuf::FieldDescriptor* field,
|
|
1473
|
+
TableEntry& ent) {
|
|
1474
|
+
const upb_MiniTable* mt = layout.GetMiniTable64(field->containing_type());
|
|
1475
|
+
const upb_MiniTable_Field* mt_f =
|
|
1476
|
+
upb_MiniTable_FindFieldByNumber(mt, field->number());
|
|
1477
|
+
std::string type = "";
|
|
1478
|
+
std::string cardinality = "";
|
|
1479
|
+
switch (mt_f->descriptortype) {
|
|
1480
|
+
case kUpb_FieldType_Bool:
|
|
1481
|
+
type = "b1";
|
|
1482
|
+
break;
|
|
1483
|
+
case kUpb_FieldType_Enum:
|
|
1484
|
+
// We don't have the means to test proto2 enum fields for valid values.
|
|
1485
|
+
return false;
|
|
1486
|
+
case kUpb_FieldType_Int32:
|
|
1487
|
+
case kUpb_FieldType_UInt32:
|
|
1488
|
+
type = "v4";
|
|
1489
|
+
break;
|
|
1490
|
+
case kUpb_FieldType_Int64:
|
|
1491
|
+
case kUpb_FieldType_UInt64:
|
|
1492
|
+
type = "v8";
|
|
1493
|
+
break;
|
|
1494
|
+
case kUpb_FieldType_Fixed32:
|
|
1495
|
+
case kUpb_FieldType_SFixed32:
|
|
1496
|
+
case kUpb_FieldType_Float:
|
|
1497
|
+
type = "f4";
|
|
1498
|
+
break;
|
|
1499
|
+
case kUpb_FieldType_Fixed64:
|
|
1500
|
+
case kUpb_FieldType_SFixed64:
|
|
1501
|
+
case kUpb_FieldType_Double:
|
|
1502
|
+
type = "f8";
|
|
1503
|
+
break;
|
|
1504
|
+
case kUpb_FieldType_SInt32:
|
|
1505
|
+
type = "z4";
|
|
1506
|
+
break;
|
|
1507
|
+
case kUpb_FieldType_SInt64:
|
|
1508
|
+
type = "z8";
|
|
1509
|
+
break;
|
|
1510
|
+
case kUpb_FieldType_String:
|
|
1511
|
+
type = "s";
|
|
1512
|
+
break;
|
|
1513
|
+
case kUpb_FieldType_Bytes:
|
|
1514
|
+
type = "b";
|
|
1515
|
+
break;
|
|
1516
|
+
case kUpb_FieldType_Message:
|
|
1517
|
+
type = "m";
|
|
1518
|
+
break;
|
|
1519
|
+
default:
|
|
1520
|
+
return false; // Not supported yet.
|
|
1521
|
+
}
|
|
1522
|
+
|
|
1523
|
+
switch (upb_FieldMode_Get(mt_f)) {
|
|
1524
|
+
case kUpb_FieldMode_Map:
|
|
1525
|
+
return false; // Not supported yet (ever?).
|
|
1526
|
+
case kUpb_FieldMode_Array:
|
|
1527
|
+
if (mt_f->mode & kUpb_LabelFlags_IsPacked) {
|
|
1528
|
+
cardinality = "p";
|
|
1529
|
+
} else {
|
|
1530
|
+
cardinality = "r";
|
|
1531
|
+
}
|
|
1532
|
+
break;
|
|
1533
|
+
case kUpb_FieldMode_Scalar:
|
|
1534
|
+
if (mt_f->presence < 0) {
|
|
1535
|
+
cardinality = "o";
|
|
1536
|
+
} else {
|
|
1537
|
+
cardinality = "s";
|
|
1538
|
+
}
|
|
1539
|
+
break;
|
|
1540
|
+
}
|
|
1541
|
+
|
|
1542
|
+
uint64_t expected_tag = GetEncodedTag(field);
|
|
1543
|
+
|
|
1544
|
+
// Data is:
|
|
1545
|
+
//
|
|
1546
|
+
// 48 32 16 0
|
|
1547
|
+
// |--------|--------|--------|--------|--------|--------|--------|--------|
|
|
1548
|
+
// | offset (16) |case offset (16) |presence| submsg | exp. tag (16) |
|
|
1549
|
+
// |--------|--------|--------|--------|--------|--------|--------|--------|
|
|
1550
|
+
//
|
|
1551
|
+
// - |presence| is either hasbit index or field number for oneofs.
|
|
1552
|
+
|
|
1553
|
+
uint64_t data = static_cast<uint64_t>(mt_f->offset) << 48 | expected_tag;
|
|
1554
|
+
|
|
1555
|
+
if (field->is_repeated()) {
|
|
1556
|
+
// No hasbit/oneof-related fields.
|
|
1557
|
+
}
|
|
1558
|
+
if (field->real_containing_oneof()) {
|
|
1559
|
+
size_t case_offset = ~mt_f->presence;
|
|
1560
|
+
if (case_offset > 0xffff) return false;
|
|
1561
|
+
assert(field->number() < 256);
|
|
1562
|
+
data |= field->number() << 24;
|
|
1563
|
+
data |= case_offset << 32;
|
|
1564
|
+
} else {
|
|
1565
|
+
uint64_t hasbit_index = 63; // No hasbit (set a high, unused bit).
|
|
1566
|
+
if (mt_f->presence) {
|
|
1567
|
+
hasbit_index = mt_f->presence;
|
|
1568
|
+
if (hasbit_index > 31) return false;
|
|
1569
|
+
}
|
|
1570
|
+
data |= hasbit_index << 24;
|
|
1571
|
+
}
|
|
1572
|
+
|
|
1573
|
+
if (field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_MESSAGE) {
|
|
1574
|
+
uint64_t idx = mt_f->submsg_index;
|
|
1575
|
+
if (idx > 255) return false;
|
|
1576
|
+
data |= idx << 16;
|
|
1577
|
+
|
|
1578
|
+
std::string size_ceil = "max";
|
|
1579
|
+
size_t size = SIZE_MAX;
|
|
1580
|
+
if (field->message_type()->file() == field->file()) {
|
|
1581
|
+
// We can only be guaranteed the size of the sub-message if it is in the
|
|
1582
|
+
// same file as us. We could relax this to increase the speed of
|
|
1583
|
+
// cross-file sub-message parsing if we are comfortable requiring that
|
|
1584
|
+
// users compile all messages at the same time.
|
|
1585
|
+
const upb_MiniTable* sub_mt =
|
|
1586
|
+
layout.GetMiniTable64(field->message_type());
|
|
1587
|
+
size = sub_mt->size + 8;
|
|
1588
|
+
}
|
|
1589
|
+
std::vector<size_t> breaks = {64, 128, 192, 256};
|
|
1590
|
+
for (auto brk : breaks) {
|
|
1591
|
+
if (size <= brk) {
|
|
1592
|
+
size_ceil = std::to_string(brk);
|
|
1593
|
+
break;
|
|
1594
|
+
}
|
|
1595
|
+
}
|
|
1596
|
+
ent.first = absl::Substitute("upb_p$0$1_$2bt_max$3b", cardinality, type,
|
|
1597
|
+
expected_tag > 0xff ? "2" : "1", size_ceil);
|
|
1598
|
+
|
|
1599
|
+
} else {
|
|
1600
|
+
ent.first = absl::Substitute("upb_p$0$1_$2bt", cardinality, type,
|
|
1601
|
+
expected_tag > 0xff ? "2" : "1");
|
|
1602
|
+
}
|
|
1603
|
+
ent.second = data;
|
|
1604
|
+
return true;
|
|
1605
|
+
}
|
|
1606
|
+
|
|
1607
|
+
std::vector<TableEntry> FastDecodeTable(const protobuf::Descriptor* message,
|
|
1608
|
+
const FileLayout& layout) {
|
|
1609
|
+
std::vector<TableEntry> table;
|
|
1610
|
+
for (const auto field : FieldHotnessOrder(message)) {
|
|
1611
|
+
TableEntry ent;
|
|
1612
|
+
int slot = GetTableSlot(field);
|
|
1613
|
+
// std::cerr << "table slot: " << field->number() << ": " << slot << "\n";
|
|
1614
|
+
if (slot < 0) {
|
|
1615
|
+
// Tag can't fit in the table.
|
|
1616
|
+
continue;
|
|
1617
|
+
}
|
|
1618
|
+
if (!TryFillTableEntry(layout, field, ent)) {
|
|
1619
|
+
// Unsupported field type or offset, hasbit index, etc. doesn't fit.
|
|
1620
|
+
continue;
|
|
1621
|
+
}
|
|
1622
|
+
while ((size_t)slot >= table.size()) {
|
|
1623
|
+
size_t size = std::max(static_cast<size_t>(1), table.size() * 2);
|
|
1624
|
+
table.resize(size, TableEntry{"fastdecode_generic", 0});
|
|
1625
|
+
}
|
|
1626
|
+
if (table[slot].first != "fastdecode_generic") {
|
|
1627
|
+
// A hotter field already filled this slot.
|
|
1628
|
+
continue;
|
|
1629
|
+
}
|
|
1630
|
+
table[slot] = ent;
|
|
1631
|
+
}
|
|
1632
|
+
return table;
|
|
1633
|
+
}
|
|
1634
|
+
|
|
1635
|
+
// Returns the field mode as a string initializer.
|
|
1636
|
+
//
|
|
1637
|
+
// We could just emit this as a number (and we may yet go in that direction) but
|
|
1638
|
+
// for now emitting symbolic constants gives this better readability and
|
|
1639
|
+
// debuggability.
|
|
1640
|
+
std::string GetModeInit(uint8_t mode) {
|
|
1641
|
+
std::string ret;
|
|
1642
|
+
switch (mode & kUpb_FieldMode_Mask) {
|
|
1643
|
+
case kUpb_FieldMode_Map:
|
|
1644
|
+
ret = "kUpb_FieldMode_Map";
|
|
1645
|
+
break;
|
|
1646
|
+
case kUpb_FieldMode_Array:
|
|
1647
|
+
ret = "kUpb_FieldMode_Array";
|
|
1648
|
+
break;
|
|
1649
|
+
case kUpb_FieldMode_Scalar:
|
|
1650
|
+
ret = "kUpb_FieldMode_Scalar";
|
|
1651
|
+
break;
|
|
1652
|
+
default:
|
|
1653
|
+
break;
|
|
1654
|
+
}
|
|
1655
|
+
|
|
1656
|
+
if (mode & kUpb_LabelFlags_IsPacked) {
|
|
1657
|
+
absl::StrAppend(&ret, " | kUpb_LabelFlags_IsPacked");
|
|
1658
|
+
}
|
|
1659
|
+
|
|
1660
|
+
if (mode & kUpb_LabelFlags_IsExtension) {
|
|
1661
|
+
absl::StrAppend(&ret, " | kUpb_LabelFlags_IsExtension");
|
|
1662
|
+
}
|
|
1663
|
+
|
|
1664
|
+
std::string rep;
|
|
1665
|
+
switch (mode >> kUpb_FieldRep_Shift) {
|
|
1666
|
+
case kUpb_FieldRep_1Byte:
|
|
1667
|
+
rep = "kUpb_FieldRep_1Byte";
|
|
1668
|
+
break;
|
|
1669
|
+
case kUpb_FieldRep_4Byte:
|
|
1670
|
+
rep = "kUpb_FieldRep_4Byte";
|
|
1671
|
+
break;
|
|
1672
|
+
case kUpb_FieldRep_Pointer:
|
|
1673
|
+
rep = "kUpb_FieldRep_Pointer";
|
|
1674
|
+
break;
|
|
1675
|
+
case kUpb_FieldRep_StringView:
|
|
1676
|
+
rep = "kUpb_FieldRep_StringView";
|
|
1677
|
+
break;
|
|
1678
|
+
case kUpb_FieldRep_8Byte:
|
|
1679
|
+
rep = "kUpb_FieldRep_8Byte";
|
|
1680
|
+
break;
|
|
1681
|
+
}
|
|
1682
|
+
|
|
1683
|
+
absl::StrAppend(&ret, " | (", rep, " << kUpb_FieldRep_Shift)");
|
|
1684
|
+
return ret;
|
|
1685
|
+
}
|
|
1686
|
+
|
|
1687
|
+
void WriteField(const upb_MiniTable_Field* field64,
|
|
1688
|
+
const upb_MiniTable_Field* field32, Output& output) {
|
|
1689
|
+
output("{$0, UPB_SIZE($1, $2), UPB_SIZE($3, $4), $5, $6, $7}",
|
|
1690
|
+
field64->number, field32->offset, field64->offset, field32->presence,
|
|
1691
|
+
field64->presence,
|
|
1692
|
+
field64->submsg_index == kUpb_NoSub
|
|
1693
|
+
? "kUpb_NoSub"
|
|
1694
|
+
: absl::StrCat(field64->submsg_index).c_str(),
|
|
1695
|
+
field64->descriptortype, GetModeInit(field64->mode));
|
|
1696
|
+
}
|
|
1697
|
+
|
|
1698
|
+
// Writes a single field into a .upb.c source file.
|
|
1699
|
+
void WriteMessageField(const upb_MiniTable_Field* field64,
|
|
1700
|
+
const upb_MiniTable_Field* field32, Output& output) {
|
|
1701
|
+
output(" ");
|
|
1702
|
+
WriteField(field64, field32, output);
|
|
1703
|
+
output(",\n");
|
|
1704
|
+
}
|
|
1705
|
+
|
|
1706
|
+
// Writes a single message into a .upb.c source file.
|
|
1707
|
+
void WriteMessage(const protobuf::Descriptor* message, const FileLayout& layout,
|
|
1708
|
+
Output& output, bool fasttable_enabled) {
|
|
1709
|
+
std::string msg_name = ToCIdent(message->full_name());
|
|
1710
|
+
std::string fields_array_ref = "NULL";
|
|
1711
|
+
std::string submsgs_array_ref = "NULL";
|
|
1712
|
+
std::string subenums_array_ref = "NULL";
|
|
1713
|
+
const upb_MiniTable* mt_32 = layout.GetMiniTable32(message);
|
|
1714
|
+
const upb_MiniTable* mt_64 = layout.GetMiniTable64(message);
|
|
1715
|
+
std::vector<std::string> subs;
|
|
1716
|
+
|
|
1717
|
+
for (int i = 0; i < mt_64->field_count; i++) {
|
|
1718
|
+
const upb_MiniTable_Field* f = &mt_64->fields[i];
|
|
1719
|
+
if (f->submsg_index != kUpb_NoSub) {
|
|
1720
|
+
subs.push_back(FilePlatformLayout::GetSub(mt_64->subs[f->submsg_index]));
|
|
1721
|
+
}
|
|
1722
|
+
}
|
|
1723
|
+
|
|
1724
|
+
if (!subs.empty()) {
|
|
1725
|
+
std::string submsgs_array_name = msg_name + "_submsgs";
|
|
1726
|
+
submsgs_array_ref = "&" + submsgs_array_name + "[0]";
|
|
1727
|
+
output("static const upb_MiniTable_Sub $0[$1] = {\n", submsgs_array_name,
|
|
1728
|
+
subs.size());
|
|
1729
|
+
|
|
1730
|
+
for (const auto& sub : subs) {
|
|
1731
|
+
output(" $0,\n", sub);
|
|
1732
|
+
}
|
|
1733
|
+
|
|
1734
|
+
output("};\n\n");
|
|
1735
|
+
}
|
|
1736
|
+
|
|
1737
|
+
if (mt_64->field_count > 0) {
|
|
1738
|
+
std::string fields_array_name = msg_name + "__fields";
|
|
1739
|
+
fields_array_ref = "&" + fields_array_name + "[0]";
|
|
1740
|
+
output("static const upb_MiniTable_Field $0[$1] = {\n", fields_array_name,
|
|
1741
|
+
mt_64->field_count);
|
|
1742
|
+
for (int i = 0; i < mt_64->field_count; i++) {
|
|
1743
|
+
WriteMessageField(&mt_64->fields[i], &mt_32->fields[i], output);
|
|
1744
|
+
}
|
|
1745
|
+
output("};\n\n");
|
|
1746
|
+
}
|
|
1747
|
+
|
|
1748
|
+
std::vector<TableEntry> table;
|
|
1749
|
+
uint8_t table_mask = -1;
|
|
1750
|
+
|
|
1751
|
+
if (fasttable_enabled) {
|
|
1752
|
+
table = FastDecodeTable(message, layout);
|
|
1753
|
+
}
|
|
1754
|
+
|
|
1755
|
+
if (table.size() > 1) {
|
|
1756
|
+
assert((table.size() & (table.size() - 1)) == 0);
|
|
1757
|
+
table_mask = (table.size() - 1) << 3;
|
|
1758
|
+
}
|
|
1759
|
+
|
|
1760
|
+
std::string msgext = "kUpb_ExtMode_NonExtendable";
|
|
1761
|
+
|
|
1762
|
+
if (message->extension_range_count()) {
|
|
1763
|
+
if (message->options().message_set_wire_format()) {
|
|
1764
|
+
msgext = "kUpb_ExtMode_IsMessageSet";
|
|
1765
|
+
} else {
|
|
1766
|
+
msgext = "kUpb_ExtMode_Extendable";
|
|
1767
|
+
}
|
|
1768
|
+
}
|
|
1769
|
+
|
|
1770
|
+
output("const upb_MiniTable $0 = {\n", MessageInit(message));
|
|
1771
|
+
output(" $0,\n", submsgs_array_ref);
|
|
1772
|
+
output(" $0,\n", fields_array_ref);
|
|
1773
|
+
output(" $0, $1, $2, $3, $4, $5,\n", layout.GetMessageSize(message),
|
|
1774
|
+
mt_64->field_count, msgext, mt_64->dense_below, table_mask,
|
|
1775
|
+
mt_64->required_count);
|
|
1776
|
+
if (!table.empty()) {
|
|
1777
|
+
output(" UPB_FASTTABLE_INIT({\n");
|
|
1778
|
+
for (const auto& ent : table) {
|
|
1779
|
+
output(" {0x$1, &$0},\n", ent.first,
|
|
1780
|
+
absl::StrCat(absl::Hex(ent.second, absl::kZeroPad16)));
|
|
1781
|
+
}
|
|
1782
|
+
output(" }),\n");
|
|
1783
|
+
}
|
|
1784
|
+
output("};\n\n");
|
|
1785
|
+
}
|
|
1786
|
+
|
|
1787
|
+
void WriteEnum(const upb_MiniTable_Enum* mt, const protobuf::EnumDescriptor* e,
|
|
1788
|
+
Output& output) {
|
|
1789
|
+
std::string values_init = "NULL";
|
|
1790
|
+
|
|
1791
|
+
if (mt->value_count) {
|
|
1792
|
+
values_init = EnumInit(e) + "_values";
|
|
1793
|
+
output("static const int32_t $0[$1] = {\n", values_init, mt->value_count);
|
|
1794
|
+
for (int i = 0; i < mt->value_count; i++) {
|
|
1795
|
+
output(" $0,\n", mt->values[i]);
|
|
1796
|
+
}
|
|
1797
|
+
output("};\n\n");
|
|
1798
|
+
}
|
|
1799
|
+
|
|
1800
|
+
output(
|
|
1801
|
+
R"cc(
|
|
1802
|
+
const upb_MiniTable_Enum $0 = {
|
|
1803
|
+
$1,
|
|
1804
|
+
$2,
|
|
1805
|
+
$3,
|
|
1806
|
+
};
|
|
1807
|
+
)cc",
|
|
1808
|
+
EnumInit(e), values_init, absl::StrCat("0x", absl::Hex(mt->mask), "ULL"),
|
|
1809
|
+
mt->value_count);
|
|
1810
|
+
output("\n");
|
|
1811
|
+
}
|
|
1812
|
+
|
|
1813
|
+
int WriteEnums(const FileLayout& layout, Output& output) {
|
|
1814
|
+
const protobuf::FileDescriptor* file = layout.descriptor();
|
|
1815
|
+
|
|
1816
|
+
if (file->syntax() != protobuf::FileDescriptor::SYNTAX_PROTO2) {
|
|
1817
|
+
return 0;
|
|
1818
|
+
}
|
|
1819
|
+
|
|
1820
|
+
std::vector<const protobuf::EnumDescriptor*> this_file_enums =
|
|
1821
|
+
SortedEnums(file);
|
|
1822
|
+
|
|
1823
|
+
for (const auto* e : this_file_enums) {
|
|
1824
|
+
WriteEnum(layout.GetEnumTable(e), e, output);
|
|
1825
|
+
}
|
|
1826
|
+
|
|
1827
|
+
if (!this_file_enums.empty()) {
|
|
1828
|
+
output("static const upb_MiniTable_Enum *$0[$1] = {\n", kEnumsInit,
|
|
1829
|
+
this_file_enums.size());
|
|
1830
|
+
for (const auto* e : this_file_enums) {
|
|
1831
|
+
output(" &$0,\n", EnumInit(e));
|
|
1832
|
+
}
|
|
1833
|
+
output("};\n");
|
|
1834
|
+
output("\n");
|
|
1835
|
+
}
|
|
1836
|
+
|
|
1837
|
+
return this_file_enums.size();
|
|
1838
|
+
}
|
|
1839
|
+
|
|
1840
|
+
int WriteMessages(const FileLayout& layout, Output& output,
|
|
1841
|
+
bool fasttable_enabled) {
|
|
1842
|
+
const protobuf::FileDescriptor* file = layout.descriptor();
|
|
1843
|
+
std::vector<const protobuf::Descriptor*> file_messages = SortedMessages(file);
|
|
1844
|
+
|
|
1845
|
+
if (file_messages.empty()) return 0;
|
|
1846
|
+
|
|
1847
|
+
for (auto message : file_messages) {
|
|
1848
|
+
WriteMessage(message, layout, output, fasttable_enabled);
|
|
1849
|
+
}
|
|
1850
|
+
|
|
1851
|
+
output("static const upb_MiniTable *$0[$1] = {\n", kMessagesInit,
|
|
1852
|
+
file_messages.size());
|
|
1853
|
+
for (auto message : file_messages) {
|
|
1854
|
+
output(" &$0,\n", MessageInit(message));
|
|
1855
|
+
}
|
|
1856
|
+
output("};\n");
|
|
1857
|
+
output("\n");
|
|
1858
|
+
return file_messages.size();
|
|
1859
|
+
}
|
|
1860
|
+
|
|
1861
|
+
void WriteExtension(const upb_MiniTable_Extension* ext, Output& output) {
|
|
1862
|
+
WriteField(&ext->field, &ext->field, output);
|
|
1863
|
+
output(",\n");
|
|
1864
|
+
output(" &$0,\n", reinterpret_cast<const char*>(ext->extendee));
|
|
1865
|
+
output(" $0,\n", FilePlatformLayout::GetSub(ext->sub));
|
|
1866
|
+
}
|
|
1867
|
+
|
|
1868
|
+
int WriteExtensions(const FileLayout& layout, Output& output) {
|
|
1869
|
+
auto exts = SortedExtensions(layout.descriptor());
|
|
1870
|
+
absl::flat_hash_set<const protobuf::Descriptor*> forward_decls;
|
|
1871
|
+
|
|
1872
|
+
if (exts.empty()) return 0;
|
|
1873
|
+
|
|
1874
|
+
// Order by full name for consistent ordering.
|
|
1875
|
+
std::map<std::string, const protobuf::Descriptor*> forward_messages;
|
|
1876
|
+
|
|
1877
|
+
for (auto ext : exts) {
|
|
1878
|
+
forward_messages[ext->containing_type()->full_name()] =
|
|
1879
|
+
ext->containing_type();
|
|
1880
|
+
if (ext->message_type()) {
|
|
1881
|
+
forward_messages[ext->message_type()->full_name()] = ext->message_type();
|
|
1882
|
+
}
|
|
1883
|
+
}
|
|
1884
|
+
|
|
1885
|
+
for (const auto& decl : forward_messages) {
|
|
1886
|
+
output("extern const upb_MiniTable $0;\n", MessageInit(decl.second));
|
|
1887
|
+
}
|
|
1888
|
+
|
|
1889
|
+
for (auto ext : exts) {
|
|
1890
|
+
output("const upb_MiniTable_Extension $0 = {\n ", ExtensionLayout(ext));
|
|
1891
|
+
WriteExtension(layout.GetExtension(ext), output);
|
|
1892
|
+
output("\n};\n");
|
|
1893
|
+
}
|
|
1894
|
+
|
|
1895
|
+
output(
|
|
1896
|
+
"\n"
|
|
1897
|
+
"static const upb_MiniTable_Extension *$0[$1] = {\n",
|
|
1898
|
+
kExtensionsInit, exts.size());
|
|
1899
|
+
|
|
1900
|
+
for (auto ext : exts) {
|
|
1901
|
+
output(" &$0,\n", ExtensionLayout(ext));
|
|
1902
|
+
}
|
|
1903
|
+
|
|
1904
|
+
output(
|
|
1905
|
+
"};\n"
|
|
1906
|
+
"\n");
|
|
1907
|
+
return exts.size();
|
|
1908
|
+
}
|
|
1909
|
+
|
|
1910
|
+
// Writes a .upb.c source file.
|
|
1911
|
+
void WriteSource(const FileLayout& layout, Output& output,
|
|
1912
|
+
bool fasttable_enabled) {
|
|
1913
|
+
const protobuf::FileDescriptor* file = layout.descriptor();
|
|
1914
|
+
EmitFileWarning(file, output);
|
|
1915
|
+
|
|
1916
|
+
output(
|
|
1917
|
+
"#include <stddef.h>\n"
|
|
1918
|
+
"#include \"upb/msg_internal.h\"\n"
|
|
1919
|
+
"#include \"$0\"\n",
|
|
1920
|
+
HeaderFilename(file));
|
|
1921
|
+
|
|
1922
|
+
for (int i = 0; i < file->dependency_count(); i++) {
|
|
1923
|
+
output("#include \"$0\"\n", HeaderFilename(file->dependency(i)));
|
|
1924
|
+
}
|
|
1925
|
+
|
|
1926
|
+
output(
|
|
1927
|
+
"\n"
|
|
1928
|
+
"#include \"upb/port_def.inc\"\n"
|
|
1929
|
+
"\n");
|
|
1930
|
+
|
|
1931
|
+
int msg_count = WriteMessages(layout, output, fasttable_enabled);
|
|
1932
|
+
int ext_count = WriteExtensions(layout, output);
|
|
1933
|
+
int enum_count = WriteEnums(layout, output);
|
|
1934
|
+
|
|
1935
|
+
output("const upb_MiniTable_File $0 = {\n", FileLayoutName(file));
|
|
1936
|
+
output(" $0,\n", msg_count ? kMessagesInit : "NULL");
|
|
1937
|
+
output(" $0,\n", enum_count ? kEnumsInit : "NULL");
|
|
1938
|
+
output(" $0,\n", ext_count ? kExtensionsInit : "NULL");
|
|
1939
|
+
output(" $0,\n", msg_count);
|
|
1940
|
+
output(" $0,\n", enum_count);
|
|
1941
|
+
output(" $0,\n", ext_count);
|
|
1942
|
+
output("};\n\n");
|
|
1943
|
+
|
|
1944
|
+
output("#include \"upb/port_undef.inc\"\n");
|
|
1945
|
+
output("\n");
|
|
1946
|
+
}
|
|
1947
|
+
|
|
1948
|
+
class Generator : public protoc::CodeGenerator {
|
|
1949
|
+
~Generator() override {}
|
|
1950
|
+
bool Generate(const protobuf::FileDescriptor* file,
|
|
1951
|
+
const std::string& parameter, protoc::GeneratorContext* context,
|
|
1952
|
+
std::string* error) const override;
|
|
1953
|
+
uint64_t GetSupportedFeatures() const override {
|
|
1954
|
+
return FEATURE_PROTO3_OPTIONAL;
|
|
1955
|
+
}
|
|
1956
|
+
};
|
|
1957
|
+
|
|
1958
|
+
bool Generator::Generate(const protobuf::FileDescriptor* file,
|
|
1959
|
+
const std::string& parameter,
|
|
1960
|
+
protoc::GeneratorContext* context,
|
|
1961
|
+
std::string* error) const {
|
|
1962
|
+
bool fasttable_enabled = false;
|
|
1963
|
+
std::vector<std::pair<std::string, std::string>> params;
|
|
1964
|
+
google::protobuf::compiler::ParseGeneratorParameter(parameter, ¶ms);
|
|
1965
|
+
|
|
1966
|
+
for (const auto& pair : params) {
|
|
1967
|
+
if (pair.first == "fasttable") {
|
|
1968
|
+
fasttable_enabled = true;
|
|
1969
|
+
} else {
|
|
1970
|
+
*error = "Unknown parameter: " + pair.first;
|
|
1971
|
+
return false;
|
|
1972
|
+
}
|
|
1973
|
+
}
|
|
1974
|
+
|
|
1975
|
+
FileLayout layout(file);
|
|
1976
|
+
|
|
1977
|
+
std::unique_ptr<protobuf::io::ZeroCopyOutputStream> h_output_stream(
|
|
1978
|
+
context->Open(HeaderFilename(file)));
|
|
1979
|
+
Output h_output(h_output_stream.get());
|
|
1980
|
+
WriteHeader(layout, h_output);
|
|
1981
|
+
|
|
1982
|
+
std::unique_ptr<protobuf::io::ZeroCopyOutputStream> c_output_stream(
|
|
1983
|
+
context->Open(SourceFilename(file)));
|
|
1984
|
+
Output c_output(c_output_stream.get());
|
|
1985
|
+
WriteSource(layout, c_output, fasttable_enabled);
|
|
1986
|
+
|
|
1987
|
+
return true;
|
|
1988
|
+
}
|
|
1989
|
+
|
|
1990
|
+
} // namespace
|
|
1991
|
+
} // namespace upbc
|
|
1992
|
+
|
|
1993
|
+
int main(int argc, char** argv) {
|
|
1994
|
+
std::unique_ptr<google::protobuf::compiler::CodeGenerator> generator(
|
|
1995
|
+
new upbc::Generator());
|
|
1996
|
+
return google::protobuf::compiler::PluginMain(argc, argv, generator.get());
|
|
1997
|
+
}
|