mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-19 00:41:43 +00:00
[wpiutil,glass,dlt] Replace libprotobuf with upb for dynamic decode (#7988)
libprotobuf is a very annoying dependency to deal with, and with the switch to nanopb for generated C++ code, libprotobuf is only used for dynamic decode in the GUI apps. libprotobuf has been swapped out with upb, a much smaller C-based library that supports reflection and can therefore do dynamic decode. This means we can remove the libprotobuf dependency and stop dealing with build issues because of it.
This commit is contained in:
2
.github/workflows/cmake-android.yml
vendored
2
.github/workflows/cmake-android.yml
vendored
@@ -45,7 +45,7 @@ jobs:
|
||||
run: sudo apt-get update && sudo apt-get install -y ninja-build
|
||||
|
||||
- name: configure
|
||||
run: cmake --preset with-sccache -DCMAKE_BUILD_TYPE=RelWithDebInfo -DWITH_WPILIB=OFF -DWITH_GUI=OFF -DWITH_CSCORE=OFF -DWITH_TESTS=OFF -DWITH_SIMULATION_MODULES=OFF -DWITH_PROTOBUF=OFF -DWITH_JAVA=ON -DBUILD_SHARED_LIBS=ON -DCMAKE_TOOLCHAIN_FILE=${{ steps.setup-ndk.outputs.ndk-path }}/build/cmake/android.toolchain.cmake -DANDROID_ABI="${{ matrix.abi }}" -DANDROID_PLATFORM=android-24
|
||||
run: cmake --preset with-sccache -DCMAKE_BUILD_TYPE=RelWithDebInfo -DWITH_WPILIB=OFF -DWITH_GUI=OFF -DWITH_CSCORE=OFF -DWITH_TESTS=OFF -DWITH_SIMULATION_MODULES=OFF -DWITH_JAVA=ON -DBUILD_SHARED_LIBS=ON -DCMAKE_TOOLCHAIN_FILE=${{ steps.setup-ndk.outputs.ndk-path }}/build/cmake/android.toolchain.cmake -DANDROID_ABI="${{ matrix.abi }}" -DANDROID_PLATFORM=android-24
|
||||
|
||||
- name: build
|
||||
run: cmake --build build-cmake --parallel $(nproc)
|
||||
|
||||
5
.github/workflows/cmake.yml
vendored
5
.github/workflows/cmake.yml
vendored
@@ -23,7 +23,6 @@ jobs:
|
||||
- os: macOS-14
|
||||
name: macOS
|
||||
container: ""
|
||||
env: ""
|
||||
flags: "--preset with-sccache -DCMAKE_BUILD_TYPE=Release -DWITH_EXAMPLES=ON"
|
||||
- os: windows-2022
|
||||
name: Windows
|
||||
@@ -36,11 +35,11 @@ jobs:
|
||||
steps:
|
||||
- name: Install dependencies (Linux)
|
||||
if: runner.os == 'Linux'
|
||||
run: sudo apt-get update && sudo apt-get install -y libopencv-dev libopencv-java libprotobuf-dev protobuf-compiler ninja-build
|
||||
run: sudo apt-get update && sudo apt-get install -y libopencv-dev libopencv-java ninja-build
|
||||
|
||||
- name: Install dependencies (macOS)
|
||||
if: runner.os == 'macOS'
|
||||
run: brew install opencv protobuf@29 ninja
|
||||
run: brew install opencv ninja
|
||||
|
||||
- uses: ilammy/msvc-dev-cmd@v1.13.0
|
||||
if: runner.os == 'Windows'
|
||||
|
||||
2
.github/workflows/sanitizers.yml
vendored
2
.github/workflows/sanitizers.yml
vendored
@@ -33,7 +33,7 @@ jobs:
|
||||
container: wpilib/roborio-cross-ubuntu:2025-24.04
|
||||
steps:
|
||||
- name: Install Dependencies
|
||||
run: sudo apt-get update && sudo apt-get install -y libopencv-dev libopencv-java clang-18 libprotobuf-dev protobuf-compiler ninja-build
|
||||
run: sudo apt-get update && sudo apt-get install -y libopencv-dev libopencv-java clang-18 ninja-build
|
||||
|
||||
- name: Install sccache
|
||||
uses: mozilla-actions/sccache-action@v0.0.9
|
||||
|
||||
12
.github/workflows/upstream-utils.yml
vendored
12
.github/workflows/upstream-utils.yml
vendored
@@ -120,12 +120,6 @@ jobs:
|
||||
./mpack.py clone
|
||||
./mpack.py copy-src
|
||||
./mpack.py format-patch
|
||||
- name: Run protobuf.py
|
||||
run: |
|
||||
cd upstream_utils
|
||||
./protobuf.py clone
|
||||
./protobuf.py copy-src
|
||||
./protobuf.py format-patch
|
||||
- name: Run sleipnir.py
|
||||
run: |
|
||||
cd upstream_utils
|
||||
@@ -138,6 +132,12 @@ jobs:
|
||||
./stb.py clone
|
||||
./stb.py copy-src
|
||||
./stb.py format-patch
|
||||
- name: Run upb.py
|
||||
run: |
|
||||
cd upstream_utils
|
||||
./upb.py clone
|
||||
./upb.py copy-src
|
||||
./upb.py format-patch
|
||||
- name: Add untracked files to index so they count as changes
|
||||
run: git add -A
|
||||
- name: Check output
|
||||
|
||||
@@ -35,7 +35,6 @@ includeOtherLibs {
|
||||
^cscore
|
||||
^fmt/
|
||||
^glass/
|
||||
^google/
|
||||
^gtest/
|
||||
^hal/
|
||||
^imgui
|
||||
@@ -47,6 +46,7 @@ includeOtherLibs {
|
||||
^support/
|
||||
^units/
|
||||
^unsupported/
|
||||
^upb/
|
||||
^vision/
|
||||
^wpi/
|
||||
^wpigui
|
||||
|
||||
@@ -90,7 +90,6 @@ option(WITH_EXAMPLES "Build examples" OFF)
|
||||
option(WITH_TESTS "Build unit tests (requires internet connection)" ON)
|
||||
option(WITH_GUI "Build GUI items" ON)
|
||||
option(WITH_SIMULATION_MODULES "Build simulation modules" ON)
|
||||
option(WITH_PROTOBUF "Build protobuf support" ON)
|
||||
option(WITH_BENCHMARK "Build the benchmark project" ON)
|
||||
|
||||
# Options for using a package manager (e.g., vcpkg) for certain dependencies.
|
||||
@@ -151,14 +150,6 @@ endif()
|
||||
|
||||
find_package(LIBSSH CONFIG 0.7.1)
|
||||
|
||||
set(CMAKE_FIND_PACKAGE_PREFER_CONFIG ON)
|
||||
if(WITH_PROTOBUF)
|
||||
set(protobuf_MODULE_COMPATIBLE ON CACHE BOOL "" FORCE)
|
||||
find_package(Protobuf REQUIRED)
|
||||
find_program(PROTOC_COMPILER protoc REQUIRED)
|
||||
endif()
|
||||
set(CMAKE_FIND_PACKAGE_PREFER_CONFIG OFF)
|
||||
|
||||
get_property(isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
|
||||
|
||||
if(isMultiConfig)
|
||||
|
||||
@@ -31,8 +31,6 @@ By default, all libraries get built with a default CMake setup. The libraries ar
|
||||
|
||||
## Prerequisites
|
||||
|
||||
The protobuf library and compiler are needed for protobuf generation.
|
||||
|
||||
OpenCV needs to be findable by CMake. On systems like the Jetson, this is installed by default. Otherwise, you will need to build OpenCV from source and install it.
|
||||
|
||||
If you want JNI and Java, you will need a JDK of at least version 21 installed. In addition, you need a `JAVA_HOME` environment variable set properly and set to the JDK directory.
|
||||
@@ -65,8 +63,6 @@ The following build options are available:
|
||||
* This option will build the HAL and wpilibc/j during the build. The HAL is the simulation HAL, unless the external HAL options are used. The CMake build has no capability to build for the roboRIO.
|
||||
* `WITH_WPIMATH` (ON Default)
|
||||
* This option will build the wpimath library. This option must be on to build wpilib.
|
||||
* `WITH_PROTOBUF` (ON Default)
|
||||
* This option will build with the protobuf library.
|
||||
* `WITH_WPIUNITS` (`WITH_JAVA` Default)
|
||||
* This option will build the wpiunits library. This option must be on to build the Java wpimath library and requires `WITH_JAVA` to also be on.
|
||||
* `OPENCV_JAVA_INSTALL_DIR`
|
||||
@@ -90,8 +86,6 @@ If you want to change any of the options, add `-DOPTIONHERE=VALUE` to the `cmake
|
||||
|
||||
If you want, you can also use `ccmake` in order to visually set these properties as well. [Here](https://cmake.org/cmake/help/v3.0/manual/ccmake.1.html) is the link to the documentation for that program. On Windows, you can use `cmake-gui` instead.
|
||||
|
||||
Note that if you are cross-compiling, you will need to override the protobuf options manually to point to the libraries for the target platform. Leave the protoc binary location as the path to the binary for the host platform, since protoc needs to execute on the host platform.
|
||||
|
||||
## Presets
|
||||
|
||||
The WPILib CMake setup has a variety of presets for common configurations and options used. The default sets the generator to Ninja and build directory to `build-cmake`. The other presets are `with-java` (sets `WITH_JAVA=ON`), `sccache` (sets the C/C++ compiler launcher to sccache), and `with-java-sccache` (a comibination of `with-java` and `sccache`.
|
||||
@@ -118,7 +112,7 @@ sudo cmake --build . --target install
|
||||
|
||||
## Preparing to use the installed libraries
|
||||
|
||||
On Windows, make sure the directories for the libraries you built are on PATH. For wpilib, the default install location is `C:\Program Files (x86)\allwpilib`. If you built other libraries like OpenCV and protobuf from source, install them, and add the install directories to PATH. This ensures CMake can locate the libraries.
|
||||
On Windows, make sure the directories for the libraries you built are on PATH. For wpilib, the default install location is `C:\Program Files (x86)\allwpilib`. If you built other libraries like OpenCV from source, install them, and add the install directories to PATH. This ensures CMake can locate the libraries.
|
||||
|
||||
You will also want to add the directories where the DLLs are located (usually the `bin` subdirectory of the install directory) to PATH so they can be loaded by your program. If you are using OpenCV and Java, the `opencv_java` DLL is located in either the `lib` subdirectory if you built but didn't install OpenCV, or the `java` subdirectory if you did install OpenCV.
|
||||
|
||||
@@ -234,6 +228,6 @@ Last Load Error:
|
||||
C:\Program Files (x86)\allwpilib\bin\wpiHaljni.dll: Can't find dependent libraries
|
||||
```
|
||||
|
||||
If you get this error, that's usually an indication that not all your libraries are in your PATH. The two libraries that should be in your PATH are OpenCV and protobuf. If the error is coming from cscore, it's likely you're missing OpenCV. Otherwise, it's likely you're missing protobuf.
|
||||
If you get this error, that's usually an indication that not all your libraries are in your PATH. If the error is coming from cscore specifically, it's likely you're missing OpenCV. Otherwise, it's likely the wpilib libraries are not in a directory on PATH.
|
||||
|
||||
Note that Linux will not have this specific type of error, as it will usually tell you the dependent library you are missing. In that case, you most likely need to add the library to `LD_LIBRARY_PATH`.
|
||||
|
||||
@@ -49,7 +49,7 @@ glfw thirdparty/imgui_suite/glfw
|
||||
Dear ImGui thirdparty/imgui_suite/imgui
|
||||
implot thirdparty/imgui_suite/implot
|
||||
nanopb wpiutil/src/main/native/thirdparty/nanopb
|
||||
protobuf wpiutil/src/main/native/thirdparty/protobuf
|
||||
upb wpiutil/src/main/native/thirdparty/upb
|
||||
mrcal wpical/src/main/native/thirdparty/mrcal
|
||||
libdogleg wpical/src/main/native/thirdparty/libdogleg
|
||||
Simd hal/src/main/native/athena/simd
|
||||
@@ -1355,7 +1355,7 @@ redistribute it freely, subject to the following restrictions:
|
||||
distribution.
|
||||
|
||||
================
|
||||
protobuf License
|
||||
upb License
|
||||
================
|
||||
Copyright 2008 Google Inc. All rights reserved.
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ macro(add_doxygen_docs)
|
||||
foreach(dir ${dirs})
|
||||
list(APPEND docs_dirs ${dir}/src/main/native/include)
|
||||
file(GLOB dirs ${dir}/src/main/native/thirdparty/*/include)
|
||||
list(FILTER dirs EXCLUDE REGEX eigen|protobuf)
|
||||
list(FILTER dirs EXCLUDE REGEX eigen)
|
||||
set(DOXYGEN_EXCLUDE_PATTERNS "*.pb.h" "**/.clang-tidy" "**/.clang-format")
|
||||
|
||||
if(DOCS_WARNINGS_AS_ERRORS)
|
||||
|
||||
@@ -2,9 +2,6 @@ include(CompileWarnings)
|
||||
|
||||
macro(wpilib_add_test name srcdir)
|
||||
file(GLOB_RECURSE test_src ${srcdir}/*.cpp)
|
||||
if(NOT WITH_PROTOBUF)
|
||||
list(FILTER test_src EXCLUDE REGEX "/proto/")
|
||||
endif()
|
||||
add_executable(${name}_test ${test_src})
|
||||
set_property(TARGET ${name}_test PROPERTY FOLDER "tests")
|
||||
wpilib_target_warnings(${name}_test)
|
||||
|
||||
@@ -21,5 +21,6 @@ repoRootNameOverride {
|
||||
includeOtherLibs {
|
||||
^fmt/
|
||||
^gtest/
|
||||
^upb/
|
||||
^wpi/(?!datalog)
|
||||
}
|
||||
|
||||
@@ -110,13 +110,18 @@ void DataLogReaderThread::ReadMain() {
|
||||
schema, err);
|
||||
}
|
||||
} else if (auto filename = wpi::remove_prefix(name, "/.schema/proto:")) {
|
||||
#ifndef NO_PROTOBUF
|
||||
// protobuf descriptor handling
|
||||
if (!m_protoDb.Add(*filename, data)) {
|
||||
upb_Status status;
|
||||
status.ok = true;
|
||||
upb_DefPool_AddFile(
|
||||
m_protoPool,
|
||||
google_protobuf_FileDescriptorProto_parse(
|
||||
reinterpret_cast<const char*>(data.data()), data.size(), m_arena),
|
||||
&status);
|
||||
if (!status.ok) {
|
||||
wpi::print("could not decode protobuf '{}' filename '{}'\n", name,
|
||||
*filename);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <upb/mem/arena.h>
|
||||
#include <upb/reflection/def.h>
|
||||
#include <wpi/DenseMap.h>
|
||||
#include <wpi/Signal.h>
|
||||
#include <wpi/mutex.h>
|
||||
@@ -20,10 +22,6 @@
|
||||
|
||||
#include "wpi/datalog/DataLogReader.h"
|
||||
|
||||
#ifndef NO_PROTOBUF
|
||||
#include <wpi/protobuf/ProtobufMessageDatabase.h>
|
||||
#endif
|
||||
|
||||
namespace wpi::log {
|
||||
|
||||
class DataLogReaderRange {
|
||||
@@ -88,9 +86,8 @@ class DataLogReaderThread {
|
||||
}
|
||||
|
||||
wpi::StructDescriptorDatabase& GetStructDatabase() { return m_structDb; }
|
||||
#ifndef NO_PROTOBUF
|
||||
wpi::ProtobufMessageDatabase& GetProtobufDatabase() { return m_protoDb; }
|
||||
#endif
|
||||
upb_DefPool* GetProtobufDatabase() { return m_protoPool; }
|
||||
upb_Arena* GetProtobufArena() { return m_arena; }
|
||||
|
||||
const wpi::log::DataLogReader& GetReader() const { return m_reader; }
|
||||
|
||||
@@ -109,9 +106,8 @@ class DataLogReaderThread {
|
||||
std::map<std::string, DataLogReaderEntry, std::less<>> m_entriesByName;
|
||||
wpi::DenseMap<int, DataLogReaderEntry*> m_entriesById;
|
||||
wpi::StructDescriptorDatabase m_structDb;
|
||||
#ifndef NO_PROTOBUF
|
||||
wpi::ProtobufMessageDatabase m_protoDb;
|
||||
#endif
|
||||
upb_DefPool* m_protoPool = upb_DefPool_New();
|
||||
upb_Arena* m_arena = upb_Arena_New();
|
||||
std::thread m_thread;
|
||||
};
|
||||
|
||||
|
||||
@@ -145,10 +145,9 @@ doxygen.sourceSets.main {
|
||||
|
||||
exclude '*.pb.h'
|
||||
|
||||
// Save space by excluding protobuf and eigen
|
||||
// Save space by excluding eigen
|
||||
exclude 'Eigen/**'
|
||||
exclude 'unsupported/**'
|
||||
exclude 'google/protobuf/**'
|
||||
|
||||
exclude '**/.clang-tidy'
|
||||
exclude '**/.clang-format'
|
||||
|
||||
@@ -24,12 +24,12 @@ includeOtherLibs {
|
||||
^fmt/
|
||||
^fields/
|
||||
^frc/
|
||||
^google/
|
||||
^imgui
|
||||
portable-file-dialogs.h
|
||||
^networktables/
|
||||
^ntcore
|
||||
^units
|
||||
^upb/
|
||||
^wpi/
|
||||
^wpigui
|
||||
^wpimath/
|
||||
|
||||
@@ -25,6 +25,12 @@
|
||||
#include <ntcore_c.h>
|
||||
#include <ntcore_cpp.h>
|
||||
#include <ntcore_cpp_types.h>
|
||||
#include <upb/message/message.h>
|
||||
#include <upb/mini_table/message.h>
|
||||
#include <upb/reflection/def.h>
|
||||
#include <upb/reflection/message.h>
|
||||
#include <upb/reflection/stage0/google/protobuf/descriptor.upb.h>
|
||||
#include <upb/wire/decode.h>
|
||||
#include <wpi/MessagePack.h>
|
||||
#include <wpi/SmallString.h>
|
||||
#include <wpi/SpanExtras.h>
|
||||
@@ -33,11 +39,6 @@
|
||||
#include <wpi/print.h>
|
||||
#include <wpi/raw_ostream.h>
|
||||
|
||||
#ifndef NO_PROTOBUF
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/message.h>
|
||||
#endif
|
||||
|
||||
#include "glass/Context.h"
|
||||
#include "glass/DataSource.h"
|
||||
#include "glass/Storage.h"
|
||||
@@ -353,172 +354,218 @@ static void UpdateStructValueSource(NetworkTablesModel& model,
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef NO_PROTOBUF
|
||||
static void UpdateProtobufValueSource(NetworkTablesModel& model,
|
||||
NetworkTablesModel::ValueSource* out,
|
||||
const google::protobuf::Message& msg,
|
||||
const upb_Message* msg,
|
||||
const upb_MessageDef* msgDef,
|
||||
std::string_view name, int64_t time) {
|
||||
auto desc = msg.GetDescriptor();
|
||||
out->typeStr = fmt::format("proto:{}", desc->full_name());
|
||||
out->typeStr = fmt::format("proto:{}", upb_MessageDef_FullName(msgDef));
|
||||
int fieldCount = upb_MessageDef_FieldCount(msgDef);
|
||||
if (!out->valueChildrenMap ||
|
||||
desc->field_count() != static_cast<int>(out->valueChildren.size())) {
|
||||
fieldCount != static_cast<int>(out->valueChildren.size())) {
|
||||
out->valueChildren.clear();
|
||||
out->valueChildrenMap = true;
|
||||
out->valueChildren.reserve(desc->field_count());
|
||||
for (int i = 0, end = desc->field_count(); i < end; ++i) {
|
||||
out->valueChildren.reserve(fieldCount);
|
||||
for (int i = 0, end = fieldCount; i < end; ++i) {
|
||||
out->valueChildren.emplace_back();
|
||||
auto& child = out->valueChildren.back();
|
||||
child.name = desc->field(i)->name();
|
||||
child.name = upb_FieldDef_Name(upb_MessageDef_Field(msgDef, i));
|
||||
child.path = fmt::format("{}/{}", name, child.name);
|
||||
}
|
||||
}
|
||||
auto refl = msg.GetReflection();
|
||||
auto outIt = out->valueChildren.begin();
|
||||
for (int fieldNum = 0, end = desc->field_count(); fieldNum < end;
|
||||
++fieldNum) {
|
||||
auto field = desc->field(fieldNum);
|
||||
for (int fieldNum = 0, end = fieldCount; fieldNum < end; ++fieldNum) {
|
||||
const upb_FieldDef* field = upb_MessageDef_Field(msgDef, fieldNum);
|
||||
auto& child = *outIt++;
|
||||
switch (field->cpp_type()) {
|
||||
case google::protobuf::FieldDescriptor::CPPTYPE_BOOL:
|
||||
if (field->is_repeated()) {
|
||||
size_t size = refl->FieldSize(msg, field);
|
||||
switch (upb_FieldDef_CType(field)) {
|
||||
case kUpb_CType_Bool: {
|
||||
if (upb_FieldDef_IsRepeated(field)) {
|
||||
const upb_Array* arr =
|
||||
upb_Message_GetFieldByDef(msg, field).array_val;
|
||||
size_t size = upb_Array_Size(arr);
|
||||
std::vector<int> v;
|
||||
v.reserve(size);
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
v.emplace_back(refl->GetRepeatedBool(msg, field, i));
|
||||
v.emplace_back(upb_Array_Get(arr, i).bool_val);
|
||||
}
|
||||
child.value = nt::Value::MakeBooleanArray(std::move(v), time);
|
||||
} else {
|
||||
child.value = nt::Value::MakeBoolean(refl->GetBool(msg, field), time);
|
||||
}
|
||||
child.UpdateFromValue(model, child.path, "");
|
||||
break;
|
||||
case google::protobuf::FieldDescriptor::CPPTYPE_STRING:
|
||||
if (field->is_repeated()) {
|
||||
size_t size = refl->FieldSize(msg, field);
|
||||
std::vector<std::string> v;
|
||||
v.reserve(size);
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
v.emplace_back(refl->GetRepeatedString(msg, field, i));
|
||||
}
|
||||
child.value = nt::Value::MakeStringArray(std::move(v), time);
|
||||
} else {
|
||||
child.value =
|
||||
nt::Value::MakeString(refl->GetString(msg, field), time);
|
||||
child.value = nt::Value::MakeBoolean(
|
||||
upb_Message_GetFieldByDef(msg, field).bool_val, time);
|
||||
child.UpdateFromValue(model, child.path, "");
|
||||
}
|
||||
break;
|
||||
case google::protobuf::FieldDescriptor::CPPTYPE_INT32:
|
||||
if (field->is_repeated()) {
|
||||
size_t size = refl->FieldSize(msg, field);
|
||||
std::vector<int64_t> v;
|
||||
v.reserve(size);
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
v.emplace_back(refl->GetRepeatedInt32(msg, field, i));
|
||||
}
|
||||
child.value = nt::Value::MakeIntegerArray(std::move(v), time);
|
||||
} else {
|
||||
child.value =
|
||||
nt::Value::MakeInteger(refl->GetInt32(msg, field), time);
|
||||
}
|
||||
child.UpdateFromValue(model, child.path, "");
|
||||
break;
|
||||
case google::protobuf::FieldDescriptor::CPPTYPE_INT64:
|
||||
if (field->is_repeated()) {
|
||||
size_t size = refl->FieldSize(msg, field);
|
||||
std::vector<int64_t> v;
|
||||
v.reserve(size);
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
v.emplace_back(refl->GetRepeatedInt64(msg, field, i));
|
||||
}
|
||||
child.value = nt::Value::MakeIntegerArray(std::move(v), time);
|
||||
} else {
|
||||
child.value =
|
||||
nt::Value::MakeInteger(refl->GetInt64(msg, field), time);
|
||||
}
|
||||
child.UpdateFromValue(model, child.path, "");
|
||||
break;
|
||||
case google::protobuf::FieldDescriptor::CPPTYPE_UINT32:
|
||||
if (field->is_repeated()) {
|
||||
size_t size = refl->FieldSize(msg, field);
|
||||
std::vector<int64_t> v;
|
||||
v.reserve(size);
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
v.emplace_back(refl->GetRepeatedUInt32(msg, field, i));
|
||||
}
|
||||
child.value = nt::Value::MakeIntegerArray(std::move(v), time);
|
||||
} else {
|
||||
child.value =
|
||||
nt::Value::MakeInteger(refl->GetUInt32(msg, field), time);
|
||||
}
|
||||
child.UpdateFromValue(model, child.path, "");
|
||||
break;
|
||||
case google::protobuf::FieldDescriptor::CPPTYPE_UINT64:
|
||||
if (field->is_repeated()) {
|
||||
size_t size = refl->FieldSize(msg, field);
|
||||
std::vector<int64_t> v;
|
||||
v.reserve(size);
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
v.emplace_back(refl->GetRepeatedUInt64(msg, field, i));
|
||||
}
|
||||
child.value = nt::Value::MakeIntegerArray(std::move(v), time);
|
||||
} else {
|
||||
child.value =
|
||||
nt::Value::MakeInteger(refl->GetUInt64(msg, field), time);
|
||||
}
|
||||
child.UpdateFromValue(model, child.path, "");
|
||||
break;
|
||||
case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT:
|
||||
if (field->is_repeated()) {
|
||||
size_t size = refl->FieldSize(msg, field);
|
||||
std::vector<float> v;
|
||||
v.reserve(size);
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
v.emplace_back(refl->GetRepeatedFloat(msg, field, i));
|
||||
}
|
||||
child.value = nt::Value::MakeFloatArray(std::move(v), time);
|
||||
} else {
|
||||
child.value = nt::Value::MakeFloat(refl->GetFloat(msg, field), time);
|
||||
}
|
||||
child.UpdateFromValue(model, child.path, "");
|
||||
break;
|
||||
case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
|
||||
if (field->is_repeated()) {
|
||||
size_t size = refl->FieldSize(msg, field);
|
||||
std::vector<double> v;
|
||||
v.reserve(size);
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
v.emplace_back(refl->GetRepeatedDouble(msg, field, i));
|
||||
}
|
||||
child.value = nt::Value::MakeDoubleArray(std::move(v), time);
|
||||
} else {
|
||||
child.value =
|
||||
nt::Value::MakeDouble(refl->GetDouble(msg, field), time);
|
||||
}
|
||||
child.UpdateFromValue(model, child.path, "");
|
||||
break;
|
||||
case google::protobuf::FieldDescriptor::CPPTYPE_ENUM:
|
||||
if (field->is_repeated()) {
|
||||
size_t size = refl->FieldSize(msg, field);
|
||||
}
|
||||
case kUpb_CType_String: {
|
||||
if (upb_FieldDef_IsRepeated(field)) {
|
||||
const upb_Array* arr =
|
||||
upb_Message_GetFieldByDef(msg, field).array_val;
|
||||
size_t size = upb_Array_Size(arr);
|
||||
std::vector<std::string> v;
|
||||
v.reserve(size);
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
v.emplace_back(refl->GetRepeatedEnum(msg, field, i)->name());
|
||||
upb_StringView sv = upb_Array_Get(arr, i).str_val;
|
||||
v.emplace_back(sv.data, sv.size);
|
||||
}
|
||||
child.value = nt::Value::MakeStringArray(std::move(v), time);
|
||||
} else {
|
||||
child.value =
|
||||
nt::Value::MakeString(refl->GetEnum(msg, field)->name(), time);
|
||||
upb_StringView sv = upb_Message_GetFieldByDef(msg, field).str_val;
|
||||
child.value = nt::Value::MakeString({sv.data, sv.size}, time);
|
||||
child.UpdateFromValue(model, child.path, "");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kUpb_CType_Int32: {
|
||||
if (upb_FieldDef_IsRepeated(field)) {
|
||||
const upb_Array* arr =
|
||||
upb_Message_GetFieldByDef(msg, field).array_val;
|
||||
size_t size = upb_Array_Size(arr);
|
||||
std::vector<int64_t> v;
|
||||
v.reserve(size);
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
v.emplace_back(upb_Array_Get(arr, i).int32_val);
|
||||
}
|
||||
child.value = nt::Value::MakeIntegerArray(std::move(v), time);
|
||||
} else {
|
||||
child.value = nt::Value::MakeInteger(
|
||||
upb_Message_GetFieldByDef(msg, field).int32_val, time);
|
||||
}
|
||||
child.UpdateFromValue(model, child.path, "");
|
||||
break;
|
||||
case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
|
||||
if (field->is_repeated()) {
|
||||
}
|
||||
case kUpb_CType_Int64: {
|
||||
if (upb_FieldDef_IsRepeated(field)) {
|
||||
const upb_Array* arr =
|
||||
upb_Message_GetFieldByDef(msg, field).array_val;
|
||||
size_t size = upb_Array_Size(arr);
|
||||
std::vector<int64_t> v;
|
||||
v.reserve(size);
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
v.emplace_back(upb_Array_Get(arr, i).int64_val);
|
||||
}
|
||||
child.value = nt::Value::MakeIntegerArray(std::move(v), time);
|
||||
} else {
|
||||
child.value = nt::Value::MakeInteger(
|
||||
upb_Message_GetFieldByDef(msg, field).int64_val, time);
|
||||
}
|
||||
child.UpdateFromValue(model, child.path, "");
|
||||
break;
|
||||
}
|
||||
case kUpb_CType_UInt32: {
|
||||
if (upb_FieldDef_IsRepeated(field)) {
|
||||
const upb_Array* arr =
|
||||
upb_Message_GetFieldByDef(msg, field).array_val;
|
||||
size_t size = upb_Array_Size(arr);
|
||||
std::vector<int64_t> v;
|
||||
v.reserve(size);
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
v.emplace_back(upb_Array_Get(arr, i).uint32_val);
|
||||
}
|
||||
child.value = nt::Value::MakeIntegerArray(std::move(v), time);
|
||||
} else {
|
||||
child.value = nt::Value::MakeInteger(
|
||||
upb_Message_GetFieldByDef(msg, field).uint32_val, time);
|
||||
}
|
||||
child.UpdateFromValue(model, child.path, "");
|
||||
break;
|
||||
}
|
||||
case kUpb_CType_UInt64: {
|
||||
if (upb_FieldDef_IsRepeated(field)) {
|
||||
const upb_Array* arr =
|
||||
upb_Message_GetFieldByDef(msg, field).array_val;
|
||||
size_t size = upb_Array_Size(arr);
|
||||
std::vector<int64_t> v;
|
||||
v.reserve(size);
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
v.emplace_back(upb_Array_Get(arr, i).uint64_val);
|
||||
}
|
||||
child.value = nt::Value::MakeIntegerArray(std::move(v), time);
|
||||
} else {
|
||||
child.value = nt::Value::MakeInteger(
|
||||
upb_Message_GetFieldByDef(msg, field).uint64_val, time);
|
||||
}
|
||||
child.UpdateFromValue(model, child.path, "");
|
||||
break;
|
||||
}
|
||||
case kUpb_CType_Float: {
|
||||
if (upb_FieldDef_IsRepeated(field)) {
|
||||
const upb_Array* arr =
|
||||
upb_Message_GetFieldByDef(msg, field).array_val;
|
||||
size_t size = upb_Array_Size(arr);
|
||||
std::vector<float> v;
|
||||
v.reserve(size);
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
v.emplace_back(upb_Array_Get(arr, i).float_val);
|
||||
}
|
||||
child.value = nt::Value::MakeFloatArray(std::move(v), time);
|
||||
} else {
|
||||
child.value = nt::Value::MakeFloat(
|
||||
upb_Message_GetFieldByDef(msg, field).float_val, time);
|
||||
}
|
||||
child.UpdateFromValue(model, child.path, "");
|
||||
break;
|
||||
}
|
||||
case kUpb_CType_Double: {
|
||||
if (upb_FieldDef_IsRepeated(field)) {
|
||||
const upb_Array* arr =
|
||||
upb_Message_GetFieldByDef(msg, field).array_val;
|
||||
size_t size = upb_Array_Size(arr);
|
||||
std::vector<double> v;
|
||||
v.reserve(size);
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
v.emplace_back(upb_Array_Get(arr, i).double_val);
|
||||
}
|
||||
child.value = nt::Value::MakeDoubleArray(std::move(v), time);
|
||||
} else {
|
||||
child.value = nt::Value::MakeDouble(
|
||||
upb_Message_GetFieldByDef(msg, field).double_val, time);
|
||||
}
|
||||
child.UpdateFromValue(model, child.path, "");
|
||||
break;
|
||||
}
|
||||
case kUpb_CType_Enum: {
|
||||
const upb_EnumDef* enumDef = upb_FieldDef_EnumSubDef(field);
|
||||
if (upb_FieldDef_IsRepeated(field)) {
|
||||
const upb_Array* arr =
|
||||
upb_Message_GetFieldByDef(msg, field).array_val;
|
||||
size_t size = upb_Array_Size(arr);
|
||||
std::vector<std::string> v;
|
||||
v.reserve(size);
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
int32_t value = upb_Message_GetFieldByDef(msg, field).int32_val;
|
||||
const upb_EnumValueDef* enumValueDef =
|
||||
upb_EnumDef_FindValueByNumber(enumDef, value);
|
||||
if (enumValueDef) {
|
||||
const char* name = upb_EnumValueDef_Name(enumValueDef);
|
||||
v.emplace_back(name);
|
||||
} else {
|
||||
v.emplace_back(fmt::format("{}", value));
|
||||
}
|
||||
}
|
||||
child.value = nt::Value::MakeStringArray(std::move(v), time);
|
||||
} else {
|
||||
int32_t value = upb_Message_GetFieldByDef(msg, field).int32_val;
|
||||
const upb_EnumValueDef* enumValueDef =
|
||||
upb_EnumDef_FindValueByNumber(enumDef, value);
|
||||
if (enumValueDef) {
|
||||
const char* name = upb_EnumValueDef_Name(enumValueDef);
|
||||
child.value = nt::Value::MakeString(name, time);
|
||||
} else {
|
||||
child.value = nt::Value::MakeString(fmt::format("{}", value), time);
|
||||
}
|
||||
}
|
||||
child.UpdateFromValue(model, child.path, "");
|
||||
break;
|
||||
}
|
||||
case kUpb_CType_Message: {
|
||||
if (upb_FieldDef_IsRepeated(field)) {
|
||||
if (child.valueChildrenMap) {
|
||||
child.valueChildren.clear();
|
||||
child.valueChildrenMap = false;
|
||||
}
|
||||
size_t size = refl->FieldSize(msg, field);
|
||||
const upb_Array* arr =
|
||||
upb_Message_GetFieldByDef(msg, field).array_val;
|
||||
size_t size = upb_Array_Size(arr);
|
||||
child.valueChildren.resize(size);
|
||||
unsigned int i = 0;
|
||||
for (auto&& child2 : child.valueChildren) {
|
||||
@@ -526,23 +573,24 @@ static void UpdateProtobufValueSource(NetworkTablesModel& model,
|
||||
child2.name = fmt::format("[{}]", i);
|
||||
child2.path = fmt::format("{}{}", name, child.name);
|
||||
}
|
||||
UpdateProtobufValueSource(model, &child2,
|
||||
refl->GetRepeatedMessage(msg, field, i),
|
||||
const upb_Message* submsg = upb_Array_Get(arr, i).msg_val;
|
||||
const upb_MessageDef* submsgDef = upb_FieldDef_MessageSubDef(field);
|
||||
UpdateProtobufValueSource(model, &child2, submsg, submsgDef,
|
||||
child2.path, time); // recurse
|
||||
++i;
|
||||
}
|
||||
} else {
|
||||
UpdateProtobufValueSource(
|
||||
model, &child,
|
||||
refl->GetMessage(msg, field,
|
||||
model.GetProtobufDatabase().GetMessageFactory()),
|
||||
child.path, time); // recurse
|
||||
model, &child, upb_Message_GetFieldByDef(msg, field).msg_val,
|
||||
upb_FieldDef_MessageSubDef(field), child.path, time); // recurse
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kUpb_CType_Bytes:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void UpdateJsonValueSource(NetworkTablesModel& model,
|
||||
NetworkTablesModel::ValueSource* out,
|
||||
@@ -817,13 +865,19 @@ void NetworkTablesModel::ValueSource::UpdateFromValue(
|
||||
valueChildren.clear();
|
||||
}
|
||||
} else if (auto filename = wpi::remove_prefix(typeStr, "proto:")) {
|
||||
#ifndef NO_PROTOBUF
|
||||
auto msg = model.m_protoDb.Find(*filename);
|
||||
if (msg) {
|
||||
msg->Clear();
|
||||
const upb_MessageDef* messageDef = upb_DefPool_FindMessageByName(
|
||||
model.GetProtobufDatabase(), filename->data());
|
||||
if (messageDef) {
|
||||
auto raw = value.GetRaw();
|
||||
if (msg->ParseFromArray(raw.data(), raw.size())) {
|
||||
UpdateProtobufValueSource(model, this, *msg, name,
|
||||
const upb_MiniTable* miniTable = upb_MessageDef_MiniTable(messageDef);
|
||||
|
||||
upb_Message* message =
|
||||
upb_Message_New(miniTable, model.GetProtobufArena());
|
||||
upb_DecodeStatus status = upb_Decode(
|
||||
reinterpret_cast<const char*>(raw.data()), raw.size(), message,
|
||||
miniTable, nullptr, 0, model.GetProtobufArena());
|
||||
if (status == kUpb_DecodeStatus_Ok) {
|
||||
UpdateProtobufValueSource(model, this, message, messageDef, name,
|
||||
value.last_change());
|
||||
} else {
|
||||
valueChildren.clear();
|
||||
@@ -831,9 +885,6 @@ void NetworkTablesModel::ValueSource::UpdateFromValue(
|
||||
} else {
|
||||
valueChildren.clear();
|
||||
}
|
||||
#else
|
||||
valueChildren.clear();
|
||||
#endif
|
||||
} else {
|
||||
valueChildren.clear();
|
||||
}
|
||||
@@ -959,9 +1010,17 @@ void NetworkTablesModel::Update() {
|
||||
wpi::remove_prefix(entry->info.name, "/.schema/proto:");
|
||||
entry->value.IsRaw() && filename &&
|
||||
entry->info.type_str == "proto:FileDescriptorProto") {
|
||||
#ifndef NO_PROTOBUF
|
||||
// protobuf descriptor handling
|
||||
if (!m_protoDb.Add(*filename, entry->value.GetRaw())) {
|
||||
upb_Status status;
|
||||
status.ok = true;
|
||||
auto descriptor = entry->value.GetRaw();
|
||||
upb_DefPool_AddFile(
|
||||
m_protoPool,
|
||||
google_protobuf_FileDescriptorProto_parse(
|
||||
reinterpret_cast<const char*>(descriptor.data()),
|
||||
descriptor.size(), m_arena),
|
||||
&status);
|
||||
if (!status.ok) {
|
||||
wpi::print("could not decode protobuf '{}' filename '{}'\n",
|
||||
entry->info.name, *filename);
|
||||
} else {
|
||||
@@ -976,7 +1035,6 @@ void NetworkTablesModel::Update() {
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,14 +16,12 @@
|
||||
#include <networktables/NetworkTableInstance.h>
|
||||
#include <networktables/NetworkTableListener.h>
|
||||
#include <ntcore_cpp.h>
|
||||
#include <upb/mem/arena.h>
|
||||
#include <upb/reflection/def.h>
|
||||
#include <wpi/DenseMap.h>
|
||||
#include <wpi/json.h>
|
||||
#include <wpi/struct/DynamicStruct.h>
|
||||
|
||||
#ifndef NO_PROTOBUF
|
||||
#include <wpi/protobuf/ProtobufMessageDatabase.h>
|
||||
#endif
|
||||
|
||||
#include "glass/Model.h"
|
||||
#include "glass/View.h"
|
||||
|
||||
@@ -174,9 +172,8 @@ class NetworkTablesModel : public Model {
|
||||
Entry* AddEntry(NT_Topic topic);
|
||||
|
||||
wpi::StructDescriptorDatabase& GetStructDatabase() { return m_structDb; }
|
||||
#ifndef NO_PROTOBUF
|
||||
wpi::ProtobufMessageDatabase& GetProtobufDatabase() { return m_protoDb; }
|
||||
#endif
|
||||
upb_DefPool* GetProtobufDatabase() { return m_protoPool; }
|
||||
upb_Arena* GetProtobufArena() { return m_arena; }
|
||||
|
||||
private:
|
||||
void RebuildTree();
|
||||
@@ -199,9 +196,8 @@ class NetworkTablesModel : public Model {
|
||||
Client m_server;
|
||||
|
||||
wpi::StructDescriptorDatabase m_structDb;
|
||||
#ifndef NO_PROTOBUF
|
||||
wpi::ProtobufMessageDatabase m_protoDb;
|
||||
#endif
|
||||
upb_DefPool* m_protoPool = upb_DefPool_New();
|
||||
upb_Arena* m_arena = upb_Arena_New();
|
||||
};
|
||||
|
||||
using NetworkTablesFlags = int;
|
||||
|
||||
@@ -1,269 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
|
||||
from upstream_utils import Lib, walk_cwd_and_copy_if
|
||||
|
||||
protobuf_lite_sources = {
|
||||
Path("any_lite.cc"),
|
||||
Path("arena.cc"),
|
||||
Path("arenastring.cc"),
|
||||
Path("arenaz_sampler.cc"),
|
||||
Path("extension_set.cc"),
|
||||
Path("generated_enum_util.cc"),
|
||||
Path("generated_message_tctable_lite.cc"),
|
||||
Path("generated_message_util.cc"),
|
||||
Path("implicit_weak_message.cc"),
|
||||
Path("inlined_string_field.cc"),
|
||||
Path("io/coded_stream.cc"),
|
||||
Path("io/io_win32.cc"),
|
||||
Path("io/strtod.cc"),
|
||||
Path("io/zero_copy_stream.cc"),
|
||||
Path("io/zero_copy_stream_impl.cc"),
|
||||
Path("io/zero_copy_stream_impl_lite.cc"),
|
||||
Path("map.cc"),
|
||||
Path("message_lite.cc"),
|
||||
Path("parse_context.cc"),
|
||||
Path("repeated_field.cc"),
|
||||
Path("repeated_ptr_field.cc"),
|
||||
Path("stubs/bytestream.cc"),
|
||||
Path("stubs/common.cc"),
|
||||
Path("stubs/int128.cc"),
|
||||
Path("stubs/status.cc"),
|
||||
Path("stubs/statusor.cc"),
|
||||
Path("stubs/stringpiece.cc"),
|
||||
Path("stubs/stringprintf.cc"),
|
||||
Path("stubs/structurally_valid.cc"),
|
||||
Path("stubs/strutil.cc"),
|
||||
Path("stubs/time.cc"),
|
||||
Path("wire_format_lite.cc"),
|
||||
}
|
||||
|
||||
protobuf_lite_includes = {
|
||||
Path("google/protobuf/any.h"),
|
||||
Path("google/protobuf/arena.h"),
|
||||
Path("google/protobuf/arena_impl.h"),
|
||||
Path("google/protobuf/arenastring.h"),
|
||||
Path("google/protobuf/arenaz_sampler.h"),
|
||||
Path("google/protobuf/endian.h"),
|
||||
Path("google/protobuf/explicitly_constructed.h"),
|
||||
Path("google/protobuf/extension_set.h"),
|
||||
Path("google/protobuf/extension_set_inl.h"),
|
||||
Path("google/protobuf/generated_enum_util.h"),
|
||||
Path("google/protobuf/generated_message_tctable_decl.h"),
|
||||
Path("google/protobuf/generated_message_tctable_impl.h"),
|
||||
Path("google/protobuf/generated_message_util.h"),
|
||||
Path("google/protobuf/has_bits.h"),
|
||||
Path("google/protobuf/implicit_weak_message.h"),
|
||||
Path("google/protobuf/inlined_string_field.h"),
|
||||
Path("google/protobuf/io/coded_stream.h"),
|
||||
Path("google/protobuf/io/io_win32.h"),
|
||||
Path("google/protobuf/io/strtod.h"),
|
||||
Path("google/protobuf/io/zero_copy_stream.h"),
|
||||
Path("google/protobuf/io/zero_copy_stream_impl.h"),
|
||||
Path("google/protobuf/io/zero_copy_stream_impl_lite.h"),
|
||||
Path("google/protobuf/map.h"),
|
||||
Path("google/protobuf/map_entry_lite.h"),
|
||||
Path("google/protobuf/map_field_lite.h"),
|
||||
Path("google/protobuf/map_type_handler.h"),
|
||||
Path("google/protobuf/message_lite.h"),
|
||||
Path("google/protobuf/metadata_lite.h"),
|
||||
Path("google/protobuf/parse_context.h"),
|
||||
Path("google/protobuf/port.h"),
|
||||
Path("google/protobuf/repeated_field.h"),
|
||||
Path("google/protobuf/repeated_ptr_field.h"),
|
||||
Path("google/protobuf/stubs/bytestream.h"),
|
||||
Path("google/protobuf/stubs/callback.h"),
|
||||
Path("google/protobuf/stubs/casts.h"),
|
||||
Path("google/protobuf/stubs/common.h"),
|
||||
Path("google/protobuf/stubs/hash.h"),
|
||||
Path("google/protobuf/stubs/logging.h"),
|
||||
Path("google/protobuf/stubs/macros.h"),
|
||||
Path("google/protobuf/stubs/map_util.h"),
|
||||
Path("google/protobuf/stubs/mutex.h"),
|
||||
Path("google/protobuf/stubs/once.h"),
|
||||
Path("google/protobuf/stubs/platform_macros.h"),
|
||||
Path("google/protobuf/stubs/port.h"),
|
||||
Path("google/protobuf/stubs/status.h"),
|
||||
Path("google/protobuf/stubs/stl_util.h"),
|
||||
Path("google/protobuf/stubs/stringpiece.h"),
|
||||
Path("google/protobuf/stubs/strutil.h"),
|
||||
Path("google/protobuf/stubs/template_util.h"),
|
||||
Path("google/protobuf/wire_format_lite.h"),
|
||||
}
|
||||
protobuf_sources = {
|
||||
Path("any.cc"),
|
||||
Path("any.pb.cc"),
|
||||
Path("api.pb.cc"),
|
||||
Path("compiler/importer.cc"),
|
||||
Path("compiler/parser.cc"),
|
||||
Path("descriptor.cc"),
|
||||
Path("descriptor.pb.cc"),
|
||||
Path("descriptor_database.cc"),
|
||||
Path("duration.pb.cc"),
|
||||
Path("dynamic_message.cc"),
|
||||
Path("empty.pb.cc"),
|
||||
Path("extension_set_heavy.cc"),
|
||||
Path("field_mask.pb.cc"),
|
||||
Path("generated_message_bases.cc"),
|
||||
Path("generated_message_reflection.cc"),
|
||||
Path("generated_message_tctable_full.cc"),
|
||||
Path("io/gzip_stream.cc"),
|
||||
Path("io/printer.cc"),
|
||||
Path("io/tokenizer.cc"),
|
||||
Path("map_field.cc"),
|
||||
Path("message.cc"),
|
||||
Path("reflection_ops.cc"),
|
||||
Path("service.cc"),
|
||||
Path("source_context.pb.cc"),
|
||||
Path("struct.pb.cc"),
|
||||
Path("stubs/substitute.cc"),
|
||||
Path("text_format.cc"),
|
||||
Path("timestamp.pb.cc"),
|
||||
Path("type.pb.cc"),
|
||||
Path("unknown_field_set.cc"),
|
||||
Path("util/delimited_message_util.cc"),
|
||||
Path("util/field_comparator.cc"),
|
||||
Path("util/field_mask_util.cc"),
|
||||
Path("util/internal/datapiece.cc"),
|
||||
Path("util/internal/default_value_objectwriter.cc"),
|
||||
Path("util/internal/error_listener.cc"),
|
||||
Path("util/internal/field_mask_utility.cc"),
|
||||
Path("util/internal/json_escaping.cc"),
|
||||
Path("util/internal/json_objectwriter.cc"),
|
||||
Path("util/internal/json_stream_parser.cc"),
|
||||
Path("util/internal/object_writer.cc"),
|
||||
Path("util/internal/proto_writer.cc"),
|
||||
Path("util/internal/protostream_objectsource.cc"),
|
||||
Path("util/internal/protostream_objectwriter.cc"),
|
||||
Path("util/internal/type_info.cc"),
|
||||
Path("util/internal/utility.cc"),
|
||||
Path("util/json_util.cc"),
|
||||
Path("util/message_differencer.cc"),
|
||||
Path("util/time_util.cc"),
|
||||
Path("util/type_resolver_util.cc"),
|
||||
Path("wire_format.cc"),
|
||||
Path("wrappers.pb.cc"),
|
||||
}
|
||||
|
||||
protobuf_includes = {
|
||||
Path("google/protobuf/any.pb.h"),
|
||||
Path("google/protobuf/api.pb.h"),
|
||||
Path("google/protobuf/compiler/importer.h"),
|
||||
Path("google/protobuf/compiler/parser.h"),
|
||||
Path("google/protobuf/descriptor.h"),
|
||||
Path("google/protobuf/descriptor.pb.h"),
|
||||
Path("google/protobuf/descriptor_database.h"),
|
||||
Path("google/protobuf/duration.pb.h"),
|
||||
Path("google/protobuf/dynamic_message.h"),
|
||||
Path("google/protobuf/empty.pb.h"),
|
||||
Path("google/protobuf/field_access_listener.h"),
|
||||
Path("google/protobuf/field_mask.pb.h"),
|
||||
Path("google/protobuf/generated_enum_reflection.h"),
|
||||
Path("google/protobuf/generated_message_bases.h"),
|
||||
Path("google/protobuf/generated_message_reflection.h"),
|
||||
Path("google/protobuf/io/gzip_stream.h"),
|
||||
Path("google/protobuf/io/printer.h"),
|
||||
Path("google/protobuf/io/tokenizer.h"),
|
||||
Path("google/protobuf/map_entry.h"),
|
||||
Path("google/protobuf/map_field.h"),
|
||||
Path("google/protobuf/map_field_inl.h"),
|
||||
Path("google/protobuf/message.h"),
|
||||
Path("google/protobuf/metadata.h"),
|
||||
Path("google/protobuf/reflection.h"),
|
||||
Path("google/protobuf/reflection_internal.h"),
|
||||
Path("google/protobuf/reflection_ops.h"),
|
||||
Path("google/protobuf/service.h"),
|
||||
Path("google/protobuf/source_context.pb.h"),
|
||||
Path("google/protobuf/struct.pb.h"),
|
||||
Path("google/protobuf/text_format.h"),
|
||||
Path("google/protobuf/timestamp.pb.h"),
|
||||
Path("google/protobuf/type.pb.h"),
|
||||
Path("google/protobuf/unknown_field_set.h"),
|
||||
Path("google/protobuf/util/delimited_message_util.h"),
|
||||
Path("google/protobuf/util/field_comparator.h"),
|
||||
Path("google/protobuf/util/field_mask_util.h"),
|
||||
Path("google/protobuf/util/json_util.h"),
|
||||
Path("google/protobuf/util/message_differencer.h"),
|
||||
Path("google/protobuf/util/time_util.h"),
|
||||
Path("google/protobuf/util/type_resolver.h"),
|
||||
Path("google/protobuf/util/type_resolver_util.h"),
|
||||
Path("google/protobuf/wire_format.h"),
|
||||
Path("google/protobuf/wrappers.pb.h"),
|
||||
}
|
||||
|
||||
protobuf_internal_includes = {
|
||||
Path("google/protobuf/port_def.inc"),
|
||||
Path("google/protobuf/port_undef.inc"),
|
||||
Path("google/protobuf/stubs/int128.h"),
|
||||
Path("google/protobuf/stubs/mathutil.h"),
|
||||
Path("google/protobuf/stubs/statusor.h"),
|
||||
Path("google/protobuf/stubs/status_macros.h"),
|
||||
Path("google/protobuf/stubs/stringprintf.h"),
|
||||
Path("google/protobuf/stubs/substitute.h"),
|
||||
Path("google/protobuf/stubs/time.h"),
|
||||
Path("google/protobuf/util/internal/constants.h"),
|
||||
Path("google/protobuf/util/internal/datapiece.h"),
|
||||
Path("google/protobuf/util/internal/default_value_objectwriter.h"),
|
||||
Path("google/protobuf/util/internal/error_listener.h"),
|
||||
Path("google/protobuf/util/internal/field_mask_utility.h"),
|
||||
Path("google/protobuf/util/internal/json_escaping.h"),
|
||||
Path("google/protobuf/util/internal/json_objectwriter.h"),
|
||||
Path("google/protobuf/util/internal/json_stream_parser.h"),
|
||||
Path("google/protobuf/util/internal/location_tracker.h"),
|
||||
Path("google/protobuf/util/internal/object_location_tracker.h"),
|
||||
Path("google/protobuf/util/internal/object_source.h"),
|
||||
Path("google/protobuf/util/internal/object_writer.h"),
|
||||
Path("google/protobuf/util/internal/proto_writer.h"),
|
||||
Path("google/protobuf/util/internal/protostream_objectsource.h"),
|
||||
Path("google/protobuf/util/internal/protostream_objectwriter.h"),
|
||||
Path("google/protobuf/util/internal/structured_objectwriter.h"),
|
||||
Path("google/protobuf/util/internal/type_info.h"),
|
||||
Path("google/protobuf/util/internal/utility.h"),
|
||||
}
|
||||
|
||||
use_src_files = protobuf_lite_sources | protobuf_sources
|
||||
use_include_files = (
|
||||
protobuf_lite_includes | protobuf_includes | protobuf_internal_includes
|
||||
)
|
||||
|
||||
|
||||
def copy_upstream_src(wpilib_root: Path):
|
||||
upstream_root = Path(".").absolute()
|
||||
wpiutil = wpilib_root / "wpiutil"
|
||||
|
||||
# Delete old install
|
||||
for d in [
|
||||
"src/main/native/thirdparty/protobuf/src",
|
||||
"src/main/native/thirdparty/protobuf/include",
|
||||
]:
|
||||
shutil.rmtree(wpiutil / d, ignore_errors=True)
|
||||
|
||||
# Copy protobuf source files into allwpilib
|
||||
os.chdir(upstream_root / "src/google/protobuf")
|
||||
walk_cwd_and_copy_if(
|
||||
lambda dp, f: dp / f in use_src_files,
|
||||
wpiutil / "src/main/native/thirdparty/protobuf/src",
|
||||
)
|
||||
|
||||
# Copy protobuf header files into allwpilib
|
||||
os.chdir(upstream_root / "src")
|
||||
walk_cwd_and_copy_if(
|
||||
lambda dp, f: dp / f in use_include_files,
|
||||
wpiutil / "src/main/native/thirdparty/protobuf/include",
|
||||
)
|
||||
|
||||
|
||||
def main():
|
||||
name = "protobuf"
|
||||
url = "https://github.com/protocolbuffers/protobuf"
|
||||
tag = "v3.21.12"
|
||||
|
||||
protobuf = Lib(name, url, tag, copy_upstream_src)
|
||||
protobuf.main()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1,325 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Johnson <johnson.peter@gmail.com>
|
||||
Date: Sat, 10 Jun 2023 14:13:07 -0700
|
||||
Subject: [PATCH 01/15] Fix sign-compare warnings
|
||||
|
||||
---
|
||||
src/google/protobuf/compiler/importer.cc | 2 +-
|
||||
src/google/protobuf/compiler/parser.cc | 4 ++--
|
||||
src/google/protobuf/io/io_win32.cc | 2 +-
|
||||
src/google/protobuf/stubs/stringprintf.cc | 4 ++--
|
||||
src/google/protobuf/stubs/strutil.cc | 2 +-
|
||||
src/google/protobuf/stubs/substitute.cc | 2 +-
|
||||
src/google/protobuf/util/field_mask_util.cc | 2 +-
|
||||
src/google/protobuf/util/internal/datapiece.cc | 7 +++++++
|
||||
.../protobuf/util/internal/default_value_objectwriter.cc | 4 ++--
|
||||
.../protobuf/util/internal/default_value_objectwriter.h | 2 +-
|
||||
src/google/protobuf/util/internal/json_escaping.cc | 6 +++---
|
||||
src/google/protobuf/util/internal/json_objectwriter.h | 2 +-
|
||||
src/google/protobuf/util/internal/json_stream_parser.cc | 8 ++++----
|
||||
src/google/protobuf/util/internal/proto_writer.cc | 2 +-
|
||||
.../protobuf/util/internal/protostream_objectwriter.cc | 2 +-
|
||||
src/google/protobuf/util/internal/utility.cc | 2 +-
|
||||
src/google/protobuf/util/json_util.cc | 2 +-
|
||||
17 files changed, 31 insertions(+), 24 deletions(-)
|
||||
|
||||
diff --git a/src/google/protobuf/compiler/importer.cc b/src/google/protobuf/compiler/importer.cc
|
||||
index f1e26f8bdd1d3619acd8827f9a2a0e6b2acdd124..678e87eb03cc3959a1890327cd1e918cb1896fa3 100644
|
||||
--- a/src/google/protobuf/compiler/importer.cc
|
||||
+++ b/src/google/protobuf/compiler/importer.cc
|
||||
@@ -398,7 +398,7 @@ DiskSourceTree::DiskFileToVirtualFile(const std::string& disk_file,
|
||||
int mapping_index = -1;
|
||||
std::string canonical_disk_file = CanonicalizePath(disk_file);
|
||||
|
||||
- for (int i = 0; i < mappings_.size(); i++) {
|
||||
+ for (size_t i = 0; i < mappings_.size(); i++) {
|
||||
// Apply the mapping in reverse.
|
||||
if (ApplyMapping(canonical_disk_file, mappings_[i].disk_path,
|
||||
mappings_[i].virtual_path, virtual_file)) {
|
||||
diff --git a/src/google/protobuf/compiler/parser.cc b/src/google/protobuf/compiler/parser.cc
|
||||
index 5bd37d147bc449444f875f89367a208a32a9146e..e36a4a74359fcace20c017f241d58930660b9381 100644
|
||||
--- a/src/google/protobuf/compiler/parser.cc
|
||||
+++ b/src/google/protobuf/compiler/parser.cc
|
||||
@@ -159,7 +159,7 @@ bool IsLowerUnderscore(const std::string& name) {
|
||||
}
|
||||
|
||||
bool IsNumberFollowUnderscore(const std::string& name) {
|
||||
- for (int i = 1; i < name.length(); i++) {
|
||||
+ for (size_t i = 1; i < name.length(); i++) {
|
||||
const char c = name[i];
|
||||
if (IsNumber(c) && name[i - 1] == '_') {
|
||||
return true;
|
||||
@@ -500,7 +500,7 @@ void Parser::LocationRecorder::AttachComments(
|
||||
if (!trailing->empty()) {
|
||||
location_->mutable_trailing_comments()->swap(*trailing);
|
||||
}
|
||||
- for (int i = 0; i < detached_comments->size(); ++i) {
|
||||
+ for (size_t i = 0; i < detached_comments->size(); ++i) {
|
||||
location_->add_leading_detached_comments()->swap((*detached_comments)[i]);
|
||||
}
|
||||
detached_comments->clear();
|
||||
diff --git a/src/google/protobuf/io/io_win32.cc b/src/google/protobuf/io/io_win32.cc
|
||||
index 4e8190880918f1ba155d75db76d6c1ee0b003247..78c07d0d771b9c227c6cd930fc91d272fd67500f 100644
|
||||
--- a/src/google/protobuf/io/io_win32.cc
|
||||
+++ b/src/google/protobuf/io/io_win32.cc
|
||||
@@ -198,7 +198,7 @@ wstring normalize(wstring path) {
|
||||
// Join all segments.
|
||||
bool first = true;
|
||||
std::wstringstream result;
|
||||
- for (int i = 0; i < segments.size(); ++i) {
|
||||
+ for (size_t i = 0; i < segments.size(); ++i) {
|
||||
if (!first) {
|
||||
result << L'\\';
|
||||
}
|
||||
diff --git a/src/google/protobuf/stubs/stringprintf.cc b/src/google/protobuf/stubs/stringprintf.cc
|
||||
index a6ad4c0da4080f5241c26176046a3add5247e25c..8b890f47c386f0d6b0ab9fd9928fae03edd076eb 100644
|
||||
--- a/src/google/protobuf/stubs/stringprintf.cc
|
||||
+++ b/src/google/protobuf/stubs/stringprintf.cc
|
||||
@@ -149,10 +149,10 @@ std::string StringPrintfVector(const char* format,
|
||||
// or displaying random chunks of memory to users.
|
||||
|
||||
const char* cstr[kStringPrintfVectorMaxArgs];
|
||||
- for (int i = 0; i < v.size(); ++i) {
|
||||
+ for (size_t i = 0; i < v.size(); ++i) {
|
||||
cstr[i] = v[i].c_str();
|
||||
}
|
||||
- for (int i = v.size(); i < GOOGLE_ARRAYSIZE(cstr); ++i) {
|
||||
+ for (size_t i = v.size(); i < GOOGLE_ARRAYSIZE(cstr); ++i) {
|
||||
cstr[i] = &string_printf_empty_block[0];
|
||||
}
|
||||
|
||||
diff --git a/src/google/protobuf/stubs/strutil.cc b/src/google/protobuf/stubs/strutil.cc
|
||||
index 594c8eac6a6ebff6d8bc8cc8518e3fd521f24da1..3462e91ff273dc071628f06b91698a0f166514fc 100644
|
||||
--- a/src/google/protobuf/stubs/strutil.cc
|
||||
+++ b/src/google/protobuf/stubs/strutil.cc
|
||||
@@ -697,7 +697,7 @@ bool safe_parse_positive_int(std::string text, IntType *value_p) {
|
||||
IntType value = 0;
|
||||
const IntType vmax = std::numeric_limits<IntType>::max();
|
||||
assert(vmax > 0);
|
||||
- assert(vmax >= base);
|
||||
+ assert(static_cast<int>(vmax) >= base);
|
||||
const IntType vmax_over_base = vmax / base;
|
||||
const char* start = text.data();
|
||||
const char* end = start + text.size();
|
||||
diff --git a/src/google/protobuf/stubs/substitute.cc b/src/google/protobuf/stubs/substitute.cc
|
||||
index d301682ee3377760430839bc5d6530621333e48d..8c75b2562e43d9d4ade3ef187d38e2e81b43e2c7 100644
|
||||
--- a/src/google/protobuf/stubs/substitute.cc
|
||||
+++ b/src/google/protobuf/stubs/substitute.cc
|
||||
@@ -128,7 +128,7 @@ void SubstituteAndAppend(std::string* output, const char* format,
|
||||
}
|
||||
}
|
||||
|
||||
- GOOGLE_DCHECK_EQ(target - output->data(), output->size());
|
||||
+ GOOGLE_DCHECK_EQ(target - output->data(), static_cast<int>(output->size()));
|
||||
}
|
||||
|
||||
} // namespace strings
|
||||
diff --git a/src/google/protobuf/util/field_mask_util.cc b/src/google/protobuf/util/field_mask_util.cc
|
||||
index 700e59004a083c731477bcc0bb4d5c36d06f306c..9a40b851a9e51d30b286ff5d89707bf9f279d0c0 100644
|
||||
--- a/src/google/protobuf/util/field_mask_util.cc
|
||||
+++ b/src/google/protobuf/util/field_mask_util.cc
|
||||
@@ -366,7 +366,7 @@ void FieldMaskTree::RemovePath(const std::string& path,
|
||||
Node* node = &root_;
|
||||
const Descriptor* current_descriptor = descriptor;
|
||||
Node* new_branch_node = nullptr;
|
||||
- for (int i = 0; i < parts.size(); ++i) {
|
||||
+ for (size_t i = 0; i < parts.size(); ++i) {
|
||||
nodes[i] = node;
|
||||
const FieldDescriptor* field_descriptor =
|
||||
current_descriptor->FindFieldByName(parts[i]);
|
||||
diff --git a/src/google/protobuf/util/internal/datapiece.cc b/src/google/protobuf/util/internal/datapiece.cc
|
||||
index 3e7aa84da7181e2ab270e181b9f63deb1905542f..56f4a18fa4afc64708938fa5352937cdd17b5747 100644
|
||||
--- a/src/google/protobuf/util/internal/datapiece.cc
|
||||
+++ b/src/google/protobuf/util/internal/datapiece.cc
|
||||
@@ -53,6 +53,10 @@ namespace {
|
||||
|
||||
template <typename To, typename From>
|
||||
util::StatusOr<To> ValidateNumberConversion(To after, From before) {
|
||||
+#ifdef __GNUC__
|
||||
+#pragma GCC diagnostic push
|
||||
+#pragma GCC diagnostic ignored "-Wsign-compare"
|
||||
+#endif
|
||||
if (after == before &&
|
||||
MathUtil::Sign<From>(before) == MathUtil::Sign<To>(after)) {
|
||||
return after;
|
||||
@@ -62,6 +66,9 @@ util::StatusOr<To> ValidateNumberConversion(To after, From before) {
|
||||
: std::is_same<From, double>::value ? DoubleAsString(before)
|
||||
: FloatAsString(before));
|
||||
}
|
||||
+#ifdef __GNUC__
|
||||
+#pragma GCC diagnostic pop
|
||||
+#endif
|
||||
}
|
||||
|
||||
// For general conversion between
|
||||
diff --git a/src/google/protobuf/util/internal/default_value_objectwriter.cc b/src/google/protobuf/util/internal/default_value_objectwriter.cc
|
||||
index 7f61cdafa7c771a69364c5e9c49667535b16d957..a7d4ce78bd47e0250def474df8937927be9ef116 100644
|
||||
--- a/src/google/protobuf/util/internal/default_value_objectwriter.cc
|
||||
+++ b/src/google/protobuf/util/internal/default_value_objectwriter.cc
|
||||
@@ -312,7 +312,7 @@ void DefaultValueObjectWriter::Node::PopulateChildren(
|
||||
std::unordered_map<std::string, int> orig_children_map;
|
||||
|
||||
// Creates a map of child nodes to speed up lookup.
|
||||
- for (int i = 0; i < children_.size(); ++i) {
|
||||
+ for (size_t i = 0; i < children_.size(); ++i) {
|
||||
InsertIfNotPresent(&orig_children_map, children_[i]->name_, i);
|
||||
}
|
||||
|
||||
@@ -389,7 +389,7 @@ void DefaultValueObjectWriter::Node::PopulateChildren(
|
||||
new_children.push_back(child.release());
|
||||
}
|
||||
// Adds all leftover nodes in children_ to the beginning of new_child.
|
||||
- for (int i = 0; i < children_.size(); ++i) {
|
||||
+ for (size_t i = 0; i < children_.size(); ++i) {
|
||||
if (children_[i] == nullptr) {
|
||||
continue;
|
||||
}
|
||||
diff --git a/src/google/protobuf/util/internal/default_value_objectwriter.h b/src/google/protobuf/util/internal/default_value_objectwriter.h
|
||||
index a9e1673fa1e4ed35ab6890a44eed1d362265d914..1a151ab25951f8b0e1c9c724253b16524b88530a 100644
|
||||
--- a/src/google/protobuf/util/internal/default_value_objectwriter.h
|
||||
+++ b/src/google/protobuf/util/internal/default_value_objectwriter.h
|
||||
@@ -154,7 +154,7 @@ class PROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter {
|
||||
bool preserve_proto_field_names, bool use_ints_for_enums,
|
||||
FieldScrubCallBack field_scrub_callback);
|
||||
virtual ~Node() {
|
||||
- for (int i = 0; i < children_.size(); ++i) {
|
||||
+ for (size_t i = 0; i < children_.size(); ++i) {
|
||||
delete children_[i];
|
||||
}
|
||||
}
|
||||
diff --git a/src/google/protobuf/util/internal/json_escaping.cc b/src/google/protobuf/util/internal/json_escaping.cc
|
||||
index e4fa8cf788642e4a9d9c0460c287b1c24891b9fa..c192ddca7aff3984ffcbf82e13585bdf34ad8aae 100644
|
||||
--- a/src/google/protobuf/util/internal/json_escaping.cc
|
||||
+++ b/src/google/protobuf/util/internal/json_escaping.cc
|
||||
@@ -179,7 +179,7 @@ bool ReadCodePoint(StringPiece str, int index, uint32_t* cp,
|
||||
// the last unicode code point.
|
||||
*num_read = 0;
|
||||
}
|
||||
- while (*num_left > 0 && index < str.size()) {
|
||||
+ while (*num_left > 0 && index < static_cast<int>(str.size())) {
|
||||
uint32_t ch = static_cast<uint8_t>(str[index++]);
|
||||
--(*num_left);
|
||||
++(*num_read);
|
||||
@@ -309,7 +309,7 @@ void JsonEscaping::Escape(strings::ByteSource* input,
|
||||
while (input->Available() > 0) {
|
||||
StringPiece str = input->Peek();
|
||||
StringPiece escaped;
|
||||
- int i = 0;
|
||||
+ size_t i = 0;
|
||||
int num_read;
|
||||
bool ok;
|
||||
bool cp_was_split = num_left > 0;
|
||||
@@ -349,7 +349,7 @@ void JsonEscaping::Escape(StringPiece input, strings::ByteSink* output) {
|
||||
const char* p = input.data();
|
||||
|
||||
bool can_skip_escaping = true;
|
||||
- for (int i = 0; i < len; i++) {
|
||||
+ for (size_t i = 0; i < len; i++) {
|
||||
char c = p[i];
|
||||
if (c < 0x20 || c >= 0x7F || c == '"' || c == '<' || c == '>' ||
|
||||
c == '\\') {
|
||||
diff --git a/src/google/protobuf/util/internal/json_objectwriter.h b/src/google/protobuf/util/internal/json_objectwriter.h
|
||||
index cb7dff6e9fe79858a73b2c7501106fe8d05ccac5..92348da3b5c3f07e6146136352f976c94fe54340 100644
|
||||
--- a/src/google/protobuf/util/internal/json_objectwriter.h
|
||||
+++ b/src/google/protobuf/util/internal/json_objectwriter.h
|
||||
@@ -102,7 +102,7 @@ class PROTOBUF_EXPORT JsonObjectWriter : public StructuredObjectWriter {
|
||||
if (!indent_string.empty()) {
|
||||
indent_char_ = indent_string[0];
|
||||
indent_count_ = indent_string.length();
|
||||
- for (int i = 1; i < indent_string.length(); i++) {
|
||||
+ for (size_t i = 1; i < indent_string.length(); i++) {
|
||||
if (indent_char_ != indent_string_[i]) {
|
||||
indent_char_ = '\0';
|
||||
indent_count_ = 0;
|
||||
diff --git a/src/google/protobuf/util/internal/json_stream_parser.cc b/src/google/protobuf/util/internal/json_stream_parser.cc
|
||||
index 5c34dbccafb9f40249ba3c0b7318b2e897f203dc..e786781f6de23c8a7ea282d061df6032111f6d21 100644
|
||||
--- a/src/google/protobuf/util/internal/json_stream_parser.cc
|
||||
+++ b/src/google/protobuf/util/internal/json_stream_parser.cc
|
||||
@@ -80,7 +80,7 @@ inline void ReplaceInvalidCodePoints(StringPiece str,
|
||||
const std::string& replacement,
|
||||
std::string* dst) {
|
||||
while (!str.empty()) {
|
||||
- int n_valid_bytes = internal::UTF8SpnStructurallyValid(str);
|
||||
+ size_t n_valid_bytes = internal::UTF8SpnStructurallyValid(str);
|
||||
StringPiece valid_part = str.substr(0, n_valid_bytes);
|
||||
StrAppend(dst, valid_part);
|
||||
|
||||
@@ -98,7 +98,7 @@ inline void ReplaceInvalidCodePoints(StringPiece str,
|
||||
|
||||
static bool ConsumeKey(StringPiece* input, StringPiece* key) {
|
||||
if (input->empty() || !IsLetter((*input)[0])) return false;
|
||||
- int len = 1;
|
||||
+ size_t len = 1;
|
||||
for (; len < input->size(); ++len) {
|
||||
if (!IsAlphanumeric((*input)[len])) {
|
||||
break;
|
||||
@@ -113,7 +113,7 @@ static bool ConsumeKey(StringPiece* input, StringPiece* key) {
|
||||
static bool ConsumeKeyPermissive(StringPiece* input,
|
||||
StringPiece* key) {
|
||||
if (input->empty() || !IsLetter((*input)[0])) return false;
|
||||
- int len = 1;
|
||||
+ size_t len = 1;
|
||||
for (; len < input->size(); ++len) {
|
||||
if (IsKeySeparator((*input)[len])) {
|
||||
break;
|
||||
@@ -946,7 +946,7 @@ util::Status JsonStreamParser::ParseKey() {
|
||||
JsonStreamParser::TokenType JsonStreamParser::GetNextTokenType() {
|
||||
SkipWhitespace();
|
||||
|
||||
- int size = p_.size();
|
||||
+ size_t size = p_.size();
|
||||
if (size == 0) {
|
||||
// If we ran out of data, report unknown and we'll place the previous parse
|
||||
// type onto the stack and try again when we have more data.
|
||||
diff --git a/src/google/protobuf/util/internal/proto_writer.cc b/src/google/protobuf/util/internal/proto_writer.cc
|
||||
index afa5e2e474b6960b8826a40b73615d5dffd971de..11b6df13d8f4f9506e828c39d6e74bc8acceb23d 100644
|
||||
--- a/src/google/protobuf/util/internal/proto_writer.cc
|
||||
+++ b/src/google/protobuf/util/internal/proto_writer.cc
|
||||
@@ -408,7 +408,7 @@ std::string ProtoWriter::ProtoElement::ToString() const {
|
||||
if (!ow_->IsRepeated(*(now->parent_field_)) ||
|
||||
now->parent()->parent_field_ != now->parent_field_) {
|
||||
std::string name = now->parent_field_->name();
|
||||
- int i = 0;
|
||||
+ size_t i = 0;
|
||||
while (i < name.size() &&
|
||||
(ascii_isalnum(name[i]) || name[i] == '_'))
|
||||
++i;
|
||||
diff --git a/src/google/protobuf/util/internal/protostream_objectwriter.cc b/src/google/protobuf/util/internal/protostream_objectwriter.cc
|
||||
index ecb219e06e514b1a6ba0e3e343126a75852d0a1d..ce94cfcefb417203f80142c54003efea283f6a1c 100644
|
||||
--- a/src/google/protobuf/util/internal/protostream_objectwriter.cc
|
||||
+++ b/src/google/protobuf/util/internal/protostream_objectwriter.cc
|
||||
@@ -378,7 +378,7 @@ void ProtoStreamObjectWriter::AnyWriter::StartAny(const DataPiece& value) {
|
||||
|
||||
// Now we know the proto type and can interpret all data fields we gathered
|
||||
// before the "@type" field.
|
||||
- for (int i = 0; i < uninterpreted_events_.size(); ++i) {
|
||||
+ for (size_t i = 0; i < uninterpreted_events_.size(); ++i) {
|
||||
uninterpreted_events_[i].Replay(this);
|
||||
}
|
||||
}
|
||||
diff --git a/src/google/protobuf/util/internal/utility.cc b/src/google/protobuf/util/internal/utility.cc
|
||||
index 918ee17d9b040ae1bf9d98e3f46f75770c471393..3c4ac086d594d67b334cbc1dc046c281cd59a374 100644
|
||||
--- a/src/google/protobuf/util/internal/utility.cc
|
||||
+++ b/src/google/protobuf/util/internal/utility.cc
|
||||
@@ -345,7 +345,7 @@ void DeleteWellKnownTypes() { delete well_known_types_; }
|
||||
|
||||
void InitWellKnownTypes() {
|
||||
well_known_types_ = new std::set<std::string>;
|
||||
- for (int i = 0; i < GOOGLE_ARRAYSIZE(well_known_types_name_array_); ++i) {
|
||||
+ for (size_t i = 0; i < GOOGLE_ARRAYSIZE(well_known_types_name_array_); ++i) {
|
||||
well_known_types_->insert(well_known_types_name_array_[i]);
|
||||
}
|
||||
google::protobuf::internal::OnShutdown(&DeleteWellKnownTypes);
|
||||
diff --git a/src/google/protobuf/util/json_util.cc b/src/google/protobuf/util/json_util.cc
|
||||
index c39c10d87b7d8bf6fc18cae1ce459257c45945d6..a9b1c52a73c86d3e3655ba0748f2a82c68bd40ce 100644
|
||||
--- a/src/google/protobuf/util/json_util.cc
|
||||
+++ b/src/google/protobuf/util/json_util.cc
|
||||
@@ -64,7 +64,7 @@ ZeroCopyStreamByteSink::~ZeroCopyStreamByteSink() {
|
||||
|
||||
void ZeroCopyStreamByteSink::Append(const char* bytes, size_t len) {
|
||||
while (true) {
|
||||
- if (len <= buffer_size_) { // NOLINT
|
||||
+ if (static_cast<int>(len) <= buffer_size_) { // NOLINT
|
||||
memcpy(buffer_, bytes, len);
|
||||
buffer_ = static_cast<char*>(buffer_) + len;
|
||||
buffer_size_ -= len;
|
||||
@@ -1,22 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Johnson <johnson.peter@gmail.com>
|
||||
Date: Sat, 10 Jun 2023 14:41:39 -0700
|
||||
Subject: [PATCH 02/15] Remove redundant move
|
||||
|
||||
---
|
||||
src/google/protobuf/extension_set.h | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/google/protobuf/extension_set.h b/src/google/protobuf/extension_set.h
|
||||
index 0e6d0521104d7f721bdbad1dd593233b035c5b85..b5343689ef7c16442995746439bbe8928022c593 100644
|
||||
--- a/src/google/protobuf/extension_set.h
|
||||
+++ b/src/google/protobuf/extension_set.h
|
||||
@@ -714,7 +714,7 @@ class PROTOBUF_EXPORT ExtensionSet {
|
||||
static KeyValueFunctor ForEach(Iterator begin, Iterator end,
|
||||
KeyValueFunctor func) {
|
||||
for (Iterator it = begin; it != end; ++it) func(it->first, it->second);
|
||||
- return std::move(func);
|
||||
+ return func;
|
||||
}
|
||||
|
||||
// Applies a functor to the <int, Extension&> pairs in sorted order.
|
||||
@@ -1,168 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Johnson <johnson.peter@gmail.com>
|
||||
Date: Sat, 10 Jun 2023 15:00:20 -0700
|
||||
Subject: [PATCH 03/15] Fix maybe-uninitialized warnings
|
||||
|
||||
---
|
||||
src/google/protobuf/arena.cc | 6 +++---
|
||||
src/google/protobuf/arena_impl.h | 4 ++--
|
||||
src/google/protobuf/extension_set_inl.h | 2 +-
|
||||
.../protobuf/generated_message_tctable_lite.cc | 16 ++++++++--------
|
||||
src/google/protobuf/io/coded_stream.cc | 2 +-
|
||||
5 files changed, 15 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/src/google/protobuf/arena.cc b/src/google/protobuf/arena.cc
|
||||
index 6ba508a5f0f3436d52ccc326cc932ceed3cd79fa..194404213ee5f6ad05b1e01f2bff23859d60dc56 100644
|
||||
--- a/src/google/protobuf/arena.cc
|
||||
+++ b/src/google/protobuf/arena.cc
|
||||
@@ -411,7 +411,7 @@ uint64_t ThreadSafeArena::Reset() {
|
||||
std::pair<void*, SerialArena::CleanupNode*>
|
||||
ThreadSafeArena::AllocateAlignedWithCleanup(size_t n,
|
||||
const std::type_info* type) {
|
||||
- SerialArena* arena;
|
||||
+ SerialArena* arena = nullptr;
|
||||
if (PROTOBUF_PREDICT_TRUE(!alloc_policy_.should_record_allocs() &&
|
||||
GetSerialArenaFast(&arena))) {
|
||||
return arena->AllocateAlignedWithCleanup(n, alloc_policy_.get());
|
||||
@@ -421,7 +421,7 @@ ThreadSafeArena::AllocateAlignedWithCleanup(size_t n,
|
||||
}
|
||||
|
||||
void ThreadSafeArena::AddCleanup(void* elem, void (*cleanup)(void*)) {
|
||||
- SerialArena* arena;
|
||||
+ SerialArena* arena = nullptr;
|
||||
if (PROTOBUF_PREDICT_FALSE(!GetSerialArenaFast(&arena))) {
|
||||
arena = GetSerialArenaFallback(&thread_cache());
|
||||
}
|
||||
@@ -433,7 +433,7 @@ void* ThreadSafeArena::AllocateAlignedFallback(size_t n,
|
||||
const std::type_info* type) {
|
||||
if (alloc_policy_.should_record_allocs()) {
|
||||
alloc_policy_.RecordAlloc(type, n);
|
||||
- SerialArena* arena;
|
||||
+ SerialArena* arena = nullptr;
|
||||
if (PROTOBUF_PREDICT_TRUE(GetSerialArenaFast(&arena))) {
|
||||
return arena->AllocateAligned(n, alloc_policy_.get());
|
||||
}
|
||||
diff --git a/src/google/protobuf/arena_impl.h b/src/google/protobuf/arena_impl.h
|
||||
index 76727688b558354be18f0c6576db1d4619348ef4..8af70c48f13feece7cf8580e71845ec267ddaddb 100644
|
||||
--- a/src/google/protobuf/arena_impl.h
|
||||
+++ b/src/google/protobuf/arena_impl.h
|
||||
@@ -482,7 +482,7 @@ class PROTOBUF_EXPORT ThreadSafeArena {
|
||||
|
||||
template <AllocationClient alloc_client = AllocationClient::kDefault>
|
||||
void* AllocateAligned(size_t n, const std::type_info* type) {
|
||||
- SerialArena* arena;
|
||||
+ SerialArena* arena = nullptr;
|
||||
if (PROTOBUF_PREDICT_TRUE(!alloc_policy_.should_record_allocs() &&
|
||||
GetSerialArenaFast(&arena))) {
|
||||
return arena->AllocateAligned<alloc_client>(n, AllocPolicy());
|
||||
@@ -492,7 +492,7 @@ class PROTOBUF_EXPORT ThreadSafeArena {
|
||||
}
|
||||
|
||||
void ReturnArrayMemory(void* p, size_t size) {
|
||||
- SerialArena* arena;
|
||||
+ SerialArena* arena = nullptr;
|
||||
if (PROTOBUF_PREDICT_TRUE(GetSerialArenaFast(&arena))) {
|
||||
arena->ReturnArrayMemory(p, size);
|
||||
}
|
||||
diff --git a/src/google/protobuf/extension_set_inl.h b/src/google/protobuf/extension_set_inl.h
|
||||
index e4e711721d4d8690e1e87fc8e31df1b5836d4fd7..50c04cd41feccf6cb5fda2740d6d4adb874645d7 100644
|
||||
--- a/src/google/protobuf/extension_set_inl.h
|
||||
+++ b/src/google/protobuf/extension_set_inl.h
|
||||
@@ -206,7 +206,7 @@ const char* ExtensionSet::ParseMessageSetItemTmpl(
|
||||
const char* ptr, const Msg* extendee, internal::InternalMetadata* metadata,
|
||||
internal::ParseContext* ctx) {
|
||||
std::string payload;
|
||||
- uint32_t type_id;
|
||||
+ uint32_t type_id = 0;
|
||||
enum class State { kNoTag, kHasType, kHasPayload, kDone };
|
||||
State state = State::kNoTag;
|
||||
|
||||
diff --git a/src/google/protobuf/generated_message_tctable_lite.cc b/src/google/protobuf/generated_message_tctable_lite.cc
|
||||
index 9993811dca3229edc766061c4a8d54933bcb0eba..2268b2be4d4c60c545765469549d73c6a468dac8 100644
|
||||
--- a/src/google/protobuf/generated_message_tctable_lite.cc
|
||||
+++ b/src/google/protobuf/generated_message_tctable_lite.cc
|
||||
@@ -770,7 +770,7 @@ PROTOBUF_NOINLINE const char* TcParser::SingularVarBigint(
|
||||
};
|
||||
volatile Spill spill = {data.data, msg, table, hasbits};
|
||||
|
||||
- uint64_t tmp;
|
||||
+ uint64_t tmp = 0;
|
||||
PROTOBUF_ASSUME(static_cast<int8_t>(*ptr) < 0);
|
||||
ptr = ParseVarint(ptr, &tmp);
|
||||
|
||||
@@ -845,7 +845,7 @@ PROTOBUF_ALWAYS_INLINE const char* TcParser::RepeatedVarint(
|
||||
auto expected_tag = UnalignedLoad<TagType>(ptr);
|
||||
do {
|
||||
ptr += sizeof(TagType);
|
||||
- uint64_t tmp;
|
||||
+ uint64_t tmp = 0;
|
||||
ptr = ParseVarint(ptr, &tmp);
|
||||
if (ptr == nullptr) {
|
||||
return Error(PROTOBUF_TC_PARAM_PASS);
|
||||
@@ -1001,7 +1001,7 @@ PROTOBUF_ALWAYS_INLINE const char* TcParser::SingularEnum(
|
||||
}
|
||||
const char* ptr2 = ptr; // Save for unknown enum case
|
||||
ptr += sizeof(TagType); // Consume tag
|
||||
- uint64_t tmp;
|
||||
+ uint64_t tmp = 0;
|
||||
ptr = ParseVarint(ptr, &tmp);
|
||||
if (ptr == nullptr) {
|
||||
return Error(PROTOBUF_TC_PARAM_PASS);
|
||||
@@ -1052,7 +1052,7 @@ PROTOBUF_ALWAYS_INLINE const char* TcParser::RepeatedEnum(
|
||||
do {
|
||||
const char* ptr2 = ptr; // save for unknown enum case
|
||||
ptr += sizeof(TagType);
|
||||
- uint64_t tmp;
|
||||
+ uint64_t tmp = 0;
|
||||
ptr = ParseVarint(ptr, &tmp);
|
||||
if (ptr == nullptr) {
|
||||
return Error(PROTOBUF_TC_PARAM_PASS);
|
||||
@@ -1477,7 +1477,7 @@ const char* TcParser::MpVarint(PROTOBUF_TC_PARAM_DECL) {
|
||||
|
||||
// Parse the value:
|
||||
const char* ptr2 = ptr; // save for unknown enum case
|
||||
- uint64_t tmp;
|
||||
+ uint64_t tmp = 0;
|
||||
ptr = ParseVarint(ptr, &tmp);
|
||||
if (ptr == nullptr) return Error(PROTOBUF_TC_PARAM_PASS);
|
||||
|
||||
@@ -1542,7 +1542,7 @@ const char* TcParser::MpRepeatedVarint(PROTOBUF_TC_PARAM_DECL) {
|
||||
const char* ptr2 = ptr;
|
||||
uint32_t next_tag;
|
||||
do {
|
||||
- uint64_t tmp;
|
||||
+ uint64_t tmp = 0;
|
||||
ptr = ParseVarint(ptr2, &tmp);
|
||||
if (ptr == nullptr) return Error(PROTOBUF_TC_PARAM_PASS);
|
||||
field.Add(is_zigzag ? WireFormatLite::ZigZagDecode64(tmp) : tmp);
|
||||
@@ -1554,7 +1554,7 @@ const char* TcParser::MpRepeatedVarint(PROTOBUF_TC_PARAM_DECL) {
|
||||
const char* ptr2 = ptr;
|
||||
uint32_t next_tag;
|
||||
do {
|
||||
- uint64_t tmp;
|
||||
+ uint64_t tmp = 0;
|
||||
ptr = ParseVarint(ptr2, &tmp);
|
||||
if (ptr == nullptr) return Error(PROTOBUF_TC_PARAM_PASS);
|
||||
if (is_validated_enum) {
|
||||
@@ -1575,7 +1575,7 @@ const char* TcParser::MpRepeatedVarint(PROTOBUF_TC_PARAM_DECL) {
|
||||
const char* ptr2 = ptr;
|
||||
uint32_t next_tag;
|
||||
do {
|
||||
- uint64_t tmp;
|
||||
+ uint64_t tmp = 0;
|
||||
ptr = ParseVarint(ptr2, &tmp);
|
||||
if (ptr == nullptr) return Error(PROTOBUF_TC_PARAM_PASS);
|
||||
field.Add(static_cast<bool>(tmp));
|
||||
diff --git a/src/google/protobuf/io/coded_stream.cc b/src/google/protobuf/io/coded_stream.cc
|
||||
index 487e1b8a379b86bfa3097d68a64ee0a727d36cab..53997901f333292f71ac52e7f9c876bd918f7bf6 100644
|
||||
--- a/src/google/protobuf/io/coded_stream.cc
|
||||
+++ b/src/google/protobuf/io/coded_stream.cc
|
||||
@@ -462,7 +462,7 @@ int64_t CodedInputStream::ReadVarint32Fallback(uint32_t first_byte_or_zero) {
|
||||
(buffer_end_ > buffer_ && !(buffer_end_[-1] & 0x80))) {
|
||||
GOOGLE_DCHECK_NE(first_byte_or_zero, 0)
|
||||
<< "Caller should provide us with *buffer_ when buffer is non-empty";
|
||||
- uint32_t temp;
|
||||
+ uint32_t temp = 0;
|
||||
::std::pair<bool, const uint8_t*> p =
|
||||
ReadVarint32FromArray(first_byte_or_zero, buffer_, &temp);
|
||||
if (!p.first) return -1;
|
||||
@@ -1,38 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Johnson <johnson.peter@gmail.com>
|
||||
Date: Sat, 10 Jun 2023 15:03:38 -0700
|
||||
Subject: [PATCH 04/15] Fix coded_stream WriteRaw
|
||||
|
||||
---
|
||||
src/google/protobuf/implicit_weak_message.h | 2 +-
|
||||
src/google/protobuf/io/coded_stream.h | 4 ++--
|
||||
2 files changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/src/google/protobuf/implicit_weak_message.h b/src/google/protobuf/implicit_weak_message.h
|
||||
index b894ab4809090011f381828857d1674a6b7bff9b..c358c14c06f773d87f5089c75566a5a6fcba13e6 100644
|
||||
--- a/src/google/protobuf/implicit_weak_message.h
|
||||
+++ b/src/google/protobuf/implicit_weak_message.h
|
||||
@@ -100,7 +100,7 @@ class PROTOBUF_EXPORT ImplicitWeakMessage : public MessageLite {
|
||||
if (data_ == nullptr) {
|
||||
return target;
|
||||
}
|
||||
- return stream->WriteRaw(data_->data(), static_cast<int>(data_->size()),
|
||||
+ return stream->WriteRaw(data_->data(), data_->size(),
|
||||
target);
|
||||
}
|
||||
|
||||
diff --git a/src/google/protobuf/io/coded_stream.h b/src/google/protobuf/io/coded_stream.h
|
||||
index c8fc994f916d047c0a7b176e53c9e946ebd752de..6c0dd4ab4099d1d748957af8bfc5f8c59c2aa3d6 100644
|
||||
--- a/src/google/protobuf/io/coded_stream.h
|
||||
+++ b/src/google/protobuf/io/coded_stream.h
|
||||
@@ -677,8 +677,8 @@ class PROTOBUF_EXPORT EpsCopyOutputStream {
|
||||
return ptr;
|
||||
}
|
||||
|
||||
- uint8_t* WriteRaw(const void* data, int size, uint8_t* ptr) {
|
||||
- if (PROTOBUF_PREDICT_FALSE(end_ - ptr < size)) {
|
||||
+ uint8_t* WriteRaw(const void* data, size_t size, uint8_t* ptr) {
|
||||
+ if (PROTOBUF_PREDICT_FALSE(end_ - ptr < static_cast<int>(size))) {
|
||||
return WriteRawFallback(data, size, ptr);
|
||||
}
|
||||
std::memcpy(ptr, data, size);
|
||||
@@ -1,36 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Johnson <johnson.peter@gmail.com>
|
||||
Date: Sat, 10 Jun 2023 15:13:45 -0700
|
||||
Subject: [PATCH 05/15] Suppress enum-enum conversion warning
|
||||
|
||||
---
|
||||
src/google/protobuf/generated_message_tctable_impl.h | 9 +++++++++
|
||||
1 file changed, 9 insertions(+)
|
||||
|
||||
diff --git a/src/google/protobuf/generated_message_tctable_impl.h b/src/google/protobuf/generated_message_tctable_impl.h
|
||||
index 21fa5332d39b24e0bdb6432f27183df743d512c6..5aceeb39ae24866e7258d62cf5b025df0ba20fc5 100644
|
||||
--- a/src/google/protobuf/generated_message_tctable_impl.h
|
||||
+++ b/src/google/protobuf/generated_message_tctable_impl.h
|
||||
@@ -180,6 +180,12 @@ static_assert(kFmtShift + kFmtBits == 12, "number of bits changed");
|
||||
// This assertion should not change unless the storage width changes:
|
||||
static_assert(kFmtShift + kFmtBits <= 16, "too many bits");
|
||||
|
||||
+#ifdef __GNUC__
|
||||
+#pragma GCC diagnostic push
|
||||
+#if __GNUC__ >= 12 || (__GNUC__ == 11 && __GNUC_MINOR__ >= 1)
|
||||
+#pragma GCC diagnostic ignored "-Wdeprecated-enum-enum-conversion"
|
||||
+#endif
|
||||
+#endif
|
||||
// Convenience aliases (16 bits, with format):
|
||||
enum FieldType : uint16_t {
|
||||
// Numeric types:
|
||||
@@ -232,6 +238,9 @@ enum FieldType : uint16_t {
|
||||
// Map types:
|
||||
kMap = kFkMap,
|
||||
};
|
||||
+#ifdef __GNUC__
|
||||
+#pragma GCC diagnostic pop
|
||||
+#endif
|
||||
|
||||
// clang-format on
|
||||
} // namespace field_layout
|
||||
@@ -1,23 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Johnson <johnson.peter@gmail.com>
|
||||
Date: Sat, 10 Jun 2023 15:16:46 -0700
|
||||
Subject: [PATCH 06/15] Fix noreturn function returning
|
||||
|
||||
---
|
||||
src/google/protobuf/generated_message_tctable_impl.h | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/src/google/protobuf/generated_message_tctable_impl.h b/src/google/protobuf/generated_message_tctable_impl.h
|
||||
index 5aceeb39ae24866e7258d62cf5b025df0ba20fc5..c80ac0cd299c126398329c780534156bb1536e15 100644
|
||||
--- a/src/google/protobuf/generated_message_tctable_impl.h
|
||||
+++ b/src/google/protobuf/generated_message_tctable_impl.h
|
||||
@@ -262,6 +262,9 @@ template <size_t align>
|
||||
#endif
|
||||
void AlignFail(uintptr_t address) {
|
||||
GOOGLE_LOG(FATAL) << "Unaligned (" << align << ") access at " << address;
|
||||
+#ifdef __GNUC__
|
||||
+ __builtin_unreachable();
|
||||
+#endif
|
||||
}
|
||||
|
||||
extern template void AlignFail<4>(uintptr_t);
|
||||
@@ -1,29 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Johnson <johnson.peter@gmail.com>
|
||||
Date: Sat, 10 Jun 2023 15:59:45 -0700
|
||||
Subject: [PATCH 07/15] Work around GCC 12 restrict warning compiler bug
|
||||
|
||||
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105329
|
||||
---
|
||||
src/google/protobuf/io/tokenizer.cc | 7 +++++++
|
||||
1 file changed, 7 insertions(+)
|
||||
|
||||
diff --git a/src/google/protobuf/io/tokenizer.cc b/src/google/protobuf/io/tokenizer.cc
|
||||
index f9e07763e7362bd37267619336db841d0ae9df25..30d62ac9647b897c2e7c8ad43cd27ff0e08922a2 100644
|
||||
--- a/src/google/protobuf/io/tokenizer.cc
|
||||
+++ b/src/google/protobuf/io/tokenizer.cc
|
||||
@@ -585,7 +585,14 @@ Tokenizer::NextCommentStatus Tokenizer::TryConsumeCommentStart() {
|
||||
} else {
|
||||
// Oops, it was just a slash. Return it.
|
||||
current_.type = TYPE_SYMBOL;
|
||||
+#if defined(__GNUC__) && !defined(__clang__)
|
||||
+#pragma GCC diagnostic push
|
||||
+#pragma GCC diagnostic ignored "-Wrestrict"
|
||||
+#endif
|
||||
current_.text = "/";
|
||||
+#if defined(__GNUC__) && !defined(__clang__)
|
||||
+#pragma GCC diagnostic pop
|
||||
+#endif
|
||||
current_.line = line_;
|
||||
current_.column = column_ - 1;
|
||||
current_.end_column = column_;
|
||||
@@ -1,24 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Johnson <johnson.peter@gmail.com>
|
||||
Date: Tue, 13 Jun 2023 23:56:15 -0700
|
||||
Subject: [PATCH 08/15] Disable MSVC switch warning
|
||||
|
||||
---
|
||||
src/google/protobuf/generated_message_reflection.cc | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/src/google/protobuf/generated_message_reflection.cc b/src/google/protobuf/generated_message_reflection.cc
|
||||
index 2a807e066bb748f214e008971309ef15473344b5..599dde80b671085d87ff1812929cafe8d2aecf75 100644
|
||||
--- a/src/google/protobuf/generated_message_reflection.cc
|
||||
+++ b/src/google/protobuf/generated_message_reflection.cc
|
||||
@@ -75,6 +75,10 @@ using google::protobuf::internal::RepeatedPtrFieldBase;
|
||||
using google::protobuf::internal::StringSpaceUsedExcludingSelfLong;
|
||||
using google::protobuf::internal::WrappedMutex;
|
||||
|
||||
+#ifdef _MSC_VER
|
||||
+#pragma warning(disable : 4065)
|
||||
+#endif
|
||||
+
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Johnson <johnson.peter@gmail.com>
|
||||
Date: Tue, 13 Jun 2023 23:58:50 -0700
|
||||
Subject: [PATCH 09/15] Disable unused function warning
|
||||
|
||||
---
|
||||
src/google/protobuf/generated_message_tctable_lite.cc | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/src/google/protobuf/generated_message_tctable_lite.cc b/src/google/protobuf/generated_message_tctable_lite.cc
|
||||
index 2268b2be4d4c60c545765469549d73c6a468dac8..23557a614752a9f0c93d8bd56724f3bc0f962185 100644
|
||||
--- a/src/google/protobuf/generated_message_tctable_lite.cc
|
||||
+++ b/src/google/protobuf/generated_message_tctable_lite.cc
|
||||
@@ -43,6 +43,10 @@
|
||||
#include <google/protobuf/port_def.inc>
|
||||
// clang-format on
|
||||
|
||||
+#ifdef __GNUC__
|
||||
+#pragma GCC diagnostic ignored "-Wunused-function"
|
||||
+#endif
|
||||
+
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
@@ -1,95 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Johnson <johnson.peter@gmail.com>
|
||||
Date: Wed, 14 Jun 2023 00:02:26 -0700
|
||||
Subject: [PATCH 10/15] Disable pedantic warning
|
||||
|
||||
---
|
||||
src/google/protobuf/descriptor.h | 8 ++++++++
|
||||
src/google/protobuf/generated_message_reflection.cc | 2 ++
|
||||
src/google/protobuf/parse_context.h | 8 ++++++++
|
||||
src/google/protobuf/stubs/common.cc | 4 ++--
|
||||
4 files changed, 20 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/google/protobuf/descriptor.h b/src/google/protobuf/descriptor.h
|
||||
index 6e536e5705f8df4f7c13638d50c114cbfb92fb4a..bee3e32b9f1d5ba47b83d1e388716a3c3b6e82c6 100644
|
||||
--- a/src/google/protobuf/descriptor.h
|
||||
+++ b/src/google/protobuf/descriptor.h
|
||||
@@ -80,6 +80,10 @@
|
||||
#define PROTOBUF_EXPORT
|
||||
#endif
|
||||
|
||||
+#ifdef __GNUC__
|
||||
+#pragma GCC diagnostic push
|
||||
+#pragma GCC diagnostic ignored "-Wpedantic"
|
||||
+#endif
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
@@ -2434,6 +2438,10 @@ inline FileDescriptor::Syntax FileDescriptor::syntax() const {
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
+#ifdef __GNUC__
|
||||
+#pragma GCC diagnostic pop
|
||||
+#endif
|
||||
+
|
||||
#undef PROTOBUF_INTERNAL_CHECK_CLASS_SIZE
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
diff --git a/src/google/protobuf/generated_message_reflection.cc b/src/google/protobuf/generated_message_reflection.cc
|
||||
index 599dde80b671085d87ff1812929cafe8d2aecf75..aaed21920908b329e22c2e0d92f69397996a9f93 100644
|
||||
--- a/src/google/protobuf/generated_message_reflection.cc
|
||||
+++ b/src/google/protobuf/generated_message_reflection.cc
|
||||
@@ -77,6 +77,8 @@ using google::protobuf::internal::WrappedMutex;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4065)
|
||||
+#elif defined(__GNUC__)
|
||||
+#pragma GCC diagnostic ignored "-Wpedantic"
|
||||
#endif
|
||||
|
||||
namespace google {
|
||||
diff --git a/src/google/protobuf/parse_context.h b/src/google/protobuf/parse_context.h
|
||||
index 7aea50cdc385f0ed01b3989e12276494bf574939..97daae09cbff11fd3b4b99cee935aeb542c42eb4 100644
|
||||
--- a/src/google/protobuf/parse_context.h
|
||||
+++ b/src/google/protobuf/parse_context.h
|
||||
@@ -52,6 +52,10 @@
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
+#ifdef __GNUC__
|
||||
+#pragma GCC diagnostic push
|
||||
+#pragma GCC diagnostic ignored "-Wpedantic"
|
||||
+#endif
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
@@ -1020,6 +1024,10 @@ PROTOBUF_NODISCARD PROTOBUF_EXPORT const char* UnknownFieldParse(
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
+#ifdef __GNUC__
|
||||
+#pragma GCC diagnostic pop
|
||||
+#endif
|
||||
+
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_PARSE_CONTEXT_H__
|
||||
diff --git a/src/google/protobuf/stubs/common.cc b/src/google/protobuf/stubs/common.cc
|
||||
index e0a807ffbbc94d07176e20db230204384170607b..1423021b846966eb02d36c10df488f8aa0082a64 100644
|
||||
--- a/src/google/protobuf/stubs/common.cc
|
||||
+++ b/src/google/protobuf/stubs/common.cc
|
||||
@@ -277,11 +277,11 @@ LogHandler* SetLogHandler(LogHandler* new_func) {
|
||||
|
||||
LogSilencer::LogSilencer() {
|
||||
++internal::log_silencer_count_;
|
||||
-};
|
||||
+}
|
||||
|
||||
LogSilencer::~LogSilencer() {
|
||||
--internal::log_silencer_count_;
|
||||
-};
|
||||
+}
|
||||
|
||||
// ===================================================================
|
||||
// emulates google3/base/callback.cc
|
||||
@@ -1,35 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Johnson <johnson.peter@gmail.com>
|
||||
Date: Mon, 9 Oct 2023 19:28:08 -0700
|
||||
Subject: [PATCH 11/15] Avoid use of sprintf
|
||||
|
||||
---
|
||||
src/google/protobuf/stubs/strutil.cc | 14 +++++++++++---
|
||||
1 file changed, 11 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/src/google/protobuf/stubs/strutil.cc b/src/google/protobuf/stubs/strutil.cc
|
||||
index 3462e91ff273dc071628f06b91698a0f166514fc..58e03d0c4aa7c1b0337b5f650283f00117c12baa 100644
|
||||
--- a/src/google/protobuf/stubs/strutil.cc
|
||||
+++ b/src/google/protobuf/stubs/strutil.cc
|
||||
@@ -503,10 +503,18 @@ int CEscapeInternal(const char* src, int src_len, char* dest,
|
||||
(last_hex_escape && isxdigit(*src)))) {
|
||||
if (dest_len - used < 4) // need space for 4 letter escape
|
||||
return -1;
|
||||
- sprintf(dest + used, (use_hex ? "\\x%02x" : "\\%03o"),
|
||||
- static_cast<uint8_t>(*src));
|
||||
+ dest[used++] = '\\';
|
||||
+ if (use_hex) {
|
||||
+ constexpr char hexdigits[] = "0123456789abcdef";
|
||||
+ dest[used++] = 'x';
|
||||
+ dest[used++] = hexdigits[(static_cast<uint8_t>(*src) >> 4) & 0xf];
|
||||
+ dest[used++] = hexdigits[static_cast<uint8_t>(*src) & 0xf];
|
||||
+ } else {
|
||||
+ dest[used++] = '0' + ((static_cast<uint8_t>(*src) >> 6) & 0x3);
|
||||
+ dest[used++] = '0' + ((static_cast<uint8_t>(*src) >> 3) & 0x7);
|
||||
+ dest[used++] = '0' + (static_cast<uint8_t>(*src) & 0x7);
|
||||
+ }
|
||||
is_hex_escape = use_hex;
|
||||
- used += 4;
|
||||
} else {
|
||||
dest[used++] = *src; break;
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Tyler Veness <calcmogul@gmail.com>
|
||||
Date: Fri, 10 Nov 2023 14:17:53 -0800
|
||||
Subject: [PATCH 12/15] Suppress stringop-overflow warning false positives
|
||||
|
||||
---
|
||||
src/google/protobuf/io/coded_stream.h | 7 +++++++
|
||||
src/google/protobuf/unknown_field_set.cc | 7 +++++++
|
||||
2 files changed, 14 insertions(+)
|
||||
|
||||
diff --git a/src/google/protobuf/io/coded_stream.h b/src/google/protobuf/io/coded_stream.h
|
||||
index 6c0dd4ab4099d1d748957af8bfc5f8c59c2aa3d6..f43b7ee044673b33410a3ebec6a501ff434d061d 100644
|
||||
--- a/src/google/protobuf/io/coded_stream.h
|
||||
+++ b/src/google/protobuf/io/coded_stream.h
|
||||
@@ -681,7 +681,14 @@ class PROTOBUF_EXPORT EpsCopyOutputStream {
|
||||
if (PROTOBUF_PREDICT_FALSE(end_ - ptr < static_cast<int>(size))) {
|
||||
return WriteRawFallback(data, size, ptr);
|
||||
}
|
||||
+#if __GNUC__ >= 12
|
||||
+#pragma GCC diagnostic push
|
||||
+#pragma GCC diagnostic ignored "-Wstringop-overflow="
|
||||
+#endif // __GNUC__ >= 12
|
||||
std::memcpy(ptr, data, size);
|
||||
+#if __GNUC__ >= 12
|
||||
+#pragma GCC diagnostic pop
|
||||
+#endif // __GNUC__ >= 12
|
||||
return ptr + size;
|
||||
}
|
||||
// Writes the buffer specified by data, size to the stream. Possibly by
|
||||
diff --git a/src/google/protobuf/unknown_field_set.cc b/src/google/protobuf/unknown_field_set.cc
|
||||
index 74c358e9a22c5475bfaef6c5ac63b05fc61b7074..5f6f7a1a298321e562112fed576a7086bd57643c 100644
|
||||
--- a/src/google/protobuf/unknown_field_set.cc
|
||||
+++ b/src/google/protobuf/unknown_field_set.cc
|
||||
@@ -96,9 +96,16 @@ void UnknownFieldSet::MergeFromAndDestroy(UnknownFieldSet* other) {
|
||||
if (fields_.empty()) {
|
||||
fields_ = std::move(other->fields_);
|
||||
} else {
|
||||
+#if __GNUC__ >= 12
|
||||
+#pragma GCC diagnostic push
|
||||
+#pragma GCC diagnostic ignored "-Wstringop-overflow="
|
||||
+#endif // __GNUC__ >= 12
|
||||
fields_.insert(fields_.end(),
|
||||
std::make_move_iterator(other->fields_.begin()),
|
||||
std::make_move_iterator(other->fields_.end()));
|
||||
+#if __GNUC__ >= 12
|
||||
+#pragma GCC diagnostic pop
|
||||
+#endif // __GNUC__ >= 12
|
||||
}
|
||||
other->fields_.clear();
|
||||
}
|
||||
@@ -1,167 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Thad House <thadhouse1@gmail.com>
|
||||
Date: Sun, 18 Aug 2024 22:43:37 -0700
|
||||
Subject: [PATCH 13/15] Switch descriptor to not use globals from header inline
|
||||
functions
|
||||
|
||||
---
|
||||
src/google/protobuf/descriptor.cc | 66 +++++++++++++++++++------------
|
||||
src/google/protobuf/descriptor.h | 20 +++++-----
|
||||
2 files changed, 51 insertions(+), 35 deletions(-)
|
||||
|
||||
diff --git a/src/google/protobuf/descriptor.cc b/src/google/protobuf/descriptor.cc
|
||||
index 5f3427dc72497b618c4dea3ec6985eeb39139349..5be05da4fb1c21fb1068ae7341cabef9dcf598a5 100644
|
||||
--- a/src/google/protobuf/descriptor.cc
|
||||
+++ b/src/google/protobuf/descriptor.cc
|
||||
@@ -791,31 +791,31 @@ class Symbol {
|
||||
const internal::SymbolBase* ptr_;
|
||||
};
|
||||
|
||||
-const FieldDescriptor::CppType
|
||||
- FieldDescriptor::kTypeToCppTypeMap[MAX_TYPE + 1] = {
|
||||
- static_cast<CppType>(0), // 0 is reserved for errors
|
||||
-
|
||||
- CPPTYPE_DOUBLE, // TYPE_DOUBLE
|
||||
- CPPTYPE_FLOAT, // TYPE_FLOAT
|
||||
- CPPTYPE_INT64, // TYPE_INT64
|
||||
- CPPTYPE_UINT64, // TYPE_UINT64
|
||||
- CPPTYPE_INT32, // TYPE_INT32
|
||||
- CPPTYPE_UINT64, // TYPE_FIXED64
|
||||
- CPPTYPE_UINT32, // TYPE_FIXED32
|
||||
- CPPTYPE_BOOL, // TYPE_BOOL
|
||||
- CPPTYPE_STRING, // TYPE_STRING
|
||||
- CPPTYPE_MESSAGE, // TYPE_GROUP
|
||||
- CPPTYPE_MESSAGE, // TYPE_MESSAGE
|
||||
- CPPTYPE_STRING, // TYPE_BYTES
|
||||
- CPPTYPE_UINT32, // TYPE_UINT32
|
||||
- CPPTYPE_ENUM, // TYPE_ENUM
|
||||
- CPPTYPE_INT32, // TYPE_SFIXED32
|
||||
- CPPTYPE_INT64, // TYPE_SFIXED64
|
||||
- CPPTYPE_INT32, // TYPE_SINT32
|
||||
- CPPTYPE_INT64, // TYPE_SINT64
|
||||
+static const FieldDescriptor::CppType
|
||||
+ kTypeToCppTypeMap[FieldDescriptor::MAX_TYPE + 1] = {
|
||||
+ static_cast<FieldDescriptor::CppType>(0), // 0 is reserved for errors
|
||||
+
|
||||
+ FieldDescriptor::CPPTYPE_DOUBLE, // TYPE_DOUBLE
|
||||
+ FieldDescriptor::CPPTYPE_FLOAT, // TYPE_FLOAT
|
||||
+ FieldDescriptor::CPPTYPE_INT64, // TYPE_INT64
|
||||
+ FieldDescriptor::CPPTYPE_UINT64, // TYPE_UINT64
|
||||
+ FieldDescriptor::CPPTYPE_INT32, // TYPE_INT32
|
||||
+ FieldDescriptor::CPPTYPE_UINT64, // TYPE_FIXED64
|
||||
+ FieldDescriptor::CPPTYPE_UINT32, // TYPE_FIXED32
|
||||
+ FieldDescriptor::CPPTYPE_BOOL, // TYPE_BOOL
|
||||
+ FieldDescriptor::CPPTYPE_STRING, // TYPE_STRING
|
||||
+ FieldDescriptor::CPPTYPE_MESSAGE, // TYPE_GROUP
|
||||
+ FieldDescriptor::CPPTYPE_MESSAGE, // TYPE_MESSAGE
|
||||
+ FieldDescriptor::CPPTYPE_STRING, // TYPE_BYTES
|
||||
+ FieldDescriptor::CPPTYPE_UINT32, // TYPE_UINT32
|
||||
+ FieldDescriptor::CPPTYPE_ENUM, // TYPE_ENUM
|
||||
+ FieldDescriptor::CPPTYPE_INT32, // TYPE_SFIXED32
|
||||
+ FieldDescriptor::CPPTYPE_INT64, // TYPE_SFIXED64
|
||||
+ FieldDescriptor::CPPTYPE_INT32, // TYPE_SINT32
|
||||
+ FieldDescriptor::CPPTYPE_INT64, // TYPE_SINT64
|
||||
};
|
||||
|
||||
-const char* const FieldDescriptor::kTypeToName[MAX_TYPE + 1] = {
|
||||
+static const char* const kTypeToName[FieldDescriptor::MAX_TYPE + 1] = {
|
||||
"ERROR", // 0 is reserved for errors
|
||||
|
||||
"double", // TYPE_DOUBLE
|
||||
@@ -838,7 +838,7 @@ const char* const FieldDescriptor::kTypeToName[MAX_TYPE + 1] = {
|
||||
"sint64", // TYPE_SINT64
|
||||
};
|
||||
|
||||
-const char* const FieldDescriptor::kCppTypeToName[MAX_CPPTYPE + 1] = {
|
||||
+static const char* const kCppTypeToName[FieldDescriptor::MAX_CPPTYPE + 1] = {
|
||||
"ERROR", // 0 is reserved for errors
|
||||
|
||||
"int32", // CPPTYPE_INT32
|
||||
@@ -853,7 +853,7 @@ const char* const FieldDescriptor::kCppTypeToName[MAX_CPPTYPE + 1] = {
|
||||
"message", // CPPTYPE_MESSAGE
|
||||
};
|
||||
|
||||
-const char* const FieldDescriptor::kLabelToName[MAX_LABEL + 1] = {
|
||||
+static const char* const kLabelToName[FieldDescriptor::MAX_LABEL + 1] = {
|
||||
"ERROR", // 0 is reserved for errors
|
||||
|
||||
"optional", // LABEL_OPTIONAL
|
||||
@@ -861,6 +861,22 @@ const char* const FieldDescriptor::kLabelToName[MAX_LABEL + 1] = {
|
||||
"repeated", // LABEL_REPEATED
|
||||
};
|
||||
|
||||
+const FieldDescriptor::CppType *FieldDescriptor::GetTypeToCppTypeMap() {
|
||||
+ return kTypeToCppTypeMap;
|
||||
+}
|
||||
+
|
||||
+const char* const *FieldDescriptor::GetTypeToName() {
|
||||
+ return kTypeToName;
|
||||
+}
|
||||
+
|
||||
+const char* const *FieldDescriptor::GetCppTypeToName() {
|
||||
+ return kCppTypeToName;
|
||||
+}
|
||||
+
|
||||
+const char* const *FieldDescriptor::GetLabelToName() {
|
||||
+ return kLabelToName;
|
||||
+}
|
||||
+
|
||||
const char* FileDescriptor::SyntaxName(FileDescriptor::Syntax syntax) {
|
||||
switch (syntax) {
|
||||
case SYNTAX_PROTO2:
|
||||
diff --git a/src/google/protobuf/descriptor.h b/src/google/protobuf/descriptor.h
|
||||
index bee3e32b9f1d5ba47b83d1e388716a3c3b6e82c6..1cb2421b5362a757abe3735e15321e630b1cab3e 100644
|
||||
--- a/src/google/protobuf/descriptor.h
|
||||
+++ b/src/google/protobuf/descriptor.h
|
||||
@@ -976,13 +976,13 @@ class PROTOBUF_EXPORT FieldDescriptor : private internal::SymbolBase {
|
||||
mutable std::atomic<const Message*> default_generated_instance_;
|
||||
};
|
||||
|
||||
- static const CppType kTypeToCppTypeMap[MAX_TYPE + 1];
|
||||
+ static const CppType *GetTypeToCppTypeMap();
|
||||
|
||||
- static const char* const kTypeToName[MAX_TYPE + 1];
|
||||
+ static const char* const *GetTypeToName();
|
||||
|
||||
- static const char* const kCppTypeToName[MAX_CPPTYPE + 1];
|
||||
+ static const char* const *GetCppTypeToName();
|
||||
|
||||
- static const char* const kLabelToName[MAX_LABEL + 1];
|
||||
+ static const char* const *GetLabelToName();
|
||||
|
||||
// Must be constructed using DescriptorPool.
|
||||
FieldDescriptor() {}
|
||||
@@ -2392,27 +2392,27 @@ inline int MethodDescriptor::index() const {
|
||||
}
|
||||
|
||||
inline const char* FieldDescriptor::type_name() const {
|
||||
- return kTypeToName[type()];
|
||||
+ return GetTypeToName()[type()];
|
||||
}
|
||||
|
||||
inline FieldDescriptor::CppType FieldDescriptor::cpp_type() const {
|
||||
- return kTypeToCppTypeMap[type()];
|
||||
+ return GetTypeToCppTypeMap()[type()];
|
||||
}
|
||||
|
||||
inline const char* FieldDescriptor::cpp_type_name() const {
|
||||
- return kCppTypeToName[kTypeToCppTypeMap[type()]];
|
||||
+ return GetCppTypeToName()[GetTypeToCppTypeMap()[type()]];
|
||||
}
|
||||
|
||||
inline FieldDescriptor::CppType FieldDescriptor::TypeToCppType(Type type) {
|
||||
- return kTypeToCppTypeMap[type];
|
||||
+ return GetTypeToCppTypeMap()[type];
|
||||
}
|
||||
|
||||
inline const char* FieldDescriptor::TypeName(Type type) {
|
||||
- return kTypeToName[type];
|
||||
+ return GetTypeToName()[type];
|
||||
}
|
||||
|
||||
inline const char* FieldDescriptor::CppTypeName(CppType cpp_type) {
|
||||
- return kCppTypeToName[cpp_type];
|
||||
+ return GetCppTypeToName()[cpp_type];
|
||||
}
|
||||
|
||||
inline bool FieldDescriptor::IsTypePackable(Type field_type) {
|
||||
@@ -1,22 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: braykoff <99614905+Braykoff@users.noreply.github.com>
|
||||
Date: Mon, 23 Dec 2024 15:12:02 -0500
|
||||
Subject: [PATCH 14/15] Remove deprecated ATOMIC_VAR_INIT
|
||||
|
||||
---
|
||||
src/google/protobuf/stubs/common.cc | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/google/protobuf/stubs/common.cc b/src/google/protobuf/stubs/common.cc
|
||||
index 1423021b846966eb02d36c10df488f8aa0082a64..a16668a5964398c85c0268d82f652cf3c6aa668e 100644
|
||||
--- a/src/google/protobuf/stubs/common.cc
|
||||
+++ b/src/google/protobuf/stubs/common.cc
|
||||
@@ -178,7 +178,7 @@ void NullLogHandler(LogLevel /* level */, const char* /* filename */,
|
||||
}
|
||||
|
||||
static LogHandler* log_handler_ = &DefaultLogHandler;
|
||||
-static std::atomic<int> log_silencer_count_ = ATOMIC_VAR_INIT(0);
|
||||
+static std::atomic<int> log_silencer_count_{0};
|
||||
|
||||
LogMessage& LogMessage::operator<<(const std::string& value) {
|
||||
message_ += value;
|
||||
115
upstream_utils/upb.py
Executable file
115
upstream_utils/upb.py
Executable file
@@ -0,0 +1,115 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
|
||||
from upstream_utils import (
|
||||
Lib,
|
||||
comment_out_invalid_includes,
|
||||
copy_to,
|
||||
walk_cwd_and_copy_if,
|
||||
)
|
||||
|
||||
|
||||
def copy_upstream_src(wpilib_root: Path):
|
||||
upstream_root = Path(".").absolute()
|
||||
wpiutil = wpilib_root / "wpiutil"
|
||||
|
||||
# Delete old install
|
||||
for d in [
|
||||
"src/main/native/thirdparty/upb/include",
|
||||
"src/main/native/thirdparty/upb/src",
|
||||
]:
|
||||
shutil.rmtree(wpiutil / d, ignore_errors=True)
|
||||
|
||||
os.chdir(upstream_root / "third_party/utf8_range")
|
||||
copy_to(
|
||||
[Path("utf8_range.h")],
|
||||
wpiutil / "src/main/native/thirdparty/upb/include",
|
||||
)
|
||||
copy_to(
|
||||
[
|
||||
Path("utf8_range.c"),
|
||||
Path("utf8_range_sse.inc"),
|
||||
Path("utf8_range_neon.inc"),
|
||||
],
|
||||
wpiutil / "src/main/native/thirdparty/upb/src",
|
||||
)
|
||||
# Change directory to upb to minimize the number of files to walk
|
||||
os.chdir(upstream_root / "upb")
|
||||
include_files = walk_cwd_and_copy_if(
|
||||
lambda dp, f: (
|
||||
len(dp.parts) >= 1
|
||||
and (
|
||||
dp.parts[0] == "base"
|
||||
or dp.parts[0] == "hash"
|
||||
or dp.parts[0] == "mem"
|
||||
or (
|
||||
dp.parts[0] == "message"
|
||||
and "compare" not in f
|
||||
and "promote" not in f
|
||||
and "accessors_split64" not in f
|
||||
)
|
||||
or dp.parts[0] == "mini_descriptor"
|
||||
or (dp.parts[0] == "mini_table" and "compat" not in f)
|
||||
or dp.parts[0] == "port"
|
||||
or dp.parts[0] == "reflection"
|
||||
or (
|
||||
dp.parts[0] == "wire"
|
||||
and "byte_size" not in f
|
||||
and "decode_fast" not in dp.parts
|
||||
and "test_util" not in dp.parts
|
||||
)
|
||||
)
|
||||
and "cmake" not in dp.parts
|
||||
)
|
||||
and (f.endswith(".h") or f.endswith(".inc"))
|
||||
or f == "generated_code_support.h",
|
||||
wpiutil / "src/main/native/thirdparty/upb/include/upb",
|
||||
)
|
||||
for f in include_files:
|
||||
comment_out_invalid_includes(
|
||||
f, [wpiutil / "src/main/native/thirdparty/upb/include"]
|
||||
)
|
||||
|
||||
walk_cwd_and_copy_if(
|
||||
lambda dp, f: (
|
||||
len(dp.parts) >= 1
|
||||
and (
|
||||
dp.parts[0] == "base"
|
||||
or dp.parts[0] == "hash"
|
||||
or dp.parts[0] == "mem"
|
||||
or (
|
||||
dp.parts[0] == "message"
|
||||
and "compare" not in f
|
||||
and "promote" not in f
|
||||
)
|
||||
or dp.parts[0] == "mini_descriptor"
|
||||
or (dp.parts[0] == "mini_table" and "compat" not in f)
|
||||
or dp.parts[0] == "port"
|
||||
or dp.parts[0] == "reflection"
|
||||
or (
|
||||
dp.parts[0] == "wire"
|
||||
and "byte_size" not in f
|
||||
and "decode_fast" not in dp.parts
|
||||
)
|
||||
)
|
||||
)
|
||||
and f.endswith(".c")
|
||||
and not f == "descriptor.upb_minitable.c",
|
||||
wpiutil / "src/main/native/thirdparty/upb/src",
|
||||
)
|
||||
|
||||
|
||||
def main():
|
||||
name = "upb"
|
||||
url = "https://github.com/protocolbuffers/protobuf"
|
||||
tag = "v32.0"
|
||||
|
||||
upb = Lib(name, url, tag, copy_upstream_src)
|
||||
upb.main()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,77 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Gold856 <117957790+Gold856@users.noreply.github.com>
|
||||
Date: Sat, 24 May 2025 23:32:48 -0400
|
||||
Subject: [PATCH 1/5] Remove patches as they interfere with upstream_utils
|
||||
|
||||
---
|
||||
Disable_bundle_install.patch | 37 ------------------------------------
|
||||
Neverlink_jruby_jars.patch | 16 ----------------
|
||||
2 files changed, 53 deletions(-)
|
||||
delete mode 100644 Disable_bundle_install.patch
|
||||
delete mode 100644 Neverlink_jruby_jars.patch
|
||||
|
||||
diff --git a/Disable_bundle_install.patch b/Disable_bundle_install.patch
|
||||
deleted file mode 100644
|
||||
index baa83832f51813161ab98115a54583bc9dbea741..0000000000000000000000000000000000000000
|
||||
--- a/Disable_bundle_install.patch
|
||||
+++ /dev/null
|
||||
@@ -1,37 +0,0 @@
|
||||
-Subject: [PATCH] Disable bundle install
|
||||
----
|
||||
-Index: ruby/private/bundle_fetch.bzl
|
||||
-IDEA additional info:
|
||||
-Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
|
||||
-<+>UTF-8
|
||||
-===================================================================
|
||||
-diff --git a/ruby/private/bundle_fetch.bzl b/ruby/private/bundle_fetch.bzl
|
||||
---- a/ruby/private/bundle_fetch.bzl (revision 075937d3f2e22d4657f5c4693e7405d8952ab209)
|
||||
-+++ b/ruby/private/bundle_fetch.bzl (date 1740971614385)
|
||||
-@@ -168,16 +168,16 @@
|
||||
- )
|
||||
-
|
||||
- # Fetch Bundler and define an `rb_gem_install()` target for it.
|
||||
-- _download_gem(repository_ctx, gemfile_lock.bundler, cache_path, gemfile_lock.bundler.sha256)
|
||||
-- gem_full_names.append(":%s" % gemfile_lock.bundler.full_name)
|
||||
-- gem_install_fragments.append(
|
||||
-- _GEM_INSTALL_BUILD_FRAGMENT.format(
|
||||
-- name = gemfile_lock.bundler.full_name,
|
||||
-- gem = gemfile_lock.bundler.filename,
|
||||
-- cache_path = cache_path,
|
||||
-- ruby = ruby_toolchain_attr,
|
||||
-- ),
|
||||
-- )
|
||||
-+# _download_gem(repository_ctx, gemfile_lock.bundler, cache_path, gemfile_lock.bundler.sha256)
|
||||
-+# gem_full_names.append(":%s" % gemfile_lock.bundler.full_name)
|
||||
-+# gem_install_fragments.append(
|
||||
-+# _GEM_INSTALL_BUILD_FRAGMENT.format(
|
||||
-+# name = gemfile_lock.bundler.full_name,
|
||||
-+# gem = gemfile_lock.bundler.filename,
|
||||
-+# cache_path = cache_path,
|
||||
-+# ruby = ruby_toolchain_attr,
|
||||
-+# ),
|
||||
-+# )
|
||||
-
|
||||
- # Create `bin` package with shims for gem executables.
|
||||
- # This allows targets to depend on `@bundle//bin:rake`
|
||||
diff --git a/Neverlink_jruby_jars.patch b/Neverlink_jruby_jars.patch
|
||||
deleted file mode 100644
|
||||
index 48ccca6c7cd656312620b912ff6f465059b63a53..0000000000000000000000000000000000000000
|
||||
--- a/Neverlink_jruby_jars.patch
|
||||
+++ /dev/null
|
||||
@@ -1,16 +0,0 @@
|
||||
-Index: ruby/private/download/BUILD.tpl
|
||||
-IDEA additional info:
|
||||
-Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
|
||||
-<+>UTF-8
|
||||
-===================================================================
|
||||
-diff --git a/ruby/private/download/BUILD.tpl b/ruby/private/download/BUILD.tpl
|
||||
---- a/ruby/private/download/BUILD.tpl (revision 26e0ba621cb82933f28a59373cb6a7afe54fae95)
|
||||
-+++ b/ruby/private/download/BUILD.tpl (date 1745340325192)
|
||||
-@@ -33,6 +33,7 @@
|
||||
- ["dist/lib/**/*.jar"],
|
||||
- allow_empty = True,
|
||||
- ),
|
||||
-+ neverlink = True,
|
||||
- )
|
||||
-
|
||||
- rb_toolchain(
|
||||
@@ -0,0 +1,36 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Gold856 <117957790+Gold856@users.noreply.github.com>
|
||||
Date: Fri, 23 May 2025 23:57:11 -0400
|
||||
Subject: [PATCH 2/5] Set bootstrap stage to 0
|
||||
|
||||
---
|
||||
upb/port/def.inc | 2 ++
|
||||
upb/reflection/descriptor_bootstrap.h | 2 +-
|
||||
2 files changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/upb/port/def.inc b/upb/port/def.inc
|
||||
index d8ccc7b8ffe36d263a1f14731223ca8500ecb376..237aa87648661b05ce9a47fce00561bd2f262b13 100644
|
||||
--- a/upb/port/def.inc
|
||||
+++ b/upb/port/def.inc
|
||||
@@ -33,6 +33,8 @@
|
||||
#error upb requires C99 or C++17 or MSVC >= 2015.
|
||||
#endif
|
||||
|
||||
+#define UPB_BOOTSTRAP_STAGE 0
|
||||
+
|
||||
// Portable check for GCC minimum version:
|
||||
// https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html
|
||||
#if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__)
|
||||
diff --git a/upb/reflection/descriptor_bootstrap.h b/upb/reflection/descriptor_bootstrap.h
|
||||
index 8c501447e7ce4f7f404e075cb6be9301470ed0f9..ffb30ea949836dc0c9d1d3f73d0dfccc509e7d0d 100644
|
||||
--- a/upb/reflection/descriptor_bootstrap.h
|
||||
+++ b/upb/reflection/descriptor_bootstrap.h
|
||||
@@ -2,7 +2,7 @@
|
||||
#define GOOGLE_UPB_UPB_REFLECTION_DESCRIPTOR_BOOTSTRAP_H__
|
||||
|
||||
// IWYU pragma: begin_exports
|
||||
-
|
||||
+#define UPB_BOOTSTRAP_STAGE 0
|
||||
#if defined(UPB_BOOTSTRAP_STAGE) && UPB_BOOTSTRAP_STAGE == 0
|
||||
// This header is checked in.
|
||||
#include "upb/reflection/stage0/google/protobuf/descriptor.upb.h"
|
||||
@@ -0,0 +1,73 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Gold856 <117957790+Gold856@users.noreply.github.com>
|
||||
Date: Sat, 24 May 2025 23:17:42 -0400
|
||||
Subject: [PATCH 3/5] Replace global alloc struct with function
|
||||
|
||||
---
|
||||
upb/mem/alloc.c | 5 ++++-
|
||||
upb/mem/alloc.h | 8 ++++----
|
||||
upb/mem/arena.h | 4 ++--
|
||||
3 files changed, 10 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/upb/mem/alloc.c b/upb/mem/alloc.c
|
||||
index 3d70ee768c2473f84129e32c24c6cf3a7f78abef..bb1a635d2926fafa3b4f7dad677dbea482cea2ed 100644
|
||||
--- a/upb/mem/alloc.c
|
||||
+++ b/upb/mem/alloc.c
|
||||
@@ -25,4 +25,7 @@ static void* upb_global_allocfunc(upb_alloc* alloc, void* ptr, size_t oldsize,
|
||||
}
|
||||
}
|
||||
|
||||
-upb_alloc upb_alloc_global = {&upb_global_allocfunc};
|
||||
+upb_alloc alloc = {&upb_global_allocfunc};
|
||||
+upb_alloc* upb_alloc_global(void) {
|
||||
+ return &alloc;
|
||||
+}
|
||||
diff --git a/upb/mem/alloc.h b/upb/mem/alloc.h
|
||||
index 04da2337b498cd204b6d196e8b3ddc6ec9e66a7a..d4d7142569469868fd9a241bb0f0169b9918129f 100644
|
||||
--- a/upb/mem/alloc.h
|
||||
+++ b/upb/mem/alloc.h
|
||||
@@ -76,7 +76,7 @@ UPB_INLINE void upb_free_sized(upb_alloc* alloc, void* ptr, size_t size) {
|
||||
|
||||
// The global allocator used by upb. Uses the standard malloc()/free().
|
||||
|
||||
-extern upb_alloc upb_alloc_global;
|
||||
+upb_alloc* upb_alloc_global(void);
|
||||
|
||||
/* Functions that hard-code the global malloc.
|
||||
*
|
||||
@@ -84,14 +84,14 @@ extern upb_alloc upb_alloc_global;
|
||||
* allocator, like injecting out-of-memory faults in debug/testing builds. */
|
||||
|
||||
UPB_INLINE void* upb_gmalloc(size_t size) {
|
||||
- return upb_malloc(&upb_alloc_global, size);
|
||||
+ return upb_malloc(upb_alloc_global(), size);
|
||||
}
|
||||
|
||||
UPB_INLINE void* upb_grealloc(void* ptr, size_t oldsize, size_t size) {
|
||||
- return upb_realloc(&upb_alloc_global, ptr, oldsize, size);
|
||||
+ return upb_realloc(upb_alloc_global(), ptr, oldsize, size);
|
||||
}
|
||||
|
||||
-UPB_INLINE void upb_gfree(void* ptr) { upb_free(&upb_alloc_global, ptr); }
|
||||
+UPB_INLINE void upb_gfree(void* ptr) { upb_free(upb_alloc_global(), ptr); }
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
diff --git a/upb/mem/arena.h b/upb/mem/arena.h
|
||||
index 614ac2e043296a8993f0ac055040ea821c130fd9..24dd3830c2b0b6d403df132062e7a78903c201af 100644
|
||||
--- a/upb/mem/arena.h
|
||||
+++ b/upb/mem/arena.h
|
||||
@@ -78,11 +78,11 @@ uintptr_t upb_Arena_SpaceAllocated(const upb_Arena* a, size_t* fused_count);
|
||||
uint32_t upb_Arena_DebugRefCount(const upb_Arena* a);
|
||||
|
||||
UPB_API_INLINE upb_Arena* upb_Arena_New(void) {
|
||||
- return upb_Arena_Init(NULL, 0, &upb_alloc_global);
|
||||
+ return upb_Arena_Init(NULL, 0, upb_alloc_global());
|
||||
}
|
||||
|
||||
UPB_API_INLINE upb_Arena* upb_Arena_NewSized(size_t size_hint) {
|
||||
- return upb_Arena_Init(NULL, size_hint, &upb_alloc_global);
|
||||
+ return upb_Arena_Init(NULL, size_hint, upb_alloc_global());
|
||||
}
|
||||
|
||||
UPB_API_INLINE void* upb_Arena_Malloc(struct upb_Arena* a, size_t size);
|
||||
@@ -0,0 +1,23 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Gold856 <117957790+Gold856@users.noreply.github.com>
|
||||
Date: Mon, 26 May 2025 01:34:57 -0400
|
||||
Subject: [PATCH 4/5] Cast key to uint64_t before doing a bit shift This fixes
|
||||
compilation on Win32
|
||||
|
||||
---
|
||||
upb/hash/common.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/upb/hash/common.c b/upb/hash/common.c
|
||||
index ca0e488689e9cc54d143f505484497654d0f8c03..26c731764ce08f4e3f12900821fd1ebd1798da27 100644
|
||||
--- a/upb/hash/common.c
|
||||
+++ b/upb/hash/common.c
|
||||
@@ -95,7 +95,7 @@ typedef bool eqlfunc_t(upb_key k1, lookupkey_t k2);
|
||||
|
||||
static uint32_t upb_inthash(uintptr_t key) {
|
||||
if (sizeof(uintptr_t) == 8) {
|
||||
- return (uint32_t)key ^ (uint32_t)(key >> 32);
|
||||
+ return (uint32_t)key ^ (uint32_t)((uint64_t)(key) >> 32);
|
||||
} else {
|
||||
UPB_ASSERT(sizeof(uintptr_t) == 4);
|
||||
return (uint32_t)key;
|
||||
113
upstream_utils/upb_patches/0005-Suppress-warnings.patch
Normal file
113
upstream_utils/upb_patches/0005-Suppress-warnings.patch
Normal file
@@ -0,0 +1,113 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Gold856 <117957790+Gold856@users.noreply.github.com>
|
||||
Date: Mon, 26 May 2025 01:35:06 -0400
|
||||
Subject: [PATCH 5/5] Suppress warnings
|
||||
|
||||
---
|
||||
third_party/utf8_range/utf8_range.c | 2 +-
|
||||
upb/port/def.inc | 24 +++++++++++++++++++
|
||||
upb/port/undef.inc | 7 ++++++
|
||||
.../stage0/google/protobuf/descriptor.upb.c | 6 ++++-
|
||||
upb/wire/internal/decoder.h | 2 +-
|
||||
5 files changed, 38 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/third_party/utf8_range/utf8_range.c b/third_party/utf8_range/utf8_range.c
|
||||
index 049e2e21508cf368dab6cd49727ed2e413542f71..3eb4bd7c95df0ea2346987d78d8933872719b230 100644
|
||||
--- a/third_party/utf8_range/utf8_range.c
|
||||
+++ b/third_party/utf8_range/utf8_range.c
|
||||
@@ -20,11 +20,11 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
-
|
||||
#if defined(__GNUC__)
|
||||
#define FORCE_INLINE_ATTR __attribute__((always_inline)) inline
|
||||
#elif defined(_MSC_VER)
|
||||
#define FORCE_INLINE_ATTR __forceinline
|
||||
+#pragma warning (disable : 4141)
|
||||
#else
|
||||
#define FORCE_INLINE_ATTR inline
|
||||
#endif
|
||||
diff --git a/upb/port/def.inc b/upb/port/def.inc
|
||||
index 237aa87648661b05ce9a47fce00561bd2f262b13..50350e60cbbed1dfab186e7bf30ae821c378f027 100644
|
||||
--- a/upb/port/def.inc
|
||||
+++ b/upb/port/def.inc
|
||||
@@ -34,6 +34,30 @@
|
||||
#endif
|
||||
|
||||
#define UPB_BOOTSTRAP_STAGE 0
|
||||
+#if _WIN32
|
||||
+#pragma warning(push)
|
||||
+#pragma warning(disable : 4018 4047 4116 4146 4200 4244 4267 4334 4646 4789)
|
||||
+#elif defined(__clang__)
|
||||
+#pragma clang diagnostic push
|
||||
+#ifdef __cplusplus
|
||||
+#pragma clang diagnostic ignored "-Wc99-extensions"
|
||||
+#endif
|
||||
+#pragma clang diagnostic ignored "-Wsign-compare"
|
||||
+#pragma clang diagnostic ignored "-Wflexible-array-extensions"
|
||||
+#elif defined(__GNUC__)
|
||||
+#pragma GCC diagnostic push
|
||||
+#pragma GCC diagnostic ignored "-Wint-to-pointer-cast"
|
||||
+#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
|
||||
+#pragma GCC diagnostic ignored "-Wpedantic"
|
||||
+#ifndef __cplusplus
|
||||
+#pragma GCC diagnostic ignored "-Wpointer-to-int-cast"
|
||||
+#endif
|
||||
+#pragma GCC diagnostic ignored "-Wclobbered"
|
||||
+#pragma GCC diagnostic ignored "-Wsign-compare"
|
||||
+#pragma GCC diagnostic ignored "-Wstringop-overflow"
|
||||
+#pragma GCC diagnostic ignored "-Wstringop-overread"
|
||||
+#pragma GCC diagnostic ignored "-Wtype-limits"
|
||||
+#endif
|
||||
|
||||
// Portable check for GCC minimum version:
|
||||
// https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html
|
||||
diff --git a/upb/port/undef.inc b/upb/port/undef.inc
|
||||
index 764c81ce69fe63b956c97d337ba6d448c6ac70f9..b1cf7202b51dd350d49987e4e282461f9fa26399 100644
|
||||
--- a/upb/port/undef.inc
|
||||
+++ b/upb/port/undef.inc
|
||||
@@ -7,6 +7,13 @@
|
||||
|
||||
// This should #undef all macros #defined in def.inc
|
||||
|
||||
+#if _WIN32
|
||||
+#pragma warning(pop)
|
||||
+#elif defined(__clang__)
|
||||
+#pragma clang diagnostic pop
|
||||
+#elif defined(__GNUC__)
|
||||
+#pragma GCC diagnostic pop
|
||||
+#endif
|
||||
#undef UPB_SIZE
|
||||
#undef UPB_PTR_AT
|
||||
#undef UPB_SIZEOF_FLEX
|
||||
diff --git a/upb/reflection/stage0/google/protobuf/descriptor.upb.c b/upb/reflection/stage0/google/protobuf/descriptor.upb.c
|
||||
index 9595ce30983144322fc3616a674fce158abeb8a9..e2f59e7702a9bb1d36cfc6bba66bd350006c138f 100644
|
||||
--- a/upb/reflection/stage0/google/protobuf/descriptor.upb.c
|
||||
+++ b/upb/reflection/stage0/google/protobuf/descriptor.upb.c
|
||||
@@ -1,7 +1,11 @@
|
||||
#include <stddef.h>
|
||||
#include "upb/generated_code_support.h"
|
||||
#include "upb/reflection/descriptor_bootstrap.h"
|
||||
-
|
||||
+#ifdef __clang__
|
||||
+#pragma clang diagnostic ignored "-Wstrict-prototypes"
|
||||
+#elif defined(__GNUC__)
|
||||
+#pragma GCC diagnostic ignored "-Wstrict-prototypes"
|
||||
+#endif
|
||||
static upb_Arena* upb_BootstrapArena() {
|
||||
static upb_Arena* arena = NULL;
|
||||
if (!arena) arena = upb_Arena_New();
|
||||
diff --git a/upb/wire/internal/decoder.h b/upb/wire/internal/decoder.h
|
||||
index 8f5299d97323760a77d72247b6d1c90034b71194..3c59c6ee69caad2c280b6823079ed0e5ab122c48 100644
|
||||
--- a/upb/wire/internal/decoder.h
|
||||
+++ b/upb/wire/internal/decoder.h
|
||||
@@ -110,7 +110,7 @@ UPB_INLINE void _upb_Decoder_Trace(upb_Decoder* d, char event) {
|
||||
d->trace_ptr[1] = '\0';
|
||||
d->trace_ptr++;
|
||||
#endif
|
||||
-};
|
||||
+}
|
||||
|
||||
UPB_INLINE
|
||||
bool _upb_Decoder_VerifyUtf8Inline(const char* ptr, int len) {
|
||||
@@ -5,7 +5,6 @@
|
||||
"opencv",
|
||||
"fmt",
|
||||
"libuv",
|
||||
"protobuf",
|
||||
"libssh"
|
||||
],
|
||||
"builtin-baseline": "37c3e63a1306562f7f59c4c3c8892ddd50fdf992"
|
||||
|
||||
@@ -39,7 +39,6 @@ includeOtherLibs {
|
||||
^Eigen/
|
||||
^fmt/
|
||||
^gcem/
|
||||
^google/
|
||||
^gtest/
|
||||
^unsupported/
|
||||
^wpi/
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
#include <google/protobuf/arena.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <wpi/SmallVector.h>
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
#include <google/protobuf/arena.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "../../ProtoTestBase.h"
|
||||
|
||||
@@ -43,9 +43,9 @@ repoRootNameOverride {
|
||||
|
||||
includeOtherLibs {
|
||||
^fmt/
|
||||
^google/
|
||||
^gmock/
|
||||
^gtest/
|
||||
^upb/
|
||||
}
|
||||
|
||||
includeGuardRoots {
|
||||
|
||||
@@ -116,12 +116,6 @@ third_party_cc_lib_helper(
|
||||
src_root = "src/main/native/thirdparty/mpack/src",
|
||||
)
|
||||
|
||||
third_party_cc_lib_helper(
|
||||
name = "protobuf",
|
||||
include_root = "src/main/native/thirdparty/protobuf/include",
|
||||
src_root = "src/main/native/thirdparty/protobuf/src",
|
||||
)
|
||||
|
||||
third_party_cc_lib_helper(
|
||||
name = "nanopb",
|
||||
include_root = "src/main/native/thirdparty/nanopb/include",
|
||||
@@ -133,6 +127,12 @@ third_party_cc_lib_helper(
|
||||
include_root = "src/main/native/thirdparty/sigslot/include",
|
||||
)
|
||||
|
||||
third_party_cc_lib_helper(
|
||||
name = "upb",
|
||||
include_root = "src/main/native/thirdparty/upb/include",
|
||||
src_root = "src/main/native/thirdparty/upb/src",
|
||||
)
|
||||
|
||||
generate_resources(
|
||||
name = "generate-resources",
|
||||
namespace = "wpi",
|
||||
@@ -173,7 +173,7 @@ wpilib_cc_library(
|
||||
":llvm",
|
||||
":mpack",
|
||||
":nanopb",
|
||||
":protobuf",
|
||||
":upb",
|
||||
],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = select({
|
||||
|
||||
@@ -117,13 +117,9 @@ file(
|
||||
src/main/native/thirdparty/llvm/cpp/*.cpp
|
||||
src/main/native/thirdparty/mpack/src/*.cpp
|
||||
src/main/native/thirdparty/nanopb/src/*.cpp
|
||||
src/main/native/thirdparty/upb/src/*.c
|
||||
)
|
||||
list(REMOVE_ITEM wpiutil_native_src ${wpiutil_jni_src})
|
||||
if(NOT WITH_PROTOBUF)
|
||||
list(FILTER wpiutil_native_src EXCLUDE REGEX "/protobuf/")
|
||||
# Don't filter out protobuf cpp file, it only uses nanopb
|
||||
list(APPEND wpiutil_native_src src/main/native/cpp/protobuf/Protobuf.cpp)
|
||||
endif()
|
||||
file(GLOB_RECURSE wpiutil_unix_src src/main/native/unix/*.cpp)
|
||||
file(GLOB_RECURSE wpiutil_linux_src src/main/native/linux/*.cpp)
|
||||
file(GLOB_RECURSE wpiutil_macos_src src/main/native/macOS/*.cpp)
|
||||
@@ -145,12 +141,7 @@ if(MSVC)
|
||||
target_compile_definitions(wpiutil PRIVATE -D_CRT_SECURE_NO_WARNINGS)
|
||||
endif()
|
||||
wpilib_target_warnings(wpiutil)
|
||||
if(WITH_PROTOBUF)
|
||||
target_link_libraries(wpiutil protobuf::libprotobuf Threads::Threads ${CMAKE_DL_LIBS})
|
||||
else()
|
||||
target_link_libraries(wpiutil Threads::Threads ${CMAKE_DL_LIBS})
|
||||
target_compile_definitions(wpiutil PUBLIC NO_PROTOBUF)
|
||||
endif()
|
||||
target_link_libraries(wpiutil Threads::Threads ${CMAKE_DL_LIBS})
|
||||
|
||||
if(ATOMIC)
|
||||
target_link_libraries(wpiutil ${ATOMIC})
|
||||
@@ -201,6 +192,7 @@ install(
|
||||
src/main/native/thirdparty/mpack/include/
|
||||
src/main/native/thirdparty/nanopb/include/
|
||||
src/main/native/thirdparty/sigslot/include/
|
||||
src/main/native/thirdparty/upb/include/
|
||||
DESTINATION "${include_dest}/wpiutil"
|
||||
)
|
||||
target_include_directories(
|
||||
@@ -215,6 +207,7 @@ target_include_directories(
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src/main/native/thirdparty/mpack/include>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src/main/native/thirdparty/nanopb/include>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src/main/native/thirdparty/sigslot/include>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src/main/native/thirdparty/upb/include>
|
||||
$<INSTALL_INTERFACE:${include_dest}/wpiutil>
|
||||
)
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
apply from: "${rootDir}/shared/resources.gradle"
|
||||
|
||||
apply plugin: 'c'
|
||||
ext {
|
||||
noWpiutil = true
|
||||
skipJniSymbols = [
|
||||
@@ -80,15 +81,6 @@ ext {
|
||||
srcDirs 'src/main/native/thirdparty/sigslot/include'
|
||||
}
|
||||
}
|
||||
protobufCpp(CppSourceSet) {
|
||||
source {
|
||||
srcDirs 'src/main/native/thirdparty/protobuf/src'
|
||||
include '**/*.cpp'
|
||||
}
|
||||
exportedHeaders {
|
||||
srcDirs 'src/main/native/thirdparty/protobuf/include'
|
||||
}
|
||||
}
|
||||
resourcesCpp(CppSourceSet) {
|
||||
source {
|
||||
srcDirs "$buildDir/generated/main/cpp", "$rootDir/shared/singlelib"
|
||||
@@ -98,6 +90,15 @@ ext {
|
||||
srcDirs 'src/main/native/include'
|
||||
}
|
||||
}
|
||||
upbCpp(CSourceSet) {
|
||||
source {
|
||||
srcDirs 'src/main/native/thirdparty/upb/src'
|
||||
include '**/*.c'
|
||||
}
|
||||
exportedHeaders {
|
||||
srcDirs 'src/main/native/thirdparty/upb/include'
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!it.targetPlatform.operatingSystem.isWindows()) {
|
||||
it.cppCompiler.define '_GNU_SOURCE'
|
||||
@@ -181,7 +182,7 @@ cppHeadersZip {
|
||||
'src/main/native/thirdparty/mpack/include',
|
||||
'src/main/native/thirdparty/nanopb/include',
|
||||
'src/main/native/thirdparty/sigslot/include',
|
||||
'src/main/native/thirdparty/protobuf/include'
|
||||
'src/main/native/thirdparty/upb/include'
|
||||
]
|
||||
|
||||
thirdpartyIncDirs.each {
|
||||
@@ -211,10 +212,10 @@ cppSourcesZip {
|
||||
from('src/main/native/thirdparty/nanopb/src') {
|
||||
into '/'
|
||||
}
|
||||
from('src/main/native/thirdparty/protobuf/src') {
|
||||
from('src/main/native/thirdparty/sigslot/src') {
|
||||
into '/'
|
||||
}
|
||||
from('src/main/native/thirdparty/sigslot/src') {
|
||||
from('src/main/native/thirdparty/upb/src') {
|
||||
into '/'
|
||||
}
|
||||
}
|
||||
@@ -224,7 +225,7 @@ model {
|
||||
all {
|
||||
it.sources.each {
|
||||
it.exportedHeaders {
|
||||
srcDirs 'src/main/native/include', 'src/main/native/thirdparty/argparse/include/', 'src/main/native/thirdparty/debugging/include', 'src/main/native/thirdparty/expected/include', 'src/main/native/thirdparty/fmtlib/include', 'src/main/native/thirdparty/llvm/include', 'src/main/native/thirdparty/sigslot/include', 'src/main/native/thirdparty/json/include', 'src/main/native/thirdparty/mpack/include', 'src/main/native/thirdparty/protobuf/include', 'src/main/native/thirdparty/nanopb/include'
|
||||
srcDirs 'src/main/native/include', 'src/main/native/thirdparty/argparse/include/', 'src/main/native/thirdparty/debugging/include', 'src/main/native/thirdparty/expected/include', 'src/main/native/thirdparty/fmtlib/include', 'src/main/native/thirdparty/llvm/include', 'src/main/native/thirdparty/sigslot/include', 'src/main/native/thirdparty/json/include', 'src/main/native/thirdparty/mpack/include', 'src/main/native/thirdparty/nanopb/include', 'src/main/native/thirdparty/upb/include'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,136 +0,0 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
#include "wpi/protobuf/ProtobufMessageDatabase.h"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/descriptor.h>
|
||||
|
||||
#include "wpi/ProtoHelper.h"
|
||||
|
||||
using namespace wpi;
|
||||
|
||||
using google::protobuf::Arena;
|
||||
using google::protobuf::FileDescriptorProto;
|
||||
using google::protobuf::Message;
|
||||
|
||||
bool ProtobufMessageDatabase::Add(std::string_view filename,
|
||||
std::span<const uint8_t> data) {
|
||||
auto& file = m_files[filename];
|
||||
bool needsRebuild = false;
|
||||
if (file.complete) {
|
||||
file.complete = false;
|
||||
|
||||
m_msgs.clear();
|
||||
m_factory.reset();
|
||||
|
||||
// rebuild the pool EXCEPT for this descriptor
|
||||
m_pool = std::make_unique<google::protobuf::DescriptorPool>();
|
||||
|
||||
for (auto&& p : m_files) {
|
||||
p.second.inPool = false;
|
||||
}
|
||||
|
||||
needsRebuild = true;
|
||||
}
|
||||
|
||||
if (!file.proto) {
|
||||
file.proto = std::unique_ptr<FileDescriptorProto>{
|
||||
wpi::CreateMessage<FileDescriptorProto>(nullptr)};
|
||||
} else {
|
||||
// replacing an existing one; remove any previously existing refs
|
||||
for (auto&& dep : file.proto->dependency()) {
|
||||
auto& depFile = m_files[dep];
|
||||
std::erase(depFile.uses, filename);
|
||||
}
|
||||
file.proto->Clear();
|
||||
}
|
||||
|
||||
// parse data
|
||||
if (!file.proto->ParseFromArray(data.data(), data.size())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// rebuild if necessary; we do this after the parse due to dependencies
|
||||
if (needsRebuild) {
|
||||
for (auto&& p : m_files) {
|
||||
if (p.second.complete && !p.second.inPool) {
|
||||
Rebuild(p.second);
|
||||
}
|
||||
}
|
||||
|
||||
// clear messages and reset factory; Find() will recreate as needed
|
||||
m_factory = std::make_unique<google::protobuf::DynamicMessageFactory>();
|
||||
}
|
||||
|
||||
// build this one
|
||||
Build(filename, file);
|
||||
return true;
|
||||
}
|
||||
|
||||
Message* ProtobufMessageDatabase::Find(std::string_view name) const {
|
||||
// cached
|
||||
auto& msg = m_msgs[name];
|
||||
if (msg) {
|
||||
return msg.get();
|
||||
}
|
||||
|
||||
// need to create it
|
||||
auto desc = m_pool->FindMessageTypeByName(std::string{name});
|
||||
if (!desc) {
|
||||
return nullptr;
|
||||
}
|
||||
msg = std::unique_ptr<Message>{m_factory->GetPrototype(desc)->New(nullptr)};
|
||||
return msg.get();
|
||||
}
|
||||
|
||||
void ProtobufMessageDatabase::Build(std::string_view filename,
|
||||
ProtoFile& file) {
|
||||
if (file.complete) {
|
||||
return;
|
||||
}
|
||||
// are all of the dependencies complete?
|
||||
bool complete = true;
|
||||
for (auto&& dep : file.proto->dependency()) {
|
||||
auto& depFile = m_files[dep];
|
||||
if (!depFile.complete) {
|
||||
complete = false;
|
||||
}
|
||||
depFile.uses.emplace_back(filename);
|
||||
}
|
||||
if (!complete) {
|
||||
return;
|
||||
}
|
||||
|
||||
// add to pool
|
||||
if (!m_pool->BuildFile(*file.proto)) {
|
||||
return;
|
||||
}
|
||||
file.inPool = true;
|
||||
file.complete = true;
|
||||
|
||||
// recursively validate all uses
|
||||
for (auto&& use : file.uses) {
|
||||
Build(use, m_files[use]);
|
||||
}
|
||||
}
|
||||
|
||||
bool ProtobufMessageDatabase::Rebuild(ProtoFile& file) {
|
||||
for (auto&& dep : file.proto->dependency()) {
|
||||
auto& depFile = m_files[dep];
|
||||
if (!depFile.inPool) {
|
||||
if (!Rebuild(depFile)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!m_pool->BuildFile(*file.proto)) {
|
||||
return false;
|
||||
}
|
||||
file.inPool = true;
|
||||
file.complete = true;
|
||||
return true;
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <google/protobuf/message.h>
|
||||
|
||||
namespace wpi {
|
||||
template <typename T>
|
||||
inline T* CreateMessage(google::protobuf::Arena* arena) {
|
||||
#if GOOGLE_PROTOBUF_VERSION < 4000000
|
||||
return google::protobuf::Arena::CreateMessage<T>(arena);
|
||||
#else
|
||||
return google::protobuf::Arena::Create<T>(arena);
|
||||
#endif
|
||||
}
|
||||
} // namespace wpi
|
||||
@@ -1,77 +0,0 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <span>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include <google/protobuf/descriptor.pb.h>
|
||||
#include <google/protobuf/descriptor_database.h>
|
||||
#include <google/protobuf/dynamic_message.h>
|
||||
|
||||
#include "wpi/StringMap.h"
|
||||
|
||||
namespace wpi {
|
||||
|
||||
/**
|
||||
* Database of protobuf dynamic messages. Unlike the protobuf descriptor pools
|
||||
* and databases, this gracefully handles adding descriptors out of order and
|
||||
* descriptors being replaced.
|
||||
*/
|
||||
class ProtobufMessageDatabase {
|
||||
public:
|
||||
/**
|
||||
* Adds a file descriptor to the database. If the file references other
|
||||
* files that have not yet been added, no messages in that file will be
|
||||
* available until those files are added. Replaces any existing file with
|
||||
* the same name.
|
||||
*
|
||||
* @param filename filename
|
||||
* @param data FileDescriptorProto serialized data
|
||||
* @return False if could not parse data
|
||||
*/
|
||||
bool Add(std::string_view filename, std::span<const uint8_t> data);
|
||||
|
||||
/**
|
||||
* Finds a message in the database by name.
|
||||
*
|
||||
* @param name type name
|
||||
* @return protobuf message, or nullptr if not found
|
||||
*/
|
||||
google::protobuf::Message* Find(std::string_view name) const;
|
||||
|
||||
/**
|
||||
* Gets message factory.
|
||||
*
|
||||
* @return message factory
|
||||
*/
|
||||
google::protobuf::MessageFactory* GetMessageFactory() {
|
||||
return m_factory.get();
|
||||
}
|
||||
|
||||
private:
|
||||
struct ProtoFile {
|
||||
std::unique_ptr<google::protobuf::FileDescriptorProto> proto;
|
||||
std::vector<std::string> uses;
|
||||
bool complete = false;
|
||||
bool inPool = false;
|
||||
};
|
||||
|
||||
void Build(std::string_view filename, ProtoFile& file);
|
||||
bool Rebuild(ProtoFile& file);
|
||||
|
||||
std::unique_ptr<google::protobuf::DescriptorPool> m_pool =
|
||||
std::make_unique<google::protobuf::DescriptorPool>();
|
||||
std::unique_ptr<google::protobuf::DynamicMessageFactory> m_factory =
|
||||
std::make_unique<google::protobuf::DynamicMessageFactory>();
|
||||
wpi::StringMap<ProtoFile> m_files; // indexed by filename
|
||||
// indexed by type string
|
||||
mutable wpi::StringMap<std::unique_ptr<google::protobuf::Message>> m_msgs;
|
||||
};
|
||||
|
||||
} // namespace wpi
|
||||
@@ -1,157 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_ANY_H__
|
||||
#define GOOGLE_PROTOBUF_ANY_H__
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/arenastring.h>
|
||||
#include <google/protobuf/message_lite.h>
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
class FieldDescriptor;
|
||||
class Message;
|
||||
|
||||
namespace internal {
|
||||
|
||||
extern const char kAnyFullTypeName[]; // "google.protobuf.Any".
|
||||
extern const char kTypeGoogleApisComPrefix[]; // "type.googleapis.com/".
|
||||
extern const char kTypeGoogleProdComPrefix[]; // "type.googleprod.com/".
|
||||
|
||||
std::string GetTypeUrl(StringPiece message_name,
|
||||
StringPiece type_url_prefix);
|
||||
|
||||
// Helper class used to implement google::protobuf::Any.
|
||||
class PROTOBUF_EXPORT AnyMetadata {
|
||||
typedef ArenaStringPtr UrlType;
|
||||
typedef ArenaStringPtr ValueType;
|
||||
public:
|
||||
// AnyMetadata does not take ownership of "type_url" and "value".
|
||||
constexpr AnyMetadata(UrlType* type_url, ValueType* value)
|
||||
: type_url_(type_url), value_(value) {}
|
||||
|
||||
// Packs a message using the default type URL prefix: "type.googleapis.com".
|
||||
// The resulted type URL will be "type.googleapis.com/<message_full_name>".
|
||||
// Returns false if serializing the message failed.
|
||||
template <typename T>
|
||||
bool PackFrom(Arena* arena, const T& message) {
|
||||
return InternalPackFrom(arena, message, kTypeGoogleApisComPrefix,
|
||||
T::FullMessageName());
|
||||
}
|
||||
|
||||
bool PackFrom(Arena* arena, const Message& message);
|
||||
|
||||
// Packs a message using the given type URL prefix. The type URL will be
|
||||
// constructed by concatenating the message type's full name to the prefix
|
||||
// with an optional "/" separator if the prefix doesn't already end with "/".
|
||||
// For example, both PackFrom(message, "type.googleapis.com") and
|
||||
// PackFrom(message, "type.googleapis.com/") yield the same result type
|
||||
// URL: "type.googleapis.com/<message_full_name>".
|
||||
// Returns false if serializing the message failed.
|
||||
template <typename T>
|
||||
bool PackFrom(Arena* arena, const T& message,
|
||||
StringPiece type_url_prefix) {
|
||||
return InternalPackFrom(arena, message, type_url_prefix,
|
||||
T::FullMessageName());
|
||||
}
|
||||
|
||||
bool PackFrom(Arena* arena, const Message& message,
|
||||
StringPiece type_url_prefix);
|
||||
|
||||
// Unpacks the payload into the given message. Returns false if the message's
|
||||
// type doesn't match the type specified in the type URL (i.e., the full
|
||||
// name after the last "/" of the type URL doesn't match the message's actual
|
||||
// full name) or parsing the payload has failed.
|
||||
template <typename T>
|
||||
bool UnpackTo(T* message) const {
|
||||
return InternalUnpackTo(T::FullMessageName(), message);
|
||||
}
|
||||
|
||||
bool UnpackTo(Message* message) const;
|
||||
|
||||
// Checks whether the type specified in the type URL matches the given type.
|
||||
// A type is considered matching if its full name matches the full name after
|
||||
// the last "/" in the type URL.
|
||||
template <typename T>
|
||||
bool Is() const {
|
||||
return InternalIs(T::FullMessageName());
|
||||
}
|
||||
|
||||
private:
|
||||
bool InternalPackFrom(Arena* arena, const MessageLite& message,
|
||||
StringPiece type_url_prefix,
|
||||
StringPiece type_name);
|
||||
bool InternalUnpackTo(StringPiece type_name,
|
||||
MessageLite* message) const;
|
||||
bool InternalIs(StringPiece type_name) const;
|
||||
|
||||
UrlType* type_url_;
|
||||
ValueType* value_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(AnyMetadata);
|
||||
};
|
||||
|
||||
// Get the proto type name from Any::type_url value. For example, passing
|
||||
// "type.googleapis.com/rpc.QueryOrigin" will return "rpc.QueryOrigin" in
|
||||
// *full_type_name. Returns false if the type_url does not have a "/"
|
||||
// in the type url separating the full type name.
|
||||
//
|
||||
// NOTE: this function is available publicly as a static method on the
|
||||
// generated message type: google::protobuf::Any::ParseAnyTypeUrl()
|
||||
bool ParseAnyTypeUrl(StringPiece type_url, std::string* full_type_name);
|
||||
|
||||
// Get the proto type name and prefix from Any::type_url value. For example,
|
||||
// passing "type.googleapis.com/rpc.QueryOrigin" will return
|
||||
// "type.googleapis.com/" in *url_prefix and "rpc.QueryOrigin" in
|
||||
// *full_type_name. Returns false if the type_url does not have a "/" in the
|
||||
// type url separating the full type name.
|
||||
bool ParseAnyTypeUrl(StringPiece type_url, std::string* url_prefix,
|
||||
std::string* full_type_name);
|
||||
|
||||
// See if message is of type google.protobuf.Any, if so, return the descriptors
|
||||
// for "type_url" and "value" fields.
|
||||
bool GetAnyFieldDescriptors(const Message& message,
|
||||
const FieldDescriptor** type_url_field,
|
||||
const FieldDescriptor** value_field);
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_ANY_H__
|
||||
@@ -1,384 +0,0 @@
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: google/protobuf/any.proto
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fany_2eproto
|
||||
#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fany_2eproto
|
||||
|
||||
#include <limits>
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/port_def.inc>
|
||||
#if PROTOBUF_VERSION < 3021000
|
||||
#error This file was generated by a newer version of protoc which is
|
||||
#error incompatible with your Protocol Buffer headers. Please update
|
||||
#error your headers.
|
||||
#endif
|
||||
#if 3021012 < PROTOBUF_MIN_PROTOC_VERSION
|
||||
#error This file was generated by an older version of protoc which is
|
||||
#error incompatible with your Protocol Buffer headers. Please
|
||||
#error regenerate this file with a newer version of protoc.
|
||||
#endif
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/arena.h>
|
||||
#include <google/protobuf/arenastring.h>
|
||||
#include <google/protobuf/generated_message_util.h>
|
||||
#include <google/protobuf/metadata_lite.h>
|
||||
#include <google/protobuf/generated_message_reflection.h>
|
||||
#include <google/protobuf/message.h>
|
||||
#include <google/protobuf/repeated_field.h> // IWYU pragma: export
|
||||
#include <google/protobuf/extension_set.h> // IWYU pragma: export
|
||||
#include <google/protobuf/unknown_field_set.h>
|
||||
// @@protoc_insertion_point(includes)
|
||||
#include <google/protobuf/port_def.inc>
|
||||
#define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fany_2eproto PROTOBUF_EXPORT
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
namespace internal {
|
||||
class AnyMetadata;
|
||||
} // namespace internal
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
|
||||
// Internal implementation detail -- do not use these members.
|
||||
struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2fany_2eproto {
|
||||
static const uint32_t offsets[];
|
||||
};
|
||||
PROTOBUF_EXPORT extern const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fany_2eproto;
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
class Any;
|
||||
struct AnyDefaultTypeInternal;
|
||||
PROTOBUF_EXPORT extern AnyDefaultTypeInternal _Any_default_instance_;
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Any* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Any>(Arena*);
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
|
||||
// ===================================================================
|
||||
|
||||
class PROTOBUF_EXPORT Any final :
|
||||
public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Any) */ {
|
||||
public:
|
||||
inline Any() : Any(nullptr) {}
|
||||
~Any() override;
|
||||
explicit PROTOBUF_CONSTEXPR Any(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
|
||||
|
||||
Any(const Any& from);
|
||||
Any(Any&& from) noexcept
|
||||
: Any() {
|
||||
*this = ::std::move(from);
|
||||
}
|
||||
|
||||
inline Any& operator=(const Any& from) {
|
||||
CopyFrom(from);
|
||||
return *this;
|
||||
}
|
||||
inline Any& operator=(Any&& from) noexcept {
|
||||
if (this == &from) return *this;
|
||||
if (GetOwningArena() == from.GetOwningArena()
|
||||
#ifdef PROTOBUF_FORCE_COPY_IN_MOVE
|
||||
&& GetOwningArena() != nullptr
|
||||
#endif // !PROTOBUF_FORCE_COPY_IN_MOVE
|
||||
) {
|
||||
InternalSwap(&from);
|
||||
} else {
|
||||
CopyFrom(from);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() {
|
||||
return GetDescriptor();
|
||||
}
|
||||
static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
|
||||
return default_instance().GetMetadata().descriptor;
|
||||
}
|
||||
static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
|
||||
return default_instance().GetMetadata().reflection;
|
||||
}
|
||||
static const Any& default_instance() {
|
||||
return *internal_default_instance();
|
||||
}
|
||||
static inline const Any* internal_default_instance() {
|
||||
return reinterpret_cast<const Any*>(
|
||||
&_Any_default_instance_);
|
||||
}
|
||||
static constexpr int kIndexInFileMessages =
|
||||
0;
|
||||
|
||||
// implements Any -----------------------------------------------
|
||||
|
||||
bool PackFrom(const ::PROTOBUF_NAMESPACE_ID::Message& message) {
|
||||
GOOGLE_DCHECK_NE(&message, this);
|
||||
return _impl_._any_metadata_.PackFrom(GetArena(), message);
|
||||
}
|
||||
bool PackFrom(const ::PROTOBUF_NAMESPACE_ID::Message& message,
|
||||
::PROTOBUF_NAMESPACE_ID::ConstStringParam type_url_prefix) {
|
||||
GOOGLE_DCHECK_NE(&message, this);
|
||||
return _impl_._any_metadata_.PackFrom(GetArena(), message, type_url_prefix);
|
||||
}
|
||||
bool UnpackTo(::PROTOBUF_NAMESPACE_ID::Message* message) const {
|
||||
return _impl_._any_metadata_.UnpackTo(message);
|
||||
}
|
||||
static bool GetAnyFieldDescriptors(
|
||||
const ::PROTOBUF_NAMESPACE_ID::Message& message,
|
||||
const ::PROTOBUF_NAMESPACE_ID::FieldDescriptor** type_url_field,
|
||||
const ::PROTOBUF_NAMESPACE_ID::FieldDescriptor** value_field);
|
||||
template <typename T, class = typename std::enable_if<!std::is_convertible<T, const ::PROTOBUF_NAMESPACE_ID::Message&>::value>::type>
|
||||
bool PackFrom(const T& message) {
|
||||
return _impl_._any_metadata_.PackFrom<T>(GetArena(), message);
|
||||
}
|
||||
template <typename T, class = typename std::enable_if<!std::is_convertible<T, const ::PROTOBUF_NAMESPACE_ID::Message&>::value>::type>
|
||||
bool PackFrom(const T& message,
|
||||
::PROTOBUF_NAMESPACE_ID::ConstStringParam type_url_prefix) {
|
||||
return _impl_._any_metadata_.PackFrom<T>(GetArena(), message, type_url_prefix);}
|
||||
template <typename T, class = typename std::enable_if<!std::is_convertible<T, const ::PROTOBUF_NAMESPACE_ID::Message&>::value>::type>
|
||||
bool UnpackTo(T* message) const {
|
||||
return _impl_._any_metadata_.UnpackTo<T>(message);
|
||||
}
|
||||
template<typename T> bool Is() const {
|
||||
return _impl_._any_metadata_.Is<T>();
|
||||
}
|
||||
static bool ParseAnyTypeUrl(::PROTOBUF_NAMESPACE_ID::ConstStringParam type_url,
|
||||
std::string* full_type_name);
|
||||
friend void swap(Any& a, Any& b) {
|
||||
a.Swap(&b);
|
||||
}
|
||||
inline void Swap(Any* other) {
|
||||
if (other == this) return;
|
||||
#ifdef PROTOBUF_FORCE_COPY_IN_SWAP
|
||||
if (GetOwningArena() != nullptr &&
|
||||
GetOwningArena() == other->GetOwningArena()) {
|
||||
#else // PROTOBUF_FORCE_COPY_IN_SWAP
|
||||
if (GetOwningArena() == other->GetOwningArena()) {
|
||||
#endif // !PROTOBUF_FORCE_COPY_IN_SWAP
|
||||
InternalSwap(other);
|
||||
} else {
|
||||
::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
|
||||
}
|
||||
}
|
||||
void UnsafeArenaSwap(Any* other) {
|
||||
if (other == this) return;
|
||||
GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
|
||||
InternalSwap(other);
|
||||
}
|
||||
|
||||
// implements Message ----------------------------------------------
|
||||
|
||||
Any* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final {
|
||||
return CreateMaybeMessage<Any>(arena);
|
||||
}
|
||||
using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
|
||||
void CopyFrom(const Any& from);
|
||||
using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
|
||||
void MergeFrom( const Any& from) {
|
||||
Any::MergeImpl(*this, from);
|
||||
}
|
||||
private:
|
||||
static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg);
|
||||
public:
|
||||
PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
|
||||
bool IsInitialized() const final;
|
||||
|
||||
size_t ByteSizeLong() const final;
|
||||
const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
|
||||
uint8_t* _InternalSerialize(
|
||||
uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
|
||||
int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
|
||||
|
||||
private:
|
||||
void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned);
|
||||
void SharedDtor();
|
||||
void SetCachedSize(int size) const final;
|
||||
void InternalSwap(Any* other);
|
||||
|
||||
private:
|
||||
friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
|
||||
static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
|
||||
return "google.protobuf.Any";
|
||||
}
|
||||
protected:
|
||||
explicit Any(::PROTOBUF_NAMESPACE_ID::Arena* arena,
|
||||
bool is_message_owned = false);
|
||||
public:
|
||||
|
||||
static const ClassData _class_data_;
|
||||
const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
|
||||
|
||||
::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
|
||||
|
||||
// nested types ----------------------------------------------------
|
||||
|
||||
// accessors -------------------------------------------------------
|
||||
|
||||
enum : int {
|
||||
kTypeUrlFieldNumber = 1,
|
||||
kValueFieldNumber = 2,
|
||||
};
|
||||
// string type_url = 1;
|
||||
void clear_type_url();
|
||||
const std::string& type_url() const;
|
||||
template <typename ArgT0 = const std::string&, typename... ArgT>
|
||||
void set_type_url(ArgT0&& arg0, ArgT... args);
|
||||
std::string* mutable_type_url();
|
||||
PROTOBUF_NODISCARD std::string* release_type_url();
|
||||
void set_allocated_type_url(std::string* type_url);
|
||||
private:
|
||||
const std::string& _internal_type_url() const;
|
||||
inline PROTOBUF_ALWAYS_INLINE void _internal_set_type_url(const std::string& value);
|
||||
std::string* _internal_mutable_type_url();
|
||||
public:
|
||||
|
||||
// bytes value = 2;
|
||||
void clear_value();
|
||||
const std::string& value() const;
|
||||
template <typename ArgT0 = const std::string&, typename... ArgT>
|
||||
void set_value(ArgT0&& arg0, ArgT... args);
|
||||
std::string* mutable_value();
|
||||
PROTOBUF_NODISCARD std::string* release_value();
|
||||
void set_allocated_value(std::string* value);
|
||||
private:
|
||||
const std::string& _internal_value() const;
|
||||
inline PROTOBUF_ALWAYS_INLINE void _internal_set_value(const std::string& value);
|
||||
std::string* _internal_mutable_value();
|
||||
public:
|
||||
|
||||
// @@protoc_insertion_point(class_scope:google.protobuf.Any)
|
||||
private:
|
||||
class _Internal;
|
||||
|
||||
template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper;
|
||||
typedef void InternalArenaConstructable_;
|
||||
typedef void DestructorSkippable_;
|
||||
struct Impl_ {
|
||||
::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr type_url_;
|
||||
::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr value_;
|
||||
mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
|
||||
::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata _any_metadata_;
|
||||
};
|
||||
union { Impl_ _impl_; };
|
||||
friend struct ::TableStruct_google_2fprotobuf_2fany_2eproto;
|
||||
};
|
||||
// ===================================================================
|
||||
|
||||
|
||||
// ===================================================================
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
|
||||
#endif // __GNUC__
|
||||
// Any
|
||||
|
||||
// string type_url = 1;
|
||||
inline void Any::clear_type_url() {
|
||||
_impl_.type_url_.ClearToEmpty();
|
||||
}
|
||||
inline const std::string& Any::type_url() const {
|
||||
// @@protoc_insertion_point(field_get:google.protobuf.Any.type_url)
|
||||
return _internal_type_url();
|
||||
}
|
||||
template <typename ArgT0, typename... ArgT>
|
||||
inline PROTOBUF_ALWAYS_INLINE
|
||||
void Any::set_type_url(ArgT0&& arg0, ArgT... args) {
|
||||
|
||||
_impl_.type_url_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
|
||||
// @@protoc_insertion_point(field_set:google.protobuf.Any.type_url)
|
||||
}
|
||||
inline std::string* Any::mutable_type_url() {
|
||||
std::string* _s = _internal_mutable_type_url();
|
||||
// @@protoc_insertion_point(field_mutable:google.protobuf.Any.type_url)
|
||||
return _s;
|
||||
}
|
||||
inline const std::string& Any::_internal_type_url() const {
|
||||
return _impl_.type_url_.Get();
|
||||
}
|
||||
inline void Any::_internal_set_type_url(const std::string& value) {
|
||||
|
||||
_impl_.type_url_.Set(value, GetArenaForAllocation());
|
||||
}
|
||||
inline std::string* Any::_internal_mutable_type_url() {
|
||||
|
||||
return _impl_.type_url_.Mutable(GetArenaForAllocation());
|
||||
}
|
||||
inline std::string* Any::release_type_url() {
|
||||
// @@protoc_insertion_point(field_release:google.protobuf.Any.type_url)
|
||||
return _impl_.type_url_.Release();
|
||||
}
|
||||
inline void Any::set_allocated_type_url(std::string* type_url) {
|
||||
if (type_url != nullptr) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
_impl_.type_url_.SetAllocated(type_url, GetArenaForAllocation());
|
||||
#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
|
||||
if (_impl_.type_url_.IsDefault()) {
|
||||
_impl_.type_url_.Set("", GetArenaForAllocation());
|
||||
}
|
||||
#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
|
||||
// @@protoc_insertion_point(field_set_allocated:google.protobuf.Any.type_url)
|
||||
}
|
||||
|
||||
// bytes value = 2;
|
||||
inline void Any::clear_value() {
|
||||
_impl_.value_.ClearToEmpty();
|
||||
}
|
||||
inline const std::string& Any::value() const {
|
||||
// @@protoc_insertion_point(field_get:google.protobuf.Any.value)
|
||||
return _internal_value();
|
||||
}
|
||||
template <typename ArgT0, typename... ArgT>
|
||||
inline PROTOBUF_ALWAYS_INLINE
|
||||
void Any::set_value(ArgT0&& arg0, ArgT... args) {
|
||||
|
||||
_impl_.value_.SetBytes(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
|
||||
// @@protoc_insertion_point(field_set:google.protobuf.Any.value)
|
||||
}
|
||||
inline std::string* Any::mutable_value() {
|
||||
std::string* _s = _internal_mutable_value();
|
||||
// @@protoc_insertion_point(field_mutable:google.protobuf.Any.value)
|
||||
return _s;
|
||||
}
|
||||
inline const std::string& Any::_internal_value() const {
|
||||
return _impl_.value_.Get();
|
||||
}
|
||||
inline void Any::_internal_set_value(const std::string& value) {
|
||||
|
||||
_impl_.value_.Set(value, GetArenaForAllocation());
|
||||
}
|
||||
inline std::string* Any::_internal_mutable_value() {
|
||||
|
||||
return _impl_.value_.Mutable(GetArenaForAllocation());
|
||||
}
|
||||
inline std::string* Any::release_value() {
|
||||
// @@protoc_insertion_point(field_release:google.protobuf.Any.value)
|
||||
return _impl_.value_.Release();
|
||||
}
|
||||
inline void Any::set_allocated_value(std::string* value) {
|
||||
if (value != nullptr) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
_impl_.value_.SetAllocated(value, GetArenaForAllocation());
|
||||
#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
|
||||
if (_impl_.value_.IsDefault()) {
|
||||
_impl_.value_.Set("", GetArenaForAllocation());
|
||||
}
|
||||
#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
|
||||
// @@protoc_insertion_point(field_set_allocated:google.protobuf.Any.value)
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif // __GNUC__
|
||||
|
||||
// @@protoc_insertion_point(namespace_scope)
|
||||
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
|
||||
// @@protoc_insertion_point(global_scope)
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
#endif // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fany_2eproto
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,851 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// This file defines an Arena allocator for better allocation performance.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_ARENA_H__
|
||||
#define GOOGLE_PROTOBUF_ARENA_H__
|
||||
|
||||
|
||||
#include <limits>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#if defined(_MSC_VER) && !defined(_LIBCPP_STD_VER) && !_HAS_EXCEPTIONS
|
||||
// Work around bugs in MSVC <typeinfo> header when _HAS_EXCEPTIONS=0.
|
||||
#include <exception>
|
||||
#include <typeinfo>
|
||||
namespace std {
|
||||
using type_info = ::type_info;
|
||||
}
|
||||
#else
|
||||
#include <typeinfo>
|
||||
#endif
|
||||
|
||||
#include <type_traits>
|
||||
#include <google/protobuf/arena_impl.h>
|
||||
#include <google/protobuf/port.h>
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
#ifdef SWIG
|
||||
#error "You cannot SWIG proto headers"
|
||||
#endif
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
struct ArenaOptions; // defined below
|
||||
class Arena; // defined below
|
||||
class Message; // defined in message.h
|
||||
class MessageLite;
|
||||
template <typename Key, typename T>
|
||||
class Map;
|
||||
|
||||
namespace arena_metrics {
|
||||
|
||||
void EnableArenaMetrics(ArenaOptions* options);
|
||||
|
||||
} // namespace arena_metrics
|
||||
|
||||
namespace TestUtil {
|
||||
class ReflectionTester; // defined in test_util.h
|
||||
} // namespace TestUtil
|
||||
|
||||
namespace internal {
|
||||
|
||||
struct ArenaTestPeer; // defined in arena_test_util.h
|
||||
class InternalMetadata; // defined in metadata_lite.h
|
||||
class LazyField; // defined in lazy_field.h
|
||||
class EpsCopyInputStream; // defined in parse_context.h
|
||||
class RepeatedPtrFieldBase; // defined in repeated_ptr_field.h
|
||||
|
||||
template <typename Type>
|
||||
class GenericTypeHandler; // defined in repeated_field.h
|
||||
|
||||
inline PROTOBUF_ALWAYS_INLINE
|
||||
void* AlignTo(void* ptr, size_t align) {
|
||||
return reinterpret_cast<void*>(
|
||||
(reinterpret_cast<uintptr_t>(ptr) + align - 1) & (~align + 1));
|
||||
}
|
||||
|
||||
// Templated cleanup methods.
|
||||
template <typename T>
|
||||
void arena_destruct_object(void* object) {
|
||||
reinterpret_cast<T*>(object)->~T();
|
||||
}
|
||||
|
||||
template <bool destructor_skippable, typename T>
|
||||
struct ObjectDestructor {
|
||||
constexpr static void (*destructor)(void*) = &arena_destruct_object<T>;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct ObjectDestructor<true, T> {
|
||||
constexpr static void (*destructor)(void*) = nullptr;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
void arena_delete_object(void* object) {
|
||||
delete reinterpret_cast<T*>(object);
|
||||
}
|
||||
} // namespace internal
|
||||
|
||||
// ArenaOptions provides optional additional parameters to arena construction
|
||||
// that control its block-allocation behavior.
|
||||
struct ArenaOptions {
|
||||
// This defines the size of the first block requested from the system malloc.
|
||||
// Subsequent block sizes will increase in a geometric series up to a maximum.
|
||||
size_t start_block_size;
|
||||
|
||||
// This defines the maximum block size requested from system malloc (unless an
|
||||
// individual arena allocation request occurs with a size larger than this
|
||||
// maximum). Requested block sizes increase up to this value, then remain
|
||||
// here.
|
||||
size_t max_block_size;
|
||||
|
||||
// An initial block of memory for the arena to use, or NULL for none. If
|
||||
// provided, the block must live at least as long as the arena itself. The
|
||||
// creator of the Arena retains ownership of the block after the Arena is
|
||||
// destroyed.
|
||||
char* initial_block;
|
||||
|
||||
// The size of the initial block, if provided.
|
||||
size_t initial_block_size;
|
||||
|
||||
// A function pointer to an alloc method that returns memory blocks of size
|
||||
// requested. By default, it contains a ptr to the malloc function.
|
||||
//
|
||||
// NOTE: block_alloc and dealloc functions are expected to behave like
|
||||
// malloc and free, including Asan poisoning.
|
||||
void* (*block_alloc)(size_t);
|
||||
// A function pointer to a dealloc method that takes ownership of the blocks
|
||||
// from the arena. By default, it contains a ptr to a wrapper function that
|
||||
// calls free.
|
||||
void (*block_dealloc)(void*, size_t);
|
||||
|
||||
ArenaOptions()
|
||||
: start_block_size(internal::AllocationPolicy::kDefaultStartBlockSize),
|
||||
max_block_size(internal::AllocationPolicy::kDefaultMaxBlockSize),
|
||||
initial_block(NULL),
|
||||
initial_block_size(0),
|
||||
block_alloc(nullptr),
|
||||
block_dealloc(nullptr),
|
||||
make_metrics_collector(nullptr) {}
|
||||
|
||||
private:
|
||||
// If make_metrics_collector is not nullptr, it will be called at Arena init
|
||||
// time. It may return a pointer to a collector instance that will be notified
|
||||
// of interesting events related to the arena.
|
||||
internal::ArenaMetricsCollector* (*make_metrics_collector)();
|
||||
|
||||
internal::ArenaMetricsCollector* MetricsCollector() const {
|
||||
return make_metrics_collector ? (*make_metrics_collector)() : nullptr;
|
||||
}
|
||||
|
||||
internal::AllocationPolicy AllocationPolicy() const {
|
||||
internal::AllocationPolicy res;
|
||||
res.start_block_size = start_block_size;
|
||||
res.max_block_size = max_block_size;
|
||||
res.block_alloc = block_alloc;
|
||||
res.block_dealloc = block_dealloc;
|
||||
res.metrics_collector = MetricsCollector();
|
||||
return res;
|
||||
}
|
||||
|
||||
friend void arena_metrics::EnableArenaMetrics(ArenaOptions*);
|
||||
|
||||
friend class Arena;
|
||||
friend class ArenaOptionsTestFriend;
|
||||
};
|
||||
|
||||
// Support for non-RTTI environments. (The metrics hooks API uses type
|
||||
// information.)
|
||||
#if PROTOBUF_RTTI
|
||||
#define RTTI_TYPE_ID(type) (&typeid(type))
|
||||
#else
|
||||
#define RTTI_TYPE_ID(type) (NULL)
|
||||
#endif
|
||||
|
||||
// Arena allocator. Arena allocation replaces ordinary (heap-based) allocation
|
||||
// with new/delete, and improves performance by aggregating allocations into
|
||||
// larger blocks and freeing allocations all at once. Protocol messages are
|
||||
// allocated on an arena by using Arena::CreateMessage<T>(Arena*), below, and
|
||||
// are automatically freed when the arena is destroyed.
|
||||
//
|
||||
// This is a thread-safe implementation: multiple threads may allocate from the
|
||||
// arena concurrently. Destruction is not thread-safe and the destructing
|
||||
// thread must synchronize with users of the arena first.
|
||||
//
|
||||
// An arena provides two allocation interfaces: CreateMessage<T>, which works
|
||||
// for arena-enabled proto2 message types as well as other types that satisfy
|
||||
// the appropriate protocol (described below), and Create<T>, which works for
|
||||
// any arbitrary type T. CreateMessage<T> is better when the type T supports it,
|
||||
// because this interface (i) passes the arena pointer to the created object so
|
||||
// that its sub-objects and internal allocations can use the arena too, and (ii)
|
||||
// elides the object's destructor call when possible. Create<T> does not place
|
||||
// any special requirements on the type T, and will invoke the object's
|
||||
// destructor when the arena is destroyed.
|
||||
//
|
||||
// The arena message allocation protocol, required by
|
||||
// CreateMessage<T>(Arena* arena, Args&&... args), is as follows:
|
||||
//
|
||||
// - The type T must have (at least) two constructors: a constructor callable
|
||||
// with `args` (without `arena`), called when a T is allocated on the heap;
|
||||
// and a constructor callable with `Arena* arena, Args&&... args`, called when
|
||||
// a T is allocated on an arena. If the second constructor is called with a
|
||||
// NULL arena pointer, it must be equivalent to invoking the first
|
||||
// (`args`-only) constructor.
|
||||
//
|
||||
// - The type T must have a particular type trait: a nested type
|
||||
// |InternalArenaConstructable_|. This is usually a typedef to |void|. If no
|
||||
// such type trait exists, then the instantiation CreateMessage<T> will fail
|
||||
// to compile.
|
||||
//
|
||||
// - The type T *may* have the type trait |DestructorSkippable_|. If this type
|
||||
// trait is present in the type, then its destructor will not be called if and
|
||||
// only if it was passed a non-NULL arena pointer. If this type trait is not
|
||||
// present on the type, then its destructor is always called when the
|
||||
// containing arena is destroyed.
|
||||
//
|
||||
// This protocol is implemented by all arena-enabled proto2 message classes as
|
||||
// well as protobuf container types like RepeatedPtrField and Map. The protocol
|
||||
// is internal to protobuf and is not guaranteed to be stable. Non-proto types
|
||||
// should not rely on this protocol.
|
||||
class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8) Arena final {
|
||||
public:
|
||||
// Default constructor with sensible default options, tuned for average
|
||||
// use-cases.
|
||||
inline Arena() : impl_() {}
|
||||
|
||||
// Construct an arena with default options, except for the supplied
|
||||
// initial block. It is more efficient to use this constructor
|
||||
// instead of passing ArenaOptions if the only configuration needed
|
||||
// by the caller is supplying an initial block.
|
||||
inline Arena(char* initial_block, size_t initial_block_size)
|
||||
: impl_(initial_block, initial_block_size) {}
|
||||
|
||||
// Arena constructor taking custom options. See ArenaOptions above for
|
||||
// descriptions of the options available.
|
||||
explicit Arena(const ArenaOptions& options)
|
||||
: impl_(options.initial_block, options.initial_block_size,
|
||||
options.AllocationPolicy()) {}
|
||||
|
||||
// Block overhead. Use this as a guide for how much to over-allocate the
|
||||
// initial block if you want an allocation of size N to fit inside it.
|
||||
//
|
||||
// WARNING: if you allocate multiple objects, it is difficult to guarantee
|
||||
// that a series of allocations will fit in the initial block, especially if
|
||||
// Arena changes its alignment guarantees in the future!
|
||||
static const size_t kBlockOverhead =
|
||||
internal::ThreadSafeArena::kBlockHeaderSize +
|
||||
internal::ThreadSafeArena::kSerialArenaSize;
|
||||
|
||||
inline ~Arena() {}
|
||||
|
||||
// TODO(protobuf-team): Fix callers to use constructor and delete this method.
|
||||
void Init(const ArenaOptions&) {}
|
||||
|
||||
// API to create proto2 message objects on the arena. If the arena passed in
|
||||
// is NULL, then a heap allocated object is returned. Type T must be a message
|
||||
// defined in a .proto file with cc_enable_arenas set to true, otherwise a
|
||||
// compilation error will occur.
|
||||
//
|
||||
// RepeatedField and RepeatedPtrField may also be instantiated directly on an
|
||||
// arena with this method.
|
||||
//
|
||||
// This function also accepts any type T that satisfies the arena message
|
||||
// allocation protocol, documented above.
|
||||
template <typename T, typename... Args>
|
||||
PROTOBUF_ALWAYS_INLINE static T* CreateMessage(Arena* arena, Args&&... args) {
|
||||
static_assert(
|
||||
InternalHelper<T>::is_arena_constructable::value,
|
||||
"CreateMessage can only construct types that are ArenaConstructable");
|
||||
// We must delegate to CreateMaybeMessage() and NOT CreateMessageInternal()
|
||||
// because protobuf generated classes specialize CreateMaybeMessage() and we
|
||||
// need to use that specialization for code size reasons.
|
||||
return Arena::CreateMaybeMessage<T>(arena, static_cast<Args&&>(args)...);
|
||||
}
|
||||
|
||||
// API to create any objects on the arena. Note that only the object will
|
||||
// be created on the arena; the underlying ptrs (in case of a proto2 message)
|
||||
// will be still heap allocated. Proto messages should usually be allocated
|
||||
// with CreateMessage<T>() instead.
|
||||
//
|
||||
// Note that even if T satisfies the arena message construction protocol
|
||||
// (InternalArenaConstructable_ trait and optional DestructorSkippable_
|
||||
// trait), as described above, this function does not follow the protocol;
|
||||
// instead, it treats T as a black-box type, just as if it did not have these
|
||||
// traits. Specifically, T's constructor arguments will always be only those
|
||||
// passed to Create<T>() -- no additional arena pointer is implicitly added.
|
||||
// Furthermore, the destructor will always be called at arena destruction time
|
||||
// (unless the destructor is trivial). Hence, from T's point of view, it is as
|
||||
// if the object were allocated on the heap (except that the underlying memory
|
||||
// is obtained from the arena).
|
||||
template <typename T, typename... Args>
|
||||
PROTOBUF_NDEBUG_INLINE static T* Create(Arena* arena, Args&&... args) {
|
||||
return CreateInternal<T>(arena, std::is_convertible<T*, MessageLite*>(),
|
||||
static_cast<Args&&>(args)...);
|
||||
}
|
||||
|
||||
// Allocates memory with the specific size and alignment.
|
||||
void* AllocateAligned(size_t size, size_t align = 8) {
|
||||
if (align <= 8) {
|
||||
return AllocateAlignedNoHook(internal::AlignUpTo8(size));
|
||||
} else {
|
||||
// We are wasting space by over allocating align - 8 bytes. Compared
|
||||
// to a dedicated function that takes current alignment in consideration.
|
||||
// Such a scheme would only waste (align - 8)/2 bytes on average, but
|
||||
// requires a dedicated function in the outline arena allocation
|
||||
// functions. Possibly re-evaluate tradeoffs later.
|
||||
return internal::AlignTo(AllocateAlignedNoHook(size + align - 8), align);
|
||||
}
|
||||
}
|
||||
|
||||
// Create an array of object type T on the arena *without* invoking the
|
||||
// constructor of T. If `arena` is null, then the return value should be freed
|
||||
// with `delete[] x;` (or `::operator delete[](x);`).
|
||||
// To ensure safe uses, this function checks at compile time
|
||||
// (when compiled as C++11) that T is trivially default-constructible and
|
||||
// trivially destructible.
|
||||
template <typename T>
|
||||
PROTOBUF_NDEBUG_INLINE static T* CreateArray(Arena* arena,
|
||||
size_t num_elements) {
|
||||
static_assert(std::is_trivial<T>::value,
|
||||
"CreateArray requires a trivially constructible type");
|
||||
static_assert(std::is_trivially_destructible<T>::value,
|
||||
"CreateArray requires a trivially destructible type");
|
||||
GOOGLE_CHECK_LE(num_elements, std::numeric_limits<size_t>::max() / sizeof(T))
|
||||
<< "Requested size is too large to fit into size_t.";
|
||||
if (arena == NULL) {
|
||||
return static_cast<T*>(::operator new[](num_elements * sizeof(T)));
|
||||
} else {
|
||||
return arena->CreateInternalRawArray<T>(num_elements);
|
||||
}
|
||||
}
|
||||
|
||||
// The following are routines are for monitoring. They will approximate the
|
||||
// total sum allocated and used memory, but the exact value is an
|
||||
// implementation deal. For instance allocated space depends on growth
|
||||
// policies. Do not use these in unit tests.
|
||||
// Returns the total space allocated by the arena, which is the sum of the
|
||||
// sizes of the underlying blocks.
|
||||
uint64_t SpaceAllocated() const { return impl_.SpaceAllocated(); }
|
||||
// Returns the total space used by the arena. Similar to SpaceAllocated but
|
||||
// does not include free space and block overhead. The total space returned
|
||||
// may not include space used by other threads executing concurrently with
|
||||
// the call to this method.
|
||||
uint64_t SpaceUsed() const { return impl_.SpaceUsed(); }
|
||||
|
||||
// Frees all storage allocated by this arena after calling destructors
|
||||
// registered with OwnDestructor() and freeing objects registered with Own().
|
||||
// Any objects allocated on this arena are unusable after this call. It also
|
||||
// returns the total space used by the arena which is the sums of the sizes
|
||||
// of the allocated blocks. This method is not thread-safe.
|
||||
uint64_t Reset() { return impl_.Reset(); }
|
||||
|
||||
// Adds |object| to a list of heap-allocated objects to be freed with |delete|
|
||||
// when the arena is destroyed or reset.
|
||||
template <typename T>
|
||||
PROTOBUF_ALWAYS_INLINE void Own(T* object) {
|
||||
OwnInternal(object, std::is_convertible<T*, MessageLite*>());
|
||||
}
|
||||
|
||||
// Adds |object| to a list of objects whose destructors will be manually
|
||||
// called when the arena is destroyed or reset. This differs from Own() in
|
||||
// that it does not free the underlying memory with |delete|; hence, it is
|
||||
// normally only used for objects that are placement-newed into
|
||||
// arena-allocated memory.
|
||||
template <typename T>
|
||||
PROTOBUF_ALWAYS_INLINE void OwnDestructor(T* object) {
|
||||
if (object != NULL) {
|
||||
impl_.AddCleanup(object, &internal::arena_destruct_object<T>);
|
||||
}
|
||||
}
|
||||
|
||||
// Adds a custom member function on an object to the list of destructors that
|
||||
// will be manually called when the arena is destroyed or reset. This differs
|
||||
// from OwnDestructor() in that any member function may be specified, not only
|
||||
// the class destructor.
|
||||
PROTOBUF_ALWAYS_INLINE void OwnCustomDestructor(void* object,
|
||||
void (*destruct)(void*)) {
|
||||
impl_.AddCleanup(object, destruct);
|
||||
}
|
||||
|
||||
// Retrieves the arena associated with |value| if |value| is an arena-capable
|
||||
// message, or NULL otherwise. If possible, the call resolves at compile time.
|
||||
// Note that we can often devirtualize calls to `value->GetArena()` so usually
|
||||
// calling this method is unnecessary.
|
||||
template <typename T>
|
||||
PROTOBUF_ALWAYS_INLINE static Arena* GetArena(const T* value) {
|
||||
return GetArenaInternal(value);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
class InternalHelper {
|
||||
private:
|
||||
// Provides access to protected GetOwningArena to generated messages.
|
||||
static Arena* GetOwningArena(const T* p) { return p->GetOwningArena(); }
|
||||
|
||||
static void InternalSwap(T* a, T* b) { a->InternalSwap(b); }
|
||||
|
||||
static Arena* GetArenaForAllocationInternal(
|
||||
const T* p, std::true_type /*is_derived_from<MessageLite>*/) {
|
||||
return p->GetArenaForAllocation();
|
||||
}
|
||||
|
||||
static Arena* GetArenaForAllocationInternal(
|
||||
const T* p, std::false_type /*is_derived_from<MessageLite>*/) {
|
||||
return GetArenaForAllocationForNonMessage(
|
||||
p, typename is_arena_constructable::type());
|
||||
}
|
||||
|
||||
static Arena* GetArenaForAllocationForNonMessage(
|
||||
const T* p, std::true_type /*is_arena_constructible*/) {
|
||||
return p->GetArena();
|
||||
}
|
||||
|
||||
static Arena* GetArenaForAllocationForNonMessage(
|
||||
const T* p, std::false_type /*is_arena_constructible*/) {
|
||||
return GetArenaForAllocationForNonMessageNonArenaConstructible(
|
||||
p, typename has_get_arena::type());
|
||||
}
|
||||
|
||||
static Arena* GetArenaForAllocationForNonMessageNonArenaConstructible(
|
||||
const T* p, std::true_type /*has_get_arena*/) {
|
||||
return p->GetArena();
|
||||
}
|
||||
|
||||
static Arena* GetArenaForAllocationForNonMessageNonArenaConstructible(
|
||||
const T* /* p */, std::false_type /*has_get_arena*/) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
static char DestructorSkippable(const typename U::DestructorSkippable_*);
|
||||
template <typename U>
|
||||
static double DestructorSkippable(...);
|
||||
|
||||
typedef std::integral_constant<
|
||||
bool, sizeof(DestructorSkippable<T>(static_cast<const T*>(0))) ==
|
||||
sizeof(char) ||
|
||||
std::is_trivially_destructible<T>::value>
|
||||
is_destructor_skippable;
|
||||
|
||||
template <typename U>
|
||||
static char ArenaConstructable(
|
||||
const typename U::InternalArenaConstructable_*);
|
||||
template <typename U>
|
||||
static double ArenaConstructable(...);
|
||||
|
||||
typedef std::integral_constant<bool, sizeof(ArenaConstructable<T>(
|
||||
static_cast<const T*>(0))) ==
|
||||
sizeof(char)>
|
||||
is_arena_constructable;
|
||||
|
||||
template <typename U,
|
||||
typename std::enable_if<
|
||||
std::is_same<Arena*, decltype(std::declval<const U>()
|
||||
.GetArena())>::value,
|
||||
int>::type = 0>
|
||||
static char HasGetArena(decltype(&U::GetArena));
|
||||
template <typename U>
|
||||
static double HasGetArena(...);
|
||||
|
||||
typedef std::integral_constant<bool, sizeof(HasGetArena<T>(nullptr)) ==
|
||||
sizeof(char)>
|
||||
has_get_arena;
|
||||
|
||||
template <typename... Args>
|
||||
static T* Construct(void* ptr, Args&&... args) {
|
||||
return new (ptr) T(static_cast<Args&&>(args)...);
|
||||
}
|
||||
|
||||
static inline PROTOBUF_ALWAYS_INLINE T* New() {
|
||||
return new T(nullptr);
|
||||
}
|
||||
|
||||
static Arena* GetArena(const T* p) { return p->GetArena(); }
|
||||
|
||||
friend class Arena;
|
||||
friend class TestUtil::ReflectionTester;
|
||||
};
|
||||
|
||||
// Provides access to protected GetOwningArena to generated messages. For
|
||||
// internal use only.
|
||||
template <typename T>
|
||||
static Arena* InternalGetOwningArena(const T* p) {
|
||||
return InternalHelper<T>::GetOwningArena(p);
|
||||
}
|
||||
|
||||
// Provides access to protected GetArenaForAllocation to generated messages.
|
||||
// For internal use only.
|
||||
template <typename T>
|
||||
static Arena* InternalGetArenaForAllocation(const T* p) {
|
||||
return InternalHelper<T>::GetArenaForAllocationInternal(
|
||||
p, std::is_convertible<T*, MessageLite*>());
|
||||
}
|
||||
|
||||
// Creates message-owned arena. For internal use only.
|
||||
static Arena* InternalCreateMessageOwnedArena() {
|
||||
return new Arena(internal::MessageOwned{});
|
||||
}
|
||||
|
||||
// Checks whether this arena is message-owned. For internal use only.
|
||||
bool InternalIsMessageOwnedArena() { return IsMessageOwned(); }
|
||||
|
||||
// Helper typetraits that indicates support for arenas in a type T at compile
|
||||
// time. This is public only to allow construction of higher-level templated
|
||||
// utilities.
|
||||
//
|
||||
// is_arena_constructable<T>::value is true if the message type T has arena
|
||||
// support enabled, and false otherwise.
|
||||
//
|
||||
// is_destructor_skippable<T>::value is true if the message type T has told
|
||||
// the arena that it is safe to skip the destructor, and false otherwise.
|
||||
//
|
||||
// This is inside Arena because only Arena has the friend relationships
|
||||
// necessary to see the underlying generated code traits.
|
||||
template <typename T>
|
||||
struct is_arena_constructable : InternalHelper<T>::is_arena_constructable {};
|
||||
template <typename T>
|
||||
struct is_destructor_skippable : InternalHelper<T>::is_destructor_skippable {
|
||||
};
|
||||
|
||||
private:
|
||||
internal::ThreadSafeArena impl_;
|
||||
|
||||
template <typename T>
|
||||
struct has_get_arena : InternalHelper<T>::has_get_arena {};
|
||||
|
||||
// Constructor solely used by message-owned arena.
|
||||
inline Arena(internal::MessageOwned) : impl_(internal::MessageOwned{}) {}
|
||||
|
||||
// Checks whether this arena is message-owned.
|
||||
PROTOBUF_ALWAYS_INLINE bool IsMessageOwned() const {
|
||||
return impl_.IsMessageOwned();
|
||||
}
|
||||
|
||||
void ReturnArrayMemory(void* p, size_t size) {
|
||||
impl_.ReturnArrayMemory(p, size);
|
||||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
PROTOBUF_NDEBUG_INLINE static T* CreateMessageInternal(Arena* arena,
|
||||
Args&&... args) {
|
||||
static_assert(
|
||||
InternalHelper<T>::is_arena_constructable::value,
|
||||
"CreateMessage can only construct types that are ArenaConstructable");
|
||||
if (arena == NULL) {
|
||||
return new T(nullptr, static_cast<Args&&>(args)...);
|
||||
} else {
|
||||
return arena->DoCreateMessage<T>(static_cast<Args&&>(args)...);
|
||||
}
|
||||
}
|
||||
|
||||
// This specialization for no arguments is necessary, because its behavior is
|
||||
// slightly different. When the arena pointer is nullptr, it calls T()
|
||||
// instead of T(nullptr).
|
||||
template <typename T>
|
||||
PROTOBUF_NDEBUG_INLINE static T* CreateMessageInternal(Arena* arena) {
|
||||
static_assert(
|
||||
InternalHelper<T>::is_arena_constructable::value,
|
||||
"CreateMessage can only construct types that are ArenaConstructable");
|
||||
if (arena == NULL) {
|
||||
// Generated arena constructor T(Arena*) is protected. Call via
|
||||
// InternalHelper.
|
||||
return InternalHelper<T>::New();
|
||||
} else {
|
||||
return arena->DoCreateMessage<T>();
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate and also optionally call collector with the allocated type info
|
||||
// when allocation recording is enabled.
|
||||
PROTOBUF_NDEBUG_INLINE void* AllocateInternal(size_t size, size_t align,
|
||||
void (*destructor)(void*),
|
||||
const std::type_info* type) {
|
||||
// Monitor allocation if needed.
|
||||
if (destructor == nullptr) {
|
||||
return AllocateAlignedWithHook(size, align, type);
|
||||
} else {
|
||||
if (align <= 8) {
|
||||
auto res = AllocateAlignedWithCleanup(internal::AlignUpTo8(size), type);
|
||||
res.second->elem = res.first;
|
||||
res.second->cleanup = destructor;
|
||||
return res.first;
|
||||
} else {
|
||||
auto res = AllocateAlignedWithCleanup(size + align - 8, type);
|
||||
auto ptr = internal::AlignTo(res.first, align);
|
||||
res.second->elem = ptr;
|
||||
res.second->cleanup = destructor;
|
||||
return ptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// CreateMessage<T> requires that T supports arenas, but this private method
|
||||
// works whether or not T supports arenas. These are not exposed to user code
|
||||
// as it can cause confusing API usages, and end up having double free in
|
||||
// user code. These are used only internally from LazyField and Repeated
|
||||
// fields, since they are designed to work in all mode combinations.
|
||||
template <typename Msg, typename... Args>
|
||||
PROTOBUF_ALWAYS_INLINE static Msg* DoCreateMaybeMessage(Arena* arena,
|
||||
std::true_type,
|
||||
Args&&... args) {
|
||||
return CreateMessageInternal<Msg>(arena, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
PROTOBUF_ALWAYS_INLINE static T* DoCreateMaybeMessage(Arena* arena,
|
||||
std::false_type,
|
||||
Args&&... args) {
|
||||
return Create<T>(arena, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
PROTOBUF_ALWAYS_INLINE static T* CreateMaybeMessage(Arena* arena,
|
||||
Args&&... args) {
|
||||
return DoCreateMaybeMessage<T>(arena, is_arena_constructable<T>(),
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
// Just allocate the required size for the given type assuming the
|
||||
// type has a trivial constructor.
|
||||
template <typename T>
|
||||
PROTOBUF_NDEBUG_INLINE T* CreateInternalRawArray(size_t num_elements) {
|
||||
GOOGLE_CHECK_LE(num_elements, std::numeric_limits<size_t>::max() / sizeof(T))
|
||||
<< "Requested size is too large to fit into size_t.";
|
||||
// We count on compiler to realize that if sizeof(T) is a multiple of
|
||||
// 8 AlignUpTo can be elided.
|
||||
const size_t n = sizeof(T) * num_elements;
|
||||
return static_cast<T*>(
|
||||
AllocateAlignedWithHookForArray(n, alignof(T), RTTI_TYPE_ID(T)));
|
||||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
PROTOBUF_NDEBUG_INLINE T* DoCreateMessage(Args&&... args) {
|
||||
return InternalHelper<T>::Construct(
|
||||
AllocateInternal(sizeof(T), alignof(T),
|
||||
internal::ObjectDestructor<
|
||||
InternalHelper<T>::is_destructor_skippable::value,
|
||||
T>::destructor,
|
||||
RTTI_TYPE_ID(T)),
|
||||
this, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
// CreateInArenaStorage is used to implement map field. Without it,
|
||||
// Map need to call generated message's protected arena constructor,
|
||||
// which needs to declare Map as friend of generated message.
|
||||
template <typename T, typename... Args>
|
||||
static void CreateInArenaStorage(T* ptr, Arena* arena, Args&&... args) {
|
||||
CreateInArenaStorageInternal(ptr, arena,
|
||||
typename is_arena_constructable<T>::type(),
|
||||
std::forward<Args>(args)...);
|
||||
if (arena != nullptr) {
|
||||
RegisterDestructorInternal(
|
||||
ptr, arena,
|
||||
typename InternalHelper<T>::is_destructor_skippable::type());
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
static void CreateInArenaStorageInternal(T* ptr, Arena* arena,
|
||||
std::true_type, Args&&... args) {
|
||||
InternalHelper<T>::Construct(ptr, arena, std::forward<Args>(args)...);
|
||||
}
|
||||
template <typename T, typename... Args>
|
||||
static void CreateInArenaStorageInternal(T* ptr, Arena* /* arena */,
|
||||
std::false_type, Args&&... args) {
|
||||
new (ptr) T(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static void RegisterDestructorInternal(T* /* ptr */, Arena* /* arena */,
|
||||
std::true_type) {}
|
||||
template <typename T>
|
||||
static void RegisterDestructorInternal(T* ptr, Arena* arena,
|
||||
std::false_type) {
|
||||
arena->OwnDestructor(ptr);
|
||||
}
|
||||
|
||||
// These implement Create(). The second parameter has type 'true_type' if T is
|
||||
// a subtype of Message and 'false_type' otherwise.
|
||||
template <typename T, typename... Args>
|
||||
PROTOBUF_ALWAYS_INLINE static T* CreateInternal(Arena* arena, std::true_type,
|
||||
Args&&... args) {
|
||||
if (arena == nullptr) {
|
||||
return new T(std::forward<Args>(args)...);
|
||||
} else {
|
||||
auto destructor =
|
||||
internal::ObjectDestructor<std::is_trivially_destructible<T>::value,
|
||||
T>::destructor;
|
||||
T* result =
|
||||
new (arena->AllocateInternal(sizeof(T), alignof(T), destructor,
|
||||
RTTI_TYPE_ID(T)))
|
||||
T(std::forward<Args>(args)...);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
template <typename T, typename... Args>
|
||||
PROTOBUF_ALWAYS_INLINE static T* CreateInternal(Arena* arena, std::false_type,
|
||||
Args&&... args) {
|
||||
if (arena == nullptr) {
|
||||
return new T(std::forward<Args>(args)...);
|
||||
} else {
|
||||
auto destructor =
|
||||
internal::ObjectDestructor<std::is_trivially_destructible<T>::value,
|
||||
T>::destructor;
|
||||
return new (arena->AllocateInternal(sizeof(T), alignof(T), destructor,
|
||||
RTTI_TYPE_ID(T)))
|
||||
T(std::forward<Args>(args)...);
|
||||
}
|
||||
}
|
||||
|
||||
// These implement Own(), which registers an object for deletion (destructor
|
||||
// call and operator delete()). The second parameter has type 'true_type' if T
|
||||
// is a subtype of Message and 'false_type' otherwise. Collapsing
|
||||
// all template instantiations to one for generic Message reduces code size,
|
||||
// using the virtual destructor instead.
|
||||
template <typename T>
|
||||
PROTOBUF_ALWAYS_INLINE void OwnInternal(T* object, std::true_type) {
|
||||
if (object != NULL) {
|
||||
impl_.AddCleanup(object, &internal::arena_delete_object<MessageLite>);
|
||||
}
|
||||
}
|
||||
template <typename T>
|
||||
PROTOBUF_ALWAYS_INLINE void OwnInternal(T* object, std::false_type) {
|
||||
if (object != NULL) {
|
||||
impl_.AddCleanup(object, &internal::arena_delete_object<T>);
|
||||
}
|
||||
}
|
||||
|
||||
// Implementation for GetArena(). Only message objects with
|
||||
// InternalArenaConstructable_ tags can be associated with an arena, and such
|
||||
// objects must implement a GetArena() method.
|
||||
template <typename T, typename std::enable_if<
|
||||
is_arena_constructable<T>::value, int>::type = 0>
|
||||
PROTOBUF_ALWAYS_INLINE static Arena* GetArenaInternal(const T* value) {
|
||||
return InternalHelper<T>::GetArena(value);
|
||||
}
|
||||
template <typename T,
|
||||
typename std::enable_if<!is_arena_constructable<T>::value &&
|
||||
has_get_arena<T>::value,
|
||||
int>::type = 0>
|
||||
PROTOBUF_ALWAYS_INLINE static Arena* GetArenaInternal(const T* value) {
|
||||
return value->GetArena();
|
||||
}
|
||||
template <typename T,
|
||||
typename std::enable_if<!is_arena_constructable<T>::value &&
|
||||
!has_get_arena<T>::value,
|
||||
int>::type = 0>
|
||||
PROTOBUF_ALWAYS_INLINE static Arena* GetArenaInternal(const T* value) {
|
||||
(void)value;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
PROTOBUF_ALWAYS_INLINE static Arena* GetOwningArena(const T* value) {
|
||||
return GetOwningArenaInternal(
|
||||
value, std::is_convertible<T*, MessageLite*>());
|
||||
}
|
||||
|
||||
// Implementation for GetOwningArena(). All and only message objects have
|
||||
// GetOwningArena() method.
|
||||
template <typename T>
|
||||
PROTOBUF_ALWAYS_INLINE static Arena* GetOwningArenaInternal(
|
||||
const T* value, std::true_type) {
|
||||
return InternalHelper<T>::GetOwningArena(value);
|
||||
}
|
||||
template <typename T>
|
||||
PROTOBUF_ALWAYS_INLINE static Arena* GetOwningArenaInternal(
|
||||
const T* /* value */, std::false_type) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void* AllocateAlignedWithHookForArray(size_t n, size_t align,
|
||||
const std::type_info* type) {
|
||||
if (align <= 8) {
|
||||
return AllocateAlignedWithHookForArray(internal::AlignUpTo8(n), type);
|
||||
} else {
|
||||
// We are wasting space by over allocating align - 8 bytes. Compared
|
||||
// to a dedicated function that takes current alignment in consideration.
|
||||
// Such a scheme would only waste (align - 8)/2 bytes on average, but
|
||||
// requires a dedicated function in the outline arena allocation
|
||||
// functions. Possibly re-evaluate tradeoffs later.
|
||||
return internal::AlignTo(
|
||||
AllocateAlignedWithHookForArray(n + align - 8, type), align);
|
||||
}
|
||||
}
|
||||
|
||||
void* AllocateAlignedWithHook(size_t n, size_t align,
|
||||
const std::type_info* type) {
|
||||
if (align <= 8) {
|
||||
return AllocateAlignedWithHook(internal::AlignUpTo8(n), type);
|
||||
} else {
|
||||
// We are wasting space by over allocating align - 8 bytes. Compared
|
||||
// to a dedicated function that takes current alignment in consideration.
|
||||
// Such a scheme would only waste (align - 8)/2 bytes on average, but
|
||||
// requires a dedicated function in the outline arena allocation
|
||||
// functions. Possibly re-evaluate tradeoffs later.
|
||||
return internal::AlignTo(AllocateAlignedWithHook(n + align - 8, type),
|
||||
align);
|
||||
}
|
||||
}
|
||||
|
||||
void* AllocateAlignedNoHook(size_t n);
|
||||
void* AllocateAlignedWithHook(size_t n, const std::type_info* type);
|
||||
void* AllocateAlignedWithHookForArray(size_t n, const std::type_info* type);
|
||||
std::pair<void*, internal::SerialArena::CleanupNode*>
|
||||
AllocateAlignedWithCleanup(size_t n, const std::type_info* type);
|
||||
|
||||
template <typename Type>
|
||||
friend class internal::GenericTypeHandler;
|
||||
friend class internal::InternalMetadata; // For user_arena().
|
||||
friend class internal::LazyField; // For CreateMaybeMessage.
|
||||
friend class internal::EpsCopyInputStream; // For parser performance
|
||||
friend class MessageLite;
|
||||
template <typename Key, typename T>
|
||||
friend class Map;
|
||||
template <typename>
|
||||
friend class RepeatedField; // For ReturnArrayMemory
|
||||
friend class internal::RepeatedPtrFieldBase; // For ReturnArrayMemory
|
||||
friend struct internal::ArenaTestPeer;
|
||||
};
|
||||
|
||||
// Defined above for supporting environments without RTTI.
|
||||
#undef RTTI_TYPE_ID
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_ARENA_H__
|
||||
@@ -1,686 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// This file defines an Arena allocator for better allocation performance.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_ARENA_IMPL_H__
|
||||
#define GOOGLE_PROTOBUF_ARENA_IMPL_H__
|
||||
|
||||
#include <atomic>
|
||||
#include <limits>
|
||||
#include <typeinfo>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/logging.h>
|
||||
#include <google/protobuf/stubs/port.h>
|
||||
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
#include <sanitizer/asan_interface.h>
|
||||
#endif // ADDRESS_SANITIZER
|
||||
|
||||
#include <google/protobuf/arenaz_sampler.h>
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
// To prevent sharing cache lines between threads
|
||||
#ifdef __cpp_aligned_new
|
||||
enum { kCacheAlignment = 64 };
|
||||
#else
|
||||
enum { kCacheAlignment = alignof(max_align_t) }; // do the best we can
|
||||
#endif
|
||||
|
||||
inline constexpr size_t AlignUpTo8(size_t n) {
|
||||
// Align n to next multiple of 8 (from Hacker's Delight, Chapter 3.)
|
||||
return (n + 7) & static_cast<size_t>(-8);
|
||||
}
|
||||
|
||||
using LifecycleIdAtomic = uint64_t;
|
||||
|
||||
// MetricsCollector collects stats for a particular arena.
|
||||
class PROTOBUF_EXPORT ArenaMetricsCollector {
|
||||
public:
|
||||
ArenaMetricsCollector(bool record_allocs) : record_allocs_(record_allocs) {}
|
||||
|
||||
// Invoked when the arena is about to be destroyed. This method will
|
||||
// typically finalize any metric collection and delete the collector.
|
||||
// space_allocated is the space used by the arena.
|
||||
virtual void OnDestroy(uint64_t space_allocated) = 0;
|
||||
|
||||
// OnReset() is called when the associated arena is reset.
|
||||
// space_allocated is the space used by the arena just before the reset.
|
||||
virtual void OnReset(uint64_t space_allocated) = 0;
|
||||
|
||||
// OnAlloc is called when an allocation happens.
|
||||
// type_info is promised to be static - its lifetime extends to
|
||||
// match program's lifetime (It is given by typeid operator).
|
||||
// Note: typeid(void) will be passed as allocated_type every time we
|
||||
// intentionally want to avoid monitoring an allocation. (i.e. internal
|
||||
// allocations for managing the arena)
|
||||
virtual void OnAlloc(const std::type_info* allocated_type,
|
||||
uint64_t alloc_size) = 0;
|
||||
|
||||
// Does OnAlloc() need to be called? If false, metric collection overhead
|
||||
// will be reduced since we will not do extra work per allocation.
|
||||
bool RecordAllocs() { return record_allocs_; }
|
||||
|
||||
protected:
|
||||
// This class is destructed by the call to OnDestroy().
|
||||
~ArenaMetricsCollector() = default;
|
||||
const bool record_allocs_;
|
||||
};
|
||||
|
||||
struct AllocationPolicy {
|
||||
static constexpr size_t kDefaultStartBlockSize = 256;
|
||||
static constexpr size_t kDefaultMaxBlockSize = 8192;
|
||||
|
||||
size_t start_block_size = kDefaultStartBlockSize;
|
||||
size_t max_block_size = kDefaultMaxBlockSize;
|
||||
void* (*block_alloc)(size_t) = nullptr;
|
||||
void (*block_dealloc)(void*, size_t) = nullptr;
|
||||
ArenaMetricsCollector* metrics_collector = nullptr;
|
||||
|
||||
bool IsDefault() const {
|
||||
return start_block_size == kDefaultMaxBlockSize &&
|
||||
max_block_size == kDefaultMaxBlockSize && block_alloc == nullptr &&
|
||||
block_dealloc == nullptr && metrics_collector == nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
// Tagged pointer to an AllocationPolicy.
|
||||
class TaggedAllocationPolicyPtr {
|
||||
public:
|
||||
constexpr TaggedAllocationPolicyPtr() : policy_(0) {}
|
||||
|
||||
explicit TaggedAllocationPolicyPtr(AllocationPolicy* policy)
|
||||
: policy_(reinterpret_cast<uintptr_t>(policy)) {}
|
||||
|
||||
void set_policy(AllocationPolicy* policy) {
|
||||
auto bits = policy_ & kTagsMask;
|
||||
policy_ = reinterpret_cast<uintptr_t>(policy) | bits;
|
||||
}
|
||||
|
||||
AllocationPolicy* get() {
|
||||
return reinterpret_cast<AllocationPolicy*>(policy_ & kPtrMask);
|
||||
}
|
||||
const AllocationPolicy* get() const {
|
||||
return reinterpret_cast<const AllocationPolicy*>(policy_ & kPtrMask);
|
||||
}
|
||||
|
||||
AllocationPolicy& operator*() { return *get(); }
|
||||
const AllocationPolicy& operator*() const { return *get(); }
|
||||
|
||||
AllocationPolicy* operator->() { return get(); }
|
||||
const AllocationPolicy* operator->() const { return get(); }
|
||||
|
||||
bool is_user_owned_initial_block() const {
|
||||
return static_cast<bool>(get_mask<kUserOwnedInitialBlock>());
|
||||
}
|
||||
void set_is_user_owned_initial_block(bool v) {
|
||||
set_mask<kUserOwnedInitialBlock>(v);
|
||||
}
|
||||
|
||||
bool should_record_allocs() const {
|
||||
return static_cast<bool>(get_mask<kRecordAllocs>());
|
||||
}
|
||||
void set_should_record_allocs(bool v) { set_mask<kRecordAllocs>(v); }
|
||||
|
||||
uintptr_t get_raw() const { return policy_; }
|
||||
|
||||
inline void RecordAlloc(const std::type_info* allocated_type,
|
||||
size_t n) const {
|
||||
get()->metrics_collector->OnAlloc(allocated_type, n);
|
||||
}
|
||||
|
||||
private:
|
||||
enum : uintptr_t {
|
||||
kUserOwnedInitialBlock = 1,
|
||||
kRecordAllocs = 2,
|
||||
};
|
||||
|
||||
static constexpr uintptr_t kTagsMask = 7;
|
||||
static constexpr uintptr_t kPtrMask = ~kTagsMask;
|
||||
|
||||
template <uintptr_t kMask>
|
||||
uintptr_t get_mask() const {
|
||||
return policy_ & kMask;
|
||||
}
|
||||
template <uintptr_t kMask>
|
||||
void set_mask(bool v) {
|
||||
if (v) {
|
||||
policy_ |= kMask;
|
||||
} else {
|
||||
policy_ &= ~kMask;
|
||||
}
|
||||
}
|
||||
uintptr_t policy_;
|
||||
};
|
||||
|
||||
enum class AllocationClient { kDefault, kArray };
|
||||
|
||||
// A simple arena allocator. Calls to allocate functions must be properly
|
||||
// serialized by the caller, hence this class cannot be used as a general
|
||||
// purpose allocator in a multi-threaded program. It serves as a building block
|
||||
// for ThreadSafeArena, which provides a thread-safe arena allocator.
|
||||
//
|
||||
// This class manages
|
||||
// 1) Arena bump allocation + owning memory blocks.
|
||||
// 2) Maintaining a cleanup list.
|
||||
// It delagetes the actual memory allocation back to ThreadSafeArena, which
|
||||
// contains the information on block growth policy and backing memory allocation
|
||||
// used.
|
||||
class PROTOBUF_EXPORT SerialArena {
|
||||
public:
|
||||
struct Memory {
|
||||
void* ptr;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
// Node contains the ptr of the object to be cleaned up and the associated
|
||||
// cleanup function ptr.
|
||||
struct CleanupNode {
|
||||
void* elem; // Pointer to the object to be cleaned up.
|
||||
void (*cleanup)(void*); // Function pointer to the destructor or deleter.
|
||||
};
|
||||
|
||||
void CleanupList();
|
||||
uint64_t SpaceAllocated() const {
|
||||
return space_allocated_.load(std::memory_order_relaxed);
|
||||
}
|
||||
uint64_t SpaceUsed() const;
|
||||
|
||||
bool HasSpace(size_t n) const {
|
||||
return n <= static_cast<size_t>(limit_ - ptr_);
|
||||
}
|
||||
|
||||
// See comments on `cached_blocks_` member for details.
|
||||
PROTOBUF_ALWAYS_INLINE void* TryAllocateFromCachedBlock(size_t size) {
|
||||
if (PROTOBUF_PREDICT_FALSE(size < 16)) return nullptr;
|
||||
// We round up to the next larger block in case the memory doesn't match
|
||||
// the pattern we are looking for.
|
||||
const size_t index = Bits::Log2FloorNonZero64(size - 1) - 3;
|
||||
|
||||
if (index >= cached_block_length_) return nullptr;
|
||||
auto& cached_head = cached_blocks_[index];
|
||||
if (cached_head == nullptr) return nullptr;
|
||||
|
||||
void* ret = cached_head;
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
ASAN_UNPOISON_MEMORY_REGION(ret, size);
|
||||
#endif // ADDRESS_SANITIZER
|
||||
cached_head = cached_head->next;
|
||||
return ret;
|
||||
}
|
||||
|
||||
// In kArray mode we look through cached blocks.
|
||||
// We do not do this by default because most non-array allocations will not
|
||||
// have the right size and will fail to find an appropriate cached block.
|
||||
//
|
||||
// TODO(sbenza): Evaluate if we should use cached blocks for message types of
|
||||
// the right size. We can statically know if the allocation size can benefit
|
||||
// from it.
|
||||
template <AllocationClient alloc_client = AllocationClient::kDefault>
|
||||
void* AllocateAligned(size_t n, const AllocationPolicy* policy) {
|
||||
GOOGLE_DCHECK_EQ(internal::AlignUpTo8(n), n); // Must be already aligned.
|
||||
GOOGLE_DCHECK_GE(limit_, ptr_);
|
||||
|
||||
if (alloc_client == AllocationClient::kArray) {
|
||||
if (void* res = TryAllocateFromCachedBlock(n)) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
if (PROTOBUF_PREDICT_FALSE(!HasSpace(n))) {
|
||||
return AllocateAlignedFallback(n, policy);
|
||||
}
|
||||
return AllocateFromExisting(n);
|
||||
}
|
||||
|
||||
private:
|
||||
void* AllocateFromExisting(size_t n) {
|
||||
void* ret = ptr_;
|
||||
ptr_ += n;
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
ASAN_UNPOISON_MEMORY_REGION(ret, n);
|
||||
#endif // ADDRESS_SANITIZER
|
||||
return ret;
|
||||
}
|
||||
|
||||
// See comments on `cached_blocks_` member for details.
|
||||
void ReturnArrayMemory(void* p, size_t size) {
|
||||
// We only need to check for 32-bit platforms.
|
||||
// In 64-bit platforms the minimum allocation size from Repeated*Field will
|
||||
// be 16 guaranteed.
|
||||
if (sizeof(void*) < 8) {
|
||||
if (PROTOBUF_PREDICT_FALSE(size < 16)) return;
|
||||
} else {
|
||||
GOOGLE_DCHECK(size >= 16);
|
||||
}
|
||||
|
||||
// We round down to the next smaller block in case the memory doesn't match
|
||||
// the pattern we are looking for. eg, someone might have called Reserve()
|
||||
// on the repeated field.
|
||||
const size_t index = Bits::Log2FloorNonZero64(size) - 4;
|
||||
|
||||
if (PROTOBUF_PREDICT_FALSE(index >= cached_block_length_)) {
|
||||
// We can't put this object on the freelist so make this object the
|
||||
// freelist. It is guaranteed it is larger than the one we have, and
|
||||
// large enough to hold another allocation of `size`.
|
||||
CachedBlock** new_list = static_cast<CachedBlock**>(p);
|
||||
size_t new_size = size / sizeof(CachedBlock*);
|
||||
|
||||
std::copy(cached_blocks_, cached_blocks_ + cached_block_length_,
|
||||
new_list);
|
||||
std::fill(new_list + cached_block_length_, new_list + new_size, nullptr);
|
||||
cached_blocks_ = new_list;
|
||||
// Make the size fit in uint8_t. This is the power of two, so we don't
|
||||
// need anything larger.
|
||||
cached_block_length_ =
|
||||
static_cast<uint8_t>(std::min(size_t{64}, new_size));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
auto& cached_head = cached_blocks_[index];
|
||||
auto* new_node = static_cast<CachedBlock*>(p);
|
||||
new_node->next = cached_head;
|
||||
cached_head = new_node;
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
ASAN_POISON_MEMORY_REGION(p, size);
|
||||
#endif // ADDRESS_SANITIZER
|
||||
}
|
||||
|
||||
public:
|
||||
// Allocate space if the current region provides enough space.
|
||||
bool MaybeAllocateAligned(size_t n, void** out) {
|
||||
GOOGLE_DCHECK_EQ(internal::AlignUpTo8(n), n); // Must be already aligned.
|
||||
GOOGLE_DCHECK_GE(limit_, ptr_);
|
||||
if (PROTOBUF_PREDICT_FALSE(!HasSpace(n))) return false;
|
||||
*out = AllocateFromExisting(n);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::pair<void*, CleanupNode*> AllocateAlignedWithCleanup(
|
||||
size_t n, const AllocationPolicy* policy) {
|
||||
GOOGLE_DCHECK_EQ(internal::AlignUpTo8(n), n); // Must be already aligned.
|
||||
if (PROTOBUF_PREDICT_FALSE(!HasSpace(n + kCleanupSize))) {
|
||||
return AllocateAlignedWithCleanupFallback(n, policy);
|
||||
}
|
||||
return AllocateFromExistingWithCleanupFallback(n);
|
||||
}
|
||||
|
||||
private:
|
||||
std::pair<void*, CleanupNode*> AllocateFromExistingWithCleanupFallback(
|
||||
size_t n) {
|
||||
void* ret = ptr_;
|
||||
ptr_ += n;
|
||||
limit_ -= kCleanupSize;
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
ASAN_UNPOISON_MEMORY_REGION(ret, n);
|
||||
ASAN_UNPOISON_MEMORY_REGION(limit_, kCleanupSize);
|
||||
#endif // ADDRESS_SANITIZER
|
||||
return CreatePair(ret, reinterpret_cast<CleanupNode*>(limit_));
|
||||
}
|
||||
|
||||
public:
|
||||
void AddCleanup(void* elem, void (*cleanup)(void*),
|
||||
const AllocationPolicy* policy) {
|
||||
auto res = AllocateAlignedWithCleanup(0, policy);
|
||||
res.second->elem = elem;
|
||||
res.second->cleanup = cleanup;
|
||||
}
|
||||
|
||||
void* owner() const { return owner_; }
|
||||
SerialArena* next() const { return next_; }
|
||||
void set_next(SerialArena* next) { next_ = next; }
|
||||
|
||||
private:
|
||||
friend class ThreadSafeArena;
|
||||
friend class ArenaBenchmark;
|
||||
|
||||
// Creates a new SerialArena inside mem using the remaining memory as for
|
||||
// future allocations.
|
||||
static SerialArena* New(SerialArena::Memory mem, void* owner,
|
||||
ThreadSafeArenaStats* stats);
|
||||
// Free SerialArena returning the memory passed in to New
|
||||
template <typename Deallocator>
|
||||
Memory Free(Deallocator deallocator);
|
||||
|
||||
// Blocks are variable length malloc-ed objects. The following structure
|
||||
// describes the common header for all blocks.
|
||||
struct Block {
|
||||
Block(Block* next, size_t size) : next(next), size(size), start(nullptr) {}
|
||||
|
||||
char* Pointer(size_t n) {
|
||||
GOOGLE_DCHECK(n <= size);
|
||||
return reinterpret_cast<char*>(this) + n;
|
||||
}
|
||||
|
||||
Block* const next;
|
||||
const size_t size;
|
||||
CleanupNode* start;
|
||||
// data follows
|
||||
};
|
||||
|
||||
void* owner_; // &ThreadCache of this thread;
|
||||
Block* head_; // Head of linked list of blocks.
|
||||
SerialArena* next_; // Next SerialArena in this linked list.
|
||||
size_t space_used_ = 0; // Necessary for metrics.
|
||||
std::atomic<size_t> space_allocated_;
|
||||
|
||||
// Next pointer to allocate from. Always 8-byte aligned. Points inside
|
||||
// head_ (and head_->pos will always be non-canonical). We keep these
|
||||
// here to reduce indirection.
|
||||
char* ptr_;
|
||||
// Limiting address up to which memory can be allocated from the head block.
|
||||
char* limit_;
|
||||
// For holding sampling information. The pointer is owned by the
|
||||
// ThreadSafeArena that holds this serial arena.
|
||||
ThreadSafeArenaStats* arena_stats_;
|
||||
|
||||
// Repeated*Field and Arena play together to reduce memory consumption by
|
||||
// reusing blocks. Currently, natural growth of the repeated field types makes
|
||||
// them allocate blocks of size `8 + 2^N, N>=3`.
|
||||
// When the repeated field grows returns the previous block and we put it in
|
||||
// this free list.
|
||||
// `cached_blocks_[i]` points to the free list for blocks of size `8+2^(i+3)`.
|
||||
// The array of freelists is grown when needed in `ReturnArrayMemory()`.
|
||||
struct CachedBlock {
|
||||
// Simple linked list.
|
||||
CachedBlock* next;
|
||||
};
|
||||
uint8_t cached_block_length_ = 0;
|
||||
CachedBlock** cached_blocks_ = nullptr;
|
||||
|
||||
// Constructor is private as only New() should be used.
|
||||
inline SerialArena(Block* b, void* owner, ThreadSafeArenaStats* stats);
|
||||
void* AllocateAlignedFallback(size_t n, const AllocationPolicy* policy);
|
||||
std::pair<void*, CleanupNode*> AllocateAlignedWithCleanupFallback(
|
||||
size_t n, const AllocationPolicy* policy);
|
||||
void AllocateNewBlock(size_t n, const AllocationPolicy* policy);
|
||||
|
||||
std::pair<void*, CleanupNode*> CreatePair(void* ptr, CleanupNode* node) {
|
||||
return {ptr, node};
|
||||
}
|
||||
|
||||
public:
|
||||
static constexpr size_t kBlockHeaderSize = AlignUpTo8(sizeof(Block));
|
||||
static constexpr size_t kCleanupSize = AlignUpTo8(sizeof(CleanupNode));
|
||||
};
|
||||
|
||||
// Tag type used to invoke the constructor of message-owned arena.
|
||||
// Only message-owned arenas use this constructor for creation.
|
||||
// Such constructors are internal implementation details of the library.
|
||||
struct MessageOwned {
|
||||
explicit MessageOwned() = default;
|
||||
};
|
||||
|
||||
// This class provides the core Arena memory allocation library. Different
|
||||
// implementations only need to implement the public interface below.
|
||||
// Arena is not a template type as that would only be useful if all protos
|
||||
// in turn would be templates, which will/cannot happen. However separating
|
||||
// the memory allocation part from the cruft of the API users expect we can
|
||||
// use #ifdef the select the best implementation based on hardware / OS.
|
||||
class PROTOBUF_EXPORT ThreadSafeArena {
|
||||
public:
|
||||
ThreadSafeArena() { Init(); }
|
||||
|
||||
// Constructor solely used by message-owned arena.
|
||||
ThreadSafeArena(internal::MessageOwned) : tag_and_id_(kMessageOwnedArena) {
|
||||
Init();
|
||||
}
|
||||
|
||||
ThreadSafeArena(char* mem, size_t size) { InitializeFrom(mem, size); }
|
||||
|
||||
explicit ThreadSafeArena(void* mem, size_t size,
|
||||
const AllocationPolicy& policy) {
|
||||
InitializeWithPolicy(mem, size, policy);
|
||||
}
|
||||
|
||||
// Destructor deletes all owned heap allocated objects, and destructs objects
|
||||
// that have non-trivial destructors, except for proto2 message objects whose
|
||||
// destructors can be skipped. Also, frees all blocks except the initial block
|
||||
// if it was passed in.
|
||||
~ThreadSafeArena();
|
||||
|
||||
uint64_t Reset();
|
||||
|
||||
uint64_t SpaceAllocated() const;
|
||||
uint64_t SpaceUsed() const;
|
||||
|
||||
template <AllocationClient alloc_client = AllocationClient::kDefault>
|
||||
void* AllocateAligned(size_t n, const std::type_info* type) {
|
||||
SerialArena* arena = nullptr;
|
||||
if (PROTOBUF_PREDICT_TRUE(!alloc_policy_.should_record_allocs() &&
|
||||
GetSerialArenaFast(&arena))) {
|
||||
return arena->AllocateAligned<alloc_client>(n, AllocPolicy());
|
||||
} else {
|
||||
return AllocateAlignedFallback(n, type);
|
||||
}
|
||||
}
|
||||
|
||||
void ReturnArrayMemory(void* p, size_t size) {
|
||||
SerialArena* arena = nullptr;
|
||||
if (PROTOBUF_PREDICT_TRUE(GetSerialArenaFast(&arena))) {
|
||||
arena->ReturnArrayMemory(p, size);
|
||||
}
|
||||
}
|
||||
|
||||
// This function allocates n bytes if the common happy case is true and
|
||||
// returns true. Otherwise does nothing and returns false. This strange
|
||||
// semantics is necessary to allow callers to program functions that only
|
||||
// have fallback function calls in tail position. This substantially improves
|
||||
// code for the happy path.
|
||||
PROTOBUF_NDEBUG_INLINE bool MaybeAllocateAligned(size_t n, void** out) {
|
||||
SerialArena* arena;
|
||||
if (PROTOBUF_PREDICT_TRUE(!alloc_policy_.should_record_allocs() &&
|
||||
GetSerialArenaFromThreadCache(&arena))) {
|
||||
return arena->MaybeAllocateAligned(n, out);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::pair<void*, SerialArena::CleanupNode*> AllocateAlignedWithCleanup(
|
||||
size_t n, const std::type_info* type);
|
||||
|
||||
// Add object pointer and cleanup function pointer to the list.
|
||||
void AddCleanup(void* elem, void (*cleanup)(void*));
|
||||
|
||||
// Checks whether this arena is message-owned.
|
||||
PROTOBUF_ALWAYS_INLINE bool IsMessageOwned() const {
|
||||
return tag_and_id_ & kMessageOwnedArena;
|
||||
}
|
||||
|
||||
private:
|
||||
// Unique for each arena. Changes on Reset().
|
||||
uint64_t tag_and_id_ = 0;
|
||||
// The LSB of tag_and_id_ indicates if the arena is message-owned.
|
||||
enum : uint64_t { kMessageOwnedArena = 1 };
|
||||
|
||||
TaggedAllocationPolicyPtr alloc_policy_; // Tagged pointer to AllocPolicy.
|
||||
|
||||
static_assert(std::is_trivially_destructible<SerialArena>{},
|
||||
"SerialArena needs to be trivially destructible.");
|
||||
// Pointer to a linked list of SerialArena.
|
||||
std::atomic<SerialArena*> threads_;
|
||||
std::atomic<SerialArena*> hint_; // Fast thread-local block access
|
||||
|
||||
const AllocationPolicy* AllocPolicy() const { return alloc_policy_.get(); }
|
||||
void InitializeFrom(void* mem, size_t size);
|
||||
void InitializeWithPolicy(void* mem, size_t size, AllocationPolicy policy);
|
||||
void* AllocateAlignedFallback(size_t n, const std::type_info* type);
|
||||
std::pair<void*, SerialArena::CleanupNode*>
|
||||
AllocateAlignedWithCleanupFallback(size_t n, const std::type_info* type);
|
||||
|
||||
void Init();
|
||||
void SetInitialBlock(void* mem, size_t size);
|
||||
|
||||
// Delete or Destruct all objects owned by the arena.
|
||||
void CleanupList();
|
||||
|
||||
inline uint64_t LifeCycleId() const {
|
||||
return tag_and_id_ & ~kMessageOwnedArena;
|
||||
}
|
||||
|
||||
inline void CacheSerialArena(SerialArena* serial) {
|
||||
thread_cache().last_serial_arena = serial;
|
||||
thread_cache().last_lifecycle_id_seen = tag_and_id_;
|
||||
// TODO(haberman): evaluate whether we would gain efficiency by getting rid
|
||||
// of hint_. It's the only write we do to ThreadSafeArena in the allocation
|
||||
// path, which will dirty the cache line.
|
||||
|
||||
hint_.store(serial, std::memory_order_release);
|
||||
}
|
||||
|
||||
PROTOBUF_NDEBUG_INLINE bool GetSerialArenaFast(SerialArena** arena) {
|
||||
if (GetSerialArenaFromThreadCache(arena)) return true;
|
||||
|
||||
// Check whether we own the last accessed SerialArena on this arena. This
|
||||
// fast path optimizes the case where a single thread uses multiple arenas.
|
||||
ThreadCache* tc = &thread_cache();
|
||||
SerialArena* serial = hint_.load(std::memory_order_acquire);
|
||||
if (PROTOBUF_PREDICT_TRUE(serial != nullptr && serial->owner() == tc)) {
|
||||
*arena = serial;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
PROTOBUF_NDEBUG_INLINE bool GetSerialArenaFromThreadCache(
|
||||
SerialArena** arena) {
|
||||
// If this thread already owns a block in this arena then try to use that.
|
||||
// This fast path optimizes the case where multiple threads allocate from
|
||||
// the same arena.
|
||||
ThreadCache* tc = &thread_cache();
|
||||
if (PROTOBUF_PREDICT_TRUE(tc->last_lifecycle_id_seen == tag_and_id_)) {
|
||||
*arena = tc->last_serial_arena;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
SerialArena* GetSerialArenaFallback(void* me);
|
||||
|
||||
template <typename Functor>
|
||||
void PerSerialArena(Functor fn) {
|
||||
// By omitting an Acquire barrier we ensure that any user code that doesn't
|
||||
// properly synchronize Reset() or the destructor will throw a TSAN warning.
|
||||
SerialArena* serial = threads_.load(std::memory_order_relaxed);
|
||||
|
||||
for (; serial; serial = serial->next()) fn(serial);
|
||||
}
|
||||
|
||||
// Releases all memory except the first block which it returns. The first
|
||||
// block might be owned by the user and thus need some extra checks before
|
||||
// deleting.
|
||||
SerialArena::Memory Free(size_t* space_allocated);
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4324)
|
||||
#endif
|
||||
struct alignas(kCacheAlignment) ThreadCache {
|
||||
#if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL)
|
||||
// If we are using the ThreadLocalStorage class to store the ThreadCache,
|
||||
// then the ThreadCache's default constructor has to be responsible for
|
||||
// initializing it.
|
||||
ThreadCache()
|
||||
: next_lifecycle_id(0),
|
||||
last_lifecycle_id_seen(-1),
|
||||
last_serial_arena(nullptr) {}
|
||||
#endif
|
||||
|
||||
// Number of per-thread lifecycle IDs to reserve. Must be power of two.
|
||||
// To reduce contention on a global atomic, each thread reserves a batch of
|
||||
// IDs. The following number is calculated based on a stress test with
|
||||
// ~6500 threads all frequently allocating a new arena.
|
||||
static constexpr size_t kPerThreadIds = 256;
|
||||
// Next lifecycle ID available to this thread. We need to reserve a new
|
||||
// batch, if `next_lifecycle_id & (kPerThreadIds - 1) == 0`.
|
||||
uint64_t next_lifecycle_id;
|
||||
// The ThreadCache is considered valid as long as this matches the
|
||||
// lifecycle_id of the arena being used.
|
||||
uint64_t last_lifecycle_id_seen;
|
||||
SerialArena* last_serial_arena;
|
||||
};
|
||||
|
||||
// Lifecycle_id can be highly contended variable in a situation of lots of
|
||||
// arena creation. Make sure that other global variables are not sharing the
|
||||
// cacheline.
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4324)
|
||||
#endif
|
||||
struct alignas(kCacheAlignment) CacheAlignedLifecycleIdGenerator {
|
||||
std::atomic<LifecycleIdAtomic> id;
|
||||
};
|
||||
static CacheAlignedLifecycleIdGenerator lifecycle_id_generator_;
|
||||
#if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL)
|
||||
// iOS does not support __thread keyword so we use a custom thread local
|
||||
// storage class we implemented.
|
||||
static ThreadCache& thread_cache();
|
||||
#elif defined(PROTOBUF_USE_DLLS)
|
||||
// Thread local variables cannot be exposed through DLL interface but we can
|
||||
// wrap them in static functions.
|
||||
static ThreadCache& thread_cache();
|
||||
#else
|
||||
static PROTOBUF_THREAD_LOCAL ThreadCache thread_cache_;
|
||||
static ThreadCache& thread_cache() { return thread_cache_; }
|
||||
#endif
|
||||
|
||||
ThreadSafeArenaStatsHandle arena_stats_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ThreadSafeArena);
|
||||
// All protos have pointers back to the arena hence Arena must have
|
||||
// pointer stability.
|
||||
ThreadSafeArena(ThreadSafeArena&&) = delete;
|
||||
ThreadSafeArena& operator=(ThreadSafeArena&&) = delete;
|
||||
|
||||
public:
|
||||
// kBlockHeaderSize is sizeof(Block), aligned up to the nearest multiple of 8
|
||||
// to protect the invariant that pos is always at a multiple of 8.
|
||||
static constexpr size_t kBlockHeaderSize = SerialArena::kBlockHeaderSize;
|
||||
static constexpr size_t kSerialArenaSize =
|
||||
(sizeof(SerialArena) + 7) & static_cast<size_t>(-8);
|
||||
static_assert(kBlockHeaderSize % 8 == 0,
|
||||
"kBlockHeaderSize must be a multiple of 8.");
|
||||
static_assert(kSerialArenaSize % 8 == 0,
|
||||
"kSerialArenaSize must be a multiple of 8.");
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_ARENA_IMPL_H__
|
||||
@@ -1,480 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_ARENASTRING_H__
|
||||
#define GOOGLE_PROTOBUF_ARENASTRING_H__
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include <google/protobuf/stubs/logging.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/arena.h>
|
||||
#include <google/protobuf/port.h>
|
||||
#include <google/protobuf/explicitly_constructed.h>
|
||||
|
||||
// must be last:
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
#ifdef SWIG
|
||||
#error "You cannot SWIG proto headers"
|
||||
#endif
|
||||
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
class EpsCopyInputStream;
|
||||
|
||||
class SwapFieldHelper;
|
||||
|
||||
// Declared in message_lite.h
|
||||
PROTOBUF_EXPORT extern ExplicitlyConstructedArenaString
|
||||
fixed_address_empty_string;
|
||||
|
||||
// Lazy string instance to support string fields with non-empty default.
|
||||
// These are initialized on the first call to .get().
|
||||
class PROTOBUF_EXPORT LazyString {
|
||||
public:
|
||||
// We explicitly make LazyString an aggregate so that MSVC can do constant
|
||||
// initialization on it without marking it `constexpr`.
|
||||
// We do not want to use `constexpr` because it makes it harder to have extern
|
||||
// storage for it and causes library bloat.
|
||||
struct InitValue {
|
||||
const char* ptr;
|
||||
size_t size;
|
||||
};
|
||||
// We keep a union of the initialization value and the std::string to save on
|
||||
// space. We don't need the string array after Init() is done.
|
||||
union {
|
||||
mutable InitValue init_value_;
|
||||
alignas(std::string) mutable char string_buf_[sizeof(std::string)];
|
||||
};
|
||||
mutable std::atomic<const std::string*> inited_;
|
||||
|
||||
const std::string& get() const {
|
||||
// This check generates less code than a call-once invocation.
|
||||
auto* res = inited_.load(std::memory_order_acquire);
|
||||
if (PROTOBUF_PREDICT_FALSE(res == nullptr)) return Init();
|
||||
return *res;
|
||||
}
|
||||
|
||||
private:
|
||||
// Initialize the string in `string_buf_`, update `inited_` and return it.
|
||||
// We return it here to avoid having to read it again in the inlined code.
|
||||
const std::string& Init() const;
|
||||
};
|
||||
|
||||
class TaggedStringPtr {
|
||||
public:
|
||||
// Bit flags qualifying string properties. We can use 2 bits as
|
||||
// ptr_ is guaranteed and enforced to be aligned on 4 byte boundaries.
|
||||
enum Flags {
|
||||
kArenaBit = 0x1, // ptr is arena allocated
|
||||
kMutableBit = 0x2, // ptr contents are fully mutable
|
||||
kMask = 0x3 // Bit mask
|
||||
};
|
||||
|
||||
// Composed logical types
|
||||
enum Type {
|
||||
// Default strings are immutable and never owned.
|
||||
kDefault = 0,
|
||||
|
||||
// Allocated strings are mutable and (as the name implies) owned.
|
||||
// A heap allocated string must be deleted.
|
||||
kAllocated = kMutableBit,
|
||||
|
||||
// Mutable arena strings are strings where the string instance is owned
|
||||
// by the arena, but the string contents itself are owned by the string
|
||||
// instance. Mutable arena string instances need to be destroyed which is
|
||||
// typically done through a cleanup action added to the arena owning it.
|
||||
kMutableArena = kArenaBit | kMutableBit,
|
||||
|
||||
// Fixed size arena strings are strings where both the string instance and
|
||||
// the string contents are fully owned by the arena. Fixed size arena
|
||||
// strings are a platform and c++ library specific customization. Fixed
|
||||
// size arena strings are immutable, with the exception of custom internal
|
||||
// updates to the content that fit inside the existing capacity.
|
||||
// Fixed size arena strings must never be deleted or destroyed.
|
||||
kFixedSizeArena = kArenaBit,
|
||||
};
|
||||
|
||||
TaggedStringPtr() = default;
|
||||
explicit constexpr TaggedStringPtr(ExplicitlyConstructedArenaString* ptr)
|
||||
: ptr_(ptr) {}
|
||||
|
||||
// Sets the value to `p`, tagging the value as being a 'default' value.
|
||||
// See documentation for kDefault for more info.
|
||||
inline const std::string* SetDefault(const std::string* p) {
|
||||
return TagAs(kDefault, const_cast<std::string*>(p));
|
||||
}
|
||||
|
||||
// Sets the value to `p`, tagging the value as a heap allocated value.
|
||||
// Allocated strings are mutable and (as the name implies) owned.
|
||||
// `p` must not be null
|
||||
inline std::string* SetAllocated(std::string* p) {
|
||||
return TagAs(kAllocated, p);
|
||||
}
|
||||
|
||||
// Sets the value to `p`, tagging the value as a fixed size arena string.
|
||||
// See documentation for kFixedSizeArena for more info.
|
||||
// `p` must not be null
|
||||
inline std::string* SetFixedSizeArena(std::string* p) {
|
||||
return TagAs(kFixedSizeArena, p);
|
||||
}
|
||||
|
||||
// Sets the value to `p`, tagging the value as a mutable arena string.
|
||||
// See documentation for kMutableArena for more info.
|
||||
// `p` must not be null
|
||||
inline std::string* SetMutableArena(std::string* p) {
|
||||
return TagAs(kMutableArena, p);
|
||||
}
|
||||
|
||||
// Returns true if the contents of the current string are fully mutable.
|
||||
inline bool IsMutable() const { return as_int() & kMutableBit; }
|
||||
|
||||
// Returns true if the current string is an immutable default value.
|
||||
inline bool IsDefault() const { return (as_int() & kMask) == kDefault; }
|
||||
|
||||
// If the current string is a heap-allocated mutable value, returns a pointer
|
||||
// to it. Returns nullptr otherwise.
|
||||
inline std::string *GetIfAllocated() const {
|
||||
auto allocated = as_int() ^ kAllocated;
|
||||
if (allocated & kMask) return nullptr;
|
||||
|
||||
auto ptr = reinterpret_cast<std::string*>(allocated);
|
||||
PROTOBUF_ASSUME(ptr != nullptr);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// Returns true if the current string is an arena allocated value.
|
||||
// This means it's either a mutable or fixed size arena string.
|
||||
inline bool IsArena() const { return as_int() & kArenaBit; }
|
||||
|
||||
// Returns true if the current string is a fixed size arena allocated value.
|
||||
inline bool IsFixedSizeArena() const {
|
||||
return (as_int() & kMask) == kFixedSizeArena;
|
||||
}
|
||||
|
||||
// Returns the contained string pointer.
|
||||
inline std::string* Get() const {
|
||||
return reinterpret_cast<std::string*>(as_int() & ~kMask);
|
||||
}
|
||||
|
||||
// Returns true if the contained pointer is null, indicating some error.
|
||||
// The Null value is only used during parsing for temporary values.
|
||||
// A persisted ArenaStringPtr value is never null.
|
||||
inline bool IsNull() { return ptr_ == nullptr; }
|
||||
|
||||
private:
|
||||
static inline void assert_aligned(const void* p) {
|
||||
GOOGLE_DCHECK_EQ(reinterpret_cast<uintptr_t>(p) & kMask, 0UL);
|
||||
}
|
||||
|
||||
inline std::string* TagAs(Type type, std::string* p) {
|
||||
GOOGLE_DCHECK(p != nullptr);
|
||||
assert_aligned(p);
|
||||
ptr_ = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(p) | type);
|
||||
return p;
|
||||
}
|
||||
|
||||
uintptr_t as_int() const { return reinterpret_cast<uintptr_t>(ptr_); }
|
||||
void* ptr_;
|
||||
};
|
||||
|
||||
static_assert(std::is_trivial<TaggedStringPtr>::value,
|
||||
"TaggedStringPtr must be trivial");
|
||||
|
||||
// This class encapsulates a pointer to a std::string with or without arena
|
||||
// owned contents, tagged by the bottom bits of the string pointer. It is a
|
||||
// high-level wrapper that almost directly corresponds to the interface required
|
||||
// by string fields in generated code. It replaces the old std::string* pointer
|
||||
// in such cases.
|
||||
//
|
||||
// The string pointer is tagged to be either a default, externally owned value,
|
||||
// a mutable heap allocated value, or an arena allocated value. The object uses
|
||||
// a single global instance of an empty string that is used as the initial
|
||||
// default value. Fields that have empty default values directly use this global
|
||||
// default. Fields that have non empty default values are supported through
|
||||
// lazily initialized default values managed by the LazyString class.
|
||||
//
|
||||
// Generated code and reflection code both ensure that ptr_ is never null.
|
||||
// Because ArenaStringPtr is used in oneof unions, its constructor is a NOP and
|
||||
// the field is always manually initialized via method calls.
|
||||
//
|
||||
// See TaggedStringPtr for more information about the types of string values
|
||||
// being held, and the mutable and ownership invariants for each type.
|
||||
struct PROTOBUF_EXPORT ArenaStringPtr {
|
||||
ArenaStringPtr() = default;
|
||||
constexpr ArenaStringPtr(ExplicitlyConstructedArenaString* default_value,
|
||||
ConstantInitialized)
|
||||
: tagged_ptr_(default_value) {}
|
||||
|
||||
// Called from generated code / reflection runtime only. Resets value to point
|
||||
// to a default string pointer, with the semantics that this ArenaStringPtr
|
||||
// does not own the pointed-to memory. Disregards initial value of ptr_ (so
|
||||
// this is the *ONLY* safe method to call after construction or when
|
||||
// reinitializing after becoming the active field in a oneof union).
|
||||
inline void InitDefault();
|
||||
|
||||
// Similar to `InitDefault` except that it allows the default value to be
|
||||
// initialized to an externally owned string. This method is called from
|
||||
// parsing code. `str` must not be null and outlive this instance.
|
||||
inline void InitExternal(const std::string* str);
|
||||
|
||||
// Called from generated code / reflection runtime only. Resets the value of
|
||||
// this instances to the heap allocated value in `str`. `str` must not be
|
||||
// null. Invokes `arena->Own(str)` to transfer ownership into the arena if
|
||||
// `arena` is not null, else, `str` will be owned by ArenaStringPtr. This
|
||||
// function should only be used to initialize a ArenaStringPtr or on an
|
||||
// instance known to not carry any heap allocated value.
|
||||
inline void InitAllocated(std::string* str, Arena* arena);
|
||||
|
||||
void Set(ConstStringParam value, Arena* arena);
|
||||
void Set(std::string&& value, Arena* arena);
|
||||
void Set(const char* s, Arena* arena);
|
||||
void Set(const char* s, size_t n, Arena* arena);
|
||||
|
||||
void SetBytes(ConstStringParam value, Arena* arena);
|
||||
void SetBytes(std::string&& value, Arena* arena);
|
||||
void SetBytes(const char* s, Arena* arena);
|
||||
void SetBytes(const void* p, size_t n, Arena* arena);
|
||||
|
||||
template <typename RefWrappedType>
|
||||
void Set(std::reference_wrapper<RefWrappedType> const_string_ref,
|
||||
::google::protobuf::Arena* arena) {
|
||||
Set(const_string_ref.get(), arena);
|
||||
}
|
||||
|
||||
// Returns a mutable std::string reference.
|
||||
// The version accepting a `LazyString` value is used in the generated code to
|
||||
// initialize mutable copies for fields with a non-empty default where the
|
||||
// default value is lazily initialized.
|
||||
std::string* Mutable(Arena* arena);
|
||||
std::string* Mutable(const LazyString& default_value, Arena* arena);
|
||||
|
||||
// Gets a mutable pointer with unspecified contents.
|
||||
// This function is identical to Mutable(), except it is optimized for the
|
||||
// case where the caller is not interested in the current contents. For
|
||||
// example, if the current field is not mutable, it will re-initialize the
|
||||
// value with an empty string rather than a (non-empty) default value.
|
||||
// Likewise, if the current value is a fixed size arena string with contents,
|
||||
// it will be initialized into an empty mutable arena string.
|
||||
std::string* MutableNoCopy(Arena* arena);
|
||||
|
||||
// Basic accessors.
|
||||
PROTOBUF_NDEBUG_INLINE const std::string& Get() const {
|
||||
// Unconditionally mask away the tag.
|
||||
return *tagged_ptr_.Get();
|
||||
}
|
||||
|
||||
// Returns a pointer to the stored contents for this instance.
|
||||
// This method is for internal debugging and tracking purposes only.
|
||||
PROTOBUF_NDEBUG_INLINE const std::string* UnsafeGetPointer() const
|
||||
PROTOBUF_RETURNS_NONNULL {
|
||||
return tagged_ptr_.Get();
|
||||
}
|
||||
|
||||
// Release returns a std::string* instance that is heap-allocated and is not
|
||||
// Own()'d by any arena. If the field is not set, this returns nullptr. The
|
||||
// caller retains ownership. Clears this field back to the default state.
|
||||
// Used to implement release_<field>() methods on generated classes.
|
||||
PROTOBUF_NODISCARD std::string* Release();
|
||||
|
||||
// Takes a std::string that is heap-allocated, and takes ownership. The
|
||||
// std::string's destructor is registered with the arena. Used to implement
|
||||
// set_allocated_<field> in generated classes.
|
||||
void SetAllocated(std::string* value, Arena* arena);
|
||||
|
||||
// Frees storage (if not on an arena).
|
||||
void Destroy();
|
||||
|
||||
// Clears content, but keeps allocated std::string, to avoid the overhead of
|
||||
// heap operations. After this returns, the content (as seen by the user) will
|
||||
// always be the empty std::string. Assumes that |default_value| is an empty
|
||||
// std::string.
|
||||
void ClearToEmpty();
|
||||
|
||||
// Clears content, assuming that the current value is not the empty
|
||||
// string default.
|
||||
void ClearNonDefaultToEmpty();
|
||||
|
||||
// Clears content, but keeps allocated std::string if arena != nullptr, to
|
||||
// avoid the overhead of heap operations. After this returns, the content
|
||||
// (as seen by the user) will always be equal to |default_value|.
|
||||
void ClearToDefault(const LazyString& default_value, ::google::protobuf::Arena* arena);
|
||||
|
||||
// Swaps internal pointers. Arena-safety semantics: this is guarded by the
|
||||
// logic in Swap()/UnsafeArenaSwap() at the message level, so this method is
|
||||
// 'unsafe' if called directly.
|
||||
inline PROTOBUF_NDEBUG_INLINE static void InternalSwap(ArenaStringPtr* rhs,
|
||||
Arena* rhs_arena,
|
||||
ArenaStringPtr* lhs,
|
||||
Arena* lhs_arena);
|
||||
|
||||
// Internal setter used only at parse time to directly set a donated string
|
||||
// value.
|
||||
void UnsafeSetTaggedPointer(TaggedStringPtr value) { tagged_ptr_ = value; }
|
||||
// Generated code only! An optimization, in certain cases the generated
|
||||
// code is certain we can obtain a std::string with no default checks and
|
||||
// tag tests.
|
||||
std::string* UnsafeMutablePointer() PROTOBUF_RETURNS_NONNULL;
|
||||
|
||||
// Returns true if this instances holds an immutable default value.
|
||||
inline bool IsDefault() const { return tagged_ptr_.IsDefault(); }
|
||||
|
||||
private:
|
||||
template <typename... Args>
|
||||
inline std::string* NewString(Arena* arena, Args&&... args) {
|
||||
if (arena == nullptr) {
|
||||
auto* s = new std::string(std::forward<Args>(args)...);
|
||||
return tagged_ptr_.SetAllocated(s);
|
||||
} else {
|
||||
auto* s = Arena::Create<std::string>(arena, std::forward<Args>(args)...);
|
||||
return tagged_ptr_.SetMutableArena(s);
|
||||
}
|
||||
}
|
||||
|
||||
TaggedStringPtr tagged_ptr_;
|
||||
|
||||
bool IsFixedSizeArena() const { return false; }
|
||||
|
||||
// Swaps tagged pointer without debug hardening. This is to allow python
|
||||
// protobuf to maintain pointer stability even in DEBUG builds.
|
||||
inline PROTOBUF_NDEBUG_INLINE static void UnsafeShallowSwap(
|
||||
ArenaStringPtr* rhs, ArenaStringPtr* lhs) {
|
||||
std::swap(lhs->tagged_ptr_, rhs->tagged_ptr_);
|
||||
}
|
||||
|
||||
friend class ::google::protobuf::internal::SwapFieldHelper;
|
||||
friend class TcParser;
|
||||
|
||||
// Slow paths.
|
||||
|
||||
// MutableSlow requires that !IsString() || IsDefault
|
||||
// Variadic to support 0 args for empty default and 1 arg for LazyString.
|
||||
template <typename... Lazy>
|
||||
std::string* MutableSlow(::google::protobuf::Arena* arena, const Lazy&... lazy_default);
|
||||
|
||||
friend class EpsCopyInputStream;
|
||||
};
|
||||
|
||||
inline void ArenaStringPtr::InitDefault() {
|
||||
tagged_ptr_ = TaggedStringPtr(&fixed_address_empty_string);
|
||||
}
|
||||
|
||||
inline void ArenaStringPtr::InitExternal(const std::string* str) {
|
||||
tagged_ptr_.SetDefault(str);
|
||||
}
|
||||
|
||||
inline void ArenaStringPtr::InitAllocated(std::string* str, Arena* arena) {
|
||||
if (arena != nullptr) {
|
||||
tagged_ptr_.SetMutableArena(str);
|
||||
arena->Own(str);
|
||||
} else {
|
||||
tagged_ptr_.SetAllocated(str);
|
||||
}
|
||||
}
|
||||
|
||||
inline void ArenaStringPtr::Set(const char* s, Arena* arena) {
|
||||
Set(ConstStringParam{s}, arena);
|
||||
}
|
||||
|
||||
inline void ArenaStringPtr::Set(const char* s, size_t n, Arena* arena) {
|
||||
Set(ConstStringParam{s, n}, arena);
|
||||
}
|
||||
|
||||
inline void ArenaStringPtr::SetBytes(ConstStringParam value, Arena* arena) {
|
||||
Set(value, arena);
|
||||
}
|
||||
|
||||
inline void ArenaStringPtr::SetBytes(std::string&& value, Arena* arena) {
|
||||
Set(std::move(value), arena);
|
||||
}
|
||||
|
||||
inline void ArenaStringPtr::SetBytes(const char* s, Arena* arena) {
|
||||
Set(s, arena);
|
||||
}
|
||||
|
||||
inline void ArenaStringPtr::SetBytes(const void* p, size_t n, Arena* arena) {
|
||||
Set(ConstStringParam{static_cast<const char*>(p), n}, arena);
|
||||
}
|
||||
|
||||
// Make sure rhs_arena allocated rhs, and lhs_arena allocated lhs.
|
||||
inline PROTOBUF_NDEBUG_INLINE void ArenaStringPtr::InternalSwap( //
|
||||
ArenaStringPtr* rhs, Arena* rhs_arena, //
|
||||
ArenaStringPtr* lhs, Arena* lhs_arena) {
|
||||
// Silence unused variable warnings in release buildls.
|
||||
(void)rhs_arena;
|
||||
(void)lhs_arena;
|
||||
std::swap(lhs->tagged_ptr_, rhs->tagged_ptr_);
|
||||
#ifdef PROTOBUF_FORCE_COPY_IN_SWAP
|
||||
auto force_realloc = [](ArenaStringPtr* p, Arena* arena) {
|
||||
if (p->IsDefault()) return;
|
||||
std::string* old_value = p->tagged_ptr_.Get();
|
||||
std::string* new_value =
|
||||
p->IsFixedSizeArena()
|
||||
? Arena::Create<std::string>(arena, *old_value)
|
||||
: Arena::Create<std::string>(arena, std::move(*old_value));
|
||||
if (arena == nullptr) {
|
||||
delete old_value;
|
||||
p->tagged_ptr_.SetAllocated(new_value);
|
||||
} else {
|
||||
p->tagged_ptr_.SetMutableArena(new_value);
|
||||
}
|
||||
};
|
||||
// Because, at this point, tagged_ptr_ has been swapped, arena should also be
|
||||
// swapped.
|
||||
force_realloc(lhs, rhs_arena);
|
||||
force_realloc(rhs, lhs_arena);
|
||||
#endif // PROTOBUF_FORCE_COPY_IN_SWAP
|
||||
}
|
||||
|
||||
inline void ArenaStringPtr::ClearNonDefaultToEmpty() {
|
||||
// Unconditionally mask away the tag.
|
||||
tagged_ptr_.Get()->clear();
|
||||
}
|
||||
|
||||
inline std::string* ArenaStringPtr::UnsafeMutablePointer() {
|
||||
GOOGLE_DCHECK(tagged_ptr_.IsMutable());
|
||||
GOOGLE_DCHECK(tagged_ptr_.Get() != nullptr);
|
||||
return tagged_ptr_.Get();
|
||||
}
|
||||
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_ARENASTRING_H__
|
||||
@@ -1,207 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_SRC_GOOGLE_PROTOBUF_ARENAZ_SAMPLER_H__
|
||||
#define GOOGLE_PROTOBUF_SRC_GOOGLE_PROTOBUF_ARENAZ_SAMPLER_H__
|
||||
|
||||
#include <atomic>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
#if defined(PROTOBUF_ARENAZ_SAMPLE)
|
||||
struct ThreadSafeArenaStats;
|
||||
void RecordResetSlow(ThreadSafeArenaStats* info);
|
||||
void RecordAllocateSlow(ThreadSafeArenaStats* info, size_t requested,
|
||||
size_t allocated, size_t wasted);
|
||||
// Stores information about a sampled thread safe arena. All mutations to this
|
||||
// *must* be made through `Record*` functions below. All reads from this *must*
|
||||
// only occur in the callback to `ThreadSafeArenazSampler::Iterate`.
|
||||
struct ThreadSafeArenaStats
|
||||
: public absl::profiling_internal::Sample<ThreadSafeArenaStats> {
|
||||
// Constructs the object but does not fill in any fields.
|
||||
ThreadSafeArenaStats();
|
||||
~ThreadSafeArenaStats();
|
||||
|
||||
// Puts the object into a clean state, fills in the logically `const` members,
|
||||
// blocking for any readers that are currently sampling the object.
|
||||
void PrepareForSampling() ABSL_EXCLUSIVE_LOCKS_REQUIRED(init_mu);
|
||||
|
||||
// These fields are mutated by the various Record* APIs and need to be
|
||||
// thread-safe.
|
||||
std::atomic<int> num_allocations;
|
||||
std::atomic<int> num_resets;
|
||||
std::atomic<size_t> bytes_requested;
|
||||
std::atomic<size_t> bytes_allocated;
|
||||
std::atomic<size_t> bytes_wasted;
|
||||
// Records the largest size an arena ever had. Maintained across resets.
|
||||
std::atomic<size_t> max_bytes_allocated;
|
||||
// Bit i when set to 1 indicates that a thread with tid % 63 = i accessed the
|
||||
// underlying arena. The field is maintained across resets.
|
||||
std::atomic<uint64_t> thread_ids;
|
||||
|
||||
// All of the fields below are set by `PrepareForSampling`, they must not
|
||||
// be mutated in `Record*` functions. They are logically `const` in that
|
||||
// sense. These are guarded by init_mu, but that is not externalized to
|
||||
// clients, who can only read them during
|
||||
// `ThreadSafeArenazSampler::Iterate` which will hold the lock.
|
||||
static constexpr int kMaxStackDepth = 64;
|
||||
int32_t depth;
|
||||
void* stack[kMaxStackDepth];
|
||||
static void RecordAllocateStats(ThreadSafeArenaStats* info, size_t requested,
|
||||
size_t allocated, size_t wasted) {
|
||||
if (PROTOBUF_PREDICT_TRUE(info == nullptr)) return;
|
||||
RecordAllocateSlow(info, requested, allocated, wasted);
|
||||
}
|
||||
};
|
||||
|
||||
ThreadSafeArenaStats* SampleSlow(int64_t* next_sample);
|
||||
void UnsampleSlow(ThreadSafeArenaStats* info);
|
||||
|
||||
class ThreadSafeArenaStatsHandle {
|
||||
public:
|
||||
explicit ThreadSafeArenaStatsHandle() = default;
|
||||
explicit ThreadSafeArenaStatsHandle(ThreadSafeArenaStats* info)
|
||||
: info_(info) {}
|
||||
|
||||
~ThreadSafeArenaStatsHandle() {
|
||||
if (PROTOBUF_PREDICT_TRUE(info_ == nullptr)) return;
|
||||
UnsampleSlow(info_);
|
||||
}
|
||||
|
||||
ThreadSafeArenaStatsHandle(ThreadSafeArenaStatsHandle&& other) noexcept
|
||||
: info_(absl::exchange(other.info_, nullptr)) {}
|
||||
|
||||
ThreadSafeArenaStatsHandle& operator=(
|
||||
ThreadSafeArenaStatsHandle&& other) noexcept {
|
||||
if (PROTOBUF_PREDICT_FALSE(info_ != nullptr)) {
|
||||
UnsampleSlow(info_);
|
||||
}
|
||||
info_ = absl::exchange(other.info_, nullptr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void RecordReset() {
|
||||
if (PROTOBUF_PREDICT_TRUE(info_ == nullptr)) return;
|
||||
RecordResetSlow(info_);
|
||||
}
|
||||
|
||||
ThreadSafeArenaStats* MutableStats() { return info_; }
|
||||
|
||||
friend void swap(ThreadSafeArenaStatsHandle& lhs,
|
||||
ThreadSafeArenaStatsHandle& rhs) {
|
||||
std::swap(lhs.info_, rhs.info_);
|
||||
}
|
||||
|
||||
friend class ThreadSafeArenaStatsHandlePeer;
|
||||
|
||||
private:
|
||||
ThreadSafeArenaStats* info_ = nullptr;
|
||||
};
|
||||
|
||||
using ThreadSafeArenazSampler =
|
||||
::absl::profiling_internal::SampleRecorder<ThreadSafeArenaStats>;
|
||||
|
||||
extern PROTOBUF_THREAD_LOCAL int64_t global_next_sample;
|
||||
|
||||
// Returns an RAII sampling handle that manages registration and unregistation
|
||||
// with the global sampler.
|
||||
inline ThreadSafeArenaStatsHandle Sample() {
|
||||
if (PROTOBUF_PREDICT_TRUE(--global_next_sample > 0)) {
|
||||
return ThreadSafeArenaStatsHandle(nullptr);
|
||||
}
|
||||
return ThreadSafeArenaStatsHandle(SampleSlow(&global_next_sample));
|
||||
}
|
||||
|
||||
#else
|
||||
struct ThreadSafeArenaStats {
|
||||
static void RecordAllocateStats(ThreadSafeArenaStats*, size_t /*requested*/,
|
||||
size_t /*allocated*/, size_t /*wasted*/) {}
|
||||
};
|
||||
|
||||
ThreadSafeArenaStats* SampleSlow(int64_t* next_sample);
|
||||
void UnsampleSlow(ThreadSafeArenaStats* info);
|
||||
|
||||
class ThreadSafeArenaStatsHandle {
|
||||
public:
|
||||
explicit ThreadSafeArenaStatsHandle() = default;
|
||||
explicit ThreadSafeArenaStatsHandle(ThreadSafeArenaStats*) {}
|
||||
|
||||
void RecordReset() {}
|
||||
|
||||
ThreadSafeArenaStats* MutableStats() { return nullptr; }
|
||||
|
||||
friend void swap(ThreadSafeArenaStatsHandle&, ThreadSafeArenaStatsHandle&) {}
|
||||
|
||||
private:
|
||||
friend class ThreadSafeArenaStatsHandlePeer;
|
||||
};
|
||||
|
||||
class ThreadSafeArenazSampler {
|
||||
public:
|
||||
void Unregister(ThreadSafeArenaStats*) {}
|
||||
void SetMaxSamples(int32_t) {}
|
||||
};
|
||||
|
||||
// Returns an RAII sampling handle that manages registration and unregistation
|
||||
// with the global sampler.
|
||||
inline ThreadSafeArenaStatsHandle Sample() {
|
||||
return ThreadSafeArenaStatsHandle(nullptr);
|
||||
}
|
||||
#endif // defined(PROTOBUF_ARENAZ_SAMPLE)
|
||||
|
||||
// Returns a global Sampler.
|
||||
ThreadSafeArenazSampler& GlobalThreadSafeArenazSampler();
|
||||
|
||||
// Enables or disables sampling for thread safe arenas.
|
||||
void SetThreadSafeArenazEnabled(bool enabled);
|
||||
|
||||
// Sets the rate at which thread safe arena will be sampled.
|
||||
void SetThreadSafeArenazSampleParameter(int32_t rate);
|
||||
|
||||
// Sets a soft max for the number of samples that will be kept.
|
||||
void SetThreadSafeArenazMaxSamples(int32_t max);
|
||||
|
||||
// Sets the current value for when arenas should be next sampled.
|
||||
void SetThreadSafeArenazGlobalNextSample(int64_t next_sample);
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
#endif // GOOGLE_PROTOBUF_SRC_PROTOBUF_ARENAZ_SAMPLER_H__
|
||||
@@ -1,338 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
//
|
||||
// This file is the public interface to the .proto file parser.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_IMPORTER_H__
|
||||
#define GOOGLE_PROTOBUF_COMPILER_IMPORTER_H__
|
||||
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <google/protobuf/compiler/parser.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/descriptor_database.h>
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
namespace io {
|
||||
class ZeroCopyInputStream;
|
||||
}
|
||||
|
||||
namespace compiler {
|
||||
|
||||
// Defined in this file.
|
||||
class Importer;
|
||||
class MultiFileErrorCollector;
|
||||
class SourceTree;
|
||||
class DiskSourceTree;
|
||||
|
||||
// TODO(kenton): Move all SourceTree stuff to a separate file?
|
||||
|
||||
// An implementation of DescriptorDatabase which loads files from a SourceTree
|
||||
// and parses them.
|
||||
//
|
||||
// Note: This class is not thread-safe since it maintains a table of source
|
||||
// code locations for error reporting. However, when a DescriptorPool wraps
|
||||
// a DescriptorDatabase, it uses mutex locking to make sure only one method
|
||||
// of the database is called at a time, even if the DescriptorPool is used
|
||||
// from multiple threads. Therefore, there is only a problem if you create
|
||||
// multiple DescriptorPools wrapping the same SourceTreeDescriptorDatabase
|
||||
// and use them from multiple threads.
|
||||
//
|
||||
// Note: This class does not implement FindFileContainingSymbol() or
|
||||
// FindFileContainingExtension(); these will always return false.
|
||||
class PROTOBUF_EXPORT SourceTreeDescriptorDatabase : public DescriptorDatabase {
|
||||
public:
|
||||
SourceTreeDescriptorDatabase(SourceTree* source_tree);
|
||||
|
||||
// If non-NULL, fallback_database will be checked if a file doesn't exist in
|
||||
// the specified source_tree.
|
||||
SourceTreeDescriptorDatabase(SourceTree* source_tree,
|
||||
DescriptorDatabase* fallback_database);
|
||||
~SourceTreeDescriptorDatabase() override;
|
||||
|
||||
// Instructs the SourceTreeDescriptorDatabase to report any parse errors
|
||||
// to the given MultiFileErrorCollector. This should be called before
|
||||
// parsing. error_collector must remain valid until either this method
|
||||
// is called again or the SourceTreeDescriptorDatabase is destroyed.
|
||||
void RecordErrorsTo(MultiFileErrorCollector* error_collector) {
|
||||
error_collector_ = error_collector;
|
||||
}
|
||||
|
||||
// Gets a DescriptorPool::ErrorCollector which records errors to the
|
||||
// MultiFileErrorCollector specified with RecordErrorsTo(). This collector
|
||||
// has the ability to determine exact line and column numbers of errors
|
||||
// from the information given to it by the DescriptorPool.
|
||||
DescriptorPool::ErrorCollector* GetValidationErrorCollector() {
|
||||
using_validation_error_collector_ = true;
|
||||
return &validation_error_collector_;
|
||||
}
|
||||
|
||||
// implements DescriptorDatabase -----------------------------------
|
||||
bool FindFileByName(const std::string& filename,
|
||||
FileDescriptorProto* output) override;
|
||||
bool FindFileContainingSymbol(const std::string& symbol_name,
|
||||
FileDescriptorProto* output) override;
|
||||
bool FindFileContainingExtension(const std::string& containing_type,
|
||||
int field_number,
|
||||
FileDescriptorProto* output) override;
|
||||
|
||||
private:
|
||||
class SingleFileErrorCollector;
|
||||
|
||||
SourceTree* source_tree_;
|
||||
DescriptorDatabase* fallback_database_;
|
||||
MultiFileErrorCollector* error_collector_;
|
||||
|
||||
class PROTOBUF_EXPORT ValidationErrorCollector
|
||||
: public DescriptorPool::ErrorCollector {
|
||||
public:
|
||||
ValidationErrorCollector(SourceTreeDescriptorDatabase* owner);
|
||||
~ValidationErrorCollector() override;
|
||||
|
||||
// implements ErrorCollector ---------------------------------------
|
||||
void AddError(const std::string& filename, const std::string& element_name,
|
||||
const Message* descriptor, ErrorLocation location,
|
||||
const std::string& message) override;
|
||||
|
||||
void AddWarning(const std::string& filename,
|
||||
const std::string& element_name, const Message* descriptor,
|
||||
ErrorLocation location,
|
||||
const std::string& message) override;
|
||||
|
||||
private:
|
||||
SourceTreeDescriptorDatabase* owner_;
|
||||
};
|
||||
friend class ValidationErrorCollector;
|
||||
|
||||
bool using_validation_error_collector_;
|
||||
SourceLocationTable source_locations_;
|
||||
ValidationErrorCollector validation_error_collector_;
|
||||
};
|
||||
|
||||
// Simple interface for parsing .proto files. This wraps the process
|
||||
// of opening the file, parsing it with a Parser, recursively parsing all its
|
||||
// imports, and then cross-linking the results to produce a FileDescriptor.
|
||||
//
|
||||
// This is really just a thin wrapper around SourceTreeDescriptorDatabase.
|
||||
// You may find that SourceTreeDescriptorDatabase is more flexible.
|
||||
//
|
||||
// TODO(kenton): I feel like this class is not well-named.
|
||||
class PROTOBUF_EXPORT Importer {
|
||||
public:
|
||||
Importer(SourceTree* source_tree, MultiFileErrorCollector* error_collector);
|
||||
~Importer();
|
||||
|
||||
// Import the given file and build a FileDescriptor representing it. If
|
||||
// the file is already in the DescriptorPool, the existing FileDescriptor
|
||||
// will be returned. The FileDescriptor is property of the DescriptorPool,
|
||||
// and will remain valid until it is destroyed. If any errors occur, they
|
||||
// will be reported using the error collector and Import() will return NULL.
|
||||
//
|
||||
// A particular Importer object will only report errors for a particular
|
||||
// file once. All future attempts to import the same file will return NULL
|
||||
// without reporting any errors. The idea is that you might want to import
|
||||
// a lot of files without seeing the same errors over and over again. If
|
||||
// you want to see errors for the same files repeatedly, you can use a
|
||||
// separate Importer object to import each one (but use the same
|
||||
// DescriptorPool so that they can be cross-linked).
|
||||
const FileDescriptor* Import(const std::string& filename);
|
||||
|
||||
// The DescriptorPool in which all imported FileDescriptors and their
|
||||
// contents are stored.
|
||||
inline const DescriptorPool* pool() const { return &pool_; }
|
||||
|
||||
void AddUnusedImportTrackFile(const std::string& file_name,
|
||||
bool is_error = false);
|
||||
void ClearUnusedImportTrackFiles();
|
||||
|
||||
|
||||
private:
|
||||
SourceTreeDescriptorDatabase database_;
|
||||
DescriptorPool pool_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Importer);
|
||||
};
|
||||
|
||||
// If the importer encounters problems while trying to import the proto files,
|
||||
// it reports them to a MultiFileErrorCollector.
|
||||
class PROTOBUF_EXPORT MultiFileErrorCollector {
|
||||
public:
|
||||
inline MultiFileErrorCollector() {}
|
||||
virtual ~MultiFileErrorCollector();
|
||||
|
||||
// Line and column numbers are zero-based. A line number of -1 indicates
|
||||
// an error with the entire file (e.g. "not found").
|
||||
virtual void AddError(const std::string& filename, int line, int column,
|
||||
const std::string& message) = 0;
|
||||
|
||||
virtual void AddWarning(const std::string& /* filename */, int /* line */,
|
||||
int /* column */, const std::string& /* message */) {}
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MultiFileErrorCollector);
|
||||
};
|
||||
|
||||
// Abstract interface which represents a directory tree containing proto files.
|
||||
// Used by the default implementation of Importer to resolve import statements
|
||||
// Most users will probably want to use the DiskSourceTree implementation,
|
||||
// below.
|
||||
class PROTOBUF_EXPORT SourceTree {
|
||||
public:
|
||||
inline SourceTree() {}
|
||||
virtual ~SourceTree();
|
||||
|
||||
// Open the given file and return a stream that reads it, or NULL if not
|
||||
// found. The caller takes ownership of the returned object. The filename
|
||||
// must be a path relative to the root of the source tree and must not
|
||||
// contain "." or ".." components.
|
||||
virtual io::ZeroCopyInputStream* Open(const std::string& filename) = 0;
|
||||
|
||||
// If Open() returns NULL, calling this method immediately will return an
|
||||
// description of the error.
|
||||
// Subclasses should implement this method and return a meaningful value for
|
||||
// better error reporting.
|
||||
// TODO(xiaofeng): change this to a pure virtual function.
|
||||
virtual std::string GetLastErrorMessage();
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SourceTree);
|
||||
};
|
||||
|
||||
// An implementation of SourceTree which loads files from locations on disk.
|
||||
// Multiple mappings can be set up to map locations in the DiskSourceTree to
|
||||
// locations in the physical filesystem.
|
||||
class PROTOBUF_EXPORT DiskSourceTree : public SourceTree {
|
||||
public:
|
||||
DiskSourceTree();
|
||||
~DiskSourceTree() override;
|
||||
|
||||
// Map a path on disk to a location in the SourceTree. The path may be
|
||||
// either a file or a directory. If it is a directory, the entire tree
|
||||
// under it will be mapped to the given virtual location. To map a directory
|
||||
// to the root of the source tree, pass an empty string for virtual_path.
|
||||
//
|
||||
// If multiple mapped paths apply when opening a file, they will be searched
|
||||
// in order. For example, if you do:
|
||||
// MapPath("bar", "foo/bar");
|
||||
// MapPath("", "baz");
|
||||
// and then you do:
|
||||
// Open("bar/qux");
|
||||
// the DiskSourceTree will first try to open foo/bar/qux, then baz/bar/qux,
|
||||
// returning the first one that opens successfully.
|
||||
//
|
||||
// disk_path may be an absolute path or relative to the current directory,
|
||||
// just like a path you'd pass to open().
|
||||
void MapPath(const std::string& virtual_path, const std::string& disk_path);
|
||||
|
||||
// Return type for DiskFileToVirtualFile().
|
||||
enum DiskFileToVirtualFileResult {
|
||||
SUCCESS,
|
||||
SHADOWED,
|
||||
CANNOT_OPEN,
|
||||
NO_MAPPING
|
||||
};
|
||||
|
||||
// Given a path to a file on disk, find a virtual path mapping to that
|
||||
// file. The first mapping created with MapPath() whose disk_path contains
|
||||
// the filename is used. However, that virtual path may not actually be
|
||||
// usable to open the given file. Possible return values are:
|
||||
// * SUCCESS: The mapping was found. *virtual_file is filled in so that
|
||||
// calling Open(*virtual_file) will open the file named by disk_file.
|
||||
// * SHADOWED: A mapping was found, but using Open() to open this virtual
|
||||
// path will end up returning some different file. This is because some
|
||||
// other mapping with a higher precedence also matches this virtual path
|
||||
// and maps it to a different file that exists on disk. *virtual_file
|
||||
// is filled in as it would be in the SUCCESS case. *shadowing_disk_file
|
||||
// is filled in with the disk path of the file which would be opened if
|
||||
// you were to call Open(*virtual_file).
|
||||
// * CANNOT_OPEN: The mapping was found and was not shadowed, but the
|
||||
// file specified cannot be opened. When this value is returned,
|
||||
// errno will indicate the reason the file cannot be opened. *virtual_file
|
||||
// will be set to the virtual path as in the SUCCESS case, even though
|
||||
// it is not useful.
|
||||
// * NO_MAPPING: Indicates that no mapping was found which contains this
|
||||
// file.
|
||||
DiskFileToVirtualFileResult DiskFileToVirtualFile(
|
||||
const std::string& disk_file, std::string* virtual_file,
|
||||
std::string* shadowing_disk_file);
|
||||
|
||||
// Given a virtual path, find the path to the file on disk.
|
||||
// Return true and update disk_file with the on-disk path if the file exists.
|
||||
// Return false and leave disk_file untouched if the file doesn't exist.
|
||||
bool VirtualFileToDiskFile(const std::string& virtual_file,
|
||||
std::string* disk_file);
|
||||
|
||||
// implements SourceTree -------------------------------------------
|
||||
io::ZeroCopyInputStream* Open(const std::string& filename) override;
|
||||
|
||||
std::string GetLastErrorMessage() override;
|
||||
|
||||
private:
|
||||
struct Mapping {
|
||||
std::string virtual_path;
|
||||
std::string disk_path;
|
||||
|
||||
inline Mapping(const std::string& virtual_path_param,
|
||||
const std::string& disk_path_param)
|
||||
: virtual_path(virtual_path_param), disk_path(disk_path_param) {}
|
||||
};
|
||||
std::vector<Mapping> mappings_;
|
||||
std::string last_error_message_;
|
||||
|
||||
// Like Open(), but returns the on-disk path in disk_file if disk_file is
|
||||
// non-NULL and the file could be successfully opened.
|
||||
io::ZeroCopyInputStream* OpenVirtualFile(const std::string& virtual_file,
|
||||
std::string* disk_file);
|
||||
|
||||
// Like Open() but given the actual on-disk path.
|
||||
io::ZeroCopyInputStream* OpenDiskFile(const std::string& filename);
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DiskSourceTree);
|
||||
};
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_IMPORTER_H__
|
||||
@@ -1,602 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
//
|
||||
// Implements parsing of .proto files to FileDescriptorProtos.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_PARSER_H__
|
||||
#define GOOGLE_PROTOBUF_COMPILER_PARSER_H__
|
||||
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/descriptor.pb.h>
|
||||
#include <google/protobuf/io/tokenizer.h>
|
||||
#include <google/protobuf/repeated_field.h>
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
class Message;
|
||||
|
||||
namespace compiler {
|
||||
|
||||
// Defined in this file.
|
||||
class Parser;
|
||||
class SourceLocationTable;
|
||||
|
||||
// Implements parsing of protocol definitions (such as .proto files).
|
||||
//
|
||||
// Note that most users will be more interested in the Importer class.
|
||||
// Parser is a lower-level class which simply converts a single .proto file
|
||||
// to a FileDescriptorProto. It does not resolve import directives or perform
|
||||
// many other kinds of validation needed to construct a complete
|
||||
// FileDescriptor.
|
||||
class PROTOBUF_EXPORT Parser {
|
||||
public:
|
||||
Parser();
|
||||
~Parser();
|
||||
|
||||
// Parse the entire input and construct a FileDescriptorProto representing
|
||||
// it. Returns true if no errors occurred, false otherwise.
|
||||
bool Parse(io::Tokenizer* input, FileDescriptorProto* file);
|
||||
|
||||
// Optional features:
|
||||
|
||||
// DEPRECATED: New code should use the SourceCodeInfo embedded in the
|
||||
// FileDescriptorProto.
|
||||
//
|
||||
// Requests that locations of certain definitions be recorded to the given
|
||||
// SourceLocationTable while parsing. This can be used to look up exact line
|
||||
// and column numbers for errors reported by DescriptorPool during validation.
|
||||
// Set to NULL (the default) to discard source location information.
|
||||
void RecordSourceLocationsTo(SourceLocationTable* location_table) {
|
||||
source_location_table_ = location_table;
|
||||
}
|
||||
|
||||
// Requests that errors be recorded to the given ErrorCollector while
|
||||
// parsing. Set to NULL (the default) to discard error messages.
|
||||
void RecordErrorsTo(io::ErrorCollector* error_collector) {
|
||||
error_collector_ = error_collector;
|
||||
}
|
||||
|
||||
// Returns the identifier used in the "syntax = " declaration, if one was
|
||||
// seen during the last call to Parse(), or the empty string otherwise.
|
||||
const std::string& GetSyntaxIdentifier() { return syntax_identifier_; }
|
||||
|
||||
// If set true, input files will be required to begin with a syntax
|
||||
// identifier. Otherwise, files may omit this. If a syntax identifier
|
||||
// is provided, it must be 'syntax = "proto2";' and must appear at the
|
||||
// top of this file regardless of whether or not it was required.
|
||||
void SetRequireSyntaxIdentifier(bool value) {
|
||||
require_syntax_identifier_ = value;
|
||||
}
|
||||
|
||||
// Call SetStopAfterSyntaxIdentifier(true) to tell the parser to stop
|
||||
// parsing as soon as it has seen the syntax identifier, or lack thereof.
|
||||
// This is useful for quickly identifying the syntax of the file without
|
||||
// parsing the whole thing. If this is enabled, no error will be recorded
|
||||
// if the syntax identifier is something other than "proto2" (since
|
||||
// presumably the caller intends to deal with that), but other kinds of
|
||||
// errors (e.g. parse errors) will still be reported. When this is enabled,
|
||||
// you may pass a NULL FileDescriptorProto to Parse().
|
||||
void SetStopAfterSyntaxIdentifier(bool value) {
|
||||
stop_after_syntax_identifier_ = value;
|
||||
}
|
||||
|
||||
private:
|
||||
class LocationRecorder;
|
||||
struct MapField;
|
||||
|
||||
// =================================================================
|
||||
// Error recovery helpers
|
||||
|
||||
// Consume the rest of the current statement. This consumes tokens
|
||||
// until it sees one of:
|
||||
// ';' Consumes the token and returns.
|
||||
// '{' Consumes the brace then calls SkipRestOfBlock().
|
||||
// '}' Returns without consuming.
|
||||
// EOF Returns (can't consume).
|
||||
// The Parser often calls SkipStatement() after encountering a syntax
|
||||
// error. This allows it to go on parsing the following lines, allowing
|
||||
// it to report more than just one error in the file.
|
||||
void SkipStatement();
|
||||
|
||||
// Consume the rest of the current block, including nested blocks,
|
||||
// ending after the closing '}' is encountered and consumed, or at EOF.
|
||||
void SkipRestOfBlock();
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// Single-token consuming helpers
|
||||
//
|
||||
// These make parsing code more readable.
|
||||
|
||||
// True if the current token is TYPE_END.
|
||||
inline bool AtEnd();
|
||||
|
||||
// True if the next token matches the given text.
|
||||
inline bool LookingAt(const char* text);
|
||||
// True if the next token is of the given type.
|
||||
inline bool LookingAtType(io::Tokenizer::TokenType token_type);
|
||||
|
||||
// If the next token exactly matches the text given, consume it and return
|
||||
// true. Otherwise, return false without logging an error.
|
||||
bool TryConsume(const char* text);
|
||||
|
||||
// These attempt to read some kind of token from the input. If successful,
|
||||
// they return true. Otherwise they return false and add the given error
|
||||
// to the error list.
|
||||
|
||||
// Consume a token with the exact text given.
|
||||
bool Consume(const char* text, const char* error);
|
||||
// Same as above, but automatically generates the error "Expected \"text\".",
|
||||
// where "text" is the expected token text.
|
||||
bool Consume(const char* text);
|
||||
// Consume a token of type IDENTIFIER and store its text in "output".
|
||||
bool ConsumeIdentifier(std::string* output, const char* error);
|
||||
// Consume an integer and store its value in "output".
|
||||
bool ConsumeInteger(int* output, const char* error);
|
||||
// Consume a signed integer and store its value in "output".
|
||||
bool ConsumeSignedInteger(int* output, const char* error);
|
||||
// Consume a 64-bit integer and store its value in "output". If the value
|
||||
// is greater than max_value, an error will be reported.
|
||||
bool ConsumeInteger64(uint64_t max_value, uint64_t* output,
|
||||
const char* error);
|
||||
// Consume a number and store its value in "output". This will accept
|
||||
// tokens of either INTEGER or FLOAT type.
|
||||
bool ConsumeNumber(double* output, const char* error);
|
||||
// Consume a string literal and store its (unescaped) value in "output".
|
||||
bool ConsumeString(std::string* output, const char* error);
|
||||
|
||||
// Consume a token representing the end of the statement. Comments between
|
||||
// this token and the next will be harvested for documentation. The given
|
||||
// LocationRecorder should refer to the declaration that was just parsed;
|
||||
// it will be populated with these comments.
|
||||
//
|
||||
// TODO(kenton): The LocationRecorder is const because historically locations
|
||||
// have been passed around by const reference, for no particularly good
|
||||
// reason. We should probably go through and change them all to mutable
|
||||
// pointer to make this more intuitive.
|
||||
bool TryConsumeEndOfDeclaration(const char* text,
|
||||
const LocationRecorder* location);
|
||||
bool TryConsumeEndOfDeclarationFinishScope(const char* text,
|
||||
const LocationRecorder* location);
|
||||
|
||||
bool ConsumeEndOfDeclaration(const char* text,
|
||||
const LocationRecorder* location);
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// Error logging helpers
|
||||
|
||||
// Invokes error_collector_->AddError(), if error_collector_ is not NULL.
|
||||
void AddError(int line, int column, const std::string& error);
|
||||
|
||||
// Invokes error_collector_->AddError() with the line and column number
|
||||
// of the current token.
|
||||
void AddError(const std::string& error);
|
||||
|
||||
// Invokes error_collector_->AddWarning() with the line and column number
|
||||
// of the current token.
|
||||
void AddWarning(const std::string& warning);
|
||||
|
||||
// Records a location in the SourceCodeInfo.location table (see
|
||||
// descriptor.proto). We use RAII to ensure that the start and end locations
|
||||
// are recorded -- the constructor records the start location and the
|
||||
// destructor records the end location. Since the parser is
|
||||
// recursive-descent, this works out beautifully.
|
||||
class PROTOBUF_EXPORT LocationRecorder {
|
||||
public:
|
||||
// Construct the file's "root" location.
|
||||
LocationRecorder(Parser* parser);
|
||||
|
||||
// Construct a location that represents a declaration nested within the
|
||||
// given parent. E.g. a field's location is nested within the location
|
||||
// for a message type. The parent's path will be copied, so you should
|
||||
// call AddPath() only to add the path components leading from the parent
|
||||
// to the child (as opposed to leading from the root to the child).
|
||||
LocationRecorder(const LocationRecorder& parent);
|
||||
|
||||
// Convenience constructors that call AddPath() one or two times.
|
||||
LocationRecorder(const LocationRecorder& parent, int path1);
|
||||
LocationRecorder(const LocationRecorder& parent, int path1, int path2);
|
||||
|
||||
// Creates a recorder that generates locations into given source code info.
|
||||
LocationRecorder(const LocationRecorder& parent, int path1,
|
||||
SourceCodeInfo* source_code_info);
|
||||
|
||||
~LocationRecorder();
|
||||
|
||||
// Add a path component. See SourceCodeInfo.Location.path in
|
||||
// descriptor.proto.
|
||||
void AddPath(int path_component);
|
||||
|
||||
// By default the location is considered to start at the current token at
|
||||
// the time the LocationRecorder is created. StartAt() sets the start
|
||||
// location to the given token instead.
|
||||
void StartAt(const io::Tokenizer::Token& token);
|
||||
|
||||
// Start at the same location as some other LocationRecorder.
|
||||
void StartAt(const LocationRecorder& other);
|
||||
|
||||
// By default the location is considered to end at the previous token at
|
||||
// the time the LocationRecorder is destroyed. EndAt() sets the end
|
||||
// location to the given token instead.
|
||||
void EndAt(const io::Tokenizer::Token& token);
|
||||
|
||||
// Records the start point of this location to the SourceLocationTable that
|
||||
// was passed to RecordSourceLocationsTo(), if any. SourceLocationTable
|
||||
// is an older way of keeping track of source locations which is still
|
||||
// used in some places.
|
||||
void RecordLegacyLocation(
|
||||
const Message* descriptor,
|
||||
DescriptorPool::ErrorCollector::ErrorLocation location);
|
||||
void RecordLegacyImportLocation(const Message* descriptor,
|
||||
const std::string& name);
|
||||
|
||||
// Returns the number of path components in the recorder's current location.
|
||||
int CurrentPathSize() const;
|
||||
|
||||
// Attaches leading and trailing comments to the location. The two strings
|
||||
// will be swapped into place, so after this is called *leading and
|
||||
// *trailing will be empty.
|
||||
//
|
||||
// TODO(kenton): See comment on TryConsumeEndOfDeclaration(), above, for
|
||||
// why this is const.
|
||||
void AttachComments(std::string* leading, std::string* trailing,
|
||||
std::vector<std::string>* detached_comments) const;
|
||||
|
||||
private:
|
||||
Parser* parser_;
|
||||
SourceCodeInfo* source_code_info_;
|
||||
SourceCodeInfo::Location* location_;
|
||||
|
||||
void Init(const LocationRecorder& parent, SourceCodeInfo* source_code_info);
|
||||
};
|
||||
|
||||
// =================================================================
|
||||
// Parsers for various language constructs
|
||||
|
||||
// Parses the "syntax = \"proto2\";" line at the top of the file. Returns
|
||||
// false if it failed to parse or if the syntax identifier was not
|
||||
// recognized.
|
||||
bool ParseSyntaxIdentifier(const LocationRecorder& parent);
|
||||
|
||||
// These methods parse various individual bits of code. They return
|
||||
// false if they completely fail to parse the construct. In this case,
|
||||
// it is probably necessary to skip the rest of the statement to recover.
|
||||
// However, if these methods return true, it does NOT mean that there
|
||||
// were no errors; only that there were no *syntax* errors. For instance,
|
||||
// if a service method is defined using proper syntax but uses a primitive
|
||||
// type as its input or output, ParseMethodField() still returns true
|
||||
// and only reports the error by calling AddError(). In practice, this
|
||||
// makes logic much simpler for the caller.
|
||||
|
||||
// Parse a top-level message, enum, service, etc.
|
||||
bool ParseTopLevelStatement(FileDescriptorProto* file,
|
||||
const LocationRecorder& root_location);
|
||||
|
||||
// Parse various language high-level language construrcts.
|
||||
bool ParseMessageDefinition(DescriptorProto* message,
|
||||
const LocationRecorder& message_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
bool ParseEnumDefinition(EnumDescriptorProto* enum_type,
|
||||
const LocationRecorder& enum_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
bool ParseServiceDefinition(ServiceDescriptorProto* service,
|
||||
const LocationRecorder& service_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
bool ParsePackage(FileDescriptorProto* file,
|
||||
const LocationRecorder& root_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
bool ParseImport(RepeatedPtrField<std::string>* dependency,
|
||||
RepeatedField<int32_t>* public_dependency,
|
||||
RepeatedField<int32_t>* weak_dependency,
|
||||
const LocationRecorder& root_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
|
||||
// These methods parse the contents of a message, enum, or service type and
|
||||
// add them to the given object. They consume the entire block including
|
||||
// the beginning and ending brace.
|
||||
bool ParseMessageBlock(DescriptorProto* message,
|
||||
const LocationRecorder& message_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
bool ParseEnumBlock(EnumDescriptorProto* enum_type,
|
||||
const LocationRecorder& enum_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
bool ParseServiceBlock(ServiceDescriptorProto* service,
|
||||
const LocationRecorder& service_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
|
||||
// Parse one statement within a message, enum, or service block, including
|
||||
// final semicolon.
|
||||
bool ParseMessageStatement(DescriptorProto* message,
|
||||
const LocationRecorder& message_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
bool ParseEnumStatement(EnumDescriptorProto* message,
|
||||
const LocationRecorder& enum_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
bool ParseServiceStatement(ServiceDescriptorProto* message,
|
||||
const LocationRecorder& service_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
|
||||
// Parse a field of a message. If the field is a group, its type will be
|
||||
// added to "messages".
|
||||
//
|
||||
// parent_location and location_field_number_for_nested_type are needed when
|
||||
// parsing groups -- we need to generate a nested message type within the
|
||||
// parent and record its location accordingly. Since the parent could be
|
||||
// either a FileDescriptorProto or a DescriptorProto, we must pass in the
|
||||
// correct field number to use.
|
||||
bool ParseMessageField(FieldDescriptorProto* field,
|
||||
RepeatedPtrField<DescriptorProto>* messages,
|
||||
const LocationRecorder& parent_location,
|
||||
int location_field_number_for_nested_type,
|
||||
const LocationRecorder& field_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
|
||||
// Like ParseMessageField() but expects the label has already been filled in
|
||||
// by the caller.
|
||||
bool ParseMessageFieldNoLabel(FieldDescriptorProto* field,
|
||||
RepeatedPtrField<DescriptorProto>* messages,
|
||||
const LocationRecorder& parent_location,
|
||||
int location_field_number_for_nested_type,
|
||||
const LocationRecorder& field_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
|
||||
bool ParseMapType(MapField* map_field, FieldDescriptorProto* field,
|
||||
LocationRecorder& type_name_location);
|
||||
|
||||
// Parse an "extensions" declaration.
|
||||
bool ParseExtensions(DescriptorProto* message,
|
||||
const LocationRecorder& extensions_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
|
||||
// Parse a "reserved" declaration.
|
||||
bool ParseReserved(DescriptorProto* message,
|
||||
const LocationRecorder& message_location);
|
||||
bool ParseReservedNames(DescriptorProto* message,
|
||||
const LocationRecorder& parent_location);
|
||||
bool ParseReservedNumbers(DescriptorProto* message,
|
||||
const LocationRecorder& parent_location);
|
||||
bool ParseReserved(EnumDescriptorProto* message,
|
||||
const LocationRecorder& message_location);
|
||||
bool ParseReservedNames(EnumDescriptorProto* message,
|
||||
const LocationRecorder& parent_location);
|
||||
bool ParseReservedNumbers(EnumDescriptorProto* message,
|
||||
const LocationRecorder& parent_location);
|
||||
|
||||
// Parse an "extend" declaration. (See also comments for
|
||||
// ParseMessageField().)
|
||||
bool ParseExtend(RepeatedPtrField<FieldDescriptorProto>* extensions,
|
||||
RepeatedPtrField<DescriptorProto>* messages,
|
||||
const LocationRecorder& parent_location,
|
||||
int location_field_number_for_nested_type,
|
||||
const LocationRecorder& extend_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
|
||||
// Parse a "oneof" declaration. The caller is responsible for setting
|
||||
// oneof_decl->label() since it will have had to parse the label before it
|
||||
// knew it was parsing a oneof.
|
||||
bool ParseOneof(OneofDescriptorProto* oneof_decl,
|
||||
DescriptorProto* containing_type, int oneof_index,
|
||||
const LocationRecorder& oneof_location,
|
||||
const LocationRecorder& containing_type_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
|
||||
// Parse a single enum value within an enum block.
|
||||
bool ParseEnumConstant(EnumValueDescriptorProto* enum_value,
|
||||
const LocationRecorder& enum_value_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
|
||||
// Parse enum constant options, i.e. the list in square brackets at the end
|
||||
// of the enum constant value definition.
|
||||
bool ParseEnumConstantOptions(EnumValueDescriptorProto* value,
|
||||
const LocationRecorder& enum_value_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
|
||||
// Parse a single method within a service definition.
|
||||
bool ParseServiceMethod(MethodDescriptorProto* method,
|
||||
const LocationRecorder& method_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
|
||||
// Parse options of a single method or stream.
|
||||
bool ParseMethodOptions(const LocationRecorder& parent_location,
|
||||
const FileDescriptorProto* containing_file,
|
||||
const int optionsFieldNumber,
|
||||
Message* mutable_options);
|
||||
|
||||
// Parse "required", "optional", or "repeated" and fill in "label"
|
||||
// with the value. Returns true if such a label is consumed.
|
||||
bool ParseLabel(FieldDescriptorProto::Label* label,
|
||||
const LocationRecorder& field_location);
|
||||
|
||||
// Parse a type name and fill in "type" (if it is a primitive) or
|
||||
// "type_name" (if it is not) with the type parsed.
|
||||
bool ParseType(FieldDescriptorProto::Type* type, std::string* type_name);
|
||||
// Parse a user-defined type and fill in "type_name" with the name.
|
||||
// If a primitive type is named, it is treated as an error.
|
||||
bool ParseUserDefinedType(std::string* type_name);
|
||||
|
||||
// Parses field options, i.e. the stuff in square brackets at the end
|
||||
// of a field definition. Also parses default value.
|
||||
bool ParseFieldOptions(FieldDescriptorProto* field,
|
||||
const LocationRecorder& field_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
|
||||
// Parse the "default" option. This needs special handling because its
|
||||
// type is the field's type.
|
||||
bool ParseDefaultAssignment(FieldDescriptorProto* field,
|
||||
const LocationRecorder& field_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
|
||||
bool ParseJsonName(FieldDescriptorProto* field,
|
||||
const LocationRecorder& field_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
|
||||
enum OptionStyle {
|
||||
OPTION_ASSIGNMENT, // just "name = value"
|
||||
OPTION_STATEMENT // "option name = value;"
|
||||
};
|
||||
|
||||
// Parse a single option name/value pair, e.g. "ctype = CORD". The name
|
||||
// identifies a field of the given Message, and the value of that field
|
||||
// is set to the parsed value.
|
||||
bool ParseOption(Message* options, const LocationRecorder& options_location,
|
||||
const FileDescriptorProto* containing_file,
|
||||
OptionStyle style);
|
||||
|
||||
// Parses a single part of a multipart option name. A multipart name consists
|
||||
// of names separated by dots. Each name is either an identifier or a series
|
||||
// of identifiers separated by dots and enclosed in parentheses. E.g.,
|
||||
// "foo.(bar.baz).moo".
|
||||
bool ParseOptionNamePart(UninterpretedOption* uninterpreted_option,
|
||||
const LocationRecorder& part_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
|
||||
// Parses a string surrounded by balanced braces. Strips off the outer
|
||||
// braces and stores the enclosed string in *value.
|
||||
// E.g.,
|
||||
// { foo } *value gets 'foo'
|
||||
// { foo { bar: box } } *value gets 'foo { bar: box }'
|
||||
// {} *value gets ''
|
||||
//
|
||||
// REQUIRES: LookingAt("{")
|
||||
// When finished successfully, we are looking at the first token past
|
||||
// the ending brace.
|
||||
bool ParseUninterpretedBlock(std::string* value);
|
||||
|
||||
struct MapField {
|
||||
// Whether the field is a map field.
|
||||
bool is_map_field;
|
||||
// The types of the key and value if they are primitive types.
|
||||
FieldDescriptorProto::Type key_type;
|
||||
FieldDescriptorProto::Type value_type;
|
||||
// Or the type names string if the types are customized types.
|
||||
std::string key_type_name;
|
||||
std::string value_type_name;
|
||||
|
||||
MapField() : is_map_field(false) {}
|
||||
};
|
||||
// Desugar the map syntax to generate a nested map entry message.
|
||||
void GenerateMapEntry(const MapField& map_field, FieldDescriptorProto* field,
|
||||
RepeatedPtrField<DescriptorProto>* messages);
|
||||
|
||||
// Whether fields without label default to optional fields.
|
||||
bool DefaultToOptionalFields() const {
|
||||
return syntax_identifier_ == "proto3";
|
||||
}
|
||||
|
||||
bool ValidateEnum(const EnumDescriptorProto* proto);
|
||||
|
||||
// =================================================================
|
||||
|
||||
io::Tokenizer* input_;
|
||||
io::ErrorCollector* error_collector_;
|
||||
SourceCodeInfo* source_code_info_;
|
||||
SourceLocationTable* source_location_table_; // legacy
|
||||
bool had_errors_;
|
||||
bool require_syntax_identifier_;
|
||||
bool stop_after_syntax_identifier_;
|
||||
std::string syntax_identifier_;
|
||||
|
||||
// Leading doc comments for the next declaration. These are not complete
|
||||
// yet; use ConsumeEndOfDeclaration() to get the complete comments.
|
||||
std::string upcoming_doc_comments_;
|
||||
|
||||
// Detached comments are not connected to any syntax entities. Elements in
|
||||
// this vector are paragraphs of comments separated by empty lines. The
|
||||
// detached comments will be put into the leading_detached_comments field for
|
||||
// the next element (See SourceCodeInfo.Location in descriptor.proto), when
|
||||
// ConsumeEndOfDeclaration() is called.
|
||||
std::vector<std::string> upcoming_detached_comments_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Parser);
|
||||
};
|
||||
|
||||
// A table mapping (descriptor, ErrorLocation) pairs -- as reported by
|
||||
// DescriptorPool when validating descriptors -- to line and column numbers
|
||||
// within the original source code.
|
||||
//
|
||||
// This is semi-obsolete: FileDescriptorProto.source_code_info now contains
|
||||
// far more complete information about source locations. However, as of this
|
||||
// writing you still need to use SourceLocationTable when integrating with
|
||||
// DescriptorPool.
|
||||
class PROTOBUF_EXPORT SourceLocationTable {
|
||||
public:
|
||||
SourceLocationTable();
|
||||
~SourceLocationTable();
|
||||
|
||||
// Finds the precise location of the given error and fills in *line and
|
||||
// *column with the line and column numbers. If not found, sets *line to
|
||||
// -1 and *column to 0 (since line = -1 is used to mean "error has no exact
|
||||
// location" in the ErrorCollector interface). Returns true if found, false
|
||||
// otherwise.
|
||||
bool Find(const Message* descriptor,
|
||||
DescriptorPool::ErrorCollector::ErrorLocation location, int* line,
|
||||
int* column) const;
|
||||
bool FindImport(const Message* descriptor, const std::string& name, int* line,
|
||||
int* column) const;
|
||||
|
||||
// Adds a location to the table.
|
||||
void Add(const Message* descriptor,
|
||||
DescriptorPool::ErrorCollector::ErrorLocation location, int line,
|
||||
int column);
|
||||
void AddImport(const Message* descriptor, const std::string& name, int line,
|
||||
int column);
|
||||
|
||||
// Clears the contents of the table.
|
||||
void Clear();
|
||||
|
||||
private:
|
||||
typedef std::map<
|
||||
std::pair<const Message*, DescriptorPool::ErrorCollector::ErrorLocation>,
|
||||
std::pair<int, int> >
|
||||
LocationMap;
|
||||
LocationMap location_map_;
|
||||
std::map<std::pair<const Message*, std::string>, std::pair<int, int> >
|
||||
import_location_map_;
|
||||
};
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_PARSER_H__
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,398 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
//
|
||||
// Interface for manipulating databases of descriptors.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_DESCRIPTOR_DATABASE_H__
|
||||
#define GOOGLE_PROTOBUF_DESCRIPTOR_DATABASE_H__
|
||||
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
#ifdef SWIG
|
||||
#error "You cannot SWIG proto headers"
|
||||
#endif
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
// Defined in this file.
|
||||
class DescriptorDatabase;
|
||||
class SimpleDescriptorDatabase;
|
||||
class EncodedDescriptorDatabase;
|
||||
class DescriptorPoolDatabase;
|
||||
class MergedDescriptorDatabase;
|
||||
|
||||
// Abstract interface for a database of descriptors.
|
||||
//
|
||||
// This is useful if you want to create a DescriptorPool which loads
|
||||
// descriptors on-demand from some sort of large database. If the database
|
||||
// is large, it may be inefficient to enumerate every .proto file inside it
|
||||
// calling DescriptorPool::BuildFile() for each one. Instead, a DescriptorPool
|
||||
// can be created which wraps a DescriptorDatabase and only builds particular
|
||||
// descriptors when they are needed.
|
||||
class PROTOBUF_EXPORT DescriptorDatabase {
|
||||
public:
|
||||
inline DescriptorDatabase() {}
|
||||
virtual ~DescriptorDatabase();
|
||||
|
||||
// Find a file by file name. Fills in in *output and returns true if found.
|
||||
// Otherwise, returns false, leaving the contents of *output undefined.
|
||||
virtual bool FindFileByName(const std::string& filename,
|
||||
FileDescriptorProto* output) = 0;
|
||||
|
||||
// Find the file that declares the given fully-qualified symbol name.
|
||||
// If found, fills in *output and returns true, otherwise returns false
|
||||
// and leaves *output undefined.
|
||||
virtual bool FindFileContainingSymbol(const std::string& symbol_name,
|
||||
FileDescriptorProto* output) = 0;
|
||||
|
||||
// Find the file which defines an extension extending the given message type
|
||||
// with the given field number. If found, fills in *output and returns true,
|
||||
// otherwise returns false and leaves *output undefined. containing_type
|
||||
// must be a fully-qualified type name.
|
||||
virtual bool FindFileContainingExtension(const std::string& containing_type,
|
||||
int field_number,
|
||||
FileDescriptorProto* output) = 0;
|
||||
|
||||
// Finds the tag numbers used by all known extensions of
|
||||
// extendee_type, and appends them to output in an undefined
|
||||
// order. This method is best-effort: it's not guaranteed that the
|
||||
// database will find all extensions, and it's not guaranteed that
|
||||
// FindFileContainingExtension will return true on all of the found
|
||||
// numbers. Returns true if the search was successful, otherwise
|
||||
// returns false and leaves output unchanged.
|
||||
//
|
||||
// This method has a default implementation that always returns
|
||||
// false.
|
||||
virtual bool FindAllExtensionNumbers(const std::string& /* extendee_type */,
|
||||
std::vector<int>* /* output */) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Finds the file names and appends them to the output in an
|
||||
// undefined order. This method is best-effort: it's not guaranteed that the
|
||||
// database will find all files. Returns true if the database supports
|
||||
// searching all file names, otherwise returns false and leaves output
|
||||
// unchanged.
|
||||
//
|
||||
// This method has a default implementation that always returns
|
||||
// false.
|
||||
virtual bool FindAllFileNames(std::vector<std::string>* /*output*/) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Finds the package names and appends them to the output in an
|
||||
// undefined order. This method is best-effort: it's not guaranteed that the
|
||||
// database will find all packages. Returns true if the database supports
|
||||
// searching all package names, otherwise returns false and leaves output
|
||||
// unchanged.
|
||||
bool FindAllPackageNames(std::vector<std::string>* output);
|
||||
|
||||
// Finds the message names and appends them to the output in an
|
||||
// undefined order. This method is best-effort: it's not guaranteed that the
|
||||
// database will find all messages. Returns true if the database supports
|
||||
// searching all message names, otherwise returns false and leaves output
|
||||
// unchanged.
|
||||
bool FindAllMessageNames(std::vector<std::string>* output);
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DescriptorDatabase);
|
||||
};
|
||||
|
||||
// A DescriptorDatabase into which you can insert files manually.
|
||||
//
|
||||
// FindFileContainingSymbol() is fully-implemented. When you add a file, its
|
||||
// symbols will be indexed for this purpose. Note that the implementation
|
||||
// may return false positives, but only if it isn't possible for the symbol
|
||||
// to be defined in any other file. In particular, if a file defines a symbol
|
||||
// "Foo", then searching for "Foo.[anything]" will match that file. This way,
|
||||
// the database does not need to aggressively index all children of a symbol.
|
||||
//
|
||||
// FindFileContainingExtension() is mostly-implemented. It works if and only
|
||||
// if the original FieldDescriptorProto defining the extension has a
|
||||
// fully-qualified type name in its "extendee" field (i.e. starts with a '.').
|
||||
// If the extendee is a relative name, SimpleDescriptorDatabase will not
|
||||
// attempt to resolve the type, so it will not know what type the extension is
|
||||
// extending. Therefore, calling FindFileContainingExtension() with the
|
||||
// extension's containing type will never actually find that extension. Note
|
||||
// that this is an unlikely problem, as all FileDescriptorProtos created by the
|
||||
// protocol compiler (as well as ones created by calling
|
||||
// FileDescriptor::CopyTo()) will always use fully-qualified names for all
|
||||
// types. You only need to worry if you are constructing FileDescriptorProtos
|
||||
// yourself, or are calling compiler::Parser directly.
|
||||
class PROTOBUF_EXPORT SimpleDescriptorDatabase : public DescriptorDatabase {
|
||||
public:
|
||||
SimpleDescriptorDatabase();
|
||||
~SimpleDescriptorDatabase() override;
|
||||
|
||||
// Adds the FileDescriptorProto to the database, making a copy. The object
|
||||
// can be deleted after Add() returns. Returns false if the file conflicted
|
||||
// with a file already in the database, in which case an error will have
|
||||
// been written to GOOGLE_LOG(ERROR).
|
||||
bool Add(const FileDescriptorProto& file);
|
||||
|
||||
// Adds the FileDescriptorProto to the database and takes ownership of it.
|
||||
bool AddAndOwn(const FileDescriptorProto* file);
|
||||
|
||||
// implements DescriptorDatabase -----------------------------------
|
||||
bool FindFileByName(const std::string& filename,
|
||||
FileDescriptorProto* output) override;
|
||||
bool FindFileContainingSymbol(const std::string& symbol_name,
|
||||
FileDescriptorProto* output) override;
|
||||
bool FindFileContainingExtension(const std::string& containing_type,
|
||||
int field_number,
|
||||
FileDescriptorProto* output) override;
|
||||
bool FindAllExtensionNumbers(const std::string& extendee_type,
|
||||
std::vector<int>* output) override;
|
||||
|
||||
bool FindAllFileNames(std::vector<std::string>* output) override;
|
||||
|
||||
private:
|
||||
// An index mapping file names, symbol names, and extension numbers to
|
||||
// some sort of values.
|
||||
template <typename Value>
|
||||
class DescriptorIndex {
|
||||
public:
|
||||
// Helpers to recursively add particular descriptors and all their contents
|
||||
// to the index.
|
||||
bool AddFile(const FileDescriptorProto& file, Value value);
|
||||
bool AddSymbol(const std::string& name, Value value);
|
||||
bool AddNestedExtensions(const std::string& filename,
|
||||
const DescriptorProto& message_type, Value value);
|
||||
bool AddExtension(const std::string& filename,
|
||||
const FieldDescriptorProto& field, Value value);
|
||||
|
||||
Value FindFile(const std::string& filename);
|
||||
Value FindSymbol(const std::string& name);
|
||||
Value FindExtension(const std::string& containing_type, int field_number);
|
||||
bool FindAllExtensionNumbers(const std::string& containing_type,
|
||||
std::vector<int>* output);
|
||||
void FindAllFileNames(std::vector<std::string>* output);
|
||||
|
||||
private:
|
||||
std::map<std::string, Value> by_name_;
|
||||
std::map<std::string, Value> by_symbol_;
|
||||
std::map<std::pair<std::string, int>, Value> by_extension_;
|
||||
|
||||
// Invariant: The by_symbol_ map does not contain any symbols which are
|
||||
// prefixes of other symbols in the map. For example, "foo.bar" is a
|
||||
// prefix of "foo.bar.baz" (but is not a prefix of "foo.barbaz").
|
||||
//
|
||||
// This invariant is important because it means that given a symbol name,
|
||||
// we can find a key in the map which is a prefix of the symbol in O(lg n)
|
||||
// time, and we know that there is at most one such key.
|
||||
//
|
||||
// The prefix lookup algorithm works like so:
|
||||
// 1) Find the last key in the map which is less than or equal to the
|
||||
// search key.
|
||||
// 2) If the found key is a prefix of the search key, then return it.
|
||||
// Otherwise, there is no match.
|
||||
//
|
||||
// I am sure this algorithm has been described elsewhere, but since I
|
||||
// wasn't able to find it quickly I will instead prove that it works
|
||||
// myself. The key to the algorithm is that if a match exists, step (1)
|
||||
// will find it. Proof:
|
||||
// 1) Define the "search key" to be the key we are looking for, the "found
|
||||
// key" to be the key found in step (1), and the "match key" to be the
|
||||
// key which actually matches the search key (i.e. the key we're trying
|
||||
// to find).
|
||||
// 2) The found key must be less than or equal to the search key by
|
||||
// definition.
|
||||
// 3) The match key must also be less than or equal to the search key
|
||||
// (because it is a prefix).
|
||||
// 4) The match key cannot be greater than the found key, because if it
|
||||
// were, then step (1) of the algorithm would have returned the match
|
||||
// key instead (since it finds the *greatest* key which is less than or
|
||||
// equal to the search key).
|
||||
// 5) Therefore, the found key must be between the match key and the search
|
||||
// key, inclusive.
|
||||
// 6) Since the search key must be a sub-symbol of the match key, if it is
|
||||
// not equal to the match key, then search_key[match_key.size()] must
|
||||
// be '.'.
|
||||
// 7) Since '.' sorts before any other character that is valid in a symbol
|
||||
// name, then if the found key is not equal to the match key, then
|
||||
// found_key[match_key.size()] must also be '.', because any other value
|
||||
// would make it sort after the search key.
|
||||
// 8) Therefore, if the found key is not equal to the match key, then the
|
||||
// found key must be a sub-symbol of the match key. However, this would
|
||||
// contradict our map invariant which says that no symbol in the map is
|
||||
// a sub-symbol of any other.
|
||||
// 9) Therefore, the found key must match the match key.
|
||||
//
|
||||
// The above proof assumes the match key exists. In the case that the
|
||||
// match key does not exist, then step (1) will return some other symbol.
|
||||
// That symbol cannot be a super-symbol of the search key since if it were,
|
||||
// then it would be a match, and we're assuming the match key doesn't exist.
|
||||
// Therefore, step 2 will correctly return no match.
|
||||
};
|
||||
|
||||
DescriptorIndex<const FileDescriptorProto*> index_;
|
||||
std::vector<std::unique_ptr<const FileDescriptorProto>> files_to_delete_;
|
||||
|
||||
// If file is non-nullptr, copy it into *output and return true, otherwise
|
||||
// return false.
|
||||
bool MaybeCopy(const FileDescriptorProto* file, FileDescriptorProto* output);
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SimpleDescriptorDatabase);
|
||||
};
|
||||
|
||||
// Very similar to SimpleDescriptorDatabase, but stores all the descriptors
|
||||
// as raw bytes and generally tries to use as little memory as possible.
|
||||
//
|
||||
// The same caveats regarding FindFileContainingExtension() apply as with
|
||||
// SimpleDescriptorDatabase.
|
||||
class PROTOBUF_EXPORT EncodedDescriptorDatabase : public DescriptorDatabase {
|
||||
public:
|
||||
EncodedDescriptorDatabase();
|
||||
~EncodedDescriptorDatabase() override;
|
||||
|
||||
// Adds the FileDescriptorProto to the database. The descriptor is provided
|
||||
// in encoded form. The database does not make a copy of the bytes, nor
|
||||
// does it take ownership; it's up to the caller to make sure the bytes
|
||||
// remain valid for the life of the database. Returns false and logs an error
|
||||
// if the bytes are not a valid FileDescriptorProto or if the file conflicted
|
||||
// with a file already in the database.
|
||||
bool Add(const void* encoded_file_descriptor, int size);
|
||||
|
||||
// Like Add(), but makes a copy of the data, so that the caller does not
|
||||
// need to keep it around.
|
||||
bool AddCopy(const void* encoded_file_descriptor, int size);
|
||||
|
||||
// Like FindFileContainingSymbol but returns only the name of the file.
|
||||
bool FindNameOfFileContainingSymbol(const std::string& symbol_name,
|
||||
std::string* output);
|
||||
|
||||
// implements DescriptorDatabase -----------------------------------
|
||||
bool FindFileByName(const std::string& filename,
|
||||
FileDescriptorProto* output) override;
|
||||
bool FindFileContainingSymbol(const std::string& symbol_name,
|
||||
FileDescriptorProto* output) override;
|
||||
bool FindFileContainingExtension(const std::string& containing_type,
|
||||
int field_number,
|
||||
FileDescriptorProto* output) override;
|
||||
bool FindAllExtensionNumbers(const std::string& extendee_type,
|
||||
std::vector<int>* output) override;
|
||||
bool FindAllFileNames(std::vector<std::string>* output) override;
|
||||
|
||||
private:
|
||||
class DescriptorIndex;
|
||||
// Keep DescriptorIndex by pointer to hide the implementation to keep a
|
||||
// cleaner header.
|
||||
std::unique_ptr<DescriptorIndex> index_;
|
||||
std::vector<void*> files_to_delete_;
|
||||
|
||||
// If encoded_file.first is non-nullptr, parse the data into *output and
|
||||
// return true, otherwise return false.
|
||||
bool MaybeParse(std::pair<const void*, int> encoded_file,
|
||||
FileDescriptorProto* output);
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EncodedDescriptorDatabase);
|
||||
};
|
||||
|
||||
// A DescriptorDatabase that fetches files from a given pool.
|
||||
class PROTOBUF_EXPORT DescriptorPoolDatabase : public DescriptorDatabase {
|
||||
public:
|
||||
explicit DescriptorPoolDatabase(const DescriptorPool& pool);
|
||||
~DescriptorPoolDatabase() override;
|
||||
|
||||
// implements DescriptorDatabase -----------------------------------
|
||||
bool FindFileByName(const std::string& filename,
|
||||
FileDescriptorProto* output) override;
|
||||
bool FindFileContainingSymbol(const std::string& symbol_name,
|
||||
FileDescriptorProto* output) override;
|
||||
bool FindFileContainingExtension(const std::string& containing_type,
|
||||
int field_number,
|
||||
FileDescriptorProto* output) override;
|
||||
bool FindAllExtensionNumbers(const std::string& extendee_type,
|
||||
std::vector<int>* output) override;
|
||||
|
||||
private:
|
||||
const DescriptorPool& pool_;
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DescriptorPoolDatabase);
|
||||
};
|
||||
|
||||
// A DescriptorDatabase that wraps two or more others. It first searches the
|
||||
// first database and, if that fails, tries the second, and so on.
|
||||
class PROTOBUF_EXPORT MergedDescriptorDatabase : public DescriptorDatabase {
|
||||
public:
|
||||
// Merge just two databases. The sources remain property of the caller.
|
||||
MergedDescriptorDatabase(DescriptorDatabase* source1,
|
||||
DescriptorDatabase* source2);
|
||||
// Merge more than two databases. The sources remain property of the caller.
|
||||
// The vector may be deleted after the constructor returns but the
|
||||
// DescriptorDatabases need to stick around.
|
||||
explicit MergedDescriptorDatabase(
|
||||
const std::vector<DescriptorDatabase*>& sources);
|
||||
~MergedDescriptorDatabase() override;
|
||||
|
||||
// implements DescriptorDatabase -----------------------------------
|
||||
bool FindFileByName(const std::string& filename,
|
||||
FileDescriptorProto* output) override;
|
||||
bool FindFileContainingSymbol(const std::string& symbol_name,
|
||||
FileDescriptorProto* output) override;
|
||||
bool FindFileContainingExtension(const std::string& containing_type,
|
||||
int field_number,
|
||||
FileDescriptorProto* output) override;
|
||||
// Merges the results of calling all databases. Returns true iff any
|
||||
// of the databases returned true.
|
||||
bool FindAllExtensionNumbers(const std::string& extendee_type,
|
||||
std::vector<int>* output) override;
|
||||
|
||||
|
||||
// This function is best-effort. Returns true if at least one underlying
|
||||
// DescriptorDatabase returns true.
|
||||
bool FindAllFileNames(std::vector<std::string>* output) override;
|
||||
|
||||
private:
|
||||
std::vector<DescriptorDatabase*> sources_;
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MergedDescriptorDatabase);
|
||||
};
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_DESCRIPTOR_DATABASE_H__
|
||||
@@ -1,278 +0,0 @@
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: google/protobuf/duration.proto
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fduration_2eproto
|
||||
#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fduration_2eproto
|
||||
|
||||
#include <limits>
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/port_def.inc>
|
||||
#if PROTOBUF_VERSION < 3021000
|
||||
#error This file was generated by a newer version of protoc which is
|
||||
#error incompatible with your Protocol Buffer headers. Please update
|
||||
#error your headers.
|
||||
#endif
|
||||
#if 3021012 < PROTOBUF_MIN_PROTOC_VERSION
|
||||
#error This file was generated by an older version of protoc which is
|
||||
#error incompatible with your Protocol Buffer headers. Please
|
||||
#error regenerate this file with a newer version of protoc.
|
||||
#endif
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/arena.h>
|
||||
#include <google/protobuf/arenastring.h>
|
||||
#include <google/protobuf/generated_message_util.h>
|
||||
#include <google/protobuf/metadata_lite.h>
|
||||
#include <google/protobuf/generated_message_reflection.h>
|
||||
#include <google/protobuf/message.h>
|
||||
#include <google/protobuf/repeated_field.h> // IWYU pragma: export
|
||||
#include <google/protobuf/extension_set.h> // IWYU pragma: export
|
||||
#include <google/protobuf/unknown_field_set.h>
|
||||
// @@protoc_insertion_point(includes)
|
||||
#include <google/protobuf/port_def.inc>
|
||||
#define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fduration_2eproto PROTOBUF_EXPORT
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
namespace internal {
|
||||
class AnyMetadata;
|
||||
} // namespace internal
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
|
||||
// Internal implementation detail -- do not use these members.
|
||||
struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2fduration_2eproto {
|
||||
static const uint32_t offsets[];
|
||||
};
|
||||
PROTOBUF_EXPORT extern const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fduration_2eproto;
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
class Duration;
|
||||
struct DurationDefaultTypeInternal;
|
||||
PROTOBUF_EXPORT extern DurationDefaultTypeInternal _Duration_default_instance_;
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Duration* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Duration>(Arena*);
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
|
||||
// ===================================================================
|
||||
|
||||
class PROTOBUF_EXPORT Duration final :
|
||||
public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Duration) */ {
|
||||
public:
|
||||
inline Duration() : Duration(nullptr) {}
|
||||
~Duration() override;
|
||||
explicit PROTOBUF_CONSTEXPR Duration(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
|
||||
|
||||
Duration(const Duration& from);
|
||||
Duration(Duration&& from) noexcept
|
||||
: Duration() {
|
||||
*this = ::std::move(from);
|
||||
}
|
||||
|
||||
inline Duration& operator=(const Duration& from) {
|
||||
CopyFrom(from);
|
||||
return *this;
|
||||
}
|
||||
inline Duration& operator=(Duration&& from) noexcept {
|
||||
if (this == &from) return *this;
|
||||
if (GetOwningArena() == from.GetOwningArena()
|
||||
#ifdef PROTOBUF_FORCE_COPY_IN_MOVE
|
||||
&& GetOwningArena() != nullptr
|
||||
#endif // !PROTOBUF_FORCE_COPY_IN_MOVE
|
||||
) {
|
||||
InternalSwap(&from);
|
||||
} else {
|
||||
CopyFrom(from);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() {
|
||||
return GetDescriptor();
|
||||
}
|
||||
static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
|
||||
return default_instance().GetMetadata().descriptor;
|
||||
}
|
||||
static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
|
||||
return default_instance().GetMetadata().reflection;
|
||||
}
|
||||
static const Duration& default_instance() {
|
||||
return *internal_default_instance();
|
||||
}
|
||||
static inline const Duration* internal_default_instance() {
|
||||
return reinterpret_cast<const Duration*>(
|
||||
&_Duration_default_instance_);
|
||||
}
|
||||
static constexpr int kIndexInFileMessages =
|
||||
0;
|
||||
|
||||
friend void swap(Duration& a, Duration& b) {
|
||||
a.Swap(&b);
|
||||
}
|
||||
inline void Swap(Duration* other) {
|
||||
if (other == this) return;
|
||||
#ifdef PROTOBUF_FORCE_COPY_IN_SWAP
|
||||
if (GetOwningArena() != nullptr &&
|
||||
GetOwningArena() == other->GetOwningArena()) {
|
||||
#else // PROTOBUF_FORCE_COPY_IN_SWAP
|
||||
if (GetOwningArena() == other->GetOwningArena()) {
|
||||
#endif // !PROTOBUF_FORCE_COPY_IN_SWAP
|
||||
InternalSwap(other);
|
||||
} else {
|
||||
::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
|
||||
}
|
||||
}
|
||||
void UnsafeArenaSwap(Duration* other) {
|
||||
if (other == this) return;
|
||||
GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
|
||||
InternalSwap(other);
|
||||
}
|
||||
|
||||
// implements Message ----------------------------------------------
|
||||
|
||||
Duration* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final {
|
||||
return CreateMaybeMessage<Duration>(arena);
|
||||
}
|
||||
using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
|
||||
void CopyFrom(const Duration& from);
|
||||
using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
|
||||
void MergeFrom( const Duration& from) {
|
||||
Duration::MergeImpl(*this, from);
|
||||
}
|
||||
private:
|
||||
static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg);
|
||||
public:
|
||||
PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
|
||||
bool IsInitialized() const final;
|
||||
|
||||
size_t ByteSizeLong() const final;
|
||||
const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
|
||||
uint8_t* _InternalSerialize(
|
||||
uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
|
||||
int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
|
||||
|
||||
private:
|
||||
void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned);
|
||||
void SharedDtor();
|
||||
void SetCachedSize(int size) const final;
|
||||
void InternalSwap(Duration* other);
|
||||
|
||||
private:
|
||||
friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
|
||||
static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
|
||||
return "google.protobuf.Duration";
|
||||
}
|
||||
protected:
|
||||
explicit Duration(::PROTOBUF_NAMESPACE_ID::Arena* arena,
|
||||
bool is_message_owned = false);
|
||||
public:
|
||||
|
||||
static const ClassData _class_data_;
|
||||
const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
|
||||
|
||||
::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
|
||||
|
||||
// nested types ----------------------------------------------------
|
||||
|
||||
// accessors -------------------------------------------------------
|
||||
|
||||
enum : int {
|
||||
kSecondsFieldNumber = 1,
|
||||
kNanosFieldNumber = 2,
|
||||
};
|
||||
// int64 seconds = 1;
|
||||
void clear_seconds();
|
||||
int64_t seconds() const;
|
||||
void set_seconds(int64_t value);
|
||||
private:
|
||||
int64_t _internal_seconds() const;
|
||||
void _internal_set_seconds(int64_t value);
|
||||
public:
|
||||
|
||||
// int32 nanos = 2;
|
||||
void clear_nanos();
|
||||
int32_t nanos() const;
|
||||
void set_nanos(int32_t value);
|
||||
private:
|
||||
int32_t _internal_nanos() const;
|
||||
void _internal_set_nanos(int32_t value);
|
||||
public:
|
||||
|
||||
// @@protoc_insertion_point(class_scope:google.protobuf.Duration)
|
||||
private:
|
||||
class _Internal;
|
||||
|
||||
template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper;
|
||||
typedef void InternalArenaConstructable_;
|
||||
typedef void DestructorSkippable_;
|
||||
struct Impl_ {
|
||||
int64_t seconds_;
|
||||
int32_t nanos_;
|
||||
mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
|
||||
};
|
||||
union { Impl_ _impl_; };
|
||||
friend struct ::TableStruct_google_2fprotobuf_2fduration_2eproto;
|
||||
};
|
||||
// ===================================================================
|
||||
|
||||
|
||||
// ===================================================================
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
|
||||
#endif // __GNUC__
|
||||
// Duration
|
||||
|
||||
// int64 seconds = 1;
|
||||
inline void Duration::clear_seconds() {
|
||||
_impl_.seconds_ = int64_t{0};
|
||||
}
|
||||
inline int64_t Duration::_internal_seconds() const {
|
||||
return _impl_.seconds_;
|
||||
}
|
||||
inline int64_t Duration::seconds() const {
|
||||
// @@protoc_insertion_point(field_get:google.protobuf.Duration.seconds)
|
||||
return _internal_seconds();
|
||||
}
|
||||
inline void Duration::_internal_set_seconds(int64_t value) {
|
||||
|
||||
_impl_.seconds_ = value;
|
||||
}
|
||||
inline void Duration::set_seconds(int64_t value) {
|
||||
_internal_set_seconds(value);
|
||||
// @@protoc_insertion_point(field_set:google.protobuf.Duration.seconds)
|
||||
}
|
||||
|
||||
// int32 nanos = 2;
|
||||
inline void Duration::clear_nanos() {
|
||||
_impl_.nanos_ = 0;
|
||||
}
|
||||
inline int32_t Duration::_internal_nanos() const {
|
||||
return _impl_.nanos_;
|
||||
}
|
||||
inline int32_t Duration::nanos() const {
|
||||
// @@protoc_insertion_point(field_get:google.protobuf.Duration.nanos)
|
||||
return _internal_nanos();
|
||||
}
|
||||
inline void Duration::_internal_set_nanos(int32_t value) {
|
||||
|
||||
_impl_.nanos_ = value;
|
||||
}
|
||||
inline void Duration::set_nanos(int32_t value) {
|
||||
_internal_set_nanos(value);
|
||||
// @@protoc_insertion_point(field_set:google.protobuf.Duration.nanos)
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif // __GNUC__
|
||||
|
||||
// @@protoc_insertion_point(namespace_scope)
|
||||
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
|
||||
// @@protoc_insertion_point(global_scope)
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
#endif // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fduration_2eproto
|
||||
@@ -1,227 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
//
|
||||
// Defines an implementation of Message which can emulate types which are not
|
||||
// known at compile-time.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_DYNAMIC_MESSAGE_H__
|
||||
#define GOOGLE_PROTOBUF_DYNAMIC_MESSAGE_H__
|
||||
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/mutex.h>
|
||||
#include <google/protobuf/message.h>
|
||||
#include <google/protobuf/reflection.h>
|
||||
#include <google/protobuf/repeated_field.h>
|
||||
|
||||
#ifdef SWIG
|
||||
#error "You cannot SWIG proto headers"
|
||||
#endif
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
// Defined in other files.
|
||||
class Descriptor; // descriptor.h
|
||||
class DescriptorPool; // descriptor.h
|
||||
|
||||
// Constructs implementations of Message which can emulate types which are not
|
||||
// known at compile-time.
|
||||
//
|
||||
// Sometimes you want to be able to manipulate protocol types that you don't
|
||||
// know about at compile time. It would be nice to be able to construct
|
||||
// a Message object which implements the message type given by any arbitrary
|
||||
// Descriptor. DynamicMessage provides this.
|
||||
//
|
||||
// As it turns out, a DynamicMessage needs to construct extra
|
||||
// information about its type in order to operate. Most of this information
|
||||
// can be shared between all DynamicMessages of the same type. But, caching
|
||||
// this information in some sort of global map would be a bad idea, since
|
||||
// the cached information for a particular descriptor could outlive the
|
||||
// descriptor itself. To avoid this problem, DynamicMessageFactory
|
||||
// encapsulates this "cache". All DynamicMessages of the same type created
|
||||
// from the same factory will share the same support data. Any Descriptors
|
||||
// used with a particular factory must outlive the factory.
|
||||
class PROTOBUF_EXPORT DynamicMessageFactory : public MessageFactory {
|
||||
public:
|
||||
// Construct a DynamicMessageFactory that will search for extensions in
|
||||
// the DescriptorPool in which the extendee is defined.
|
||||
DynamicMessageFactory();
|
||||
|
||||
// Construct a DynamicMessageFactory that will search for extensions in
|
||||
// the given DescriptorPool.
|
||||
//
|
||||
// DEPRECATED: Use CodedInputStream::SetExtensionRegistry() to tell the
|
||||
// parser to look for extensions in an alternate pool. However, note that
|
||||
// this is almost never what you want to do. Almost all users should use
|
||||
// the zero-arg constructor.
|
||||
DynamicMessageFactory(const DescriptorPool* pool);
|
||||
|
||||
~DynamicMessageFactory() override;
|
||||
|
||||
// Call this to tell the DynamicMessageFactory that if it is given a
|
||||
// Descriptor d for which:
|
||||
// d->file()->pool() == DescriptorPool::generated_pool(),
|
||||
// then it should delegate to MessageFactory::generated_factory() instead
|
||||
// of constructing a dynamic implementation of the message. In theory there
|
||||
// is no down side to doing this, so it may become the default in the future.
|
||||
void SetDelegateToGeneratedFactory(bool enable) {
|
||||
delegate_to_generated_factory_ = enable;
|
||||
}
|
||||
|
||||
// implements MessageFactory ---------------------------------------
|
||||
|
||||
// Given a Descriptor, constructs the default (prototype) Message of that
|
||||
// type. You can then call that message's New() method to construct a
|
||||
// mutable message of that type.
|
||||
//
|
||||
// Calling this method twice with the same Descriptor returns the same
|
||||
// object. The returned object remains property of the factory and will
|
||||
// be destroyed when the factory is destroyed. Also, any objects created
|
||||
// by calling the prototype's New() method share some data with the
|
||||
// prototype, so these must be destroyed before the DynamicMessageFactory
|
||||
// is destroyed.
|
||||
//
|
||||
// The given descriptor must outlive the returned message, and hence must
|
||||
// outlive the DynamicMessageFactory.
|
||||
//
|
||||
// The method is thread-safe.
|
||||
const Message* GetPrototype(const Descriptor* type) override;
|
||||
|
||||
private:
|
||||
const DescriptorPool* pool_;
|
||||
bool delegate_to_generated_factory_;
|
||||
|
||||
struct TypeInfo;
|
||||
std::unordered_map<const Descriptor*, const TypeInfo*> prototypes_;
|
||||
mutable internal::WrappedMutex prototypes_mutex_;
|
||||
|
||||
friend class DynamicMessage;
|
||||
const Message* GetPrototypeNoLock(const Descriptor* type);
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMessageFactory);
|
||||
};
|
||||
|
||||
// Helper for computing a sorted list of map entries via reflection.
|
||||
class PROTOBUF_EXPORT DynamicMapSorter {
|
||||
public:
|
||||
static std::vector<const Message*> Sort(const Message& message, int map_size,
|
||||
const Reflection* reflection,
|
||||
const FieldDescriptor* field) {
|
||||
std::vector<const Message*> result;
|
||||
result.reserve(map_size);
|
||||
RepeatedFieldRef<Message> map_field =
|
||||
reflection->GetRepeatedFieldRef<Message>(message, field);
|
||||
for (auto it = map_field.begin(); it != map_field.end(); ++it) {
|
||||
result.push_back(&*it);
|
||||
}
|
||||
MapEntryMessageComparator comparator(field->message_type());
|
||||
std::stable_sort(result.begin(), result.end(), comparator);
|
||||
// Complain if the keys aren't in ascending order.
|
||||
#ifndef NDEBUG
|
||||
for (size_t j = 1; j < static_cast<size_t>(map_size); j++) {
|
||||
if (!comparator(result[j - 1], result[j])) {
|
||||
GOOGLE_LOG(ERROR) << (comparator(result[j], result[j - 1])
|
||||
? "internal error in map key sorting"
|
||||
: "map keys are not unique");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
class PROTOBUF_EXPORT MapEntryMessageComparator {
|
||||
public:
|
||||
explicit MapEntryMessageComparator(const Descriptor* descriptor)
|
||||
: field_(descriptor->field(0)) {}
|
||||
|
||||
bool operator()(const Message* a, const Message* b) {
|
||||
const Reflection* reflection = a->GetReflection();
|
||||
switch (field_->cpp_type()) {
|
||||
case FieldDescriptor::CPPTYPE_BOOL: {
|
||||
bool first = reflection->GetBool(*a, field_);
|
||||
bool second = reflection->GetBool(*b, field_);
|
||||
return first < second;
|
||||
}
|
||||
case FieldDescriptor::CPPTYPE_INT32: {
|
||||
int32_t first = reflection->GetInt32(*a, field_);
|
||||
int32_t second = reflection->GetInt32(*b, field_);
|
||||
return first < second;
|
||||
}
|
||||
case FieldDescriptor::CPPTYPE_INT64: {
|
||||
int64_t first = reflection->GetInt64(*a, field_);
|
||||
int64_t second = reflection->GetInt64(*b, field_);
|
||||
return first < second;
|
||||
}
|
||||
case FieldDescriptor::CPPTYPE_UINT32: {
|
||||
uint32_t first = reflection->GetUInt32(*a, field_);
|
||||
uint32_t second = reflection->GetUInt32(*b, field_);
|
||||
return first < second;
|
||||
}
|
||||
case FieldDescriptor::CPPTYPE_UINT64: {
|
||||
uint64_t first = reflection->GetUInt64(*a, field_);
|
||||
uint64_t second = reflection->GetUInt64(*b, field_);
|
||||
return first < second;
|
||||
}
|
||||
case FieldDescriptor::CPPTYPE_STRING: {
|
||||
std::string first = reflection->GetString(*a, field_);
|
||||
std::string second = reflection->GetString(*b, field_);
|
||||
return first < second;
|
||||
}
|
||||
default:
|
||||
GOOGLE_LOG(DFATAL) << "Invalid key for map field.";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
const FieldDescriptor* field_;
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_DYNAMIC_MESSAGE_H__
|
||||
@@ -1,198 +0,0 @@
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: google/protobuf/empty.proto
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fempty_2eproto
|
||||
#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fempty_2eproto
|
||||
|
||||
#include <limits>
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/port_def.inc>
|
||||
#if PROTOBUF_VERSION < 3021000
|
||||
#error This file was generated by a newer version of protoc which is
|
||||
#error incompatible with your Protocol Buffer headers. Please update
|
||||
#error your headers.
|
||||
#endif
|
||||
#if 3021012 < PROTOBUF_MIN_PROTOC_VERSION
|
||||
#error This file was generated by an older version of protoc which is
|
||||
#error incompatible with your Protocol Buffer headers. Please
|
||||
#error regenerate this file with a newer version of protoc.
|
||||
#endif
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/arena.h>
|
||||
#include <google/protobuf/arenastring.h>
|
||||
#include <google/protobuf/generated_message_bases.h>
|
||||
#include <google/protobuf/generated_message_util.h>
|
||||
#include <google/protobuf/metadata_lite.h>
|
||||
#include <google/protobuf/generated_message_reflection.h>
|
||||
#include <google/protobuf/message.h>
|
||||
#include <google/protobuf/repeated_field.h> // IWYU pragma: export
|
||||
#include <google/protobuf/extension_set.h> // IWYU pragma: export
|
||||
#include <google/protobuf/unknown_field_set.h>
|
||||
// @@protoc_insertion_point(includes)
|
||||
#include <google/protobuf/port_def.inc>
|
||||
#define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fempty_2eproto PROTOBUF_EXPORT
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
namespace internal {
|
||||
class AnyMetadata;
|
||||
} // namespace internal
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
|
||||
// Internal implementation detail -- do not use these members.
|
||||
struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2fempty_2eproto {
|
||||
static const uint32_t offsets[];
|
||||
};
|
||||
PROTOBUF_EXPORT extern const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fempty_2eproto;
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
class Empty;
|
||||
struct EmptyDefaultTypeInternal;
|
||||
PROTOBUF_EXPORT extern EmptyDefaultTypeInternal _Empty_default_instance_;
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Empty* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Empty>(Arena*);
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
|
||||
// ===================================================================
|
||||
|
||||
class PROTOBUF_EXPORT Empty final :
|
||||
public ::PROTOBUF_NAMESPACE_ID::internal::ZeroFieldsBase /* @@protoc_insertion_point(class_definition:google.protobuf.Empty) */ {
|
||||
public:
|
||||
inline Empty() : Empty(nullptr) {}
|
||||
explicit PROTOBUF_CONSTEXPR Empty(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
|
||||
|
||||
Empty(const Empty& from);
|
||||
Empty(Empty&& from) noexcept
|
||||
: Empty() {
|
||||
*this = ::std::move(from);
|
||||
}
|
||||
|
||||
inline Empty& operator=(const Empty& from) {
|
||||
CopyFrom(from);
|
||||
return *this;
|
||||
}
|
||||
inline Empty& operator=(Empty&& from) noexcept {
|
||||
if (this == &from) return *this;
|
||||
if (GetOwningArena() == from.GetOwningArena()
|
||||
#ifdef PROTOBUF_FORCE_COPY_IN_MOVE
|
||||
&& GetOwningArena() != nullptr
|
||||
#endif // !PROTOBUF_FORCE_COPY_IN_MOVE
|
||||
) {
|
||||
InternalSwap(&from);
|
||||
} else {
|
||||
CopyFrom(from);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() {
|
||||
return GetDescriptor();
|
||||
}
|
||||
static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
|
||||
return default_instance().GetMetadata().descriptor;
|
||||
}
|
||||
static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
|
||||
return default_instance().GetMetadata().reflection;
|
||||
}
|
||||
static const Empty& default_instance() {
|
||||
return *internal_default_instance();
|
||||
}
|
||||
static inline const Empty* internal_default_instance() {
|
||||
return reinterpret_cast<const Empty*>(
|
||||
&_Empty_default_instance_);
|
||||
}
|
||||
static constexpr int kIndexInFileMessages =
|
||||
0;
|
||||
|
||||
friend void swap(Empty& a, Empty& b) {
|
||||
a.Swap(&b);
|
||||
}
|
||||
inline void Swap(Empty* other) {
|
||||
if (other == this) return;
|
||||
#ifdef PROTOBUF_FORCE_COPY_IN_SWAP
|
||||
if (GetOwningArena() != nullptr &&
|
||||
GetOwningArena() == other->GetOwningArena()) {
|
||||
#else // PROTOBUF_FORCE_COPY_IN_SWAP
|
||||
if (GetOwningArena() == other->GetOwningArena()) {
|
||||
#endif // !PROTOBUF_FORCE_COPY_IN_SWAP
|
||||
InternalSwap(other);
|
||||
} else {
|
||||
::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
|
||||
}
|
||||
}
|
||||
void UnsafeArenaSwap(Empty* other) {
|
||||
if (other == this) return;
|
||||
GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
|
||||
InternalSwap(other);
|
||||
}
|
||||
|
||||
// implements Message ----------------------------------------------
|
||||
|
||||
Empty* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final {
|
||||
return CreateMaybeMessage<Empty>(arena);
|
||||
}
|
||||
using ::PROTOBUF_NAMESPACE_ID::internal::ZeroFieldsBase::CopyFrom;
|
||||
inline void CopyFrom(const Empty& from) {
|
||||
::PROTOBUF_NAMESPACE_ID::internal::ZeroFieldsBase::CopyImpl(*this, from);
|
||||
}
|
||||
using ::PROTOBUF_NAMESPACE_ID::internal::ZeroFieldsBase::MergeFrom;
|
||||
void MergeFrom(const Empty& from) {
|
||||
::PROTOBUF_NAMESPACE_ID::internal::ZeroFieldsBase::MergeImpl(*this, from);
|
||||
}
|
||||
public:
|
||||
|
||||
private:
|
||||
friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
|
||||
static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
|
||||
return "google.protobuf.Empty";
|
||||
}
|
||||
protected:
|
||||
explicit Empty(::PROTOBUF_NAMESPACE_ID::Arena* arena,
|
||||
bool is_message_owned = false);
|
||||
public:
|
||||
|
||||
static const ClassData _class_data_;
|
||||
const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
|
||||
|
||||
::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
|
||||
|
||||
// nested types ----------------------------------------------------
|
||||
|
||||
// accessors -------------------------------------------------------
|
||||
|
||||
// @@protoc_insertion_point(class_scope:google.protobuf.Empty)
|
||||
private:
|
||||
class _Internal;
|
||||
|
||||
template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper;
|
||||
typedef void InternalArenaConstructable_;
|
||||
typedef void DestructorSkippable_;
|
||||
struct Impl_ {
|
||||
};
|
||||
friend struct ::TableStruct_google_2fprotobuf_2fempty_2eproto;
|
||||
};
|
||||
// ===================================================================
|
||||
|
||||
|
||||
// ===================================================================
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
|
||||
#endif // __GNUC__
|
||||
// Empty
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif // __GNUC__
|
||||
|
||||
// @@protoc_insertion_point(namespace_scope)
|
||||
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
|
||||
// @@protoc_insertion_point(global_scope)
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
#endif // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fempty_2eproto
|
||||
@@ -1,198 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_ENDIAN_H__
|
||||
#define GOOGLE_PROTOBUF_ENDIAN_H__
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
inline uint64_t BSwap64(uint64_t host_int) {
|
||||
#if defined(PROTOBUF_BUILTIN_BSWAP64)
|
||||
return PROTOBUF_BUILTIN_BSWAP64(host_int);
|
||||
#elif defined(_MSC_VER)
|
||||
return _byteswap_uint64(host_int);
|
||||
#else
|
||||
return (((host_int & uint64_t{0xFF}) << 56) |
|
||||
((host_int & uint64_t{0xFF00}) << 40) |
|
||||
((host_int & uint64_t{0xFF0000}) << 24) |
|
||||
((host_int & uint64_t{0xFF000000}) << 8) |
|
||||
((host_int & uint64_t{0xFF00000000}) >> 8) |
|
||||
((host_int & uint64_t{0xFF0000000000}) >> 24) |
|
||||
((host_int & uint64_t{0xFF000000000000}) >> 40) |
|
||||
((host_int & uint64_t{0xFF00000000000000}) >> 56));
|
||||
#endif
|
||||
}
|
||||
|
||||
inline uint32_t BSwap32(uint32_t host_int) {
|
||||
#if defined(PROTOBUF_BUILTIN_BSWAP32)
|
||||
return PROTOBUF_BUILTIN_BSWAP32(host_int);
|
||||
#elif defined(_MSC_VER)
|
||||
return _byteswap_ulong(host_int);
|
||||
#else
|
||||
return (((host_int & uint32_t{0xFF}) << 24) |
|
||||
((host_int & uint32_t{0xFF00}) << 8) |
|
||||
((host_int & uint32_t{0xFF0000}) >> 8) |
|
||||
((host_int & uint32_t{0xFF000000}) >> 24));
|
||||
#endif
|
||||
}
|
||||
|
||||
inline uint16_t BSwap16(uint16_t host_int) {
|
||||
#if defined(PROTOBUF_BUILTIN_BSWAP16)
|
||||
return PROTOBUF_BUILTIN_BSWAP16(host_int);
|
||||
#elif defined(_MSC_VER)
|
||||
return _byteswap_ushort(host_int);
|
||||
#else
|
||||
return (((host_int & uint16_t{0xFF}) << 8) |
|
||||
((host_int & uint16_t{0xFF00}) >> 8));
|
||||
#endif
|
||||
}
|
||||
|
||||
namespace little_endian {
|
||||
|
||||
inline uint16_t FromHost(uint16_t value) {
|
||||
#if defined(PROTOBUF_BIG_ENDIAN)
|
||||
return BSwap16(value);
|
||||
#else
|
||||
return value;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline uint32_t FromHost(uint32_t value) {
|
||||
#if defined(PROTOBUF_BIG_ENDIAN)
|
||||
return BSwap32(value);
|
||||
#else
|
||||
return value;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline uint64_t FromHost(uint64_t value) {
|
||||
#if defined(PROTOBUF_BIG_ENDIAN)
|
||||
return BSwap64(value);
|
||||
#else
|
||||
return value;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline uint16_t ToHost(uint16_t value) {
|
||||
#if defined(PROTOBUF_BIG_ENDIAN)
|
||||
return BSwap16(value);
|
||||
#else
|
||||
return value;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline uint32_t ToHost(uint32_t value) {
|
||||
#if defined(PROTOBUF_BIG_ENDIAN)
|
||||
return BSwap32(value);
|
||||
#else
|
||||
return value;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline uint64_t ToHost(uint64_t value) {
|
||||
#if defined(PROTOBUF_BIG_ENDIAN)
|
||||
return BSwap64(value);
|
||||
#else
|
||||
return value;
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace little_endian
|
||||
|
||||
namespace big_endian {
|
||||
|
||||
inline uint16_t FromHost(uint16_t value) {
|
||||
#if defined(PROTOBUF_BIG_ENDIAN)
|
||||
return value;
|
||||
#else
|
||||
return BSwap16(value);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline uint32_t FromHost(uint32_t value) {
|
||||
#if defined(PROTOBUF_BIG_ENDIAN)
|
||||
return value;
|
||||
#else
|
||||
return BSwap32(value);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline uint64_t FromHost(uint64_t value) {
|
||||
#if defined(PROTOBUF_BIG_ENDIAN)
|
||||
return value;
|
||||
#else
|
||||
return BSwap64(value);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline uint16_t ToHost(uint16_t value) {
|
||||
#if defined(PROTOBUF_BIG_ENDIAN)
|
||||
return value;
|
||||
#else
|
||||
return BSwap16(value);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline uint32_t ToHost(uint32_t value) {
|
||||
#if defined(PROTOBUF_BIG_ENDIAN)
|
||||
return value;
|
||||
#else
|
||||
return BSwap32(value);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline uint64_t ToHost(uint64_t value) {
|
||||
#if defined(PROTOBUF_BIG_ENDIAN)
|
||||
return value;
|
||||
#else
|
||||
return BSwap64(value);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace big_endian
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_ENDIAN_H__
|
||||
@@ -1,97 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_EXPLICITLY_CONSTRUCTED_H__
|
||||
#define GOOGLE_PROTOBUF_EXPLICITLY_CONSTRUCTED_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include <google/protobuf/stubs/logging.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
// clang-format off
|
||||
#include <google/protobuf/port_def.inc>
|
||||
// clang-format on
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
// Wraps a variable whose constructor and destructor are explicitly
|
||||
// called. It is particularly useful for a global variable, without its
|
||||
// constructor and destructor run on start and end of the program lifetime.
|
||||
// This circumvents the initial construction order fiasco, while keeping
|
||||
// the address of the empty string a compile time constant.
|
||||
//
|
||||
// Pay special attention to the initialization state of the object.
|
||||
// 1. The object is "uninitialized" to begin with.
|
||||
// 2. Call Construct() or DefaultConstruct() only if the object is
|
||||
// uninitialized. After the call, the object becomes "initialized".
|
||||
// 3. Call get() and get_mutable() only if the object is initialized.
|
||||
// 4. Call Destruct() only if the object is initialized.
|
||||
// After the call, the object becomes uninitialized.
|
||||
template <typename T, size_t min_align = 1>
|
||||
class ExplicitlyConstructed {
|
||||
public:
|
||||
void DefaultConstruct() { new (&union_) T(); }
|
||||
|
||||
template <typename... Args>
|
||||
void Construct(Args&&... args) {
|
||||
new (&union_) T(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
void Destruct() { get_mutable()->~T(); }
|
||||
|
||||
constexpr const T& get() const { return reinterpret_cast<const T&>(union_); }
|
||||
T* get_mutable() { return reinterpret_cast<T*>(&union_); }
|
||||
|
||||
private:
|
||||
union AlignedUnion {
|
||||
alignas(min_align > alignof(T) ? min_align
|
||||
: alignof(T)) char space[sizeof(T)];
|
||||
int64_t align_to_int64;
|
||||
void* align_to_ptr;
|
||||
} union_;
|
||||
};
|
||||
|
||||
// ArenaStringPtr compatible explicitly constructed string type.
|
||||
// This empty string type is aligned with a minimum alignment of 8 bytes
|
||||
// which is the minimum requirement of ArenaStringPtr
|
||||
using ExplicitlyConstructedArenaString = ExplicitlyConstructed<std::string, 8>;
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_EXPLICITLY_CONSTRUCTED_H__
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,285 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_EXTENSION_SET_INL_H__
|
||||
#define GOOGLE_PROTOBUF_EXTENSION_SET_INL_H__
|
||||
|
||||
#include <google/protobuf/extension_set.h>
|
||||
#include <google/protobuf/metadata_lite.h>
|
||||
#include <google/protobuf/parse_context.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
template <typename T>
|
||||
const char* ExtensionSet::ParseFieldWithExtensionInfo(
|
||||
int number, bool was_packed_on_wire, const ExtensionInfo& extension,
|
||||
InternalMetadata* metadata, const char* ptr, internal::ParseContext* ctx) {
|
||||
if (was_packed_on_wire) {
|
||||
switch (extension.type) {
|
||||
#define HANDLE_TYPE(UPPERCASE, CPP_CAMELCASE) \
|
||||
case WireFormatLite::TYPE_##UPPERCASE: \
|
||||
return internal::Packed##CPP_CAMELCASE##Parser( \
|
||||
MutableRawRepeatedField(number, extension.type, extension.is_packed, \
|
||||
extension.descriptor), \
|
||||
ptr, ctx);
|
||||
HANDLE_TYPE(INT32, Int32);
|
||||
HANDLE_TYPE(INT64, Int64);
|
||||
HANDLE_TYPE(UINT32, UInt32);
|
||||
HANDLE_TYPE(UINT64, UInt64);
|
||||
HANDLE_TYPE(SINT32, SInt32);
|
||||
HANDLE_TYPE(SINT64, SInt64);
|
||||
HANDLE_TYPE(FIXED32, Fixed32);
|
||||
HANDLE_TYPE(FIXED64, Fixed64);
|
||||
HANDLE_TYPE(SFIXED32, SFixed32);
|
||||
HANDLE_TYPE(SFIXED64, SFixed64);
|
||||
HANDLE_TYPE(FLOAT, Float);
|
||||
HANDLE_TYPE(DOUBLE, Double);
|
||||
HANDLE_TYPE(BOOL, Bool);
|
||||
#undef HANDLE_TYPE
|
||||
|
||||
case WireFormatLite::TYPE_ENUM:
|
||||
return internal::PackedEnumParserArg<T>(
|
||||
MutableRawRepeatedField(number, extension.type, extension.is_packed,
|
||||
extension.descriptor),
|
||||
ptr, ctx, extension.enum_validity_check.func,
|
||||
extension.enum_validity_check.arg, metadata, number);
|
||||
case WireFormatLite::TYPE_STRING:
|
||||
case WireFormatLite::TYPE_BYTES:
|
||||
case WireFormatLite::TYPE_GROUP:
|
||||
case WireFormatLite::TYPE_MESSAGE:
|
||||
GOOGLE_LOG(FATAL) << "Non-primitive types can't be packed.";
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (extension.type) {
|
||||
#define HANDLE_VARINT_TYPE(UPPERCASE, CPP_CAMELCASE) \
|
||||
case WireFormatLite::TYPE_##UPPERCASE: { \
|
||||
uint64_t value; \
|
||||
ptr = VarintParse(ptr, &value); \
|
||||
GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); \
|
||||
if (extension.is_repeated) { \
|
||||
Add##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, \
|
||||
extension.is_packed, value, extension.descriptor); \
|
||||
} else { \
|
||||
Set##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, value, \
|
||||
extension.descriptor); \
|
||||
} \
|
||||
} break
|
||||
|
||||
HANDLE_VARINT_TYPE(INT32, Int32);
|
||||
HANDLE_VARINT_TYPE(INT64, Int64);
|
||||
HANDLE_VARINT_TYPE(UINT32, UInt32);
|
||||
HANDLE_VARINT_TYPE(UINT64, UInt64);
|
||||
HANDLE_VARINT_TYPE(BOOL, Bool);
|
||||
#undef HANDLE_VARINT_TYPE
|
||||
#define HANDLE_SVARINT_TYPE(UPPERCASE, CPP_CAMELCASE, SIZE) \
|
||||
case WireFormatLite::TYPE_##UPPERCASE: { \
|
||||
uint64_t val; \
|
||||
ptr = VarintParse(ptr, &val); \
|
||||
GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); \
|
||||
auto value = WireFormatLite::ZigZagDecode##SIZE(val); \
|
||||
if (extension.is_repeated) { \
|
||||
Add##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, \
|
||||
extension.is_packed, value, extension.descriptor); \
|
||||
} else { \
|
||||
Set##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, value, \
|
||||
extension.descriptor); \
|
||||
} \
|
||||
} break
|
||||
|
||||
HANDLE_SVARINT_TYPE(SINT32, Int32, 32);
|
||||
HANDLE_SVARINT_TYPE(SINT64, Int64, 64);
|
||||
#undef HANDLE_SVARINT_TYPE
|
||||
#define HANDLE_FIXED_TYPE(UPPERCASE, CPP_CAMELCASE, CPPTYPE) \
|
||||
case WireFormatLite::TYPE_##UPPERCASE: { \
|
||||
auto value = UnalignedLoad<CPPTYPE>(ptr); \
|
||||
ptr += sizeof(CPPTYPE); \
|
||||
if (extension.is_repeated) { \
|
||||
Add##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, \
|
||||
extension.is_packed, value, extension.descriptor); \
|
||||
} else { \
|
||||
Set##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, value, \
|
||||
extension.descriptor); \
|
||||
} \
|
||||
} break
|
||||
|
||||
HANDLE_FIXED_TYPE(FIXED32, UInt32, uint32_t);
|
||||
HANDLE_FIXED_TYPE(FIXED64, UInt64, uint64_t);
|
||||
HANDLE_FIXED_TYPE(SFIXED32, Int32, int32_t);
|
||||
HANDLE_FIXED_TYPE(SFIXED64, Int64, int64_t);
|
||||
HANDLE_FIXED_TYPE(FLOAT, Float, float);
|
||||
HANDLE_FIXED_TYPE(DOUBLE, Double, double);
|
||||
#undef HANDLE_FIXED_TYPE
|
||||
|
||||
case WireFormatLite::TYPE_ENUM: {
|
||||
uint64_t val;
|
||||
ptr = VarintParse(ptr, &val);
|
||||
GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
|
||||
int value = val;
|
||||
|
||||
if (!extension.enum_validity_check.func(
|
||||
extension.enum_validity_check.arg, value)) {
|
||||
WriteVarint(number, val, metadata->mutable_unknown_fields<T>());
|
||||
} else if (extension.is_repeated) {
|
||||
AddEnum(number, WireFormatLite::TYPE_ENUM, extension.is_packed, value,
|
||||
extension.descriptor);
|
||||
} else {
|
||||
SetEnum(number, WireFormatLite::TYPE_ENUM, value,
|
||||
extension.descriptor);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case WireFormatLite::TYPE_BYTES:
|
||||
case WireFormatLite::TYPE_STRING: {
|
||||
std::string* value =
|
||||
extension.is_repeated
|
||||
? AddString(number, WireFormatLite::TYPE_STRING,
|
||||
extension.descriptor)
|
||||
: MutableString(number, WireFormatLite::TYPE_STRING,
|
||||
extension.descriptor);
|
||||
int size = ReadSize(&ptr);
|
||||
GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
|
||||
return ctx->ReadString(ptr, size, value);
|
||||
}
|
||||
|
||||
case WireFormatLite::TYPE_GROUP: {
|
||||
MessageLite* value =
|
||||
extension.is_repeated
|
||||
? AddMessage(number, WireFormatLite::TYPE_GROUP,
|
||||
*extension.message_info.prototype,
|
||||
extension.descriptor)
|
||||
: MutableMessage(number, WireFormatLite::TYPE_GROUP,
|
||||
*extension.message_info.prototype,
|
||||
extension.descriptor);
|
||||
uint32_t tag = (number << 3) + WireFormatLite::WIRETYPE_START_GROUP;
|
||||
return ctx->ParseGroup(value, ptr, tag);
|
||||
}
|
||||
|
||||
case WireFormatLite::TYPE_MESSAGE: {
|
||||
MessageLite* value =
|
||||
extension.is_repeated
|
||||
? AddMessage(number, WireFormatLite::TYPE_MESSAGE,
|
||||
*extension.message_info.prototype,
|
||||
extension.descriptor)
|
||||
: MutableMessage(number, WireFormatLite::TYPE_MESSAGE,
|
||||
*extension.message_info.prototype,
|
||||
extension.descriptor);
|
||||
return ctx->ParseMessage(value, ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
template <typename Msg, typename T>
|
||||
const char* ExtensionSet::ParseMessageSetItemTmpl(
|
||||
const char* ptr, const Msg* extendee, internal::InternalMetadata* metadata,
|
||||
internal::ParseContext* ctx) {
|
||||
std::string payload;
|
||||
uint32_t type_id = 0;
|
||||
enum class State { kNoTag, kHasType, kHasPayload, kDone };
|
||||
State state = State::kNoTag;
|
||||
|
||||
while (!ctx->Done(&ptr)) {
|
||||
uint32_t tag = static_cast<uint8_t>(*ptr++);
|
||||
if (tag == WireFormatLite::kMessageSetTypeIdTag) {
|
||||
uint64_t tmp;
|
||||
ptr = ParseBigVarint(ptr, &tmp);
|
||||
GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
|
||||
if (state == State::kNoTag) {
|
||||
type_id = tmp;
|
||||
state = State::kHasType;
|
||||
} else if (state == State::kHasPayload) {
|
||||
type_id = tmp;
|
||||
ExtensionInfo extension;
|
||||
bool was_packed_on_wire;
|
||||
if (!FindExtension(2, type_id, extendee, ctx, &extension,
|
||||
&was_packed_on_wire)) {
|
||||
WriteLengthDelimited(type_id, payload,
|
||||
metadata->mutable_unknown_fields<T>());
|
||||
} else {
|
||||
MessageLite* value =
|
||||
extension.is_repeated
|
||||
? AddMessage(type_id, WireFormatLite::TYPE_MESSAGE,
|
||||
*extension.message_info.prototype,
|
||||
extension.descriptor)
|
||||
: MutableMessage(type_id, WireFormatLite::TYPE_MESSAGE,
|
||||
*extension.message_info.prototype,
|
||||
extension.descriptor);
|
||||
|
||||
const char* p;
|
||||
// We can't use regular parse from string as we have to track
|
||||
// proper recursion depth and descriptor pools.
|
||||
ParseContext tmp_ctx(ctx->depth(), false, &p, payload);
|
||||
tmp_ctx.data().pool = ctx->data().pool;
|
||||
tmp_ctx.data().factory = ctx->data().factory;
|
||||
GOOGLE_PROTOBUF_PARSER_ASSERT(value->_InternalParse(p, &tmp_ctx) &&
|
||||
tmp_ctx.EndedAtLimit());
|
||||
}
|
||||
state = State::kDone;
|
||||
}
|
||||
} else if (tag == WireFormatLite::kMessageSetMessageTag) {
|
||||
if (state == State::kHasType) {
|
||||
ptr = ParseFieldMaybeLazily(static_cast<uint64_t>(type_id) * 8 + 2, ptr,
|
||||
extendee, metadata, ctx);
|
||||
GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
|
||||
state = State::kDone;
|
||||
} else {
|
||||
std::string tmp;
|
||||
int32_t size = ReadSize(&ptr);
|
||||
GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
|
||||
ptr = ctx->ReadString(ptr, size, &tmp);
|
||||
GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
|
||||
if (state == State::kNoTag) {
|
||||
payload = std::move(tmp);
|
||||
state = State::kHasPayload;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ptr = ReadTag(ptr - 1, &tag);
|
||||
if (tag == 0 || (tag & 7) == 4) {
|
||||
ctx->SetLastTag(tag);
|
||||
return ptr;
|
||||
}
|
||||
ptr = ParseField(tag, ptr, extendee, metadata, ctx);
|
||||
GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
|
||||
}
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_EXTENSION_SET_INL_H__
|
||||
@@ -1,172 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_FIELD_ACCESS_LISTENER_H__
|
||||
#define GOOGLE_PROTOBUF_FIELD_ACCESS_LISTENER_H__
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/message_lite.h>
|
||||
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
// A default/no-op implementation of message hooks.
|
||||
//
|
||||
// See go/statically-dispatched-message-hooks for details.
|
||||
template <typename Proto>
|
||||
struct NoOpAccessListener {
|
||||
// Number of fields are provided at compile time for the trackers to be able
|
||||
// to have stack allocated bitmaps for the fields. This is useful for
|
||||
// performance critical trackers. This is also to avoid cyclic dependencies
|
||||
// if the number of fields is needed.
|
||||
static constexpr int kFields = Proto::_kInternalFieldNumber;
|
||||
// Default constructor is called during the static global initialization of
|
||||
// the program.
|
||||
// We provide a pointer to extract the name of the proto not to get cyclic
|
||||
// dependencies on GetDescriptor() and OnGetMetadata() calls. If you want
|
||||
// to differentiate the protos during the runtime before the start of the
|
||||
// program, use this functor to get its name. We either way need it for
|
||||
// LITE_RUNTIME protos as they don't have descriptors at all.
|
||||
explicit NoOpAccessListener(StringPiece (*name_extractor)()) {}
|
||||
// called repeatedly during serialization/deserialization/ByteSize of
|
||||
// Reflection as:
|
||||
// AccessListener<MessageT>::OnSerialize(this);
|
||||
static void OnSerialize(const MessageLite* msg) {}
|
||||
static void OnDeserialize(const MessageLite* msg) {}
|
||||
static void OnByteSize(const MessageLite* msg) {}
|
||||
static void OnMergeFrom(const MessageLite* to, const MessageLite* from) {}
|
||||
|
||||
// NOTE: This function can be called pre-main. Make sure it does not make
|
||||
// the state of the listener invalid.
|
||||
static void OnGetMetadata() {}
|
||||
|
||||
// called from accessors as:
|
||||
// AccessListener<MessageT>::On$operation(this, &field_storage_);
|
||||
// If you need to override this with type, in your hook implementation
|
||||
// introduce
|
||||
// template <int kFieldNum, typename T>
|
||||
// static void On$operation(const MessageLite* msg,
|
||||
// const T* field) {}
|
||||
// And overloads for std::nullptr_t for incomplete types such as Messages,
|
||||
// Maps. Extract them using reflection if you need. Consequently, second
|
||||
// argument can be null pointer.
|
||||
// For an example, see proto_hooks/testing/memory_test_field_listener.h
|
||||
// And argument template deduction will deduce the type itself without
|
||||
// changing the generated code.
|
||||
|
||||
// add_<field>(f)
|
||||
template <int kFieldNum>
|
||||
static void OnAdd(const MessageLite* msg, const void* field) {}
|
||||
|
||||
// add_<field>()
|
||||
template <int kFieldNum>
|
||||
static void OnAddMutable(const MessageLite* msg, const void* field) {}
|
||||
|
||||
// <field>() and <repeated_field>(i)
|
||||
template <int kFieldNum>
|
||||
static void OnGet(const MessageLite* msg, const void* field) {}
|
||||
|
||||
// clear_<field>()
|
||||
template <int kFieldNum>
|
||||
static void OnClear(const MessageLite* msg, const void* field) {}
|
||||
|
||||
// has_<field>()
|
||||
template <int kFieldNum>
|
||||
static void OnHas(const MessageLite* msg, const void* field) {}
|
||||
|
||||
// <repeated_field>()
|
||||
template <int kFieldNum>
|
||||
static void OnList(const MessageLite* msg, const void* field) {}
|
||||
|
||||
// mutable_<field>()
|
||||
template <int kFieldNum>
|
||||
static void OnMutable(const MessageLite* msg, const void* field) {}
|
||||
|
||||
// mutable_<repeated_field>()
|
||||
template <int kFieldNum>
|
||||
static void OnMutableList(const MessageLite* msg, const void* field) {}
|
||||
|
||||
// release_<field>()
|
||||
template <int kFieldNum>
|
||||
static void OnRelease(const MessageLite* msg, const void* field) {}
|
||||
|
||||
// set_<field>() and set_<repeated_field>(i)
|
||||
template <int kFieldNum>
|
||||
static void OnSet(const MessageLite* msg, const void* field) {}
|
||||
|
||||
// <repeated_field>_size()
|
||||
template <int kFieldNum>
|
||||
static void OnSize(const MessageLite* msg, const void* field) {}
|
||||
|
||||
static void OnHasExtension(const MessageLite* msg, int extension_tag,
|
||||
const void* field) {}
|
||||
// TODO(b/190614678): Support clear in the proto compiler.
|
||||
static void OnClearExtension(const MessageLite* msg, int extension_tag,
|
||||
const void* field) {}
|
||||
static void OnExtensionSize(const MessageLite* msg, int extension_tag,
|
||||
const void* field) {}
|
||||
static void OnGetExtension(const MessageLite* msg, int extension_tag,
|
||||
const void* field) {}
|
||||
static void OnMutableExtension(const MessageLite* msg, int extension_tag,
|
||||
const void* field) {}
|
||||
static void OnSetExtension(const MessageLite* msg, int extension_tag,
|
||||
const void* field) {}
|
||||
static void OnReleaseExtension(const MessageLite* msg, int extension_tag,
|
||||
const void* field) {}
|
||||
static void OnAddExtension(const MessageLite* msg, int extension_tag,
|
||||
const void* field) {}
|
||||
static void OnAddMutableExtension(const MessageLite* msg, int extension_tag,
|
||||
const void* field) {}
|
||||
static void OnListExtension(const MessageLite* msg, int extension_tag,
|
||||
const void* field) {}
|
||||
static void OnMutableListExtension(const MessageLite* msg, int extension_tag,
|
||||
const void* field) {}
|
||||
};
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#ifndef REPLACE_PROTO_LISTENER_IMPL
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
template <class T>
|
||||
using AccessListener = NoOpAccessListener<T>;
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
#else
|
||||
// You can put your implementations of hooks/listeners here.
|
||||
// All hooks are subject to approval by protobuf-team@.
|
||||
|
||||
#endif // !REPLACE_PROTO_LISTENER_IMPL
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_FIELD_ACCESS_LISTENER_H__
|
||||
@@ -1,317 +0,0 @@
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: google/protobuf/field_mask.proto
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2ffield_5fmask_2eproto
|
||||
#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2ffield_5fmask_2eproto
|
||||
|
||||
#include <limits>
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/port_def.inc>
|
||||
#if PROTOBUF_VERSION < 3021000
|
||||
#error This file was generated by a newer version of protoc which is
|
||||
#error incompatible with your Protocol Buffer headers. Please update
|
||||
#error your headers.
|
||||
#endif
|
||||
#if 3021012 < PROTOBUF_MIN_PROTOC_VERSION
|
||||
#error This file was generated by an older version of protoc which is
|
||||
#error incompatible with your Protocol Buffer headers. Please
|
||||
#error regenerate this file with a newer version of protoc.
|
||||
#endif
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/arena.h>
|
||||
#include <google/protobuf/arenastring.h>
|
||||
#include <google/protobuf/generated_message_util.h>
|
||||
#include <google/protobuf/metadata_lite.h>
|
||||
#include <google/protobuf/generated_message_reflection.h>
|
||||
#include <google/protobuf/message.h>
|
||||
#include <google/protobuf/repeated_field.h> // IWYU pragma: export
|
||||
#include <google/protobuf/extension_set.h> // IWYU pragma: export
|
||||
#include <google/protobuf/unknown_field_set.h>
|
||||
// @@protoc_insertion_point(includes)
|
||||
#include <google/protobuf/port_def.inc>
|
||||
#define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2ffield_5fmask_2eproto PROTOBUF_EXPORT
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
namespace internal {
|
||||
class AnyMetadata;
|
||||
} // namespace internal
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
|
||||
// Internal implementation detail -- do not use these members.
|
||||
struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2ffield_5fmask_2eproto {
|
||||
static const uint32_t offsets[];
|
||||
};
|
||||
PROTOBUF_EXPORT extern const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto;
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
class FieldMask;
|
||||
struct FieldMaskDefaultTypeInternal;
|
||||
PROTOBUF_EXPORT extern FieldMaskDefaultTypeInternal _FieldMask_default_instance_;
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::FieldMask* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::FieldMask>(Arena*);
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
|
||||
// ===================================================================
|
||||
|
||||
class PROTOBUF_EXPORT FieldMask final :
|
||||
public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.FieldMask) */ {
|
||||
public:
|
||||
inline FieldMask() : FieldMask(nullptr) {}
|
||||
~FieldMask() override;
|
||||
explicit PROTOBUF_CONSTEXPR FieldMask(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
|
||||
|
||||
FieldMask(const FieldMask& from);
|
||||
FieldMask(FieldMask&& from) noexcept
|
||||
: FieldMask() {
|
||||
*this = ::std::move(from);
|
||||
}
|
||||
|
||||
inline FieldMask& operator=(const FieldMask& from) {
|
||||
CopyFrom(from);
|
||||
return *this;
|
||||
}
|
||||
inline FieldMask& operator=(FieldMask&& from) noexcept {
|
||||
if (this == &from) return *this;
|
||||
if (GetOwningArena() == from.GetOwningArena()
|
||||
#ifdef PROTOBUF_FORCE_COPY_IN_MOVE
|
||||
&& GetOwningArena() != nullptr
|
||||
#endif // !PROTOBUF_FORCE_COPY_IN_MOVE
|
||||
) {
|
||||
InternalSwap(&from);
|
||||
} else {
|
||||
CopyFrom(from);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() {
|
||||
return GetDescriptor();
|
||||
}
|
||||
static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
|
||||
return default_instance().GetMetadata().descriptor;
|
||||
}
|
||||
static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
|
||||
return default_instance().GetMetadata().reflection;
|
||||
}
|
||||
static const FieldMask& default_instance() {
|
||||
return *internal_default_instance();
|
||||
}
|
||||
static inline const FieldMask* internal_default_instance() {
|
||||
return reinterpret_cast<const FieldMask*>(
|
||||
&_FieldMask_default_instance_);
|
||||
}
|
||||
static constexpr int kIndexInFileMessages =
|
||||
0;
|
||||
|
||||
friend void swap(FieldMask& a, FieldMask& b) {
|
||||
a.Swap(&b);
|
||||
}
|
||||
inline void Swap(FieldMask* other) {
|
||||
if (other == this) return;
|
||||
#ifdef PROTOBUF_FORCE_COPY_IN_SWAP
|
||||
if (GetOwningArena() != nullptr &&
|
||||
GetOwningArena() == other->GetOwningArena()) {
|
||||
#else // PROTOBUF_FORCE_COPY_IN_SWAP
|
||||
if (GetOwningArena() == other->GetOwningArena()) {
|
||||
#endif // !PROTOBUF_FORCE_COPY_IN_SWAP
|
||||
InternalSwap(other);
|
||||
} else {
|
||||
::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
|
||||
}
|
||||
}
|
||||
void UnsafeArenaSwap(FieldMask* other) {
|
||||
if (other == this) return;
|
||||
GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
|
||||
InternalSwap(other);
|
||||
}
|
||||
|
||||
// implements Message ----------------------------------------------
|
||||
|
||||
FieldMask* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final {
|
||||
return CreateMaybeMessage<FieldMask>(arena);
|
||||
}
|
||||
using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
|
||||
void CopyFrom(const FieldMask& from);
|
||||
using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
|
||||
void MergeFrom( const FieldMask& from) {
|
||||
FieldMask::MergeImpl(*this, from);
|
||||
}
|
||||
private:
|
||||
static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg);
|
||||
public:
|
||||
PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
|
||||
bool IsInitialized() const final;
|
||||
|
||||
size_t ByteSizeLong() const final;
|
||||
const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
|
||||
uint8_t* _InternalSerialize(
|
||||
uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
|
||||
int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
|
||||
|
||||
private:
|
||||
void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned);
|
||||
void SharedDtor();
|
||||
void SetCachedSize(int size) const final;
|
||||
void InternalSwap(FieldMask* other);
|
||||
|
||||
private:
|
||||
friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
|
||||
static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
|
||||
return "google.protobuf.FieldMask";
|
||||
}
|
||||
protected:
|
||||
explicit FieldMask(::PROTOBUF_NAMESPACE_ID::Arena* arena,
|
||||
bool is_message_owned = false);
|
||||
public:
|
||||
|
||||
static const ClassData _class_data_;
|
||||
const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
|
||||
|
||||
::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
|
||||
|
||||
// nested types ----------------------------------------------------
|
||||
|
||||
// accessors -------------------------------------------------------
|
||||
|
||||
enum : int {
|
||||
kPathsFieldNumber = 1,
|
||||
};
|
||||
// repeated string paths = 1;
|
||||
int paths_size() const;
|
||||
private:
|
||||
int _internal_paths_size() const;
|
||||
public:
|
||||
void clear_paths();
|
||||
const std::string& paths(int index) const;
|
||||
std::string* mutable_paths(int index);
|
||||
void set_paths(int index, const std::string& value);
|
||||
void set_paths(int index, std::string&& value);
|
||||
void set_paths(int index, const char* value);
|
||||
void set_paths(int index, const char* value, size_t size);
|
||||
std::string* add_paths();
|
||||
void add_paths(const std::string& value);
|
||||
void add_paths(std::string&& value);
|
||||
void add_paths(const char* value);
|
||||
void add_paths(const char* value, size_t size);
|
||||
const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string>& paths() const;
|
||||
::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string>* mutable_paths();
|
||||
private:
|
||||
const std::string& _internal_paths(int index) const;
|
||||
std::string* _internal_add_paths();
|
||||
public:
|
||||
|
||||
// @@protoc_insertion_point(class_scope:google.protobuf.FieldMask)
|
||||
private:
|
||||
class _Internal;
|
||||
|
||||
template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper;
|
||||
typedef void InternalArenaConstructable_;
|
||||
typedef void DestructorSkippable_;
|
||||
struct Impl_ {
|
||||
::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string> paths_;
|
||||
mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
|
||||
};
|
||||
union { Impl_ _impl_; };
|
||||
friend struct ::TableStruct_google_2fprotobuf_2ffield_5fmask_2eproto;
|
||||
};
|
||||
// ===================================================================
|
||||
|
||||
|
||||
// ===================================================================
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
|
||||
#endif // __GNUC__
|
||||
// FieldMask
|
||||
|
||||
// repeated string paths = 1;
|
||||
inline int FieldMask::_internal_paths_size() const {
|
||||
return _impl_.paths_.size();
|
||||
}
|
||||
inline int FieldMask::paths_size() const {
|
||||
return _internal_paths_size();
|
||||
}
|
||||
inline void FieldMask::clear_paths() {
|
||||
_impl_.paths_.Clear();
|
||||
}
|
||||
inline std::string* FieldMask::add_paths() {
|
||||
std::string* _s = _internal_add_paths();
|
||||
// @@protoc_insertion_point(field_add_mutable:google.protobuf.FieldMask.paths)
|
||||
return _s;
|
||||
}
|
||||
inline const std::string& FieldMask::_internal_paths(int index) const {
|
||||
return _impl_.paths_.Get(index);
|
||||
}
|
||||
inline const std::string& FieldMask::paths(int index) const {
|
||||
// @@protoc_insertion_point(field_get:google.protobuf.FieldMask.paths)
|
||||
return _internal_paths(index);
|
||||
}
|
||||
inline std::string* FieldMask::mutable_paths(int index) {
|
||||
// @@protoc_insertion_point(field_mutable:google.protobuf.FieldMask.paths)
|
||||
return _impl_.paths_.Mutable(index);
|
||||
}
|
||||
inline void FieldMask::set_paths(int index, const std::string& value) {
|
||||
_impl_.paths_.Mutable(index)->assign(value);
|
||||
// @@protoc_insertion_point(field_set:google.protobuf.FieldMask.paths)
|
||||
}
|
||||
inline void FieldMask::set_paths(int index, std::string&& value) {
|
||||
_impl_.paths_.Mutable(index)->assign(std::move(value));
|
||||
// @@protoc_insertion_point(field_set:google.protobuf.FieldMask.paths)
|
||||
}
|
||||
inline void FieldMask::set_paths(int index, const char* value) {
|
||||
GOOGLE_DCHECK(value != nullptr);
|
||||
_impl_.paths_.Mutable(index)->assign(value);
|
||||
// @@protoc_insertion_point(field_set_char:google.protobuf.FieldMask.paths)
|
||||
}
|
||||
inline void FieldMask::set_paths(int index, const char* value, size_t size) {
|
||||
_impl_.paths_.Mutable(index)->assign(
|
||||
reinterpret_cast<const char*>(value), size);
|
||||
// @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldMask.paths)
|
||||
}
|
||||
inline std::string* FieldMask::_internal_add_paths() {
|
||||
return _impl_.paths_.Add();
|
||||
}
|
||||
inline void FieldMask::add_paths(const std::string& value) {
|
||||
_impl_.paths_.Add()->assign(value);
|
||||
// @@protoc_insertion_point(field_add:google.protobuf.FieldMask.paths)
|
||||
}
|
||||
inline void FieldMask::add_paths(std::string&& value) {
|
||||
_impl_.paths_.Add(std::move(value));
|
||||
// @@protoc_insertion_point(field_add:google.protobuf.FieldMask.paths)
|
||||
}
|
||||
inline void FieldMask::add_paths(const char* value) {
|
||||
GOOGLE_DCHECK(value != nullptr);
|
||||
_impl_.paths_.Add()->assign(value);
|
||||
// @@protoc_insertion_point(field_add_char:google.protobuf.FieldMask.paths)
|
||||
}
|
||||
inline void FieldMask::add_paths(const char* value, size_t size) {
|
||||
_impl_.paths_.Add()->assign(reinterpret_cast<const char*>(value), size);
|
||||
// @@protoc_insertion_point(field_add_pointer:google.protobuf.FieldMask.paths)
|
||||
}
|
||||
inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string>&
|
||||
FieldMask::paths() const {
|
||||
// @@protoc_insertion_point(field_list:google.protobuf.FieldMask.paths)
|
||||
return _impl_.paths_;
|
||||
}
|
||||
inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string>*
|
||||
FieldMask::mutable_paths() {
|
||||
// @@protoc_insertion_point(field_mutable_list:google.protobuf.FieldMask.paths)
|
||||
return &_impl_.paths_;
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif // __GNUC__
|
||||
|
||||
// @@protoc_insertion_point(namespace_scope)
|
||||
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
|
||||
// @@protoc_insertion_point(global_scope)
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
#endif // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2ffield_5fmask_2eproto
|
||||
@@ -1,100 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: jasonh@google.com (Jason Hsueh)
|
||||
//
|
||||
// This header is logically internal, but is made public because it is used
|
||||
// from protocol-compiler-generated code, which may reside in other components.
|
||||
// It provides reflection support for generated enums, and is included in
|
||||
// generated .pb.h files and should have minimal dependencies. The methods are
|
||||
// implemented in generated_message_reflection.cc.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_GENERATED_ENUM_REFLECTION_H__
|
||||
#define GOOGLE_PROTOBUF_GENERATED_ENUM_REFLECTION_H__
|
||||
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/port.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
#include <google/protobuf/generated_enum_util.h>
|
||||
|
||||
#ifdef SWIG
|
||||
#error "You cannot SWIG proto headers"
|
||||
#endif
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
class EnumDescriptor;
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
// Returns the EnumDescriptor for enum type E, which must be a
|
||||
// proto-declared enum type. Code generated by the protocol compiler
|
||||
// will include specializations of this template for each enum type declared.
|
||||
template <typename E>
|
||||
const EnumDescriptor* GetEnumDescriptor();
|
||||
|
||||
namespace internal {
|
||||
|
||||
// Helper for EnumType_Parse functions: try to parse the string 'name' as
|
||||
// an enum name of the given type, returning true and filling in value on
|
||||
// success, or returning false and leaving value unchanged on failure.
|
||||
PROTOBUF_EXPORT bool ParseNamedEnum(const EnumDescriptor* descriptor,
|
||||
ConstStringParam name, int* value);
|
||||
|
||||
template <typename EnumType>
|
||||
bool ParseNamedEnum(const EnumDescriptor* descriptor, ConstStringParam name,
|
||||
EnumType* value) {
|
||||
int tmp;
|
||||
if (!ParseNamedEnum(descriptor, name, &tmp)) return false;
|
||||
*value = static_cast<EnumType>(tmp);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Just a wrapper around printing the name of a value. The main point of this
|
||||
// function is not to be inlined, so that you can do this without including
|
||||
// descriptor.h.
|
||||
PROTOBUF_EXPORT const std::string& NameOfEnum(const EnumDescriptor* descriptor,
|
||||
int value);
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_GENERATED_ENUM_REFLECTION_H__
|
||||
@@ -1,85 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_GENERATED_ENUM_UTIL_H__
|
||||
#define GOOGLE_PROTOBUF_GENERATED_ENUM_UTIL_H__
|
||||
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
#include <google/protobuf/message_lite.h>
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
#ifdef SWIG
|
||||
#error "You cannot SWIG proto headers"
|
||||
#endif
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
// This type trait can be used to cause templates to only match proto2 enum
|
||||
// types.
|
||||
template <typename T>
|
||||
struct is_proto_enum : ::std::false_type {};
|
||||
|
||||
namespace internal {
|
||||
|
||||
// The table entry format for storing enum name-to-value mapping used with lite
|
||||
// protos. This struct and the following related functions should only be used
|
||||
// by protobuf generated code.
|
||||
struct EnumEntry {
|
||||
StringPiece name;
|
||||
int value;
|
||||
};
|
||||
|
||||
// Looks up a numeric enum value given the string name.
|
||||
PROTOBUF_EXPORT bool LookUpEnumValue(const EnumEntry* enums, size_t size,
|
||||
StringPiece name, int* value);
|
||||
|
||||
// Looks up an enum name given the numeric value.
|
||||
PROTOBUF_EXPORT int LookUpEnumName(const EnumEntry* enums,
|
||||
const int* sorted_indices, size_t size,
|
||||
int value);
|
||||
|
||||
// Initializes the list of enum names in std::string form.
|
||||
PROTOBUF_EXPORT bool InitializeEnumStrings(
|
||||
const EnumEntry* enums, const int* sorted_indices, size_t size,
|
||||
internal::ExplicitlyConstructed<std::string>* enum_strings);
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_GENERATED_ENUM_UTIL_H__
|
||||
@@ -1,87 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// This file contains helpers for generated code.
|
||||
//
|
||||
// Nothing in this file should be directly referenced by users of protobufs.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_GENERATED_MESSAGE_BASES_H__
|
||||
#define GOOGLE_PROTOBUF_GENERATED_MESSAGE_BASES_H__
|
||||
|
||||
#include <google/protobuf/io/zero_copy_stream_impl.h>
|
||||
#include <google/protobuf/arena.h>
|
||||
#include <google/protobuf/generated_message_util.h>
|
||||
#include <google/protobuf/message.h>
|
||||
#include <google/protobuf/parse_context.h>
|
||||
|
||||
// Must come last:
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
// To save code size, protos without any fields are derived from ZeroFieldsBase
|
||||
// rather than Message.
|
||||
class PROTOBUF_EXPORT ZeroFieldsBase : public Message {
|
||||
public:
|
||||
PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
|
||||
bool IsInitialized() const final { return true; }
|
||||
size_t ByteSizeLong() const final;
|
||||
int GetCachedSize() const final { return _cached_size_.Get(); }
|
||||
const char* _InternalParse(const char* ptr,
|
||||
internal::ParseContext* ctx) final;
|
||||
::uint8_t* _InternalSerialize(::uint8_t* target,
|
||||
io::EpsCopyOutputStream* stream) const final;
|
||||
|
||||
protected:
|
||||
constexpr ZeroFieldsBase() {}
|
||||
explicit ZeroFieldsBase(Arena* arena, bool is_message_owned)
|
||||
: Message(arena, is_message_owned) {}
|
||||
ZeroFieldsBase(const ZeroFieldsBase&) = delete;
|
||||
ZeroFieldsBase& operator=(const ZeroFieldsBase&) = delete;
|
||||
~ZeroFieldsBase() override;
|
||||
|
||||
void SetCachedSize(int size) const final { _cached_size_.Set(size); }
|
||||
|
||||
static void MergeImpl(Message& to, const Message& from);
|
||||
static void CopyImpl(Message& to, const Message& from);
|
||||
void InternalSwap(ZeroFieldsBase* other);
|
||||
|
||||
mutable internal::CachedSize _cached_size_;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_GENERATED_MESSAGE_BASES_H__
|
||||
@@ -1,354 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
//
|
||||
// This header is logically internal, but is made public because it is used
|
||||
// from protocol-compiler-generated code, which may reside in other components.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_GENERATED_MESSAGE_REFLECTION_H__
|
||||
#define GOOGLE_PROTOBUF_GENERATED_MESSAGE_REFLECTION_H__
|
||||
|
||||
#include <google/protobuf/stubs/casts.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/once.h>
|
||||
#include <google/protobuf/port.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/generated_enum_reflection.h>
|
||||
#include <google/protobuf/unknown_field_set.h>
|
||||
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
#ifdef SWIG
|
||||
#error "You cannot SWIG proto headers"
|
||||
#endif
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
class MapKey;
|
||||
class MapValueRef;
|
||||
class MessageLayoutInspector;
|
||||
class Message;
|
||||
struct Metadata;
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
class DefaultEmptyOneof;
|
||||
// Defined in other files.
|
||||
class ExtensionSet; // extension_set.h
|
||||
class WeakFieldMap; // weak_field_map.h
|
||||
|
||||
// This struct describes the internal layout of the message, hence this is
|
||||
// used to act on the message reflectively.
|
||||
// default_instance: The default instance of the message. This is only
|
||||
// used to obtain pointers to default instances of embedded
|
||||
// messages, which GetMessage() will return if the particular
|
||||
// sub-message has not been initialized yet. (Thus, all
|
||||
// embedded message fields *must* have non-null pointers
|
||||
// in the default instance.)
|
||||
// offsets: An array of ints giving the byte offsets.
|
||||
// For each oneof or weak field, the offset is relative to the
|
||||
// default_instance. These can be computed at compile time
|
||||
// using the
|
||||
// PROTO2_GENERATED_DEFAULT_ONEOF_FIELD_OFFSET()
|
||||
// macro. For each none oneof field, the offset is related to
|
||||
// the start of the message object. These can be computed at
|
||||
// compile time using the
|
||||
// PROTO2_GENERATED_MESSAGE_FIELD_OFFSET() macro.
|
||||
// Besides offsets for all fields, this array also contains
|
||||
// offsets for oneof unions. The offset of the i-th oneof union
|
||||
// is offsets[descriptor->field_count() + i].
|
||||
// has_bit_indices: Mapping from field indexes to their index in the has
|
||||
// bit array.
|
||||
// has_bits_offset: Offset in the message of an array of uint32s of size
|
||||
// descriptor->field_count()/32, rounded up. This is a
|
||||
// bitfield where each bit indicates whether or not the
|
||||
// corresponding field of the message has been initialized.
|
||||
// The bit for field index i is obtained by the expression:
|
||||
// has_bits[i / 32] & (1 << (i % 32))
|
||||
// unknown_fields_offset: Offset in the message of the UnknownFieldSet for
|
||||
// the message.
|
||||
// extensions_offset: Offset in the message of the ExtensionSet for the
|
||||
// message, or -1 if the message type has no extension
|
||||
// ranges.
|
||||
// oneof_case_offset: Offset in the message of an array of uint32s of
|
||||
// size descriptor->oneof_decl_count(). Each uint32_t
|
||||
// indicates what field is set for each oneof.
|
||||
// object_size: The size of a message object of this type, as measured
|
||||
// by sizeof().
|
||||
// arena_offset: If a message doesn't have a unknown_field_set that stores
|
||||
// the arena, it must have a direct pointer to the arena.
|
||||
// weak_field_map_offset: If the message proto has weak fields, this is the
|
||||
// offset of _weak_field_map_ in the generated proto. Otherwise
|
||||
// -1.
|
||||
struct ReflectionSchema {
|
||||
public:
|
||||
// Size of a google::protobuf::Message object of this type.
|
||||
uint32_t GetObjectSize() const { return static_cast<uint32_t>(object_size_); }
|
||||
|
||||
bool InRealOneof(const FieldDescriptor* field) const {
|
||||
return field->containing_oneof() &&
|
||||
!field->containing_oneof()->is_synthetic();
|
||||
}
|
||||
|
||||
// Offset of a non-oneof field. Getting a field offset is slightly more
|
||||
// efficient when we know statically that it is not a oneof field.
|
||||
uint32_t GetFieldOffsetNonOneof(const FieldDescriptor* field) const {
|
||||
GOOGLE_DCHECK(!InRealOneof(field));
|
||||
return OffsetValue(offsets_[field->index()], field->type());
|
||||
}
|
||||
|
||||
// Offset of any field.
|
||||
uint32_t GetFieldOffset(const FieldDescriptor* field) const {
|
||||
if (InRealOneof(field)) {
|
||||
size_t offset =
|
||||
static_cast<size_t>(field->containing_type()->field_count()) +
|
||||
field->containing_oneof()->index();
|
||||
return OffsetValue(offsets_[offset], field->type());
|
||||
} else {
|
||||
return GetFieldOffsetNonOneof(field);
|
||||
}
|
||||
}
|
||||
|
||||
bool IsFieldInlined(const FieldDescriptor* field) const {
|
||||
return Inlined(offsets_[field->index()], field->type());
|
||||
}
|
||||
|
||||
uint32_t GetOneofCaseOffset(const OneofDescriptor* oneof_descriptor) const {
|
||||
return static_cast<uint32_t>(oneof_case_offset_) +
|
||||
static_cast<uint32_t>(
|
||||
static_cast<size_t>(oneof_descriptor->index()) *
|
||||
sizeof(uint32_t));
|
||||
}
|
||||
|
||||
bool HasHasbits() const { return has_bits_offset_ != -1; }
|
||||
|
||||
// Bit index within the bit array of hasbits. Bit order is low-to-high.
|
||||
uint32_t HasBitIndex(const FieldDescriptor* field) const {
|
||||
if (has_bits_offset_ == -1) return static_cast<uint32_t>(-1);
|
||||
GOOGLE_DCHECK(HasHasbits());
|
||||
return has_bit_indices_[field->index()];
|
||||
}
|
||||
|
||||
// Byte offset of the hasbits array.
|
||||
uint32_t HasBitsOffset() const {
|
||||
GOOGLE_DCHECK(HasHasbits());
|
||||
return static_cast<uint32_t>(has_bits_offset_);
|
||||
}
|
||||
|
||||
bool HasInlinedString() const { return inlined_string_donated_offset_ != -1; }
|
||||
|
||||
// Bit index within the bit array of _inlined_string_donated_. Bit order is
|
||||
// low-to-high.
|
||||
uint32_t InlinedStringIndex(const FieldDescriptor* field) const {
|
||||
GOOGLE_DCHECK(HasInlinedString());
|
||||
return inlined_string_indices_[field->index()];
|
||||
}
|
||||
|
||||
// Byte offset of the _inlined_string_donated_ array.
|
||||
uint32_t InlinedStringDonatedOffset() const {
|
||||
GOOGLE_DCHECK(HasInlinedString());
|
||||
return static_cast<uint32_t>(inlined_string_donated_offset_);
|
||||
}
|
||||
|
||||
// The offset of the InternalMetadataWithArena member.
|
||||
// For Lite this will actually be an InternalMetadataWithArenaLite.
|
||||
// The schema doesn't contain enough information to distinguish between
|
||||
// these two cases.
|
||||
uint32_t GetMetadataOffset() const {
|
||||
return static_cast<uint32_t>(metadata_offset_);
|
||||
}
|
||||
|
||||
// Whether this message has an ExtensionSet.
|
||||
bool HasExtensionSet() const { return extensions_offset_ != -1; }
|
||||
|
||||
// The offset of the ExtensionSet in this message.
|
||||
uint32_t GetExtensionSetOffset() const {
|
||||
GOOGLE_DCHECK(HasExtensionSet());
|
||||
return static_cast<uint32_t>(extensions_offset_);
|
||||
}
|
||||
|
||||
// The off set of WeakFieldMap when the message contains weak fields.
|
||||
// The default is 0 for now.
|
||||
int GetWeakFieldMapOffset() const { return weak_field_map_offset_; }
|
||||
|
||||
bool IsDefaultInstance(const Message& message) const {
|
||||
return &message == default_instance_;
|
||||
}
|
||||
|
||||
// Returns a pointer to the default value for this field. The size and type
|
||||
// of the underlying data depends on the field's type.
|
||||
const void* GetFieldDefault(const FieldDescriptor* field) const {
|
||||
return reinterpret_cast<const uint8_t*>(default_instance_) +
|
||||
OffsetValue(offsets_[field->index()], field->type());
|
||||
}
|
||||
|
||||
// Returns true if the field is implicitly backed by LazyField.
|
||||
bool IsEagerlyVerifiedLazyField(const FieldDescriptor* field) const {
|
||||
GOOGLE_DCHECK_EQ(field->type(), FieldDescriptor::TYPE_MESSAGE);
|
||||
(void)field;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsFieldStripped(const FieldDescriptor* field) const {
|
||||
(void)field;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsMessageStripped(const Descriptor* descriptor) const {
|
||||
(void)descriptor;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool HasWeakFields() const { return weak_field_map_offset_ > 0; }
|
||||
|
||||
// These members are intended to be private, but we cannot actually make them
|
||||
// private because this prevents us from using aggregate initialization of
|
||||
// them, ie.
|
||||
//
|
||||
// ReflectionSchema schema = {a, b, c, d, e, ...};
|
||||
// private:
|
||||
const Message* default_instance_;
|
||||
const uint32_t* offsets_;
|
||||
const uint32_t* has_bit_indices_;
|
||||
int has_bits_offset_;
|
||||
int metadata_offset_;
|
||||
int extensions_offset_;
|
||||
int oneof_case_offset_;
|
||||
int object_size_;
|
||||
int weak_field_map_offset_;
|
||||
const uint32_t* inlined_string_indices_;
|
||||
int inlined_string_donated_offset_;
|
||||
|
||||
// We tag offset values to provide additional data about fields (such as
|
||||
// "unused" or "lazy" or "inlined").
|
||||
static uint32_t OffsetValue(uint32_t v, FieldDescriptor::Type type) {
|
||||
if (type == FieldDescriptor::TYPE_MESSAGE ||
|
||||
type == FieldDescriptor::TYPE_STRING ||
|
||||
type == FieldDescriptor::TYPE_BYTES) {
|
||||
return v & 0xFFFFFFFEu;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
static bool Inlined(uint32_t v, FieldDescriptor::Type type) {
|
||||
if (type == FieldDescriptor::TYPE_STRING ||
|
||||
type == FieldDescriptor::TYPE_BYTES) {
|
||||
return (v & 1u) != 0u;
|
||||
} else {
|
||||
// Non string/byte fields are not inlined.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Structs that the code generator emits directly to describe a message.
|
||||
// These should never used directly except to build a ReflectionSchema
|
||||
// object.
|
||||
//
|
||||
// EXPERIMENTAL: these are changing rapidly, and may completely disappear
|
||||
// or merge with ReflectionSchema.
|
||||
struct MigrationSchema {
|
||||
int32_t offsets_index;
|
||||
int32_t has_bit_indices_index;
|
||||
int32_t inlined_string_indices_index;
|
||||
int object_size;
|
||||
};
|
||||
|
||||
// This struct tries to reduce unnecessary padding.
|
||||
// The num_xxx might not be close to their respective pointer, but this saves
|
||||
// padding.
|
||||
struct PROTOBUF_EXPORT DescriptorTable {
|
||||
mutable bool is_initialized;
|
||||
bool is_eager;
|
||||
int size; // of serialized descriptor
|
||||
const char* descriptor;
|
||||
const char* filename;
|
||||
once_flag* once;
|
||||
const DescriptorTable* const* deps;
|
||||
int num_deps;
|
||||
int num_messages;
|
||||
const MigrationSchema* schemas;
|
||||
const Message* const* default_instances;
|
||||
const uint32_t* offsets;
|
||||
// update the following descriptor arrays.
|
||||
Metadata* file_level_metadata;
|
||||
const EnumDescriptor** file_level_enum_descriptors;
|
||||
const ServiceDescriptor** file_level_service_descriptors;
|
||||
};
|
||||
|
||||
enum {
|
||||
// Tag used on offsets for fields that don't have a real offset.
|
||||
// For example, weak message fields go into the WeakFieldMap and not in an
|
||||
// actual field.
|
||||
kInvalidFieldOffsetTag = 0x40000000u,
|
||||
};
|
||||
|
||||
// AssignDescriptors() pulls the compiled FileDescriptor from the DescriptorPool
|
||||
// and uses it to populate all of the global variables which store pointers to
|
||||
// the descriptor objects. It also constructs the reflection objects. It is
|
||||
// called the first time anyone calls descriptor() or GetReflection() on one of
|
||||
// the types defined in the file. AssignDescriptors() is thread-safe.
|
||||
void PROTOBUF_EXPORT AssignDescriptors(const DescriptorTable* table,
|
||||
bool eager = false);
|
||||
|
||||
// Overload used to implement GetMetadataStatic in the generated code.
|
||||
// See comments in compiler/cpp/internal/file.cc as to why.
|
||||
// It takes a `Metadata` and returns it to allow for tail calls and reduce
|
||||
// binary size.
|
||||
Metadata PROTOBUF_EXPORT AssignDescriptors(const DescriptorTable* (*table)(),
|
||||
internal::once_flag* once,
|
||||
const Metadata& metadata);
|
||||
|
||||
// These cannot be in lite so we put them in the reflection.
|
||||
PROTOBUF_EXPORT void UnknownFieldSetSerializer(const uint8_t* base,
|
||||
uint32_t offset, uint32_t tag,
|
||||
uint32_t has_offset,
|
||||
io::CodedOutputStream* output);
|
||||
|
||||
struct PROTOBUF_EXPORT AddDescriptorsRunner {
|
||||
explicit AddDescriptorsRunner(const DescriptorTable* table);
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_GENERATED_MESSAGE_REFLECTION_H__
|
||||
@@ -1,312 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// This file contains declarations needed in generated headers for messages
|
||||
// that use tail-call table parsing. Everything in this file is for internal
|
||||
// use only.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_GENERATED_MESSAGE_TCTABLE_DECL_H__
|
||||
#define GOOGLE_PROTOBUF_GENERATED_MESSAGE_TCTABLE_DECL_H__
|
||||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <type_traits>
|
||||
|
||||
#include <google/protobuf/message_lite.h>
|
||||
#include <google/protobuf/parse_context.h>
|
||||
|
||||
// Must come last:
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
// Additional information about this field:
|
||||
struct TcFieldData {
|
||||
constexpr TcFieldData() : data(0) {}
|
||||
|
||||
// Fast table entry constructor:
|
||||
constexpr TcFieldData(uint16_t coded_tag, uint8_t hasbit_idx, uint8_t aux_idx,
|
||||
uint16_t offset)
|
||||
: data(uint64_t{offset} << 48 | //
|
||||
uint64_t{aux_idx} << 24 | //
|
||||
uint64_t{hasbit_idx} << 16 | //
|
||||
uint64_t{coded_tag}) {}
|
||||
|
||||
// Fields used in fast table parsing:
|
||||
//
|
||||
// Bit:
|
||||
// +-----------+-------------------+
|
||||
// |63 .. 32|31 .. 0|
|
||||
// +---------------+---------------+
|
||||
// : . : . : . 16|=======| [16] coded_tag()
|
||||
// : . : . : 24|===| . : [ 8] hasbit_idx()
|
||||
// : . : . 32|===| : . : [ 8] aux_idx()
|
||||
// : . 48:---.---: . : . : [16] (unused)
|
||||
// |=======| . : . : . : [16] offset()
|
||||
// +-----------+-------------------+
|
||||
// |63 .. 32|31 .. 0|
|
||||
// +---------------+---------------+
|
||||
|
||||
template <typename TagType = uint16_t>
|
||||
TagType coded_tag() const {
|
||||
return static_cast<TagType>(data);
|
||||
}
|
||||
uint8_t hasbit_idx() const { return static_cast<uint8_t>(data >> 16); }
|
||||
uint8_t aux_idx() const { return static_cast<uint8_t>(data >> 24); }
|
||||
uint16_t offset() const { return static_cast<uint16_t>(data >> 48); }
|
||||
|
||||
// Fields used in mini table parsing:
|
||||
//
|
||||
// Bit:
|
||||
// +-----------+-------------------+
|
||||
// |63 .. 32|31 .. 0|
|
||||
// +---------------+---------------+
|
||||
// : . : . |===============| [32] tag() (decoded)
|
||||
// |===============| . : . : [32] entry_offset()
|
||||
// +-----------+-------------------+
|
||||
// |63 .. 32|31 .. 0|
|
||||
// +---------------+---------------+
|
||||
|
||||
uint32_t tag() const { return static_cast<uint32_t>(data); }
|
||||
uint32_t entry_offset() const { return static_cast<uint32_t>(data >> 32); }
|
||||
|
||||
uint64_t data;
|
||||
};
|
||||
|
||||
struct TcParseTableBase;
|
||||
|
||||
// TailCallParseFunc is the function pointer type used in the tailcall table.
|
||||
typedef const char* (*TailCallParseFunc)(PROTOBUF_TC_PARAM_DECL);
|
||||
|
||||
namespace field_layout {
|
||||
struct Offset {
|
||||
uint32_t off;
|
||||
};
|
||||
} // namespace field_layout
|
||||
|
||||
#if defined(_MSC_VER) && !defined(_WIN64)
|
||||
#pragma warning(push)
|
||||
// TcParseTableBase is intentionally overaligned on 32 bit targets.
|
||||
#pragma warning(disable : 4324)
|
||||
#endif
|
||||
|
||||
// Base class for message-level table with info for the tail-call parser.
|
||||
struct alignas(uint64_t) TcParseTableBase {
|
||||
// Common attributes for message layout:
|
||||
uint16_t has_bits_offset;
|
||||
uint16_t extension_offset;
|
||||
uint32_t extension_range_low;
|
||||
uint32_t extension_range_high;
|
||||
uint32_t max_field_number;
|
||||
uint8_t fast_idx_mask;
|
||||
uint16_t lookup_table_offset;
|
||||
uint32_t skipmap32;
|
||||
uint32_t field_entries_offset;
|
||||
uint16_t num_field_entries;
|
||||
|
||||
uint16_t num_aux_entries;
|
||||
uint32_t aux_offset;
|
||||
|
||||
const MessageLite* default_instance;
|
||||
|
||||
// Handler for fields which are not handled by table dispatch.
|
||||
TailCallParseFunc fallback;
|
||||
|
||||
// This constructor exactly follows the field layout, so it's technically
|
||||
// not necessary. However, it makes it much much easier to add or re-arrange
|
||||
// fields, because it can be overloaded with an additional constructor,
|
||||
// temporarily allowing both old and new protocol buffer headers to be
|
||||
// compiled.
|
||||
constexpr TcParseTableBase(
|
||||
uint16_t has_bits_offset, uint16_t extension_offset,
|
||||
uint32_t extension_range_low, uint32_t extension_range_high,
|
||||
uint32_t max_field_number, uint8_t fast_idx_mask,
|
||||
uint16_t lookup_table_offset, uint32_t skipmap32,
|
||||
uint32_t field_entries_offset, uint16_t num_field_entries,
|
||||
uint16_t num_aux_entries, uint32_t aux_offset,
|
||||
const MessageLite* default_instance, TailCallParseFunc fallback)
|
||||
: has_bits_offset(has_bits_offset),
|
||||
extension_offset(extension_offset),
|
||||
extension_range_low(extension_range_low),
|
||||
extension_range_high(extension_range_high),
|
||||
max_field_number(max_field_number),
|
||||
fast_idx_mask(fast_idx_mask),
|
||||
lookup_table_offset(lookup_table_offset),
|
||||
skipmap32(skipmap32),
|
||||
field_entries_offset(field_entries_offset),
|
||||
num_field_entries(num_field_entries),
|
||||
num_aux_entries(num_aux_entries),
|
||||
aux_offset(aux_offset),
|
||||
default_instance(default_instance),
|
||||
fallback(fallback) {}
|
||||
|
||||
// Table entry for fast-path tailcall dispatch handling.
|
||||
struct FastFieldEntry {
|
||||
// Target function for dispatch:
|
||||
TailCallParseFunc target;
|
||||
// Field data used during parse:
|
||||
TcFieldData bits;
|
||||
};
|
||||
// There is always at least one table entry.
|
||||
const FastFieldEntry* fast_entry(size_t idx) const {
|
||||
return reinterpret_cast<const FastFieldEntry*>(this + 1) + idx;
|
||||
}
|
||||
|
||||
// Returns a begin iterator (pointer) to the start of the field lookup table.
|
||||
const uint16_t* field_lookup_begin() const {
|
||||
return reinterpret_cast<const uint16_t*>(reinterpret_cast<uintptr_t>(this) +
|
||||
lookup_table_offset);
|
||||
}
|
||||
|
||||
// Field entry for all fields.
|
||||
struct FieldEntry {
|
||||
uint32_t offset; // offset in the message object
|
||||
int32_t has_idx; // has-bit index
|
||||
uint16_t aux_idx; // index for `field_aux`.
|
||||
uint16_t type_card; // `FieldType` and `Cardinality` (see _impl.h)
|
||||
};
|
||||
|
||||
// Returns a begin iterator (pointer) to the start of the field entries array.
|
||||
const FieldEntry* field_entries_begin() const {
|
||||
return reinterpret_cast<const FieldEntry*>(
|
||||
reinterpret_cast<uintptr_t>(this) + field_entries_offset);
|
||||
}
|
||||
|
||||
// Auxiliary entries for field types that need extra information.
|
||||
union FieldAux {
|
||||
constexpr FieldAux() : message_default(nullptr) {}
|
||||
constexpr FieldAux(bool (*enum_validator)(int))
|
||||
: enum_validator(enum_validator) {}
|
||||
constexpr FieldAux(field_layout::Offset off) : offset(off.off) {}
|
||||
constexpr FieldAux(int16_t range_start, uint16_t range_length)
|
||||
: enum_range{range_start, range_length} {}
|
||||
constexpr FieldAux(const MessageLite* msg) : message_default(msg) {}
|
||||
bool (*enum_validator)(int);
|
||||
struct {
|
||||
int16_t start; // minimum enum number (if it fits)
|
||||
uint16_t length; // length of range (i.e., max = start + length - 1)
|
||||
} enum_range;
|
||||
uint32_t offset;
|
||||
const MessageLite* message_default;
|
||||
};
|
||||
const FieldAux* field_aux(uint32_t idx) const {
|
||||
return reinterpret_cast<const FieldAux*>(reinterpret_cast<uintptr_t>(this) +
|
||||
aux_offset) +
|
||||
idx;
|
||||
}
|
||||
const FieldAux* field_aux(const FieldEntry* entry) const {
|
||||
return field_aux(entry->aux_idx);
|
||||
}
|
||||
|
||||
// Field name data
|
||||
const char* name_data() const {
|
||||
return reinterpret_cast<const char*>(reinterpret_cast<uintptr_t>(this) +
|
||||
aux_offset +
|
||||
num_aux_entries * sizeof(FieldAux));
|
||||
}
|
||||
};
|
||||
|
||||
#if defined(_MSC_VER) && !defined(_WIN64)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
static_assert(sizeof(TcParseTableBase::FastFieldEntry) <= 16,
|
||||
"Fast field entry is too big.");
|
||||
static_assert(sizeof(TcParseTableBase::FieldEntry) <= 16,
|
||||
"Field entry is too big.");
|
||||
|
||||
template <size_t kFastTableSizeLog2, size_t kNumFieldEntries = 0,
|
||||
size_t kNumFieldAux = 0, size_t kNameTableSize = 0,
|
||||
size_t kFieldLookupSize = 2>
|
||||
struct TcParseTable {
|
||||
TcParseTableBase header;
|
||||
|
||||
// Entries for each field.
|
||||
//
|
||||
// Fields are indexed by the lowest bits of their field number. The field
|
||||
// number is masked to fit inside the table. Note that the parsing logic
|
||||
// generally calls `TailCallParseTableBase::fast_entry()` instead of accessing
|
||||
// this field directly.
|
||||
std::array<TcParseTableBase::FastFieldEntry, (1 << kFastTableSizeLog2)>
|
||||
fast_entries;
|
||||
|
||||
// Just big enough to find all the field entries.
|
||||
std::array<uint16_t, kFieldLookupSize> field_lookup_table;
|
||||
// Entries for all fields:
|
||||
std::array<TcParseTableBase::FieldEntry, kNumFieldEntries> field_entries;
|
||||
std::array<TcParseTableBase::FieldAux, kNumFieldAux> aux_entries;
|
||||
std::array<char, kNameTableSize> field_names;
|
||||
};
|
||||
|
||||
// Partial specialization: if there are no aux entries, there will be no array.
|
||||
// In C++, arrays cannot have length 0, but (C++11) std::array<T, 0> is valid.
|
||||
// However, different implementations have different sizeof(std::array<T, 0>).
|
||||
// Skipping the member makes offset computations portable.
|
||||
template <size_t kFastTableSizeLog2, size_t kNumFieldEntries,
|
||||
size_t kNameTableSize, size_t kFieldLookupSize>
|
||||
struct TcParseTable<kFastTableSizeLog2, kNumFieldEntries, 0, kNameTableSize,
|
||||
kFieldLookupSize> {
|
||||
TcParseTableBase header;
|
||||
std::array<TcParseTableBase::FastFieldEntry, (1 << kFastTableSizeLog2)>
|
||||
fast_entries;
|
||||
std::array<uint16_t, kFieldLookupSize> field_lookup_table;
|
||||
std::array<TcParseTableBase::FieldEntry, kNumFieldEntries> field_entries;
|
||||
std::array<char, kNameTableSize> field_names;
|
||||
};
|
||||
|
||||
// Partial specialization: if there are no fields at all, then we can save space
|
||||
// by skipping the field numbers and entries.
|
||||
template <size_t kNameTableSize, size_t kFieldLookupSize>
|
||||
struct TcParseTable<0, 0, 0, kNameTableSize, kFieldLookupSize> {
|
||||
TcParseTableBase header;
|
||||
// N.B.: the fast entries are sized by log2, so 2**0 fields = 1 entry.
|
||||
// The fast parsing loop will always use this entry, so it must be present.
|
||||
std::array<TcParseTableBase::FastFieldEntry, 1> fast_entries;
|
||||
std::array<uint16_t, kFieldLookupSize> field_lookup_table;
|
||||
std::array<char, kNameTableSize> field_names;
|
||||
};
|
||||
|
||||
static_assert(std::is_standard_layout<TcParseTable<1>>::value,
|
||||
"TcParseTable must be standard layout.");
|
||||
|
||||
static_assert(offsetof(TcParseTable<1>, fast_entries) ==
|
||||
sizeof(TcParseTableBase),
|
||||
"Table entries must be laid out after TcParseTableBase.");
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_GENERATED_MESSAGE_TCTABLE_DECL_H__
|
||||
@@ -1,565 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_GENERATED_MESSAGE_TCTABLE_IMPL_H__
|
||||
#define GOOGLE_PROTOBUF_GENERATED_MESSAGE_TCTABLE_IMPL_H__
|
||||
|
||||
#include <cstdint>
|
||||
#include <type_traits>
|
||||
|
||||
#include <google/protobuf/port.h>
|
||||
#include <google/protobuf/extension_set.h>
|
||||
#include <google/protobuf/generated_message_tctable_decl.h>
|
||||
#include <google/protobuf/message_lite.h>
|
||||
#include <google/protobuf/metadata_lite.h>
|
||||
#include <google/protobuf/parse_context.h>
|
||||
#include <google/protobuf/wire_format_lite.h>
|
||||
|
||||
// Must come last:
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
class Message;
|
||||
class UnknownFieldSet;
|
||||
|
||||
namespace internal {
|
||||
|
||||
// Field layout enums.
|
||||
//
|
||||
// Structural information about fields is packed into a 16-bit value. The enum
|
||||
// types below represent bitwise fields, along with their respective widths,
|
||||
// shifts, and masks.
|
||||
//
|
||||
// Bit:
|
||||
// +-----------------------+-----------------------+
|
||||
// |15 .. 8|7 .. 0|
|
||||
// +-----------------------+-----------------------+
|
||||
// : . : . : . : . : . : . : 3|========| [3] FieldType
|
||||
// : : : : : : 5|=====| : : [2] FieldCardinality
|
||||
// : . : . : . : . 8|========| : . : . : [3] FieldRep
|
||||
// : : : 10|=====| : : : : [2] TransformValidation
|
||||
// : . : .12|=====| . : . : . : . : . : [2] FormatDiscriminator
|
||||
// +-----------------------+-----------------------+
|
||||
// |15 .. 8|7 .. 0|
|
||||
// +-----------------------+-----------------------+
|
||||
//
|
||||
namespace field_layout {
|
||||
// clang-format off
|
||||
|
||||
// Field kind (3 bits):
|
||||
// These values broadly represent a wire type and an in-memory storage class.
|
||||
enum FieldKind : uint16_t {
|
||||
kFkShift = 0,
|
||||
kFkBits = 3,
|
||||
kFkMask = ((1 << kFkBits) - 1) << kFkShift,
|
||||
|
||||
kFkNone = 0,
|
||||
kFkVarint, // WT=0 rep=8,32,64 bits
|
||||
kFkPackedVarint, // WT=2 rep=8,32,64 bits
|
||||
kFkFixed, // WT=1,5 rep=32,64 bits
|
||||
kFkPackedFixed, // WT=2 rep=32,64 bits
|
||||
kFkString, // WT=2 rep=various
|
||||
kFkMessage, // WT=2,3,4 rep=MessageLite*
|
||||
// Maps are a special case of Message, but use different parsing logic.
|
||||
kFkMap, // WT=2 rep=Map(Lite)<various, various>
|
||||
};
|
||||
|
||||
static_assert(kFkMap < (1 << kFkBits), "too many types");
|
||||
|
||||
// Cardinality (2 bits):
|
||||
// These values determine how many values a field can have and its presence.
|
||||
// Packed fields are represented in FieldType.
|
||||
enum Cardinality : uint16_t {
|
||||
kFcShift = kFkShift + kFkBits,
|
||||
kFcBits = 2,
|
||||
kFcMask = ((1 << kFcBits) - 1) << kFcShift,
|
||||
|
||||
kFcSingular = 0,
|
||||
kFcOptional = 1 << kFcShift,
|
||||
kFcRepeated = 2 << kFcShift,
|
||||
kFcOneof = 3 << kFcShift,
|
||||
};
|
||||
|
||||
// Field representation (3 bits):
|
||||
// These values are the specific refinements of storage classes in FieldType.
|
||||
enum FieldRep : uint16_t {
|
||||
kRepShift = kFcShift + kFcBits,
|
||||
kRepBits = 3,
|
||||
kRepMask = ((1 << kRepBits) - 1) << kRepShift,
|
||||
|
||||
// Numeric types (used for optional and repeated fields):
|
||||
kRep8Bits = 0,
|
||||
kRep32Bits = 2 << kRepShift,
|
||||
kRep64Bits = 3 << kRepShift,
|
||||
// String types:
|
||||
kRepAString = 0, // ArenaStringPtr
|
||||
kRepIString = 1 << kRepShift, // InlinedString
|
||||
kRepCord = 2 << kRepShift, // absl::Cord
|
||||
kRepSPiece = 3 << kRepShift, // StringPieceField
|
||||
kRepSString = 4 << kRepShift, // std::string*
|
||||
// Message types (WT=2 unless otherwise noted):
|
||||
kRepMessage = 0, // MessageLite*
|
||||
kRepGroup = 1 << kRepShift, // MessageLite* (WT=3,4)
|
||||
kRepLazy = 2 << kRepShift, // LazyField*
|
||||
kRepIWeak = 3 << kRepShift, // ImplicitWeak
|
||||
};
|
||||
|
||||
// Transform/validation (2 bits):
|
||||
// These values determine transforms or validation to/from wire format.
|
||||
enum TransformValidation : uint16_t {
|
||||
kTvShift = kRepShift + kRepBits,
|
||||
kTvBits = 2,
|
||||
kTvMask = ((1 << kTvBits) - 1) << kTvShift,
|
||||
|
||||
// Varint fields:
|
||||
kTvZigZag = 1 << kTvShift,
|
||||
kTvEnum = 2 << kTvShift, // validate using generated _IsValid()
|
||||
kTvRange = 3 << kTvShift, // validate using FieldAux::enum_range
|
||||
// String fields:
|
||||
kTvUtf8Debug = 1 << kTvShift, // proto2
|
||||
kTvUtf8 = 2 << kTvShift, // proto3
|
||||
};
|
||||
|
||||
static_assert((kTvEnum & kTvRange) != 0,
|
||||
"enum validation types must share a bit");
|
||||
static_assert((kTvEnum & kTvRange & kTvZigZag) == 0,
|
||||
"zigzag encoding is not enum validation");
|
||||
|
||||
// Format discriminators (2 bits):
|
||||
enum FormatDiscriminator : uint16_t {
|
||||
kFmtShift = kTvShift + kTvBits,
|
||||
kFmtBits = 2,
|
||||
kFmtMask = ((1 << kFmtBits) - 1) << kFmtShift,
|
||||
|
||||
// Numeric:
|
||||
kFmtUnsigned = 1 << kFmtShift, // fixed, varint
|
||||
kFmtSigned = 2 << kFmtShift, // fixed, varint
|
||||
kFmtFloating = 3 << kFmtShift, // fixed
|
||||
kFmtEnum = 3 << kFmtShift, // varint
|
||||
// Strings:
|
||||
kFmtUtf8 = 1 << kFmtShift, // string (proto3, enforce_utf8=true)
|
||||
kFmtUtf8Escape = 2 << kFmtShift, // string (proto2, enforce_utf8=false)
|
||||
// Bytes:
|
||||
kFmtArray = 1 << kFmtShift, // bytes
|
||||
// Messages:
|
||||
kFmtShow = 1 << kFmtShift, // message, map
|
||||
};
|
||||
|
||||
// Update this assertion (and comments above) when adding or removing bits:
|
||||
static_assert(kFmtShift + kFmtBits == 12, "number of bits changed");
|
||||
|
||||
// This assertion should not change unless the storage width changes:
|
||||
static_assert(kFmtShift + kFmtBits <= 16, "too many bits");
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#if __GNUC__ >= 12 || (__GNUC__ == 11 && __GNUC_MINOR__ >= 1)
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-enum-enum-conversion"
|
||||
#endif
|
||||
#endif
|
||||
// Convenience aliases (16 bits, with format):
|
||||
enum FieldType : uint16_t {
|
||||
// Numeric types:
|
||||
kBool = kFkVarint | kRep8Bits,
|
||||
|
||||
kFixed32 = kFkFixed | kRep32Bits | kFmtUnsigned,
|
||||
kUInt32 = kFkVarint | kRep32Bits | kFmtUnsigned,
|
||||
kSFixed32 = kFkFixed | kRep32Bits | kFmtSigned,
|
||||
kInt32 = kFkVarint | kRep32Bits | kFmtSigned,
|
||||
kSInt32 = kFkVarint | kRep32Bits | kFmtSigned | kTvZigZag,
|
||||
kFloat = kFkFixed | kRep32Bits | kFmtFloating,
|
||||
kEnum = kFkVarint | kRep32Bits | kFmtEnum | kTvEnum,
|
||||
kEnumRange = kFkVarint | kRep32Bits | kFmtEnum | kTvRange,
|
||||
kOpenEnum = kFkVarint | kRep32Bits | kFmtEnum,
|
||||
|
||||
kFixed64 = kFkFixed | kRep64Bits | kFmtUnsigned,
|
||||
kUInt64 = kFkVarint | kRep64Bits | kFmtUnsigned,
|
||||
kSFixed64 = kFkFixed | kRep64Bits | kFmtSigned,
|
||||
kInt64 = kFkVarint | kRep64Bits | kFmtSigned,
|
||||
kSInt64 = kFkVarint | kRep64Bits | kFmtSigned | kTvZigZag,
|
||||
kDouble = kFkFixed | kRep64Bits | kFmtFloating,
|
||||
|
||||
kPackedBool = kFkPackedVarint | kRep8Bits,
|
||||
|
||||
kPackedFixed32 = kFkPackedFixed | kRep32Bits | kFmtUnsigned,
|
||||
kPackedUInt32 = kFkPackedVarint | kRep32Bits | kFmtUnsigned,
|
||||
kPackedSFixed32 = kFkPackedFixed | kRep32Bits | kFmtSigned,
|
||||
kPackedInt32 = kFkPackedVarint | kRep32Bits | kFmtSigned,
|
||||
kPackedSInt32 = kFkPackedVarint | kRep32Bits | kFmtSigned | kTvZigZag,
|
||||
kPackedFloat = kFkPackedFixed | kRep32Bits | kFmtFloating,
|
||||
kPackedEnum = kFkPackedVarint | kRep32Bits | kFmtEnum | kTvEnum,
|
||||
kPackedEnumRange = kFkPackedVarint | kRep32Bits | kFmtEnum | kTvRange,
|
||||
kPackedOpenEnum = kFkPackedVarint | kRep32Bits | kFmtEnum,
|
||||
|
||||
kPackedFixed64 = kFkPackedFixed | kRep64Bits | kFmtUnsigned,
|
||||
kPackedUInt64 = kFkPackedVarint | kRep64Bits | kFmtUnsigned,
|
||||
kPackedSFixed64 = kFkPackedFixed | kRep64Bits | kFmtSigned,
|
||||
kPackedInt64 = kFkPackedVarint | kRep64Bits | kFmtSigned,
|
||||
kPackedSInt64 = kFkPackedVarint | kRep64Bits | kFmtSigned | kTvZigZag,
|
||||
kPackedDouble = kFkPackedFixed | kRep64Bits | kFmtFloating,
|
||||
|
||||
// String types:
|
||||
kBytes = kFkString | kFmtArray,
|
||||
kRawString = kFkString | kFmtUtf8 | kTvUtf8Debug,
|
||||
kUtf8String = kFkString | kFmtUtf8 | kTvUtf8,
|
||||
|
||||
// Message types:
|
||||
kMessage = kFkMessage,
|
||||
|
||||
// Map types:
|
||||
kMap = kFkMap,
|
||||
};
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
// clang-format on
|
||||
} // namespace field_layout
|
||||
|
||||
// PROTOBUF_TC_PARAM_DECL are the parameters for tailcall functions, it is
|
||||
// defined in port_def.inc.
|
||||
//
|
||||
// Note that this is performance sensitive: changing the parameters will change
|
||||
// the registers used by the ABI calling convention, which subsequently affects
|
||||
// register selection logic inside the function.
|
||||
|
||||
// PROTOBUF_TC_PARAM_PASS passes values to match PROTOBUF_TC_PARAM_DECL.
|
||||
#define PROTOBUF_TC_PARAM_PASS msg, ptr, ctx, table, hasbits, data
|
||||
|
||||
#ifndef NDEBUG
|
||||
template <size_t align>
|
||||
#ifndef _MSC_VER
|
||||
[[noreturn]]
|
||||
#endif
|
||||
void AlignFail(uintptr_t address) {
|
||||
GOOGLE_LOG(FATAL) << "Unaligned (" << align << ") access at " << address;
|
||||
#ifdef __GNUC__
|
||||
__builtin_unreachable();
|
||||
#endif
|
||||
}
|
||||
|
||||
extern template void AlignFail<4>(uintptr_t);
|
||||
extern template void AlignFail<8>(uintptr_t);
|
||||
#endif
|
||||
|
||||
// TcParser implements most of the parsing logic for tailcall tables.
|
||||
class PROTOBUF_EXPORT TcParser final {
|
||||
public:
|
||||
static const char* GenericFallback(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* GenericFallbackLite(PROTOBUF_TC_PARAM_DECL);
|
||||
|
||||
static const char* ParseLoop(MessageLite* msg, const char* ptr,
|
||||
ParseContext* ctx,
|
||||
const TcParseTableBase* table);
|
||||
|
||||
// Functions referenced by generated fast tables (numeric types):
|
||||
// F: fixed V: varint Z: zigzag
|
||||
// 8/32/64: storage type width (bits)
|
||||
// S: singular R: repeated P: packed
|
||||
// 1/2: tag length (bytes)
|
||||
|
||||
// Fixed:
|
||||
static const char* FastF32S1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastF32S2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastF32R1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastF32R2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastF32P1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastF32P2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastF64S1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastF64S2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastF64R1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastF64R2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastF64P1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastF64P2(PROTOBUF_TC_PARAM_DECL);
|
||||
|
||||
// Varint:
|
||||
static const char* FastV8S1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastV8S2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastV8R1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastV8R2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastV8P1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastV8P2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastV32S1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastV32S2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastV32R1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastV32R2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastV32P1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastV32P2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastV64S1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastV64S2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastV64R1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastV64R2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastV64P1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastV64P2(PROTOBUF_TC_PARAM_DECL);
|
||||
|
||||
// Varint (with zigzag):
|
||||
static const char* FastZ32S1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastZ32S2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastZ32R1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastZ32R2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastZ32P1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastZ32P2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastZ64S1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastZ64S2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastZ64R1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastZ64R2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastZ64P1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastZ64P2(PROTOBUF_TC_PARAM_DECL);
|
||||
|
||||
// Functions referenced by generated fast tables (closed enum):
|
||||
// E: closed enum (N.B.: open enums use V32, above)
|
||||
// r: enum range v: enum validator (_IsValid function)
|
||||
// S: singular R: repeated
|
||||
// 1/2: tag length (bytes)
|
||||
static const char* FastErS1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastErS2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastErR1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastErR2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastEvS1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastEvS2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastEvR1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastEvR2(PROTOBUF_TC_PARAM_DECL);
|
||||
|
||||
// Functions referenced by generated fast tables (string types):
|
||||
// B: bytes S: string U: UTF-8 string
|
||||
// (empty): ArenaStringPtr i: InlinedString
|
||||
// S: singular R: repeated
|
||||
// 1/2: tag length (bytes)
|
||||
static const char* FastBS1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastBS2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastBR1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastBR2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastSS1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastSS2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastSR1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastSR2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastUS1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastUS2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastUR1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastUR2(PROTOBUF_TC_PARAM_DECL);
|
||||
|
||||
static const char* FastBiS1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastBiS2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastSiS1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastSiS2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastUiS1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastUiS2(PROTOBUF_TC_PARAM_DECL);
|
||||
|
||||
// Functions referenced by generated fast tables (message types):
|
||||
// M: message G: group
|
||||
// S: singular R: repeated
|
||||
// 1/2: tag length (bytes)
|
||||
static const char* FastMS1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastMS2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastMR1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastMR2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastGS1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastGS2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastGR1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastGR2(PROTOBUF_TC_PARAM_DECL);
|
||||
|
||||
template <typename T>
|
||||
static inline T& RefAt(void* x, size_t offset) {
|
||||
T* target = reinterpret_cast<T*>(static_cast<char*>(x) + offset);
|
||||
#ifndef NDEBUG
|
||||
if (PROTOBUF_PREDICT_FALSE(
|
||||
reinterpret_cast<uintptr_t>(target) % alignof(T) != 0)) {
|
||||
AlignFail<alignof(T)>(reinterpret_cast<uintptr_t>(target));
|
||||
}
|
||||
#endif
|
||||
return *target;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static inline const T& RefAt(const void* x, size_t offset) {
|
||||
const T* target =
|
||||
reinterpret_cast<const T*>(static_cast<const char*>(x) + offset);
|
||||
#ifndef NDEBUG
|
||||
if (PROTOBUF_PREDICT_FALSE(
|
||||
reinterpret_cast<uintptr_t>(target) % alignof(T) != 0)) {
|
||||
AlignFail<alignof(T)>(reinterpret_cast<uintptr_t>(target));
|
||||
}
|
||||
#endif
|
||||
return *target;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static inline T ReadAt(const void* x, size_t offset) {
|
||||
T out;
|
||||
memcpy(&out, static_cast<const char*>(x) + offset, sizeof(T));
|
||||
return out;
|
||||
}
|
||||
|
||||
// Mini parsing:
|
||||
//
|
||||
// This function parses a field from incoming data based on metadata stored in
|
||||
// the message definition. If the field is not defined in the message, it is
|
||||
// stored in either the ExtensionSet (if applicable) or the UnknownFieldSet.
|
||||
//
|
||||
// NOTE: Currently, this function only calls the table-level fallback
|
||||
// function, so it should only be called as the fallback from fast table
|
||||
// parsing.
|
||||
static const char* MiniParse(PROTOBUF_TC_PARAM_DECL);
|
||||
|
||||
private:
|
||||
friend class GeneratedTcTableLiteTest;
|
||||
|
||||
template <typename TagType, bool group_coding>
|
||||
static inline const char* SingularParseMessageAuxImpl(PROTOBUF_TC_PARAM_DECL);
|
||||
template <typename TagType, bool group_coding>
|
||||
static inline const char* RepeatedParseMessageAuxImpl(PROTOBUF_TC_PARAM_DECL);
|
||||
|
||||
static inline PROTOBUF_ALWAYS_INLINE void SyncHasbits(
|
||||
MessageLite* msg, uint64_t hasbits, const TcParseTableBase* table) {
|
||||
const uint32_t has_bits_offset = table->has_bits_offset;
|
||||
if (has_bits_offset) {
|
||||
// Only the first 32 has-bits are updated. Nothing above those is stored,
|
||||
// but e.g. messages without has-bits update the upper bits.
|
||||
RefAt<uint32_t>(msg, has_bits_offset) = static_cast<uint32_t>(hasbits);
|
||||
}
|
||||
}
|
||||
|
||||
static const char* TagDispatch(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* ToTagDispatch(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* ToParseLoop(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* Error(PROTOBUF_TC_PARAM_DECL);
|
||||
|
||||
static const char* FastUnknownEnumFallback(PROTOBUF_TC_PARAM_DECL);
|
||||
|
||||
class ScopedArenaSwap;
|
||||
|
||||
template <class MessageBaseT, class UnknownFieldsT>
|
||||
static const char* GenericFallbackImpl(PROTOBUF_TC_PARAM_DECL) {
|
||||
#define CHK_(x) \
|
||||
if (PROTOBUF_PREDICT_FALSE(!(x))) return nullptr /* NOLINT */
|
||||
|
||||
SyncHasbits(msg, hasbits, table);
|
||||
CHK_(ptr);
|
||||
uint32_t tag = data.tag();
|
||||
if ((tag & 7) == WireFormatLite::WIRETYPE_END_GROUP || tag == 0) {
|
||||
ctx->SetLastTag(tag);
|
||||
return ptr;
|
||||
}
|
||||
uint32_t num = tag >> 3;
|
||||
if (table->extension_range_low <= num &&
|
||||
num <= table->extension_range_high) {
|
||||
return RefAt<ExtensionSet>(msg, table->extension_offset)
|
||||
.ParseField(tag, ptr,
|
||||
static_cast<const MessageBaseT*>(table->default_instance),
|
||||
&msg->_internal_metadata_, ctx);
|
||||
}
|
||||
return UnknownFieldParse(
|
||||
tag, msg->_internal_metadata_.mutable_unknown_fields<UnknownFieldsT>(),
|
||||
ptr, ctx);
|
||||
#undef CHK_
|
||||
}
|
||||
|
||||
// Note: `inline` is needed on template function declarations below to avoid
|
||||
// -Wattributes diagnostic in GCC.
|
||||
|
||||
// Implementations for fast fixed field parsing functions:
|
||||
template <typename LayoutType, typename TagType>
|
||||
static inline const char* SingularFixed(PROTOBUF_TC_PARAM_DECL);
|
||||
template <typename LayoutType, typename TagType>
|
||||
static inline const char* RepeatedFixed(PROTOBUF_TC_PARAM_DECL);
|
||||
template <typename LayoutType, typename TagType>
|
||||
static inline const char* PackedFixed(PROTOBUF_TC_PARAM_DECL);
|
||||
|
||||
// Implementations for fast varint field parsing functions:
|
||||
template <typename FieldType, typename TagType, bool zigzag = false>
|
||||
static inline const char* SingularVarint(PROTOBUF_TC_PARAM_DECL);
|
||||
template <typename FieldType, typename TagType, bool zigzag = false>
|
||||
static inline const char* RepeatedVarint(PROTOBUF_TC_PARAM_DECL);
|
||||
template <typename FieldType, typename TagType, bool zigzag = false>
|
||||
static inline const char* PackedVarint(PROTOBUF_TC_PARAM_DECL);
|
||||
|
||||
// Helper for ints > 127:
|
||||
template <typename FieldType, typename TagType, bool zigzag = false>
|
||||
static const char* SingularVarBigint(PROTOBUF_TC_PARAM_DECL);
|
||||
|
||||
// Implementations for fast enum field parsing functions:
|
||||
template <typename TagType, uint16_t xform_val>
|
||||
static inline const char* SingularEnum(PROTOBUF_TC_PARAM_DECL);
|
||||
template <typename TagType, uint16_t xform_val>
|
||||
static inline const char* RepeatedEnum(PROTOBUF_TC_PARAM_DECL);
|
||||
|
||||
// Implementations for fast string field parsing functions:
|
||||
enum Utf8Type { kNoUtf8 = 0, kUtf8 = 1, kUtf8ValidateOnly = 2 };
|
||||
template <typename TagType, Utf8Type utf8>
|
||||
static inline const char* SingularString(PROTOBUF_TC_PARAM_DECL);
|
||||
template <typename TagType, Utf8Type utf8>
|
||||
static inline const char* RepeatedString(PROTOBUF_TC_PARAM_DECL);
|
||||
|
||||
// Mini field lookup:
|
||||
static const TcParseTableBase::FieldEntry* FindFieldEntry(
|
||||
const TcParseTableBase* table, uint32_t field_num);
|
||||
static StringPiece MessageName(const TcParseTableBase* table);
|
||||
static StringPiece FieldName(const TcParseTableBase* table,
|
||||
const TcParseTableBase::FieldEntry*);
|
||||
static bool ChangeOneof(const TcParseTableBase* table,
|
||||
const TcParseTableBase::FieldEntry& entry,
|
||||
uint32_t field_num, ParseContext* ctx,
|
||||
MessageLite* msg);
|
||||
|
||||
// UTF-8 validation:
|
||||
static void ReportFastUtf8Error(uint32_t decoded_tag,
|
||||
const TcParseTableBase* table);
|
||||
static bool MpVerifyUtf8(StringPiece wire_bytes,
|
||||
const TcParseTableBase* table,
|
||||
const TcParseTableBase::FieldEntry& entry,
|
||||
uint16_t xform_val);
|
||||
|
||||
// For FindFieldEntry tests:
|
||||
friend class FindFieldEntryTest;
|
||||
static constexpr const uint32_t kMtSmallScanSize = 4;
|
||||
|
||||
// Mini parsing:
|
||||
static const char* MpVarint(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* MpRepeatedVarint(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* MpPackedVarint(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* MpFixed(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* MpRepeatedFixed(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* MpPackedFixed(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* MpString(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* MpRepeatedString(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* MpMessage(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* MpRepeatedMessage(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* MpMap(PROTOBUF_TC_PARAM_DECL);
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_GENERATED_MESSAGE_TCTABLE_IMPL_H__
|
||||
@@ -1,214 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
//
|
||||
// This file contains miscellaneous helper code used by generated code --
|
||||
// including lite types -- but which should not be used directly by users.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__
|
||||
#define GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <climits>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/once.h> // Add direct dep on port for pb.cc
|
||||
#include <google/protobuf/port.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
#include <google/protobuf/any.h>
|
||||
#include <google/protobuf/has_bits.h>
|
||||
#include <google/protobuf/implicit_weak_message.h>
|
||||
#include <google/protobuf/message_lite.h>
|
||||
#include <google/protobuf/repeated_field.h>
|
||||
#include <google/protobuf/wire_format_lite.h>
|
||||
#include <google/protobuf/stubs/casts.h>
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
#ifdef SWIG
|
||||
#error "You cannot SWIG proto headers"
|
||||
#endif
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
class Arena;
|
||||
class Message;
|
||||
|
||||
namespace io {
|
||||
class CodedInputStream;
|
||||
}
|
||||
|
||||
namespace internal {
|
||||
|
||||
template <typename To, typename From>
|
||||
inline To DownCast(From* f) {
|
||||
return PROTOBUF_NAMESPACE_ID::internal::down_cast<To>(f);
|
||||
}
|
||||
template <typename To, typename From>
|
||||
inline To DownCast(From& f) {
|
||||
return PROTOBUF_NAMESPACE_ID::internal::down_cast<To>(f);
|
||||
}
|
||||
|
||||
|
||||
// This fastpath inlines a single branch instead of having to make the
|
||||
// InitProtobufDefaults function call.
|
||||
// It also generates less inlined code than a function-scope static initializer.
|
||||
PROTOBUF_EXPORT extern std::atomic<bool> init_protobuf_defaults_state;
|
||||
PROTOBUF_EXPORT void InitProtobufDefaultsSlow();
|
||||
PROTOBUF_EXPORT inline void InitProtobufDefaults() {
|
||||
if (PROTOBUF_PREDICT_FALSE(
|
||||
!init_protobuf_defaults_state.load(std::memory_order_acquire))) {
|
||||
InitProtobufDefaultsSlow();
|
||||
}
|
||||
}
|
||||
|
||||
// This used by proto1
|
||||
PROTOBUF_EXPORT inline const std::string& GetEmptyString() {
|
||||
InitProtobufDefaults();
|
||||
return GetEmptyStringAlreadyInited();
|
||||
}
|
||||
|
||||
|
||||
// True if IsInitialized() is true for all elements of t. Type is expected
|
||||
// to be a RepeatedPtrField<some message type>. It's useful to have this
|
||||
// helper here to keep the protobuf compiler from ever having to emit loops in
|
||||
// IsInitialized() methods. We want the C++ compiler to inline this or not
|
||||
// as it sees fit.
|
||||
template <typename Msg>
|
||||
bool AllAreInitialized(const RepeatedPtrField<Msg>& t) {
|
||||
for (int i = t.size(); --i >= 0;) {
|
||||
if (!t.Get(i).IsInitialized()) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// "Weak" variant of AllAreInitialized, used to implement implicit weak fields.
|
||||
// This version operates on MessageLite to avoid introducing a dependency on the
|
||||
// concrete message type.
|
||||
template <class T>
|
||||
bool AllAreInitializedWeak(const RepeatedPtrField<T>& t) {
|
||||
for (int i = t.size(); --i >= 0;) {
|
||||
if (!reinterpret_cast<const RepeatedPtrFieldBase&>(t)
|
||||
.Get<ImplicitWeakTypeHandler<T> >(i)
|
||||
.IsInitialized()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool IsPresent(const void* base, uint32_t hasbit) {
|
||||
const uint32_t* has_bits_array = static_cast<const uint32_t*>(base);
|
||||
return (has_bits_array[hasbit / 32] & (1u << (hasbit & 31))) != 0;
|
||||
}
|
||||
|
||||
inline bool IsOneofPresent(const void* base, uint32_t offset, uint32_t tag) {
|
||||
const uint32_t* oneof = reinterpret_cast<const uint32_t*>(
|
||||
static_cast<const uint8_t*>(base) + offset);
|
||||
return *oneof == tag >> 3;
|
||||
}
|
||||
|
||||
typedef void (*SpecialSerializer)(const uint8_t* base, uint32_t offset,
|
||||
uint32_t tag, uint32_t has_offset,
|
||||
io::CodedOutputStream* output);
|
||||
|
||||
PROTOBUF_EXPORT void ExtensionSerializer(const MessageLite* extendee,
|
||||
const uint8_t* ptr, uint32_t offset,
|
||||
uint32_t tag, uint32_t has_offset,
|
||||
io::CodedOutputStream* output);
|
||||
PROTOBUF_EXPORT void UnknownFieldSerializerLite(const uint8_t* base,
|
||||
uint32_t offset, uint32_t tag,
|
||||
uint32_t has_offset,
|
||||
io::CodedOutputStream* output);
|
||||
|
||||
PROTOBUF_EXPORT MessageLite* DuplicateIfNonNullInternal(MessageLite* message);
|
||||
PROTOBUF_EXPORT MessageLite* GetOwnedMessageInternal(Arena* message_arena,
|
||||
MessageLite* submessage,
|
||||
Arena* submessage_arena);
|
||||
PROTOBUF_EXPORT void GenericSwap(MessageLite* m1, MessageLite* m2);
|
||||
// We specialize GenericSwap for non-lite messages to benefit from reflection.
|
||||
PROTOBUF_EXPORT void GenericSwap(Message* m1, Message* m2);
|
||||
|
||||
template <typename T>
|
||||
T* DuplicateIfNonNull(T* message) {
|
||||
// The casts must be reinterpret_cast<> because T might be a forward-declared
|
||||
// type that the compiler doesn't know is related to MessageLite.
|
||||
return reinterpret_cast<T*>(
|
||||
DuplicateIfNonNullInternal(reinterpret_cast<MessageLite*>(message)));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T* GetOwnedMessage(Arena* message_arena, T* submessage,
|
||||
Arena* submessage_arena) {
|
||||
// The casts must be reinterpret_cast<> because T might be a forward-declared
|
||||
// type that the compiler doesn't know is related to MessageLite.
|
||||
return reinterpret_cast<T*>(GetOwnedMessageInternal(
|
||||
message_arena, reinterpret_cast<MessageLite*>(submessage),
|
||||
submessage_arena));
|
||||
}
|
||||
|
||||
// Hide atomic from the public header and allow easy change to regular int
|
||||
// on platforms where the atomic might have a perf impact.
|
||||
class PROTOBUF_EXPORT CachedSize {
|
||||
public:
|
||||
int Get() const { return size_.load(std::memory_order_relaxed); }
|
||||
void Set(int size) { size_.store(size, std::memory_order_relaxed); }
|
||||
|
||||
private:
|
||||
std::atomic<int> size_{0};
|
||||
};
|
||||
|
||||
PROTOBUF_EXPORT void DestroyMessage(const void* message);
|
||||
PROTOBUF_EXPORT void DestroyString(const void* s);
|
||||
// Destroy (not delete) the message
|
||||
inline void OnShutdownDestroyMessage(const void* ptr) {
|
||||
OnShutdownRun(DestroyMessage, ptr);
|
||||
}
|
||||
// Destroy the string (call std::string destructor)
|
||||
inline void OnShutdownDestroyString(const std::string* ptr) {
|
||||
OnShutdownRun(DestroyString, ptr);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__
|
||||
@@ -1,117 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_HAS_BITS_H__
|
||||
#define GOOGLE_PROTOBUF_HAS_BITS_H__
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/port.h>
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
#ifdef SWIG
|
||||
#error "You cannot SWIG proto headers"
|
||||
#endif
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
template <size_t doublewords>
|
||||
class HasBits {
|
||||
public:
|
||||
PROTOBUF_NDEBUG_INLINE constexpr HasBits() : has_bits_{} {}
|
||||
|
||||
PROTOBUF_NDEBUG_INLINE void Clear() {
|
||||
memset(has_bits_, 0, sizeof(has_bits_));
|
||||
}
|
||||
|
||||
PROTOBUF_NDEBUG_INLINE uint32_t& operator[](int index) {
|
||||
return has_bits_[index];
|
||||
}
|
||||
|
||||
PROTOBUF_NDEBUG_INLINE const uint32_t& operator[](int index) const {
|
||||
return has_bits_[index];
|
||||
}
|
||||
|
||||
bool operator==(const HasBits<doublewords>& rhs) const {
|
||||
return memcmp(has_bits_, rhs.has_bits_, sizeof(has_bits_)) == 0;
|
||||
}
|
||||
|
||||
bool operator!=(const HasBits<doublewords>& rhs) const {
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
void Or(const HasBits<doublewords>& rhs) {
|
||||
for (size_t i = 0; i < doublewords; i++) has_bits_[i] |= rhs[i];
|
||||
}
|
||||
|
||||
bool empty() const;
|
||||
|
||||
private:
|
||||
uint32_t has_bits_[doublewords];
|
||||
};
|
||||
|
||||
template <>
|
||||
inline bool HasBits<1>::empty() const {
|
||||
return !has_bits_[0];
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool HasBits<2>::empty() const {
|
||||
return !(has_bits_[0] | has_bits_[1]);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool HasBits<3>::empty() const {
|
||||
return !(has_bits_[0] | has_bits_[1] | has_bits_[2]);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool HasBits<4>::empty() const {
|
||||
return !(has_bits_[0] | has_bits_[1] | has_bits_[2] | has_bits_[3]);
|
||||
}
|
||||
|
||||
template <size_t doublewords>
|
||||
inline bool HasBits<doublewords>::empty() const {
|
||||
for (size_t i = 0; i < doublewords; ++i) {
|
||||
if (has_bits_[i]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_HAS_BITS_H__
|
||||
@@ -1,213 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_IMPLICIT_WEAK_MESSAGE_H__
|
||||
#define GOOGLE_PROTOBUF_IMPLICIT_WEAK_MESSAGE_H__
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/arena.h>
|
||||
#include <google/protobuf/message_lite.h>
|
||||
#include <google/protobuf/repeated_field.h>
|
||||
|
||||
#ifdef SWIG
|
||||
#error "You cannot SWIG proto headers"
|
||||
#endif
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
// This file is logically internal-only and should only be used by protobuf
|
||||
// generated code.
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
// An implementation of MessageLite that treats all data as unknown. This type
|
||||
// acts as a placeholder for an implicit weak field in the case where the true
|
||||
// message type does not get linked into the binary.
|
||||
class PROTOBUF_EXPORT ImplicitWeakMessage : public MessageLite {
|
||||
public:
|
||||
ImplicitWeakMessage() : data_(new std::string) {}
|
||||
explicit constexpr ImplicitWeakMessage(ConstantInitialized)
|
||||
: data_(nullptr) {}
|
||||
explicit ImplicitWeakMessage(Arena* arena)
|
||||
: MessageLite(arena), data_(new std::string) {}
|
||||
|
||||
~ImplicitWeakMessage() override {
|
||||
// data_ will be null in the default instance, but we can safely call delete
|
||||
// here because the default instance will never be destroyed.
|
||||
delete data_;
|
||||
}
|
||||
|
||||
static const ImplicitWeakMessage* default_instance();
|
||||
|
||||
std::string GetTypeName() const override { return ""; }
|
||||
|
||||
MessageLite* New(Arena* arena) const override {
|
||||
return Arena::CreateMessage<ImplicitWeakMessage>(arena);
|
||||
}
|
||||
|
||||
void Clear() override { data_->clear(); }
|
||||
|
||||
bool IsInitialized() const override { return true; }
|
||||
|
||||
void CheckTypeAndMergeFrom(const MessageLite& other) override {
|
||||
const std::string* other_data =
|
||||
static_cast<const ImplicitWeakMessage&>(other).data_;
|
||||
if (other_data != nullptr) {
|
||||
data_->append(*other_data);
|
||||
}
|
||||
}
|
||||
|
||||
const char* _InternalParse(const char* ptr, ParseContext* ctx) final;
|
||||
|
||||
size_t ByteSizeLong() const override {
|
||||
return data_ == nullptr ? 0 : data_->size();
|
||||
}
|
||||
|
||||
uint8_t* _InternalSerialize(uint8_t* target,
|
||||
io::EpsCopyOutputStream* stream) const final {
|
||||
if (data_ == nullptr) {
|
||||
return target;
|
||||
}
|
||||
return stream->WriteRaw(data_->data(), data_->size(),
|
||||
target);
|
||||
}
|
||||
|
||||
int GetCachedSize() const override {
|
||||
return data_ == nullptr ? 0 : static_cast<int>(data_->size());
|
||||
}
|
||||
|
||||
typedef void InternalArenaConstructable_;
|
||||
|
||||
private:
|
||||
// This std::string is allocated on the heap, but we use a raw pointer so that
|
||||
// the default instance can be constant-initialized. In the const methods, we
|
||||
// have to handle the possibility of data_ being null.
|
||||
std::string* data_;
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImplicitWeakMessage);
|
||||
};
|
||||
|
||||
struct ImplicitWeakMessageDefaultType;
|
||||
extern ImplicitWeakMessageDefaultType implicit_weak_message_default_instance;
|
||||
|
||||
// A type handler for use with implicit weak repeated message fields.
|
||||
template <typename ImplicitWeakType>
|
||||
class ImplicitWeakTypeHandler {
|
||||
public:
|
||||
typedef MessageLite Type;
|
||||
static constexpr bool Moveable = false;
|
||||
|
||||
static inline MessageLite* NewFromPrototype(const MessageLite* prototype,
|
||||
Arena* arena = nullptr) {
|
||||
return prototype->New(arena);
|
||||
}
|
||||
|
||||
static inline void Delete(MessageLite* value, Arena* arena) {
|
||||
if (arena == nullptr) {
|
||||
delete value;
|
||||
}
|
||||
}
|
||||
static inline Arena* GetArena(MessageLite* value) {
|
||||
return value->GetArena();
|
||||
}
|
||||
static inline void Clear(MessageLite* value) { value->Clear(); }
|
||||
static void Merge(const MessageLite& from, MessageLite* to) {
|
||||
to->CheckTypeAndMergeFrom(from);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
template <typename T>
|
||||
struct WeakRepeatedPtrField {
|
||||
using TypeHandler = internal::ImplicitWeakTypeHandler<T>;
|
||||
constexpr WeakRepeatedPtrField() : weak() {}
|
||||
explicit WeakRepeatedPtrField(Arena* arena) : weak(arena) {}
|
||||
~WeakRepeatedPtrField() { weak.template Destroy<TypeHandler>(); }
|
||||
|
||||
typedef internal::RepeatedPtrIterator<MessageLite> iterator;
|
||||
typedef internal::RepeatedPtrIterator<const MessageLite> const_iterator;
|
||||
typedef internal::RepeatedPtrOverPtrsIterator<MessageLite*, void*>
|
||||
pointer_iterator;
|
||||
typedef internal::RepeatedPtrOverPtrsIterator<const MessageLite* const,
|
||||
const void* const>
|
||||
const_pointer_iterator;
|
||||
|
||||
iterator begin() { return iterator(base().raw_data()); }
|
||||
const_iterator begin() const { return iterator(base().raw_data()); }
|
||||
const_iterator cbegin() const { return begin(); }
|
||||
iterator end() { return begin() + base().size(); }
|
||||
const_iterator end() const { return begin() + base().size(); }
|
||||
const_iterator cend() const { return end(); }
|
||||
pointer_iterator pointer_begin() {
|
||||
return pointer_iterator(base().raw_mutable_data());
|
||||
}
|
||||
const_pointer_iterator pointer_begin() const {
|
||||
return const_pointer_iterator(base().raw_mutable_data());
|
||||
}
|
||||
pointer_iterator pointer_end() {
|
||||
return pointer_iterator(base().raw_mutable_data() + base().size());
|
||||
}
|
||||
const_pointer_iterator pointer_end() const {
|
||||
return const_pointer_iterator(base().raw_mutable_data() + base().size());
|
||||
}
|
||||
|
||||
MessageLite* AddWeak(const MessageLite* prototype) {
|
||||
return base().AddWeak(prototype);
|
||||
}
|
||||
T* Add() { return weak.Add(); }
|
||||
void Clear() { base().template Clear<TypeHandler>(); }
|
||||
void MergeFrom(const WeakRepeatedPtrField& other) {
|
||||
base().template MergeFrom<TypeHandler>(other.base());
|
||||
}
|
||||
void InternalSwap(WeakRepeatedPtrField* other) {
|
||||
base().InternalSwap(&other->base());
|
||||
}
|
||||
|
||||
const internal::RepeatedPtrFieldBase& base() const { return weak; }
|
||||
internal::RepeatedPtrFieldBase& base() { return weak; }
|
||||
// Union disables running the destructor. Which would create a strong link.
|
||||
// Instead we explicitly destroy the underlying base through the virtual
|
||||
// destructor.
|
||||
union {
|
||||
RepeatedPtrField<T> weak;
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_IMPLICIT_WEAK_MESSAGE_H__
|
||||
@@ -1,532 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_INLINED_STRING_FIELD_H__
|
||||
#define GOOGLE_PROTOBUF_INLINED_STRING_FIELD_H__
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include <google/protobuf/stubs/logging.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/port.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
#include <google/protobuf/arenastring.h>
|
||||
#include <google/protobuf/message_lite.h>
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
#ifdef SWIG
|
||||
#error "You cannot SWIG proto headers"
|
||||
#endif
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
class Arena;
|
||||
|
||||
namespace internal {
|
||||
|
||||
// InlinedStringField wraps a std::string instance and exposes an API similar to
|
||||
// ArenaStringPtr's wrapping of a std::string* instance.
|
||||
//
|
||||
// default_value parameters are taken for consistency with ArenaStringPtr, but
|
||||
// are not used for most methods. With inlining, these should be removed from
|
||||
// the generated binary.
|
||||
//
|
||||
// InlinedStringField has a donating mechanism that allows string buffer
|
||||
// allocated on arena. A string is donated means both the string container and
|
||||
// the data buffer are on arena. The donating mechanism here is similar to the
|
||||
// one in ArenaStringPtr with some differences:
|
||||
//
|
||||
// When an InlinedStringField is constructed, the donating state is true. This
|
||||
// is because the string container is directly stored in the message on the
|
||||
// arena:
|
||||
//
|
||||
// Construction: donated=true
|
||||
// Arena:
|
||||
// +-----------------------+
|
||||
// |Message foo: |
|
||||
// | +-------------------+ |
|
||||
// | |InlinedStringField:| |
|
||||
// | | +-----+ | |
|
||||
// | | | | | | | |
|
||||
// | | +-----+ | |
|
||||
// | +-------------------+ |
|
||||
// +-----------------------+
|
||||
//
|
||||
// When lvalue Set is called, the donating state is still true. String data will
|
||||
// be allocated on the arena:
|
||||
//
|
||||
// Lvalue Set: donated=true
|
||||
// Arena:
|
||||
// +-----------------------+
|
||||
// |Message foo: |
|
||||
// | +-------------------+ |
|
||||
// | |InlinedStringField:| |
|
||||
// | | +-----+ | |
|
||||
// | | | | | | | |
|
||||
// | | +|----+ | |
|
||||
// | +--|----------------+ |
|
||||
// | V |
|
||||
// | +----------------+ |
|
||||
// | |'f','o','o',... | |
|
||||
// | +----------------+ |
|
||||
// +-----------------------+
|
||||
//
|
||||
// Some operations will undonate a donated string, including: Mutable,
|
||||
// SetAllocated, Rvalue Set, and Swap with a non-donated string.
|
||||
//
|
||||
// For more details of the donating states transitions, go/pd-inlined-string.
|
||||
class PROTOBUF_EXPORT InlinedStringField {
|
||||
public:
|
||||
InlinedStringField() { Init(); }
|
||||
inline void Init() { new (get_mutable()) std::string(); }
|
||||
// Add the dummy parameter just to make InlinedStringField(nullptr)
|
||||
// unambiguous.
|
||||
constexpr InlinedStringField(
|
||||
const ExplicitlyConstructed<std::string>* /*default_value*/,
|
||||
bool /*dummy*/)
|
||||
: value_{} {}
|
||||
explicit InlinedStringField(const std::string& default_value);
|
||||
explicit InlinedStringField(Arena* arena);
|
||||
~InlinedStringField() { Destruct(); }
|
||||
|
||||
// Lvalue Set. To save space, we pack the donating states of multiple
|
||||
// InlinedStringFields into an uint32_t `donating_states`. The `mask`
|
||||
// indicates the position of the bit for this InlinedStringField. `donated` is
|
||||
// whether this field is donated.
|
||||
//
|
||||
// The caller should guarantee that:
|
||||
//
|
||||
// `donated == ((donating_states & ~mask) != 0)`
|
||||
//
|
||||
// This method never changes the `donating_states`.
|
||||
void Set(ConstStringParam value, Arena* arena, bool donated,
|
||||
uint32_t* donating_states, uint32_t mask, MessageLite* msg);
|
||||
|
||||
// Rvalue Set. If this field is donated, this method will undonate this field
|
||||
// by mutating the `donating_states` according to `mask`.
|
||||
void Set(std::string&& value, Arena* arena, bool donated,
|
||||
uint32_t* donating_states, uint32_t mask, MessageLite* msg);
|
||||
|
||||
void Set(const char* str, ::google::protobuf::Arena* arena, bool donated,
|
||||
uint32_t* donating_states, uint32_t mask, MessageLite* msg);
|
||||
|
||||
void Set(const char* str, size_t size, ::google::protobuf::Arena* arena, bool donated,
|
||||
uint32_t* donating_states, uint32_t mask, MessageLite* msg);
|
||||
|
||||
template <typename RefWrappedType>
|
||||
void Set(std::reference_wrapper<RefWrappedType> const_string_ref,
|
||||
::google::protobuf::Arena* arena, bool donated, uint32_t* donating_states,
|
||||
uint32_t mask, MessageLite* msg);
|
||||
|
||||
void SetBytes(ConstStringParam value, Arena* arena, bool donated,
|
||||
uint32_t* donating_states, uint32_t mask, MessageLite* msg);
|
||||
|
||||
void SetBytes(std::string&& value, Arena* arena, bool donated,
|
||||
uint32_t* donating_states, uint32_t mask, MessageLite* msg);
|
||||
|
||||
void SetBytes(const char* str, ::google::protobuf::Arena* arena, bool donated,
|
||||
uint32_t* donating_states, uint32_t mask, MessageLite* msg);
|
||||
|
||||
void SetBytes(const void* p, size_t size, ::google::protobuf::Arena* arena,
|
||||
bool donated, uint32_t* donating_states, uint32_t mask,
|
||||
MessageLite* msg);
|
||||
|
||||
template <typename RefWrappedType>
|
||||
void SetBytes(std::reference_wrapper<RefWrappedType> const_string_ref,
|
||||
::google::protobuf::Arena* arena, bool donated, uint32_t* donating_states,
|
||||
uint32_t mask, MessageLite* msg);
|
||||
|
||||
PROTOBUF_NDEBUG_INLINE void SetNoArena(StringPiece value);
|
||||
PROTOBUF_NDEBUG_INLINE void SetNoArena(std::string&& value);
|
||||
|
||||
// Basic accessors.
|
||||
PROTOBUF_NDEBUG_INLINE const std::string& Get() const { return GetNoArena(); }
|
||||
PROTOBUF_NDEBUG_INLINE const std::string& GetNoArena() const;
|
||||
|
||||
// Mutable returns a std::string* instance that is heap-allocated. If this
|
||||
// field is donated, this method undonates this field by mutating the
|
||||
// `donating_states` according to `mask`, and copies the content of the
|
||||
// original string to the returning string.
|
||||
std::string* Mutable(Arena* arena, bool donated, uint32_t* donating_states,
|
||||
uint32_t mask, MessageLite* msg);
|
||||
std::string* Mutable(const LazyString& default_value, Arena* arena,
|
||||
bool donated, uint32_t* donating_states, uint32_t mask,
|
||||
MessageLite* msg);
|
||||
|
||||
// Mutable(nullptr_t) is an overload to explicitly support Mutable(nullptr)
|
||||
// calls used by the internal parser logic. This provides API equivalence with
|
||||
// ArenaStringPtr, while still protecting against calls with arena pointers.
|
||||
std::string* Mutable(std::nullptr_t);
|
||||
std::string* MutableNoCopy(std::nullptr_t);
|
||||
|
||||
// Takes a std::string that is heap-allocated, and takes ownership. The
|
||||
// std::string's destructor is registered with the arena. Used to implement
|
||||
// set_allocated_<field> in generated classes.
|
||||
//
|
||||
// If this field is donated, this method undonates this field by mutating the
|
||||
// `donating_states` according to `mask`.
|
||||
void SetAllocated(const std::string* default_value, std::string* value,
|
||||
Arena* arena, bool donated, uint32_t* donating_states,
|
||||
uint32_t mask, MessageLite* msg);
|
||||
|
||||
void SetAllocatedNoArena(const std::string* default_value,
|
||||
std::string* value);
|
||||
|
||||
// Release returns a std::string* instance that is heap-allocated and is not
|
||||
// Own()'d by any arena. If the field is not set, this returns nullptr. The
|
||||
// caller retains ownership. Clears this field back to nullptr state. Used to
|
||||
// implement release_<field>() methods on generated classes.
|
||||
PROTOBUF_NODISCARD std::string* Release(Arena* arena, bool donated);
|
||||
PROTOBUF_NODISCARD std::string* Release();
|
||||
|
||||
// --------------------------------------------------------
|
||||
// Below functions will be removed in subsequent code change
|
||||
// --------------------------------------------------------
|
||||
#ifdef DEPRECATED_METHODS_TO_BE_DELETED
|
||||
PROTOBUF_NODISCARD std::string* Release(const std::string*, Arena* arena,
|
||||
bool donated) {
|
||||
return Release(arena, donated);
|
||||
}
|
||||
|
||||
PROTOBUF_NODISCARD std::string* ReleaseNonDefault(const std::string*,
|
||||
Arena* arena) {
|
||||
return Release();
|
||||
}
|
||||
|
||||
std::string* ReleaseNonDefaultNoArena(const std::string* default_value) {
|
||||
return Release();
|
||||
}
|
||||
|
||||
void Set(const std::string*, ConstStringParam value, Arena* arena,
|
||||
bool donated, uint32_t* donating_states, uint32_t mask,
|
||||
MessageLite* msg) {
|
||||
Set(value, arena, donated, donating_states, mask, msg);
|
||||
}
|
||||
|
||||
void Set(const std::string*, std::string&& value, Arena* arena, bool donated,
|
||||
uint32_t* donating_states, uint32_t mask, MessageLite* msg) {
|
||||
Set(std::move(value), arena, donated, donating_states, mask, msg);
|
||||
}
|
||||
|
||||
|
||||
template <typename FirstParam>
|
||||
void Set(FirstParam, const char* str, ::google::protobuf::Arena* arena, bool donated,
|
||||
uint32_t* donating_states, uint32_t mask, MessageLite* msg) {
|
||||
Set(str, arena, donated, donating_states, mask, msg);
|
||||
}
|
||||
|
||||
template <typename FirstParam>
|
||||
void Set(FirstParam p1, const char* str, size_t size, ::google::protobuf::Arena* arena,
|
||||
bool donated, uint32_t* donating_states, uint32_t mask,
|
||||
MessageLite* msg) {
|
||||
Set(str, size, arena, donated, donating_states, mask, msg);
|
||||
}
|
||||
|
||||
template <typename FirstParam, typename RefWrappedType>
|
||||
void Set(FirstParam p1,
|
||||
std::reference_wrapper<RefWrappedType> const_string_ref,
|
||||
::google::protobuf::Arena* arena, bool donated, uint32_t* donating_states,
|
||||
uint32_t mask, MessageLite* msg) {
|
||||
Set(const_string_ref, arena, donated, donating_states, mask, msg);
|
||||
}
|
||||
|
||||
void SetBytes(const std::string*, ConstStringParam value, Arena* arena,
|
||||
bool donated, uint32_t* donating_states, uint32_t mask,
|
||||
MessageLite* msg) {
|
||||
Set(value, arena, donated, donating_states, mask, msg);
|
||||
}
|
||||
|
||||
|
||||
void SetBytes(const std::string*, std::string&& value, Arena* arena,
|
||||
bool donated, uint32_t* donating_states, uint32_t mask,
|
||||
MessageLite* msg) {
|
||||
Set(std::move(value), arena, donated, donating_states, mask, msg);
|
||||
}
|
||||
|
||||
template <typename FirstParam>
|
||||
void SetBytes(FirstParam p1, const char* str, ::google::protobuf::Arena* arena,
|
||||
bool donated, uint32_t* donating_states, uint32_t mask,
|
||||
MessageLite* msg) {
|
||||
SetBytes(str, arena, donated, donating_states, mask, msg);
|
||||
}
|
||||
|
||||
template <typename FirstParam>
|
||||
void SetBytes(FirstParam p1, const void* p, size_t size,
|
||||
::google::protobuf::Arena* arena, bool donated, uint32_t* donating_states,
|
||||
uint32_t mask, MessageLite* msg) {
|
||||
SetBytes(p, size, arena, donated, donating_states, mask, msg);
|
||||
}
|
||||
|
||||
template <typename FirstParam, typename RefWrappedType>
|
||||
void SetBytes(FirstParam p1,
|
||||
std::reference_wrapper<RefWrappedType> const_string_ref,
|
||||
::google::protobuf::Arena* arena, bool donated, uint32_t* donating_states,
|
||||
uint32_t mask, MessageLite* msg) {
|
||||
SetBytes(const_string_ref.get(), arena, donated, donating_states, mask,
|
||||
msg);
|
||||
}
|
||||
|
||||
void SetNoArena(const std::string*, StringPiece value) {
|
||||
SetNoArena(value);
|
||||
}
|
||||
void SetNoArena(const std::string*, std::string&& value) {
|
||||
SetNoArena(std::move(value));
|
||||
}
|
||||
|
||||
std::string* Mutable(ArenaStringPtr::EmptyDefault, Arena* arena, bool donated,
|
||||
uint32_t* donating_states, uint32_t mask,
|
||||
MessageLite* msg) {
|
||||
return Mutable(arena, donated, donating_states, mask, msg);
|
||||
}
|
||||
|
||||
PROTOBUF_NDEBUG_INLINE std::string* MutableNoArenaNoDefault(
|
||||
const std::string* /*default_value*/) {
|
||||
return MutableNoCopy(nullptr);
|
||||
}
|
||||
|
||||
#endif // DEPRECATED_METHODS_TO_BE_DELETED
|
||||
|
||||
// Arena-safety semantics: this is guarded by the logic in
|
||||
// Swap()/UnsafeArenaSwap() at the message level, so this method is
|
||||
// 'unsafe' if called directly.
|
||||
inline PROTOBUF_NDEBUG_INLINE static void InternalSwap(
|
||||
InlinedStringField* lhs, Arena* lhs_arena, bool lhs_arena_dtor_registered,
|
||||
MessageLite* lhs_msg, //
|
||||
InlinedStringField* rhs, Arena* rhs_arena, bool rhs_arena_dtor_registered,
|
||||
MessageLite* rhs_msg);
|
||||
|
||||
// Frees storage (if not on an arena).
|
||||
PROTOBUF_NDEBUG_INLINE void Destroy(const std::string* default_value,
|
||||
Arena* arena) {
|
||||
if (arena == nullptr) {
|
||||
DestroyNoArena(default_value);
|
||||
}
|
||||
}
|
||||
PROTOBUF_NDEBUG_INLINE void DestroyNoArena(const std::string* default_value);
|
||||
|
||||
// Clears content, but keeps allocated std::string, to avoid the overhead of
|
||||
// heap operations. After this returns, the content (as seen by the user) will
|
||||
// always be the empty std::string.
|
||||
PROTOBUF_NDEBUG_INLINE void ClearToEmpty() { ClearNonDefaultToEmpty(); }
|
||||
PROTOBUF_NDEBUG_INLINE void ClearNonDefaultToEmpty() {
|
||||
get_mutable()->clear();
|
||||
}
|
||||
|
||||
// Clears content, but keeps allocated std::string if arena != nullptr, to
|
||||
// avoid the overhead of heap operations. After this returns, the content (as
|
||||
// seen by the user) will always be equal to |default_value|.
|
||||
void ClearToDefault(const LazyString& default_value, Arena* arena,
|
||||
bool donated);
|
||||
|
||||
// Generated code / reflection only! Returns a mutable pointer to the string.
|
||||
PROTOBUF_NDEBUG_INLINE std::string* UnsafeMutablePointer();
|
||||
|
||||
// InlinedStringField doesn't have things like the `default_value` pointer in
|
||||
// ArenaStringPtr.
|
||||
static constexpr bool IsDefault() { return false; }
|
||||
static constexpr bool IsDefault(const std::string*) { return false; }
|
||||
|
||||
private:
|
||||
void Destruct() { get_mutable()->~basic_string(); }
|
||||
|
||||
PROTOBUF_NDEBUG_INLINE std::string* get_mutable();
|
||||
PROTOBUF_NDEBUG_INLINE const std::string* get_const() const;
|
||||
|
||||
alignas(std::string) char value_[sizeof(std::string)];
|
||||
|
||||
std::string* MutableSlow(::google::protobuf::Arena* arena, bool donated,
|
||||
uint32_t* donating_states, uint32_t mask,
|
||||
MessageLite* msg);
|
||||
|
||||
|
||||
// When constructed in an Arena, we want our destructor to be skipped.
|
||||
friend class ::google::protobuf::Arena;
|
||||
typedef void InternalArenaConstructable_;
|
||||
typedef void DestructorSkippable_;
|
||||
};
|
||||
|
||||
inline std::string* InlinedStringField::get_mutable() {
|
||||
return reinterpret_cast<std::string*>(&value_);
|
||||
}
|
||||
|
||||
inline const std::string* InlinedStringField::get_const() const {
|
||||
return reinterpret_cast<const std::string*>(&value_);
|
||||
}
|
||||
|
||||
inline InlinedStringField::InlinedStringField(
|
||||
const std::string& default_value) {
|
||||
new (get_mutable()) std::string(default_value);
|
||||
}
|
||||
|
||||
|
||||
inline InlinedStringField::InlinedStringField(Arena* /*arena*/) { Init(); }
|
||||
|
||||
inline const std::string& InlinedStringField::GetNoArena() const {
|
||||
return *get_const();
|
||||
}
|
||||
|
||||
inline void InlinedStringField::SetAllocatedNoArena(
|
||||
const std::string* /*default_value*/, std::string* value) {
|
||||
if (value == nullptr) {
|
||||
// Currently, inlined string field can't have non empty default.
|
||||
get_mutable()->clear();
|
||||
} else {
|
||||
get_mutable()->assign(std::move(*value));
|
||||
delete value;
|
||||
}
|
||||
}
|
||||
|
||||
inline void InlinedStringField::DestroyNoArena(const std::string*) {
|
||||
// This is invoked from the generated message's ArenaDtor, which is used to
|
||||
// clean up objects not allocated on the Arena.
|
||||
this->~InlinedStringField();
|
||||
}
|
||||
|
||||
inline void InlinedStringField::SetNoArena(StringPiece value) {
|
||||
get_mutable()->assign(value.data(), value.length());
|
||||
}
|
||||
|
||||
inline void InlinedStringField::SetNoArena(std::string&& value) {
|
||||
get_mutable()->assign(std::move(value));
|
||||
}
|
||||
|
||||
// Caller should make sure rhs_arena allocated rhs, and lhs_arena allocated lhs.
|
||||
inline PROTOBUF_NDEBUG_INLINE void InlinedStringField::InternalSwap(
|
||||
InlinedStringField* lhs, Arena* lhs_arena, bool lhs_arena_dtor_registered,
|
||||
MessageLite* lhs_msg, //
|
||||
InlinedStringField* rhs, Arena* rhs_arena, bool rhs_arena_dtor_registered,
|
||||
MessageLite* rhs_msg) {
|
||||
#if GOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE
|
||||
lhs->get_mutable()->swap(*rhs->get_mutable());
|
||||
if (!lhs_arena_dtor_registered && rhs_arena_dtor_registered) {
|
||||
lhs_msg->OnDemandRegisterArenaDtor(lhs_arena);
|
||||
} else if (lhs_arena_dtor_registered && !rhs_arena_dtor_registered) {
|
||||
rhs_msg->OnDemandRegisterArenaDtor(rhs_arena);
|
||||
}
|
||||
#else
|
||||
(void)lhs_arena;
|
||||
(void)rhs_arena;
|
||||
(void)lhs_arena_dtor_registered;
|
||||
(void)rhs_arena_dtor_registered;
|
||||
(void)lhs_msg;
|
||||
(void)rhs_msg;
|
||||
lhs->get_mutable()->swap(*rhs->get_mutable());
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void InlinedStringField::Set(ConstStringParam value, Arena* arena,
|
||||
bool donated, uint32_t* /*donating_states*/,
|
||||
uint32_t /*mask*/, MessageLite* /*msg*/) {
|
||||
(void)arena;
|
||||
(void)donated;
|
||||
SetNoArena(value);
|
||||
}
|
||||
|
||||
inline void InlinedStringField::Set(const char* str, ::google::protobuf::Arena* arena,
|
||||
bool donated, uint32_t* donating_states,
|
||||
uint32_t mask, MessageLite* msg) {
|
||||
Set(ConstStringParam(str), arena, donated, donating_states, mask, msg);
|
||||
}
|
||||
|
||||
inline void InlinedStringField::Set(const char* str, size_t size,
|
||||
::google::protobuf::Arena* arena, bool donated,
|
||||
uint32_t* donating_states, uint32_t mask,
|
||||
MessageLite* msg) {
|
||||
Set(ConstStringParam{str, size}, arena, donated, donating_states, mask, msg);
|
||||
}
|
||||
|
||||
inline void InlinedStringField::SetBytes(ConstStringParam value, Arena* arena,
|
||||
bool donated,
|
||||
uint32_t* donating_states,
|
||||
uint32_t mask, MessageLite* msg) {
|
||||
Set(value, arena, donated, donating_states, mask, msg);
|
||||
}
|
||||
|
||||
inline void InlinedStringField::SetBytes(std::string&& value, Arena* arena,
|
||||
bool donated,
|
||||
uint32_t* donating_states,
|
||||
uint32_t mask, MessageLite* msg) {
|
||||
Set(std::move(value), arena, donated, donating_states, mask, msg);
|
||||
}
|
||||
|
||||
inline void InlinedStringField::SetBytes(const char* str,
|
||||
::google::protobuf::Arena* arena, bool donated,
|
||||
uint32_t* donating_states,
|
||||
uint32_t mask, MessageLite* msg) {
|
||||
Set(str, arena, donated, donating_states, mask, msg);
|
||||
}
|
||||
|
||||
inline void InlinedStringField::SetBytes(const void* p, size_t size,
|
||||
::google::protobuf::Arena* arena, bool donated,
|
||||
uint32_t* donating_states,
|
||||
uint32_t mask, MessageLite* msg) {
|
||||
Set(static_cast<const char*>(p), size, arena, donated, donating_states, mask,
|
||||
msg);
|
||||
}
|
||||
|
||||
template <typename RefWrappedType>
|
||||
inline void InlinedStringField::Set(
|
||||
std::reference_wrapper<RefWrappedType> const_string_ref,
|
||||
::google::protobuf::Arena* arena, bool donated, uint32_t* donating_states,
|
||||
uint32_t mask, MessageLite* msg) {
|
||||
Set(const_string_ref.get(), arena, donated, donating_states, mask, msg);
|
||||
}
|
||||
|
||||
template <typename RefWrappedType>
|
||||
inline void InlinedStringField::SetBytes(
|
||||
std::reference_wrapper<RefWrappedType> const_string_ref,
|
||||
::google::protobuf::Arena* arena, bool donated, uint32_t* donating_states,
|
||||
uint32_t mask, MessageLite* msg) {
|
||||
Set(const_string_ref.get(), arena, donated, donating_states, mask, msg);
|
||||
}
|
||||
|
||||
inline std::string* InlinedStringField::UnsafeMutablePointer() {
|
||||
return get_mutable();
|
||||
}
|
||||
|
||||
inline std::string* InlinedStringField::Mutable(std::nullptr_t) {
|
||||
return get_mutable();
|
||||
}
|
||||
|
||||
inline std::string* InlinedStringField::MutableNoCopy(std::nullptr_t) {
|
||||
return get_mutable();
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_INLINED_STRING_FIELD_H__
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,205 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: brianolson@google.com (Brian Olson)
|
||||
//
|
||||
// This file contains the definition for classes GzipInputStream and
|
||||
// GzipOutputStream.
|
||||
//
|
||||
// GzipInputStream decompresses data from an underlying
|
||||
// ZeroCopyInputStream and provides the decompressed data as a
|
||||
// ZeroCopyInputStream.
|
||||
//
|
||||
// GzipOutputStream is an ZeroCopyOutputStream that compresses data to
|
||||
// an underlying ZeroCopyOutputStream.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_IO_GZIP_STREAM_H__
|
||||
#define GOOGLE_PROTOBUF_IO_GZIP_STREAM_H__
|
||||
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/io/zero_copy_stream.h>
|
||||
#include <google/protobuf/port.h>
|
||||
#include "zlib.h"
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace io {
|
||||
|
||||
// A ZeroCopyInputStream that reads compressed data through zlib
|
||||
class PROTOBUF_EXPORT GzipInputStream PROTOBUF_FUTURE_FINAL
|
||||
: public ZeroCopyInputStream {
|
||||
public:
|
||||
// Format key for constructor
|
||||
enum Format {
|
||||
// zlib will autodetect gzip header or deflate stream
|
||||
AUTO = 0,
|
||||
|
||||
// GZIP streams have some extra header data for file attributes.
|
||||
GZIP = 1,
|
||||
|
||||
// Simpler zlib stream format.
|
||||
ZLIB = 2,
|
||||
};
|
||||
|
||||
// buffer_size and format may be -1 for default of 64kB and GZIP format
|
||||
explicit GzipInputStream(ZeroCopyInputStream* sub_stream,
|
||||
Format format = AUTO, int buffer_size = -1);
|
||||
virtual ~GzipInputStream();
|
||||
|
||||
// Return last error message or NULL if no error.
|
||||
inline const char* ZlibErrorMessage() const { return zcontext_.msg; }
|
||||
inline int ZlibErrorCode() const { return zerror_; }
|
||||
|
||||
// implements ZeroCopyInputStream ----------------------------------
|
||||
bool Next(const void** data, int* size) override;
|
||||
void BackUp(int count) override;
|
||||
bool Skip(int count) override;
|
||||
int64_t ByteCount() const override;
|
||||
|
||||
private:
|
||||
Format format_;
|
||||
|
||||
ZeroCopyInputStream* sub_stream_;
|
||||
|
||||
z_stream zcontext_;
|
||||
int zerror_;
|
||||
|
||||
void* output_buffer_;
|
||||
void* output_position_;
|
||||
size_t output_buffer_length_;
|
||||
int64_t byte_count_;
|
||||
|
||||
int Inflate(int flush);
|
||||
void DoNextOutput(const void** data, int* size);
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GzipInputStream);
|
||||
};
|
||||
|
||||
class PROTOBUF_EXPORT GzipOutputStream PROTOBUF_FUTURE_FINAL
|
||||
: public ZeroCopyOutputStream {
|
||||
public:
|
||||
// Format key for constructor
|
||||
enum Format {
|
||||
// GZIP streams have some extra header data for file attributes.
|
||||
GZIP = 1,
|
||||
|
||||
// Simpler zlib stream format.
|
||||
ZLIB = 2,
|
||||
};
|
||||
|
||||
struct PROTOBUF_EXPORT Options {
|
||||
// Defaults to GZIP.
|
||||
Format format;
|
||||
|
||||
// What size buffer to use internally. Defaults to 64kB.
|
||||
int buffer_size;
|
||||
|
||||
// A number between 0 and 9, where 0 is no compression and 9 is best
|
||||
// compression. Defaults to Z_DEFAULT_COMPRESSION (see zlib.h).
|
||||
int compression_level;
|
||||
|
||||
// Defaults to Z_DEFAULT_STRATEGY. Can also be set to Z_FILTERED,
|
||||
// Z_HUFFMAN_ONLY, or Z_RLE. See the documentation for deflateInit2 in
|
||||
// zlib.h for definitions of these constants.
|
||||
int compression_strategy;
|
||||
|
||||
Options(); // Initializes with default values.
|
||||
};
|
||||
|
||||
// Create a GzipOutputStream with default options.
|
||||
explicit GzipOutputStream(ZeroCopyOutputStream* sub_stream);
|
||||
|
||||
// Create a GzipOutputStream with the given options.
|
||||
GzipOutputStream(ZeroCopyOutputStream* sub_stream, const Options& options);
|
||||
|
||||
virtual ~GzipOutputStream();
|
||||
|
||||
// Return last error message or NULL if no error.
|
||||
inline const char* ZlibErrorMessage() const { return zcontext_.msg; }
|
||||
inline int ZlibErrorCode() const { return zerror_; }
|
||||
|
||||
// Flushes data written so far to zipped data in the underlying stream.
|
||||
// It is the caller's responsibility to flush the underlying stream if
|
||||
// necessary.
|
||||
// Compression may be less efficient stopping and starting around flushes.
|
||||
// Returns true if no error.
|
||||
//
|
||||
// Please ensure that block size is > 6. Here is an excerpt from the zlib
|
||||
// doc that explains why:
|
||||
//
|
||||
// In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that avail_out
|
||||
// is greater than six to avoid repeated flush markers due to
|
||||
// avail_out == 0 on return.
|
||||
bool Flush();
|
||||
|
||||
// Writes out all data and closes the gzip stream.
|
||||
// It is the caller's responsibility to close the underlying stream if
|
||||
// necessary.
|
||||
// Returns true if no error.
|
||||
bool Close();
|
||||
|
||||
// implements ZeroCopyOutputStream ---------------------------------
|
||||
bool Next(void** data, int* size) override;
|
||||
void BackUp(int count) override;
|
||||
int64_t ByteCount() const override;
|
||||
|
||||
private:
|
||||
ZeroCopyOutputStream* sub_stream_;
|
||||
// Result from calling Next() on sub_stream_
|
||||
void* sub_data_;
|
||||
int sub_data_size_;
|
||||
|
||||
z_stream zcontext_;
|
||||
int zerror_;
|
||||
void* input_buffer_;
|
||||
size_t input_buffer_length_;
|
||||
|
||||
// Shared constructor code.
|
||||
void Init(ZeroCopyOutputStream* sub_stream, const Options& options);
|
||||
|
||||
// Do some compression.
|
||||
// Takes zlib flush mode.
|
||||
// Returns zlib error code.
|
||||
int Deflate(int flush);
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GzipOutputStream);
|
||||
};
|
||||
|
||||
} // namespace io
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_IO_GZIP_STREAM_H__
|
||||
@@ -1,141 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: laszlocsomor@google.com (Laszlo Csomor)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
|
||||
// This file contains the declarations for Windows implementations of
|
||||
// commonly used POSIX functions such as open(2) and access(2), as well
|
||||
// as macro definitions for flags of these functions.
|
||||
//
|
||||
// By including this file you'll redefine open/access/etc. to
|
||||
// ::google::protobuf::io::win32::{open/access/etc.}.
|
||||
// Make sure you don't include a header that attempts to redeclare or
|
||||
// redefine these functions, that'll lead to confusing compilation
|
||||
// errors. It's best to #include this file as the last one to ensure that.
|
||||
//
|
||||
// This file is only used on Windows, it's empty on other platforms.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_IO_IO_WIN32_H__
|
||||
#define GOOGLE_PROTOBUF_IO_IO_WIN32_H__
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/port.h>
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
// Compilers on Windows other than MSVC (e.g. Cygwin, MinGW32) define the
|
||||
// following functions already, except for mkdir.
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace io {
|
||||
namespace win32 {
|
||||
|
||||
PROTOBUF_EXPORT FILE* fopen(const char* path, const char* mode);
|
||||
PROTOBUF_EXPORT int access(const char* path, int mode);
|
||||
PROTOBUF_EXPORT int chdir(const char* path);
|
||||
PROTOBUF_EXPORT int close(int fd);
|
||||
PROTOBUF_EXPORT int dup(int fd);
|
||||
PROTOBUF_EXPORT int dup2(int fd1, int fd2);
|
||||
PROTOBUF_EXPORT int mkdir(const char* path, int _mode);
|
||||
PROTOBUF_EXPORT int open(const char* path, int flags, int mode = 0);
|
||||
PROTOBUF_EXPORT int read(int fd, void* buffer, size_t size);
|
||||
PROTOBUF_EXPORT int setmode(int fd, int mode);
|
||||
PROTOBUF_EXPORT int stat(const char* path, struct _stat* buffer);
|
||||
PROTOBUF_EXPORT int write(int fd, const void* buffer, size_t size);
|
||||
PROTOBUF_EXPORT std::wstring testonly_utf8_to_winpath(const char* path);
|
||||
|
||||
enum class ExpandWildcardsResult {
|
||||
kSuccess = 0,
|
||||
kErrorNoMatchingFile = 1,
|
||||
kErrorInputPathConversion = 2,
|
||||
kErrorOutputPathConversion = 3,
|
||||
};
|
||||
|
||||
// Expand wildcards in a path pattern, feed the result to a consumer function.
|
||||
//
|
||||
// `path` must be a valid, Windows-style path. It may be absolute, or relative
|
||||
// to the current working directory, and it may contain wildcards ("*" and "?")
|
||||
// in the last path segment. This function passes all matching file names to
|
||||
// `consume`. The resulting paths may not be absolute nor normalized.
|
||||
//
|
||||
// The function returns a value from `ExpandWildcardsResult`.
|
||||
PROTOBUF_EXPORT ExpandWildcardsResult ExpandWildcards(
|
||||
const std::string& path, std::function<void(const std::string&)> consume);
|
||||
|
||||
namespace strings {
|
||||
|
||||
// Convert from UTF-16 to Active-Code-Page-encoded or to UTF-8-encoded text.
|
||||
PROTOBUF_EXPORT bool wcs_to_mbs(const wchar_t* s, std::string* out,
|
||||
bool outUtf8);
|
||||
|
||||
// Convert from Active-Code-Page-encoded or UTF-8-encoded text to UTF-16.
|
||||
PROTOBUF_EXPORT bool mbs_to_wcs(const char* s, std::wstring* out, bool inUtf8);
|
||||
|
||||
// Convert from UTF-8-encoded text to UTF-16.
|
||||
PROTOBUF_EXPORT bool utf8_to_wcs(const char* input, std::wstring* out);
|
||||
|
||||
// Convert from UTF-16-encoded text to UTF-8.
|
||||
PROTOBUF_EXPORT bool wcs_to_utf8(const wchar_t* input, std::string* out);
|
||||
|
||||
} // namespace strings
|
||||
|
||||
} // namespace win32
|
||||
} // namespace io
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#ifndef W_OK
|
||||
#define W_OK 02 // not defined by MSVC for whatever reason
|
||||
#endif
|
||||
|
||||
#ifndef F_OK
|
||||
#define F_OK 00 // not defined by MSVC for whatever reason
|
||||
#endif
|
||||
|
||||
#ifndef STDIN_FILENO
|
||||
#define STDIN_FILENO 0
|
||||
#endif
|
||||
|
||||
#ifndef STDOUT_FILENO
|
||||
#define STDOUT_FILENO 1
|
||||
#endif
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // defined(_WIN32)
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_IO_IO_WIN32_H__
|
||||
@@ -1,387 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
//
|
||||
// Utility class for writing text to a ZeroCopyOutputStream.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_IO_PRINTER_H__
|
||||
#define GOOGLE_PROTOBUF_IO_PRINTER_H__
|
||||
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace io {
|
||||
|
||||
class ZeroCopyOutputStream; // zero_copy_stream.h
|
||||
|
||||
// Records annotations about a Printer's output.
|
||||
class PROTOBUF_EXPORT AnnotationCollector {
|
||||
public:
|
||||
// Annotation is a offset range and a payload pair.
|
||||
typedef std::pair<std::pair<size_t, size_t>, std::string> Annotation;
|
||||
|
||||
// Records that the bytes in file_path beginning with begin_offset and ending
|
||||
// before end_offset are associated with the SourceCodeInfo-style path.
|
||||
virtual void AddAnnotation(size_t begin_offset, size_t end_offset,
|
||||
const std::string& file_path,
|
||||
const std::vector<int>& path) = 0;
|
||||
|
||||
// TODO(gerbens) I don't see why we need virtuals here. Just a vector of
|
||||
// range, payload pairs stored in a context should suffice.
|
||||
virtual void AddAnnotationNew(Annotation& /* a */) {}
|
||||
|
||||
virtual ~AnnotationCollector() {}
|
||||
};
|
||||
|
||||
// Records annotations about a Printer's output to the given protocol buffer,
|
||||
// assuming that the buffer has an ::Annotation message exposing path,
|
||||
// source_file, begin and end fields.
|
||||
template <typename AnnotationProto>
|
||||
class AnnotationProtoCollector : public AnnotationCollector {
|
||||
public:
|
||||
// annotation_proto is the protocol buffer to which new Annotations should be
|
||||
// added. It is not owned by the AnnotationProtoCollector.
|
||||
explicit AnnotationProtoCollector(AnnotationProto* annotation_proto)
|
||||
: annotation_proto_(annotation_proto) {}
|
||||
|
||||
// Override for AnnotationCollector::AddAnnotation.
|
||||
void AddAnnotation(size_t begin_offset, size_t end_offset,
|
||||
const std::string& file_path,
|
||||
const std::vector<int>& path) override {
|
||||
typename AnnotationProto::Annotation* annotation =
|
||||
annotation_proto_->add_annotation();
|
||||
for (int i = 0; i < path.size(); ++i) {
|
||||
annotation->add_path(path[i]);
|
||||
}
|
||||
annotation->set_source_file(file_path);
|
||||
annotation->set_begin(begin_offset);
|
||||
annotation->set_end(end_offset);
|
||||
}
|
||||
// Override for AnnotationCollector::AddAnnotation.
|
||||
void AddAnnotationNew(Annotation& a) override {
|
||||
auto* annotation = annotation_proto_->add_annotation();
|
||||
annotation->ParseFromString(a.second);
|
||||
annotation->set_begin(a.first.first);
|
||||
annotation->set_end(a.first.second);
|
||||
}
|
||||
|
||||
private:
|
||||
// The protocol buffer to which new annotations should be added.
|
||||
AnnotationProto* const annotation_proto_;
|
||||
};
|
||||
|
||||
// This simple utility class assists in code generation. It basically
|
||||
// allows the caller to define a set of variables and then output some
|
||||
// text with variable substitutions. Example usage:
|
||||
//
|
||||
// Printer printer(output, '$');
|
||||
// map<string, string> vars;
|
||||
// vars["name"] = "Bob";
|
||||
// printer.Print(vars, "My name is $name$.");
|
||||
//
|
||||
// The above writes "My name is Bob." to the output stream.
|
||||
//
|
||||
// Printer aggressively enforces correct usage, crashing (with assert failures)
|
||||
// in the case of undefined variables in debug builds. This helps greatly in
|
||||
// debugging code which uses it.
|
||||
//
|
||||
// If a Printer is constructed with an AnnotationCollector, it will provide it
|
||||
// with annotations that connect the Printer's output to paths that can identify
|
||||
// various descriptors. In the above example, if person_ is a descriptor that
|
||||
// identifies Bob, we can associate the output string "My name is Bob." with
|
||||
// a source path pointing to that descriptor with:
|
||||
//
|
||||
// printer.Annotate("name", person_);
|
||||
//
|
||||
// The AnnotationCollector will be sent an annotation linking the output range
|
||||
// covering "Bob" to the logical path provided by person_. Tools may use
|
||||
// this association to (for example) link "Bob" in the output back to the
|
||||
// source file that defined the person_ descriptor identifying Bob.
|
||||
//
|
||||
// Annotate can only examine variables substituted during the last call to
|
||||
// Print. It is invalid to refer to a variable that was used multiple times
|
||||
// in a single Print call.
|
||||
//
|
||||
// In full generality, one may specify a range of output text using a beginning
|
||||
// substitution variable and an ending variable. The resulting annotation will
|
||||
// span from the first character of the substituted value for the beginning
|
||||
// variable to the last character of the substituted value for the ending
|
||||
// variable. For example, the Annotate call above is equivalent to this one:
|
||||
//
|
||||
// printer.Annotate("name", "name", person_);
|
||||
//
|
||||
// This is useful if multiple variables combine to form a single span of output
|
||||
// that should be annotated with the same source path. For example:
|
||||
//
|
||||
// Printer printer(output, '$');
|
||||
// map<string, string> vars;
|
||||
// vars["first"] = "Alice";
|
||||
// vars["last"] = "Smith";
|
||||
// printer.Print(vars, "My name is $first$ $last$.");
|
||||
// printer.Annotate("first", "last", person_);
|
||||
//
|
||||
// This code would associate the span covering "Alice Smith" in the output with
|
||||
// the person_ descriptor.
|
||||
//
|
||||
// Note that the beginning variable must come before (or overlap with, in the
|
||||
// case of zero-sized substitution values) the ending variable.
|
||||
//
|
||||
// It is also sometimes useful to use variables with zero-sized values as
|
||||
// markers. This avoids issues with multiple references to the same variable
|
||||
// and also allows annotation ranges to span literal text from the Print
|
||||
// templates:
|
||||
//
|
||||
// Printer printer(output, '$');
|
||||
// map<string, string> vars;
|
||||
// vars["foo"] = "bar";
|
||||
// vars["function"] = "call";
|
||||
// vars["mark"] = "";
|
||||
// printer.Print(vars, "$function$($foo$,$foo$)$mark$");
|
||||
// printer.Annotate("function", "mark", call_);
|
||||
//
|
||||
// This code associates the span covering "call(bar,bar)" in the output with the
|
||||
// call_ descriptor.
|
||||
|
||||
class PROTOBUF_EXPORT Printer {
|
||||
public:
|
||||
// Create a printer that writes text to the given output stream. Use the
|
||||
// given character as the delimiter for variables.
|
||||
Printer(ZeroCopyOutputStream* output, char variable_delimiter);
|
||||
|
||||
// Create a printer that writes text to the given output stream. Use the
|
||||
// given character as the delimiter for variables. If annotation_collector
|
||||
// is not null, Printer will provide it with annotations about code written
|
||||
// to the stream. annotation_collector is not owned by Printer.
|
||||
Printer(ZeroCopyOutputStream* output, char variable_delimiter,
|
||||
AnnotationCollector* annotation_collector);
|
||||
|
||||
~Printer();
|
||||
|
||||
// Link a substitution variable emitted by the last call to Print to the
|
||||
// object described by descriptor.
|
||||
template <typename SomeDescriptor>
|
||||
void Annotate(const char* varname, const SomeDescriptor* descriptor) {
|
||||
Annotate(varname, varname, descriptor);
|
||||
}
|
||||
|
||||
// Link the output range defined by the substitution variables as emitted by
|
||||
// the last call to Print to the object described by descriptor. The range
|
||||
// begins at begin_varname's value and ends after the last character of the
|
||||
// value substituted for end_varname.
|
||||
template <typename SomeDescriptor>
|
||||
void Annotate(const char* begin_varname, const char* end_varname,
|
||||
const SomeDescriptor* descriptor) {
|
||||
if (annotation_collector_ == NULL) {
|
||||
// Annotations aren't turned on for this Printer, so don't pay the cost
|
||||
// of building the location path.
|
||||
return;
|
||||
}
|
||||
std::vector<int> path;
|
||||
descriptor->GetLocationPath(&path);
|
||||
Annotate(begin_varname, end_varname, descriptor->file()->name(), path);
|
||||
}
|
||||
|
||||
// Link a substitution variable emitted by the last call to Print to the file
|
||||
// with path file_name.
|
||||
void Annotate(const char* varname, const std::string& file_name) {
|
||||
Annotate(varname, varname, file_name);
|
||||
}
|
||||
|
||||
// Link the output range defined by the substitution variables as emitted by
|
||||
// the last call to Print to the file with path file_name. The range begins
|
||||
// at begin_varname's value and ends after the last character of the value
|
||||
// substituted for end_varname.
|
||||
void Annotate(const char* begin_varname, const char* end_varname,
|
||||
const std::string& file_name) {
|
||||
if (annotation_collector_ == NULL) {
|
||||
// Annotations aren't turned on for this Printer.
|
||||
return;
|
||||
}
|
||||
std::vector<int> empty_path;
|
||||
Annotate(begin_varname, end_varname, file_name, empty_path);
|
||||
}
|
||||
|
||||
// Print some text after applying variable substitutions. If a particular
|
||||
// variable in the text is not defined, this will crash. Variables to be
|
||||
// substituted are identified by their names surrounded by delimiter
|
||||
// characters (as given to the constructor). The variable bindings are
|
||||
// defined by the given map.
|
||||
void Print(const std::map<std::string, std::string>& variables,
|
||||
const char* text);
|
||||
|
||||
// Like the first Print(), except the substitutions are given as parameters.
|
||||
template <typename... Args>
|
||||
void Print(const char* text, const Args&... args) {
|
||||
std::map<std::string, std::string> vars;
|
||||
PrintInternal(&vars, text, args...);
|
||||
}
|
||||
|
||||
// Indent text by two spaces. After calling Indent(), two spaces will be
|
||||
// inserted at the beginning of each line of text. Indent() may be called
|
||||
// multiple times to produce deeper indents.
|
||||
void Indent();
|
||||
|
||||
// Reduces the current indent level by two spaces, or crashes if the indent
|
||||
// level is zero.
|
||||
void Outdent();
|
||||
|
||||
// Write a string to the output buffer.
|
||||
// This method does not look for newlines to add indentation.
|
||||
void PrintRaw(const std::string& data);
|
||||
|
||||
// Write a zero-delimited string to output buffer.
|
||||
// This method does not look for newlines to add indentation.
|
||||
void PrintRaw(const char* data);
|
||||
|
||||
// Write some bytes to the output buffer.
|
||||
// This method does not look for newlines to add indentation.
|
||||
void WriteRaw(const char* data, int size);
|
||||
|
||||
// FormatInternal is a helper function not meant to use directly, use
|
||||
// compiler::cpp::Formatter instead. This function is meant to support
|
||||
// formatting text using named variables (eq. "$foo$) from a lookup map (vars)
|
||||
// and variables directly supplied by arguments (eq "$1$" meaning first
|
||||
// argument which is the zero index element of args).
|
||||
void FormatInternal(const std::vector<std::string>& args,
|
||||
const std::map<std::string, std::string>& vars,
|
||||
const char* format);
|
||||
|
||||
// True if any write to the underlying stream failed. (We don't just
|
||||
// crash in this case because this is an I/O failure, not a programming
|
||||
// error.)
|
||||
bool failed() const { return failed_; }
|
||||
|
||||
private:
|
||||
// Link the output range defined by the substitution variables as emitted by
|
||||
// the last call to Print to the object found at the SourceCodeInfo-style path
|
||||
// in a file with path file_path. The range begins at the start of
|
||||
// begin_varname's value and ends after the last character of the value
|
||||
// substituted for end_varname. Note that begin_varname and end_varname
|
||||
// may refer to the same variable.
|
||||
void Annotate(const char* begin_varname, const char* end_varname,
|
||||
const std::string& file_path, const std::vector<int>& path);
|
||||
|
||||
// Base case
|
||||
void PrintInternal(std::map<std::string, std::string>* vars,
|
||||
const char* text) {
|
||||
Print(*vars, text);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
void PrintInternal(std::map<std::string, std::string>* vars, const char* text,
|
||||
const char* key, const std::string& value,
|
||||
const Args&... args) {
|
||||
(*vars)[key] = value;
|
||||
PrintInternal(vars, text, args...);
|
||||
}
|
||||
|
||||
// Copy size worth of bytes from data to buffer_.
|
||||
void CopyToBuffer(const char* data, int size);
|
||||
|
||||
void push_back(char c) {
|
||||
if (failed_) return;
|
||||
if (buffer_size_ == 0) {
|
||||
if (!Next()) return;
|
||||
}
|
||||
*buffer_++ = c;
|
||||
buffer_size_--;
|
||||
offset_++;
|
||||
}
|
||||
|
||||
bool Next();
|
||||
|
||||
inline void IndentIfAtStart();
|
||||
const char* WriteVariable(
|
||||
const std::vector<std::string>& args,
|
||||
const std::map<std::string, std::string>& vars, const char* format,
|
||||
int* arg_index,
|
||||
std::vector<AnnotationCollector::Annotation>* annotations);
|
||||
|
||||
const char variable_delimiter_;
|
||||
|
||||
ZeroCopyOutputStream* const output_;
|
||||
char* buffer_;
|
||||
int buffer_size_;
|
||||
// The current position, in bytes, in the output stream. This is equivalent
|
||||
// to the total number of bytes that have been written so far. This value is
|
||||
// used to calculate annotation ranges in the substitutions_ map below.
|
||||
size_t offset_;
|
||||
|
||||
std::string indent_;
|
||||
bool at_start_of_line_;
|
||||
bool failed_;
|
||||
|
||||
// A map from variable name to [start, end) offsets in the output buffer.
|
||||
// These refer to the offsets used for a variable after the last call to
|
||||
// Print. If a variable was used more than once, the entry used in
|
||||
// this map is set to a negative-length span. For singly-used variables, the
|
||||
// start offset is the beginning of the substitution; the end offset is the
|
||||
// last byte of the substitution plus one (such that (end - start) is the
|
||||
// length of the substituted string).
|
||||
std::map<std::string, std::pair<size_t, size_t> > substitutions_;
|
||||
|
||||
// Keeps track of the keys in substitutions_ that need to be updated when
|
||||
// indents are inserted. These are keys that refer to the beginning of the
|
||||
// current line.
|
||||
std::vector<std::string> line_start_variables_;
|
||||
|
||||
// Returns true and sets range to the substitution range in the output for
|
||||
// varname if varname was used once in the last call to Print. If varname
|
||||
// was not used, or if it was used multiple times, returns false (and
|
||||
// fails a debug assertion).
|
||||
bool GetSubstitutionRange(const char* varname,
|
||||
std::pair<size_t, size_t>* range);
|
||||
|
||||
// If non-null, annotation_collector_ is used to store annotations about
|
||||
// generated code.
|
||||
AnnotationCollector* const annotation_collector_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Printer);
|
||||
};
|
||||
|
||||
} // namespace io
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_IO_PRINTER_H__
|
||||
@@ -1,55 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// A locale-independent version of strtod(), used to parse floating
|
||||
// point default values in .proto files, where the decimal separator
|
||||
// is always a dot.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_IO_STRTOD_H__
|
||||
#define GOOGLE_PROTOBUF_IO_STRTOD_H__
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace io {
|
||||
|
||||
// A locale-independent version of the standard strtod(), which always
|
||||
// uses a dot as the decimal separator.
|
||||
double NoLocaleStrtod(const char* str, char** endptr);
|
||||
|
||||
// Casts a double value to a float value. If the value is outside of the
|
||||
// representable range of float, it will be converted to positive or negative
|
||||
// infinity.
|
||||
float SafeDoubleToFloat(double value);
|
||||
|
||||
} // namespace io
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_IO_STRTOD_H__
|
||||
@@ -1,442 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
//
|
||||
// Class for parsing tokenized text from a ZeroCopyInputStream.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_IO_TOKENIZER_H__
|
||||
#define GOOGLE_PROTOBUF_IO_TOKENIZER_H__
|
||||
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/logging.h>
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace io {
|
||||
|
||||
class ZeroCopyInputStream; // zero_copy_stream.h
|
||||
|
||||
// Defined in this file.
|
||||
class ErrorCollector;
|
||||
class Tokenizer;
|
||||
|
||||
// By "column number", the proto compiler refers to a count of the number
|
||||
// of bytes before a given byte, except that a tab character advances to
|
||||
// the next multiple of 8 bytes. Note in particular that column numbers
|
||||
// are zero-based, while many user interfaces use one-based column numbers.
|
||||
typedef int ColumnNumber;
|
||||
|
||||
// Abstract interface for an object which collects the errors that occur
|
||||
// during parsing. A typical implementation might simply print the errors
|
||||
// to stdout.
|
||||
class PROTOBUF_EXPORT ErrorCollector {
|
||||
public:
|
||||
inline ErrorCollector() {}
|
||||
virtual ~ErrorCollector();
|
||||
|
||||
// Indicates that there was an error in the input at the given line and
|
||||
// column numbers. The numbers are zero-based, so you may want to add
|
||||
// 1 to each before printing them.
|
||||
virtual void AddError(int line, ColumnNumber column,
|
||||
const std::string& message) = 0;
|
||||
|
||||
// Indicates that there was a warning in the input at the given line and
|
||||
// column numbers. The numbers are zero-based, so you may want to add
|
||||
// 1 to each before printing them.
|
||||
virtual void AddWarning(int /* line */, ColumnNumber /* column */,
|
||||
const std::string& /* message */) {}
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ErrorCollector);
|
||||
};
|
||||
|
||||
// This class converts a stream of raw text into a stream of tokens for
|
||||
// the protocol definition parser to parse. The tokens recognized are
|
||||
// similar to those that make up the C language; see the TokenType enum for
|
||||
// precise descriptions. Whitespace and comments are skipped. By default,
|
||||
// C- and C++-style comments are recognized, but other styles can be used by
|
||||
// calling set_comment_style().
|
||||
class PROTOBUF_EXPORT Tokenizer {
|
||||
public:
|
||||
// Construct a Tokenizer that reads and tokenizes text from the given
|
||||
// input stream and writes errors to the given error_collector.
|
||||
// The caller keeps ownership of input and error_collector.
|
||||
Tokenizer(ZeroCopyInputStream* input, ErrorCollector* error_collector);
|
||||
~Tokenizer();
|
||||
|
||||
enum TokenType {
|
||||
TYPE_START, // Next() has not yet been called.
|
||||
TYPE_END, // End of input reached. "text" is empty.
|
||||
|
||||
TYPE_IDENTIFIER, // A sequence of letters, digits, and underscores, not
|
||||
// starting with a digit. It is an error for a number
|
||||
// to be followed by an identifier with no space in
|
||||
// between.
|
||||
TYPE_INTEGER, // A sequence of digits representing an integer. Normally
|
||||
// the digits are decimal, but a prefix of "0x" indicates
|
||||
// a hex number and a leading zero indicates octal, just
|
||||
// like with C numeric literals. A leading negative sign
|
||||
// is NOT included in the token; it's up to the parser to
|
||||
// interpret the unary minus operator on its own.
|
||||
TYPE_FLOAT, // A floating point literal, with a fractional part and/or
|
||||
// an exponent. Always in decimal. Again, never
|
||||
// negative.
|
||||
TYPE_STRING, // A quoted sequence of escaped characters. Either single
|
||||
// or double quotes can be used, but they must match.
|
||||
// A string literal cannot cross a line break.
|
||||
TYPE_SYMBOL, // Any other printable character, like '!' or '+'.
|
||||
// Symbols are always a single character, so "!+$%" is
|
||||
// four tokens.
|
||||
TYPE_WHITESPACE, // A sequence of whitespace. This token type is only
|
||||
// produced if report_whitespace() is true. It is not
|
||||
// reported for whitespace within comments or strings.
|
||||
TYPE_NEWLINE, // A newline (\n). This token type is only
|
||||
// produced if report_whitespace() is true and
|
||||
// report_newlines() is true. It is not reported for
|
||||
// newlines in comments or strings.
|
||||
};
|
||||
|
||||
// Structure representing a token read from the token stream.
|
||||
struct Token {
|
||||
TokenType type;
|
||||
std::string text; // The exact text of the token as it appeared in
|
||||
// the input. e.g. tokens of TYPE_STRING will still
|
||||
// be escaped and in quotes.
|
||||
|
||||
// "line" and "column" specify the position of the first character of
|
||||
// the token within the input stream. They are zero-based.
|
||||
int line;
|
||||
ColumnNumber column;
|
||||
ColumnNumber end_column;
|
||||
};
|
||||
|
||||
// Get the current token. This is updated when Next() is called. Before
|
||||
// the first call to Next(), current() has type TYPE_START and no contents.
|
||||
const Token& current();
|
||||
|
||||
// Return the previous token -- i.e. what current() returned before the
|
||||
// previous call to Next().
|
||||
const Token& previous();
|
||||
|
||||
// Advance to the next token. Returns false if the end of the input is
|
||||
// reached.
|
||||
bool Next();
|
||||
|
||||
// Like Next(), but also collects comments which appear between the previous
|
||||
// and next tokens.
|
||||
//
|
||||
// Comments which appear to be attached to the previous token are stored
|
||||
// in *prev_tailing_comments. Comments which appear to be attached to the
|
||||
// next token are stored in *next_leading_comments. Comments appearing in
|
||||
// between which do not appear to be attached to either will be added to
|
||||
// detached_comments. Any of these parameters can be NULL to simply discard
|
||||
// the comments.
|
||||
//
|
||||
// A series of line comments appearing on consecutive lines, with no other
|
||||
// tokens appearing on those lines, will be treated as a single comment.
|
||||
//
|
||||
// Only the comment content is returned; comment markers (e.g. //) are
|
||||
// stripped out. For block comments, leading whitespace and an asterisk will
|
||||
// be stripped from the beginning of each line other than the first. Newlines
|
||||
// are included in the output.
|
||||
//
|
||||
// Examples:
|
||||
//
|
||||
// optional int32 foo = 1; // Comment attached to foo.
|
||||
// // Comment attached to bar.
|
||||
// optional int32 bar = 2;
|
||||
//
|
||||
// optional string baz = 3;
|
||||
// // Comment attached to baz.
|
||||
// // Another line attached to baz.
|
||||
//
|
||||
// // Comment attached to qux.
|
||||
// //
|
||||
// // Another line attached to qux.
|
||||
// optional double qux = 4;
|
||||
//
|
||||
// // Detached comment. This is not attached to qux or corge
|
||||
// // because there are blank lines separating it from both.
|
||||
//
|
||||
// optional string corge = 5;
|
||||
// /* Block comment attached
|
||||
// * to corge. Leading asterisks
|
||||
// * will be removed. */
|
||||
// /* Block comment attached to
|
||||
// * grault. */
|
||||
// optional int32 grault = 6;
|
||||
bool NextWithComments(std::string* prev_trailing_comments,
|
||||
std::vector<std::string>* detached_comments,
|
||||
std::string* next_leading_comments);
|
||||
|
||||
// Parse helpers ---------------------------------------------------
|
||||
|
||||
// Parses a TYPE_FLOAT token. This never fails, so long as the text actually
|
||||
// comes from a TYPE_FLOAT token parsed by Tokenizer. If it doesn't, the
|
||||
// result is undefined (possibly an assert failure).
|
||||
static double ParseFloat(const std::string& text);
|
||||
|
||||
// Parses a TYPE_STRING token. This never fails, so long as the text actually
|
||||
// comes from a TYPE_STRING token parsed by Tokenizer. If it doesn't, the
|
||||
// result is undefined (possibly an assert failure).
|
||||
static void ParseString(const std::string& text, std::string* output);
|
||||
|
||||
// Identical to ParseString, but appends to output.
|
||||
static void ParseStringAppend(const std::string& text, std::string* output);
|
||||
|
||||
// Parses a TYPE_INTEGER token. Returns false if the result would be
|
||||
// greater than max_value. Otherwise, returns true and sets *output to the
|
||||
// result. If the text is not from a Token of type TYPE_INTEGER originally
|
||||
// parsed by a Tokenizer, the result is undefined (possibly an assert
|
||||
// failure).
|
||||
static bool ParseInteger(const std::string& text, uint64_t max_value,
|
||||
uint64_t* output);
|
||||
|
||||
// Options ---------------------------------------------------------
|
||||
|
||||
// Set true to allow floats to be suffixed with the letter 'f'. Tokens
|
||||
// which would otherwise be integers but which have the 'f' suffix will be
|
||||
// forced to be interpreted as floats. For all other purposes, the 'f' is
|
||||
// ignored.
|
||||
void set_allow_f_after_float(bool value) { allow_f_after_float_ = value; }
|
||||
|
||||
// Valid values for set_comment_style().
|
||||
enum CommentStyle {
|
||||
// Line comments begin with "//", block comments are delimited by "/*" and
|
||||
// "*/".
|
||||
CPP_COMMENT_STYLE,
|
||||
// Line comments begin with "#". No way to write block comments.
|
||||
SH_COMMENT_STYLE
|
||||
};
|
||||
|
||||
// Sets the comment style.
|
||||
void set_comment_style(CommentStyle style) { comment_style_ = style; }
|
||||
|
||||
// Whether to require whitespace between a number and a field name.
|
||||
// Default is true. Do not use this; for Google-internal cleanup only.
|
||||
void set_require_space_after_number(bool require) {
|
||||
require_space_after_number_ = require;
|
||||
}
|
||||
|
||||
// Whether to allow string literals to span multiple lines. Default is false.
|
||||
// Do not use this; for Google-internal cleanup only.
|
||||
void set_allow_multiline_strings(bool allow) {
|
||||
allow_multiline_strings_ = allow;
|
||||
}
|
||||
|
||||
// If true, whitespace tokens are reported by Next().
|
||||
// Note: `set_report_whitespace(false)` implies `set_report_newlines(false)`.
|
||||
bool report_whitespace() const;
|
||||
void set_report_whitespace(bool report);
|
||||
|
||||
// If true, newline tokens are reported by Next().
|
||||
// Note: `set_report_newlines(true)` implies `set_report_whitespace(true)`.
|
||||
bool report_newlines() const;
|
||||
void set_report_newlines(bool report);
|
||||
|
||||
// External helper: validate an identifier.
|
||||
static bool IsIdentifier(const std::string& text);
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Tokenizer);
|
||||
|
||||
Token current_; // Returned by current().
|
||||
Token previous_; // Returned by previous().
|
||||
|
||||
ZeroCopyInputStream* input_;
|
||||
ErrorCollector* error_collector_;
|
||||
|
||||
char current_char_; // == buffer_[buffer_pos_], updated by NextChar().
|
||||
const char* buffer_; // Current buffer returned from input_.
|
||||
int buffer_size_; // Size of buffer_.
|
||||
int buffer_pos_; // Current position within the buffer.
|
||||
bool read_error_; // Did we previously encounter a read error?
|
||||
|
||||
// Line and column number of current_char_ within the whole input stream.
|
||||
int line_;
|
||||
ColumnNumber column_;
|
||||
|
||||
// String to which text should be appended as we advance through it.
|
||||
// Call RecordTo(&str) to start recording and StopRecording() to stop.
|
||||
// E.g. StartToken() calls RecordTo(¤t_.text). record_start_ is the
|
||||
// position within the current buffer where recording started.
|
||||
std::string* record_target_;
|
||||
int record_start_;
|
||||
|
||||
// Options.
|
||||
bool allow_f_after_float_;
|
||||
CommentStyle comment_style_;
|
||||
bool require_space_after_number_;
|
||||
bool allow_multiline_strings_;
|
||||
bool report_whitespace_ = false;
|
||||
bool report_newlines_ = false;
|
||||
|
||||
// Since we count columns we need to interpret tabs somehow. We'll take
|
||||
// the standard 8-character definition for lack of any way to do better.
|
||||
// This must match the documentation of ColumnNumber.
|
||||
static const int kTabWidth = 8;
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// Helper methods.
|
||||
|
||||
// Consume this character and advance to the next one.
|
||||
void NextChar();
|
||||
|
||||
// Read a new buffer from the input.
|
||||
void Refresh();
|
||||
|
||||
inline void RecordTo(std::string* target);
|
||||
inline void StopRecording();
|
||||
|
||||
// Called when the current character is the first character of a new
|
||||
// token (not including whitespace or comments).
|
||||
inline void StartToken();
|
||||
// Called when the current character is the first character after the
|
||||
// end of the last token. After this returns, current_.text will
|
||||
// contain all text consumed since StartToken() was called.
|
||||
inline void EndToken();
|
||||
|
||||
// Convenience method to add an error at the current line and column.
|
||||
void AddError(const std::string& message) {
|
||||
error_collector_->AddError(line_, column_, message);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// The following four methods are used to consume tokens of specific
|
||||
// types. They are actually used to consume all characters *after*
|
||||
// the first, since the calling function consumes the first character
|
||||
// in order to decide what kind of token is being read.
|
||||
|
||||
// Read and consume a string, ending when the given delimiter is
|
||||
// consumed.
|
||||
void ConsumeString(char delimiter);
|
||||
|
||||
// Read and consume a number, returning TYPE_FLOAT or TYPE_INTEGER
|
||||
// depending on what was read. This needs to know if the first
|
||||
// character was a zero in order to correctly recognize hex and octal
|
||||
// numbers.
|
||||
// It also needs to know if the first character was a . to parse floating
|
||||
// point correctly.
|
||||
TokenType ConsumeNumber(bool started_with_zero, bool started_with_dot);
|
||||
|
||||
// Consume the rest of a line.
|
||||
void ConsumeLineComment(std::string* content);
|
||||
// Consume until "*/".
|
||||
void ConsumeBlockComment(std::string* content);
|
||||
|
||||
enum NextCommentStatus {
|
||||
// Started a line comment.
|
||||
LINE_COMMENT,
|
||||
|
||||
// Started a block comment.
|
||||
BLOCK_COMMENT,
|
||||
|
||||
// Consumed a slash, then realized it wasn't a comment. current_ has
|
||||
// been filled in with a slash token. The caller should return it.
|
||||
SLASH_NOT_COMMENT,
|
||||
|
||||
// We do not appear to be starting a comment here.
|
||||
NO_COMMENT
|
||||
};
|
||||
|
||||
// If we're at the start of a new comment, consume it and return what kind
|
||||
// of comment it is.
|
||||
NextCommentStatus TryConsumeCommentStart();
|
||||
|
||||
// If we're looking at a TYPE_WHITESPACE token and `report_whitespace_` is
|
||||
// true, consume it and return true.
|
||||
bool TryConsumeWhitespace();
|
||||
|
||||
// If we're looking at a TYPE_NEWLINE token and `report_newlines_` is true,
|
||||
// consume it and return true.
|
||||
bool TryConsumeNewline();
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// These helper methods make the parsing code more readable. The
|
||||
// "character classes" referred to are defined at the top of the .cc file.
|
||||
// Basically it is a C++ class with one method:
|
||||
// static bool InClass(char c);
|
||||
// The method returns true if c is a member of this "class", like "Letter"
|
||||
// or "Digit".
|
||||
|
||||
// Returns true if the current character is of the given character
|
||||
// class, but does not consume anything.
|
||||
template <typename CharacterClass>
|
||||
inline bool LookingAt();
|
||||
|
||||
// If the current character is in the given class, consume it and return
|
||||
// true. Otherwise return false.
|
||||
// e.g. TryConsumeOne<Letter>()
|
||||
template <typename CharacterClass>
|
||||
inline bool TryConsumeOne();
|
||||
|
||||
// Like above, but try to consume the specific character indicated.
|
||||
inline bool TryConsume(char c);
|
||||
|
||||
// Consume zero or more of the given character class.
|
||||
template <typename CharacterClass>
|
||||
inline void ConsumeZeroOrMore();
|
||||
|
||||
// Consume one or more of the given character class or log the given
|
||||
// error message.
|
||||
// e.g. ConsumeOneOrMore<Digit>("Expected digits.");
|
||||
template <typename CharacterClass>
|
||||
inline void ConsumeOneOrMore(const char* error);
|
||||
};
|
||||
|
||||
// inline methods ====================================================
|
||||
inline const Tokenizer::Token& Tokenizer::current() { return current_; }
|
||||
|
||||
inline const Tokenizer::Token& Tokenizer::previous() { return previous_; }
|
||||
|
||||
inline void Tokenizer::ParseString(const std::string& text,
|
||||
std::string* output) {
|
||||
output->clear();
|
||||
ParseStringAppend(text, output);
|
||||
}
|
||||
|
||||
} // namespace io
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_IO_TOKENIZER_H__
|
||||
@@ -1,260 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
//
|
||||
// This file contains the ZeroCopyInputStream and ZeroCopyOutputStream
|
||||
// interfaces, which represent abstract I/O streams to and from which
|
||||
// protocol buffers can be read and written. For a few simple
|
||||
// implementations of these interfaces, see zero_copy_stream_impl.h.
|
||||
//
|
||||
// These interfaces are different from classic I/O streams in that they
|
||||
// try to minimize the amount of data copying that needs to be done.
|
||||
// To accomplish this, responsibility for allocating buffers is moved to
|
||||
// the stream object, rather than being the responsibility of the caller.
|
||||
// So, the stream can return a buffer which actually points directly into
|
||||
// the final data structure where the bytes are to be stored, and the caller
|
||||
// can interact directly with that buffer, eliminating an intermediate copy
|
||||
// operation.
|
||||
//
|
||||
// As an example, consider the common case in which you are reading bytes
|
||||
// from an array that is already in memory (or perhaps an mmap()ed file).
|
||||
// With classic I/O streams, you would do something like:
|
||||
// char buffer[BUFFER_SIZE];
|
||||
// input->Read(buffer, BUFFER_SIZE);
|
||||
// DoSomething(buffer, BUFFER_SIZE);
|
||||
// Then, the stream basically just calls memcpy() to copy the data from
|
||||
// the array into your buffer. With a ZeroCopyInputStream, you would do
|
||||
// this instead:
|
||||
// const void* buffer;
|
||||
// int size;
|
||||
// input->Next(&buffer, &size);
|
||||
// DoSomething(buffer, size);
|
||||
// Here, no copy is performed. The input stream returns a pointer directly
|
||||
// into the backing array, and the caller ends up reading directly from it.
|
||||
//
|
||||
// If you want to be able to read the old-fashion way, you can create
|
||||
// a CodedInputStream or CodedOutputStream wrapping these objects and use
|
||||
// their ReadRaw()/WriteRaw() methods. These will, of course, add a copy
|
||||
// step, but Coded*Stream will handle buffering so at least it will be
|
||||
// reasonably efficient.
|
||||
//
|
||||
// ZeroCopyInputStream example:
|
||||
// // Read in a file and print its contents to stdout.
|
||||
// int fd = open("myfile", O_RDONLY);
|
||||
// ZeroCopyInputStream* input = new FileInputStream(fd);
|
||||
//
|
||||
// const void* buffer;
|
||||
// int size;
|
||||
// while (input->Next(&buffer, &size)) {
|
||||
// cout.write(buffer, size);
|
||||
// }
|
||||
//
|
||||
// delete input;
|
||||
// close(fd);
|
||||
//
|
||||
// ZeroCopyOutputStream example:
|
||||
// // Copy the contents of "infile" to "outfile", using plain read() for
|
||||
// // "infile" but a ZeroCopyOutputStream for "outfile".
|
||||
// int infd = open("infile", O_RDONLY);
|
||||
// int outfd = open("outfile", O_WRONLY);
|
||||
// ZeroCopyOutputStream* output = new FileOutputStream(outfd);
|
||||
//
|
||||
// void* buffer;
|
||||
// int size;
|
||||
// while (output->Next(&buffer, &size)) {
|
||||
// int bytes = read(infd, buffer, size);
|
||||
// if (bytes < size) {
|
||||
// // Reached EOF.
|
||||
// output->BackUp(size - bytes);
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// delete output;
|
||||
// close(infd);
|
||||
// close(outfd);
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_H__
|
||||
#define GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_H__
|
||||
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace io {
|
||||
|
||||
// Defined in this file.
|
||||
class ZeroCopyInputStream;
|
||||
class ZeroCopyOutputStream;
|
||||
|
||||
// Abstract interface similar to an input stream but designed to minimize
|
||||
// copying.
|
||||
class PROTOBUF_EXPORT ZeroCopyInputStream {
|
||||
public:
|
||||
ZeroCopyInputStream() {}
|
||||
virtual ~ZeroCopyInputStream() {}
|
||||
|
||||
// Obtains a chunk of data from the stream.
|
||||
//
|
||||
// Preconditions:
|
||||
// * "size" and "data" are not NULL.
|
||||
//
|
||||
// Postconditions:
|
||||
// * If the returned value is false, there is no more data to return or
|
||||
// an error occurred. All errors are permanent.
|
||||
// * Otherwise, "size" points to the actual number of bytes read and "data"
|
||||
// points to a pointer to a buffer containing these bytes.
|
||||
// * Ownership of this buffer remains with the stream, and the buffer
|
||||
// remains valid only until some other method of the stream is called
|
||||
// or the stream is destroyed.
|
||||
// * It is legal for the returned buffer to have zero size, as long
|
||||
// as repeatedly calling Next() eventually yields a buffer with non-zero
|
||||
// size.
|
||||
virtual bool Next(const void** data, int* size) = 0;
|
||||
|
||||
// Backs up a number of bytes, so that the next call to Next() returns
|
||||
// data again that was already returned by the last call to Next(). This
|
||||
// is useful when writing procedures that are only supposed to read up
|
||||
// to a certain point in the input, then return. If Next() returns a
|
||||
// buffer that goes beyond what you wanted to read, you can use BackUp()
|
||||
// to return to the point where you intended to finish.
|
||||
//
|
||||
// This method can be called with `count = 0` to finalize (flush) any
|
||||
// previously returned buffer. For example, a file output stream can
|
||||
// flush buffers returned from a previous call to Next() upon such
|
||||
// BackUp(0) invocations. ZeroCopyOutputStream callers should always
|
||||
// invoke BackUp() after a final Next() call, even if there is no
|
||||
// excess buffer data to be backed up to indicate a flush point.
|
||||
//
|
||||
// Preconditions:
|
||||
// * The last method called must have been Next().
|
||||
// * count must be less than or equal to the size of the last buffer
|
||||
// returned by Next().
|
||||
//
|
||||
// Postconditions:
|
||||
// * The last "count" bytes of the last buffer returned by Next() will be
|
||||
// pushed back into the stream. Subsequent calls to Next() will return
|
||||
// the same data again before producing new data.
|
||||
virtual void BackUp(int count) = 0;
|
||||
|
||||
// Skips a number of bytes. Returns false if the end of the stream is
|
||||
// reached or some input error occurred. In the end-of-stream case, the
|
||||
// stream is advanced to the end of the stream (so ByteCount() will return
|
||||
// the total size of the stream).
|
||||
virtual bool Skip(int count) = 0;
|
||||
|
||||
// Returns the total number of bytes read since this object was created.
|
||||
virtual int64_t ByteCount() const = 0;
|
||||
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ZeroCopyInputStream);
|
||||
};
|
||||
|
||||
// Abstract interface similar to an output stream but designed to minimize
|
||||
// copying.
|
||||
class PROTOBUF_EXPORT ZeroCopyOutputStream {
|
||||
public:
|
||||
ZeroCopyOutputStream() {}
|
||||
virtual ~ZeroCopyOutputStream() {}
|
||||
|
||||
// Obtains a buffer into which data can be written. Any data written
|
||||
// into this buffer will eventually (maybe instantly, maybe later on)
|
||||
// be written to the output.
|
||||
//
|
||||
// Preconditions:
|
||||
// * "size" and "data" are not NULL.
|
||||
//
|
||||
// Postconditions:
|
||||
// * If the returned value is false, an error occurred. All errors are
|
||||
// permanent.
|
||||
// * Otherwise, "size" points to the actual number of bytes in the buffer
|
||||
// and "data" points to the buffer.
|
||||
// * Ownership of this buffer remains with the stream, and the buffer
|
||||
// remains valid only until some other method of the stream is called
|
||||
// or the stream is destroyed.
|
||||
// * Any data which the caller stores in this buffer will eventually be
|
||||
// written to the output (unless BackUp() is called).
|
||||
// * It is legal for the returned buffer to have zero size, as long
|
||||
// as repeatedly calling Next() eventually yields a buffer with non-zero
|
||||
// size.
|
||||
virtual bool Next(void** data, int* size) = 0;
|
||||
|
||||
// Backs up a number of bytes, so that the end of the last buffer returned
|
||||
// by Next() is not actually written. This is needed when you finish
|
||||
// writing all the data you want to write, but the last buffer was bigger
|
||||
// than you needed. You don't want to write a bunch of garbage after the
|
||||
// end of your data, so you use BackUp() to back up.
|
||||
//
|
||||
// Preconditions:
|
||||
// * The last method called must have been Next().
|
||||
// * count must be less than or equal to the size of the last buffer
|
||||
// returned by Next().
|
||||
// * The caller must not have written anything to the last "count" bytes
|
||||
// of that buffer.
|
||||
//
|
||||
// Postconditions:
|
||||
// * The last "count" bytes of the last buffer returned by Next() will be
|
||||
// ignored.
|
||||
virtual void BackUp(int count) = 0;
|
||||
|
||||
// Returns the total number of bytes written since this object was created.
|
||||
virtual int64_t ByteCount() const = 0;
|
||||
|
||||
// Write a given chunk of data to the output. Some output streams may
|
||||
// implement this in a way that avoids copying. Check AllowsAliasing() before
|
||||
// calling WriteAliasedRaw(). It will GOOGLE_CHECK fail if WriteAliasedRaw() is
|
||||
// called on a stream that does not allow aliasing.
|
||||
//
|
||||
// NOTE: It is caller's responsibility to ensure that the chunk of memory
|
||||
// remains live until all of the data has been consumed from the stream.
|
||||
virtual bool WriteAliasedRaw(const void* data, int size);
|
||||
virtual bool AllowsAliasing() const { return false; }
|
||||
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ZeroCopyOutputStream);
|
||||
};
|
||||
|
||||
} // namespace io
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_H__
|
||||
@@ -1,336 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
//
|
||||
// This file contains common implementations of the interfaces defined in
|
||||
// zero_copy_stream.h which are only included in the full (non-lite)
|
||||
// protobuf library. These implementations include Unix file descriptors
|
||||
// and C++ iostreams. See also: zero_copy_stream_impl_lite.h
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_H__
|
||||
#define GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_H__
|
||||
|
||||
|
||||
#include <iosfwd>
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/io/zero_copy_stream.h>
|
||||
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace io {
|
||||
|
||||
// ===================================================================
|
||||
|
||||
// A ZeroCopyInputStream which reads from a file descriptor.
|
||||
//
|
||||
// FileInputStream is preferred over using an ifstream with IstreamInputStream.
|
||||
// The latter will introduce an extra layer of buffering, harming performance.
|
||||
// Also, it's conceivable that FileInputStream could someday be enhanced
|
||||
// to use zero-copy file descriptors on OSs which support them.
|
||||
class PROTOBUF_EXPORT FileInputStream PROTOBUF_FUTURE_FINAL
|
||||
: public ZeroCopyInputStream {
|
||||
public:
|
||||
// Creates a stream that reads from the given Unix file descriptor.
|
||||
// If a block_size is given, it specifies the number of bytes that
|
||||
// should be read and returned with each call to Next(). Otherwise,
|
||||
// a reasonable default is used.
|
||||
explicit FileInputStream(int file_descriptor, int block_size = -1);
|
||||
|
||||
// Flushes any buffers and closes the underlying file. Returns false if
|
||||
// an error occurs during the process; use GetErrno() to examine the error.
|
||||
// Even if an error occurs, the file descriptor is closed when this returns.
|
||||
bool Close();
|
||||
|
||||
// By default, the file descriptor is not closed when the stream is
|
||||
// destroyed. Call SetCloseOnDelete(true) to change that. WARNING:
|
||||
// This leaves no way for the caller to detect if close() fails. If
|
||||
// detecting close() errors is important to you, you should arrange
|
||||
// to close the descriptor yourself.
|
||||
void SetCloseOnDelete(bool value) { copying_input_.SetCloseOnDelete(value); }
|
||||
|
||||
// If an I/O error has occurred on this file descriptor, this is the
|
||||
// errno from that error. Otherwise, this is zero. Once an error
|
||||
// occurs, the stream is broken and all subsequent operations will
|
||||
// fail.
|
||||
int GetErrno() const { return copying_input_.GetErrno(); }
|
||||
|
||||
// implements ZeroCopyInputStream ----------------------------------
|
||||
bool Next(const void** data, int* size) override;
|
||||
void BackUp(int count) override;
|
||||
bool Skip(int count) override;
|
||||
int64_t ByteCount() const override;
|
||||
|
||||
private:
|
||||
class PROTOBUF_EXPORT CopyingFileInputStream PROTOBUF_FUTURE_FINAL
|
||||
: public CopyingInputStream {
|
||||
public:
|
||||
CopyingFileInputStream(int file_descriptor);
|
||||
~CopyingFileInputStream() override;
|
||||
|
||||
bool Close();
|
||||
void SetCloseOnDelete(bool value) { close_on_delete_ = value; }
|
||||
int GetErrno() const { return errno_; }
|
||||
|
||||
// implements CopyingInputStream ---------------------------------
|
||||
int Read(void* buffer, int size) override;
|
||||
int Skip(int count) override;
|
||||
|
||||
private:
|
||||
// The file descriptor.
|
||||
const int file_;
|
||||
bool close_on_delete_;
|
||||
bool is_closed_;
|
||||
|
||||
// The errno of the I/O error, if one has occurred. Otherwise, zero.
|
||||
int errno_;
|
||||
|
||||
// Did we try to seek once and fail? If so, we assume this file descriptor
|
||||
// doesn't support seeking and won't try again.
|
||||
bool previous_seek_failed_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingFileInputStream);
|
||||
};
|
||||
|
||||
CopyingFileInputStream copying_input_;
|
||||
CopyingInputStreamAdaptor impl_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileInputStream);
|
||||
};
|
||||
|
||||
// ===================================================================
|
||||
|
||||
// A ZeroCopyOutputStream which writes to a file descriptor.
|
||||
//
|
||||
// FileOutputStream is preferred over using an ofstream with
|
||||
// OstreamOutputStream. The latter will introduce an extra layer of buffering,
|
||||
// harming performance. Also, it's conceivable that FileOutputStream could
|
||||
// someday be enhanced to use zero-copy file descriptors on OSs which
|
||||
// support them.
|
||||
class PROTOBUF_EXPORT FileOutputStream PROTOBUF_FUTURE_FINAL
|
||||
: public CopyingOutputStreamAdaptor {
|
||||
public:
|
||||
// Creates a stream that writes to the given Unix file descriptor.
|
||||
// If a block_size is given, it specifies the size of the buffers
|
||||
// that should be returned by Next(). Otherwise, a reasonable default
|
||||
// is used.
|
||||
explicit FileOutputStream(int file_descriptor, int block_size = -1);
|
||||
|
||||
~FileOutputStream() override;
|
||||
|
||||
// Flushes any buffers and closes the underlying file. Returns false if
|
||||
// an error occurs during the process; use GetErrno() to examine the error.
|
||||
// Even if an error occurs, the file descriptor is closed when this returns.
|
||||
bool Close();
|
||||
|
||||
// By default, the file descriptor is not closed when the stream is
|
||||
// destroyed. Call SetCloseOnDelete(true) to change that. WARNING:
|
||||
// This leaves no way for the caller to detect if close() fails. If
|
||||
// detecting close() errors is important to you, you should arrange
|
||||
// to close the descriptor yourself.
|
||||
void SetCloseOnDelete(bool value) { copying_output_.SetCloseOnDelete(value); }
|
||||
|
||||
// If an I/O error has occurred on this file descriptor, this is the
|
||||
// errno from that error. Otherwise, this is zero. Once an error
|
||||
// occurs, the stream is broken and all subsequent operations will
|
||||
// fail.
|
||||
int GetErrno() const { return copying_output_.GetErrno(); }
|
||||
|
||||
private:
|
||||
class PROTOBUF_EXPORT CopyingFileOutputStream PROTOBUF_FUTURE_FINAL
|
||||
: public CopyingOutputStream {
|
||||
public:
|
||||
CopyingFileOutputStream(int file_descriptor);
|
||||
~CopyingFileOutputStream() override;
|
||||
|
||||
bool Close();
|
||||
void SetCloseOnDelete(bool value) { close_on_delete_ = value; }
|
||||
int GetErrno() const { return errno_; }
|
||||
|
||||
// implements CopyingOutputStream --------------------------------
|
||||
bool Write(const void* buffer, int size) override;
|
||||
|
||||
private:
|
||||
// The file descriptor.
|
||||
const int file_;
|
||||
bool close_on_delete_;
|
||||
bool is_closed_;
|
||||
|
||||
// The errno of the I/O error, if one has occurred. Otherwise, zero.
|
||||
int errno_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingFileOutputStream);
|
||||
};
|
||||
|
||||
CopyingFileOutputStream copying_output_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileOutputStream);
|
||||
};
|
||||
|
||||
// ===================================================================
|
||||
|
||||
// A ZeroCopyInputStream which reads from a C++ istream.
|
||||
//
|
||||
// Note that for reading files (or anything represented by a file descriptor),
|
||||
// FileInputStream is more efficient.
|
||||
class PROTOBUF_EXPORT IstreamInputStream PROTOBUF_FUTURE_FINAL
|
||||
: public ZeroCopyInputStream {
|
||||
public:
|
||||
// Creates a stream that reads from the given C++ istream.
|
||||
// If a block_size is given, it specifies the number of bytes that
|
||||
// should be read and returned with each call to Next(). Otherwise,
|
||||
// a reasonable default is used.
|
||||
explicit IstreamInputStream(std::istream* stream, int block_size = -1);
|
||||
|
||||
// implements ZeroCopyInputStream ----------------------------------
|
||||
bool Next(const void** data, int* size) override;
|
||||
void BackUp(int count) override;
|
||||
bool Skip(int count) override;
|
||||
int64_t ByteCount() const override;
|
||||
|
||||
private:
|
||||
class PROTOBUF_EXPORT CopyingIstreamInputStream PROTOBUF_FUTURE_FINAL
|
||||
: public CopyingInputStream {
|
||||
public:
|
||||
CopyingIstreamInputStream(std::istream* input);
|
||||
~CopyingIstreamInputStream() override;
|
||||
|
||||
// implements CopyingInputStream ---------------------------------
|
||||
int Read(void* buffer, int size) override;
|
||||
// (We use the default implementation of Skip().)
|
||||
|
||||
private:
|
||||
// The stream.
|
||||
std::istream* input_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingIstreamInputStream);
|
||||
};
|
||||
|
||||
CopyingIstreamInputStream copying_input_;
|
||||
CopyingInputStreamAdaptor impl_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(IstreamInputStream);
|
||||
};
|
||||
|
||||
// ===================================================================
|
||||
|
||||
// A ZeroCopyOutputStream which writes to a C++ ostream.
|
||||
//
|
||||
// Note that for writing files (or anything represented by a file descriptor),
|
||||
// FileOutputStream is more efficient.
|
||||
class PROTOBUF_EXPORT OstreamOutputStream PROTOBUF_FUTURE_FINAL
|
||||
: public ZeroCopyOutputStream {
|
||||
public:
|
||||
// Creates a stream that writes to the given C++ ostream.
|
||||
// If a block_size is given, it specifies the size of the buffers
|
||||
// that should be returned by Next(). Otherwise, a reasonable default
|
||||
// is used.
|
||||
explicit OstreamOutputStream(std::ostream* stream, int block_size = -1);
|
||||
~OstreamOutputStream() override;
|
||||
|
||||
// implements ZeroCopyOutputStream ---------------------------------
|
||||
bool Next(void** data, int* size) override;
|
||||
void BackUp(int count) override;
|
||||
int64_t ByteCount() const override;
|
||||
|
||||
private:
|
||||
class PROTOBUF_EXPORT CopyingOstreamOutputStream PROTOBUF_FUTURE_FINAL
|
||||
: public CopyingOutputStream {
|
||||
public:
|
||||
CopyingOstreamOutputStream(std::ostream* output);
|
||||
~CopyingOstreamOutputStream() override;
|
||||
|
||||
// implements CopyingOutputStream --------------------------------
|
||||
bool Write(const void* buffer, int size) override;
|
||||
|
||||
private:
|
||||
// The stream.
|
||||
std::ostream* output_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingOstreamOutputStream);
|
||||
};
|
||||
|
||||
CopyingOstreamOutputStream copying_output_;
|
||||
CopyingOutputStreamAdaptor impl_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(OstreamOutputStream);
|
||||
};
|
||||
|
||||
// ===================================================================
|
||||
|
||||
// A ZeroCopyInputStream which reads from several other streams in sequence.
|
||||
// ConcatenatingInputStream is unable to distinguish between end-of-stream
|
||||
// and read errors in the underlying streams, so it assumes any errors mean
|
||||
// end-of-stream. So, if the underlying streams fail for any other reason,
|
||||
// ConcatenatingInputStream may do odd things. It is suggested that you do
|
||||
// not use ConcatenatingInputStream on streams that might produce read errors
|
||||
// other than end-of-stream.
|
||||
class PROTOBUF_EXPORT ConcatenatingInputStream PROTOBUF_FUTURE_FINAL
|
||||
: public ZeroCopyInputStream {
|
||||
public:
|
||||
// All streams passed in as well as the array itself must remain valid
|
||||
// until the ConcatenatingInputStream is destroyed.
|
||||
ConcatenatingInputStream(ZeroCopyInputStream* const streams[], int count);
|
||||
~ConcatenatingInputStream() override = default;
|
||||
|
||||
// implements ZeroCopyInputStream ----------------------------------
|
||||
bool Next(const void** data, int* size) override;
|
||||
void BackUp(int count) override;
|
||||
bool Skip(int count) override;
|
||||
int64_t ByteCount() const override;
|
||||
|
||||
|
||||
private:
|
||||
// As streams are retired, streams_ is incremented and count_ is
|
||||
// decremented.
|
||||
ZeroCopyInputStream* const* streams_;
|
||||
int stream_count_;
|
||||
int64_t bytes_retired_; // Bytes read from previous streams.
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ConcatenatingInputStream);
|
||||
};
|
||||
|
||||
// ===================================================================
|
||||
|
||||
} // namespace io
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_H__
|
||||
@@ -1,413 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
//
|
||||
// This file contains common implementations of the interfaces defined in
|
||||
// zero_copy_stream.h which are included in the "lite" protobuf library.
|
||||
// These implementations cover I/O on raw arrays and strings, as well as
|
||||
// adaptors which make it easy to implement streams based on traditional
|
||||
// streams. Of course, many users will probably want to write their own
|
||||
// implementations of these interfaces specific to the particular I/O
|
||||
// abstractions they prefer to use, but these should cover the most common
|
||||
// cases.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_LITE_H__
|
||||
#define GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_LITE_H__
|
||||
|
||||
|
||||
#include <iosfwd>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/stubs/callback.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/io/zero_copy_stream.h>
|
||||
#include <google/protobuf/stubs/stl_util.h>
|
||||
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace io {
|
||||
|
||||
// ===================================================================
|
||||
|
||||
// A ZeroCopyInputStream backed by an in-memory array of bytes.
|
||||
class PROTOBUF_EXPORT ArrayInputStream PROTOBUF_FUTURE_FINAL
|
||||
: public ZeroCopyInputStream {
|
||||
public:
|
||||
// Create an InputStream that returns the bytes pointed to by "data".
|
||||
// "data" remains the property of the caller but must remain valid until
|
||||
// the stream is destroyed. If a block_size is given, calls to Next()
|
||||
// will return data blocks no larger than the given size. Otherwise, the
|
||||
// first call to Next() returns the entire array. block_size is mainly
|
||||
// useful for testing; in production you would probably never want to set
|
||||
// it.
|
||||
ArrayInputStream(const void* data, int size, int block_size = -1);
|
||||
~ArrayInputStream() override = default;
|
||||
|
||||
// implements ZeroCopyInputStream ----------------------------------
|
||||
bool Next(const void** data, int* size) override;
|
||||
void BackUp(int count) override;
|
||||
bool Skip(int count) override;
|
||||
int64_t ByteCount() const override;
|
||||
|
||||
|
||||
private:
|
||||
const uint8_t* const data_; // The byte array.
|
||||
const int size_; // Total size of the array.
|
||||
const int block_size_; // How many bytes to return at a time.
|
||||
|
||||
int position_;
|
||||
int last_returned_size_; // How many bytes we returned last time Next()
|
||||
// was called (used for error checking only).
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ArrayInputStream);
|
||||
};
|
||||
|
||||
// ===================================================================
|
||||
|
||||
// A ZeroCopyOutputStream backed by an in-memory array of bytes.
|
||||
class PROTOBUF_EXPORT ArrayOutputStream PROTOBUF_FUTURE_FINAL
|
||||
: public ZeroCopyOutputStream {
|
||||
public:
|
||||
// Create an OutputStream that writes to the bytes pointed to by "data".
|
||||
// "data" remains the property of the caller but must remain valid until
|
||||
// the stream is destroyed. If a block_size is given, calls to Next()
|
||||
// will return data blocks no larger than the given size. Otherwise, the
|
||||
// first call to Next() returns the entire array. block_size is mainly
|
||||
// useful for testing; in production you would probably never want to set
|
||||
// it.
|
||||
ArrayOutputStream(void* data, int size, int block_size = -1);
|
||||
~ArrayOutputStream() override = default;
|
||||
|
||||
// implements ZeroCopyOutputStream ---------------------------------
|
||||
bool Next(void** data, int* size) override;
|
||||
void BackUp(int count) override;
|
||||
int64_t ByteCount() const override;
|
||||
|
||||
private:
|
||||
uint8_t* const data_; // The byte array.
|
||||
const int size_; // Total size of the array.
|
||||
const int block_size_; // How many bytes to return at a time.
|
||||
|
||||
int position_;
|
||||
int last_returned_size_; // How many bytes we returned last time Next()
|
||||
// was called (used for error checking only).
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ArrayOutputStream);
|
||||
};
|
||||
|
||||
// ===================================================================
|
||||
|
||||
// A ZeroCopyOutputStream which appends bytes to a string.
|
||||
class PROTOBUF_EXPORT StringOutputStream PROTOBUF_FUTURE_FINAL
|
||||
: public ZeroCopyOutputStream {
|
||||
public:
|
||||
// Create a StringOutputStream which appends bytes to the given string.
|
||||
// The string remains property of the caller, but it is mutated in arbitrary
|
||||
// ways and MUST NOT be accessed in any way until you're done with the
|
||||
// stream. Either be sure there's no further usage, or (safest) destroy the
|
||||
// stream before using the contents.
|
||||
//
|
||||
// Hint: If you call target->reserve(n) before creating the stream,
|
||||
// the first call to Next() will return at least n bytes of buffer
|
||||
// space.
|
||||
explicit StringOutputStream(std::string* target);
|
||||
~StringOutputStream() override = default;
|
||||
|
||||
// implements ZeroCopyOutputStream ---------------------------------
|
||||
bool Next(void** data, int* size) override;
|
||||
void BackUp(int count) override;
|
||||
int64_t ByteCount() const override;
|
||||
|
||||
private:
|
||||
static constexpr size_t kMinimumSize = 16;
|
||||
|
||||
std::string* target_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringOutputStream);
|
||||
};
|
||||
|
||||
// Note: There is no StringInputStream. Instead, just create an
|
||||
// ArrayInputStream as follows:
|
||||
// ArrayInputStream input(str.data(), str.size());
|
||||
|
||||
// ===================================================================
|
||||
|
||||
// A generic traditional input stream interface.
|
||||
//
|
||||
// Lots of traditional input streams (e.g. file descriptors, C stdio
|
||||
// streams, and C++ iostreams) expose an interface where every read
|
||||
// involves copying bytes into a buffer. If you want to take such an
|
||||
// interface and make a ZeroCopyInputStream based on it, simply implement
|
||||
// CopyingInputStream and then use CopyingInputStreamAdaptor.
|
||||
//
|
||||
// CopyingInputStream implementations should avoid buffering if possible.
|
||||
// CopyingInputStreamAdaptor does its own buffering and will read data
|
||||
// in large blocks.
|
||||
class PROTOBUF_EXPORT CopyingInputStream {
|
||||
public:
|
||||
virtual ~CopyingInputStream() {}
|
||||
|
||||
// Reads up to "size" bytes into the given buffer. Returns the number of
|
||||
// bytes read. Read() waits until at least one byte is available, or
|
||||
// returns zero if no bytes will ever become available (EOF), or -1 if a
|
||||
// permanent read error occurred.
|
||||
virtual int Read(void* buffer, int size) = 0;
|
||||
|
||||
// Skips the next "count" bytes of input. Returns the number of bytes
|
||||
// actually skipped. This will always be exactly equal to "count" unless
|
||||
// EOF was reached or a permanent read error occurred.
|
||||
//
|
||||
// The default implementation just repeatedly calls Read() into a scratch
|
||||
// buffer.
|
||||
virtual int Skip(int count);
|
||||
};
|
||||
|
||||
// A ZeroCopyInputStream which reads from a CopyingInputStream. This is
|
||||
// useful for implementing ZeroCopyInputStreams that read from traditional
|
||||
// streams. Note that this class is not really zero-copy.
|
||||
//
|
||||
// If you want to read from file descriptors or C++ istreams, this is
|
||||
// already implemented for you: use FileInputStream or IstreamInputStream
|
||||
// respectively.
|
||||
class PROTOBUF_EXPORT CopyingInputStreamAdaptor : public ZeroCopyInputStream {
|
||||
public:
|
||||
// Creates a stream that reads from the given CopyingInputStream.
|
||||
// If a block_size is given, it specifies the number of bytes that
|
||||
// should be read and returned with each call to Next(). Otherwise,
|
||||
// a reasonable default is used. The caller retains ownership of
|
||||
// copying_stream unless SetOwnsCopyingStream(true) is called.
|
||||
explicit CopyingInputStreamAdaptor(CopyingInputStream* copying_stream,
|
||||
int block_size = -1);
|
||||
~CopyingInputStreamAdaptor() override;
|
||||
|
||||
// Call SetOwnsCopyingStream(true) to tell the CopyingInputStreamAdaptor to
|
||||
// delete the underlying CopyingInputStream when it is destroyed.
|
||||
void SetOwnsCopyingStream(bool value) { owns_copying_stream_ = value; }
|
||||
|
||||
// implements ZeroCopyInputStream ----------------------------------
|
||||
bool Next(const void** data, int* size) override;
|
||||
void BackUp(int count) override;
|
||||
bool Skip(int count) override;
|
||||
int64_t ByteCount() const override;
|
||||
|
||||
private:
|
||||
// Insures that buffer_ is not NULL.
|
||||
void AllocateBufferIfNeeded();
|
||||
// Frees the buffer and resets buffer_used_.
|
||||
void FreeBuffer();
|
||||
|
||||
// The underlying copying stream.
|
||||
CopyingInputStream* copying_stream_;
|
||||
bool owns_copying_stream_;
|
||||
|
||||
// True if we have seen a permanent error from the underlying stream.
|
||||
bool failed_;
|
||||
|
||||
// The current position of copying_stream_, relative to the point where
|
||||
// we started reading.
|
||||
int64_t position_;
|
||||
|
||||
// Data is read into this buffer. It may be NULL if no buffer is currently
|
||||
// in use. Otherwise, it points to an array of size buffer_size_.
|
||||
std::unique_ptr<uint8_t[]> buffer_;
|
||||
const int buffer_size_;
|
||||
|
||||
// Number of valid bytes currently in the buffer (i.e. the size last
|
||||
// returned by Next()). 0 <= buffer_used_ <= buffer_size_.
|
||||
int buffer_used_;
|
||||
|
||||
// Number of bytes in the buffer which were backed up over by a call to
|
||||
// BackUp(). These need to be returned again.
|
||||
// 0 <= backup_bytes_ <= buffer_used_
|
||||
int backup_bytes_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingInputStreamAdaptor);
|
||||
};
|
||||
|
||||
// ===================================================================
|
||||
|
||||
// A generic traditional output stream interface.
|
||||
//
|
||||
// Lots of traditional output streams (e.g. file descriptors, C stdio
|
||||
// streams, and C++ iostreams) expose an interface where every write
|
||||
// involves copying bytes from a buffer. If you want to take such an
|
||||
// interface and make a ZeroCopyOutputStream based on it, simply implement
|
||||
// CopyingOutputStream and then use CopyingOutputStreamAdaptor.
|
||||
//
|
||||
// CopyingOutputStream implementations should avoid buffering if possible.
|
||||
// CopyingOutputStreamAdaptor does its own buffering and will write data
|
||||
// in large blocks.
|
||||
class PROTOBUF_EXPORT CopyingOutputStream {
|
||||
public:
|
||||
virtual ~CopyingOutputStream() {}
|
||||
|
||||
// Writes "size" bytes from the given buffer to the output. Returns true
|
||||
// if successful, false on a write error.
|
||||
virtual bool Write(const void* buffer, int size) = 0;
|
||||
};
|
||||
|
||||
// A ZeroCopyOutputStream which writes to a CopyingOutputStream. This is
|
||||
// useful for implementing ZeroCopyOutputStreams that write to traditional
|
||||
// streams. Note that this class is not really zero-copy.
|
||||
//
|
||||
// If you want to write to file descriptors or C++ ostreams, this is
|
||||
// already implemented for you: use FileOutputStream or OstreamOutputStream
|
||||
// respectively.
|
||||
class PROTOBUF_EXPORT CopyingOutputStreamAdaptor : public ZeroCopyOutputStream {
|
||||
public:
|
||||
// Creates a stream that writes to the given Unix file descriptor.
|
||||
// If a block_size is given, it specifies the size of the buffers
|
||||
// that should be returned by Next(). Otherwise, a reasonable default
|
||||
// is used.
|
||||
explicit CopyingOutputStreamAdaptor(CopyingOutputStream* copying_stream,
|
||||
int block_size = -1);
|
||||
~CopyingOutputStreamAdaptor() override;
|
||||
|
||||
// Writes all pending data to the underlying stream. Returns false if a
|
||||
// write error occurred on the underlying stream. (The underlying
|
||||
// stream itself is not necessarily flushed.)
|
||||
bool Flush();
|
||||
|
||||
// Call SetOwnsCopyingStream(true) to tell the CopyingOutputStreamAdaptor to
|
||||
// delete the underlying CopyingOutputStream when it is destroyed.
|
||||
void SetOwnsCopyingStream(bool value) { owns_copying_stream_ = value; }
|
||||
|
||||
// implements ZeroCopyOutputStream ---------------------------------
|
||||
bool Next(void** data, int* size) override;
|
||||
void BackUp(int count) override;
|
||||
int64_t ByteCount() const override;
|
||||
bool WriteAliasedRaw(const void* data, int size) override;
|
||||
bool AllowsAliasing() const override { return true; }
|
||||
|
||||
private:
|
||||
// Write the current buffer, if it is present.
|
||||
bool WriteBuffer();
|
||||
// Insures that buffer_ is not NULL.
|
||||
void AllocateBufferIfNeeded();
|
||||
// Frees the buffer.
|
||||
void FreeBuffer();
|
||||
|
||||
// The underlying copying stream.
|
||||
CopyingOutputStream* copying_stream_;
|
||||
bool owns_copying_stream_;
|
||||
|
||||
// True if we have seen a permanent error from the underlying stream.
|
||||
bool failed_;
|
||||
|
||||
// The current position of copying_stream_, relative to the point where
|
||||
// we started writing.
|
||||
int64_t position_;
|
||||
|
||||
// Data is written from this buffer. It may be NULL if no buffer is
|
||||
// currently in use. Otherwise, it points to an array of size buffer_size_.
|
||||
std::unique_ptr<uint8_t[]> buffer_;
|
||||
const int buffer_size_;
|
||||
|
||||
// Number of valid bytes currently in the buffer (i.e. the size last
|
||||
// returned by Next()). When BackUp() is called, we just reduce this.
|
||||
// 0 <= buffer_used_ <= buffer_size_.
|
||||
int buffer_used_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingOutputStreamAdaptor);
|
||||
};
|
||||
|
||||
// ===================================================================
|
||||
|
||||
// A ZeroCopyInputStream which wraps some other stream and limits it to
|
||||
// a particular byte count.
|
||||
class PROTOBUF_EXPORT LimitingInputStream PROTOBUF_FUTURE_FINAL
|
||||
: public ZeroCopyInputStream {
|
||||
public:
|
||||
LimitingInputStream(ZeroCopyInputStream* input, int64_t limit);
|
||||
~LimitingInputStream() override;
|
||||
|
||||
// implements ZeroCopyInputStream ----------------------------------
|
||||
bool Next(const void** data, int* size) override;
|
||||
void BackUp(int count) override;
|
||||
bool Skip(int count) override;
|
||||
int64_t ByteCount() const override;
|
||||
|
||||
|
||||
private:
|
||||
ZeroCopyInputStream* input_;
|
||||
int64_t limit_; // Decreases as we go, becomes negative if we overshoot.
|
||||
int64_t prior_bytes_read_; // Bytes read on underlying stream at construction
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(LimitingInputStream);
|
||||
};
|
||||
|
||||
|
||||
// ===================================================================
|
||||
|
||||
// mutable_string_data() and as_string_data() are workarounds to improve
|
||||
// the performance of writing new data to an existing string. Unfortunately
|
||||
// the methods provided by the string class are suboptimal, and using memcpy()
|
||||
// is mildly annoying because it requires its pointer args to be non-NULL even
|
||||
// if we ask it to copy 0 bytes. Furthermore, string_as_array() has the
|
||||
// property that it always returns NULL if its arg is the empty string, exactly
|
||||
// what we want to avoid if we're using it in conjunction with memcpy()!
|
||||
// With C++11, the desired memcpy() boils down to memcpy(..., &(*s)[0], size),
|
||||
// where s is a string*. Without C++11, &(*s)[0] is not guaranteed to be safe,
|
||||
// so we use string_as_array(), and live with the extra logic that tests whether
|
||||
// *s is empty.
|
||||
|
||||
// Return a pointer to mutable characters underlying the given string. The
|
||||
// return value is valid until the next time the string is resized. We
|
||||
// trust the caller to treat the return value as an array of length s->size().
|
||||
inline char* mutable_string_data(std::string* s) {
|
||||
// This should be simpler & faster than string_as_array() because the latter
|
||||
// is guaranteed to return NULL when *s is empty, so it has to check for that.
|
||||
return &(*s)[0];
|
||||
}
|
||||
|
||||
// as_string_data(s) is equivalent to
|
||||
// ({ char* p = mutable_string_data(s); make_pair(p, p != NULL); })
|
||||
// Sometimes it's faster: in some scenarios p cannot be NULL, and then the
|
||||
// code can avoid that check.
|
||||
inline std::pair<char*, bool> as_string_data(std::string* s) {
|
||||
char* p = mutable_string_data(s);
|
||||
return std::make_pair(p, true);
|
||||
}
|
||||
|
||||
} // namespace io
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_LITE_H__
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,134 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_MAP_ENTRY_H__
|
||||
#define GOOGLE_PROTOBUF_MAP_ENTRY_H__
|
||||
|
||||
#include <google/protobuf/port.h>
|
||||
#include <google/protobuf/generated_message_reflection.h>
|
||||
#include <google/protobuf/map_entry_lite.h>
|
||||
#include <google/protobuf/map_type_handler.h>
|
||||
#include <google/protobuf/reflection_ops.h>
|
||||
#include <google/protobuf/unknown_field_set.h>
|
||||
#include <google/protobuf/wire_format_lite.h>
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
#ifdef SWIG
|
||||
#error "You cannot SWIG proto headers"
|
||||
#endif
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
class Arena;
|
||||
namespace internal {
|
||||
template <typename Derived, typename Key, typename Value,
|
||||
WireFormatLite::FieldType kKeyFieldType,
|
||||
WireFormatLite::FieldType kValueFieldType>
|
||||
class MapField;
|
||||
}
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
// MapEntry is the returned google::protobuf::Message when calling AddMessage of
|
||||
// google::protobuf::Reflection. In order to let it work with generated message
|
||||
// reflection, its in-memory type is the same as generated message with the same
|
||||
// fields. However, in order to decide the in-memory type of key/value, we need
|
||||
// to know both their cpp type in generated api and proto type. In
|
||||
// implementation, all in-memory types have related wire format functions to
|
||||
// support except ArenaStringPtr. Therefore, we need to define another type with
|
||||
// supporting wire format functions. Since this type is only used as return type
|
||||
// of MapEntry accessors, it's named MapEntry accessor type.
|
||||
//
|
||||
// cpp type: the type visible to users in public API.
|
||||
// proto type: WireFormatLite::FieldType of the field.
|
||||
// in-memory type: type of the data member used to stored this field.
|
||||
// MapEntry accessor type: type used in MapEntry getters/mutators to access the
|
||||
// field.
|
||||
//
|
||||
// cpp type | proto type | in-memory type | MapEntry accessor type
|
||||
// int32_t TYPE_INT32 int32_t int32_t
|
||||
// int32_t TYPE_FIXED32 int32_t int32_t
|
||||
// string TYPE_STRING ArenaStringPtr string
|
||||
// FooEnum TYPE_ENUM int int
|
||||
// FooMessage TYPE_MESSAGE FooMessage* FooMessage
|
||||
//
|
||||
// The in-memory types of primitive types can be inferred from its proto type,
|
||||
// while we need to explicitly specify the cpp type if proto type is
|
||||
// TYPE_MESSAGE to infer the in-memory type.
|
||||
template <typename Derived, typename Key, typename Value,
|
||||
WireFormatLite::FieldType kKeyFieldType,
|
||||
WireFormatLite::FieldType kValueFieldType>
|
||||
class MapEntry : public MapEntryImpl<Derived, Message, Key, Value,
|
||||
kKeyFieldType, kValueFieldType> {
|
||||
public:
|
||||
constexpr MapEntry() {}
|
||||
explicit MapEntry(Arena* arena)
|
||||
: MapEntryImpl<Derived, Message, Key, Value, kKeyFieldType,
|
||||
kValueFieldType>(arena) {}
|
||||
~MapEntry() override {
|
||||
Message::_internal_metadata_.template Delete<UnknownFieldSet>();
|
||||
}
|
||||
typedef void InternalArenaConstructable_;
|
||||
typedef void DestructorSkippable_;
|
||||
|
||||
typedef typename MapEntryImpl<Derived, Message, Key, Value, kKeyFieldType,
|
||||
kValueFieldType>::KeyTypeHandler KeyTypeHandler;
|
||||
typedef
|
||||
typename MapEntryImpl<Derived, Message, Key, Value, kKeyFieldType,
|
||||
kValueFieldType>::ValueTypeHandler ValueTypeHandler;
|
||||
size_t SpaceUsedLong() const override {
|
||||
size_t size = sizeof(Derived);
|
||||
size += KeyTypeHandler::SpaceUsedInMapEntryLong(this->key_);
|
||||
size += ValueTypeHandler::SpaceUsedInMapEntryLong(this->value_);
|
||||
return size;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class ::PROTOBUF_NAMESPACE_ID::Arena;
|
||||
template <typename C, typename K, typename V,
|
||||
WireFormatLite::FieldType k_wire_type, WireFormatLite::FieldType>
|
||||
friend class internal::MapField;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntry);
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_MAP_ENTRY_H__
|
||||
@@ -1,563 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_MAP_ENTRY_LITE_H__
|
||||
#define GOOGLE_PROTOBUF_MAP_ENTRY_LITE_H__
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include <google/protobuf/stubs/casts.h>
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/arena.h>
|
||||
#include <google/protobuf/port.h>
|
||||
#include <google/protobuf/arenastring.h>
|
||||
#include <google/protobuf/generated_message_util.h>
|
||||
#include <google/protobuf/map.h>
|
||||
#include <google/protobuf/map_type_handler.h>
|
||||
#include <google/protobuf/parse_context.h>
|
||||
#include <google/protobuf/wire_format_lite.h>
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
#ifdef SWIG
|
||||
#error "You cannot SWIG proto headers"
|
||||
#endif
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
template <typename Derived, typename Key, typename Value,
|
||||
WireFormatLite::FieldType kKeyFieldType,
|
||||
WireFormatLite::FieldType kValueFieldType>
|
||||
class MapEntry;
|
||||
template <typename Derived, typename Key, typename Value,
|
||||
WireFormatLite::FieldType kKeyFieldType,
|
||||
WireFormatLite::FieldType kValueFieldType>
|
||||
class MapFieldLite;
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
// MoveHelper::Move is used to set *dest. It copies *src, or moves it (in
|
||||
// the C++11 sense), or swaps it. *src is left in a sane state for
|
||||
// subsequent destruction, but shouldn't be used for anything.
|
||||
template <bool is_enum, bool is_message, bool is_stringlike, typename T>
|
||||
struct MoveHelper { // primitives
|
||||
static void Move(T* src, T* dest) { *dest = *src; }
|
||||
};
|
||||
|
||||
template <bool is_message, bool is_stringlike, typename T>
|
||||
struct MoveHelper<true, is_message, is_stringlike, T> { // enums
|
||||
static void Move(T* src, T* dest) { *dest = *src; }
|
||||
// T is an enum here, so allow conversions to and from int.
|
||||
static void Move(T* src, int* dest) { *dest = static_cast<int>(*src); }
|
||||
static void Move(int* src, T* dest) { *dest = static_cast<T>(*src); }
|
||||
};
|
||||
|
||||
template <bool is_stringlike, typename T>
|
||||
struct MoveHelper<false, true, is_stringlike, T> { // messages
|
||||
static void Move(T* src, T* dest) { dest->Swap(src); }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct MoveHelper<false, false, true, T> { // strings and similar
|
||||
static void Move(T* src, T* dest) {
|
||||
*dest = std::move(*src);
|
||||
}
|
||||
};
|
||||
|
||||
// MapEntryImpl is used to implement parsing and serialization of map entries.
|
||||
// It uses Curious Recursive Template Pattern (CRTP) to provide the type of
|
||||
// the eventual code to the template code.
|
||||
template <typename Derived, typename Base, typename Key, typename Value,
|
||||
WireFormatLite::FieldType kKeyFieldType,
|
||||
WireFormatLite::FieldType kValueFieldType>
|
||||
class MapEntryImpl : public Base {
|
||||
public:
|
||||
typedef MapEntryFuncs<Key, Value, kKeyFieldType, kValueFieldType> Funcs;
|
||||
|
||||
protected:
|
||||
// Provide utilities to parse/serialize key/value. Provide utilities to
|
||||
// manipulate internal stored type.
|
||||
typedef MapTypeHandler<kKeyFieldType, Key> KeyTypeHandler;
|
||||
typedef MapTypeHandler<kValueFieldType, Value> ValueTypeHandler;
|
||||
|
||||
// Define internal memory layout. Strings and messages are stored as
|
||||
// pointers, while other types are stored as values.
|
||||
typedef typename KeyTypeHandler::TypeOnMemory KeyOnMemory;
|
||||
typedef typename ValueTypeHandler::TypeOnMemory ValueOnMemory;
|
||||
|
||||
// Enum type cannot be used for MapTypeHandler::Read. Define a type
|
||||
// which will replace Enum with int.
|
||||
typedef typename KeyTypeHandler::MapEntryAccessorType KeyMapEntryAccessorType;
|
||||
typedef
|
||||
typename ValueTypeHandler::MapEntryAccessorType ValueMapEntryAccessorType;
|
||||
|
||||
// Constants for field number.
|
||||
static const int kKeyFieldNumber = 1;
|
||||
static const int kValueFieldNumber = 2;
|
||||
|
||||
// Constants for field tag.
|
||||
static const uint8_t kKeyTag =
|
||||
GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(kKeyFieldNumber, KeyTypeHandler::kWireType);
|
||||
static const uint8_t kValueTag = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(
|
||||
kValueFieldNumber, ValueTypeHandler::kWireType);
|
||||
static const size_t kTagSize = 1;
|
||||
|
||||
public:
|
||||
// Work-around for a compiler bug (see repeated_field.h).
|
||||
typedef void MapEntryHasMergeTypeTrait;
|
||||
typedef Derived EntryType;
|
||||
typedef Key EntryKeyType;
|
||||
typedef Value EntryValueType;
|
||||
static const WireFormatLite::FieldType kEntryKeyFieldType = kKeyFieldType;
|
||||
static const WireFormatLite::FieldType kEntryValueFieldType = kValueFieldType;
|
||||
|
||||
constexpr MapEntryImpl()
|
||||
: key_(KeyTypeHandler::Constinit()),
|
||||
value_(ValueTypeHandler::Constinit()),
|
||||
_has_bits_{} {}
|
||||
|
||||
explicit MapEntryImpl(Arena* arena)
|
||||
: Base(arena),
|
||||
key_(KeyTypeHandler::Constinit()),
|
||||
value_(ValueTypeHandler::Constinit()),
|
||||
_has_bits_{} {}
|
||||
|
||||
~MapEntryImpl() override {
|
||||
if (Base::GetArenaForAllocation() != nullptr) return;
|
||||
KeyTypeHandler::DeleteNoArena(key_);
|
||||
ValueTypeHandler::DeleteNoArena(value_);
|
||||
}
|
||||
|
||||
// accessors ======================================================
|
||||
|
||||
virtual inline const KeyMapEntryAccessorType& key() const {
|
||||
return KeyTypeHandler::GetExternalReference(key_);
|
||||
}
|
||||
virtual inline const ValueMapEntryAccessorType& value() const {
|
||||
return ValueTypeHandler::DefaultIfNotInitialized(value_);
|
||||
}
|
||||
inline KeyMapEntryAccessorType* mutable_key() {
|
||||
set_has_key();
|
||||
return KeyTypeHandler::EnsureMutable(&key_, Base::GetArenaForAllocation());
|
||||
}
|
||||
inline ValueMapEntryAccessorType* mutable_value() {
|
||||
set_has_value();
|
||||
return ValueTypeHandler::EnsureMutable(&value_,
|
||||
Base::GetArenaForAllocation());
|
||||
}
|
||||
|
||||
// implements MessageLite =========================================
|
||||
|
||||
// MapEntryImpl is for implementation only and this function isn't called
|
||||
// anywhere. Just provide a fake implementation here for MessageLite.
|
||||
std::string GetTypeName() const override { return ""; }
|
||||
|
||||
void CheckTypeAndMergeFrom(const MessageLite& other) override {
|
||||
MergeFromInternal(*::google::protobuf::internal::DownCast<const Derived*>(&other));
|
||||
}
|
||||
|
||||
const char* _InternalParse(const char* ptr, ParseContext* ctx) final {
|
||||
while (!ctx->Done(&ptr)) {
|
||||
uint32_t tag;
|
||||
ptr = ReadTag(ptr, &tag);
|
||||
GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
|
||||
if (tag == kKeyTag) {
|
||||
set_has_key();
|
||||
KeyMapEntryAccessorType* key = mutable_key();
|
||||
ptr = KeyTypeHandler::Read(ptr, ctx, key);
|
||||
if (!Derived::ValidateKey(key)) return nullptr;
|
||||
} else if (tag == kValueTag) {
|
||||
set_has_value();
|
||||
ValueMapEntryAccessorType* value = mutable_value();
|
||||
ptr = ValueTypeHandler::Read(ptr, ctx, value);
|
||||
if (!Derived::ValidateValue(value)) return nullptr;
|
||||
} else {
|
||||
if (tag == 0 || WireFormatLite::GetTagWireType(tag) ==
|
||||
WireFormatLite::WIRETYPE_END_GROUP) {
|
||||
ctx->SetLastTag(tag);
|
||||
return ptr;
|
||||
}
|
||||
ptr = UnknownFieldParse(tag, static_cast<std::string*>(nullptr), ptr,
|
||||
ctx);
|
||||
}
|
||||
GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
size_t ByteSizeLong() const override {
|
||||
size_t size = 0;
|
||||
size += kTagSize + static_cast<size_t>(KeyTypeHandler::ByteSize(key()));
|
||||
size += kTagSize + static_cast<size_t>(ValueTypeHandler::ByteSize(value()));
|
||||
return size;
|
||||
}
|
||||
|
||||
::uint8_t* _InternalSerialize(
|
||||
::uint8_t* ptr, io::EpsCopyOutputStream* stream) const override {
|
||||
ptr = KeyTypeHandler::Write(kKeyFieldNumber, key(), ptr, stream);
|
||||
return ValueTypeHandler::Write(kValueFieldNumber, value(), ptr, stream);
|
||||
}
|
||||
|
||||
// Don't override SerializeWithCachedSizesToArray. Use MessageLite's.
|
||||
|
||||
int GetCachedSize() const override {
|
||||
int size = 0;
|
||||
size += has_key() ? static_cast<int>(kTagSize) +
|
||||
KeyTypeHandler::GetCachedSize(key())
|
||||
: 0;
|
||||
size += has_value() ? static_cast<int>(kTagSize) +
|
||||
ValueTypeHandler::GetCachedSize(value())
|
||||
: 0;
|
||||
return size;
|
||||
}
|
||||
|
||||
bool IsInitialized() const override {
|
||||
return ValueTypeHandler::IsInitialized(value_);
|
||||
}
|
||||
|
||||
Base* New(Arena* arena) const override {
|
||||
Derived* entry = Arena::CreateMessage<Derived>(arena);
|
||||
return entry;
|
||||
}
|
||||
|
||||
protected:
|
||||
// We can't declare this function directly here as it would hide the other
|
||||
// overload (const Message&).
|
||||
void MergeFromInternal(const MapEntryImpl& from) {
|
||||
if (from._has_bits_[0]) {
|
||||
if (from.has_key()) {
|
||||
KeyTypeHandler::EnsureMutable(&key_, Base::GetArenaForAllocation());
|
||||
KeyTypeHandler::Merge(from.key(), &key_, Base::GetArenaForAllocation());
|
||||
set_has_key();
|
||||
}
|
||||
if (from.has_value()) {
|
||||
ValueTypeHandler::EnsureMutable(&value_, Base::GetArenaForAllocation());
|
||||
ValueTypeHandler::Merge(from.value(), &value_,
|
||||
Base::GetArenaForAllocation());
|
||||
set_has_value();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
void Clear() override {
|
||||
KeyTypeHandler::Clear(&key_, Base::GetArenaForAllocation());
|
||||
ValueTypeHandler::Clear(&value_, Base::GetArenaForAllocation());
|
||||
clear_has_key();
|
||||
clear_has_value();
|
||||
}
|
||||
|
||||
// Parsing using MergePartialFromCodedStream, above, is not as
|
||||
// efficient as it could be. This helper class provides a speedier way.
|
||||
template <typename MapField, typename Map>
|
||||
class Parser {
|
||||
public:
|
||||
explicit Parser(MapField* mf) : mf_(mf), map_(mf->MutableMap()) {}
|
||||
~Parser() {
|
||||
if (entry_ != nullptr && entry_->GetArenaForAllocation() == nullptr)
|
||||
delete entry_;
|
||||
}
|
||||
|
||||
const char* _InternalParse(const char* ptr, ParseContext* ctx) {
|
||||
if (PROTOBUF_PREDICT_TRUE(!ctx->Done(&ptr) && *ptr == kKeyTag)) {
|
||||
ptr = KeyTypeHandler::Read(ptr + 1, ctx, &key_);
|
||||
if (PROTOBUF_PREDICT_FALSE(!ptr || !Derived::ValidateKey(&key_))) {
|
||||
return nullptr;
|
||||
}
|
||||
if (PROTOBUF_PREDICT_TRUE(!ctx->Done(&ptr) && *ptr == kValueTag)) {
|
||||
typename Map::size_type map_size = map_->size();
|
||||
value_ptr_ = &(*map_)[key_];
|
||||
if (PROTOBUF_PREDICT_TRUE(map_size != map_->size())) {
|
||||
using T =
|
||||
typename MapIf<ValueTypeHandler::kIsEnum, int*, Value*>::type;
|
||||
ptr = ValueTypeHandler::Read(ptr + 1, ctx,
|
||||
reinterpret_cast<T>(value_ptr_));
|
||||
if (PROTOBUF_PREDICT_FALSE(!ptr ||
|
||||
!Derived::ValidateValue(value_ptr_))) {
|
||||
map_->erase(key_); // Failure! Undo insertion.
|
||||
return nullptr;
|
||||
}
|
||||
if (PROTOBUF_PREDICT_TRUE(ctx->Done(&ptr))) return ptr;
|
||||
if (!ptr) return nullptr;
|
||||
NewEntry();
|
||||
ValueMover::Move(value_ptr_, entry_->mutable_value());
|
||||
map_->erase(key_);
|
||||
goto move_key;
|
||||
}
|
||||
} else {
|
||||
if (!ptr) return nullptr;
|
||||
}
|
||||
NewEntry();
|
||||
move_key:
|
||||
KeyMover::Move(&key_, entry_->mutable_key());
|
||||
} else {
|
||||
if (!ptr) return nullptr;
|
||||
NewEntry();
|
||||
}
|
||||
ptr = entry_->_InternalParse(ptr, ctx);
|
||||
if (ptr) UseKeyAndValueFromEntry();
|
||||
return ptr;
|
||||
}
|
||||
|
||||
template <typename UnknownType>
|
||||
const char* ParseWithEnumValidation(const char* ptr, ParseContext* ctx,
|
||||
bool (*is_valid)(int),
|
||||
uint32_t field_num,
|
||||
InternalMetadata* metadata) {
|
||||
auto entry = NewEntry();
|
||||
ptr = entry->_InternalParse(ptr, ctx);
|
||||
if (!ptr) return nullptr;
|
||||
if (is_valid(entry->value())) {
|
||||
UseKeyAndValueFromEntry();
|
||||
} else {
|
||||
WriteLengthDelimited(field_num, entry->SerializeAsString(),
|
||||
metadata->mutable_unknown_fields<UnknownType>());
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
MapEntryImpl* NewEntry() { return entry_ = mf_->NewEntry(); }
|
||||
|
||||
const Key& key() const { return key_; }
|
||||
const Value& value() const { return *value_ptr_; }
|
||||
|
||||
const Key& entry_key() const { return entry_->key(); }
|
||||
const Value& entry_value() const { return entry_->value(); }
|
||||
|
||||
private:
|
||||
void UseKeyAndValueFromEntry() {
|
||||
// Update key_ in case we need it later (because key() is called).
|
||||
// This is potentially inefficient, especially if the key is
|
||||
// expensive to copy (e.g., a long string), but this is a cold
|
||||
// path, so it's not a big deal.
|
||||
key_ = entry_->key();
|
||||
value_ptr_ = &(*map_)[key_];
|
||||
ValueMover::Move(entry_->mutable_value(), value_ptr_);
|
||||
}
|
||||
|
||||
// After reading a key and value successfully, and inserting that data
|
||||
// into map_, we are not at the end of the input. This is unusual, but
|
||||
// allowed by the spec.
|
||||
bool ReadBeyondKeyValuePair(io::CodedInputStream* input) PROTOBUF_COLD {
|
||||
NewEntry();
|
||||
ValueMover::Move(value_ptr_, entry_->mutable_value());
|
||||
map_->erase(key_);
|
||||
KeyMover::Move(&key_, entry_->mutable_key());
|
||||
const bool result = entry_->MergePartialFromCodedStream(input);
|
||||
if (result) UseKeyAndValueFromEntry();
|
||||
return result;
|
||||
}
|
||||
|
||||
typedef MoveHelper<KeyTypeHandler::kIsEnum, KeyTypeHandler::kIsMessage,
|
||||
KeyTypeHandler::kWireType ==
|
||||
WireFormatLite::WIRETYPE_LENGTH_DELIMITED,
|
||||
Key>
|
||||
KeyMover;
|
||||
typedef MoveHelper<ValueTypeHandler::kIsEnum, ValueTypeHandler::kIsMessage,
|
||||
ValueTypeHandler::kWireType ==
|
||||
WireFormatLite::WIRETYPE_LENGTH_DELIMITED,
|
||||
Value>
|
||||
ValueMover;
|
||||
|
||||
MapField* const mf_;
|
||||
Map* const map_;
|
||||
Key key_;
|
||||
Value* value_ptr_;
|
||||
MapEntryImpl* entry_ = nullptr;
|
||||
};
|
||||
|
||||
protected:
|
||||
void set_has_key() { _has_bits_[0] |= 0x00000001u; }
|
||||
bool has_key() const { return (_has_bits_[0] & 0x00000001u) != 0; }
|
||||
void clear_has_key() { _has_bits_[0] &= ~0x00000001u; }
|
||||
void set_has_value() { _has_bits_[0] |= 0x00000002u; }
|
||||
bool has_value() const { return (_has_bits_[0] & 0x00000002u) != 0; }
|
||||
void clear_has_value() { _has_bits_[0] &= ~0x00000002u; }
|
||||
|
||||
public:
|
||||
inline Arena* GetArena() const { return Base::GetArena(); }
|
||||
|
||||
protected: // Needed for constructing tables
|
||||
KeyOnMemory key_;
|
||||
ValueOnMemory value_;
|
||||
uint32_t _has_bits_[1];
|
||||
|
||||
private:
|
||||
friend class ::PROTOBUF_NAMESPACE_ID::Arena;
|
||||
typedef void InternalArenaConstructable_;
|
||||
typedef void DestructorSkippable_;
|
||||
template <typename C, typename K, typename V, WireFormatLite::FieldType,
|
||||
WireFormatLite::FieldType>
|
||||
friend class internal::MapEntry;
|
||||
template <typename C, typename K, typename V, WireFormatLite::FieldType,
|
||||
WireFormatLite::FieldType>
|
||||
friend class internal::MapFieldLite;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntryImpl);
|
||||
};
|
||||
|
||||
template <typename T, typename Key, typename Value,
|
||||
WireFormatLite::FieldType kKeyFieldType,
|
||||
WireFormatLite::FieldType kValueFieldType>
|
||||
class MapEntryLite : public MapEntryImpl<T, MessageLite, Key, Value,
|
||||
kKeyFieldType, kValueFieldType> {
|
||||
public:
|
||||
typedef MapEntryImpl<T, MessageLite, Key, Value, kKeyFieldType,
|
||||
kValueFieldType>
|
||||
SuperType;
|
||||
constexpr MapEntryLite() {}
|
||||
explicit MapEntryLite(Arena* arena) : SuperType(arena) {}
|
||||
~MapEntryLite() override {
|
||||
MessageLite::_internal_metadata_.template Delete<std::string>();
|
||||
}
|
||||
void MergeFrom(const MapEntryLite& other) { MergeFromInternal(other); }
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntryLite);
|
||||
};
|
||||
|
||||
// Helpers for deterministic serialization =============================
|
||||
|
||||
// Iterator base for MapSorterFlat and MapSorterPtr.
|
||||
template <typename storage_type>
|
||||
struct MapSorterIt {
|
||||
storage_type* ptr;
|
||||
MapSorterIt(storage_type* ptr) : ptr(ptr) {}
|
||||
bool operator==(const MapSorterIt& other) const { return ptr == other.ptr; }
|
||||
bool operator!=(const MapSorterIt& other) const { return !(*this == other); }
|
||||
MapSorterIt& operator++() { ++ptr; return *this; }
|
||||
MapSorterIt operator++(int) { auto other = *this; ++ptr; return other; }
|
||||
MapSorterIt operator+(int v) { return MapSorterIt{ptr + v}; }
|
||||
};
|
||||
|
||||
// MapSorterFlat stores keys inline with pointers to map entries, so that
|
||||
// keys can be compared without indirection. This type is used for maps with
|
||||
// keys that are not strings.
|
||||
template <typename MapT>
|
||||
class MapSorterFlat {
|
||||
public:
|
||||
using value_type = typename MapT::value_type;
|
||||
using storage_type = std::pair<typename MapT::key_type, const value_type*>;
|
||||
|
||||
// This const_iterator dereferenes to the map entry stored in the sorting
|
||||
// array pairs. This is the same interface as the Map::const_iterator type,
|
||||
// and allows generated code to use the same loop body with either form:
|
||||
// for (const auto& entry : map) { ... }
|
||||
// for (const auto& entry : MapSorterFlat(map)) { ... }
|
||||
struct const_iterator : public MapSorterIt<storage_type> {
|
||||
using pointer = const typename MapT::value_type*;
|
||||
using reference = const typename MapT::value_type&;
|
||||
using MapSorterIt<storage_type>::MapSorterIt;
|
||||
|
||||
pointer operator->() const { return this->ptr->second; }
|
||||
reference operator*() const { return *this->operator->(); }
|
||||
};
|
||||
|
||||
explicit MapSorterFlat(const MapT& m)
|
||||
: size_(m.size()), items_(size_ ? new storage_type[size_] : nullptr) {
|
||||
if (!size_) return;
|
||||
storage_type* it = &items_[0];
|
||||
for (const auto& entry : m) {
|
||||
*it++ = {entry.first, &entry};
|
||||
}
|
||||
std::sort(&items_[0], &items_[size_],
|
||||
[](const storage_type& a, const storage_type& b) {
|
||||
return a.first < b.first;
|
||||
});
|
||||
}
|
||||
size_t size() const { return size_; }
|
||||
const_iterator begin() const { return {items_.get()}; }
|
||||
const_iterator end() const { return {items_.get() + size_}; }
|
||||
|
||||
private:
|
||||
size_t size_;
|
||||
std::unique_ptr<storage_type[]> items_;
|
||||
};
|
||||
|
||||
// MapSorterPtr stores and sorts pointers to map entries. This type is used for
|
||||
// maps with keys that are strings.
|
||||
template <typename MapT>
|
||||
class MapSorterPtr {
|
||||
public:
|
||||
using value_type = typename MapT::value_type;
|
||||
using storage_type = const typename MapT::value_type*;
|
||||
|
||||
// This const_iterator dereferenes the map entry pointer stored in the sorting
|
||||
// array. This is the same interface as the Map::const_iterator type, and
|
||||
// allows generated code to use the same loop body with either form:
|
||||
// for (const auto& entry : map) { ... }
|
||||
// for (const auto& entry : MapSorterPtr(map)) { ... }
|
||||
struct const_iterator : public MapSorterIt<storage_type> {
|
||||
using pointer = const typename MapT::value_type*;
|
||||
using reference = const typename MapT::value_type&;
|
||||
using MapSorterIt<storage_type>::MapSorterIt;
|
||||
|
||||
pointer operator->() const { return *this->ptr; }
|
||||
reference operator*() const { return *this->operator->(); }
|
||||
};
|
||||
|
||||
explicit MapSorterPtr(const MapT& m)
|
||||
: size_(m.size()), items_(size_ ? new storage_type[size_] : nullptr) {
|
||||
if (!size_) return;
|
||||
storage_type* it = &items_[0];
|
||||
for (const auto& entry : m) {
|
||||
*it++ = &entry;
|
||||
}
|
||||
std::sort(&items_[0], &items_[size_],
|
||||
[](const storage_type& a, const storage_type& b) {
|
||||
return a->first < b->first;
|
||||
});
|
||||
}
|
||||
size_t size() const { return size_; }
|
||||
const_iterator begin() const { return {items_.get()}; }
|
||||
const_iterator end() const { return {items_.get() + size_}; }
|
||||
|
||||
private:
|
||||
size_t size_;
|
||||
std::unique_ptr<storage_type[]> items_;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_MAP_ENTRY_LITE_H__
|
||||
@@ -1,946 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_MAP_FIELD_H__
|
||||
#define GOOGLE_PROTOBUF_MAP_FIELD_H__
|
||||
|
||||
#include <atomic>
|
||||
#include <functional>
|
||||
|
||||
#include <google/protobuf/arena.h>
|
||||
#include <google/protobuf/stubs/mutex.h>
|
||||
#include <google/protobuf/port.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/generated_message_reflection.h>
|
||||
#include <google/protobuf/generated_message_util.h>
|
||||
#include <google/protobuf/map_entry.h>
|
||||
#include <google/protobuf/map_field_lite.h>
|
||||
#include <google/protobuf/map_type_handler.h>
|
||||
#include <google/protobuf/message.h>
|
||||
#include <google/protobuf/repeated_field.h>
|
||||
#include <google/protobuf/unknown_field_set.h>
|
||||
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
#ifdef SWIG
|
||||
#error "You cannot SWIG proto headers"
|
||||
#endif
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
class DynamicMessage;
|
||||
class MapIterator;
|
||||
|
||||
// Microsoft compiler complains about non-virtual destructor,
|
||||
// even when the destructor is private.
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4265)
|
||||
#endif // _MSC_VER
|
||||
|
||||
#define TYPE_CHECK(EXPECTEDTYPE, METHOD) \
|
||||
if (type() != EXPECTEDTYPE) { \
|
||||
GOOGLE_LOG(FATAL) << "Protocol Buffer map usage error:\n" \
|
||||
<< METHOD << " type does not match\n" \
|
||||
<< " Expected : " \
|
||||
<< FieldDescriptor::CppTypeName(EXPECTEDTYPE) << "\n" \
|
||||
<< " Actual : " << FieldDescriptor::CppTypeName(type()); \
|
||||
}
|
||||
|
||||
// MapKey is an union type for representing any possible
|
||||
// map key.
|
||||
class PROTOBUF_EXPORT MapKey {
|
||||
public:
|
||||
MapKey() : type_() {}
|
||||
MapKey(const MapKey& other) : type_() { CopyFrom(other); }
|
||||
|
||||
MapKey& operator=(const MapKey& other) {
|
||||
CopyFrom(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
~MapKey() {
|
||||
if (type_ == FieldDescriptor::CPPTYPE_STRING) {
|
||||
val_.string_value_.Destruct();
|
||||
}
|
||||
}
|
||||
|
||||
FieldDescriptor::CppType type() const {
|
||||
if (type_ == FieldDescriptor::CppType()) {
|
||||
GOOGLE_LOG(FATAL) << "Protocol Buffer map usage error:\n"
|
||||
<< "MapKey::type MapKey is not initialized. "
|
||||
<< "Call set methods to initialize MapKey.";
|
||||
}
|
||||
return type_;
|
||||
}
|
||||
|
||||
void SetInt64Value(int64_t value) {
|
||||
SetType(FieldDescriptor::CPPTYPE_INT64);
|
||||
val_.int64_value_ = value;
|
||||
}
|
||||
void SetUInt64Value(uint64_t value) {
|
||||
SetType(FieldDescriptor::CPPTYPE_UINT64);
|
||||
val_.uint64_value_ = value;
|
||||
}
|
||||
void SetInt32Value(int32_t value) {
|
||||
SetType(FieldDescriptor::CPPTYPE_INT32);
|
||||
val_.int32_value_ = value;
|
||||
}
|
||||
void SetUInt32Value(uint32_t value) {
|
||||
SetType(FieldDescriptor::CPPTYPE_UINT32);
|
||||
val_.uint32_value_ = value;
|
||||
}
|
||||
void SetBoolValue(bool value) {
|
||||
SetType(FieldDescriptor::CPPTYPE_BOOL);
|
||||
val_.bool_value_ = value;
|
||||
}
|
||||
void SetStringValue(std::string val) {
|
||||
SetType(FieldDescriptor::CPPTYPE_STRING);
|
||||
*val_.string_value_.get_mutable() = std::move(val);
|
||||
}
|
||||
|
||||
int64_t GetInt64Value() const {
|
||||
TYPE_CHECK(FieldDescriptor::CPPTYPE_INT64, "MapKey::GetInt64Value");
|
||||
return val_.int64_value_;
|
||||
}
|
||||
uint64_t GetUInt64Value() const {
|
||||
TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT64, "MapKey::GetUInt64Value");
|
||||
return val_.uint64_value_;
|
||||
}
|
||||
int32_t GetInt32Value() const {
|
||||
TYPE_CHECK(FieldDescriptor::CPPTYPE_INT32, "MapKey::GetInt32Value");
|
||||
return val_.int32_value_;
|
||||
}
|
||||
uint32_t GetUInt32Value() const {
|
||||
TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT32, "MapKey::GetUInt32Value");
|
||||
return val_.uint32_value_;
|
||||
}
|
||||
bool GetBoolValue() const {
|
||||
TYPE_CHECK(FieldDescriptor::CPPTYPE_BOOL, "MapKey::GetBoolValue");
|
||||
return val_.bool_value_;
|
||||
}
|
||||
const std::string& GetStringValue() const {
|
||||
TYPE_CHECK(FieldDescriptor::CPPTYPE_STRING, "MapKey::GetStringValue");
|
||||
return val_.string_value_.get();
|
||||
}
|
||||
|
||||
bool operator<(const MapKey& other) const {
|
||||
if (type_ != other.type_) {
|
||||
// We could define a total order that handles this case, but
|
||||
// there currently no need. So, for now, fail.
|
||||
GOOGLE_LOG(FATAL) << "Unsupported: type mismatch";
|
||||
}
|
||||
switch (type()) {
|
||||
case FieldDescriptor::CPPTYPE_DOUBLE:
|
||||
case FieldDescriptor::CPPTYPE_FLOAT:
|
||||
case FieldDescriptor::CPPTYPE_ENUM:
|
||||
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||
GOOGLE_LOG(FATAL) << "Unsupported";
|
||||
return false;
|
||||
case FieldDescriptor::CPPTYPE_STRING:
|
||||
return val_.string_value_.get() < other.val_.string_value_.get();
|
||||
case FieldDescriptor::CPPTYPE_INT64:
|
||||
return val_.int64_value_ < other.val_.int64_value_;
|
||||
case FieldDescriptor::CPPTYPE_INT32:
|
||||
return val_.int32_value_ < other.val_.int32_value_;
|
||||
case FieldDescriptor::CPPTYPE_UINT64:
|
||||
return val_.uint64_value_ < other.val_.uint64_value_;
|
||||
case FieldDescriptor::CPPTYPE_UINT32:
|
||||
return val_.uint32_value_ < other.val_.uint32_value_;
|
||||
case FieldDescriptor::CPPTYPE_BOOL:
|
||||
return val_.bool_value_ < other.val_.bool_value_;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool operator==(const MapKey& other) const {
|
||||
if (type_ != other.type_) {
|
||||
// To be consistent with operator<, we don't allow this either.
|
||||
GOOGLE_LOG(FATAL) << "Unsupported: type mismatch";
|
||||
}
|
||||
switch (type()) {
|
||||
case FieldDescriptor::CPPTYPE_DOUBLE:
|
||||
case FieldDescriptor::CPPTYPE_FLOAT:
|
||||
case FieldDescriptor::CPPTYPE_ENUM:
|
||||
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||
GOOGLE_LOG(FATAL) << "Unsupported";
|
||||
break;
|
||||
case FieldDescriptor::CPPTYPE_STRING:
|
||||
return val_.string_value_.get() == other.val_.string_value_.get();
|
||||
case FieldDescriptor::CPPTYPE_INT64:
|
||||
return val_.int64_value_ == other.val_.int64_value_;
|
||||
case FieldDescriptor::CPPTYPE_INT32:
|
||||
return val_.int32_value_ == other.val_.int32_value_;
|
||||
case FieldDescriptor::CPPTYPE_UINT64:
|
||||
return val_.uint64_value_ == other.val_.uint64_value_;
|
||||
case FieldDescriptor::CPPTYPE_UINT32:
|
||||
return val_.uint32_value_ == other.val_.uint32_value_;
|
||||
case FieldDescriptor::CPPTYPE_BOOL:
|
||||
return val_.bool_value_ == other.val_.bool_value_;
|
||||
}
|
||||
GOOGLE_LOG(FATAL) << "Can't get here.";
|
||||
return false;
|
||||
}
|
||||
|
||||
void CopyFrom(const MapKey& other) {
|
||||
SetType(other.type());
|
||||
switch (type_) {
|
||||
case FieldDescriptor::CPPTYPE_DOUBLE:
|
||||
case FieldDescriptor::CPPTYPE_FLOAT:
|
||||
case FieldDescriptor::CPPTYPE_ENUM:
|
||||
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||
GOOGLE_LOG(FATAL) << "Unsupported";
|
||||
break;
|
||||
case FieldDescriptor::CPPTYPE_STRING:
|
||||
*val_.string_value_.get_mutable() = other.val_.string_value_.get();
|
||||
break;
|
||||
case FieldDescriptor::CPPTYPE_INT64:
|
||||
val_.int64_value_ = other.val_.int64_value_;
|
||||
break;
|
||||
case FieldDescriptor::CPPTYPE_INT32:
|
||||
val_.int32_value_ = other.val_.int32_value_;
|
||||
break;
|
||||
case FieldDescriptor::CPPTYPE_UINT64:
|
||||
val_.uint64_value_ = other.val_.uint64_value_;
|
||||
break;
|
||||
case FieldDescriptor::CPPTYPE_UINT32:
|
||||
val_.uint32_value_ = other.val_.uint32_value_;
|
||||
break;
|
||||
case FieldDescriptor::CPPTYPE_BOOL:
|
||||
val_.bool_value_ = other.val_.bool_value_;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename K, typename V>
|
||||
friend class internal::TypeDefinedMapFieldBase;
|
||||
friend class ::PROTOBUF_NAMESPACE_ID::MapIterator;
|
||||
friend class internal::DynamicMapField;
|
||||
|
||||
union KeyValue {
|
||||
KeyValue() {}
|
||||
internal::ExplicitlyConstructed<std::string> string_value_;
|
||||
int64_t int64_value_;
|
||||
int32_t int32_value_;
|
||||
uint64_t uint64_value_;
|
||||
uint32_t uint32_value_;
|
||||
bool bool_value_;
|
||||
} val_;
|
||||
|
||||
void SetType(FieldDescriptor::CppType type) {
|
||||
if (type_ == type) return;
|
||||
if (type_ == FieldDescriptor::CPPTYPE_STRING) {
|
||||
val_.string_value_.Destruct();
|
||||
}
|
||||
type_ = type;
|
||||
if (type_ == FieldDescriptor::CPPTYPE_STRING) {
|
||||
val_.string_value_.DefaultConstruct();
|
||||
}
|
||||
}
|
||||
|
||||
// type_ is 0 or a valid FieldDescriptor::CppType.
|
||||
// Use "CppType()" to indicate zero.
|
||||
FieldDescriptor::CppType type_;
|
||||
};
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
namespace std {
|
||||
template <>
|
||||
struct hash<::PROTOBUF_NAMESPACE_ID::MapKey> {
|
||||
size_t operator()(const ::PROTOBUF_NAMESPACE_ID::MapKey& map_key) const {
|
||||
switch (map_key.type()) {
|
||||
case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_DOUBLE:
|
||||
case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_FLOAT:
|
||||
case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_ENUM:
|
||||
case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_MESSAGE:
|
||||
GOOGLE_LOG(FATAL) << "Unsupported";
|
||||
break;
|
||||
case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_STRING:
|
||||
return hash<std::string>()(map_key.GetStringValue());
|
||||
case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_INT64: {
|
||||
auto value = map_key.GetInt64Value();
|
||||
return hash<decltype(value)>()(value);
|
||||
}
|
||||
case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_INT32: {
|
||||
auto value = map_key.GetInt32Value();
|
||||
return hash<decltype(value)>()(map_key.GetInt32Value());
|
||||
}
|
||||
case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_UINT64: {
|
||||
auto value = map_key.GetUInt64Value();
|
||||
return hash<decltype(value)>()(map_key.GetUInt64Value());
|
||||
}
|
||||
case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_UINT32: {
|
||||
auto value = map_key.GetUInt32Value();
|
||||
return hash<decltype(value)>()(map_key.GetUInt32Value());
|
||||
}
|
||||
case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_BOOL: {
|
||||
return hash<bool>()(map_key.GetBoolValue());
|
||||
}
|
||||
}
|
||||
GOOGLE_LOG(FATAL) << "Can't get here.";
|
||||
return 0;
|
||||
}
|
||||
bool operator()(const ::PROTOBUF_NAMESPACE_ID::MapKey& map_key1,
|
||||
const ::PROTOBUF_NAMESPACE_ID::MapKey& map_key2) const {
|
||||
return map_key1 < map_key2;
|
||||
}
|
||||
};
|
||||
} // namespace std
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
class ContendedMapCleanTest;
|
||||
class GeneratedMessageReflection;
|
||||
class MapFieldAccessor;
|
||||
|
||||
// This class provides access to map field using reflection, which is the same
|
||||
// as those provided for RepeatedPtrField<Message>. It is used for internal
|
||||
// reflection implementation only. Users should never use this directly.
|
||||
class PROTOBUF_EXPORT MapFieldBase {
|
||||
public:
|
||||
MapFieldBase()
|
||||
: arena_(nullptr), repeated_field_(nullptr), state_(STATE_MODIFIED_MAP) {}
|
||||
|
||||
// This constructor is for constant initialized global instances.
|
||||
// It uses a linker initialized mutex, so it is not compatible with regular
|
||||
// runtime instances.
|
||||
// Except in MSVC, where we can't have a constinit mutex.
|
||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||
constexpr MapFieldBase(ConstantInitialized)
|
||||
: arena_(nullptr),
|
||||
repeated_field_(nullptr),
|
||||
mutex_(GOOGLE_PROTOBUF_LINKER_INITIALIZED),
|
||||
state_(STATE_MODIFIED_MAP) {}
|
||||
explicit MapFieldBase(Arena* arena)
|
||||
: arena_(arena), repeated_field_(nullptr), state_(STATE_MODIFIED_MAP) {}
|
||||
|
||||
protected:
|
||||
~MapFieldBase() { // "protected" stops users from deleting a `MapFieldBase *`
|
||||
GOOGLE_DCHECK(repeated_field_ == nullptr);
|
||||
}
|
||||
void Destruct();
|
||||
|
||||
public:
|
||||
// Returns reference to internal repeated field. Data written using
|
||||
// Map's api prior to calling this function is guarantted to be
|
||||
// included in repeated field.
|
||||
const RepeatedPtrFieldBase& GetRepeatedField() const;
|
||||
|
||||
// Like above. Returns mutable pointer to the internal repeated field.
|
||||
RepeatedPtrFieldBase* MutableRepeatedField();
|
||||
|
||||
// Pure virtual map APIs for Map Reflection.
|
||||
virtual bool ContainsMapKey(const MapKey& map_key) const = 0;
|
||||
virtual bool InsertOrLookupMapValue(const MapKey& map_key,
|
||||
MapValueRef* val) = 0;
|
||||
virtual bool LookupMapValue(const MapKey& map_key,
|
||||
MapValueConstRef* val) const = 0;
|
||||
bool LookupMapValue(const MapKey&, MapValueRef*) const = delete;
|
||||
|
||||
// Returns whether changes to the map are reflected in the repeated field.
|
||||
bool IsRepeatedFieldValid() const;
|
||||
// Insures operations after won't get executed before calling this.
|
||||
bool IsMapValid() const;
|
||||
virtual bool DeleteMapValue(const MapKey& map_key) = 0;
|
||||
virtual bool EqualIterator(const MapIterator& a,
|
||||
const MapIterator& b) const = 0;
|
||||
virtual void MapBegin(MapIterator* map_iter) const = 0;
|
||||
virtual void MapEnd(MapIterator* map_iter) const = 0;
|
||||
virtual void MergeFrom(const MapFieldBase& other) = 0;
|
||||
virtual void Swap(MapFieldBase* other);
|
||||
virtual void UnsafeShallowSwap(MapFieldBase* other);
|
||||
// Sync Map with repeated field and returns the size of map.
|
||||
virtual int size() const = 0;
|
||||
virtual void Clear() = 0;
|
||||
|
||||
// Returns the number of bytes used by the repeated field, excluding
|
||||
// sizeof(*this)
|
||||
size_t SpaceUsedExcludingSelfLong() const;
|
||||
|
||||
int SpaceUsedExcludingSelf() const {
|
||||
return internal::ToIntSize(SpaceUsedExcludingSelfLong());
|
||||
}
|
||||
|
||||
protected:
|
||||
// Gets the size of space used by map field.
|
||||
virtual size_t SpaceUsedExcludingSelfNoLock() const;
|
||||
|
||||
// Synchronizes the content in Map to RepeatedPtrField if there is any change
|
||||
// to Map after last synchronization.
|
||||
void SyncRepeatedFieldWithMap() const;
|
||||
virtual void SyncRepeatedFieldWithMapNoLock() const;
|
||||
|
||||
// Synchronizes the content in RepeatedPtrField to Map if there is any change
|
||||
// to RepeatedPtrField after last synchronization.
|
||||
void SyncMapWithRepeatedField() const;
|
||||
virtual void SyncMapWithRepeatedFieldNoLock() const {}
|
||||
|
||||
// Tells MapFieldBase that there is new change to Map.
|
||||
void SetMapDirty();
|
||||
|
||||
// Tells MapFieldBase that there is new change to RepeatedPtrField.
|
||||
void SetRepeatedDirty();
|
||||
|
||||
// Provides derived class the access to repeated field.
|
||||
void* MutableRepeatedPtrField() const;
|
||||
|
||||
void InternalSwap(MapFieldBase* other);
|
||||
|
||||
// Support thread sanitizer (tsan) by making const / mutable races
|
||||
// more apparent. If one thread calls MutableAccess() while another
|
||||
// thread calls either ConstAccess() or MutableAccess(), on the same
|
||||
// MapFieldBase-derived object, and there is no synchronization going
|
||||
// on between them, tsan will alert.
|
||||
#if defined(__SANITIZE_THREAD__) || defined(THREAD_SANITIZER)
|
||||
void ConstAccess() const { GOOGLE_CHECK_EQ(seq1_, seq2_); }
|
||||
void MutableAccess() {
|
||||
if (seq1_ & 1) {
|
||||
seq2_ = ++seq1_;
|
||||
} else {
|
||||
seq1_ = ++seq2_;
|
||||
}
|
||||
}
|
||||
unsigned int seq1_ = 0, seq2_ = 0;
|
||||
#else
|
||||
void ConstAccess() const {}
|
||||
void MutableAccess() {}
|
||||
#endif
|
||||
enum State {
|
||||
STATE_MODIFIED_MAP = 0, // map has newly added data that has not been
|
||||
// synchronized to repeated field
|
||||
STATE_MODIFIED_REPEATED = 1, // repeated field has newly added data that
|
||||
// has not been synchronized to map
|
||||
CLEAN = 2, // data in map and repeated field are same
|
||||
};
|
||||
|
||||
Arena* arena_;
|
||||
mutable RepeatedPtrField<Message>* repeated_field_;
|
||||
|
||||
mutable internal::WrappedMutex
|
||||
mutex_; // The thread to synchronize map and repeated field
|
||||
// needs to get lock first;
|
||||
mutable std::atomic<State> state_;
|
||||
|
||||
private:
|
||||
friend class ContendedMapCleanTest;
|
||||
friend class GeneratedMessageReflection;
|
||||
friend class MapFieldAccessor;
|
||||
friend class ::PROTOBUF_NAMESPACE_ID::Reflection;
|
||||
friend class ::PROTOBUF_NAMESPACE_ID::DynamicMessage;
|
||||
|
||||
// Virtual helper methods for MapIterator. MapIterator doesn't have the
|
||||
// type helper for key and value. Call these help methods to deal with
|
||||
// different types. Real helper methods are implemented in
|
||||
// TypeDefinedMapFieldBase.
|
||||
friend class ::PROTOBUF_NAMESPACE_ID::MapIterator;
|
||||
// Allocate map<...>::iterator for MapIterator.
|
||||
virtual void InitializeIterator(MapIterator* map_iter) const = 0;
|
||||
|
||||
// DeleteIterator() is called by the destructor of MapIterator only.
|
||||
// It deletes map<...>::iterator for MapIterator.
|
||||
virtual void DeleteIterator(MapIterator* map_iter) const = 0;
|
||||
|
||||
// Copy the map<...>::iterator from other_iterator to
|
||||
// this_iterator.
|
||||
virtual void CopyIterator(MapIterator* this_iterator,
|
||||
const MapIterator& other_iterator) const = 0;
|
||||
|
||||
// IncreaseIterator() is called by operator++() of MapIterator only.
|
||||
// It implements the ++ operator of MapIterator.
|
||||
virtual void IncreaseIterator(MapIterator* map_iter) const = 0;
|
||||
|
||||
// Swaps state_ with another MapFieldBase
|
||||
void SwapState(MapFieldBase* other);
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapFieldBase);
|
||||
};
|
||||
|
||||
// This class provides common Map Reflection implementations for generated
|
||||
// message and dynamic message.
|
||||
template <typename Key, typename T>
|
||||
class TypeDefinedMapFieldBase : public MapFieldBase {
|
||||
public:
|
||||
TypeDefinedMapFieldBase() {}
|
||||
|
||||
// This constructor is for constant initialized global instances.
|
||||
// It uses a linker initialized mutex, so it is not compatible with regular
|
||||
// runtime instances.
|
||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||
constexpr TypeDefinedMapFieldBase(ConstantInitialized tag)
|
||||
: MapFieldBase(tag) {}
|
||||
explicit TypeDefinedMapFieldBase(Arena* arena) : MapFieldBase(arena) {}
|
||||
TypeDefinedMapFieldBase(ArenaInitialized, Arena* arena)
|
||||
: TypeDefinedMapFieldBase(arena) {}
|
||||
|
||||
protected:
|
||||
~TypeDefinedMapFieldBase() {}
|
||||
using MapFieldBase::Destruct;
|
||||
|
||||
public:
|
||||
void MapBegin(MapIterator* map_iter) const override;
|
||||
void MapEnd(MapIterator* map_iter) const override;
|
||||
bool EqualIterator(const MapIterator& a, const MapIterator& b) const override;
|
||||
|
||||
virtual const Map<Key, T>& GetMap() const = 0;
|
||||
virtual Map<Key, T>* MutableMap() = 0;
|
||||
|
||||
protected:
|
||||
typename Map<Key, T>::const_iterator& InternalGetIterator(
|
||||
const MapIterator* map_iter) const;
|
||||
|
||||
private:
|
||||
void InitializeIterator(MapIterator* map_iter) const override;
|
||||
void DeleteIterator(MapIterator* map_iter) const override;
|
||||
void CopyIterator(MapIterator* this_iteratorm,
|
||||
const MapIterator& that_iterator) const override;
|
||||
void IncreaseIterator(MapIterator* map_iter) const override;
|
||||
|
||||
virtual void SetMapIteratorValue(MapIterator* map_iter) const = 0;
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TypeDefinedMapFieldBase);
|
||||
};
|
||||
|
||||
// This class provides access to map field using generated api. It is used for
|
||||
// internal generated message implementation only. Users should never use this
|
||||
// directly.
|
||||
template <typename Derived, typename Key, typename T,
|
||||
WireFormatLite::FieldType kKeyFieldType,
|
||||
WireFormatLite::FieldType kValueFieldType>
|
||||
class MapField : public TypeDefinedMapFieldBase<Key, T> {
|
||||
// Provide utilities to parse/serialize key/value. Provide utilities to
|
||||
// manipulate internal stored type.
|
||||
typedef MapTypeHandler<kKeyFieldType, Key> KeyTypeHandler;
|
||||
typedef MapTypeHandler<kValueFieldType, T> ValueTypeHandler;
|
||||
|
||||
// Define message type for internal repeated field.
|
||||
typedef Derived EntryType;
|
||||
|
||||
// Define abbreviation for parent MapFieldLite
|
||||
typedef MapFieldLite<Derived, Key, T, kKeyFieldType, kValueFieldType>
|
||||
MapFieldLiteType;
|
||||
|
||||
// Enum needs to be handled differently from other types because it has
|
||||
// different exposed type in Map's api and repeated field's api. For
|
||||
// details see the comment in the implementation of
|
||||
// SyncMapWithRepeatedFieldNoLock.
|
||||
static constexpr bool kIsValueEnum = ValueTypeHandler::kIsEnum;
|
||||
typedef typename MapIf<kIsValueEnum, T, const T&>::type CastValueType;
|
||||
|
||||
public:
|
||||
typedef Map<Key, T> MapType;
|
||||
|
||||
MapField() : impl_() {}
|
||||
virtual ~MapField() {} // Destruct() must already have been called!
|
||||
void Destruct() {
|
||||
impl_.Destruct();
|
||||
TypeDefinedMapFieldBase<Key, T>::Destruct();
|
||||
}
|
||||
|
||||
// This constructor is for constant initialized global instances.
|
||||
// It uses a linker initialized mutex, so it is not compatible with regular
|
||||
// runtime instances.
|
||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||
constexpr MapField(ConstantInitialized tag)
|
||||
: TypeDefinedMapFieldBase<Key, T>(tag), impl_() {}
|
||||
explicit MapField(Arena* arena)
|
||||
: TypeDefinedMapFieldBase<Key, T>(arena), impl_(arena) {}
|
||||
MapField(ArenaInitialized, Arena* arena) : MapField(arena) {}
|
||||
|
||||
// Implement MapFieldBase
|
||||
bool ContainsMapKey(const MapKey& map_key) const override;
|
||||
bool InsertOrLookupMapValue(const MapKey& map_key, MapValueRef* val) override;
|
||||
bool LookupMapValue(const MapKey& map_key,
|
||||
MapValueConstRef* val) const override;
|
||||
bool LookupMapValue(const MapKey&, MapValueRef*) const = delete;
|
||||
bool DeleteMapValue(const MapKey& map_key) override;
|
||||
|
||||
const Map<Key, T>& GetMap() const override {
|
||||
MapFieldBase::SyncMapWithRepeatedField();
|
||||
return impl_.GetMap();
|
||||
}
|
||||
|
||||
Map<Key, T>* MutableMap() override {
|
||||
MapFieldBase::SyncMapWithRepeatedField();
|
||||
Map<Key, T>* result = impl_.MutableMap();
|
||||
MapFieldBase::SetMapDirty();
|
||||
return result;
|
||||
}
|
||||
|
||||
int size() const override;
|
||||
void Clear() override;
|
||||
void MergeFrom(const MapFieldBase& other) override;
|
||||
void Swap(MapFieldBase* other) override;
|
||||
void UnsafeShallowSwap(MapFieldBase* other) override;
|
||||
void InternalSwap(MapField* other);
|
||||
|
||||
// Used in the implementation of parsing. Caller should take the ownership iff
|
||||
// arena_ is nullptr.
|
||||
EntryType* NewEntry() const { return impl_.NewEntry(); }
|
||||
|
||||
const char* _InternalParse(const char* ptr, ParseContext* ctx) {
|
||||
return impl_._InternalParse(ptr, ctx);
|
||||
}
|
||||
template <typename UnknownType>
|
||||
const char* ParseWithEnumValidation(const char* ptr, ParseContext* ctx,
|
||||
bool (*is_valid)(int), uint32_t field_num,
|
||||
InternalMetadata* metadata) {
|
||||
return impl_.template ParseWithEnumValidation<UnknownType>(
|
||||
ptr, ctx, is_valid, field_num, metadata);
|
||||
}
|
||||
|
||||
private:
|
||||
MapFieldLiteType impl_;
|
||||
|
||||
typedef void InternalArenaConstructable_;
|
||||
typedef void DestructorSkippable_;
|
||||
|
||||
// Implements MapFieldBase
|
||||
void SyncRepeatedFieldWithMapNoLock() const override;
|
||||
void SyncMapWithRepeatedFieldNoLock() const override;
|
||||
size_t SpaceUsedExcludingSelfNoLock() const override;
|
||||
|
||||
void SetMapIteratorValue(MapIterator* map_iter) const override;
|
||||
|
||||
friend class ::PROTOBUF_NAMESPACE_ID::Arena;
|
||||
friend class MapFieldStateTest; // For testing, it needs raw access to impl_
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapField);
|
||||
};
|
||||
|
||||
template <typename Derived, typename Key, typename T,
|
||||
WireFormatLite::FieldType key_wire_type,
|
||||
WireFormatLite::FieldType value_wire_type>
|
||||
bool AllAreInitialized(
|
||||
const MapField<Derived, Key, T, key_wire_type, value_wire_type>& field) {
|
||||
const auto& t = field.GetMap();
|
||||
for (typename Map<Key, T>::const_iterator it = t.begin(); it != t.end();
|
||||
++it) {
|
||||
if (!it->second.IsInitialized()) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T, typename Key, typename Value,
|
||||
WireFormatLite::FieldType kKeyFieldType,
|
||||
WireFormatLite::FieldType kValueFieldType>
|
||||
struct MapEntryToMapField<
|
||||
MapEntry<T, Key, Value, kKeyFieldType, kValueFieldType>> {
|
||||
typedef MapField<T, Key, Value, kKeyFieldType, kValueFieldType> MapFieldType;
|
||||
};
|
||||
|
||||
class PROTOBUF_EXPORT DynamicMapField
|
||||
: public TypeDefinedMapFieldBase<MapKey, MapValueRef> {
|
||||
public:
|
||||
explicit DynamicMapField(const Message* default_entry);
|
||||
DynamicMapField(const Message* default_entry, Arena* arena);
|
||||
virtual ~DynamicMapField();
|
||||
|
||||
// Implement MapFieldBase
|
||||
bool ContainsMapKey(const MapKey& map_key) const override;
|
||||
bool InsertOrLookupMapValue(const MapKey& map_key, MapValueRef* val) override;
|
||||
bool LookupMapValue(const MapKey& map_key,
|
||||
MapValueConstRef* val) const override;
|
||||
bool LookupMapValue(const MapKey&, MapValueRef*) const = delete;
|
||||
bool DeleteMapValue(const MapKey& map_key) override;
|
||||
void MergeFrom(const MapFieldBase& other) override;
|
||||
void Swap(MapFieldBase* other) override;
|
||||
void UnsafeShallowSwap(MapFieldBase* other) override { Swap(other); }
|
||||
|
||||
const Map<MapKey, MapValueRef>& GetMap() const override;
|
||||
Map<MapKey, MapValueRef>* MutableMap() override;
|
||||
|
||||
int size() const override;
|
||||
void Clear() override;
|
||||
|
||||
private:
|
||||
Map<MapKey, MapValueRef> map_;
|
||||
const Message* default_entry_;
|
||||
|
||||
void AllocateMapValue(MapValueRef* map_val);
|
||||
|
||||
// Implements MapFieldBase
|
||||
void SyncRepeatedFieldWithMapNoLock() const override;
|
||||
void SyncMapWithRepeatedFieldNoLock() const override;
|
||||
size_t SpaceUsedExcludingSelfNoLock() const override;
|
||||
void SetMapIteratorValue(MapIterator* map_iter) const override;
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMapField);
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// MapValueConstRef points to a map value. Users can NOT modify
|
||||
// the map value.
|
||||
class PROTOBUF_EXPORT MapValueConstRef {
|
||||
public:
|
||||
MapValueConstRef() : data_(nullptr), type_() {}
|
||||
|
||||
int64_t GetInt64Value() const {
|
||||
TYPE_CHECK(FieldDescriptor::CPPTYPE_INT64,
|
||||
"MapValueConstRef::GetInt64Value");
|
||||
return *reinterpret_cast<int64_t*>(data_);
|
||||
}
|
||||
uint64_t GetUInt64Value() const {
|
||||
TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT64,
|
||||
"MapValueConstRef::GetUInt64Value");
|
||||
return *reinterpret_cast<uint64_t*>(data_);
|
||||
}
|
||||
int32_t GetInt32Value() const {
|
||||
TYPE_CHECK(FieldDescriptor::CPPTYPE_INT32,
|
||||
"MapValueConstRef::GetInt32Value");
|
||||
return *reinterpret_cast<int32_t*>(data_);
|
||||
}
|
||||
uint32_t GetUInt32Value() const {
|
||||
TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT32,
|
||||
"MapValueConstRef::GetUInt32Value");
|
||||
return *reinterpret_cast<uint32_t*>(data_);
|
||||
}
|
||||
bool GetBoolValue() const {
|
||||
TYPE_CHECK(FieldDescriptor::CPPTYPE_BOOL, "MapValueConstRef::GetBoolValue");
|
||||
return *reinterpret_cast<bool*>(data_);
|
||||
}
|
||||
int GetEnumValue() const {
|
||||
TYPE_CHECK(FieldDescriptor::CPPTYPE_ENUM, "MapValueConstRef::GetEnumValue");
|
||||
return *reinterpret_cast<int*>(data_);
|
||||
}
|
||||
const std::string& GetStringValue() const {
|
||||
TYPE_CHECK(FieldDescriptor::CPPTYPE_STRING,
|
||||
"MapValueConstRef::GetStringValue");
|
||||
return *reinterpret_cast<std::string*>(data_);
|
||||
}
|
||||
float GetFloatValue() const {
|
||||
TYPE_CHECK(FieldDescriptor::CPPTYPE_FLOAT,
|
||||
"MapValueConstRef::GetFloatValue");
|
||||
return *reinterpret_cast<float*>(data_);
|
||||
}
|
||||
double GetDoubleValue() const {
|
||||
TYPE_CHECK(FieldDescriptor::CPPTYPE_DOUBLE,
|
||||
"MapValueConstRef::GetDoubleValue");
|
||||
return *reinterpret_cast<double*>(data_);
|
||||
}
|
||||
|
||||
const Message& GetMessageValue() const {
|
||||
TYPE_CHECK(FieldDescriptor::CPPTYPE_MESSAGE,
|
||||
"MapValueConstRef::GetMessageValue");
|
||||
return *reinterpret_cast<Message*>(data_);
|
||||
}
|
||||
|
||||
protected:
|
||||
// data_ point to a map value. MapValueConstRef does not
|
||||
// own this value.
|
||||
void* data_;
|
||||
// type_ is 0 or a valid FieldDescriptor::CppType.
|
||||
// Use "CppType()" to indicate zero.
|
||||
FieldDescriptor::CppType type_;
|
||||
|
||||
FieldDescriptor::CppType type() const {
|
||||
if (type_ == FieldDescriptor::CppType() || data_ == nullptr) {
|
||||
GOOGLE_LOG(FATAL)
|
||||
<< "Protocol Buffer map usage error:\n"
|
||||
<< "MapValueConstRef::type MapValueConstRef is not initialized.";
|
||||
}
|
||||
return type_;
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename Derived, typename K, typename V,
|
||||
internal::WireFormatLite::FieldType key_wire_type,
|
||||
internal::WireFormatLite::FieldType value_wire_type>
|
||||
friend class internal::MapField;
|
||||
template <typename K, typename V>
|
||||
friend class internal::TypeDefinedMapFieldBase;
|
||||
friend class ::PROTOBUF_NAMESPACE_ID::MapIterator;
|
||||
friend class Reflection;
|
||||
friend class internal::DynamicMapField;
|
||||
|
||||
void SetType(FieldDescriptor::CppType type) { type_ = type; }
|
||||
void SetValue(const void* val) { data_ = const_cast<void*>(val); }
|
||||
void CopyFrom(const MapValueConstRef& other) {
|
||||
type_ = other.type_;
|
||||
data_ = other.data_;
|
||||
}
|
||||
};
|
||||
|
||||
// MapValueRef points to a map value. Users are able to modify
|
||||
// the map value.
|
||||
class PROTOBUF_EXPORT MapValueRef final : public MapValueConstRef {
|
||||
public:
|
||||
MapValueRef() {}
|
||||
|
||||
void SetInt64Value(int64_t value) {
|
||||
TYPE_CHECK(FieldDescriptor::CPPTYPE_INT64, "MapValueRef::SetInt64Value");
|
||||
*reinterpret_cast<int64_t*>(data_) = value;
|
||||
}
|
||||
void SetUInt64Value(uint64_t value) {
|
||||
TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT64, "MapValueRef::SetUInt64Value");
|
||||
*reinterpret_cast<uint64_t*>(data_) = value;
|
||||
}
|
||||
void SetInt32Value(int32_t value) {
|
||||
TYPE_CHECK(FieldDescriptor::CPPTYPE_INT32, "MapValueRef::SetInt32Value");
|
||||
*reinterpret_cast<int32_t*>(data_) = value;
|
||||
}
|
||||
void SetUInt32Value(uint32_t value) {
|
||||
TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT32, "MapValueRef::SetUInt32Value");
|
||||
*reinterpret_cast<uint32_t*>(data_) = value;
|
||||
}
|
||||
void SetBoolValue(bool value) {
|
||||
TYPE_CHECK(FieldDescriptor::CPPTYPE_BOOL, "MapValueRef::SetBoolValue");
|
||||
*reinterpret_cast<bool*>(data_) = value;
|
||||
}
|
||||
// TODO(jieluo) - Checks that enum is member.
|
||||
void SetEnumValue(int value) {
|
||||
TYPE_CHECK(FieldDescriptor::CPPTYPE_ENUM, "MapValueRef::SetEnumValue");
|
||||
*reinterpret_cast<int*>(data_) = value;
|
||||
}
|
||||
void SetStringValue(const std::string& value) {
|
||||
TYPE_CHECK(FieldDescriptor::CPPTYPE_STRING, "MapValueRef::SetStringValue");
|
||||
*reinterpret_cast<std::string*>(data_) = value;
|
||||
}
|
||||
void SetFloatValue(float value) {
|
||||
TYPE_CHECK(FieldDescriptor::CPPTYPE_FLOAT, "MapValueRef::SetFloatValue");
|
||||
*reinterpret_cast<float*>(data_) = value;
|
||||
}
|
||||
void SetDoubleValue(double value) {
|
||||
TYPE_CHECK(FieldDescriptor::CPPTYPE_DOUBLE, "MapValueRef::SetDoubleValue");
|
||||
*reinterpret_cast<double*>(data_) = value;
|
||||
}
|
||||
|
||||
Message* MutableMessageValue() {
|
||||
TYPE_CHECK(FieldDescriptor::CPPTYPE_MESSAGE,
|
||||
"MapValueRef::MutableMessageValue");
|
||||
return reinterpret_cast<Message*>(data_);
|
||||
}
|
||||
|
||||
private:
|
||||
friend class internal::DynamicMapField;
|
||||
|
||||
// Only used in DynamicMapField
|
||||
void DeleteData() {
|
||||
switch (type_) {
|
||||
#define HANDLE_TYPE(CPPTYPE, TYPE) \
|
||||
case FieldDescriptor::CPPTYPE_##CPPTYPE: { \
|
||||
delete reinterpret_cast<TYPE*>(data_); \
|
||||
break; \
|
||||
}
|
||||
HANDLE_TYPE(INT32, int32_t);
|
||||
HANDLE_TYPE(INT64, int64_t);
|
||||
HANDLE_TYPE(UINT32, uint32_t);
|
||||
HANDLE_TYPE(UINT64, uint64_t);
|
||||
HANDLE_TYPE(DOUBLE, double);
|
||||
HANDLE_TYPE(FLOAT, float);
|
||||
HANDLE_TYPE(BOOL, bool);
|
||||
HANDLE_TYPE(STRING, std::string);
|
||||
HANDLE_TYPE(ENUM, int32_t);
|
||||
HANDLE_TYPE(MESSAGE, Message);
|
||||
#undef HANDLE_TYPE
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#undef TYPE_CHECK
|
||||
|
||||
class PROTOBUF_EXPORT MapIterator {
|
||||
public:
|
||||
MapIterator(Message* message, const FieldDescriptor* field) {
|
||||
const Reflection* reflection = message->GetReflection();
|
||||
map_ = reflection->MutableMapData(message, field);
|
||||
key_.SetType(field->message_type()->map_key()->cpp_type());
|
||||
value_.SetType(field->message_type()->map_value()->cpp_type());
|
||||
map_->InitializeIterator(this);
|
||||
}
|
||||
MapIterator(const MapIterator& other) {
|
||||
map_ = other.map_;
|
||||
map_->InitializeIterator(this);
|
||||
map_->CopyIterator(this, other);
|
||||
}
|
||||
~MapIterator() { map_->DeleteIterator(this); }
|
||||
MapIterator& operator=(const MapIterator& other) {
|
||||
map_ = other.map_;
|
||||
map_->CopyIterator(this, other);
|
||||
return *this;
|
||||
}
|
||||
friend bool operator==(const MapIterator& a, const MapIterator& b) {
|
||||
return a.map_->EqualIterator(a, b);
|
||||
}
|
||||
friend bool operator!=(const MapIterator& a, const MapIterator& b) {
|
||||
return !a.map_->EqualIterator(a, b);
|
||||
}
|
||||
MapIterator& operator++() {
|
||||
map_->IncreaseIterator(this);
|
||||
return *this;
|
||||
}
|
||||
MapIterator operator++(int) {
|
||||
// iter_ is copied from Map<...>::iterator, no need to
|
||||
// copy from its self again. Use the same implementation
|
||||
// with operator++()
|
||||
map_->IncreaseIterator(this);
|
||||
return *this;
|
||||
}
|
||||
const MapKey& GetKey() { return key_; }
|
||||
const MapValueRef& GetValueRef() { return value_; }
|
||||
MapValueRef* MutableValueRef() {
|
||||
map_->SetMapDirty();
|
||||
return &value_;
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename Key, typename T>
|
||||
friend class internal::TypeDefinedMapFieldBase;
|
||||
friend class internal::DynamicMapField;
|
||||
template <typename Derived, typename Key, typename T,
|
||||
internal::WireFormatLite::FieldType kKeyFieldType,
|
||||
internal::WireFormatLite::FieldType kValueFieldType>
|
||||
friend class internal::MapField;
|
||||
|
||||
// reinterpret_cast from heap-allocated Map<...>::iterator*. MapIterator owns
|
||||
// the iterator. It is allocated by MapField<...>::InitializeIterator() called
|
||||
// in constructor and deleted by MapField<...>::DeleteIterator() called in
|
||||
// destructor.
|
||||
void* iter_;
|
||||
// Point to a MapField to call helper methods implemented in MapField.
|
||||
// MapIterator does not own this object.
|
||||
internal::MapFieldBase* map_;
|
||||
MapKey key_;
|
||||
MapValueRef value_;
|
||||
};
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop) // restore warning C4265
|
||||
#endif // _MSC_VER
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_MAP_FIELD_H__
|
||||
@@ -1,375 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_MAP_FIELD_INL_H__
|
||||
#define GOOGLE_PROTOBUF_MAP_FIELD_INL_H__
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <google/protobuf/stubs/casts.h>
|
||||
#include <google/protobuf/map.h>
|
||||
#include <google/protobuf/map_field.h>
|
||||
#include <google/protobuf/map_type_handler.h>
|
||||
|
||||
#ifdef SWIG
|
||||
#error "You cannot SWIG proto headers"
|
||||
#endif
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
// UnwrapMapKey template
|
||||
template <typename T>
|
||||
T UnwrapMapKey(const MapKey& map_key);
|
||||
template <>
|
||||
inline int32_t UnwrapMapKey<int32_t>(const MapKey& map_key) {
|
||||
return map_key.GetInt32Value();
|
||||
}
|
||||
template <>
|
||||
inline uint32_t UnwrapMapKey<uint32_t>(const MapKey& map_key) {
|
||||
return map_key.GetUInt32Value();
|
||||
}
|
||||
template <>
|
||||
inline int64_t UnwrapMapKey<int64_t>(const MapKey& map_key) {
|
||||
return map_key.GetInt64Value();
|
||||
}
|
||||
template <>
|
||||
inline uint64_t UnwrapMapKey<uint64_t>(const MapKey& map_key) {
|
||||
return map_key.GetUInt64Value();
|
||||
}
|
||||
template <>
|
||||
inline bool UnwrapMapKey<bool>(const MapKey& map_key) {
|
||||
return map_key.GetBoolValue();
|
||||
}
|
||||
template <>
|
||||
inline std::string UnwrapMapKey<std::string>(const MapKey& map_key) {
|
||||
return map_key.GetStringValue();
|
||||
}
|
||||
|
||||
// SetMapKey template
|
||||
template <typename T>
|
||||
inline void SetMapKey(MapKey* map_key, const T& value);
|
||||
template <>
|
||||
inline void SetMapKey<int32_t>(MapKey* map_key, const int32_t& value) {
|
||||
map_key->SetInt32Value(value);
|
||||
}
|
||||
template <>
|
||||
inline void SetMapKey<uint32_t>(MapKey* map_key, const uint32_t& value) {
|
||||
map_key->SetUInt32Value(value);
|
||||
}
|
||||
template <>
|
||||
inline void SetMapKey<int64_t>(MapKey* map_key, const int64_t& value) {
|
||||
map_key->SetInt64Value(value);
|
||||
}
|
||||
template <>
|
||||
inline void SetMapKey<uint64_t>(MapKey* map_key, const uint64_t& value) {
|
||||
map_key->SetUInt64Value(value);
|
||||
}
|
||||
template <>
|
||||
inline void SetMapKey<bool>(MapKey* map_key, const bool& value) {
|
||||
map_key->SetBoolValue(value);
|
||||
}
|
||||
template <>
|
||||
inline void SetMapKey<std::string>(MapKey* map_key, const std::string& value) {
|
||||
map_key->SetStringValue(value);
|
||||
}
|
||||
|
||||
// ------------------------TypeDefinedMapFieldBase---------------
|
||||
template <typename Key, typename T>
|
||||
typename Map<Key, T>::const_iterator&
|
||||
TypeDefinedMapFieldBase<Key, T>::InternalGetIterator(
|
||||
const MapIterator* map_iter) const {
|
||||
return *reinterpret_cast<typename Map<Key, T>::const_iterator*>(
|
||||
map_iter->iter_);
|
||||
}
|
||||
|
||||
template <typename Key, typename T>
|
||||
void TypeDefinedMapFieldBase<Key, T>::MapBegin(MapIterator* map_iter) const {
|
||||
InternalGetIterator(map_iter) = GetMap().begin();
|
||||
SetMapIteratorValue(map_iter);
|
||||
}
|
||||
|
||||
template <typename Key, typename T>
|
||||
void TypeDefinedMapFieldBase<Key, T>::MapEnd(MapIterator* map_iter) const {
|
||||
InternalGetIterator(map_iter) = GetMap().end();
|
||||
}
|
||||
|
||||
template <typename Key, typename T>
|
||||
bool TypeDefinedMapFieldBase<Key, T>::EqualIterator(
|
||||
const MapIterator& a, const MapIterator& b) const {
|
||||
return InternalGetIterator(&a) == InternalGetIterator(&b);
|
||||
}
|
||||
|
||||
template <typename Key, typename T>
|
||||
void TypeDefinedMapFieldBase<Key, T>::IncreaseIterator(
|
||||
MapIterator* map_iter) const {
|
||||
++InternalGetIterator(map_iter);
|
||||
SetMapIteratorValue(map_iter);
|
||||
}
|
||||
|
||||
template <typename Key, typename T>
|
||||
void TypeDefinedMapFieldBase<Key, T>::InitializeIterator(
|
||||
MapIterator* map_iter) const {
|
||||
map_iter->iter_ = new typename Map<Key, T>::const_iterator;
|
||||
GOOGLE_CHECK(map_iter->iter_ != nullptr);
|
||||
}
|
||||
|
||||
template <typename Key, typename T>
|
||||
void TypeDefinedMapFieldBase<Key, T>::DeleteIterator(
|
||||
MapIterator* map_iter) const {
|
||||
delete reinterpret_cast<typename Map<Key, T>::const_iterator*>(
|
||||
map_iter->iter_);
|
||||
}
|
||||
|
||||
template <typename Key, typename T>
|
||||
void TypeDefinedMapFieldBase<Key, T>::CopyIterator(
|
||||
MapIterator* this_iter, const MapIterator& that_iter) const {
|
||||
InternalGetIterator(this_iter) = InternalGetIterator(&that_iter);
|
||||
this_iter->key_.SetType(that_iter.key_.type());
|
||||
// MapValueRef::type() fails when containing data is null. However, if
|
||||
// this_iter points to MapEnd, data can be null.
|
||||
this_iter->value_.SetType(
|
||||
static_cast<FieldDescriptor::CppType>(that_iter.value_.type_));
|
||||
SetMapIteratorValue(this_iter);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
template <typename Derived, typename Key, typename T,
|
||||
WireFormatLite::FieldType kKeyFieldType,
|
||||
WireFormatLite::FieldType kValueFieldType>
|
||||
int MapField<Derived, Key, T, kKeyFieldType, kValueFieldType>::size() const {
|
||||
MapFieldBase::SyncMapWithRepeatedField();
|
||||
return static_cast<int>(impl_.GetMap().size());
|
||||
}
|
||||
|
||||
template <typename Derived, typename Key, typename T,
|
||||
WireFormatLite::FieldType kKeyFieldType,
|
||||
WireFormatLite::FieldType kValueFieldType>
|
||||
void MapField<Derived, Key, T, kKeyFieldType, kValueFieldType>::Clear() {
|
||||
if (this->MapFieldBase::repeated_field_ != nullptr) {
|
||||
RepeatedPtrField<EntryType>* repeated_field =
|
||||
reinterpret_cast<RepeatedPtrField<EntryType>*>(
|
||||
this->MapFieldBase::repeated_field_);
|
||||
repeated_field->Clear();
|
||||
}
|
||||
|
||||
impl_.MutableMap()->clear();
|
||||
// Data in map and repeated field are both empty, but we can't set status
|
||||
// CLEAN. Because clear is a generated API, we cannot invalidate previous
|
||||
// reference to map.
|
||||
MapFieldBase::SetMapDirty();
|
||||
}
|
||||
|
||||
template <typename Derived, typename Key, typename T,
|
||||
WireFormatLite::FieldType kKeyFieldType,
|
||||
WireFormatLite::FieldType kValueFieldType>
|
||||
void MapField<Derived, Key, T, kKeyFieldType,
|
||||
kValueFieldType>::SetMapIteratorValue(MapIterator* map_iter)
|
||||
const {
|
||||
const Map<Key, T>& map = impl_.GetMap();
|
||||
typename Map<Key, T>::const_iterator iter =
|
||||
TypeDefinedMapFieldBase<Key, T>::InternalGetIterator(map_iter);
|
||||
if (iter == map.end()) return;
|
||||
SetMapKey(&map_iter->key_, iter->first);
|
||||
map_iter->value_.SetValue(&iter->second);
|
||||
}
|
||||
|
||||
template <typename Derived, typename Key, typename T,
|
||||
WireFormatLite::FieldType kKeyFieldType,
|
||||
WireFormatLite::FieldType kValueFieldType>
|
||||
bool MapField<Derived, Key, T, kKeyFieldType, kValueFieldType>::ContainsMapKey(
|
||||
const MapKey& map_key) const {
|
||||
const Map<Key, T>& map = impl_.GetMap();
|
||||
const Key& key = UnwrapMapKey<Key>(map_key);
|
||||
typename Map<Key, T>::const_iterator iter = map.find(key);
|
||||
return iter != map.end();
|
||||
}
|
||||
|
||||
template <typename Derived, typename Key, typename T,
|
||||
WireFormatLite::FieldType kKeyFieldType,
|
||||
WireFormatLite::FieldType kValueFieldType>
|
||||
bool MapField<Derived, Key, T, kKeyFieldType,
|
||||
kValueFieldType>::InsertOrLookupMapValue(const MapKey& map_key,
|
||||
MapValueRef* val) {
|
||||
// Always use mutable map because users may change the map value by
|
||||
// MapValueRef.
|
||||
Map<Key, T>* map = MutableMap();
|
||||
const Key& key = UnwrapMapKey<Key>(map_key);
|
||||
typename Map<Key, T>::iterator iter = map->find(key);
|
||||
if (map->end() == iter) {
|
||||
val->SetValue(&((*map)[key]));
|
||||
return true;
|
||||
}
|
||||
// Key is already in the map. Make sure (*map)[key] is not called.
|
||||
// [] may reorder the map and iterators.
|
||||
val->SetValue(&(iter->second));
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename Derived, typename Key, typename T,
|
||||
WireFormatLite::FieldType kKeyFieldType,
|
||||
WireFormatLite::FieldType kValueFieldType>
|
||||
bool MapField<Derived, Key, T, kKeyFieldType, kValueFieldType>::LookupMapValue(
|
||||
const MapKey& map_key, MapValueConstRef* val) const {
|
||||
const Map<Key, T>& map = GetMap();
|
||||
const Key& key = UnwrapMapKey<Key>(map_key);
|
||||
typename Map<Key, T>::const_iterator iter = map.find(key);
|
||||
if (map.end() == iter) {
|
||||
return false;
|
||||
}
|
||||
// Key is already in the map. Make sure (*map)[key] is not called.
|
||||
// [] may reorder the map and iterators.
|
||||
val->SetValue(&(iter->second));
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Derived, typename Key, typename T,
|
||||
WireFormatLite::FieldType kKeyFieldType,
|
||||
WireFormatLite::FieldType kValueFieldType>
|
||||
bool MapField<Derived, Key, T, kKeyFieldType, kValueFieldType>::DeleteMapValue(
|
||||
const MapKey& map_key) {
|
||||
const Key& key = UnwrapMapKey<Key>(map_key);
|
||||
return MutableMap()->erase(key);
|
||||
}
|
||||
|
||||
template <typename Derived, typename Key, typename T,
|
||||
WireFormatLite::FieldType kKeyFieldType,
|
||||
WireFormatLite::FieldType kValueFieldType>
|
||||
void MapField<Derived, Key, T, kKeyFieldType, kValueFieldType>::MergeFrom(
|
||||
const MapFieldBase& other) {
|
||||
MapFieldBase::SyncMapWithRepeatedField();
|
||||
const MapField& other_field = static_cast<const MapField&>(other);
|
||||
other_field.SyncMapWithRepeatedField();
|
||||
impl_.MergeFrom(other_field.impl_);
|
||||
MapFieldBase::SetMapDirty();
|
||||
}
|
||||
|
||||
template <typename Derived, typename Key, typename T,
|
||||
WireFormatLite::FieldType kKeyFieldType,
|
||||
WireFormatLite::FieldType kValueFieldType>
|
||||
void MapField<Derived, Key, T, kKeyFieldType, kValueFieldType>::Swap(
|
||||
MapFieldBase* other) {
|
||||
MapFieldBase::Swap(other);
|
||||
MapField* other_field = down_cast<MapField*>(other);
|
||||
impl_.Swap(&other_field->impl_);
|
||||
}
|
||||
|
||||
template <typename Derived, typename Key, typename T,
|
||||
WireFormatLite::FieldType kKeyFieldType,
|
||||
WireFormatLite::FieldType kValueFieldType>
|
||||
void MapField<Derived, Key, T, kKeyFieldType,
|
||||
kValueFieldType>::UnsafeShallowSwap(MapFieldBase* other) {
|
||||
InternalSwap(down_cast<MapField*>(other));
|
||||
}
|
||||
|
||||
template <typename Derived, typename Key, typename T,
|
||||
WireFormatLite::FieldType kKeyFieldType,
|
||||
WireFormatLite::FieldType kValueFieldType>
|
||||
void MapField<Derived, Key, T, kKeyFieldType, kValueFieldType>::InternalSwap(
|
||||
MapField* other) {
|
||||
MapFieldBase::InternalSwap(other);
|
||||
impl_.InternalSwap(&other->impl_);
|
||||
}
|
||||
|
||||
template <typename Derived, typename Key, typename T,
|
||||
WireFormatLite::FieldType kKeyFieldType,
|
||||
WireFormatLite::FieldType kValueFieldType>
|
||||
void MapField<Derived, Key, T, kKeyFieldType,
|
||||
kValueFieldType>::SyncRepeatedFieldWithMapNoLock() const {
|
||||
if (this->MapFieldBase::repeated_field_ == nullptr) {
|
||||
this->MapFieldBase::repeated_field_ =
|
||||
Arena::CreateMessage<RepeatedPtrField<Message> >(
|
||||
this->MapFieldBase::arena_);
|
||||
}
|
||||
const Map<Key, T>& map = impl_.GetMap();
|
||||
RepeatedPtrField<EntryType>* repeated_field =
|
||||
reinterpret_cast<RepeatedPtrField<EntryType>*>(
|
||||
this->MapFieldBase::repeated_field_);
|
||||
|
||||
repeated_field->Clear();
|
||||
|
||||
// The only way we can get at this point is through reflection and the
|
||||
// only way we can get the reflection object is by having called GetReflection
|
||||
// on the encompassing field. So that type must have existed and hence we
|
||||
// know that this MapEntry default_type has also already been constructed.
|
||||
// So it's safe to just call internal_default_instance().
|
||||
const Message* default_entry = Derived::internal_default_instance();
|
||||
for (typename Map<Key, T>::const_iterator it = map.begin(); it != map.end();
|
||||
++it) {
|
||||
EntryType* new_entry =
|
||||
down_cast<EntryType*>(default_entry->New(this->MapFieldBase::arena_));
|
||||
repeated_field->AddAllocated(new_entry);
|
||||
(*new_entry->mutable_key()) = it->first;
|
||||
(*new_entry->mutable_value()) = it->second;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Derived, typename Key, typename T,
|
||||
WireFormatLite::FieldType kKeyFieldType,
|
||||
WireFormatLite::FieldType kValueFieldType>
|
||||
void MapField<Derived, Key, T, kKeyFieldType,
|
||||
kValueFieldType>::SyncMapWithRepeatedFieldNoLock() const {
|
||||
Map<Key, T>* map = const_cast<MapField*>(this)->impl_.MutableMap();
|
||||
RepeatedPtrField<EntryType>* repeated_field =
|
||||
reinterpret_cast<RepeatedPtrField<EntryType>*>(
|
||||
this->MapFieldBase::repeated_field_);
|
||||
GOOGLE_CHECK(this->MapFieldBase::repeated_field_ != nullptr);
|
||||
map->clear();
|
||||
for (typename RepeatedPtrField<EntryType>::iterator it =
|
||||
repeated_field->begin();
|
||||
it != repeated_field->end(); ++it) {
|
||||
// Cast is needed because Map's api and internal storage is different when
|
||||
// value is enum. For enum, we cannot cast an int to enum. Thus, we have to
|
||||
// copy value. For other types, they have same exposed api type and internal
|
||||
// stored type. We should not introduce value copy for them. We achieve this
|
||||
// by casting to value for enum while casting to reference for other types.
|
||||
(*map)[it->key()] = static_cast<CastValueType>(it->value());
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Derived, typename Key, typename T,
|
||||
WireFormatLite::FieldType kKeyFieldType,
|
||||
WireFormatLite::FieldType kValueFieldType>
|
||||
size_t MapField<Derived, Key, T, kKeyFieldType,
|
||||
kValueFieldType>::SpaceUsedExcludingSelfNoLock() const {
|
||||
size_t size = 0;
|
||||
if (this->MapFieldBase::repeated_field_ != nullptr) {
|
||||
size += this->MapFieldBase::repeated_field_->SpaceUsedExcludingSelfLong();
|
||||
}
|
||||
size += impl_.GetMap().SpaceUsedExcludingSelfLong();
|
||||
|
||||
return size;
|
||||
}
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_MAP_FIELD_INL_H__
|
||||
@@ -1,209 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_MAP_FIELD_LITE_H__
|
||||
#define GOOGLE_PROTOBUF_MAP_FIELD_LITE_H__
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/port.h>
|
||||
#include <google/protobuf/map.h>
|
||||
#include <google/protobuf/map_entry_lite.h>
|
||||
#include <google/protobuf/parse_context.h>
|
||||
#include <google/protobuf/wire_format_lite.h>
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
#ifdef SWIG
|
||||
#error "You cannot SWIG proto headers"
|
||||
#endif
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
#ifndef NDEBUG
|
||||
void MapFieldLiteNotDestructed(void* map_field_lite);
|
||||
#endif
|
||||
|
||||
// This class provides access to map field using generated api. It is used for
|
||||
// internal generated message implementation only. Users should never use this
|
||||
// directly.
|
||||
template <typename Derived, typename Key, typename T,
|
||||
WireFormatLite::FieldType key_wire_type,
|
||||
WireFormatLite::FieldType value_wire_type>
|
||||
class MapFieldLite {
|
||||
// Define message type for internal repeated field.
|
||||
typedef Derived EntryType;
|
||||
|
||||
public:
|
||||
typedef Map<Key, T> MapType;
|
||||
|
||||
constexpr MapFieldLite() : map_() {}
|
||||
explicit MapFieldLite(Arena* arena) : map_(arena) {}
|
||||
MapFieldLite(ArenaInitialized, Arena* arena) : MapFieldLite(arena) {}
|
||||
|
||||
#ifdef NDEBUG
|
||||
void Destruct() { map_.~Map(); }
|
||||
~MapFieldLite() {}
|
||||
#else
|
||||
void Destruct() {
|
||||
// We want to destruct the map in such a way that we can verify
|
||||
// that we've done that, but also be sure that we've deallocated
|
||||
// everything (as opposed to leaving an allocation behind with no
|
||||
// data in it, as would happen if a vector was resize'd to zero.
|
||||
// Map::Swap with an empty map accomplishes that.
|
||||
decltype(map_) swapped_map(map_.arena());
|
||||
map_.InternalSwap(swapped_map);
|
||||
}
|
||||
~MapFieldLite() {
|
||||
if (map_.arena() == nullptr && !map_.empty()) {
|
||||
MapFieldLiteNotDestructed(this);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// Accessors
|
||||
const Map<Key, T>& GetMap() const { return map_; }
|
||||
Map<Key, T>* MutableMap() { return &map_; }
|
||||
|
||||
// Convenient methods for generated message implementation.
|
||||
int size() const { return static_cast<int>(map_.size()); }
|
||||
void Clear() { return map_.clear(); }
|
||||
void MergeFrom(const MapFieldLite& other) {
|
||||
for (typename Map<Key, T>::const_iterator it = other.map_.begin();
|
||||
it != other.map_.end(); ++it) {
|
||||
map_[it->first] = it->second;
|
||||
}
|
||||
}
|
||||
void Swap(MapFieldLite* other) { map_.swap(other->map_); }
|
||||
void InternalSwap(MapFieldLite* other) { map_.InternalSwap(other->map_); }
|
||||
|
||||
// Used in the implementation of parsing. Caller should take the ownership iff
|
||||
// arena_ is nullptr.
|
||||
EntryType* NewEntry() const {
|
||||
return Arena::CreateMessage<EntryType>(map_.arena());
|
||||
}
|
||||
|
||||
const char* _InternalParse(const char* ptr, ParseContext* ctx) {
|
||||
typename Derived::template Parser<MapFieldLite, Map<Key, T>> parser(this);
|
||||
return parser._InternalParse(ptr, ctx);
|
||||
}
|
||||
|
||||
template <typename UnknownType>
|
||||
const char* ParseWithEnumValidation(const char* ptr, ParseContext* ctx,
|
||||
bool (*is_valid)(int), uint32_t field_num,
|
||||
InternalMetadata* metadata) {
|
||||
typename Derived::template Parser<MapFieldLite, Map<Key, T>> parser(this);
|
||||
return parser.template ParseWithEnumValidation<UnknownType>(
|
||||
ptr, ctx, is_valid, field_num, metadata);
|
||||
}
|
||||
|
||||
private:
|
||||
typedef void DestructorSkippable_;
|
||||
|
||||
// map_ is inside an anonymous union so we can explicitly control its
|
||||
// destruction
|
||||
union {
|
||||
Map<Key, T> map_;
|
||||
};
|
||||
|
||||
friend class ::PROTOBUF_NAMESPACE_ID::Arena;
|
||||
};
|
||||
|
||||
template <typename UnknownType, typename T>
|
||||
struct EnumParseWrapper {
|
||||
const char* _InternalParse(const char* ptr, ParseContext* ctx) {
|
||||
return map_field->template ParseWithEnumValidation<UnknownType>(
|
||||
ptr, ctx, is_valid, field_num, metadata);
|
||||
}
|
||||
T* map_field;
|
||||
bool (*is_valid)(int);
|
||||
uint32_t field_num;
|
||||
InternalMetadata* metadata;
|
||||
};
|
||||
|
||||
// Helper function because the typenames of maps are horrendous to print. This
|
||||
// leverages compiler type deduction, to keep all type data out of the
|
||||
// generated code
|
||||
template <typename UnknownType, typename T>
|
||||
EnumParseWrapper<UnknownType, T> InitEnumParseWrapper(
|
||||
T* map_field, bool (*is_valid)(int), uint32_t field_num,
|
||||
InternalMetadata* metadata) {
|
||||
return EnumParseWrapper<UnknownType, T>{map_field, is_valid, field_num,
|
||||
metadata};
|
||||
}
|
||||
|
||||
// True if IsInitialized() is true for value field in all elements of t. T is
|
||||
// expected to be message. It's useful to have this helper here to keep the
|
||||
// protobuf compiler from ever having to emit loops in IsInitialized() methods.
|
||||
// We want the C++ compiler to inline this or not as it sees fit.
|
||||
template <typename Derived, typename Key, typename T,
|
||||
WireFormatLite::FieldType key_wire_type,
|
||||
WireFormatLite::FieldType value_wire_type>
|
||||
bool AllAreInitialized(const MapFieldLite<Derived, Key, T, key_wire_type,
|
||||
value_wire_type>& field) {
|
||||
const auto& t = field.GetMap();
|
||||
for (typename Map<Key, T>::const_iterator it = t.begin(); it != t.end();
|
||||
++it) {
|
||||
if (!it->second.IsInitialized()) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename MEntry>
|
||||
struct MapEntryToMapField : MapEntryToMapField<typename MEntry::SuperType> {};
|
||||
|
||||
template <typename T, typename Key, typename Value,
|
||||
WireFormatLite::FieldType kKeyFieldType,
|
||||
WireFormatLite::FieldType kValueFieldType>
|
||||
struct MapEntryToMapField<
|
||||
MapEntryLite<T, Key, Value, kKeyFieldType, kValueFieldType>> {
|
||||
typedef MapFieldLite<
|
||||
MapEntryLite<T, Key, Value, kKeyFieldType, kValueFieldType>, Key, Value,
|
||||
kKeyFieldType, kValueFieldType>
|
||||
MapFieldType;
|
||||
};
|
||||
|
||||
#ifndef NDEBUG
|
||||
inline PROTOBUF_NOINLINE void MapFieldLiteNotDestructed(void* map_field_lite) {
|
||||
bool proper_destruct = false;
|
||||
GOOGLE_CHECK(proper_destruct) << map_field_lite;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_MAP_FIELD_LITE_H__
|
||||
@@ -1,736 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_MAP_TYPE_HANDLER_H__
|
||||
#define GOOGLE_PROTOBUF_MAP_TYPE_HANDLER_H__
|
||||
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/arena.h>
|
||||
#include <google/protobuf/arenastring.h>
|
||||
#include <google/protobuf/parse_context.h>
|
||||
#include <google/protobuf/wire_format_lite.h>
|
||||
|
||||
#ifdef SWIG
|
||||
#error "You cannot SWIG proto headers"
|
||||
#endif
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
// Used for compile time type selection. MapIf::type will be TrueType if Flag is
|
||||
// true and FalseType otherwise.
|
||||
template <bool Flag, typename TrueType, typename FalseType>
|
||||
struct MapIf;
|
||||
|
||||
template <typename TrueType, typename FalseType>
|
||||
struct MapIf<true, TrueType, FalseType> {
|
||||
typedef TrueType type;
|
||||
};
|
||||
|
||||
template <typename TrueType, typename FalseType>
|
||||
struct MapIf<false, TrueType, FalseType> {
|
||||
typedef FalseType type;
|
||||
};
|
||||
|
||||
template <typename Type, bool is_arena_constructable>
|
||||
class MapArenaMessageCreator {
|
||||
public:
|
||||
// Use arena to create message if Type is arena constructable. Otherwise,
|
||||
// create the message on heap.
|
||||
static inline Type* CreateMessage(Arena* arena);
|
||||
};
|
||||
template <typename Type>
|
||||
class MapArenaMessageCreator<Type, true> {
|
||||
public:
|
||||
static inline Type* CreateMessage(Arena* arena) {
|
||||
return Arena::CreateMessage<Type>(arena);
|
||||
}
|
||||
};
|
||||
template <typename Type>
|
||||
class MapArenaMessageCreator<Type, false> {
|
||||
public:
|
||||
static inline Type* CreateMessage(Arena* arena) {
|
||||
return Arena::Create<Type>(arena);
|
||||
}
|
||||
};
|
||||
|
||||
// Define constants for given wire field type
|
||||
template <WireFormatLite::FieldType field_type, typename Type>
|
||||
class MapWireFieldTypeTraits {};
|
||||
|
||||
#define TYPE_TRAITS(FieldType, CType, WireFormatType, IsMessage, IsEnum) \
|
||||
template <typename Type> \
|
||||
class MapWireFieldTypeTraits<WireFormatLite::TYPE_##FieldType, Type> { \
|
||||
public: \
|
||||
static const bool kIsMessage = IsMessage; \
|
||||
static const bool kIsEnum = IsEnum; \
|
||||
typedef typename MapIf<kIsMessage, Type*, CType>::type TypeOnMemory; \
|
||||
typedef typename MapIf<kIsEnum, int, Type>::type MapEntryAccessorType; \
|
||||
static const WireFormatLite::WireType kWireType = \
|
||||
WireFormatLite::WIRETYPE_##WireFormatType; \
|
||||
};
|
||||
|
||||
TYPE_TRAITS(MESSAGE, Type, LENGTH_DELIMITED, true, false)
|
||||
TYPE_TRAITS(STRING, ArenaStringPtr, LENGTH_DELIMITED, false, false)
|
||||
TYPE_TRAITS(BYTES, ArenaStringPtr, LENGTH_DELIMITED, false, false)
|
||||
TYPE_TRAITS(INT64, int64_t, VARINT, false, false)
|
||||
TYPE_TRAITS(UINT64, uint64_t, VARINT, false, false)
|
||||
TYPE_TRAITS(INT32, int32_t, VARINT, false, false)
|
||||
TYPE_TRAITS(UINT32, uint32_t, VARINT, false, false)
|
||||
TYPE_TRAITS(SINT64, int64_t, VARINT, false, false)
|
||||
TYPE_TRAITS(SINT32, int32_t, VARINT, false, false)
|
||||
TYPE_TRAITS(ENUM, int, VARINT, false, true)
|
||||
TYPE_TRAITS(DOUBLE, double, FIXED64, false, false)
|
||||
TYPE_TRAITS(FLOAT, float, FIXED32, false, false)
|
||||
TYPE_TRAITS(FIXED64, uint64_t, FIXED64, false, false)
|
||||
TYPE_TRAITS(FIXED32, uint32_t, FIXED32, false, false)
|
||||
TYPE_TRAITS(SFIXED64, int64_t, FIXED64, false, false)
|
||||
TYPE_TRAITS(SFIXED32, int32_t, FIXED32, false, false)
|
||||
TYPE_TRAITS(BOOL, bool, VARINT, false, false)
|
||||
|
||||
#undef TYPE_TRAITS
|
||||
|
||||
template <WireFormatLite::FieldType field_type, typename Type>
|
||||
class MapTypeHandler {};
|
||||
|
||||
template <typename Type>
|
||||
class MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type> {
|
||||
public:
|
||||
// Enum type cannot be used for MapTypeHandler::Read. Define a type which will
|
||||
// replace Enum with int.
|
||||
typedef typename MapWireFieldTypeTraits<WireFormatLite::TYPE_MESSAGE,
|
||||
Type>::MapEntryAccessorType
|
||||
MapEntryAccessorType;
|
||||
// Internal stored type in MapEntryLite for given wire field type.
|
||||
typedef typename MapWireFieldTypeTraits<WireFormatLite::TYPE_MESSAGE,
|
||||
Type>::TypeOnMemory TypeOnMemory;
|
||||
// Corresponding wire type for field type.
|
||||
static constexpr WireFormatLite::WireType kWireType =
|
||||
MapWireFieldTypeTraits<WireFormatLite::TYPE_MESSAGE, Type>::kWireType;
|
||||
// Whether wire type is for message.
|
||||
static constexpr bool kIsMessage =
|
||||
MapWireFieldTypeTraits<WireFormatLite::TYPE_MESSAGE, Type>::kIsMessage;
|
||||
// Whether wire type is for enum.
|
||||
static constexpr bool kIsEnum =
|
||||
MapWireFieldTypeTraits<WireFormatLite::TYPE_MESSAGE, Type>::kIsEnum;
|
||||
|
||||
// Functions used in parsing and serialization. ===================
|
||||
static inline size_t ByteSize(const MapEntryAccessorType& value);
|
||||
static inline int GetCachedSize(const MapEntryAccessorType& value);
|
||||
static inline bool Read(io::CodedInputStream* input,
|
||||
MapEntryAccessorType* value);
|
||||
static inline const char* Read(const char* ptr, ParseContext* ctx,
|
||||
MapEntryAccessorType* value);
|
||||
|
||||
static inline uint8_t* Write(int field, const MapEntryAccessorType& value,
|
||||
uint8_t* ptr, io::EpsCopyOutputStream* stream);
|
||||
|
||||
// Functions to manipulate data on memory. ========================
|
||||
static inline const Type& GetExternalReference(const Type* value);
|
||||
static inline void DeleteNoArena(const Type* x);
|
||||
static inline void Merge(const Type& from, Type** to, Arena* arena);
|
||||
static inline void Clear(Type** value, Arena* arena);
|
||||
static constexpr TypeOnMemory Constinit();
|
||||
|
||||
static inline Type* EnsureMutable(Type** value, Arena* arena);
|
||||
// SpaceUsedInMapEntry: Return bytes used by value in MapEntry, excluding
|
||||
// those already calculate in sizeof(MapField).
|
||||
static inline size_t SpaceUsedInMapEntryLong(const Type* value);
|
||||
// Return default instance if value is not initialized when calling const
|
||||
// reference accessor.
|
||||
static inline const Type& DefaultIfNotInitialized(const Type* value);
|
||||
// Check if all required fields have values set.
|
||||
static inline bool IsInitialized(Type* value);
|
||||
};
|
||||
|
||||
#define MAP_HANDLER(FieldType) \
|
||||
template <typename Type> \
|
||||
class MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type> { \
|
||||
public: \
|
||||
typedef typename MapWireFieldTypeTraits<WireFormatLite::TYPE_##FieldType, \
|
||||
Type>::MapEntryAccessorType \
|
||||
MapEntryAccessorType; \
|
||||
typedef typename MapWireFieldTypeTraits<WireFormatLite::TYPE_##FieldType, \
|
||||
Type>::TypeOnMemory TypeOnMemory; \
|
||||
static const WireFormatLite::WireType kWireType = \
|
||||
MapWireFieldTypeTraits<WireFormatLite::TYPE_##FieldType, \
|
||||
Type>::kWireType; \
|
||||
static const bool kIsMessage = \
|
||||
MapWireFieldTypeTraits<WireFormatLite::TYPE_##FieldType, \
|
||||
Type>::kIsMessage; \
|
||||
static const bool kIsEnum = \
|
||||
MapWireFieldTypeTraits<WireFormatLite::TYPE_##FieldType, \
|
||||
Type>::kIsEnum; \
|
||||
static inline int ByteSize(const MapEntryAccessorType& value); \
|
||||
static inline int GetCachedSize(const MapEntryAccessorType& value); \
|
||||
static inline bool Read(io::CodedInputStream* input, \
|
||||
MapEntryAccessorType* value); \
|
||||
static inline const char* Read(const char* begin, ParseContext* ctx, \
|
||||
MapEntryAccessorType* value); \
|
||||
static inline uint8_t* Write(int field, const MapEntryAccessorType& value, \
|
||||
uint8_t* ptr, \
|
||||
io::EpsCopyOutputStream* stream); \
|
||||
static inline const MapEntryAccessorType& GetExternalReference( \
|
||||
const TypeOnMemory& value); \
|
||||
static inline void DeleteNoArena(const TypeOnMemory& x); \
|
||||
static inline void Merge(const MapEntryAccessorType& from, \
|
||||
TypeOnMemory* to, Arena* arena); \
|
||||
static inline void Clear(TypeOnMemory* value, Arena* arena); \
|
||||
static inline size_t SpaceUsedInMapEntryLong(const TypeOnMemory& value); \
|
||||
static inline const MapEntryAccessorType& DefaultIfNotInitialized( \
|
||||
const TypeOnMemory& value); \
|
||||
static inline bool IsInitialized(const TypeOnMemory& value); \
|
||||
static void DeleteNoArena(TypeOnMemory& value); \
|
||||
static constexpr TypeOnMemory Constinit(); \
|
||||
static inline MapEntryAccessorType* EnsureMutable(TypeOnMemory* value, \
|
||||
Arena* arena); \
|
||||
};
|
||||
MAP_HANDLER(STRING)
|
||||
MAP_HANDLER(BYTES)
|
||||
MAP_HANDLER(INT64)
|
||||
MAP_HANDLER(UINT64)
|
||||
MAP_HANDLER(INT32)
|
||||
MAP_HANDLER(UINT32)
|
||||
MAP_HANDLER(SINT64)
|
||||
MAP_HANDLER(SINT32)
|
||||
MAP_HANDLER(ENUM)
|
||||
MAP_HANDLER(DOUBLE)
|
||||
MAP_HANDLER(FLOAT)
|
||||
MAP_HANDLER(FIXED64)
|
||||
MAP_HANDLER(FIXED32)
|
||||
MAP_HANDLER(SFIXED64)
|
||||
MAP_HANDLER(SFIXED32)
|
||||
MAP_HANDLER(BOOL)
|
||||
#undef MAP_HANDLER
|
||||
|
||||
template <typename Type>
|
||||
inline size_t MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::ByteSize(
|
||||
const MapEntryAccessorType& value) {
|
||||
return WireFormatLite::MessageSizeNoVirtual(value);
|
||||
}
|
||||
|
||||
#define GOOGLE_PROTOBUF_BYTE_SIZE(FieldType, DeclaredType) \
|
||||
template <typename Type> \
|
||||
inline int MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::ByteSize( \
|
||||
const MapEntryAccessorType& value) { \
|
||||
return static_cast<int>(WireFormatLite::DeclaredType##Size(value)); \
|
||||
}
|
||||
|
||||
GOOGLE_PROTOBUF_BYTE_SIZE(STRING, String)
|
||||
GOOGLE_PROTOBUF_BYTE_SIZE(BYTES, Bytes)
|
||||
GOOGLE_PROTOBUF_BYTE_SIZE(INT64, Int64)
|
||||
GOOGLE_PROTOBUF_BYTE_SIZE(UINT64, UInt64)
|
||||
GOOGLE_PROTOBUF_BYTE_SIZE(INT32, Int32)
|
||||
GOOGLE_PROTOBUF_BYTE_SIZE(UINT32, UInt32)
|
||||
GOOGLE_PROTOBUF_BYTE_SIZE(SINT64, SInt64)
|
||||
GOOGLE_PROTOBUF_BYTE_SIZE(SINT32, SInt32)
|
||||
GOOGLE_PROTOBUF_BYTE_SIZE(ENUM, Enum)
|
||||
|
||||
#undef GOOGLE_PROTOBUF_BYTE_SIZE
|
||||
|
||||
#define FIXED_BYTE_SIZE(FieldType, DeclaredType) \
|
||||
template <typename Type> \
|
||||
inline int MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::ByteSize( \
|
||||
const MapEntryAccessorType& /* value */) { \
|
||||
return WireFormatLite::k##DeclaredType##Size; \
|
||||
}
|
||||
|
||||
FIXED_BYTE_SIZE(DOUBLE, Double)
|
||||
FIXED_BYTE_SIZE(FLOAT, Float)
|
||||
FIXED_BYTE_SIZE(FIXED64, Fixed64)
|
||||
FIXED_BYTE_SIZE(FIXED32, Fixed32)
|
||||
FIXED_BYTE_SIZE(SFIXED64, SFixed64)
|
||||
FIXED_BYTE_SIZE(SFIXED32, SFixed32)
|
||||
FIXED_BYTE_SIZE(BOOL, Bool)
|
||||
|
||||
#undef FIXED_BYTE_SIZE
|
||||
|
||||
template <typename Type>
|
||||
inline int MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::GetCachedSize(
|
||||
const MapEntryAccessorType& value) {
|
||||
return static_cast<int>(WireFormatLite::LengthDelimitedSize(
|
||||
static_cast<size_t>(value.GetCachedSize())));
|
||||
}
|
||||
|
||||
#define GET_CACHED_SIZE(FieldType, DeclaredType) \
|
||||
template <typename Type> \
|
||||
inline int \
|
||||
MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::GetCachedSize( \
|
||||
const MapEntryAccessorType& value) { \
|
||||
return static_cast<int>(WireFormatLite::DeclaredType##Size(value)); \
|
||||
}
|
||||
|
||||
GET_CACHED_SIZE(STRING, String)
|
||||
GET_CACHED_SIZE(BYTES, Bytes)
|
||||
GET_CACHED_SIZE(INT64, Int64)
|
||||
GET_CACHED_SIZE(UINT64, UInt64)
|
||||
GET_CACHED_SIZE(INT32, Int32)
|
||||
GET_CACHED_SIZE(UINT32, UInt32)
|
||||
GET_CACHED_SIZE(SINT64, SInt64)
|
||||
GET_CACHED_SIZE(SINT32, SInt32)
|
||||
GET_CACHED_SIZE(ENUM, Enum)
|
||||
|
||||
#undef GET_CACHED_SIZE
|
||||
|
||||
#define GET_FIXED_CACHED_SIZE(FieldType, DeclaredType) \
|
||||
template <typename Type> \
|
||||
inline int \
|
||||
MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::GetCachedSize( \
|
||||
const MapEntryAccessorType& /* value */) { \
|
||||
return WireFormatLite::k##DeclaredType##Size; \
|
||||
}
|
||||
|
||||
GET_FIXED_CACHED_SIZE(DOUBLE, Double)
|
||||
GET_FIXED_CACHED_SIZE(FLOAT, Float)
|
||||
GET_FIXED_CACHED_SIZE(FIXED64, Fixed64)
|
||||
GET_FIXED_CACHED_SIZE(FIXED32, Fixed32)
|
||||
GET_FIXED_CACHED_SIZE(SFIXED64, SFixed64)
|
||||
GET_FIXED_CACHED_SIZE(SFIXED32, SFixed32)
|
||||
GET_FIXED_CACHED_SIZE(BOOL, Bool)
|
||||
|
||||
#undef GET_FIXED_CACHED_SIZE
|
||||
|
||||
template <typename Type>
|
||||
inline uint8_t* MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::Write(
|
||||
int field, const MapEntryAccessorType& value, uint8_t* ptr,
|
||||
io::EpsCopyOutputStream* stream) {
|
||||
ptr = stream->EnsureSpace(ptr);
|
||||
return WireFormatLite::InternalWriteMessage(
|
||||
field, value, value.GetCachedSize(), ptr, stream);
|
||||
}
|
||||
|
||||
#define WRITE_METHOD(FieldType, DeclaredType) \
|
||||
template <typename Type> \
|
||||
inline uint8_t* \
|
||||
MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Write( \
|
||||
int field, const MapEntryAccessorType& value, uint8_t* ptr, \
|
||||
io::EpsCopyOutputStream* stream) { \
|
||||
ptr = stream->EnsureSpace(ptr); \
|
||||
return stream->Write##DeclaredType(field, value, ptr); \
|
||||
}
|
||||
|
||||
WRITE_METHOD(STRING, String)
|
||||
WRITE_METHOD(BYTES, Bytes)
|
||||
|
||||
#undef WRITE_METHOD
|
||||
#define WRITE_METHOD(FieldType, DeclaredType) \
|
||||
template <typename Type> \
|
||||
inline uint8_t* \
|
||||
MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Write( \
|
||||
int field, const MapEntryAccessorType& value, uint8_t* ptr, \
|
||||
io::EpsCopyOutputStream* stream) { \
|
||||
ptr = stream->EnsureSpace(ptr); \
|
||||
return WireFormatLite::Write##DeclaredType##ToArray(field, value, ptr); \
|
||||
}
|
||||
|
||||
WRITE_METHOD(INT64, Int64)
|
||||
WRITE_METHOD(UINT64, UInt64)
|
||||
WRITE_METHOD(INT32, Int32)
|
||||
WRITE_METHOD(UINT32, UInt32)
|
||||
WRITE_METHOD(SINT64, SInt64)
|
||||
WRITE_METHOD(SINT32, SInt32)
|
||||
WRITE_METHOD(ENUM, Enum)
|
||||
WRITE_METHOD(DOUBLE, Double)
|
||||
WRITE_METHOD(FLOAT, Float)
|
||||
WRITE_METHOD(FIXED64, Fixed64)
|
||||
WRITE_METHOD(FIXED32, Fixed32)
|
||||
WRITE_METHOD(SFIXED64, SFixed64)
|
||||
WRITE_METHOD(SFIXED32, SFixed32)
|
||||
WRITE_METHOD(BOOL, Bool)
|
||||
|
||||
#undef WRITE_METHOD
|
||||
|
||||
template <typename Type>
|
||||
inline bool MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::Read(
|
||||
io::CodedInputStream* input, MapEntryAccessorType* value) {
|
||||
return WireFormatLite::ReadMessageNoVirtual(input, value);
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
inline bool MapTypeHandler<WireFormatLite::TYPE_STRING, Type>::Read(
|
||||
io::CodedInputStream* input, MapEntryAccessorType* value) {
|
||||
return WireFormatLite::ReadString(input, value);
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
inline bool MapTypeHandler<WireFormatLite::TYPE_BYTES, Type>::Read(
|
||||
io::CodedInputStream* input, MapEntryAccessorType* value) {
|
||||
return WireFormatLite::ReadBytes(input, value);
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
const char* MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::Read(
|
||||
const char* ptr, ParseContext* ctx, MapEntryAccessorType* value) {
|
||||
return ctx->ParseMessage(value, ptr);
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
const char* MapTypeHandler<WireFormatLite::TYPE_STRING, Type>::Read(
|
||||
const char* ptr, ParseContext* ctx, MapEntryAccessorType* value) {
|
||||
int size = ReadSize(&ptr);
|
||||
GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
|
||||
return ctx->ReadString(ptr, size, value);
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
const char* MapTypeHandler<WireFormatLite::TYPE_BYTES, Type>::Read(
|
||||
const char* ptr, ParseContext* ctx, MapEntryAccessorType* value) {
|
||||
int size = ReadSize(&ptr);
|
||||
GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
|
||||
return ctx->ReadString(ptr, size, value);
|
||||
}
|
||||
|
||||
inline const char* ReadINT64(const char* ptr, int64_t* value) {
|
||||
return VarintParse(ptr, reinterpret_cast<uint64_t*>(value));
|
||||
}
|
||||
inline const char* ReadUINT64(const char* ptr, uint64_t* value) {
|
||||
return VarintParse(ptr, value);
|
||||
}
|
||||
inline const char* ReadINT32(const char* ptr, int32_t* value) {
|
||||
return VarintParse(ptr, reinterpret_cast<uint32_t*>(value));
|
||||
}
|
||||
inline const char* ReadUINT32(const char* ptr, uint32_t* value) {
|
||||
return VarintParse(ptr, value);
|
||||
}
|
||||
inline const char* ReadSINT64(const char* ptr, int64_t* value) {
|
||||
*value = ReadVarintZigZag64(&ptr);
|
||||
return ptr;
|
||||
}
|
||||
inline const char* ReadSINT32(const char* ptr, int32_t* value) {
|
||||
*value = ReadVarintZigZag32(&ptr);
|
||||
return ptr;
|
||||
}
|
||||
template <typename E>
|
||||
inline const char* ReadENUM(const char* ptr, E* value) {
|
||||
*value = static_cast<E>(ReadVarint32(&ptr));
|
||||
return ptr;
|
||||
}
|
||||
inline const char* ReadBOOL(const char* ptr, bool* value) {
|
||||
*value = static_cast<bool>(ReadVarint32(&ptr));
|
||||
return ptr;
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
inline const char* ReadUnaligned(const char* ptr, F* value) {
|
||||
*value = UnalignedLoad<F>(ptr);
|
||||
return ptr + sizeof(F);
|
||||
}
|
||||
inline const char* ReadFLOAT(const char* ptr, float* value) {
|
||||
return ReadUnaligned(ptr, value);
|
||||
}
|
||||
inline const char* ReadDOUBLE(const char* ptr, double* value) {
|
||||
return ReadUnaligned(ptr, value);
|
||||
}
|
||||
inline const char* ReadFIXED64(const char* ptr, uint64_t* value) {
|
||||
return ReadUnaligned(ptr, value);
|
||||
}
|
||||
inline const char* ReadFIXED32(const char* ptr, uint32_t* value) {
|
||||
return ReadUnaligned(ptr, value);
|
||||
}
|
||||
inline const char* ReadSFIXED64(const char* ptr, int64_t* value) {
|
||||
return ReadUnaligned(ptr, value);
|
||||
}
|
||||
inline const char* ReadSFIXED32(const char* ptr, int32_t* value) {
|
||||
return ReadUnaligned(ptr, value);
|
||||
}
|
||||
|
||||
#define READ_METHOD(FieldType) \
|
||||
template <typename Type> \
|
||||
inline bool MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Read( \
|
||||
io::CodedInputStream* input, MapEntryAccessorType* value) { \
|
||||
return WireFormatLite::ReadPrimitive<TypeOnMemory, \
|
||||
WireFormatLite::TYPE_##FieldType>( \
|
||||
input, value); \
|
||||
} \
|
||||
template <typename Type> \
|
||||
const char* MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Read( \
|
||||
const char* begin, ParseContext* ctx, MapEntryAccessorType* value) { \
|
||||
(void)ctx; \
|
||||
return Read##FieldType(begin, value); \
|
||||
}
|
||||
|
||||
READ_METHOD(INT64)
|
||||
READ_METHOD(UINT64)
|
||||
READ_METHOD(INT32)
|
||||
READ_METHOD(UINT32)
|
||||
READ_METHOD(SINT64)
|
||||
READ_METHOD(SINT32)
|
||||
READ_METHOD(ENUM)
|
||||
READ_METHOD(DOUBLE)
|
||||
READ_METHOD(FLOAT)
|
||||
READ_METHOD(FIXED64)
|
||||
READ_METHOD(FIXED32)
|
||||
READ_METHOD(SFIXED64)
|
||||
READ_METHOD(SFIXED32)
|
||||
READ_METHOD(BOOL)
|
||||
|
||||
#undef READ_METHOD
|
||||
|
||||
// Definition for message handler
|
||||
|
||||
template <typename Type>
|
||||
inline const Type&
|
||||
MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::GetExternalReference(
|
||||
const Type* value) {
|
||||
return *value;
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
inline size_t MapTypeHandler<WireFormatLite::TYPE_MESSAGE,
|
||||
Type>::SpaceUsedInMapEntryLong(const Type* value) {
|
||||
return value->SpaceUsedLong();
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
inline void MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::Clear(
|
||||
Type** value, Arena* /* arena */) {
|
||||
if (*value != nullptr) (*value)->Clear();
|
||||
}
|
||||
template <typename Type>
|
||||
inline void MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::Merge(
|
||||
const Type& from, Type** to, Arena* /* arena */) {
|
||||
(*to)->MergeFrom(from);
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
void MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::DeleteNoArena(
|
||||
const Type* ptr) {
|
||||
delete ptr;
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
constexpr auto MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::Constinit()
|
||||
-> TypeOnMemory {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
inline Type* MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::EnsureMutable(
|
||||
Type** value, Arena* arena) {
|
||||
if (*value == nullptr) {
|
||||
*value = MapArenaMessageCreator<
|
||||
Type,
|
||||
Arena::is_arena_constructable<Type>::type::value>::CreateMessage(arena);
|
||||
}
|
||||
return *value;
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
inline const Type&
|
||||
MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::DefaultIfNotInitialized(
|
||||
const Type* value) {
|
||||
return value != nullptr ? *value : *Type::internal_default_instance();
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
inline bool MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::IsInitialized(
|
||||
Type* value) {
|
||||
return value ? value->IsInitialized() : false;
|
||||
}
|
||||
|
||||
// Definition for string/bytes handler
|
||||
|
||||
#define STRING_OR_BYTES_HANDLER_FUNCTIONS(FieldType) \
|
||||
template <typename Type> \
|
||||
inline const typename MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
|
||||
Type>::MapEntryAccessorType& \
|
||||
MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
|
||||
Type>::GetExternalReference(const TypeOnMemory& value) { \
|
||||
return value.Get(); \
|
||||
} \
|
||||
template <typename Type> \
|
||||
inline size_t \
|
||||
MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
|
||||
Type>::SpaceUsedInMapEntryLong(const TypeOnMemory& value) { \
|
||||
return sizeof(value); \
|
||||
} \
|
||||
template <typename Type> \
|
||||
inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Clear( \
|
||||
TypeOnMemory* value, Arena* /* arena */) { \
|
||||
value->ClearToEmpty(); \
|
||||
} \
|
||||
template <typename Type> \
|
||||
inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Merge( \
|
||||
const MapEntryAccessorType& from, TypeOnMemory* to, Arena* arena) { \
|
||||
to->Set(from, arena); \
|
||||
} \
|
||||
template <typename Type> \
|
||||
void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::DeleteNoArena( \
|
||||
TypeOnMemory& value) { \
|
||||
value.Destroy(); \
|
||||
} \
|
||||
template <typename Type> \
|
||||
constexpr auto \
|
||||
MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Constinit() \
|
||||
->TypeOnMemory { \
|
||||
return TypeOnMemory(&internal::fixed_address_empty_string, \
|
||||
ConstantInitialized{}); \
|
||||
} \
|
||||
template <typename Type> \
|
||||
inline typename MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
|
||||
Type>::MapEntryAccessorType* \
|
||||
MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::EnsureMutable( \
|
||||
TypeOnMemory* value, Arena* arena) { \
|
||||
return value->Mutable(arena); \
|
||||
} \
|
||||
template <typename Type> \
|
||||
inline const typename MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
|
||||
Type>::MapEntryAccessorType& \
|
||||
MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
|
||||
Type>::DefaultIfNotInitialized(const TypeOnMemory& value) { \
|
||||
return value.Get(); \
|
||||
} \
|
||||
template <typename Type> \
|
||||
inline bool \
|
||||
MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::IsInitialized( \
|
||||
const TypeOnMemory& /* value */) { \
|
||||
return true; \
|
||||
}
|
||||
STRING_OR_BYTES_HANDLER_FUNCTIONS(STRING)
|
||||
STRING_OR_BYTES_HANDLER_FUNCTIONS(BYTES)
|
||||
#undef STRING_OR_BYTES_HANDLER_FUNCTIONS
|
||||
|
||||
#define PRIMITIVE_HANDLER_FUNCTIONS(FieldType) \
|
||||
template <typename Type> \
|
||||
inline const typename MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
|
||||
Type>::MapEntryAccessorType& \
|
||||
MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
|
||||
Type>::GetExternalReference(const TypeOnMemory& value) { \
|
||||
return value; \
|
||||
} \
|
||||
template <typename Type> \
|
||||
inline size_t MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>:: \
|
||||
SpaceUsedInMapEntryLong(const TypeOnMemory& /* value */) { \
|
||||
return 0; \
|
||||
} \
|
||||
template <typename Type> \
|
||||
inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Clear( \
|
||||
TypeOnMemory* value, Arena* /* arena */) { \
|
||||
*value = 0; \
|
||||
} \
|
||||
template <typename Type> \
|
||||
inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Merge( \
|
||||
const MapEntryAccessorType& from, TypeOnMemory* to, \
|
||||
Arena* /* arena */) { \
|
||||
*to = from; \
|
||||
} \
|
||||
template <typename Type> \
|
||||
inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
|
||||
Type>::DeleteNoArena(TypeOnMemory& /* x */) {} \
|
||||
template <typename Type> \
|
||||
constexpr auto \
|
||||
MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Constinit() \
|
||||
->TypeOnMemory { \
|
||||
return 0; \
|
||||
} \
|
||||
template <typename Type> \
|
||||
inline typename MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
|
||||
Type>::MapEntryAccessorType* \
|
||||
MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::EnsureMutable( \
|
||||
TypeOnMemory* value, Arena* /* arena */) { \
|
||||
return value; \
|
||||
} \
|
||||
template <typename Type> \
|
||||
inline const typename MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
|
||||
Type>::MapEntryAccessorType& \
|
||||
MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
|
||||
Type>::DefaultIfNotInitialized(const TypeOnMemory& value) { \
|
||||
return value; \
|
||||
} \
|
||||
template <typename Type> \
|
||||
inline bool \
|
||||
MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::IsInitialized( \
|
||||
const TypeOnMemory& /* value */) { \
|
||||
return true; \
|
||||
}
|
||||
PRIMITIVE_HANDLER_FUNCTIONS(INT64)
|
||||
PRIMITIVE_HANDLER_FUNCTIONS(UINT64)
|
||||
PRIMITIVE_HANDLER_FUNCTIONS(INT32)
|
||||
PRIMITIVE_HANDLER_FUNCTIONS(UINT32)
|
||||
PRIMITIVE_HANDLER_FUNCTIONS(SINT64)
|
||||
PRIMITIVE_HANDLER_FUNCTIONS(SINT32)
|
||||
PRIMITIVE_HANDLER_FUNCTIONS(ENUM)
|
||||
PRIMITIVE_HANDLER_FUNCTIONS(DOUBLE)
|
||||
PRIMITIVE_HANDLER_FUNCTIONS(FLOAT)
|
||||
PRIMITIVE_HANDLER_FUNCTIONS(FIXED64)
|
||||
PRIMITIVE_HANDLER_FUNCTIONS(FIXED32)
|
||||
PRIMITIVE_HANDLER_FUNCTIONS(SFIXED64)
|
||||
PRIMITIVE_HANDLER_FUNCTIONS(SFIXED32)
|
||||
PRIMITIVE_HANDLER_FUNCTIONS(BOOL)
|
||||
#undef PRIMITIVE_HANDLER_FUNCTIONS
|
||||
|
||||
// Functions for operating on a map entry using type handlers.
|
||||
//
|
||||
// Does not contain any representation (this class is not intended to be
|
||||
// instantiated).
|
||||
template <typename Key, typename Value, WireFormatLite::FieldType kKeyFieldType,
|
||||
WireFormatLite::FieldType kValueFieldType>
|
||||
struct MapEntryFuncs {
|
||||
typedef MapTypeHandler<kKeyFieldType, Key> KeyTypeHandler;
|
||||
typedef MapTypeHandler<kValueFieldType, Value> ValueTypeHandler;
|
||||
enum : int {
|
||||
kKeyFieldNumber = 1,
|
||||
kValueFieldNumber = 2
|
||||
};
|
||||
|
||||
static uint8_t* InternalSerialize(int field_number, const Key& key,
|
||||
const Value& value, uint8_t* ptr,
|
||||
io::EpsCopyOutputStream* stream) {
|
||||
ptr = stream->EnsureSpace(ptr);
|
||||
ptr = WireFormatLite::WriteTagToArray(
|
||||
field_number, WireFormatLite::WIRETYPE_LENGTH_DELIMITED, ptr);
|
||||
ptr = io::CodedOutputStream::WriteVarint32ToArray(GetCachedSize(key, value),
|
||||
ptr);
|
||||
|
||||
ptr = KeyTypeHandler::Write(kKeyFieldNumber, key, ptr, stream);
|
||||
return ValueTypeHandler::Write(kValueFieldNumber, value, ptr, stream);
|
||||
}
|
||||
|
||||
static size_t ByteSizeLong(const Key& key, const Value& value) {
|
||||
// Tags for key and value will both be one byte (field numbers 1 and 2).
|
||||
size_t inner_length =
|
||||
2 + KeyTypeHandler::ByteSize(key) + ValueTypeHandler::ByteSize(value);
|
||||
return inner_length + io::CodedOutputStream::VarintSize32(
|
||||
static_cast<uint32_t>(inner_length));
|
||||
}
|
||||
|
||||
static int GetCachedSize(const Key& key, const Value& value) {
|
||||
// Tags for key and value will both be one byte (field numbers 1 and 2).
|
||||
return 2 + KeyTypeHandler::GetCachedSize(key) +
|
||||
ValueTypeHandler::GetCachedSize(value);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_MAP_TYPE_HANDLER_H__
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,591 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Authors: wink@google.com (Wink Saville),
|
||||
// kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
//
|
||||
// Defines MessageLite, the abstract interface implemented by all (lite
|
||||
// and non-lite) protocol message objects.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_MESSAGE_LITE_H__
|
||||
#define GOOGLE_PROTOBUF_MESSAGE_LITE_H__
|
||||
|
||||
|
||||
#include <climits>
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/logging.h>
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/arena.h>
|
||||
#include <google/protobuf/stubs/once.h>
|
||||
#include <google/protobuf/port.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
#include <google/protobuf/explicitly_constructed.h>
|
||||
#include <google/protobuf/metadata_lite.h>
|
||||
#include <google/protobuf/stubs/hash.h> // TODO(b/211442718): cleanup
|
||||
|
||||
// clang-format off
|
||||
#include <google/protobuf/port_def.inc>
|
||||
// clang-format on
|
||||
|
||||
#ifdef SWIG
|
||||
#error "You cannot SWIG proto headers"
|
||||
#endif
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
template <typename T>
|
||||
class RepeatedPtrField;
|
||||
|
||||
class FastReflectionMessageMutator;
|
||||
class FastReflectionStringSetter;
|
||||
class Reflection;
|
||||
|
||||
namespace io {
|
||||
|
||||
class CodedInputStream;
|
||||
class CodedOutputStream;
|
||||
class ZeroCopyInputStream;
|
||||
class ZeroCopyOutputStream;
|
||||
|
||||
} // namespace io
|
||||
namespace internal {
|
||||
|
||||
class SwapFieldHelper;
|
||||
|
||||
// See parse_context.h for explanation
|
||||
class ParseContext;
|
||||
|
||||
class ExtensionSet;
|
||||
class LazyField;
|
||||
class RepeatedPtrFieldBase;
|
||||
class TcParser;
|
||||
class WireFormatLite;
|
||||
class WeakFieldMap;
|
||||
|
||||
template <typename Type>
|
||||
class GenericTypeHandler; // defined in repeated_field.h
|
||||
|
||||
// We compute sizes as size_t but cache them as int. This function converts a
|
||||
// computed size to a cached size. Since we don't proceed with serialization
|
||||
// if the total size was > INT_MAX, it is not important what this function
|
||||
// returns for inputs > INT_MAX. However this case should not error or
|
||||
// GOOGLE_CHECK-fail, because the full size_t resolution is still returned from
|
||||
// ByteSizeLong() and checked against INT_MAX; we can catch the overflow
|
||||
// there.
|
||||
inline int ToCachedSize(size_t size) { return static_cast<int>(size); }
|
||||
|
||||
// We mainly calculate sizes in terms of size_t, but some functions that
|
||||
// compute sizes return "int". These int sizes are expected to always be
|
||||
// positive. This function is more efficient than casting an int to size_t
|
||||
// directly on 64-bit platforms because it avoids making the compiler emit a
|
||||
// sign extending instruction, which we don't want and don't want to pay for.
|
||||
inline size_t FromIntSize(int size) {
|
||||
// Convert to unsigned before widening so sign extension is not necessary.
|
||||
return static_cast<unsigned int>(size);
|
||||
}
|
||||
|
||||
// For cases where a legacy function returns an integer size. We GOOGLE_DCHECK()
|
||||
// that the conversion will fit within an integer; if this is false then we
|
||||
// are losing information.
|
||||
inline int ToIntSize(size_t size) {
|
||||
GOOGLE_DCHECK_LE(size, static_cast<size_t>(INT_MAX));
|
||||
return static_cast<int>(size);
|
||||
}
|
||||
|
||||
// Default empty string object. Don't use this directly. Instead, call
|
||||
// GetEmptyString() to get the reference. This empty string is aligned with a
|
||||
// minimum alignment of 8 bytes to match the requirement of ArenaStringPtr.
|
||||
PROTOBUF_EXPORT extern ExplicitlyConstructedArenaString
|
||||
fixed_address_empty_string;
|
||||
|
||||
|
||||
PROTOBUF_EXPORT constexpr const std::string& GetEmptyStringAlreadyInited() {
|
||||
return fixed_address_empty_string.get();
|
||||
}
|
||||
|
||||
PROTOBUF_EXPORT size_t StringSpaceUsedExcludingSelfLong(const std::string& str);
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// Interface to light weight protocol messages.
|
||||
//
|
||||
// This interface is implemented by all protocol message objects. Non-lite
|
||||
// messages additionally implement the Message interface, which is a
|
||||
// subclass of MessageLite. Use MessageLite instead when you only need
|
||||
// the subset of features which it supports -- namely, nothing that uses
|
||||
// descriptors or reflection. You can instruct the protocol compiler
|
||||
// to generate classes which implement only MessageLite, not the full
|
||||
// Message interface, by adding the following line to the .proto file:
|
||||
//
|
||||
// option optimize_for = LITE_RUNTIME;
|
||||
//
|
||||
// This is particularly useful on resource-constrained systems where
|
||||
// the full protocol buffers runtime library is too big.
|
||||
//
|
||||
// Note that on non-constrained systems (e.g. servers) when you need
|
||||
// to link in lots of protocol definitions, a better way to reduce
|
||||
// total code footprint is to use optimize_for = CODE_SIZE. This
|
||||
// will make the generated code smaller while still supporting all the
|
||||
// same features (at the expense of speed). optimize_for = LITE_RUNTIME
|
||||
// is best when you only have a small number of message types linked
|
||||
// into your binary, in which case the size of the protocol buffers
|
||||
// runtime itself is the biggest problem.
|
||||
//
|
||||
// Users must not derive from this class. Only the protocol compiler and
|
||||
// the internal library are allowed to create subclasses.
|
||||
class PROTOBUF_EXPORT MessageLite {
|
||||
public:
|
||||
constexpr MessageLite() {}
|
||||
virtual ~MessageLite() = default;
|
||||
|
||||
// Basic Operations ------------------------------------------------
|
||||
|
||||
// Get the name of this message type, e.g. "foo.bar.BazProto".
|
||||
virtual std::string GetTypeName() const = 0;
|
||||
|
||||
// Construct a new instance of the same type. Ownership is passed to the
|
||||
// caller.
|
||||
MessageLite* New() const { return New(nullptr); }
|
||||
|
||||
// Construct a new instance on the arena. Ownership is passed to the caller
|
||||
// if arena is a nullptr.
|
||||
virtual MessageLite* New(Arena* arena) const = 0;
|
||||
|
||||
// Returns user-owned arena; nullptr if it's message owned.
|
||||
Arena* GetArena() const { return _internal_metadata_.user_arena(); }
|
||||
|
||||
// Clear all fields of the message and set them to their default values.
|
||||
// Clear() assumes that any memory allocated to hold parts of the message
|
||||
// will likely be needed again, so the memory used may not be freed.
|
||||
// To ensure that all memory used by a Message is freed, you must delete it.
|
||||
virtual void Clear() = 0;
|
||||
|
||||
// Quickly check if all required fields have values set.
|
||||
virtual bool IsInitialized() const = 0;
|
||||
|
||||
// This is not implemented for Lite messages -- it just returns "(cannot
|
||||
// determine missing fields for lite message)". However, it is implemented
|
||||
// for full messages. See message.h.
|
||||
virtual std::string InitializationErrorString() const;
|
||||
|
||||
// If |other| is the exact same class as this, calls MergeFrom(). Otherwise,
|
||||
// results are undefined (probably crash).
|
||||
virtual void CheckTypeAndMergeFrom(const MessageLite& other) = 0;
|
||||
|
||||
// These methods return a human-readable summary of the message. Note that
|
||||
// since the MessageLite interface does not support reflection, there is very
|
||||
// little information that these methods can provide. They are shadowed by
|
||||
// methods of the same name on the Message interface which provide much more
|
||||
// information. The methods here are intended primarily to facilitate code
|
||||
// reuse for logic that needs to interoperate with both full and lite protos.
|
||||
//
|
||||
// The format of the returned string is subject to change, so please do not
|
||||
// assume it will remain stable over time.
|
||||
std::string DebugString() const;
|
||||
std::string ShortDebugString() const { return DebugString(); }
|
||||
// MessageLite::DebugString is already Utf8 Safe. This is to add compatibility
|
||||
// with Message.
|
||||
std::string Utf8DebugString() const { return DebugString(); }
|
||||
|
||||
// Parsing ---------------------------------------------------------
|
||||
// Methods for parsing in protocol buffer format. Most of these are
|
||||
// just simple wrappers around MergeFromCodedStream(). Clear() will be
|
||||
// called before merging the input.
|
||||
|
||||
// Fill the message with a protocol buffer parsed from the given input
|
||||
// stream. Returns false on a read error or if the input is in the wrong
|
||||
// format. A successful return does not indicate the entire input is
|
||||
// consumed, ensure you call ConsumedEntireMessage() to check that if
|
||||
// applicable.
|
||||
PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParseFromCodedStream(
|
||||
io::CodedInputStream* input);
|
||||
// Like ParseFromCodedStream(), but accepts messages that are missing
|
||||
// required fields.
|
||||
PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParsePartialFromCodedStream(
|
||||
io::CodedInputStream* input);
|
||||
// Read a protocol buffer from the given zero-copy input stream. If
|
||||
// successful, the entire input will be consumed.
|
||||
PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParseFromZeroCopyStream(
|
||||
io::ZeroCopyInputStream* input);
|
||||
// Like ParseFromZeroCopyStream(), but accepts messages that are missing
|
||||
// required fields.
|
||||
PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParsePartialFromZeroCopyStream(
|
||||
io::ZeroCopyInputStream* input);
|
||||
// Parse a protocol buffer from a file descriptor. If successful, the entire
|
||||
// input will be consumed.
|
||||
PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParseFromFileDescriptor(
|
||||
int file_descriptor);
|
||||
// Like ParseFromFileDescriptor(), but accepts messages that are missing
|
||||
// required fields.
|
||||
PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParsePartialFromFileDescriptor(
|
||||
int file_descriptor);
|
||||
// Parse a protocol buffer from a C++ istream. If successful, the entire
|
||||
// input will be consumed.
|
||||
PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParseFromIstream(std::istream* input);
|
||||
// Like ParseFromIstream(), but accepts messages that are missing
|
||||
// required fields.
|
||||
PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParsePartialFromIstream(
|
||||
std::istream* input);
|
||||
// Read a protocol buffer from the given zero-copy input stream, expecting
|
||||
// the message to be exactly "size" bytes long. If successful, exactly
|
||||
// this many bytes will have been consumed from the input.
|
||||
bool MergePartialFromBoundedZeroCopyStream(io::ZeroCopyInputStream* input,
|
||||
int size);
|
||||
// Like ParseFromBoundedZeroCopyStream(), but accepts messages that are
|
||||
// missing required fields.
|
||||
bool MergeFromBoundedZeroCopyStream(io::ZeroCopyInputStream* input, int size);
|
||||
PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParseFromBoundedZeroCopyStream(
|
||||
io::ZeroCopyInputStream* input, int size);
|
||||
// Like ParseFromBoundedZeroCopyStream(), but accepts messages that are
|
||||
// missing required fields.
|
||||
PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParsePartialFromBoundedZeroCopyStream(
|
||||
io::ZeroCopyInputStream* input, int size);
|
||||
// Parses a protocol buffer contained in a string. Returns true on success.
|
||||
// This function takes a string in the (non-human-readable) binary wire
|
||||
// format, matching the encoding output by MessageLite::SerializeToString().
|
||||
// If you'd like to convert a human-readable string into a protocol buffer
|
||||
// object, see google::protobuf::TextFormat::ParseFromString().
|
||||
PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParseFromString(ConstStringParam data);
|
||||
// Like ParseFromString(), but accepts messages that are missing
|
||||
// required fields.
|
||||
PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParsePartialFromString(
|
||||
ConstStringParam data);
|
||||
// Parse a protocol buffer contained in an array of bytes.
|
||||
PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParseFromArray(const void* data,
|
||||
int size);
|
||||
// Like ParseFromArray(), but accepts messages that are missing
|
||||
// required fields.
|
||||
PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParsePartialFromArray(const void* data,
|
||||
int size);
|
||||
|
||||
|
||||
// Reads a protocol buffer from the stream and merges it into this
|
||||
// Message. Singular fields read from the what is
|
||||
// already in the Message and repeated fields are appended to those
|
||||
// already present.
|
||||
//
|
||||
// It is the responsibility of the caller to call input->LastTagWas()
|
||||
// (for groups) or input->ConsumedEntireMessage() (for non-groups) after
|
||||
// this returns to verify that the message's end was delimited correctly.
|
||||
//
|
||||
// ParseFromCodedStream() is implemented as Clear() followed by
|
||||
// MergeFromCodedStream().
|
||||
bool MergeFromCodedStream(io::CodedInputStream* input);
|
||||
|
||||
// Like MergeFromCodedStream(), but succeeds even if required fields are
|
||||
// missing in the input.
|
||||
//
|
||||
// MergeFromCodedStream() is just implemented as MergePartialFromCodedStream()
|
||||
// followed by IsInitialized().
|
||||
bool MergePartialFromCodedStream(io::CodedInputStream* input);
|
||||
|
||||
// Merge a protocol buffer contained in a string.
|
||||
bool MergeFromString(ConstStringParam data);
|
||||
|
||||
|
||||
// Serialization ---------------------------------------------------
|
||||
// Methods for serializing in protocol buffer format. Most of these
|
||||
// are just simple wrappers around ByteSize() and SerializeWithCachedSizes().
|
||||
|
||||
// Write a protocol buffer of this message to the given output. Returns
|
||||
// false on a write error. If the message is missing required fields,
|
||||
// this may GOOGLE_CHECK-fail.
|
||||
bool SerializeToCodedStream(io::CodedOutputStream* output) const;
|
||||
// Like SerializeToCodedStream(), but allows missing required fields.
|
||||
bool SerializePartialToCodedStream(io::CodedOutputStream* output) const;
|
||||
// Write the message to the given zero-copy output stream. All required
|
||||
// fields must be set.
|
||||
bool SerializeToZeroCopyStream(io::ZeroCopyOutputStream* output) const;
|
||||
// Like SerializeToZeroCopyStream(), but allows missing required fields.
|
||||
bool SerializePartialToZeroCopyStream(io::ZeroCopyOutputStream* output) const;
|
||||
// Serialize the message and store it in the given string. All required
|
||||
// fields must be set.
|
||||
bool SerializeToString(std::string* output) const;
|
||||
// Like SerializeToString(), but allows missing required fields.
|
||||
bool SerializePartialToString(std::string* output) const;
|
||||
// Serialize the message and store it in the given byte array. All required
|
||||
// fields must be set.
|
||||
bool SerializeToArray(void* data, int size) const;
|
||||
// Like SerializeToArray(), but allows missing required fields.
|
||||
bool SerializePartialToArray(void* data, int size) const;
|
||||
|
||||
// Make a string encoding the message. Is equivalent to calling
|
||||
// SerializeToString() on a string and using that. Returns the empty
|
||||
// string if SerializeToString() would have returned an error.
|
||||
// Note: If you intend to generate many such strings, you may
|
||||
// reduce heap fragmentation by instead re-using the same string
|
||||
// object with calls to SerializeToString().
|
||||
std::string SerializeAsString() const;
|
||||
// Like SerializeAsString(), but allows missing required fields.
|
||||
std::string SerializePartialAsString() const;
|
||||
|
||||
// Serialize the message and write it to the given file descriptor. All
|
||||
// required fields must be set.
|
||||
bool SerializeToFileDescriptor(int file_descriptor) const;
|
||||
// Like SerializeToFileDescriptor(), but allows missing required fields.
|
||||
bool SerializePartialToFileDescriptor(int file_descriptor) const;
|
||||
// Serialize the message and write it to the given C++ ostream. All
|
||||
// required fields must be set.
|
||||
bool SerializeToOstream(std::ostream* output) const;
|
||||
// Like SerializeToOstream(), but allows missing required fields.
|
||||
bool SerializePartialToOstream(std::ostream* output) const;
|
||||
|
||||
// Like SerializeToString(), but appends to the data to the string's
|
||||
// existing contents. All required fields must be set.
|
||||
bool AppendToString(std::string* output) const;
|
||||
// Like AppendToString(), but allows missing required fields.
|
||||
bool AppendPartialToString(std::string* output) const;
|
||||
|
||||
|
||||
// Computes the serialized size of the message. This recursively calls
|
||||
// ByteSizeLong() on all embedded messages.
|
||||
//
|
||||
// ByteSizeLong() is generally linear in the number of fields defined for the
|
||||
// proto.
|
||||
virtual size_t ByteSizeLong() const = 0;
|
||||
|
||||
// Legacy ByteSize() API.
|
||||
PROTOBUF_DEPRECATED_MSG("Please use ByteSizeLong() instead")
|
||||
int ByteSize() const { return internal::ToIntSize(ByteSizeLong()); }
|
||||
|
||||
// Serializes the message without recomputing the size. The message must not
|
||||
// have changed since the last call to ByteSize(), and the value returned by
|
||||
// ByteSize must be non-negative. Otherwise the results are undefined.
|
||||
void SerializeWithCachedSizes(io::CodedOutputStream* output) const {
|
||||
output->SetCur(_InternalSerialize(output->Cur(), output->EpsCopy()));
|
||||
}
|
||||
|
||||
// Functions below here are not part of the public interface. It isn't
|
||||
// enforced, but they should be treated as private, and will be private
|
||||
// at some future time. Unfortunately the implementation of the "friend"
|
||||
// keyword in GCC is broken at the moment, but we expect it will be fixed.
|
||||
|
||||
// Like SerializeWithCachedSizes, but writes directly to *target, returning
|
||||
// a pointer to the byte immediately after the last byte written. "target"
|
||||
// must point at a byte array of at least ByteSize() bytes. Whether to use
|
||||
// deterministic serialization, e.g., maps in sorted order, is determined by
|
||||
// CodedOutputStream::IsDefaultSerializationDeterministic().
|
||||
uint8_t* SerializeWithCachedSizesToArray(uint8_t* target) const;
|
||||
|
||||
// Returns the result of the last call to ByteSize(). An embedded message's
|
||||
// size is needed both to serialize it (because embedded messages are
|
||||
// length-delimited) and to compute the outer message's size. Caching
|
||||
// the size avoids computing it multiple times.
|
||||
//
|
||||
// ByteSize() does not automatically use the cached size when available
|
||||
// because this would require invalidating it every time the message was
|
||||
// modified, which would be too hard and expensive. (E.g. if a deeply-nested
|
||||
// sub-message is changed, all of its parents' cached sizes would need to be
|
||||
// invalidated, which is too much work for an otherwise inlined setter
|
||||
// method.)
|
||||
virtual int GetCachedSize() const = 0;
|
||||
|
||||
virtual const char* _InternalParse(const char* /*ptr*/,
|
||||
internal::ParseContext* /*ctx*/) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
virtual void OnDemandRegisterArenaDtor(Arena* /*arena*/) {}
|
||||
|
||||
protected:
|
||||
template <typename T>
|
||||
static T* CreateMaybeMessage(Arena* arena) {
|
||||
return Arena::CreateMaybeMessage<T>(arena);
|
||||
}
|
||||
|
||||
inline explicit MessageLite(Arena* arena, bool is_message_owned = false)
|
||||
: _internal_metadata_(arena, is_message_owned) {}
|
||||
|
||||
// Returns the arena, if any, that directly owns this message and its internal
|
||||
// memory (Arena::Own is different in that the arena doesn't directly own the
|
||||
// internal memory). This method is used in proto's implementation for
|
||||
// swapping, moving and setting allocated, for deciding whether the ownership
|
||||
// of this message or its internal memory could be changed.
|
||||
Arena* GetOwningArena() const { return _internal_metadata_.owning_arena(); }
|
||||
|
||||
// Returns the arena, used for allocating internal objects(e.g., child
|
||||
// messages, etc), or owning incoming objects (e.g., set allocated).
|
||||
Arena* GetArenaForAllocation() const { return _internal_metadata_.arena(); }
|
||||
|
||||
// Returns true if this message is enabled for message-owned arena (MOA)
|
||||
// trials. No lite messages are eligible for MOA.
|
||||
static bool InMoaTrial() { return false; }
|
||||
|
||||
internal::InternalMetadata _internal_metadata_;
|
||||
|
||||
public:
|
||||
enum ParseFlags {
|
||||
kMerge = 0,
|
||||
kParse = 1,
|
||||
kMergePartial = 2,
|
||||
kParsePartial = 3,
|
||||
kMergeWithAliasing = 4,
|
||||
kParseWithAliasing = 5,
|
||||
kMergePartialWithAliasing = 6,
|
||||
kParsePartialWithAliasing = 7
|
||||
};
|
||||
|
||||
template <ParseFlags flags, typename T>
|
||||
bool ParseFrom(const T& input);
|
||||
|
||||
// Fast path when conditions match (ie. non-deterministic)
|
||||
// uint8_t* _InternalSerialize(uint8_t* ptr) const;
|
||||
virtual uint8_t* _InternalSerialize(
|
||||
uint8_t* ptr, io::EpsCopyOutputStream* stream) const = 0;
|
||||
|
||||
// Identical to IsInitialized() except that it logs an error message.
|
||||
bool IsInitializedWithErrors() const {
|
||||
if (IsInitialized()) return true;
|
||||
LogInitializationErrorMessage();
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class FastReflectionMessageMutator;
|
||||
friend class FastReflectionStringSetter;
|
||||
friend class Message;
|
||||
friend class Reflection;
|
||||
friend class internal::ExtensionSet;
|
||||
friend class internal::LazyField;
|
||||
friend class internal::SwapFieldHelper;
|
||||
friend class internal::TcParser;
|
||||
friend class internal::WeakFieldMap;
|
||||
friend class internal::WireFormatLite;
|
||||
|
||||
template <typename Type>
|
||||
friend class Arena::InternalHelper;
|
||||
template <typename Type>
|
||||
friend class internal::GenericTypeHandler;
|
||||
|
||||
void LogInitializationErrorMessage() const;
|
||||
|
||||
bool MergeFromImpl(io::CodedInputStream* input, ParseFlags parse_flags);
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageLite);
|
||||
};
|
||||
|
||||
namespace internal {
|
||||
|
||||
template <bool alias>
|
||||
bool MergeFromImpl(StringPiece input, MessageLite* msg,
|
||||
MessageLite::ParseFlags parse_flags);
|
||||
extern template bool MergeFromImpl<false>(StringPiece input,
|
||||
MessageLite* msg,
|
||||
MessageLite::ParseFlags parse_flags);
|
||||
extern template bool MergeFromImpl<true>(StringPiece input,
|
||||
MessageLite* msg,
|
||||
MessageLite::ParseFlags parse_flags);
|
||||
|
||||
template <bool alias>
|
||||
bool MergeFromImpl(io::ZeroCopyInputStream* input, MessageLite* msg,
|
||||
MessageLite::ParseFlags parse_flags);
|
||||
extern template bool MergeFromImpl<false>(io::ZeroCopyInputStream* input,
|
||||
MessageLite* msg,
|
||||
MessageLite::ParseFlags parse_flags);
|
||||
extern template bool MergeFromImpl<true>(io::ZeroCopyInputStream* input,
|
||||
MessageLite* msg,
|
||||
MessageLite::ParseFlags parse_flags);
|
||||
|
||||
struct BoundedZCIS {
|
||||
io::ZeroCopyInputStream* zcis;
|
||||
int limit;
|
||||
};
|
||||
|
||||
template <bool alias>
|
||||
bool MergeFromImpl(BoundedZCIS input, MessageLite* msg,
|
||||
MessageLite::ParseFlags parse_flags);
|
||||
extern template bool MergeFromImpl<false>(BoundedZCIS input, MessageLite* msg,
|
||||
MessageLite::ParseFlags parse_flags);
|
||||
extern template bool MergeFromImpl<true>(BoundedZCIS input, MessageLite* msg,
|
||||
MessageLite::ParseFlags parse_flags);
|
||||
|
||||
template <typename T>
|
||||
struct SourceWrapper;
|
||||
|
||||
template <bool alias, typename T>
|
||||
bool MergeFromImpl(const SourceWrapper<T>& input, MessageLite* msg,
|
||||
MessageLite::ParseFlags parse_flags) {
|
||||
return input.template MergeInto<alias>(msg, parse_flags);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
template <MessageLite::ParseFlags flags, typename T>
|
||||
bool MessageLite::ParseFrom(const T& input) {
|
||||
if (flags & kParse) Clear();
|
||||
constexpr bool alias = (flags & kMergeWithAliasing) != 0;
|
||||
return internal::MergeFromImpl<alias>(input, this, flags);
|
||||
}
|
||||
|
||||
// ===================================================================
|
||||
// Shutdown support.
|
||||
|
||||
|
||||
// Shut down the entire protocol buffers library, deleting all static-duration
|
||||
// objects allocated by the library or by generated .pb.cc files.
|
||||
//
|
||||
// There are two reasons you might want to call this:
|
||||
// * You use a draconian definition of "memory leak" in which you expect
|
||||
// every single malloc() to have a corresponding free(), even for objects
|
||||
// which live until program exit.
|
||||
// * You are writing a dynamically-loaded library which needs to clean up
|
||||
// after itself when the library is unloaded.
|
||||
//
|
||||
// It is safe to call this multiple times. However, it is not safe to use
|
||||
// any other part of the protocol buffers library after
|
||||
// ShutdownProtobufLibrary() has been called. Furthermore this call is not
|
||||
// thread safe, user needs to synchronize multiple calls.
|
||||
PROTOBUF_EXPORT void ShutdownProtobufLibrary();
|
||||
|
||||
namespace internal {
|
||||
|
||||
// Register a function to be called when ShutdownProtocolBuffers() is called.
|
||||
PROTOBUF_EXPORT void OnShutdown(void (*func)());
|
||||
// Run an arbitrary function on an arg
|
||||
PROTOBUF_EXPORT void OnShutdownRun(void (*f)(const void*), const void* arg);
|
||||
|
||||
template <typename T>
|
||||
T* OnShutdownDelete(T* p) {
|
||||
OnShutdownRun([](const void* pp) { delete static_cast<const T*>(pp); }, p);
|
||||
return p;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_MESSAGE_LITE_H__
|
||||
@@ -1,36 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_METADATA_H__
|
||||
#define GOOGLE_PROTOBUF_METADATA_H__
|
||||
|
||||
// TODO(b/151117630): Remove this file and all instances where it gets imported.
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_METADATA_H__
|
||||
@@ -1,316 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_METADATA_LITE_H__
|
||||
#define GOOGLE_PROTOBUF_METADATA_LITE_H__
|
||||
|
||||
#include <string>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/arena.h>
|
||||
#include <google/protobuf/port.h>
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
#ifdef SWIG
|
||||
#error "You cannot SWIG proto headers"
|
||||
#endif
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
// This is the representation for messages that support arena allocation. It
|
||||
// uses a tagged pointer to either store the owning Arena pointer, if there are
|
||||
// no unknown fields, or a pointer to a block of memory with both the owning
|
||||
// Arena pointer and the UnknownFieldSet, if there are unknown fields. Besides,
|
||||
// it also uses the tag to distinguish whether the owning Arena pointer is also
|
||||
// used by sub-structure allocation. This optimization allows for
|
||||
// "zero-overhead" storage of the Arena pointer, relative to the above baseline
|
||||
// implementation.
|
||||
//
|
||||
// The tagged pointer uses the least two significant bits to disambiguate cases.
|
||||
// It uses bit 0 == 0 to indicate an arena pointer and bit 0 == 1 to indicate a
|
||||
// UFS+Arena-container pointer. Besides it uses bit 1 == 0 to indicate arena
|
||||
// allocation and bit 1 == 1 to indicate heap allocation.
|
||||
class PROTOBUF_EXPORT InternalMetadata {
|
||||
public:
|
||||
constexpr InternalMetadata() : ptr_(0) {}
|
||||
explicit InternalMetadata(Arena* arena, bool is_message_owned = false) {
|
||||
SetArena(arena, is_message_owned);
|
||||
}
|
||||
|
||||
void SetArena(Arena* arena, bool is_message_owned) {
|
||||
ptr_ = is_message_owned
|
||||
? reinterpret_cast<intptr_t>(arena) | kMessageOwnedArenaTagMask
|
||||
: reinterpret_cast<intptr_t>(arena);
|
||||
GOOGLE_DCHECK(!is_message_owned || arena != nullptr);
|
||||
}
|
||||
|
||||
// To keep the ABI identical between debug and non-debug builds,
|
||||
// the destructor is always defined here even though it may delegate
|
||||
// to a non-inline private method.
|
||||
// (see https://github.com/protocolbuffers/protobuf/issues/9947)
|
||||
~InternalMetadata() {
|
||||
#if defined(NDEBUG) || defined(_MSC_VER)
|
||||
if (HasMessageOwnedArenaTag()) {
|
||||
delete reinterpret_cast<Arena*>(ptr_ - kMessageOwnedArenaTagMask);
|
||||
}
|
||||
#else
|
||||
CheckedDestruct();
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Delete() {
|
||||
// Note that Delete<> should be called not more than once.
|
||||
if (have_unknown_fields()) {
|
||||
DeleteOutOfLineHelper<T>();
|
||||
}
|
||||
}
|
||||
|
||||
// DeleteReturnArena will delete the unknown fields only if they weren't
|
||||
// allocated on an arena. Then it updates the flags so that if you call
|
||||
// have_unknown_fields(), it will return false. Finally, it returns the
|
||||
// current value of arena(). It is designed to be used as part of a
|
||||
// Message class's destructor call, so that when control eventually gets
|
||||
// to ~InternalMetadata(), we don't need to check for have_unknown_fields()
|
||||
// again.
|
||||
template <typename T>
|
||||
Arena* DeleteReturnArena() {
|
||||
if (have_unknown_fields()) {
|
||||
return DeleteOutOfLineHelper<T>();
|
||||
} else {
|
||||
return PtrValue<Arena>();
|
||||
}
|
||||
}
|
||||
|
||||
PROTOBUF_NDEBUG_INLINE Arena* owning_arena() const {
|
||||
return HasMessageOwnedArenaTag() ? nullptr : arena();
|
||||
}
|
||||
|
||||
PROTOBUF_NDEBUG_INLINE Arena* user_arena() const {
|
||||
Arena* a = arena();
|
||||
return a && !a->IsMessageOwned() ? a : nullptr;
|
||||
}
|
||||
|
||||
PROTOBUF_NDEBUG_INLINE Arena* arena() const {
|
||||
if (PROTOBUF_PREDICT_FALSE(have_unknown_fields())) {
|
||||
return PtrValue<ContainerBase>()->arena;
|
||||
} else {
|
||||
return PtrValue<Arena>();
|
||||
}
|
||||
}
|
||||
|
||||
PROTOBUF_NDEBUG_INLINE bool have_unknown_fields() const {
|
||||
return HasUnknownFieldsTag();
|
||||
}
|
||||
|
||||
PROTOBUF_NDEBUG_INLINE void* raw_arena_ptr() const {
|
||||
return reinterpret_cast<void*>(ptr_);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
PROTOBUF_NDEBUG_INLINE const T& unknown_fields(
|
||||
const T& (*default_instance)()) const {
|
||||
if (PROTOBUF_PREDICT_FALSE(have_unknown_fields())) {
|
||||
return PtrValue<Container<T>>()->unknown_fields;
|
||||
} else {
|
||||
return default_instance();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
PROTOBUF_NDEBUG_INLINE T* mutable_unknown_fields() {
|
||||
if (PROTOBUF_PREDICT_TRUE(have_unknown_fields())) {
|
||||
return &PtrValue<Container<T>>()->unknown_fields;
|
||||
} else {
|
||||
return mutable_unknown_fields_slow<T>();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
PROTOBUF_NDEBUG_INLINE void Swap(InternalMetadata* other) {
|
||||
// Semantics here are that we swap only the unknown fields, not the arena
|
||||
// pointer. We cannot simply swap ptr_ with other->ptr_ because we need to
|
||||
// maintain our own arena ptr. Also, our ptr_ and other's ptr_ may be in
|
||||
// different states (direct arena pointer vs. container with UFS) so we
|
||||
// cannot simply swap ptr_ and then restore the arena pointers. We reuse
|
||||
// UFS's swap implementation instead.
|
||||
if (have_unknown_fields() || other->have_unknown_fields()) {
|
||||
DoSwap<T>(other->mutable_unknown_fields<T>());
|
||||
}
|
||||
}
|
||||
|
||||
PROTOBUF_NDEBUG_INLINE void InternalSwap(InternalMetadata* other) {
|
||||
std::swap(ptr_, other->ptr_);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
PROTOBUF_NDEBUG_INLINE void MergeFrom(const InternalMetadata& other) {
|
||||
if (other.have_unknown_fields()) {
|
||||
DoMergeFrom<T>(other.unknown_fields<T>(nullptr));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
PROTOBUF_NDEBUG_INLINE void Clear() {
|
||||
if (have_unknown_fields()) {
|
||||
DoClear<T>();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
intptr_t ptr_;
|
||||
|
||||
// Tagged pointer implementation.
|
||||
static constexpr intptr_t kUnknownFieldsTagMask = 1;
|
||||
static constexpr intptr_t kMessageOwnedArenaTagMask = 2;
|
||||
static constexpr intptr_t kPtrTagMask =
|
||||
kUnknownFieldsTagMask | kMessageOwnedArenaTagMask;
|
||||
static constexpr intptr_t kPtrValueMask = ~kPtrTagMask;
|
||||
|
||||
// Accessors for pointer tag and pointer value.
|
||||
PROTOBUF_ALWAYS_INLINE bool HasUnknownFieldsTag() const {
|
||||
return ptr_ & kUnknownFieldsTagMask;
|
||||
}
|
||||
PROTOBUF_ALWAYS_INLINE bool HasMessageOwnedArenaTag() const {
|
||||
return ptr_ & kMessageOwnedArenaTagMask;
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
U* PtrValue() const {
|
||||
return reinterpret_cast<U*>(ptr_ & kPtrValueMask);
|
||||
}
|
||||
|
||||
// If ptr_'s tag is kTagContainer, it points to an instance of this struct.
|
||||
struct ContainerBase {
|
||||
Arena* arena;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct Container : public ContainerBase {
|
||||
T unknown_fields;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
PROTOBUF_NOINLINE Arena* DeleteOutOfLineHelper() {
|
||||
if (auto* a = arena()) {
|
||||
// Subtle: we want to preserve the message-owned arena flag, while at the
|
||||
// same time replacing the pointer to Container<T> with a pointer to the
|
||||
// arena.
|
||||
intptr_t message_owned_arena_tag = ptr_ & kMessageOwnedArenaTagMask;
|
||||
ptr_ = reinterpret_cast<intptr_t>(a) | message_owned_arena_tag;
|
||||
return a;
|
||||
} else {
|
||||
delete PtrValue<Container<T>>();
|
||||
ptr_ = 0;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
PROTOBUF_NOINLINE T* mutable_unknown_fields_slow() {
|
||||
Arena* my_arena = arena();
|
||||
Container<T>* container = Arena::Create<Container<T>>(my_arena);
|
||||
intptr_t message_owned_arena_tag = ptr_ & kMessageOwnedArenaTagMask;
|
||||
// Two-step assignment works around a bug in clang's static analyzer:
|
||||
// https://bugs.llvm.org/show_bug.cgi?id=34198.
|
||||
ptr_ = reinterpret_cast<intptr_t>(container);
|
||||
ptr_ |= kUnknownFieldsTagMask | message_owned_arena_tag;
|
||||
container->arena = my_arena;
|
||||
return &(container->unknown_fields);
|
||||
}
|
||||
|
||||
// Templated functions.
|
||||
|
||||
template <typename T>
|
||||
PROTOBUF_NOINLINE void DoClear() {
|
||||
mutable_unknown_fields<T>()->Clear();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
PROTOBUF_NOINLINE void DoMergeFrom(const T& other) {
|
||||
mutable_unknown_fields<T>()->MergeFrom(other);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
PROTOBUF_NOINLINE void DoSwap(T* other) {
|
||||
mutable_unknown_fields<T>()->Swap(other);
|
||||
}
|
||||
|
||||
// Private helper with debug checks for ~InternalMetadata()
|
||||
void CheckedDestruct();
|
||||
};
|
||||
|
||||
// String Template specializations.
|
||||
|
||||
template <>
|
||||
PROTOBUF_EXPORT void InternalMetadata::DoClear<std::string>();
|
||||
template <>
|
||||
PROTOBUF_EXPORT void InternalMetadata::DoMergeFrom<std::string>(
|
||||
const std::string& other);
|
||||
template <>
|
||||
PROTOBUF_EXPORT void InternalMetadata::DoSwap<std::string>(std::string* other);
|
||||
|
||||
// This helper RAII class is needed to efficiently parse unknown fields. We
|
||||
// should only call mutable_unknown_fields if there are actual unknown fields.
|
||||
// The obvious thing to just use a stack string and swap it at the end of
|
||||
// the parse won't work, because the destructor of StringOutputStream needs to
|
||||
// be called before we can modify the string (it check-fails). Using
|
||||
// LiteUnknownFieldSetter setter(&_internal_metadata_);
|
||||
// StringOutputStream stream(setter.buffer());
|
||||
// guarantees that the string is only swapped after stream is destroyed.
|
||||
class PROTOBUF_EXPORT LiteUnknownFieldSetter {
|
||||
public:
|
||||
explicit LiteUnknownFieldSetter(InternalMetadata* metadata)
|
||||
: metadata_(metadata) {
|
||||
if (metadata->have_unknown_fields()) {
|
||||
buffer_.swap(*metadata->mutable_unknown_fields<std::string>());
|
||||
}
|
||||
}
|
||||
~LiteUnknownFieldSetter() {
|
||||
if (!buffer_.empty())
|
||||
metadata_->mutable_unknown_fields<std::string>()->swap(buffer_);
|
||||
}
|
||||
std::string* buffer() { return &buffer_; }
|
||||
|
||||
private:
|
||||
InternalMetadata* metadata_;
|
||||
std::string buffer_;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_METADATA_LITE_H__
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user