mirror of
https://github.com/google/sentencepiece.git
synced 2024-09-11 10:55:42 +03:00
use builtin protobuf-lite package in third_party
This commit is contained in:
parent
092a728975
commit
7b19d68be0
3
.gitignore
vendored
3
.gitignore
vendored
@ -53,9 +53,6 @@ spm_train
|
||||
spm_normalize
|
||||
spm_test
|
||||
|
||||
*.pb.cc
|
||||
*.pb.h
|
||||
|
||||
.DS_Store
|
||||
*.egg-info/
|
||||
dist/
|
||||
|
@ -25,6 +25,7 @@ option(SPM_ENABLE_TENSORFLOW_SHARED "Makes a tensorflow compatible shared file."
|
||||
option(SPM_ENABLE_TCMALLOC "Enable TCMalloc if available." ON)
|
||||
option(SPM_TCMALLOC_STATIC "Link static library of TCMALLOC." OFF)
|
||||
option(SPM_NO_THREADLOCAL "Disable thread_local operator" OFF)
|
||||
option(SPM_USE_BUILTIN_PROTOBUF "Use built-in protobuf" ON)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
@ -35,13 +36,19 @@ set(libdir "\${exec_prefix}/lib")
|
||||
set(includedir "\${prefix}/include")
|
||||
set(GNUCXX_STD_SUPPORT_VERSION "4.3")
|
||||
|
||||
if(MSVC)
|
||||
if (SPM_USE_BUILTIN_PROTOBUF)
|
||||
set(libprotobuf_lite "")
|
||||
else()
|
||||
set(libprotobuf_lite "-lprotobuf-lite")
|
||||
endif()
|
||||
|
||||
if (MSVC)
|
||||
string(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG})
|
||||
string(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_MINSIZEREL ${CMAKE_CXX_FLAGS_MINSIZEREL})
|
||||
string(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE})
|
||||
string(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_RELWITHDEBINFO ${CMAKE_CXX_FLAGS_RELWITHDEBINFO})
|
||||
add_definitions("/wd4267 /wd4244 /wd4305 /Zc:strictStrings /utf-8")
|
||||
endif(MSVC)
|
||||
endif()
|
||||
|
||||
if (APPLE)
|
||||
set(CMAKE_MACOSX_RPATH ON)
|
||||
|
45
data/extract_headers.pl
Executable file
45
data/extract_headers.pl
Executable file
@ -0,0 +1,45 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
# Copyright 2018 Google Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# Extract header files required for build protobuf-lite
|
||||
#
|
||||
# usage: ./extract_headers.pl *.cc
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
sub Process() {
|
||||
my $file = shift @_;
|
||||
if ($file =~ /\.h$/) {
|
||||
print "$file\n";
|
||||
}
|
||||
return unless open(F, $file);
|
||||
my @files = ();
|
||||
while (<F>) {
|
||||
chomp;
|
||||
if (/\#include <(google\/protobuf\/[^>]+)>/) {
|
||||
push @files, $1;
|
||||
}
|
||||
}
|
||||
close(F);
|
||||
for my $file (@files) {
|
||||
&Process($file);
|
||||
}
|
||||
}
|
||||
|
||||
for my $f (@ARGV) {
|
||||
&Process($f);
|
||||
}
|
173
data/gen_spec_parser.pl
Executable file
173
data/gen_spec_parser.pl
Executable file
@ -0,0 +1,173 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
# Copyright 2018 Google Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# Generate spec_parser.h from sentencepiece_model.proto
|
||||
#
|
||||
# usage: ./gen_spec_parser.pl sentencepiece_model.proto > spec_parser.h
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
sub ProcessPrinter() {
|
||||
my ($filename) = @_;
|
||||
my $classname = "";
|
||||
my $valid = 0;
|
||||
my %enum;
|
||||
open(F, $filename) || die;
|
||||
print "namespace {\n";
|
||||
while (<F>) {
|
||||
chomp;
|
||||
if (/^\s*message (\S+)/) {
|
||||
$classname = $1;
|
||||
$valid = 0;
|
||||
if ($classname =~ /(TrainerSpec|NormalizerSpec)/) {
|
||||
print "inline std::string PrintProto(const $classname &message) {\n";
|
||||
print " std::ostringstream os;\n\n";
|
||||
print " os << \"$classname {\\n\";\n";
|
||||
$valid = 1;
|
||||
}
|
||||
} elsif (/^\s*}/) {
|
||||
next if (!$valid);
|
||||
print " os << \"}\\n\";\n";
|
||||
print "\n return os.str();\n";
|
||||
print "}\n\n";
|
||||
} elsif (/enum\s*(\S+)/) {
|
||||
my $name = $1;
|
||||
$enum{$name} = 1;
|
||||
next if (!$valid);
|
||||
print " static const std::map<$classname::$name, std::string> k${name}_Map = { ";
|
||||
while (<F>) {
|
||||
if (/(\S+)\s*=\s*(\d+)/) {
|
||||
print "{$classname::$1, \"$1\"}, ";
|
||||
} elsif (/}/) {
|
||||
print " };\n";
|
||||
last;
|
||||
}
|
||||
}
|
||||
} elsif (/\s*(repeated|optional)\s+(\S+)\s+(\S+)\s*=\s*(\d+)/) {
|
||||
next if (!$valid);
|
||||
my $opt = $1;
|
||||
my $type = $2;
|
||||
my $name = $3;
|
||||
if ($type =~ /(int|double|float|bool|string)/) {
|
||||
if ($opt eq "optional") {
|
||||
print " os << \" ${name}: \" << message.${name}() << \"\\n\";\n";
|
||||
} else {
|
||||
print " for (const auto &v : message.${name}())\n";
|
||||
print " os << \" ${name}: \" << v << \"\\n\";\n";
|
||||
}
|
||||
} elsif (defined $enum{$type}) {
|
||||
if ($opt eq "optional") {
|
||||
print " {\n";
|
||||
print " const auto it = k${type}_Map.find(message.${name}());\n";
|
||||
print " if (it == k${type}_Map.end())\n";
|
||||
print " os << \" ${name}: unknown\\n\";\n";
|
||||
print " else\n";
|
||||
print " os << \" ${name}: \" << it->second << \"\\n\";\n";
|
||||
print " }\n";
|
||||
} else {
|
||||
print " for (const auto &v : message.${name}()) {\n";
|
||||
print " const auto it = k${type}_Map.find(v);\n";
|
||||
print " if (it == k${type}_Map.end())\n";
|
||||
print " os << \" ${name}: unknown\\n\";\n";
|
||||
print " else\n";
|
||||
print " os << \" ${name}: \" << it->second << \"\\n\";\n";
|
||||
print " }\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
print "} // namespace\n\n";
|
||||
close(F);
|
||||
}
|
||||
|
||||
sub ProcessParser() {
|
||||
my ($filename) = @_;
|
||||
my $classname = "";
|
||||
my $valid = 0;
|
||||
my %enum;
|
||||
open(F, $filename) || die;
|
||||
while (<F>) {
|
||||
if (/^\s*message (\S+)/) {
|
||||
$classname = $1;
|
||||
$valid = 0;
|
||||
if ($classname =~ /(TrainerSpec|NormalizerSpec)/) {
|
||||
print "util::Status SentencePieceTrainer::SetProtoField(const std::string& name, const std::string& value, $classname *message) {\n";
|
||||
print " CHECK_OR_RETURN(message);\n\n";
|
||||
$valid = 1;
|
||||
}
|
||||
} elsif (/^\s*}/) {
|
||||
next if (!$valid);
|
||||
print " return util::StatusBuilder(util::error::NOT_FOUND)\n";
|
||||
print " << \"unknown field name \\\"\" << name << \"\\\" in ${classname}.\";\n";
|
||||
print "}\n\n";
|
||||
} elsif (/enum\s*(\S+)/) {
|
||||
my $name = $1;
|
||||
$enum{$name} = 1;
|
||||
next if (!$valid);
|
||||
print " static const std::map <std::string, $classname::$name> k${name}_Map = { ";
|
||||
while (<F>) {
|
||||
if (/(\S+)\s*=\s*(\d+)/) {
|
||||
print "{\"$1\", $classname::$1}, ";
|
||||
} elsif (/}/) {
|
||||
print " };\n\n";
|
||||
last;
|
||||
}
|
||||
}
|
||||
} elsif (/\s*(repeated|optional)\s+(\S+)\s+(\S+)\s*=\s*(\d+)/) {
|
||||
next if (!$valid);
|
||||
my $opt = $1;
|
||||
my $type = $2;
|
||||
my $name = $3;
|
||||
my $func_prefix = $opt eq "optional" ? "set_" : "add_";
|
||||
my $body = "";
|
||||
if ($type =~ /(int|double|float|bool)/) {
|
||||
my $empty = $type eq "bool" ? "\"true\"" : "\"\"";
|
||||
$body =
|
||||
"${type} v;\n" .
|
||||
" if (!string_util::lexical_cast(val.empty() ? ${empty} : val, &v))\n" .
|
||||
" return util::StatusBuilder(util::error::INVALID_ARGUMENT) << \"cannot parse \\\"\" << val << \"\\\" as ${type}.\";\n" .
|
||||
" message->${func_prefix}${name}(v);\n";
|
||||
} elsif ($type =~ /string/) {
|
||||
$body = "message->${func_prefix}${name}(val);\n";
|
||||
} elsif ($type =~ /bytes/) {
|
||||
$body = "message->${func_prefix}${name}(val.data(), val.size());\n";
|
||||
} elsif (defined $enum{$type}) {
|
||||
$body = "const auto it = k${type}_Map.find(string_util::ToUpper(val));\n" .
|
||||
" if (it == k${type}_Map.end())\n" .
|
||||
" return util::StatusBuilder(util::error::INVALID_ARGUMENT) << \"unknown enumeration value of \\\"\" << val << \"\\\" as ${type}.\";\n" .
|
||||
" message->${func_prefix}${name}(it->second);\n";
|
||||
}
|
||||
print " if (name == \"${name}\") {\n";
|
||||
if ($opt eq "repeated") {
|
||||
print " for (const auto &val : string_util::Split(value, \",\")) {\n";
|
||||
print " ${body}";
|
||||
print " }\n";
|
||||
} else {
|
||||
print " const auto &val = value;\n";
|
||||
print " ${body}";
|
||||
}
|
||||
print " return util::OkStatus();\n";
|
||||
print " }\n\n";
|
||||
}
|
||||
}
|
||||
close(F);
|
||||
}
|
||||
|
||||
for my $file (@ARGV) {
|
||||
&ProcessPrinter($file);
|
||||
&ProcessParser($file);
|
||||
}
|
@ -15,7 +15,6 @@
|
||||
set -e # exit immediately on error
|
||||
set -x # display all commands
|
||||
|
||||
PROTOBUF_VERSION=3.6.1
|
||||
CMAKE_VERSION=3.12.0
|
||||
|
||||
run_docker() {
|
||||
@ -43,16 +42,6 @@ build() {
|
||||
make install
|
||||
cd ..
|
||||
|
||||
# Install protobuf
|
||||
curl -L -O https://github.com/google/protobuf/releases/download/v${PROTOBUF_VERSION}/protobuf-cpp-${PROTOBUF_VERSION}.tar.gz
|
||||
tar zxfv protobuf-cpp-${PROTOBUF_VERSION}.tar.gz
|
||||
cd protobuf-${PROTOBUF_VERSION}
|
||||
cp -f ../../once.h src/google/protobuf/stubs/once.h
|
||||
./configure --disable-shared --with-pic
|
||||
make CXXFLAGS+="-std=c++11 -O3" CFLAGS+="-std=c++11 -O3" -j4
|
||||
make install || true
|
||||
cd ..
|
||||
|
||||
# Install sentencepiece
|
||||
cmake ../.. -DSPM_ENABLE_SHARED=OFF
|
||||
make -j4
|
||||
|
@ -16,8 +16,6 @@
|
||||
set -e # exit immediately on error
|
||||
set -x # display all commands
|
||||
|
||||
PROTOBUF_VERSION=3.6.1
|
||||
|
||||
build_python() {
|
||||
VERSION=$1
|
||||
URL=$2
|
||||
@ -61,16 +59,6 @@ build() {
|
||||
mkdir -p build
|
||||
cd build
|
||||
|
||||
# Install protobuf
|
||||
curl -L -O https://github.com/google/protobuf/releases/download/v${PROTOBUF_VERSION}/protobuf-cpp-${PROTOBUF_VERSION}.tar.gz
|
||||
tar zxfv protobuf-cpp-${PROTOBUF_VERSION}.tar.gz
|
||||
cd protobuf-${PROTOBUF_VERSION}
|
||||
./configure --disable-shared --with-pic
|
||||
make CXXFLAGS+="-std=c++11 -O3 -DGOOGLE_PROTOBUF_NO_THREADLOCAL=1" \
|
||||
CFLAGS+="-std=c++11 -O3 -DGOOGLE_PROTOBUF_NO_THREADLOCAL=1" -j4
|
||||
make install || true
|
||||
cd ..
|
||||
|
||||
# Install sentencepiece
|
||||
cmake ../.. -DSPM_ENABLE_SHARED=OFF -DSPM_NO_THREADLOCAL=ON
|
||||
make -j4 VERBOSE=1
|
||||
|
@ -53,8 +53,7 @@ def cflags():
|
||||
def libs():
|
||||
if sys.platform == 'win32':
|
||||
return ['..\\build\\root\\lib\\sentencepiece.lib',
|
||||
'..\\build\\root\\lib\\sentencepiece_train.lib',
|
||||
'..\\build\\root\\lib\\libprotobuf.lib']
|
||||
'..\\build\\root\\lib\\sentencepiece_train.lib']
|
||||
|
||||
return cmd('pkg-config sentencepiece --libs')
|
||||
|
||||
|
@ -6,5 +6,5 @@ includedir=@includedir@
|
||||
Name: @PROJECT_NAME@
|
||||
Description: Unsupervised text tokenizer and detokenizer for Neural Network-based text generation.
|
||||
Version: @PROJECT_VERSION@
|
||||
Libs: -L${libdir} -lsentencepiece -lsentencepiece_train -lprotobuf @pkgconfiglibs@
|
||||
Libs: -L${libdir} -lsentencepiece -lsentencepiece_train @libprotobuf_lite@ @pkgconfiglibs@
|
||||
Cflags: -I${includedir} @pkgconfigcflags@
|
||||
|
@ -12,15 +12,56 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.!
|
||||
|
||||
find_package(Protobuf REQUIRED)
|
||||
include_directories(${Protobuf_INCLUDE_DIRS})
|
||||
protobuf_generate_cpp(SPM_PROTO_SRCS SPM_PROTO_HDRS sentencepiece.proto)
|
||||
protobuf_generate_cpp(SPM_MODEL_PROTO_SRCS SPM_MODEL_PROTO_HDRS sentencepiece_model.proto)
|
||||
if (SPM_USE_BUILTIN_PROTOBUF)
|
||||
set(SPM_PROTO_HDRS builtin_pb/sentencepiece.pb.h)
|
||||
set(SPM_PROTO_SRCS builtin_pb/sentencepiece.pb.cc)
|
||||
set(SPM_MODEL_PROTO_HDRS builtin_pb/sentencepiece_model.pb.h)
|
||||
set(SPM_MODEL_PROTO_SRCS builtin_pb/sentencepiece_model.pb.cc)
|
||||
set(PROTOBUF_LITE_LIBRARY "")
|
||||
set(PROTOBUF_LITE_SRCS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../third_party/protobuf-lite/arena.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../third_party/protobuf-lite/arenastring.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../third_party/protobuf-lite/bytestream.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../third_party/protobuf-lite/coded_stream.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../third_party/protobuf-lite/common.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../third_party/protobuf-lite/extension_set.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../third_party/protobuf-lite/generated_message_table_driven_lite.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../third_party/protobuf-lite/generated_message_util.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../third_party/protobuf-lite/implicit_weak_message.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../third_party/protobuf-lite/int128.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../third_party/protobuf-lite/io_win32.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../third_party/protobuf-lite/message_lite.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../third_party/protobuf-lite/repeated_field.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../third_party/protobuf-lite/status.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../third_party/protobuf-lite/statusor.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../third_party/protobuf-lite/stringpiece.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../third_party/protobuf-lite/stringprintf.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../third_party/protobuf-lite/structurally_valid.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../third_party/protobuf-lite/strutil.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../third_party/protobuf-lite/time.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../third_party/protobuf-lite/wire_format_lite.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../third_party/protobuf-lite/zero_copy_stream.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../third_party/protobuf-lite/zero_copy_stream_impl_lite.cc)
|
||||
if (MSVC)
|
||||
add_definitions("/DHAVE_PTHREAD /wd4018 /wd4514")
|
||||
else()
|
||||
add_definitions("-pthread -DHAVE_PTHREAD=1 -Wno-sign-compare")
|
||||
endif()
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../third_party/protobuf-lite)
|
||||
include_directories(builtin_pb)
|
||||
else()
|
||||
find_package(Protobuf REQUIRED)
|
||||
include_directories(${Protobuf_INCLUDE_DIRS})
|
||||
protobuf_generate_cpp(SPM_PROTO_SRCS SPM_PROTO_HDRS sentencepiece.proto)
|
||||
protobuf_generate_cpp(SPM_MODEL_PROTO_SRCS SPM_MODEL_PROTO_HDRS sentencepiece_model.proto)
|
||||
set(PROTOBUF_LITE_SRCS "")
|
||||
include_directories(${PROTOBUF_INCLUDE_DIR})
|
||||
endif()
|
||||
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||
include_directories(${PROTOBUF_INCLUDE_DIR})
|
||||
|
||||
set(SPM_SRCS
|
||||
${PROTOBUF_LITE_SRCS}
|
||||
${SPM_PROTO_HDRS}
|
||||
${SPM_PROTO_SRCS}
|
||||
${SPM_MODEL_PROTO_HDRS}
|
||||
@ -106,7 +147,7 @@ set(SPM_TEST_SRCS
|
||||
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
set(SPM_LIBS ${PROTOBUF_LIBRARY} Threads::Threads)
|
||||
set(SPM_LIBS ${PROTOBUF_LITE_LIBRARY} Threads::Threads)
|
||||
|
||||
if (SPM_ENABLE_NFKC_COMPILE)
|
||||
find_package(ICU 4.4 COMPONENTS i18n data uc REQUIRED)
|
||||
@ -175,6 +216,7 @@ if (NOT MSVC)
|
||||
endif()
|
||||
if (SPM_NO_THREADLOCAL)
|
||||
add_definitions(-DSPM_NO_THREADLOCAL=1)
|
||||
add_definitions(-DGOOGLE_PROTOBUF_NO_THREADLOCAL=1)
|
||||
endif()
|
||||
set_source_files_properties(
|
||||
sentencepiece.pb.cc sentencepiece_model.pb.cc
|
||||
|
@ -173,8 +173,6 @@ void Trainer::UpdateActiveSymbols() {
|
||||
util::Status Trainer::Train() {
|
||||
RETURN_IF_ERROR(status());
|
||||
|
||||
LOG(INFO) << "Starts training with : \n" << trainer_spec_.Utf8DebugString();
|
||||
|
||||
CHECK_OR_RETURN(normalizer_spec_.escape_whitespaces());
|
||||
CHECK_EQ_OR_RETURN(TrainerSpec::BPE, trainer_spec_.model_type());
|
||||
|
||||
|
953
src/builtin_pb/sentencepiece.pb.cc
Normal file
953
src/builtin_pb/sentencepiece.pb.cc
Normal file
@ -0,0 +1,953 @@
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: sentencepiece.proto
|
||||
|
||||
#include "sentencepiece.pb.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/port.h>
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/wire_format_lite_inl.h>
|
||||
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
|
||||
// This is a temporary google only hack
|
||||
#ifdef GOOGLE_PROTOBUF_ENFORCE_UNIQUENESS
|
||||
#include "third_party/protobuf/version.h"
|
||||
#endif
|
||||
// @@protoc_insertion_point(includes)
|
||||
|
||||
namespace protobuf_sentencepiece_2eproto {
|
||||
extern PROTOBUF_INTERNAL_EXPORT_protobuf_sentencepiece_2eproto ::google::protobuf::internal::SCCInfo<0> scc_info_SentencePieceText_SentencePiece;
|
||||
extern PROTOBUF_INTERNAL_EXPORT_protobuf_sentencepiece_2eproto ::google::protobuf::internal::SCCInfo<1> scc_info_SentencePieceText;
|
||||
} // namespace protobuf_sentencepiece_2eproto
|
||||
namespace sentencepiece {
|
||||
class SentencePieceText_SentencePieceDefaultTypeInternal {
|
||||
public:
|
||||
::google::protobuf::internal::ExplicitlyConstructed<SentencePieceText_SentencePiece>
|
||||
_instance;
|
||||
} _SentencePieceText_SentencePiece_default_instance_;
|
||||
class SentencePieceTextDefaultTypeInternal {
|
||||
public:
|
||||
::google::protobuf::internal::ExplicitlyConstructed<SentencePieceText>
|
||||
_instance;
|
||||
} _SentencePieceText_default_instance_;
|
||||
class NBestSentencePieceTextDefaultTypeInternal {
|
||||
public:
|
||||
::google::protobuf::internal::ExplicitlyConstructed<NBestSentencePieceText>
|
||||
_instance;
|
||||
} _NBestSentencePieceText_default_instance_;
|
||||
} // namespace sentencepiece
|
||||
namespace protobuf_sentencepiece_2eproto {
|
||||
static void InitDefaultsSentencePieceText_SentencePiece() {
|
||||
GOOGLE_PROTOBUF_VERIFY_VERSION;
|
||||
|
||||
{
|
||||
void* ptr = &::sentencepiece::_SentencePieceText_SentencePiece_default_instance_;
|
||||
new (ptr) ::sentencepiece::SentencePieceText_SentencePiece();
|
||||
::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
|
||||
}
|
||||
::sentencepiece::SentencePieceText_SentencePiece::InitAsDefaultInstance();
|
||||
}
|
||||
|
||||
::google::protobuf::internal::SCCInfo<0> scc_info_SentencePieceText_SentencePiece =
|
||||
{{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 0, InitDefaultsSentencePieceText_SentencePiece}, {}};
|
||||
|
||||
static void InitDefaultsSentencePieceText() {
|
||||
GOOGLE_PROTOBUF_VERIFY_VERSION;
|
||||
|
||||
{
|
||||
void* ptr = &::sentencepiece::_SentencePieceText_default_instance_;
|
||||
new (ptr) ::sentencepiece::SentencePieceText();
|
||||
::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
|
||||
}
|
||||
::sentencepiece::SentencePieceText::InitAsDefaultInstance();
|
||||
}
|
||||
|
||||
::google::protobuf::internal::SCCInfo<1> scc_info_SentencePieceText =
|
||||
{{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 1, InitDefaultsSentencePieceText}, {
|
||||
&protobuf_sentencepiece_2eproto::scc_info_SentencePieceText_SentencePiece.base,}};
|
||||
|
||||
static void InitDefaultsNBestSentencePieceText() {
|
||||
GOOGLE_PROTOBUF_VERIFY_VERSION;
|
||||
|
||||
{
|
||||
void* ptr = &::sentencepiece::_NBestSentencePieceText_default_instance_;
|
||||
new (ptr) ::sentencepiece::NBestSentencePieceText();
|
||||
::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
|
||||
}
|
||||
::sentencepiece::NBestSentencePieceText::InitAsDefaultInstance();
|
||||
}
|
||||
|
||||
::google::protobuf::internal::SCCInfo<1> scc_info_NBestSentencePieceText =
|
||||
{{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 1, InitDefaultsNBestSentencePieceText}, {
|
||||
&protobuf_sentencepiece_2eproto::scc_info_SentencePieceText.base,}};
|
||||
|
||||
void InitDefaults() {
|
||||
::google::protobuf::internal::InitSCC(&scc_info_SentencePieceText_SentencePiece.base);
|
||||
::google::protobuf::internal::InitSCC(&scc_info_SentencePieceText.base);
|
||||
::google::protobuf::internal::InitSCC(&scc_info_NBestSentencePieceText.base);
|
||||
}
|
||||
|
||||
} // namespace protobuf_sentencepiece_2eproto
|
||||
namespace sentencepiece {
|
||||
|
||||
// ===================================================================
|
||||
|
||||
void SentencePieceText_SentencePiece::InitAsDefaultInstance() {
|
||||
}
|
||||
#if !defined(_MSC_VER) || _MSC_VER >= 1900
|
||||
const int SentencePieceText_SentencePiece::kPieceFieldNumber;
|
||||
const int SentencePieceText_SentencePiece::kIdFieldNumber;
|
||||
const int SentencePieceText_SentencePiece::kSurfaceFieldNumber;
|
||||
const int SentencePieceText_SentencePiece::kBeginFieldNumber;
|
||||
const int SentencePieceText_SentencePiece::kEndFieldNumber;
|
||||
#endif // !defined(_MSC_VER) || _MSC_VER >= 1900
|
||||
|
||||
SentencePieceText_SentencePiece::SentencePieceText_SentencePiece()
|
||||
: ::google::protobuf::MessageLite(), _internal_metadata_(NULL) {
|
||||
::google::protobuf::internal::InitSCC(
|
||||
&protobuf_sentencepiece_2eproto::scc_info_SentencePieceText_SentencePiece.base);
|
||||
SharedCtor();
|
||||
// @@protoc_insertion_point(constructor:sentencepiece.SentencePieceText.SentencePiece)
|
||||
}
|
||||
SentencePieceText_SentencePiece::SentencePieceText_SentencePiece(const SentencePieceText_SentencePiece& from)
|
||||
: ::google::protobuf::MessageLite(),
|
||||
_internal_metadata_(NULL),
|
||||
_has_bits_(from._has_bits_) {
|
||||
_internal_metadata_.MergeFrom(from._internal_metadata_);
|
||||
_extensions_.MergeFrom(from._extensions_);
|
||||
piece_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
if (from.has_piece()) {
|
||||
piece_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.piece_);
|
||||
}
|
||||
surface_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
if (from.has_surface()) {
|
||||
surface_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.surface_);
|
||||
}
|
||||
::memcpy(&id_, &from.id_,
|
||||
static_cast<size_t>(reinterpret_cast<char*>(&end_) -
|
||||
reinterpret_cast<char*>(&id_)) + sizeof(end_));
|
||||
// @@protoc_insertion_point(copy_constructor:sentencepiece.SentencePieceText.SentencePiece)
|
||||
}
|
||||
|
||||
void SentencePieceText_SentencePiece::SharedCtor() {
|
||||
piece_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
surface_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
::memset(&id_, 0, static_cast<size_t>(
|
||||
reinterpret_cast<char*>(&end_) -
|
||||
reinterpret_cast<char*>(&id_)) + sizeof(end_));
|
||||
}
|
||||
|
||||
SentencePieceText_SentencePiece::~SentencePieceText_SentencePiece() {
|
||||
// @@protoc_insertion_point(destructor:sentencepiece.SentencePieceText.SentencePiece)
|
||||
SharedDtor();
|
||||
}
|
||||
|
||||
void SentencePieceText_SentencePiece::SharedDtor() {
|
||||
piece_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
surface_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
|
||||
void SentencePieceText_SentencePiece::SetCachedSize(int size) const {
|
||||
_cached_size_.Set(size);
|
||||
}
|
||||
const SentencePieceText_SentencePiece& SentencePieceText_SentencePiece::default_instance() {
|
||||
::google::protobuf::internal::InitSCC(&protobuf_sentencepiece_2eproto::scc_info_SentencePieceText_SentencePiece.base);
|
||||
return *internal_default_instance();
|
||||
}
|
||||
|
||||
|
||||
void SentencePieceText_SentencePiece::Clear() {
|
||||
// @@protoc_insertion_point(message_clear_start:sentencepiece.SentencePieceText.SentencePiece)
|
||||
::google::protobuf::uint32 cached_has_bits = 0;
|
||||
// Prevent compiler warnings about cached_has_bits being unused
|
||||
(void) cached_has_bits;
|
||||
|
||||
_extensions_.Clear();
|
||||
cached_has_bits = _has_bits_[0];
|
||||
if (cached_has_bits & 3u) {
|
||||
if (cached_has_bits & 0x00000001u) {
|
||||
piece_.ClearNonDefaultToEmptyNoArena();
|
||||
}
|
||||
if (cached_has_bits & 0x00000002u) {
|
||||
surface_.ClearNonDefaultToEmptyNoArena();
|
||||
}
|
||||
}
|
||||
if (cached_has_bits & 28u) {
|
||||
::memset(&id_, 0, static_cast<size_t>(
|
||||
reinterpret_cast<char*>(&end_) -
|
||||
reinterpret_cast<char*>(&id_)) + sizeof(end_));
|
||||
}
|
||||
_has_bits_.Clear();
|
||||
_internal_metadata_.Clear();
|
||||
}
|
||||
|
||||
bool SentencePieceText_SentencePiece::MergePartialFromCodedStream(
|
||||
::google::protobuf::io::CodedInputStream* input) {
|
||||
#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
|
||||
::google::protobuf::uint32 tag;
|
||||
::google::protobuf::internal::LiteUnknownFieldSetter unknown_fields_setter(
|
||||
&_internal_metadata_);
|
||||
::google::protobuf::io::StringOutputStream unknown_fields_output(
|
||||
unknown_fields_setter.buffer());
|
||||
::google::protobuf::io::CodedOutputStream unknown_fields_stream(
|
||||
&unknown_fields_output, false);
|
||||
// @@protoc_insertion_point(parse_start:sentencepiece.SentencePieceText.SentencePiece)
|
||||
for (;;) {
|
||||
::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
|
||||
tag = p.first;
|
||||
if (!p.second) goto handle_unusual;
|
||||
switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
|
||||
// optional string piece = 1;
|
||||
case 1: {
|
||||
if (static_cast< ::google::protobuf::uint8>(tag) ==
|
||||
static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) {
|
||||
DO_(::google::protobuf::internal::WireFormatLite::ReadString(
|
||||
input, this->mutable_piece()));
|
||||
} else {
|
||||
goto handle_unusual;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// optional uint32 id = 2;
|
||||
case 2: {
|
||||
if (static_cast< ::google::protobuf::uint8>(tag) ==
|
||||
static_cast< ::google::protobuf::uint8>(16u /* 16 & 0xFF */)) {
|
||||
set_has_id();
|
||||
DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
|
||||
::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>(
|
||||
input, &id_)));
|
||||
} else {
|
||||
goto handle_unusual;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// optional string surface = 3;
|
||||
case 3: {
|
||||
if (static_cast< ::google::protobuf::uint8>(tag) ==
|
||||
static_cast< ::google::protobuf::uint8>(26u /* 26 & 0xFF */)) {
|
||||
DO_(::google::protobuf::internal::WireFormatLite::ReadString(
|
||||
input, this->mutable_surface()));
|
||||
} else {
|
||||
goto handle_unusual;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// optional uint32 begin = 4;
|
||||
case 4: {
|
||||
if (static_cast< ::google::protobuf::uint8>(tag) ==
|
||||
static_cast< ::google::protobuf::uint8>(32u /* 32 & 0xFF */)) {
|
||||
set_has_begin();
|
||||
DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
|
||||
::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>(
|
||||
input, &begin_)));
|
||||
} else {
|
||||
goto handle_unusual;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// optional uint32 end = 5;
|
||||
case 5: {
|
||||
if (static_cast< ::google::protobuf::uint8>(tag) ==
|
||||
static_cast< ::google::protobuf::uint8>(40u /* 40 & 0xFF */)) {
|
||||
set_has_end();
|
||||
DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
|
||||
::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>(
|
||||
input, &end_)));
|
||||
} else {
|
||||
goto handle_unusual;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
handle_unusual:
|
||||
if (tag == 0) {
|
||||
goto success;
|
||||
}
|
||||
if ((1600u <= tag)) {
|
||||
DO_(_extensions_.ParseField(tag, input,
|
||||
internal_default_instance(),
|
||||
&unknown_fields_stream));
|
||||
continue;
|
||||
}
|
||||
DO_(::google::protobuf::internal::WireFormatLite::SkipField(
|
||||
input, tag, &unknown_fields_stream));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
success:
|
||||
// @@protoc_insertion_point(parse_success:sentencepiece.SentencePieceText.SentencePiece)
|
||||
return true;
|
||||
failure:
|
||||
// @@protoc_insertion_point(parse_failure:sentencepiece.SentencePieceText.SentencePiece)
|
||||
return false;
|
||||
#undef DO_
|
||||
}
|
||||
|
||||
void SentencePieceText_SentencePiece::SerializeWithCachedSizes(
|
||||
::google::protobuf::io::CodedOutputStream* output) const {
|
||||
// @@protoc_insertion_point(serialize_start:sentencepiece.SentencePieceText.SentencePiece)
|
||||
::google::protobuf::uint32 cached_has_bits = 0;
|
||||
(void) cached_has_bits;
|
||||
|
||||
cached_has_bits = _has_bits_[0];
|
||||
// optional string piece = 1;
|
||||
if (cached_has_bits & 0x00000001u) {
|
||||
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
|
||||
1, this->piece(), output);
|
||||
}
|
||||
|
||||
// optional uint32 id = 2;
|
||||
if (cached_has_bits & 0x00000004u) {
|
||||
::google::protobuf::internal::WireFormatLite::WriteUInt32(2, this->id(), output);
|
||||
}
|
||||
|
||||
// optional string surface = 3;
|
||||
if (cached_has_bits & 0x00000002u) {
|
||||
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
|
||||
3, this->surface(), output);
|
||||
}
|
||||
|
||||
// optional uint32 begin = 4;
|
||||
if (cached_has_bits & 0x00000008u) {
|
||||
::google::protobuf::internal::WireFormatLite::WriteUInt32(4, this->begin(), output);
|
||||
}
|
||||
|
||||
// optional uint32 end = 5;
|
||||
if (cached_has_bits & 0x00000010u) {
|
||||
::google::protobuf::internal::WireFormatLite::WriteUInt32(5, this->end(), output);
|
||||
}
|
||||
|
||||
// Extension range [200, 536870912)
|
||||
_extensions_.SerializeWithCachedSizes(
|
||||
200, 536870912, output);
|
||||
|
||||
output->WriteRaw(_internal_metadata_.unknown_fields().data(),
|
||||
static_cast<int>(_internal_metadata_.unknown_fields().size()));
|
||||
// @@protoc_insertion_point(serialize_end:sentencepiece.SentencePieceText.SentencePiece)
|
||||
}
|
||||
|
||||
size_t SentencePieceText_SentencePiece::ByteSizeLong() const {
|
||||
// @@protoc_insertion_point(message_byte_size_start:sentencepiece.SentencePieceText.SentencePiece)
|
||||
size_t total_size = 0;
|
||||
|
||||
total_size += _extensions_.ByteSize();
|
||||
|
||||
total_size += _internal_metadata_.unknown_fields().size();
|
||||
|
||||
if (_has_bits_[0 / 32] & 31u) {
|
||||
// optional string piece = 1;
|
||||
if (has_piece()) {
|
||||
total_size += 1 +
|
||||
::google::protobuf::internal::WireFormatLite::StringSize(
|
||||
this->piece());
|
||||
}
|
||||
|
||||
// optional string surface = 3;
|
||||
if (has_surface()) {
|
||||
total_size += 1 +
|
||||
::google::protobuf::internal::WireFormatLite::StringSize(
|
||||
this->surface());
|
||||
}
|
||||
|
||||
// optional uint32 id = 2;
|
||||
if (has_id()) {
|
||||
total_size += 1 +
|
||||
::google::protobuf::internal::WireFormatLite::UInt32Size(
|
||||
this->id());
|
||||
}
|
||||
|
||||
// optional uint32 begin = 4;
|
||||
if (has_begin()) {
|
||||
total_size += 1 +
|
||||
::google::protobuf::internal::WireFormatLite::UInt32Size(
|
||||
this->begin());
|
||||
}
|
||||
|
||||
// optional uint32 end = 5;
|
||||
if (has_end()) {
|
||||
total_size += 1 +
|
||||
::google::protobuf::internal::WireFormatLite::UInt32Size(
|
||||
this->end());
|
||||
}
|
||||
|
||||
}
|
||||
int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
|
||||
SetCachedSize(cached_size);
|
||||
return total_size;
|
||||
}
|
||||
|
||||
void SentencePieceText_SentencePiece::CheckTypeAndMergeFrom(
|
||||
const ::google::protobuf::MessageLite& from) {
|
||||
MergeFrom(*::google::protobuf::down_cast<const SentencePieceText_SentencePiece*>(&from));
|
||||
}
|
||||
|
||||
void SentencePieceText_SentencePiece::MergeFrom(const SentencePieceText_SentencePiece& from) {
|
||||
// @@protoc_insertion_point(class_specific_merge_from_start:sentencepiece.SentencePieceText.SentencePiece)
|
||||
GOOGLE_DCHECK_NE(&from, this);
|
||||
_extensions_.MergeFrom(from._extensions_);
|
||||
_internal_metadata_.MergeFrom(from._internal_metadata_);
|
||||
::google::protobuf::uint32 cached_has_bits = 0;
|
||||
(void) cached_has_bits;
|
||||
|
||||
cached_has_bits = from._has_bits_[0];
|
||||
if (cached_has_bits & 31u) {
|
||||
if (cached_has_bits & 0x00000001u) {
|
||||
set_has_piece();
|
||||
piece_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.piece_);
|
||||
}
|
||||
if (cached_has_bits & 0x00000002u) {
|
||||
set_has_surface();
|
||||
surface_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.surface_);
|
||||
}
|
||||
if (cached_has_bits & 0x00000004u) {
|
||||
id_ = from.id_;
|
||||
}
|
||||
if (cached_has_bits & 0x00000008u) {
|
||||
begin_ = from.begin_;
|
||||
}
|
||||
if (cached_has_bits & 0x00000010u) {
|
||||
end_ = from.end_;
|
||||
}
|
||||
_has_bits_[0] |= cached_has_bits;
|
||||
}
|
||||
}
|
||||
|
||||
void SentencePieceText_SentencePiece::CopyFrom(const SentencePieceText_SentencePiece& from) {
|
||||
// @@protoc_insertion_point(class_specific_copy_from_start:sentencepiece.SentencePieceText.SentencePiece)
|
||||
if (&from == this) return;
|
||||
Clear();
|
||||
MergeFrom(from);
|
||||
}
|
||||
|
||||
bool SentencePieceText_SentencePiece::IsInitialized() const {
|
||||
if (!_extensions_.IsInitialized()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SentencePieceText_SentencePiece::Swap(SentencePieceText_SentencePiece* other) {
|
||||
if (other == this) return;
|
||||
InternalSwap(other);
|
||||
}
|
||||
void SentencePieceText_SentencePiece::InternalSwap(SentencePieceText_SentencePiece* other) {
|
||||
using std::swap;
|
||||
piece_.Swap(&other->piece_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
|
||||
GetArenaNoVirtual());
|
||||
surface_.Swap(&other->surface_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
|
||||
GetArenaNoVirtual());
|
||||
swap(id_, other->id_);
|
||||
swap(begin_, other->begin_);
|
||||
swap(end_, other->end_);
|
||||
swap(_has_bits_[0], other->_has_bits_[0]);
|
||||
_internal_metadata_.Swap(&other->_internal_metadata_);
|
||||
_extensions_.Swap(&other->_extensions_);
|
||||
}
|
||||
|
||||
::std::string SentencePieceText_SentencePiece::GetTypeName() const {
|
||||
return "sentencepiece.SentencePieceText.SentencePiece";
|
||||
}
|
||||
|
||||
|
||||
// ===================================================================
|
||||
|
||||
void SentencePieceText::InitAsDefaultInstance() {
|
||||
}
|
||||
#if !defined(_MSC_VER) || _MSC_VER >= 1900
|
||||
const int SentencePieceText::kTextFieldNumber;
|
||||
const int SentencePieceText::kPiecesFieldNumber;
|
||||
const int SentencePieceText::kScoreFieldNumber;
|
||||
#endif // !defined(_MSC_VER) || _MSC_VER >= 1900
|
||||
|
||||
SentencePieceText::SentencePieceText()
|
||||
: ::google::protobuf::MessageLite(), _internal_metadata_(NULL) {
|
||||
::google::protobuf::internal::InitSCC(
|
||||
&protobuf_sentencepiece_2eproto::scc_info_SentencePieceText.base);
|
||||
SharedCtor();
|
||||
// @@protoc_insertion_point(constructor:sentencepiece.SentencePieceText)
|
||||
}
|
||||
SentencePieceText::SentencePieceText(const SentencePieceText& from)
|
||||
: ::google::protobuf::MessageLite(),
|
||||
_internal_metadata_(NULL),
|
||||
_has_bits_(from._has_bits_),
|
||||
pieces_(from.pieces_) {
|
||||
_internal_metadata_.MergeFrom(from._internal_metadata_);
|
||||
_extensions_.MergeFrom(from._extensions_);
|
||||
text_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
if (from.has_text()) {
|
||||
text_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.text_);
|
||||
}
|
||||
score_ = from.score_;
|
||||
// @@protoc_insertion_point(copy_constructor:sentencepiece.SentencePieceText)
|
||||
}
|
||||
|
||||
void SentencePieceText::SharedCtor() {
|
||||
text_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
score_ = 0;
|
||||
}
|
||||
|
||||
SentencePieceText::~SentencePieceText() {
|
||||
// @@protoc_insertion_point(destructor:sentencepiece.SentencePieceText)
|
||||
SharedDtor();
|
||||
}
|
||||
|
||||
void SentencePieceText::SharedDtor() {
|
||||
text_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
|
||||
void SentencePieceText::SetCachedSize(int size) const {
|
||||
_cached_size_.Set(size);
|
||||
}
|
||||
const SentencePieceText& SentencePieceText::default_instance() {
|
||||
::google::protobuf::internal::InitSCC(&protobuf_sentencepiece_2eproto::scc_info_SentencePieceText.base);
|
||||
return *internal_default_instance();
|
||||
}
|
||||
|
||||
|
||||
void SentencePieceText::Clear() {
|
||||
// @@protoc_insertion_point(message_clear_start:sentencepiece.SentencePieceText)
|
||||
::google::protobuf::uint32 cached_has_bits = 0;
|
||||
// Prevent compiler warnings about cached_has_bits being unused
|
||||
(void) cached_has_bits;
|
||||
|
||||
_extensions_.Clear();
|
||||
pieces_.Clear();
|
||||
cached_has_bits = _has_bits_[0];
|
||||
if (cached_has_bits & 0x00000001u) {
|
||||
text_.ClearNonDefaultToEmptyNoArena();
|
||||
}
|
||||
score_ = 0;
|
||||
_has_bits_.Clear();
|
||||
_internal_metadata_.Clear();
|
||||
}
|
||||
|
||||
bool SentencePieceText::MergePartialFromCodedStream(
|
||||
::google::protobuf::io::CodedInputStream* input) {
|
||||
#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
|
||||
::google::protobuf::uint32 tag;
|
||||
::google::protobuf::internal::LiteUnknownFieldSetter unknown_fields_setter(
|
||||
&_internal_metadata_);
|
||||
::google::protobuf::io::StringOutputStream unknown_fields_output(
|
||||
unknown_fields_setter.buffer());
|
||||
::google::protobuf::io::CodedOutputStream unknown_fields_stream(
|
||||
&unknown_fields_output, false);
|
||||
// @@protoc_insertion_point(parse_start:sentencepiece.SentencePieceText)
|
||||
for (;;) {
|
||||
::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
|
||||
tag = p.first;
|
||||
if (!p.second) goto handle_unusual;
|
||||
switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
|
||||
// optional string text = 1;
|
||||
case 1: {
|
||||
if (static_cast< ::google::protobuf::uint8>(tag) ==
|
||||
static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) {
|
||||
DO_(::google::protobuf::internal::WireFormatLite::ReadString(
|
||||
input, this->mutable_text()));
|
||||
} else {
|
||||
goto handle_unusual;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// repeated .sentencepiece.SentencePieceText.SentencePiece pieces = 2;
|
||||
case 2: {
|
||||
if (static_cast< ::google::protobuf::uint8>(tag) ==
|
||||
static_cast< ::google::protobuf::uint8>(18u /* 18 & 0xFF */)) {
|
||||
DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
|
||||
input, add_pieces()));
|
||||
} else {
|
||||
goto handle_unusual;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// optional float score = 3;
|
||||
case 3: {
|
||||
if (static_cast< ::google::protobuf::uint8>(tag) ==
|
||||
static_cast< ::google::protobuf::uint8>(29u /* 29 & 0xFF */)) {
|
||||
set_has_score();
|
||||
DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
|
||||
float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>(
|
||||
input, &score_)));
|
||||
} else {
|
||||
goto handle_unusual;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
handle_unusual:
|
||||
if (tag == 0) {
|
||||
goto success;
|
||||
}
|
||||
if ((1600u <= tag)) {
|
||||
DO_(_extensions_.ParseField(tag, input,
|
||||
internal_default_instance(),
|
||||
&unknown_fields_stream));
|
||||
continue;
|
||||
}
|
||||
DO_(::google::protobuf::internal::WireFormatLite::SkipField(
|
||||
input, tag, &unknown_fields_stream));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
success:
|
||||
// @@protoc_insertion_point(parse_success:sentencepiece.SentencePieceText)
|
||||
return true;
|
||||
failure:
|
||||
// @@protoc_insertion_point(parse_failure:sentencepiece.SentencePieceText)
|
||||
return false;
|
||||
#undef DO_
|
||||
}
|
||||
|
||||
void SentencePieceText::SerializeWithCachedSizes(
|
||||
::google::protobuf::io::CodedOutputStream* output) const {
|
||||
// @@protoc_insertion_point(serialize_start:sentencepiece.SentencePieceText)
|
||||
::google::protobuf::uint32 cached_has_bits = 0;
|
||||
(void) cached_has_bits;
|
||||
|
||||
cached_has_bits = _has_bits_[0];
|
||||
// optional string text = 1;
|
||||
if (cached_has_bits & 0x00000001u) {
|
||||
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
|
||||
1, this->text(), output);
|
||||
}
|
||||
|
||||
// repeated .sentencepiece.SentencePieceText.SentencePiece pieces = 2;
|
||||
for (unsigned int i = 0,
|
||||
n = static_cast<unsigned int>(this->pieces_size()); i < n; i++) {
|
||||
::google::protobuf::internal::WireFormatLite::WriteMessage(
|
||||
2,
|
||||
this->pieces(static_cast<int>(i)),
|
||||
output);
|
||||
}
|
||||
|
||||
// optional float score = 3;
|
||||
if (cached_has_bits & 0x00000002u) {
|
||||
::google::protobuf::internal::WireFormatLite::WriteFloat(3, this->score(), output);
|
||||
}
|
||||
|
||||
// Extension range [200, 536870912)
|
||||
_extensions_.SerializeWithCachedSizes(
|
||||
200, 536870912, output);
|
||||
|
||||
output->WriteRaw(_internal_metadata_.unknown_fields().data(),
|
||||
static_cast<int>(_internal_metadata_.unknown_fields().size()));
|
||||
// @@protoc_insertion_point(serialize_end:sentencepiece.SentencePieceText)
|
||||
}
|
||||
|
||||
size_t SentencePieceText::ByteSizeLong() const {
|
||||
// @@protoc_insertion_point(message_byte_size_start:sentencepiece.SentencePieceText)
|
||||
size_t total_size = 0;
|
||||
|
||||
total_size += _extensions_.ByteSize();
|
||||
|
||||
total_size += _internal_metadata_.unknown_fields().size();
|
||||
|
||||
// repeated .sentencepiece.SentencePieceText.SentencePiece pieces = 2;
|
||||
{
|
||||
unsigned int count = static_cast<unsigned int>(this->pieces_size());
|
||||
total_size += 1UL * count;
|
||||
for (unsigned int i = 0; i < count; i++) {
|
||||
total_size +=
|
||||
::google::protobuf::internal::WireFormatLite::MessageSize(
|
||||
this->pieces(static_cast<int>(i)));
|
||||
}
|
||||
}
|
||||
|
||||
if (_has_bits_[0 / 32] & 3u) {
|
||||
// optional string text = 1;
|
||||
if (has_text()) {
|
||||
total_size += 1 +
|
||||
::google::protobuf::internal::WireFormatLite::StringSize(
|
||||
this->text());
|
||||
}
|
||||
|
||||
// optional float score = 3;
|
||||
if (has_score()) {
|
||||
total_size += 1 + 4;
|
||||
}
|
||||
|
||||
}
|
||||
int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
|
||||
SetCachedSize(cached_size);
|
||||
return total_size;
|
||||
}
|
||||
|
||||
void SentencePieceText::CheckTypeAndMergeFrom(
|
||||
const ::google::protobuf::MessageLite& from) {
|
||||
MergeFrom(*::google::protobuf::down_cast<const SentencePieceText*>(&from));
|
||||
}
|
||||
|
||||
void SentencePieceText::MergeFrom(const SentencePieceText& from) {
|
||||
// @@protoc_insertion_point(class_specific_merge_from_start:sentencepiece.SentencePieceText)
|
||||
GOOGLE_DCHECK_NE(&from, this);
|
||||
_extensions_.MergeFrom(from._extensions_);
|
||||
_internal_metadata_.MergeFrom(from._internal_metadata_);
|
||||
::google::protobuf::uint32 cached_has_bits = 0;
|
||||
(void) cached_has_bits;
|
||||
|
||||
pieces_.MergeFrom(from.pieces_);
|
||||
cached_has_bits = from._has_bits_[0];
|
||||
if (cached_has_bits & 3u) {
|
||||
if (cached_has_bits & 0x00000001u) {
|
||||
set_has_text();
|
||||
text_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.text_);
|
||||
}
|
||||
if (cached_has_bits & 0x00000002u) {
|
||||
score_ = from.score_;
|
||||
}
|
||||
_has_bits_[0] |= cached_has_bits;
|
||||
}
|
||||
}
|
||||
|
||||
void SentencePieceText::CopyFrom(const SentencePieceText& from) {
|
||||
// @@protoc_insertion_point(class_specific_copy_from_start:sentencepiece.SentencePieceText)
|
||||
if (&from == this) return;
|
||||
Clear();
|
||||
MergeFrom(from);
|
||||
}
|
||||
|
||||
bool SentencePieceText::IsInitialized() const {
|
||||
if (!_extensions_.IsInitialized()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!::google::protobuf::internal::AllAreInitialized(this->pieces())) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void SentencePieceText::Swap(SentencePieceText* other) {
|
||||
if (other == this) return;
|
||||
InternalSwap(other);
|
||||
}
|
||||
void SentencePieceText::InternalSwap(SentencePieceText* other) {
|
||||
using std::swap;
|
||||
CastToBase(&pieces_)->InternalSwap(CastToBase(&other->pieces_));
|
||||
text_.Swap(&other->text_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
|
||||
GetArenaNoVirtual());
|
||||
swap(score_, other->score_);
|
||||
swap(_has_bits_[0], other->_has_bits_[0]);
|
||||
_internal_metadata_.Swap(&other->_internal_metadata_);
|
||||
_extensions_.Swap(&other->_extensions_);
|
||||
}
|
||||
|
||||
::std::string SentencePieceText::GetTypeName() const {
|
||||
return "sentencepiece.SentencePieceText";
|
||||
}
|
||||
|
||||
|
||||
// ===================================================================
|
||||
|
||||
void NBestSentencePieceText::InitAsDefaultInstance() {
|
||||
}
|
||||
#if !defined(_MSC_VER) || _MSC_VER >= 1900
|
||||
const int NBestSentencePieceText::kNbestsFieldNumber;
|
||||
#endif // !defined(_MSC_VER) || _MSC_VER >= 1900
|
||||
|
||||
NBestSentencePieceText::NBestSentencePieceText()
|
||||
: ::google::protobuf::MessageLite(), _internal_metadata_(NULL) {
|
||||
::google::protobuf::internal::InitSCC(
|
||||
&protobuf_sentencepiece_2eproto::scc_info_NBestSentencePieceText.base);
|
||||
SharedCtor();
|
||||
// @@protoc_insertion_point(constructor:sentencepiece.NBestSentencePieceText)
|
||||
}
|
||||
NBestSentencePieceText::NBestSentencePieceText(const NBestSentencePieceText& from)
|
||||
: ::google::protobuf::MessageLite(),
|
||||
_internal_metadata_(NULL),
|
||||
_has_bits_(from._has_bits_),
|
||||
nbests_(from.nbests_) {
|
||||
_internal_metadata_.MergeFrom(from._internal_metadata_);
|
||||
// @@protoc_insertion_point(copy_constructor:sentencepiece.NBestSentencePieceText)
|
||||
}
|
||||
|
||||
void NBestSentencePieceText::SharedCtor() {
|
||||
}
|
||||
|
||||
NBestSentencePieceText::~NBestSentencePieceText() {
|
||||
// @@protoc_insertion_point(destructor:sentencepiece.NBestSentencePieceText)
|
||||
SharedDtor();
|
||||
}
|
||||
|
||||
void NBestSentencePieceText::SharedDtor() {
|
||||
}
|
||||
|
||||
void NBestSentencePieceText::SetCachedSize(int size) const {
|
||||
_cached_size_.Set(size);
|
||||
}
|
||||
const NBestSentencePieceText& NBestSentencePieceText::default_instance() {
|
||||
::google::protobuf::internal::InitSCC(&protobuf_sentencepiece_2eproto::scc_info_NBestSentencePieceText.base);
|
||||
return *internal_default_instance();
|
||||
}
|
||||
|
||||
|
||||
void NBestSentencePieceText::Clear() {
|
||||
// @@protoc_insertion_point(message_clear_start:sentencepiece.NBestSentencePieceText)
|
||||
::google::protobuf::uint32 cached_has_bits = 0;
|
||||
// Prevent compiler warnings about cached_has_bits being unused
|
||||
(void) cached_has_bits;
|
||||
|
||||
nbests_.Clear();
|
||||
_has_bits_.Clear();
|
||||
_internal_metadata_.Clear();
|
||||
}
|
||||
|
||||
bool NBestSentencePieceText::MergePartialFromCodedStream(
|
||||
::google::protobuf::io::CodedInputStream* input) {
|
||||
#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
|
||||
::google::protobuf::uint32 tag;
|
||||
::google::protobuf::internal::LiteUnknownFieldSetter unknown_fields_setter(
|
||||
&_internal_metadata_);
|
||||
::google::protobuf::io::StringOutputStream unknown_fields_output(
|
||||
unknown_fields_setter.buffer());
|
||||
::google::protobuf::io::CodedOutputStream unknown_fields_stream(
|
||||
&unknown_fields_output, false);
|
||||
// @@protoc_insertion_point(parse_start:sentencepiece.NBestSentencePieceText)
|
||||
for (;;) {
|
||||
::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
|
||||
tag = p.first;
|
||||
if (!p.second) goto handle_unusual;
|
||||
switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
|
||||
// repeated .sentencepiece.SentencePieceText nbests = 1;
|
||||
case 1: {
|
||||
if (static_cast< ::google::protobuf::uint8>(tag) ==
|
||||
static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) {
|
||||
DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
|
||||
input, add_nbests()));
|
||||
} else {
|
||||
goto handle_unusual;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
handle_unusual:
|
||||
if (tag == 0) {
|
||||
goto success;
|
||||
}
|
||||
DO_(::google::protobuf::internal::WireFormatLite::SkipField(
|
||||
input, tag, &unknown_fields_stream));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
success:
|
||||
// @@protoc_insertion_point(parse_success:sentencepiece.NBestSentencePieceText)
|
||||
return true;
|
||||
failure:
|
||||
// @@protoc_insertion_point(parse_failure:sentencepiece.NBestSentencePieceText)
|
||||
return false;
|
||||
#undef DO_
|
||||
}
|
||||
|
||||
void NBestSentencePieceText::SerializeWithCachedSizes(
|
||||
::google::protobuf::io::CodedOutputStream* output) const {
|
||||
// @@protoc_insertion_point(serialize_start:sentencepiece.NBestSentencePieceText)
|
||||
::google::protobuf::uint32 cached_has_bits = 0;
|
||||
(void) cached_has_bits;
|
||||
|
||||
// repeated .sentencepiece.SentencePieceText nbests = 1;
|
||||
for (unsigned int i = 0,
|
||||
n = static_cast<unsigned int>(this->nbests_size()); i < n; i++) {
|
||||
::google::protobuf::internal::WireFormatLite::WriteMessage(
|
||||
1,
|
||||
this->nbests(static_cast<int>(i)),
|
||||
output);
|
||||
}
|
||||
|
||||
output->WriteRaw(_internal_metadata_.unknown_fields().data(),
|
||||
static_cast<int>(_internal_metadata_.unknown_fields().size()));
|
||||
// @@protoc_insertion_point(serialize_end:sentencepiece.NBestSentencePieceText)
|
||||
}
|
||||
|
||||
size_t NBestSentencePieceText::ByteSizeLong() const {
|
||||
// @@protoc_insertion_point(message_byte_size_start:sentencepiece.NBestSentencePieceText)
|
||||
size_t total_size = 0;
|
||||
|
||||
total_size += _internal_metadata_.unknown_fields().size();
|
||||
|
||||
// repeated .sentencepiece.SentencePieceText nbests = 1;
|
||||
{
|
||||
unsigned int count = static_cast<unsigned int>(this->nbests_size());
|
||||
total_size += 1UL * count;
|
||||
for (unsigned int i = 0; i < count; i++) {
|
||||
total_size +=
|
||||
::google::protobuf::internal::WireFormatLite::MessageSize(
|
||||
this->nbests(static_cast<int>(i)));
|
||||
}
|
||||
}
|
||||
|
||||
int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
|
||||
SetCachedSize(cached_size);
|
||||
return total_size;
|
||||
}
|
||||
|
||||
void NBestSentencePieceText::CheckTypeAndMergeFrom(
|
||||
const ::google::protobuf::MessageLite& from) {
|
||||
MergeFrom(*::google::protobuf::down_cast<const NBestSentencePieceText*>(&from));
|
||||
}
|
||||
|
||||
void NBestSentencePieceText::MergeFrom(const NBestSentencePieceText& from) {
|
||||
// @@protoc_insertion_point(class_specific_merge_from_start:sentencepiece.NBestSentencePieceText)
|
||||
GOOGLE_DCHECK_NE(&from, this);
|
||||
_internal_metadata_.MergeFrom(from._internal_metadata_);
|
||||
::google::protobuf::uint32 cached_has_bits = 0;
|
||||
(void) cached_has_bits;
|
||||
|
||||
nbests_.MergeFrom(from.nbests_);
|
||||
}
|
||||
|
||||
void NBestSentencePieceText::CopyFrom(const NBestSentencePieceText& from) {
|
||||
// @@protoc_insertion_point(class_specific_copy_from_start:sentencepiece.NBestSentencePieceText)
|
||||
if (&from == this) return;
|
||||
Clear();
|
||||
MergeFrom(from);
|
||||
}
|
||||
|
||||
bool NBestSentencePieceText::IsInitialized() const {
|
||||
if (!::google::protobuf::internal::AllAreInitialized(this->nbests())) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void NBestSentencePieceText::Swap(NBestSentencePieceText* other) {
|
||||
if (other == this) return;
|
||||
InternalSwap(other);
|
||||
}
|
||||
void NBestSentencePieceText::InternalSwap(NBestSentencePieceText* other) {
|
||||
using std::swap;
|
||||
CastToBase(&nbests_)->InternalSwap(CastToBase(&other->nbests_));
|
||||
swap(_has_bits_[0], other->_has_bits_[0]);
|
||||
_internal_metadata_.Swap(&other->_internal_metadata_);
|
||||
}
|
||||
|
||||
::std::string NBestSentencePieceText::GetTypeName() const {
|
||||
return "sentencepiece.NBestSentencePieceText";
|
||||
}
|
||||
|
||||
|
||||
// @@protoc_insertion_point(namespace_scope)
|
||||
} // namespace sentencepiece
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
template<> GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE ::sentencepiece::SentencePieceText_SentencePiece* Arena::CreateMaybeMessage< ::sentencepiece::SentencePieceText_SentencePiece >(Arena* arena) {
|
||||
return Arena::CreateInternal< ::sentencepiece::SentencePieceText_SentencePiece >(arena);
|
||||
}
|
||||
template<> GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE ::sentencepiece::SentencePieceText* Arena::CreateMaybeMessage< ::sentencepiece::SentencePieceText >(Arena* arena) {
|
||||
return Arena::CreateInternal< ::sentencepiece::SentencePieceText >(arena);
|
||||
}
|
||||
template<> GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE ::sentencepiece::NBestSentencePieceText* Arena::CreateMaybeMessage< ::sentencepiece::NBestSentencePieceText >(Arena* arena) {
|
||||
return Arena::CreateInternal< ::sentencepiece::NBestSentencePieceText >(arena);
|
||||
}
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
// @@protoc_insertion_point(global_scope)
|
887
src/builtin_pb/sentencepiece.pb.h
Normal file
887
src/builtin_pb/sentencepiece.pb.h
Normal file
@ -0,0 +1,887 @@
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: sentencepiece.proto
|
||||
|
||||
#ifndef PROTOBUF_INCLUDED_sentencepiece_2eproto
|
||||
#define PROTOBUF_INCLUDED_sentencepiece_2eproto
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
#if GOOGLE_PROTOBUF_VERSION < 3006001
|
||||
#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 3006001 < GOOGLE_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/io/coded_stream.h>
|
||||
#include <google/protobuf/arena.h>
|
||||
#include <google/protobuf/arenastring.h>
|
||||
#include <google/protobuf/generated_message_table_driven.h>
|
||||
#include <google/protobuf/generated_message_util.h>
|
||||
#include <google/protobuf/inlined_string_field.h>
|
||||
#include <google/protobuf/metadata_lite.h>
|
||||
#include <google/protobuf/message_lite.h>
|
||||
#include <google/protobuf/repeated_field.h> // IWYU pragma: export
|
||||
#include <google/protobuf/extension_set.h> // IWYU pragma: export
|
||||
// @@protoc_insertion_point(includes)
|
||||
#define PROTOBUF_INTERNAL_EXPORT_protobuf_sentencepiece_2eproto
|
||||
|
||||
namespace protobuf_sentencepiece_2eproto {
|
||||
// Internal implementation detail -- do not use these members.
|
||||
struct TableStruct {
|
||||
static const ::google::protobuf::internal::ParseTableField entries[];
|
||||
static const ::google::protobuf::internal::AuxillaryParseTableField aux[];
|
||||
static const ::google::protobuf::internal::ParseTable schema[3];
|
||||
static const ::google::protobuf::internal::FieldMetadata field_metadata[];
|
||||
static const ::google::protobuf::internal::SerializationTable serialization_table[];
|
||||
static const ::google::protobuf::uint32 offsets[];
|
||||
};
|
||||
} // namespace protobuf_sentencepiece_2eproto
|
||||
namespace sentencepiece {
|
||||
class NBestSentencePieceText;
|
||||
class NBestSentencePieceTextDefaultTypeInternal;
|
||||
extern NBestSentencePieceTextDefaultTypeInternal _NBestSentencePieceText_default_instance_;
|
||||
class SentencePieceText;
|
||||
class SentencePieceTextDefaultTypeInternal;
|
||||
extern SentencePieceTextDefaultTypeInternal _SentencePieceText_default_instance_;
|
||||
class SentencePieceText_SentencePiece;
|
||||
class SentencePieceText_SentencePieceDefaultTypeInternal;
|
||||
extern SentencePieceText_SentencePieceDefaultTypeInternal _SentencePieceText_SentencePiece_default_instance_;
|
||||
} // namespace sentencepiece
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
template<> ::sentencepiece::NBestSentencePieceText* Arena::CreateMaybeMessage<::sentencepiece::NBestSentencePieceText>(Arena*);
|
||||
template<> ::sentencepiece::SentencePieceText* Arena::CreateMaybeMessage<::sentencepiece::SentencePieceText>(Arena*);
|
||||
template<> ::sentencepiece::SentencePieceText_SentencePiece* Arena::CreateMaybeMessage<::sentencepiece::SentencePieceText_SentencePiece>(Arena*);
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
namespace sentencepiece {
|
||||
|
||||
// ===================================================================
|
||||
|
||||
class SentencePieceText_SentencePiece : public ::google::protobuf::MessageLite /* @@protoc_insertion_point(class_definition:sentencepiece.SentencePieceText.SentencePiece) */ {
|
||||
public:
|
||||
SentencePieceText_SentencePiece();
|
||||
virtual ~SentencePieceText_SentencePiece();
|
||||
|
||||
SentencePieceText_SentencePiece(const SentencePieceText_SentencePiece& from);
|
||||
|
||||
inline SentencePieceText_SentencePiece& operator=(const SentencePieceText_SentencePiece& from) {
|
||||
CopyFrom(from);
|
||||
return *this;
|
||||
}
|
||||
#if LANG_CXX11
|
||||
SentencePieceText_SentencePiece(SentencePieceText_SentencePiece&& from) noexcept
|
||||
: SentencePieceText_SentencePiece() {
|
||||
*this = ::std::move(from);
|
||||
}
|
||||
|
||||
inline SentencePieceText_SentencePiece& operator=(SentencePieceText_SentencePiece&& from) noexcept {
|
||||
if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
|
||||
if (this != &from) InternalSwap(&from);
|
||||
} else {
|
||||
CopyFrom(from);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
inline const ::std::string& unknown_fields() const {
|
||||
return _internal_metadata_.unknown_fields();
|
||||
}
|
||||
inline ::std::string* mutable_unknown_fields() {
|
||||
return _internal_metadata_.mutable_unknown_fields();
|
||||
}
|
||||
|
||||
static const SentencePieceText_SentencePiece& default_instance();
|
||||
|
||||
static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY
|
||||
static inline const SentencePieceText_SentencePiece* internal_default_instance() {
|
||||
return reinterpret_cast<const SentencePieceText_SentencePiece*>(
|
||||
&_SentencePieceText_SentencePiece_default_instance_);
|
||||
}
|
||||
static constexpr int kIndexInFileMessages =
|
||||
0;
|
||||
|
||||
void Swap(SentencePieceText_SentencePiece* other);
|
||||
friend void swap(SentencePieceText_SentencePiece& a, SentencePieceText_SentencePiece& b) {
|
||||
a.Swap(&b);
|
||||
}
|
||||
|
||||
// implements Message ----------------------------------------------
|
||||
|
||||
inline SentencePieceText_SentencePiece* New() const final {
|
||||
return CreateMaybeMessage<SentencePieceText_SentencePiece>(NULL);
|
||||
}
|
||||
|
||||
SentencePieceText_SentencePiece* New(::google::protobuf::Arena* arena) const final {
|
||||
return CreateMaybeMessage<SentencePieceText_SentencePiece>(arena);
|
||||
}
|
||||
void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from)
|
||||
final;
|
||||
void CopyFrom(const SentencePieceText_SentencePiece& from);
|
||||
void MergeFrom(const SentencePieceText_SentencePiece& from);
|
||||
void Clear() final;
|
||||
bool IsInitialized() const final;
|
||||
|
||||
size_t ByteSizeLong() const final;
|
||||
bool MergePartialFromCodedStream(
|
||||
::google::protobuf::io::CodedInputStream* input) final;
|
||||
void SerializeWithCachedSizes(
|
||||
::google::protobuf::io::CodedOutputStream* output) const final;
|
||||
void DiscardUnknownFields();
|
||||
int GetCachedSize() const final { return _cached_size_.Get(); }
|
||||
|
||||
private:
|
||||
void SharedCtor();
|
||||
void SharedDtor();
|
||||
void SetCachedSize(int size) const;
|
||||
void InternalSwap(SentencePieceText_SentencePiece* other);
|
||||
private:
|
||||
inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
|
||||
return NULL;
|
||||
}
|
||||
inline void* MaybeArenaPtr() const {
|
||||
return NULL;
|
||||
}
|
||||
public:
|
||||
|
||||
::std::string GetTypeName() const final;
|
||||
|
||||
// nested types ----------------------------------------------------
|
||||
|
||||
// accessors -------------------------------------------------------
|
||||
|
||||
// optional string piece = 1;
|
||||
bool has_piece() const;
|
||||
void clear_piece();
|
||||
static const int kPieceFieldNumber = 1;
|
||||
const ::std::string& piece() const;
|
||||
void set_piece(const ::std::string& value);
|
||||
#if LANG_CXX11
|
||||
void set_piece(::std::string&& value);
|
||||
#endif
|
||||
void set_piece(const char* value);
|
||||
void set_piece(const char* value, size_t size);
|
||||
::std::string* mutable_piece();
|
||||
::std::string* release_piece();
|
||||
void set_allocated_piece(::std::string* piece);
|
||||
|
||||
// optional string surface = 3;
|
||||
bool has_surface() const;
|
||||
void clear_surface();
|
||||
static const int kSurfaceFieldNumber = 3;
|
||||
const ::std::string& surface() const;
|
||||
void set_surface(const ::std::string& value);
|
||||
#if LANG_CXX11
|
||||
void set_surface(::std::string&& value);
|
||||
#endif
|
||||
void set_surface(const char* value);
|
||||
void set_surface(const char* value, size_t size);
|
||||
::std::string* mutable_surface();
|
||||
::std::string* release_surface();
|
||||
void set_allocated_surface(::std::string* surface);
|
||||
|
||||
// optional uint32 id = 2;
|
||||
bool has_id() const;
|
||||
void clear_id();
|
||||
static const int kIdFieldNumber = 2;
|
||||
::google::protobuf::uint32 id() const;
|
||||
void set_id(::google::protobuf::uint32 value);
|
||||
|
||||
// optional uint32 begin = 4;
|
||||
bool has_begin() const;
|
||||
void clear_begin();
|
||||
static const int kBeginFieldNumber = 4;
|
||||
::google::protobuf::uint32 begin() const;
|
||||
void set_begin(::google::protobuf::uint32 value);
|
||||
|
||||
// optional uint32 end = 5;
|
||||
bool has_end() const;
|
||||
void clear_end();
|
||||
static const int kEndFieldNumber = 5;
|
||||
::google::protobuf::uint32 end() const;
|
||||
void set_end(::google::protobuf::uint32 value);
|
||||
|
||||
GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(SentencePieceText_SentencePiece)
|
||||
// @@protoc_insertion_point(class_scope:sentencepiece.SentencePieceText.SentencePiece)
|
||||
private:
|
||||
void set_has_piece();
|
||||
void clear_has_piece();
|
||||
void set_has_id();
|
||||
void clear_has_id();
|
||||
void set_has_surface();
|
||||
void clear_has_surface();
|
||||
void set_has_begin();
|
||||
void clear_has_begin();
|
||||
void set_has_end();
|
||||
void clear_has_end();
|
||||
|
||||
::google::protobuf::internal::ExtensionSet _extensions_;
|
||||
|
||||
::google::protobuf::internal::InternalMetadataWithArenaLite _internal_metadata_;
|
||||
::google::protobuf::internal::HasBits<1> _has_bits_;
|
||||
mutable ::google::protobuf::internal::CachedSize _cached_size_;
|
||||
::google::protobuf::internal::ArenaStringPtr piece_;
|
||||
::google::protobuf::internal::ArenaStringPtr surface_;
|
||||
::google::protobuf::uint32 id_;
|
||||
::google::protobuf::uint32 begin_;
|
||||
::google::protobuf::uint32 end_;
|
||||
friend struct ::protobuf_sentencepiece_2eproto::TableStruct;
|
||||
};
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
class SentencePieceText : public ::google::protobuf::MessageLite /* @@protoc_insertion_point(class_definition:sentencepiece.SentencePieceText) */ {
|
||||
public:
|
||||
SentencePieceText();
|
||||
virtual ~SentencePieceText();
|
||||
|
||||
SentencePieceText(const SentencePieceText& from);
|
||||
|
||||
inline SentencePieceText& operator=(const SentencePieceText& from) {
|
||||
CopyFrom(from);
|
||||
return *this;
|
||||
}
|
||||
#if LANG_CXX11
|
||||
SentencePieceText(SentencePieceText&& from) noexcept
|
||||
: SentencePieceText() {
|
||||
*this = ::std::move(from);
|
||||
}
|
||||
|
||||
inline SentencePieceText& operator=(SentencePieceText&& from) noexcept {
|
||||
if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
|
||||
if (this != &from) InternalSwap(&from);
|
||||
} else {
|
||||
CopyFrom(from);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
inline const ::std::string& unknown_fields() const {
|
||||
return _internal_metadata_.unknown_fields();
|
||||
}
|
||||
inline ::std::string* mutable_unknown_fields() {
|
||||
return _internal_metadata_.mutable_unknown_fields();
|
||||
}
|
||||
|
||||
static const SentencePieceText& default_instance();
|
||||
|
||||
static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY
|
||||
static inline const SentencePieceText* internal_default_instance() {
|
||||
return reinterpret_cast<const SentencePieceText*>(
|
||||
&_SentencePieceText_default_instance_);
|
||||
}
|
||||
static constexpr int kIndexInFileMessages =
|
||||
1;
|
||||
|
||||
void Swap(SentencePieceText* other);
|
||||
friend void swap(SentencePieceText& a, SentencePieceText& b) {
|
||||
a.Swap(&b);
|
||||
}
|
||||
|
||||
// implements Message ----------------------------------------------
|
||||
|
||||
inline SentencePieceText* New() const final {
|
||||
return CreateMaybeMessage<SentencePieceText>(NULL);
|
||||
}
|
||||
|
||||
SentencePieceText* New(::google::protobuf::Arena* arena) const final {
|
||||
return CreateMaybeMessage<SentencePieceText>(arena);
|
||||
}
|
||||
void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from)
|
||||
final;
|
||||
void CopyFrom(const SentencePieceText& from);
|
||||
void MergeFrom(const SentencePieceText& from);
|
||||
void Clear() final;
|
||||
bool IsInitialized() const final;
|
||||
|
||||
size_t ByteSizeLong() const final;
|
||||
bool MergePartialFromCodedStream(
|
||||
::google::protobuf::io::CodedInputStream* input) final;
|
||||
void SerializeWithCachedSizes(
|
||||
::google::protobuf::io::CodedOutputStream* output) const final;
|
||||
void DiscardUnknownFields();
|
||||
int GetCachedSize() const final { return _cached_size_.Get(); }
|
||||
|
||||
private:
|
||||
void SharedCtor();
|
||||
void SharedDtor();
|
||||
void SetCachedSize(int size) const;
|
||||
void InternalSwap(SentencePieceText* other);
|
||||
private:
|
||||
inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
|
||||
return NULL;
|
||||
}
|
||||
inline void* MaybeArenaPtr() const {
|
||||
return NULL;
|
||||
}
|
||||
public:
|
||||
|
||||
::std::string GetTypeName() const final;
|
||||
|
||||
// nested types ----------------------------------------------------
|
||||
|
||||
typedef SentencePieceText_SentencePiece SentencePiece;
|
||||
|
||||
// accessors -------------------------------------------------------
|
||||
|
||||
// repeated .sentencepiece.SentencePieceText.SentencePiece pieces = 2;
|
||||
int pieces_size() const;
|
||||
void clear_pieces();
|
||||
static const int kPiecesFieldNumber = 2;
|
||||
::sentencepiece::SentencePieceText_SentencePiece* mutable_pieces(int index);
|
||||
::google::protobuf::RepeatedPtrField< ::sentencepiece::SentencePieceText_SentencePiece >*
|
||||
mutable_pieces();
|
||||
const ::sentencepiece::SentencePieceText_SentencePiece& pieces(int index) const;
|
||||
::sentencepiece::SentencePieceText_SentencePiece* add_pieces();
|
||||
const ::google::protobuf::RepeatedPtrField< ::sentencepiece::SentencePieceText_SentencePiece >&
|
||||
pieces() const;
|
||||
|
||||
// optional string text = 1;
|
||||
bool has_text() const;
|
||||
void clear_text();
|
||||
static const int kTextFieldNumber = 1;
|
||||
const ::std::string& text() const;
|
||||
void set_text(const ::std::string& value);
|
||||
#if LANG_CXX11
|
||||
void set_text(::std::string&& value);
|
||||
#endif
|
||||
void set_text(const char* value);
|
||||
void set_text(const char* value, size_t size);
|
||||
::std::string* mutable_text();
|
||||
::std::string* release_text();
|
||||
void set_allocated_text(::std::string* text);
|
||||
|
||||
// optional float score = 3;
|
||||
bool has_score() const;
|
||||
void clear_score();
|
||||
static const int kScoreFieldNumber = 3;
|
||||
float score() const;
|
||||
void set_score(float value);
|
||||
|
||||
GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(SentencePieceText)
|
||||
// @@protoc_insertion_point(class_scope:sentencepiece.SentencePieceText)
|
||||
private:
|
||||
void set_has_text();
|
||||
void clear_has_text();
|
||||
void set_has_score();
|
||||
void clear_has_score();
|
||||
|
||||
::google::protobuf::internal::ExtensionSet _extensions_;
|
||||
|
||||
::google::protobuf::internal::InternalMetadataWithArenaLite _internal_metadata_;
|
||||
::google::protobuf::internal::HasBits<1> _has_bits_;
|
||||
mutable ::google::protobuf::internal::CachedSize _cached_size_;
|
||||
::google::protobuf::RepeatedPtrField< ::sentencepiece::SentencePieceText_SentencePiece > pieces_;
|
||||
::google::protobuf::internal::ArenaStringPtr text_;
|
||||
float score_;
|
||||
friend struct ::protobuf_sentencepiece_2eproto::TableStruct;
|
||||
};
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
class NBestSentencePieceText : public ::google::protobuf::MessageLite /* @@protoc_insertion_point(class_definition:sentencepiece.NBestSentencePieceText) */ {
|
||||
public:
|
||||
NBestSentencePieceText();
|
||||
virtual ~NBestSentencePieceText();
|
||||
|
||||
NBestSentencePieceText(const NBestSentencePieceText& from);
|
||||
|
||||
inline NBestSentencePieceText& operator=(const NBestSentencePieceText& from) {
|
||||
CopyFrom(from);
|
||||
return *this;
|
||||
}
|
||||
#if LANG_CXX11
|
||||
NBestSentencePieceText(NBestSentencePieceText&& from) noexcept
|
||||
: NBestSentencePieceText() {
|
||||
*this = ::std::move(from);
|
||||
}
|
||||
|
||||
inline NBestSentencePieceText& operator=(NBestSentencePieceText&& from) noexcept {
|
||||
if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
|
||||
if (this != &from) InternalSwap(&from);
|
||||
} else {
|
||||
CopyFrom(from);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
inline const ::std::string& unknown_fields() const {
|
||||
return _internal_metadata_.unknown_fields();
|
||||
}
|
||||
inline ::std::string* mutable_unknown_fields() {
|
||||
return _internal_metadata_.mutable_unknown_fields();
|
||||
}
|
||||
|
||||
static const NBestSentencePieceText& default_instance();
|
||||
|
||||
static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY
|
||||
static inline const NBestSentencePieceText* internal_default_instance() {
|
||||
return reinterpret_cast<const NBestSentencePieceText*>(
|
||||
&_NBestSentencePieceText_default_instance_);
|
||||
}
|
||||
static constexpr int kIndexInFileMessages =
|
||||
2;
|
||||
|
||||
void Swap(NBestSentencePieceText* other);
|
||||
friend void swap(NBestSentencePieceText& a, NBestSentencePieceText& b) {
|
||||
a.Swap(&b);
|
||||
}
|
||||
|
||||
// implements Message ----------------------------------------------
|
||||
|
||||
inline NBestSentencePieceText* New() const final {
|
||||
return CreateMaybeMessage<NBestSentencePieceText>(NULL);
|
||||
}
|
||||
|
||||
NBestSentencePieceText* New(::google::protobuf::Arena* arena) const final {
|
||||
return CreateMaybeMessage<NBestSentencePieceText>(arena);
|
||||
}
|
||||
void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from)
|
||||
final;
|
||||
void CopyFrom(const NBestSentencePieceText& from);
|
||||
void MergeFrom(const NBestSentencePieceText& from);
|
||||
void Clear() final;
|
||||
bool IsInitialized() const final;
|
||||
|
||||
size_t ByteSizeLong() const final;
|
||||
bool MergePartialFromCodedStream(
|
||||
::google::protobuf::io::CodedInputStream* input) final;
|
||||
void SerializeWithCachedSizes(
|
||||
::google::protobuf::io::CodedOutputStream* output) const final;
|
||||
void DiscardUnknownFields();
|
||||
int GetCachedSize() const final { return _cached_size_.Get(); }
|
||||
|
||||
private:
|
||||
void SharedCtor();
|
||||
void SharedDtor();
|
||||
void SetCachedSize(int size) const;
|
||||
void InternalSwap(NBestSentencePieceText* other);
|
||||
private:
|
||||
inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
|
||||
return NULL;
|
||||
}
|
||||
inline void* MaybeArenaPtr() const {
|
||||
return NULL;
|
||||
}
|
||||
public:
|
||||
|
||||
::std::string GetTypeName() const final;
|
||||
|
||||
// nested types ----------------------------------------------------
|
||||
|
||||
// accessors -------------------------------------------------------
|
||||
|
||||
// repeated .sentencepiece.SentencePieceText nbests = 1;
|
||||
int nbests_size() const;
|
||||
void clear_nbests();
|
||||
static const int kNbestsFieldNumber = 1;
|
||||
::sentencepiece::SentencePieceText* mutable_nbests(int index);
|
||||
::google::protobuf::RepeatedPtrField< ::sentencepiece::SentencePieceText >*
|
||||
mutable_nbests();
|
||||
const ::sentencepiece::SentencePieceText& nbests(int index) const;
|
||||
::sentencepiece::SentencePieceText* add_nbests();
|
||||
const ::google::protobuf::RepeatedPtrField< ::sentencepiece::SentencePieceText >&
|
||||
nbests() const;
|
||||
|
||||
// @@protoc_insertion_point(class_scope:sentencepiece.NBestSentencePieceText)
|
||||
private:
|
||||
|
||||
::google::protobuf::internal::InternalMetadataWithArenaLite _internal_metadata_;
|
||||
::google::protobuf::internal::HasBits<1> _has_bits_;
|
||||
mutable ::google::protobuf::internal::CachedSize _cached_size_;
|
||||
::google::protobuf::RepeatedPtrField< ::sentencepiece::SentencePieceText > nbests_;
|
||||
friend struct ::protobuf_sentencepiece_2eproto::TableStruct;
|
||||
};
|
||||
// ===================================================================
|
||||
|
||||
|
||||
// ===================================================================
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
|
||||
#endif // __GNUC__
|
||||
// SentencePieceText_SentencePiece
|
||||
|
||||
// optional string piece = 1;
|
||||
inline bool SentencePieceText_SentencePiece::has_piece() const {
|
||||
return (_has_bits_[0] & 0x00000001u) != 0;
|
||||
}
|
||||
inline void SentencePieceText_SentencePiece::set_has_piece() {
|
||||
_has_bits_[0] |= 0x00000001u;
|
||||
}
|
||||
inline void SentencePieceText_SentencePiece::clear_has_piece() {
|
||||
_has_bits_[0] &= ~0x00000001u;
|
||||
}
|
||||
inline void SentencePieceText_SentencePiece::clear_piece() {
|
||||
piece_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
clear_has_piece();
|
||||
}
|
||||
inline const ::std::string& SentencePieceText_SentencePiece::piece() const {
|
||||
// @@protoc_insertion_point(field_get:sentencepiece.SentencePieceText.SentencePiece.piece)
|
||||
return piece_.GetNoArena();
|
||||
}
|
||||
inline void SentencePieceText_SentencePiece::set_piece(const ::std::string& value) {
|
||||
set_has_piece();
|
||||
piece_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
|
||||
// @@protoc_insertion_point(field_set:sentencepiece.SentencePieceText.SentencePiece.piece)
|
||||
}
|
||||
#if LANG_CXX11
|
||||
inline void SentencePieceText_SentencePiece::set_piece(::std::string&& value) {
|
||||
set_has_piece();
|
||||
piece_.SetNoArena(
|
||||
&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
|
||||
// @@protoc_insertion_point(field_set_rvalue:sentencepiece.SentencePieceText.SentencePiece.piece)
|
||||
}
|
||||
#endif
|
||||
inline void SentencePieceText_SentencePiece::set_piece(const char* value) {
|
||||
GOOGLE_DCHECK(value != NULL);
|
||||
set_has_piece();
|
||||
piece_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
|
||||
// @@protoc_insertion_point(field_set_char:sentencepiece.SentencePieceText.SentencePiece.piece)
|
||||
}
|
||||
inline void SentencePieceText_SentencePiece::set_piece(const char* value, size_t size) {
|
||||
set_has_piece();
|
||||
piece_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
|
||||
::std::string(reinterpret_cast<const char*>(value), size));
|
||||
// @@protoc_insertion_point(field_set_pointer:sentencepiece.SentencePieceText.SentencePiece.piece)
|
||||
}
|
||||
inline ::std::string* SentencePieceText_SentencePiece::mutable_piece() {
|
||||
set_has_piece();
|
||||
// @@protoc_insertion_point(field_mutable:sentencepiece.SentencePieceText.SentencePiece.piece)
|
||||
return piece_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
inline ::std::string* SentencePieceText_SentencePiece::release_piece() {
|
||||
// @@protoc_insertion_point(field_release:sentencepiece.SentencePieceText.SentencePiece.piece)
|
||||
if (!has_piece()) {
|
||||
return NULL;
|
||||
}
|
||||
clear_has_piece();
|
||||
return piece_.ReleaseNonDefaultNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
inline void SentencePieceText_SentencePiece::set_allocated_piece(::std::string* piece) {
|
||||
if (piece != NULL) {
|
||||
set_has_piece();
|
||||
} else {
|
||||
clear_has_piece();
|
||||
}
|
||||
piece_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), piece);
|
||||
// @@protoc_insertion_point(field_set_allocated:sentencepiece.SentencePieceText.SentencePiece.piece)
|
||||
}
|
||||
|
||||
// optional uint32 id = 2;
|
||||
inline bool SentencePieceText_SentencePiece::has_id() const {
|
||||
return (_has_bits_[0] & 0x00000004u) != 0;
|
||||
}
|
||||
inline void SentencePieceText_SentencePiece::set_has_id() {
|
||||
_has_bits_[0] |= 0x00000004u;
|
||||
}
|
||||
inline void SentencePieceText_SentencePiece::clear_has_id() {
|
||||
_has_bits_[0] &= ~0x00000004u;
|
||||
}
|
||||
inline void SentencePieceText_SentencePiece::clear_id() {
|
||||
id_ = 0u;
|
||||
clear_has_id();
|
||||
}
|
||||
inline ::google::protobuf::uint32 SentencePieceText_SentencePiece::id() const {
|
||||
// @@protoc_insertion_point(field_get:sentencepiece.SentencePieceText.SentencePiece.id)
|
||||
return id_;
|
||||
}
|
||||
inline void SentencePieceText_SentencePiece::set_id(::google::protobuf::uint32 value) {
|
||||
set_has_id();
|
||||
id_ = value;
|
||||
// @@protoc_insertion_point(field_set:sentencepiece.SentencePieceText.SentencePiece.id)
|
||||
}
|
||||
|
||||
// optional string surface = 3;
|
||||
inline bool SentencePieceText_SentencePiece::has_surface() const {
|
||||
return (_has_bits_[0] & 0x00000002u) != 0;
|
||||
}
|
||||
inline void SentencePieceText_SentencePiece::set_has_surface() {
|
||||
_has_bits_[0] |= 0x00000002u;
|
||||
}
|
||||
inline void SentencePieceText_SentencePiece::clear_has_surface() {
|
||||
_has_bits_[0] &= ~0x00000002u;
|
||||
}
|
||||
inline void SentencePieceText_SentencePiece::clear_surface() {
|
||||
surface_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
clear_has_surface();
|
||||
}
|
||||
inline const ::std::string& SentencePieceText_SentencePiece::surface() const {
|
||||
// @@protoc_insertion_point(field_get:sentencepiece.SentencePieceText.SentencePiece.surface)
|
||||
return surface_.GetNoArena();
|
||||
}
|
||||
inline void SentencePieceText_SentencePiece::set_surface(const ::std::string& value) {
|
||||
set_has_surface();
|
||||
surface_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
|
||||
// @@protoc_insertion_point(field_set:sentencepiece.SentencePieceText.SentencePiece.surface)
|
||||
}
|
||||
#if LANG_CXX11
|
||||
inline void SentencePieceText_SentencePiece::set_surface(::std::string&& value) {
|
||||
set_has_surface();
|
||||
surface_.SetNoArena(
|
||||
&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
|
||||
// @@protoc_insertion_point(field_set_rvalue:sentencepiece.SentencePieceText.SentencePiece.surface)
|
||||
}
|
||||
#endif
|
||||
inline void SentencePieceText_SentencePiece::set_surface(const char* value) {
|
||||
GOOGLE_DCHECK(value != NULL);
|
||||
set_has_surface();
|
||||
surface_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
|
||||
// @@protoc_insertion_point(field_set_char:sentencepiece.SentencePieceText.SentencePiece.surface)
|
||||
}
|
||||
inline void SentencePieceText_SentencePiece::set_surface(const char* value, size_t size) {
|
||||
set_has_surface();
|
||||
surface_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
|
||||
::std::string(reinterpret_cast<const char*>(value), size));
|
||||
// @@protoc_insertion_point(field_set_pointer:sentencepiece.SentencePieceText.SentencePiece.surface)
|
||||
}
|
||||
inline ::std::string* SentencePieceText_SentencePiece::mutable_surface() {
|
||||
set_has_surface();
|
||||
// @@protoc_insertion_point(field_mutable:sentencepiece.SentencePieceText.SentencePiece.surface)
|
||||
return surface_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
inline ::std::string* SentencePieceText_SentencePiece::release_surface() {
|
||||
// @@protoc_insertion_point(field_release:sentencepiece.SentencePieceText.SentencePiece.surface)
|
||||
if (!has_surface()) {
|
||||
return NULL;
|
||||
}
|
||||
clear_has_surface();
|
||||
return surface_.ReleaseNonDefaultNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
inline void SentencePieceText_SentencePiece::set_allocated_surface(::std::string* surface) {
|
||||
if (surface != NULL) {
|
||||
set_has_surface();
|
||||
} else {
|
||||
clear_has_surface();
|
||||
}
|
||||
surface_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), surface);
|
||||
// @@protoc_insertion_point(field_set_allocated:sentencepiece.SentencePieceText.SentencePiece.surface)
|
||||
}
|
||||
|
||||
// optional uint32 begin = 4;
|
||||
inline bool SentencePieceText_SentencePiece::has_begin() const {
|
||||
return (_has_bits_[0] & 0x00000008u) != 0;
|
||||
}
|
||||
inline void SentencePieceText_SentencePiece::set_has_begin() {
|
||||
_has_bits_[0] |= 0x00000008u;
|
||||
}
|
||||
inline void SentencePieceText_SentencePiece::clear_has_begin() {
|
||||
_has_bits_[0] &= ~0x00000008u;
|
||||
}
|
||||
inline void SentencePieceText_SentencePiece::clear_begin() {
|
||||
begin_ = 0u;
|
||||
clear_has_begin();
|
||||
}
|
||||
inline ::google::protobuf::uint32 SentencePieceText_SentencePiece::begin() const {
|
||||
// @@protoc_insertion_point(field_get:sentencepiece.SentencePieceText.SentencePiece.begin)
|
||||
return begin_;
|
||||
}
|
||||
inline void SentencePieceText_SentencePiece::set_begin(::google::protobuf::uint32 value) {
|
||||
set_has_begin();
|
||||
begin_ = value;
|
||||
// @@protoc_insertion_point(field_set:sentencepiece.SentencePieceText.SentencePiece.begin)
|
||||
}
|
||||
|
||||
// optional uint32 end = 5;
|
||||
inline bool SentencePieceText_SentencePiece::has_end() const {
|
||||
return (_has_bits_[0] & 0x00000010u) != 0;
|
||||
}
|
||||
inline void SentencePieceText_SentencePiece::set_has_end() {
|
||||
_has_bits_[0] |= 0x00000010u;
|
||||
}
|
||||
inline void SentencePieceText_SentencePiece::clear_has_end() {
|
||||
_has_bits_[0] &= ~0x00000010u;
|
||||
}
|
||||
inline void SentencePieceText_SentencePiece::clear_end() {
|
||||
end_ = 0u;
|
||||
clear_has_end();
|
||||
}
|
||||
inline ::google::protobuf::uint32 SentencePieceText_SentencePiece::end() const {
|
||||
// @@protoc_insertion_point(field_get:sentencepiece.SentencePieceText.SentencePiece.end)
|
||||
return end_;
|
||||
}
|
||||
inline void SentencePieceText_SentencePiece::set_end(::google::protobuf::uint32 value) {
|
||||
set_has_end();
|
||||
end_ = value;
|
||||
// @@protoc_insertion_point(field_set:sentencepiece.SentencePieceText.SentencePiece.end)
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
// SentencePieceText
|
||||
|
||||
// optional string text = 1;
|
||||
inline bool SentencePieceText::has_text() const {
|
||||
return (_has_bits_[0] & 0x00000001u) != 0;
|
||||
}
|
||||
inline void SentencePieceText::set_has_text() {
|
||||
_has_bits_[0] |= 0x00000001u;
|
||||
}
|
||||
inline void SentencePieceText::clear_has_text() {
|
||||
_has_bits_[0] &= ~0x00000001u;
|
||||
}
|
||||
inline void SentencePieceText::clear_text() {
|
||||
text_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
clear_has_text();
|
||||
}
|
||||
inline const ::std::string& SentencePieceText::text() const {
|
||||
// @@protoc_insertion_point(field_get:sentencepiece.SentencePieceText.text)
|
||||
return text_.GetNoArena();
|
||||
}
|
||||
inline void SentencePieceText::set_text(const ::std::string& value) {
|
||||
set_has_text();
|
||||
text_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
|
||||
// @@protoc_insertion_point(field_set:sentencepiece.SentencePieceText.text)
|
||||
}
|
||||
#if LANG_CXX11
|
||||
inline void SentencePieceText::set_text(::std::string&& value) {
|
||||
set_has_text();
|
||||
text_.SetNoArena(
|
||||
&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
|
||||
// @@protoc_insertion_point(field_set_rvalue:sentencepiece.SentencePieceText.text)
|
||||
}
|
||||
#endif
|
||||
inline void SentencePieceText::set_text(const char* value) {
|
||||
GOOGLE_DCHECK(value != NULL);
|
||||
set_has_text();
|
||||
text_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
|
||||
// @@protoc_insertion_point(field_set_char:sentencepiece.SentencePieceText.text)
|
||||
}
|
||||
inline void SentencePieceText::set_text(const char* value, size_t size) {
|
||||
set_has_text();
|
||||
text_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
|
||||
::std::string(reinterpret_cast<const char*>(value), size));
|
||||
// @@protoc_insertion_point(field_set_pointer:sentencepiece.SentencePieceText.text)
|
||||
}
|
||||
inline ::std::string* SentencePieceText::mutable_text() {
|
||||
set_has_text();
|
||||
// @@protoc_insertion_point(field_mutable:sentencepiece.SentencePieceText.text)
|
||||
return text_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
inline ::std::string* SentencePieceText::release_text() {
|
||||
// @@protoc_insertion_point(field_release:sentencepiece.SentencePieceText.text)
|
||||
if (!has_text()) {
|
||||
return NULL;
|
||||
}
|
||||
clear_has_text();
|
||||
return text_.ReleaseNonDefaultNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
inline void SentencePieceText::set_allocated_text(::std::string* text) {
|
||||
if (text != NULL) {
|
||||
set_has_text();
|
||||
} else {
|
||||
clear_has_text();
|
||||
}
|
||||
text_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), text);
|
||||
// @@protoc_insertion_point(field_set_allocated:sentencepiece.SentencePieceText.text)
|
||||
}
|
||||
|
||||
// repeated .sentencepiece.SentencePieceText.SentencePiece pieces = 2;
|
||||
inline int SentencePieceText::pieces_size() const {
|
||||
return pieces_.size();
|
||||
}
|
||||
inline void SentencePieceText::clear_pieces() {
|
||||
pieces_.Clear();
|
||||
}
|
||||
inline ::sentencepiece::SentencePieceText_SentencePiece* SentencePieceText::mutable_pieces(int index) {
|
||||
// @@protoc_insertion_point(field_mutable:sentencepiece.SentencePieceText.pieces)
|
||||
return pieces_.Mutable(index);
|
||||
}
|
||||
inline ::google::protobuf::RepeatedPtrField< ::sentencepiece::SentencePieceText_SentencePiece >*
|
||||
SentencePieceText::mutable_pieces() {
|
||||
// @@protoc_insertion_point(field_mutable_list:sentencepiece.SentencePieceText.pieces)
|
||||
return &pieces_;
|
||||
}
|
||||
inline const ::sentencepiece::SentencePieceText_SentencePiece& SentencePieceText::pieces(int index) const {
|
||||
// @@protoc_insertion_point(field_get:sentencepiece.SentencePieceText.pieces)
|
||||
return pieces_.Get(index);
|
||||
}
|
||||
inline ::sentencepiece::SentencePieceText_SentencePiece* SentencePieceText::add_pieces() {
|
||||
// @@protoc_insertion_point(field_add:sentencepiece.SentencePieceText.pieces)
|
||||
return pieces_.Add();
|
||||
}
|
||||
inline const ::google::protobuf::RepeatedPtrField< ::sentencepiece::SentencePieceText_SentencePiece >&
|
||||
SentencePieceText::pieces() const {
|
||||
// @@protoc_insertion_point(field_list:sentencepiece.SentencePieceText.pieces)
|
||||
return pieces_;
|
||||
}
|
||||
|
||||
// optional float score = 3;
|
||||
inline bool SentencePieceText::has_score() const {
|
||||
return (_has_bits_[0] & 0x00000002u) != 0;
|
||||
}
|
||||
inline void SentencePieceText::set_has_score() {
|
||||
_has_bits_[0] |= 0x00000002u;
|
||||
}
|
||||
inline void SentencePieceText::clear_has_score() {
|
||||
_has_bits_[0] &= ~0x00000002u;
|
||||
}
|
||||
inline void SentencePieceText::clear_score() {
|
||||
score_ = 0;
|
||||
clear_has_score();
|
||||
}
|
||||
inline float SentencePieceText::score() const {
|
||||
// @@protoc_insertion_point(field_get:sentencepiece.SentencePieceText.score)
|
||||
return score_;
|
||||
}
|
||||
inline void SentencePieceText::set_score(float value) {
|
||||
set_has_score();
|
||||
score_ = value;
|
||||
// @@protoc_insertion_point(field_set:sentencepiece.SentencePieceText.score)
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
// NBestSentencePieceText
|
||||
|
||||
// repeated .sentencepiece.SentencePieceText nbests = 1;
|
||||
inline int NBestSentencePieceText::nbests_size() const {
|
||||
return nbests_.size();
|
||||
}
|
||||
inline void NBestSentencePieceText::clear_nbests() {
|
||||
nbests_.Clear();
|
||||
}
|
||||
inline ::sentencepiece::SentencePieceText* NBestSentencePieceText::mutable_nbests(int index) {
|
||||
// @@protoc_insertion_point(field_mutable:sentencepiece.NBestSentencePieceText.nbests)
|
||||
return nbests_.Mutable(index);
|
||||
}
|
||||
inline ::google::protobuf::RepeatedPtrField< ::sentencepiece::SentencePieceText >*
|
||||
NBestSentencePieceText::mutable_nbests() {
|
||||
// @@protoc_insertion_point(field_mutable_list:sentencepiece.NBestSentencePieceText.nbests)
|
||||
return &nbests_;
|
||||
}
|
||||
inline const ::sentencepiece::SentencePieceText& NBestSentencePieceText::nbests(int index) const {
|
||||
// @@protoc_insertion_point(field_get:sentencepiece.NBestSentencePieceText.nbests)
|
||||
return nbests_.Get(index);
|
||||
}
|
||||
inline ::sentencepiece::SentencePieceText* NBestSentencePieceText::add_nbests() {
|
||||
// @@protoc_insertion_point(field_add:sentencepiece.NBestSentencePieceText.nbests)
|
||||
return nbests_.Add();
|
||||
}
|
||||
inline const ::google::protobuf::RepeatedPtrField< ::sentencepiece::SentencePieceText >&
|
||||
NBestSentencePieceText::nbests() const {
|
||||
// @@protoc_insertion_point(field_list:sentencepiece.NBestSentencePieceText.nbests)
|
||||
return nbests_;
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif // __GNUC__
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
|
||||
// @@protoc_insertion_point(namespace_scope)
|
||||
|
||||
} // namespace sentencepiece
|
||||
|
||||
// @@protoc_insertion_point(global_scope)
|
||||
|
||||
#endif // PROTOBUF_INCLUDED_sentencepiece_2eproto
|
3111
src/builtin_pb/sentencepiece_model.pb.cc
Normal file
3111
src/builtin_pb/sentencepiece_model.pb.cc
Normal file
File diff suppressed because it is too large
Load Diff
3567
src/builtin_pb/sentencepiece_model.pb.h
Normal file
3567
src/builtin_pb/sentencepiece_model.pb.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -25,8 +25,6 @@ namespace character {
|
||||
util::Status Trainer::Train() {
|
||||
RETURN_IF_ERROR(status());
|
||||
|
||||
LOG(INFO) << "Starts training with : \n" << trainer_spec_.Utf8DebugString();
|
||||
|
||||
CHECK_OR_RETURN(normalizer_spec_.escape_whitespaces());
|
||||
CHECK_EQ_OR_RETURN(TrainerSpec::CHAR, trainer_spec_.model_type());
|
||||
|
||||
@ -56,8 +54,6 @@ util::Status Trainer::Train() {
|
||||
trainer_spec_.set_vocab_size(final_pieces_.size() + meta_pieces_.size());
|
||||
}
|
||||
|
||||
LOG(INFO) << trainer_spec_.Utf8DebugString();
|
||||
|
||||
return Save();
|
||||
}
|
||||
} // namespace character
|
||||
|
@ -13,6 +13,7 @@
|
||||
// limitations under the License.!
|
||||
|
||||
syntax = "proto2";
|
||||
option optimize_for = LITE_RUNTIME;
|
||||
|
||||
package sentencepiece;
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
// limitations under the License.!
|
||||
|
||||
syntax = "proto2";
|
||||
option optimize_for = LITE_RUNTIME;
|
||||
|
||||
package sentencepiece;
|
||||
|
||||
|
@ -902,7 +902,8 @@ TEST(SentencePieceProcessorTest, EndToEndTest) {
|
||||
EXPECT_NOT_OK(sp.SetDecodeExtraOptions("foo"));
|
||||
|
||||
auto RunTest = [&model_proto](const SentencePieceProcessor &sp) {
|
||||
EXPECT_EQ(model_proto.DebugString(), sp.model_proto().DebugString());
|
||||
EXPECT_EQ(model_proto.SerializeAsString(),
|
||||
sp.model_proto().SerializeAsString());
|
||||
|
||||
EXPECT_EQ(8, sp.GetPieceSize());
|
||||
EXPECT_EQ(0, sp.PieceToId("<unk>"));
|
||||
|
@ -30,6 +30,9 @@ namespace {
|
||||
static constexpr char kDefaultNormalizerName[] = "nmt_nfkc";
|
||||
} // namespace
|
||||
|
||||
// this header is automatically generated.
|
||||
#include "spec_parser.h"
|
||||
|
||||
// static
|
||||
util::Status SentencePieceTrainer::Train(const TrainerSpec &trainer_spec) {
|
||||
NormalizerSpec normalizer_spec;
|
||||
@ -42,6 +45,10 @@ util::Status SentencePieceTrainer::Train(
|
||||
auto copied_normalizer_spec = normalizer_spec;
|
||||
RETURN_IF_ERROR(PopulateNormalizerSpec(&copied_normalizer_spec));
|
||||
auto trainer = TrainerFactory::Create(trainer_spec, copied_normalizer_spec);
|
||||
|
||||
LOG(INFO) << "Starts training with : \n"
|
||||
<< PrintProto(trainer_spec) << PrintProto(copied_normalizer_spec);
|
||||
|
||||
return trainer->Train();
|
||||
}
|
||||
|
||||
@ -55,82 +62,6 @@ NormalizerSpec SentencePieceTrainer::GetNormalizerSpec(
|
||||
return spec;
|
||||
}
|
||||
|
||||
// static
|
||||
util::Status SentencePieceTrainer::SetProtoField(
|
||||
util::min_string_view _field_name, util::min_string_view _value,
|
||||
google::protobuf::Message *message) {
|
||||
const absl::string_view field_name(_field_name.data(), _field_name.size());
|
||||
const absl::string_view value(_value.data(), _value.size());
|
||||
|
||||
const auto *descriptor = message->GetDescriptor();
|
||||
const auto *reflection = message->GetReflection();
|
||||
|
||||
CHECK_OR_RETURN(descriptor != nullptr && reflection != nullptr)
|
||||
<< "reflection is not supported.";
|
||||
|
||||
const auto *field = descriptor->FindFieldByName(
|
||||
std::string(field_name.data(), field_name.size()));
|
||||
|
||||
if (field == nullptr) {
|
||||
return util::StatusBuilder(util::error::NOT_FOUND)
|
||||
<< "unknown field name \"" << field_name << "\" in\n"
|
||||
<< descriptor->DebugString();
|
||||
}
|
||||
|
||||
std::vector<std::string> values = {std::string(value)};
|
||||
if (field->is_repeated())
|
||||
values = string_util::Split(std::string(value), ",");
|
||||
|
||||
#define SET_FIELD(METHOD_TYPE, v) \
|
||||
if (field->is_repeated()) \
|
||||
reflection->Add##METHOD_TYPE(message, field, v); \
|
||||
else \
|
||||
reflection->Set##METHOD_TYPE(message, field, v);
|
||||
|
||||
#define DEFINE_SET_FIELD(PROTO_TYPE, CPP_TYPE, FUNC_PREFIX, METHOD_TYPE, \
|
||||
EMPTY) \
|
||||
case google::protobuf::FieldDescriptor::CPPTYPE_##PROTO_TYPE: { \
|
||||
CPP_TYPE v; \
|
||||
if (!string_util::lexical_cast(value.empty() ? EMPTY : value, &v)) \
|
||||
return util::StatusBuilder(util::error::INVALID_ARGUMENT) \
|
||||
<< "cannot parse \"" << value << "\" as \"" << field->type_name() \
|
||||
<< "\"."; \
|
||||
SET_FIELD(METHOD_TYPE, v); \
|
||||
break; \
|
||||
}
|
||||
|
||||
for (const auto &value : values) {
|
||||
switch (field->cpp_type()) {
|
||||
DEFINE_SET_FIELD(INT32, int32, i, Int32, "");
|
||||
DEFINE_SET_FIELD(INT64, int64, i, Int64, "");
|
||||
DEFINE_SET_FIELD(UINT32, uint32, i, UInt32, "");
|
||||
DEFINE_SET_FIELD(UINT64, uint64, i, UInt64, "");
|
||||
DEFINE_SET_FIELD(DOUBLE, double, d, Double, "");
|
||||
DEFINE_SET_FIELD(FLOAT, float, f, Float, "");
|
||||
DEFINE_SET_FIELD(BOOL, bool, b, Bool, "true");
|
||||
case google::protobuf::FieldDescriptor::CPPTYPE_STRING:
|
||||
SET_FIELD(String, value);
|
||||
break;
|
||||
case google::protobuf::FieldDescriptor::CPPTYPE_ENUM: {
|
||||
const auto *enum_value =
|
||||
field->enum_type()->FindValueByName(string_util::ToUpper(value));
|
||||
if (enum_value == nullptr)
|
||||
return util::StatusBuilder(util::error::INVALID_ARGUMENT)
|
||||
<< "unknown enumeration value of \"" << value
|
||||
<< "\" for field \"" << field->name() << "\".";
|
||||
SET_FIELD(Enum, enum_value);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return util::StatusBuilder(util::error::UNIMPLEMENTED)
|
||||
<< "proto type \"" << field->cpp_type_name()
|
||||
<< "\" is not supported.";
|
||||
}
|
||||
}
|
||||
|
||||
return util::OkStatus();
|
||||
}
|
||||
|
||||
// static
|
||||
util::Status SentencePieceTrainer::MergeSpecsFromArgs(
|
||||
util::min_string_view _args, TrainerSpec *trainer_spec,
|
||||
|
@ -18,12 +18,6 @@
|
||||
#include <string>
|
||||
#include "sentencepiece_processor.h"
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
class Message;
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
namespace sentencepiece {
|
||||
|
||||
class TrainerSpec;
|
||||
@ -63,9 +57,15 @@ class SentencePieceTrainer {
|
||||
// Helper function to set `field_name=value` in `message`.
|
||||
// When `field_name` is repeated, multiple values can be passed
|
||||
// with comma-separated values. `field_name` must not be a nested message.
|
||||
static util::Status SetProtoField(util::min_string_view field_name,
|
||||
util::min_string_view value,
|
||||
google::protobuf::Message *message);
|
||||
// The body of these functions are automatically generated with
|
||||
// data/gen_spec_parser.pl
|
||||
static util::Status SetProtoField(const std::string &name,
|
||||
const std::string &value,
|
||||
TrainerSpec *message);
|
||||
|
||||
static util::Status SetProtoField(const std::string &name,
|
||||
const std::string &value,
|
||||
NormalizerSpec *message);
|
||||
|
||||
SentencePieceTrainer() = delete;
|
||||
~SentencePieceTrainer() = delete;
|
||||
|
@ -96,6 +96,7 @@ TEST(SentencePieceTrainerTest, TrainTest) {
|
||||
}
|
||||
|
||||
TEST(SentencePieceTrainerTest, SetProtoFieldTest) {
|
||||
{
|
||||
TrainerSpec spec;
|
||||
|
||||
EXPECT_NOT_OK(SentencePieceTrainer::SetProtoField("dummy", "1000", &spec));
|
||||
@ -105,25 +106,28 @@ TEST(SentencePieceTrainerTest, SetProtoFieldTest) {
|
||||
EXPECT_NOT_OK(
|
||||
SentencePieceTrainer::SetProtoField("vocab_size", "UNK", &spec));
|
||||
|
||||
EXPECT_OK(SentencePieceTrainer::SetProtoField("input_format", "TSV", &spec));
|
||||
EXPECT_OK(
|
||||
SentencePieceTrainer::SetProtoField("input_format", "TSV", &spec));
|
||||
EXPECT_EQ("TSV", spec.input_format());
|
||||
EXPECT_OK(SentencePieceTrainer::SetProtoField("input_format", "123", &spec));
|
||||
EXPECT_OK(
|
||||
SentencePieceTrainer::SetProtoField("input_format", "123", &spec));
|
||||
EXPECT_EQ("123", spec.input_format());
|
||||
|
||||
EXPECT_OK(SentencePieceTrainer::SetProtoField("split_by_whitespace", "false",
|
||||
&spec));
|
||||
EXPECT_OK(SentencePieceTrainer::SetProtoField("split_by_whitespace",
|
||||
"false", &spec));
|
||||
EXPECT_FALSE(spec.split_by_whitespace());
|
||||
EXPECT_OK(
|
||||
SentencePieceTrainer::SetProtoField("split_by_whitespace", "", &spec));
|
||||
EXPECT_TRUE(spec.split_by_whitespace());
|
||||
|
||||
EXPECT_OK(
|
||||
SentencePieceTrainer::SetProtoField("character_coverage", "0.5", &spec));
|
||||
EXPECT_OK(SentencePieceTrainer::SetProtoField("character_coverage", "0.5",
|
||||
&spec));
|
||||
EXPECT_NEAR(spec.character_coverage(), 0.5, 0.001);
|
||||
EXPECT_NOT_OK(
|
||||
SentencePieceTrainer::SetProtoField("character_coverage", "UNK", &spec));
|
||||
EXPECT_NOT_OK(SentencePieceTrainer::SetProtoField("character_coverage",
|
||||
"UNK", &spec));
|
||||
|
||||
EXPECT_OK(SentencePieceTrainer::SetProtoField("input", "foo,bar,buz", &spec));
|
||||
EXPECT_OK(
|
||||
SentencePieceTrainer::SetProtoField("input", "foo,bar,buz", &spec));
|
||||
EXPECT_EQ(3, spec.input_size());
|
||||
EXPECT_EQ("foo", spec.input(0));
|
||||
EXPECT_EQ("bar", spec.input(1));
|
||||
@ -132,11 +136,20 @@ TEST(SentencePieceTrainerTest, SetProtoFieldTest) {
|
||||
EXPECT_OK(SentencePieceTrainer::SetProtoField("model_type", "BPE", &spec));
|
||||
EXPECT_NOT_OK(
|
||||
SentencePieceTrainer::SetProtoField("model_type", "UNK", &spec));
|
||||
}
|
||||
|
||||
// Nested message is not supported.
|
||||
ModelProto proto;
|
||||
EXPECT_NOT_OK(
|
||||
SentencePieceTrainer::SetProtoField("trainer_spec", "UNK", &proto));
|
||||
{
|
||||
NormalizerSpec spec;
|
||||
EXPECT_OK(SentencePieceTrainer::SetProtoField("add_dummy_prefix", "false",
|
||||
&spec));
|
||||
EXPECT_FALSE(spec.add_dummy_prefix());
|
||||
|
||||
EXPECT_OK(SentencePieceTrainer::SetProtoField("escape_whitespaces", "false",
|
||||
&spec));
|
||||
EXPECT_FALSE(spec.escape_whitespaces());
|
||||
|
||||
EXPECT_NOT_OK(SentencePieceTrainer::SetProtoField("dummy", "1000", &spec));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(SentencePieceTrainerTest, MergeSpecsFromArgs) {
|
||||
|
409
src/spec_parser.h
Normal file
409
src/spec_parser.h
Normal file
@ -0,0 +1,409 @@
|
||||
namespace {
|
||||
inline std::string PrintProto(const TrainerSpec &message) {
|
||||
std::ostringstream os;
|
||||
|
||||
os << "TrainerSpec {\n";
|
||||
for (const auto &v : message.input())
|
||||
os << " input: " << v << "\n";
|
||||
os << " input_format: " << message.input_format() << "\n";
|
||||
os << " model_prefix: " << message.model_prefix() << "\n";
|
||||
static const std::map<TrainerSpec::ModelType, std::string> kModelType_Map = { {TrainerSpec::UNIGRAM, "UNIGRAM"}, {TrainerSpec::BPE, "BPE"}, {TrainerSpec::WORD, "WORD"}, {TrainerSpec::CHAR, "CHAR"}, };
|
||||
{
|
||||
const auto it = kModelType_Map.find(message.model_type());
|
||||
if (it == kModelType_Map.end())
|
||||
os << " model_type: unknown\n";
|
||||
else
|
||||
os << " model_type: " << it->second << "\n";
|
||||
}
|
||||
os << " vocab_size: " << message.vocab_size() << "\n";
|
||||
for (const auto &v : message.accept_language())
|
||||
os << " accept_language: " << v << "\n";
|
||||
os << " self_test_sample_size: " << message.self_test_sample_size() << "\n";
|
||||
os << " character_coverage: " << message.character_coverage() << "\n";
|
||||
os << " input_sentence_size: " << message.input_sentence_size() << "\n";
|
||||
os << " shuffle_input_sentence: " << message.shuffle_input_sentence() << "\n";
|
||||
os << " mining_sentence_size: " << message.mining_sentence_size() << "\n";
|
||||
os << " training_sentence_size: " << message.training_sentence_size() << "\n";
|
||||
os << " seed_sentencepiece_size: " << message.seed_sentencepiece_size() << "\n";
|
||||
os << " shrinking_factor: " << message.shrinking_factor() << "\n";
|
||||
os << " max_sentence_length: " << message.max_sentence_length() << "\n";
|
||||
os << " num_threads: " << message.num_threads() << "\n";
|
||||
os << " num_sub_iterations: " << message.num_sub_iterations() << "\n";
|
||||
os << " max_sentencepiece_length: " << message.max_sentencepiece_length() << "\n";
|
||||
os << " split_by_unicode_script: " << message.split_by_unicode_script() << "\n";
|
||||
os << " split_by_number: " << message.split_by_number() << "\n";
|
||||
os << " split_by_whitespace: " << message.split_by_whitespace() << "\n";
|
||||
for (const auto &v : message.control_symbols())
|
||||
os << " control_symbols: " << v << "\n";
|
||||
for (const auto &v : message.user_defined_symbols())
|
||||
os << " user_defined_symbols: " << v << "\n";
|
||||
os << " hard_vocab_limit: " << message.hard_vocab_limit() << "\n";
|
||||
os << " use_all_vocab: " << message.use_all_vocab() << "\n";
|
||||
os << " unk_id: " << message.unk_id() << "\n";
|
||||
os << " bos_id: " << message.bos_id() << "\n";
|
||||
os << " eos_id: " << message.eos_id() << "\n";
|
||||
os << " pad_id: " << message.pad_id() << "\n";
|
||||
os << " unk_piece: " << message.unk_piece() << "\n";
|
||||
os << " bos_piece: " << message.bos_piece() << "\n";
|
||||
os << " eos_piece: " << message.eos_piece() << "\n";
|
||||
os << " pad_piece: " << message.pad_piece() << "\n";
|
||||
os << " unk_surface: " << message.unk_surface() << "\n";
|
||||
os << "}\n";
|
||||
|
||||
return os.str();
|
||||
}
|
||||
|
||||
inline std::string PrintProto(const NormalizerSpec &message) {
|
||||
std::ostringstream os;
|
||||
|
||||
os << "NormalizerSpec {\n";
|
||||
os << " name: " << message.name() << "\n";
|
||||
os << " add_dummy_prefix: " << message.add_dummy_prefix() << "\n";
|
||||
os << " remove_extra_whitespaces: " << message.remove_extra_whitespaces() << "\n";
|
||||
os << " escape_whitespaces: " << message.escape_whitespaces() << "\n";
|
||||
os << " normalization_rule_tsv: " << message.normalization_rule_tsv() << "\n";
|
||||
os << "}\n";
|
||||
|
||||
return os.str();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
util::Status SentencePieceTrainer::SetProtoField(const std::string& name, const std::string& value, TrainerSpec *message) {
|
||||
CHECK_OR_RETURN(message);
|
||||
|
||||
if (name == "input") {
|
||||
for (const auto &val : string_util::Split(value, ",")) {
|
||||
message->add_input(val);
|
||||
}
|
||||
return util::OkStatus();
|
||||
}
|
||||
|
||||
if (name == "input_format") {
|
||||
const auto &val = value;
|
||||
message->set_input_format(val);
|
||||
return util::OkStatus();
|
||||
}
|
||||
|
||||
if (name == "model_prefix") {
|
||||
const auto &val = value;
|
||||
message->set_model_prefix(val);
|
||||
return util::OkStatus();
|
||||
}
|
||||
|
||||
static const std::map <std::string, TrainerSpec::ModelType> kModelType_Map = { {"UNIGRAM", TrainerSpec::UNIGRAM}, {"BPE", TrainerSpec::BPE}, {"WORD", TrainerSpec::WORD}, {"CHAR", TrainerSpec::CHAR}, };
|
||||
|
||||
if (name == "model_type") {
|
||||
const auto &val = value;
|
||||
const auto it = kModelType_Map.find(string_util::ToUpper(val));
|
||||
if (it == kModelType_Map.end())
|
||||
return util::StatusBuilder(util::error::INVALID_ARGUMENT) << "unknown enumeration value of \"" << val << "\" as ModelType.";
|
||||
message->set_model_type(it->second);
|
||||
return util::OkStatus();
|
||||
}
|
||||
|
||||
if (name == "vocab_size") {
|
||||
const auto &val = value;
|
||||
int32 v;
|
||||
if (!string_util::lexical_cast(val.empty() ? "" : val, &v))
|
||||
return util::StatusBuilder(util::error::INVALID_ARGUMENT) << "cannot parse \"" << val << "\" as int32.";
|
||||
message->set_vocab_size(v);
|
||||
return util::OkStatus();
|
||||
}
|
||||
|
||||
if (name == "accept_language") {
|
||||
for (const auto &val : string_util::Split(value, ",")) {
|
||||
message->add_accept_language(val);
|
||||
}
|
||||
return util::OkStatus();
|
||||
}
|
||||
|
||||
if (name == "self_test_sample_size") {
|
||||
const auto &val = value;
|
||||
int32 v;
|
||||
if (!string_util::lexical_cast(val.empty() ? "" : val, &v))
|
||||
return util::StatusBuilder(util::error::INVALID_ARGUMENT) << "cannot parse \"" << val << "\" as int32.";
|
||||
message->set_self_test_sample_size(v);
|
||||
return util::OkStatus();
|
||||
}
|
||||
|
||||
if (name == "character_coverage") {
|
||||
const auto &val = value;
|
||||
float v;
|
||||
if (!string_util::lexical_cast(val.empty() ? "" : val, &v))
|
||||
return util::StatusBuilder(util::error::INVALID_ARGUMENT) << "cannot parse \"" << val << "\" as float.";
|
||||
message->set_character_coverage(v);
|
||||
return util::OkStatus();
|
||||
}
|
||||
|
||||
if (name == "input_sentence_size") {
|
||||
const auto &val = value;
|
||||
int32 v;
|
||||
if (!string_util::lexical_cast(val.empty() ? "" : val, &v))
|
||||
return util::StatusBuilder(util::error::INVALID_ARGUMENT) << "cannot parse \"" << val << "\" as int32.";
|
||||
message->set_input_sentence_size(v);
|
||||
return util::OkStatus();
|
||||
}
|
||||
|
||||
if (name == "shuffle_input_sentence") {
|
||||
const auto &val = value;
|
||||
bool v;
|
||||
if (!string_util::lexical_cast(val.empty() ? "true" : val, &v))
|
||||
return util::StatusBuilder(util::error::INVALID_ARGUMENT) << "cannot parse \"" << val << "\" as bool.";
|
||||
message->set_shuffle_input_sentence(v);
|
||||
return util::OkStatus();
|
||||
}
|
||||
|
||||
if (name == "mining_sentence_size") {
|
||||
const auto &val = value;
|
||||
int32 v;
|
||||
if (!string_util::lexical_cast(val.empty() ? "" : val, &v))
|
||||
return util::StatusBuilder(util::error::INVALID_ARGUMENT) << "cannot parse \"" << val << "\" as int32.";
|
||||
message->set_mining_sentence_size(v);
|
||||
return util::OkStatus();
|
||||
}
|
||||
|
||||
if (name == "training_sentence_size") {
|
||||
const auto &val = value;
|
||||
int32 v;
|
||||
if (!string_util::lexical_cast(val.empty() ? "" : val, &v))
|
||||
return util::StatusBuilder(util::error::INVALID_ARGUMENT) << "cannot parse \"" << val << "\" as int32.";
|
||||
message->set_training_sentence_size(v);
|
||||
return util::OkStatus();
|
||||
}
|
||||
|
||||
if (name == "seed_sentencepiece_size") {
|
||||
const auto &val = value;
|
||||
int32 v;
|
||||
if (!string_util::lexical_cast(val.empty() ? "" : val, &v))
|
||||
return util::StatusBuilder(util::error::INVALID_ARGUMENT) << "cannot parse \"" << val << "\" as int32.";
|
||||
message->set_seed_sentencepiece_size(v);
|
||||
return util::OkStatus();
|
||||
}
|
||||
|
||||
if (name == "shrinking_factor") {
|
||||
const auto &val = value;
|
||||
float v;
|
||||
if (!string_util::lexical_cast(val.empty() ? "" : val, &v))
|
||||
return util::StatusBuilder(util::error::INVALID_ARGUMENT) << "cannot parse \"" << val << "\" as float.";
|
||||
message->set_shrinking_factor(v);
|
||||
return util::OkStatus();
|
||||
}
|
||||
|
||||
if (name == "max_sentence_length") {
|
||||
const auto &val = value;
|
||||
int32 v;
|
||||
if (!string_util::lexical_cast(val.empty() ? "" : val, &v))
|
||||
return util::StatusBuilder(util::error::INVALID_ARGUMENT) << "cannot parse \"" << val << "\" as int32.";
|
||||
message->set_max_sentence_length(v);
|
||||
return util::OkStatus();
|
||||
}
|
||||
|
||||
if (name == "num_threads") {
|
||||
const auto &val = value;
|
||||
int32 v;
|
||||
if (!string_util::lexical_cast(val.empty() ? "" : val, &v))
|
||||
return util::StatusBuilder(util::error::INVALID_ARGUMENT) << "cannot parse \"" << val << "\" as int32.";
|
||||
message->set_num_threads(v);
|
||||
return util::OkStatus();
|
||||
}
|
||||
|
||||
if (name == "num_sub_iterations") {
|
||||
const auto &val = value;
|
||||
int32 v;
|
||||
if (!string_util::lexical_cast(val.empty() ? "" : val, &v))
|
||||
return util::StatusBuilder(util::error::INVALID_ARGUMENT) << "cannot parse \"" << val << "\" as int32.";
|
||||
message->set_num_sub_iterations(v);
|
||||
return util::OkStatus();
|
||||
}
|
||||
|
||||
if (name == "max_sentencepiece_length") {
|
||||
const auto &val = value;
|
||||
int32 v;
|
||||
if (!string_util::lexical_cast(val.empty() ? "" : val, &v))
|
||||
return util::StatusBuilder(util::error::INVALID_ARGUMENT) << "cannot parse \"" << val << "\" as int32.";
|
||||
message->set_max_sentencepiece_length(v);
|
||||
return util::OkStatus();
|
||||
}
|
||||
|
||||
if (name == "split_by_unicode_script") {
|
||||
const auto &val = value;
|
||||
bool v;
|
||||
if (!string_util::lexical_cast(val.empty() ? "true" : val, &v))
|
||||
return util::StatusBuilder(util::error::INVALID_ARGUMENT) << "cannot parse \"" << val << "\" as bool.";
|
||||
message->set_split_by_unicode_script(v);
|
||||
return util::OkStatus();
|
||||
}
|
||||
|
||||
if (name == "split_by_number") {
|
||||
const auto &val = value;
|
||||
bool v;
|
||||
if (!string_util::lexical_cast(val.empty() ? "true" : val, &v))
|
||||
return util::StatusBuilder(util::error::INVALID_ARGUMENT) << "cannot parse \"" << val << "\" as bool.";
|
||||
message->set_split_by_number(v);
|
||||
return util::OkStatus();
|
||||
}
|
||||
|
||||
if (name == "split_by_whitespace") {
|
||||
const auto &val = value;
|
||||
bool v;
|
||||
if (!string_util::lexical_cast(val.empty() ? "true" : val, &v))
|
||||
return util::StatusBuilder(util::error::INVALID_ARGUMENT) << "cannot parse \"" << val << "\" as bool.";
|
||||
message->set_split_by_whitespace(v);
|
||||
return util::OkStatus();
|
||||
}
|
||||
|
||||
if (name == "control_symbols") {
|
||||
for (const auto &val : string_util::Split(value, ",")) {
|
||||
message->add_control_symbols(val);
|
||||
}
|
||||
return util::OkStatus();
|
||||
}
|
||||
|
||||
if (name == "user_defined_symbols") {
|
||||
for (const auto &val : string_util::Split(value, ",")) {
|
||||
message->add_user_defined_symbols(val);
|
||||
}
|
||||
return util::OkStatus();
|
||||
}
|
||||
|
||||
if (name == "hard_vocab_limit") {
|
||||
const auto &val = value;
|
||||
bool v;
|
||||
if (!string_util::lexical_cast(val.empty() ? "true" : val, &v))
|
||||
return util::StatusBuilder(util::error::INVALID_ARGUMENT) << "cannot parse \"" << val << "\" as bool.";
|
||||
message->set_hard_vocab_limit(v);
|
||||
return util::OkStatus();
|
||||
}
|
||||
|
||||
if (name == "use_all_vocab") {
|
||||
const auto &val = value;
|
||||
bool v;
|
||||
if (!string_util::lexical_cast(val.empty() ? "true" : val, &v))
|
||||
return util::StatusBuilder(util::error::INVALID_ARGUMENT) << "cannot parse \"" << val << "\" as bool.";
|
||||
message->set_use_all_vocab(v);
|
||||
return util::OkStatus();
|
||||
}
|
||||
|
||||
if (name == "unk_id") {
|
||||
const auto &val = value;
|
||||
int32 v;
|
||||
if (!string_util::lexical_cast(val.empty() ? "" : val, &v))
|
||||
return util::StatusBuilder(util::error::INVALID_ARGUMENT) << "cannot parse \"" << val << "\" as int32.";
|
||||
message->set_unk_id(v);
|
||||
return util::OkStatus();
|
||||
}
|
||||
|
||||
if (name == "bos_id") {
|
||||
const auto &val = value;
|
||||
int32 v;
|
||||
if (!string_util::lexical_cast(val.empty() ? "" : val, &v))
|
||||
return util::StatusBuilder(util::error::INVALID_ARGUMENT) << "cannot parse \"" << val << "\" as int32.";
|
||||
message->set_bos_id(v);
|
||||
return util::OkStatus();
|
||||
}
|
||||
|
||||
if (name == "eos_id") {
|
||||
const auto &val = value;
|
||||
int32 v;
|
||||
if (!string_util::lexical_cast(val.empty() ? "" : val, &v))
|
||||
return util::StatusBuilder(util::error::INVALID_ARGUMENT) << "cannot parse \"" << val << "\" as int32.";
|
||||
message->set_eos_id(v);
|
||||
return util::OkStatus();
|
||||
}
|
||||
|
||||
if (name == "pad_id") {
|
||||
const auto &val = value;
|
||||
int32 v;
|
||||
if (!string_util::lexical_cast(val.empty() ? "" : val, &v))
|
||||
return util::StatusBuilder(util::error::INVALID_ARGUMENT) << "cannot parse \"" << val << "\" as int32.";
|
||||
message->set_pad_id(v);
|
||||
return util::OkStatus();
|
||||
}
|
||||
|
||||
if (name == "unk_piece") {
|
||||
const auto &val = value;
|
||||
message->set_unk_piece(val);
|
||||
return util::OkStatus();
|
||||
}
|
||||
|
||||
if (name == "bos_piece") {
|
||||
const auto &val = value;
|
||||
message->set_bos_piece(val);
|
||||
return util::OkStatus();
|
||||
}
|
||||
|
||||
if (name == "eos_piece") {
|
||||
const auto &val = value;
|
||||
message->set_eos_piece(val);
|
||||
return util::OkStatus();
|
||||
}
|
||||
|
||||
if (name == "pad_piece") {
|
||||
const auto &val = value;
|
||||
message->set_pad_piece(val);
|
||||
return util::OkStatus();
|
||||
}
|
||||
|
||||
if (name == "unk_surface") {
|
||||
const auto &val = value;
|
||||
message->set_unk_surface(val);
|
||||
return util::OkStatus();
|
||||
}
|
||||
|
||||
return util::StatusBuilder(util::error::NOT_FOUND)
|
||||
<< "unknown field name \"" << name << "\" in TrainerSpec.";
|
||||
}
|
||||
|
||||
util::Status SentencePieceTrainer::SetProtoField(const std::string& name, const std::string& value, NormalizerSpec *message) {
|
||||
CHECK_OR_RETURN(message);
|
||||
|
||||
if (name == "name") {
|
||||
const auto &val = value;
|
||||
message->set_name(val);
|
||||
return util::OkStatus();
|
||||
}
|
||||
|
||||
if (name == "precompiled_charsmap") {
|
||||
const auto &val = value;
|
||||
message->set_precompiled_charsmap(val.data(), val.size());
|
||||
return util::OkStatus();
|
||||
}
|
||||
|
||||
if (name == "add_dummy_prefix") {
|
||||
const auto &val = value;
|
||||
bool v;
|
||||
if (!string_util::lexical_cast(val.empty() ? "true" : val, &v))
|
||||
return util::StatusBuilder(util::error::INVALID_ARGUMENT) << "cannot parse \"" << val << "\" as bool.";
|
||||
message->set_add_dummy_prefix(v);
|
||||
return util::OkStatus();
|
||||
}
|
||||
|
||||
if (name == "remove_extra_whitespaces") {
|
||||
const auto &val = value;
|
||||
bool v;
|
||||
if (!string_util::lexical_cast(val.empty() ? "true" : val, &v))
|
||||
return util::StatusBuilder(util::error::INVALID_ARGUMENT) << "cannot parse \"" << val << "\" as bool.";
|
||||
message->set_remove_extra_whitespaces(v);
|
||||
return util::OkStatus();
|
||||
}
|
||||
|
||||
if (name == "escape_whitespaces") {
|
||||
const auto &val = value;
|
||||
bool v;
|
||||
if (!string_util::lexical_cast(val.empty() ? "true" : val, &v))
|
||||
return util::StatusBuilder(util::error::INVALID_ARGUMENT) << "cannot parse \"" << val << "\" as bool.";
|
||||
message->set_escape_whitespaces(v);
|
||||
return util::OkStatus();
|
||||
}
|
||||
|
||||
if (name == "normalization_rule_tsv") {
|
||||
const auto &val = value;
|
||||
message->set_normalization_rule_tsv(val);
|
||||
return util::OkStatus();
|
||||
}
|
||||
|
||||
return util::StatusBuilder(util::error::NOT_FOUND)
|
||||
<< "unknown field name \"" << name << "\" in NormalizerSpec.";
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ int main(int argc, char *argv[]) {
|
||||
} else if (FLAGS_output_format == "proto") {
|
||||
process = [&](const std::vector<std::string> &pieces) {
|
||||
CHECK_OK(sp.Decode(pieces, &spt));
|
||||
output->WriteLine(spt.Utf8DebugString());
|
||||
// output->WriteLine(spt.Utf8DebugString());
|
||||
};
|
||||
} else {
|
||||
LOG(FATAL) << "Unknown output format: " << FLAGS_output_format;
|
||||
@ -79,7 +79,7 @@ int main(int argc, char *argv[]) {
|
||||
} else if (FLAGS_output_format == "proto") {
|
||||
process = [&](const std::vector<std::string> &pieces) {
|
||||
CHECK_OK(sp.Decode(ToIds(pieces), &spt));
|
||||
output->WriteLine(spt.Utf8DebugString());
|
||||
// output->WriteLine(spt.Utf8DebugString());
|
||||
};
|
||||
} else {
|
||||
LOG(FATAL) << "Unknown output format: " << FLAGS_output_format;
|
||||
|
@ -94,7 +94,7 @@ int main(int argc, char *argv[]) {
|
||||
} else if (FLAGS_output_format == "proto") {
|
||||
process = [&](const std::string &line) {
|
||||
CHECK_OK(sp.Encode(line, &spt));
|
||||
output->WriteLine(spt.Utf8DebugString());
|
||||
// output->WriteLine(spt.Utf8DebugString());
|
||||
};
|
||||
} else if (FLAGS_output_format == "sample_piece") {
|
||||
process = [&](const std::string &line) {
|
||||
@ -109,7 +109,7 @@ int main(int argc, char *argv[]) {
|
||||
} else if (FLAGS_output_format == "sample_proto") {
|
||||
process = [&](const std::string &line) {
|
||||
CHECK_OK(sp.SampleEncode(line, FLAGS_nbest_size, FLAGS_alpha, &spt));
|
||||
output->WriteLine(spt.Utf8DebugString());
|
||||
// output->WriteLine(spt.Utf8DebugString());
|
||||
};
|
||||
} else if (FLAGS_output_format == "nbest_piece") {
|
||||
process = [&](const std::string &line) {
|
||||
@ -128,7 +128,7 @@ int main(int argc, char *argv[]) {
|
||||
} else if (FLAGS_output_format == "nbest_proto") {
|
||||
process = [&](const std::string &line) {
|
||||
CHECK_OK(sp.NBestEncode(line, FLAGS_nbest_size, &nbest_spt));
|
||||
output->WriteLine(nbest_spt.Utf8DebugString());
|
||||
// output->WriteLine(nbest_spt.Utf8DebugString());
|
||||
};
|
||||
} else {
|
||||
LOG(FATAL) << "Unknown output format: " << FLAGS_output_format;
|
||||
|
@ -1,3 +1,5 @@
|
||||
|
||||
|
||||
// Copyright 2016 Google Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -37,7 +39,7 @@ int main(int argc, char *argv[]) {
|
||||
output->WriteLine(os.str());
|
||||
}
|
||||
} else if (FLAGS_output_format == "proto") {
|
||||
output->Write(sp.model_proto().Utf8DebugString());
|
||||
// output->Write(sp.model_proto().Utf8DebugString());
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -102,7 +102,7 @@ class SentenceSelector {
|
||||
} else {
|
||||
LOG(INFO)
|
||||
<< "First " << spec_->input_sentence_size()
|
||||
<< " sentences are select. Remaining sentences are discarded.";
|
||||
<< " sentences are selected. Remaining sentences are discarded.";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -452,8 +452,6 @@ TrainerModel::SentencePieces Trainer::FinalizeSentencePieces(
|
||||
util::Status Trainer::Train() {
|
||||
RETURN_IF_ERROR(status());
|
||||
|
||||
LOG(INFO) << "Starts training with : \n" << trainer_spec_.Utf8DebugString();
|
||||
|
||||
CHECK_EQ_OR_RETURN(TrainerSpec::UNIGRAM, trainer_spec_.model_type());
|
||||
CHECK_OR_RETURN(normalizer_spec_.escape_whitespaces());
|
||||
|
||||
|
@ -28,8 +28,6 @@ namespace word {
|
||||
util::Status Trainer::Train() {
|
||||
RETURN_IF_ERROR(status());
|
||||
|
||||
LOG(INFO) << "Starts training with : \n" << trainer_spec_.Utf8DebugString();
|
||||
|
||||
CHECK_OR_RETURN(normalizer_spec_.escape_whitespaces());
|
||||
CHECK_EQ_OR_RETURN(TrainerSpec::WORD, trainer_spec_.model_type());
|
||||
|
||||
|
@ -17,7 +17,6 @@
|
||||
set -e # exit immediately on error
|
||||
set -x # display all commands
|
||||
|
||||
PROTOBUF_VERSION=3.6.1
|
||||
CMAKE_VERSION=3.12.0
|
||||
|
||||
run_docker() {
|
||||
@ -47,7 +46,6 @@ build_tf_wrapper() {
|
||||
-fPIC ${TF_CFLAGS[@]} -O2 \
|
||||
-D_GLIBCXX_USE_CXX11_ABI=0 \
|
||||
-Wl,--whole-archive \
|
||||
/usr/local/lib/libprotobuf.a \
|
||||
/usr/local/lib/libsentencepiece.a \
|
||||
-Wl,--no-whole-archive \
|
||||
sentencepiece_processor_ops.cc \
|
||||
@ -66,16 +64,6 @@ build() {
|
||||
apt-get update
|
||||
apt-get install -y curl build-essential cmake git pkg-config python-pip python3-pip
|
||||
|
||||
# Install protobuf
|
||||
curl -L -O https://github.com/google/protobuf/releases/download/v${PROTOBUF_VERSION}/protobuf-cpp-${PROTOBUF_VERSION}.tar.gz
|
||||
tar zxfv protobuf-cpp-${PROTOBUF_VERSION}.tar.gz
|
||||
cd protobuf-${PROTOBUF_VERSION}
|
||||
./configure --disable-shared --with-pic
|
||||
make CXXFLAGS+="-std=c++11 -O3 -D_GLIBCXX_USE_CXX11_ABI=0" \
|
||||
CFLAGS+="-std=c++11 -O3 -D_GLIBCXX_USE_CXX11_ABI=0" -j4
|
||||
make install
|
||||
cd ..
|
||||
|
||||
# Install sentencepiece
|
||||
cmake ../.. -DSPM_ENABLE_SHARED=OFF -DSPM_ENABLE_TENSORFLOW_SHARED=ON
|
||||
make -j4
|
||||
|
@ -17,8 +17,6 @@
|
||||
set -e # exit immediately on error
|
||||
set -x # display all commands
|
||||
|
||||
PROTOBUF_VERSION=3.6.1
|
||||
|
||||
build_tf_wrapper() {
|
||||
if [ "$1" != "" ]; then
|
||||
pkg_name="==$1"
|
||||
@ -36,7 +34,6 @@ build_tf_wrapper() {
|
||||
-fPIC ${TF_CFLAGS[@]} -O2 \
|
||||
-D_GLIBCXX_USE_CXX11_ABI=0 \
|
||||
-Wl,-all_load \
|
||||
/usr/local/lib/libprotobuf.a \
|
||||
/usr/local/lib/libsentencepiece.a \
|
||||
-Wl,-noall_load \
|
||||
sentencepiece_processor_ops.cc \
|
||||
@ -52,16 +49,6 @@ build() {
|
||||
mkdir -p build
|
||||
cd build
|
||||
|
||||
# Install protobuf
|
||||
curl -L -O https://github.com/google/protobuf/releases/download/v${PROTOBUF_VERSION}/protobuf-cpp-${PROTOBUF_VERSION}.tar.gz
|
||||
tar zxfv protobuf-cpp-${PROTOBUF_VERSION}.tar.gz
|
||||
cd protobuf-${PROTOBUF_VERSION}
|
||||
./configure --disable-shared --with-pic
|
||||
make CXXFLAGS+="-std=c++11 -O3 -D_GLIBCXX_USE_CXX11_ABI=0" \
|
||||
CFLAGS+="-std=c++11 -O3 -D_GLIBCXX_USE_CXX11_ABI=0" -j4
|
||||
make install || true
|
||||
cd ..
|
||||
|
||||
# Install sentencepiece
|
||||
cmake ../.. -DSPM_ENABLE_SHARED=OFF -DSPM_ENABLE_TENSORFLOW_SHARED=ON
|
||||
make -j4 VERBOSE=1
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
8
test.bat
8
test.bat
@ -1,4 +1,3 @@
|
||||
set PROTOBUF_VERSION=3.6.1
|
||||
set PLATFORM=%1
|
||||
if "%PLATFORM%"=="" set PLATFORM=x64
|
||||
set PLATFORM_PREFIX=
|
||||
@ -11,13 +10,6 @@ set LIBRARY_PATH=%CURRENT_PATH%build\root
|
||||
mkdir build
|
||||
cd build
|
||||
|
||||
curl -O -L https://github.com/google/protobuf/releases/download/v%PROTOBUF_VERSION%/protobuf-cpp-%PROTOBUF_VERSION%.zip
|
||||
unzip protobuf-cpp-%PROTOBUF_VERSION%.zip
|
||||
cd protobuf-%PROTOBUF_VERSION%\cmake
|
||||
cmake . -A %PLATFORM% -DCMAKE_INSTALL_PREFIX=%LIBRARY_PATH% || goto :error
|
||||
cmake --build . --config Release --target install || goto :error
|
||||
|
||||
cd ..\..
|
||||
cmake .. -A %PLATFORM% -DSPM_BUILD_TEST=ON -DSPM_ENABLE_SHARED=OFF -DCMAKE_INSTALL_PREFIX=%LIBRARY_PATH%
|
||||
cmake --build . --config Release --target install || goto :error
|
||||
ctest -C Release || goto :error
|
||||
|
5
test.sh
5
test.sh
@ -19,8 +19,7 @@ set -x # display all commands
|
||||
|
||||
setup_ubuntu() {
|
||||
apt-get update
|
||||
apt-get install -y build-essential cmake git \
|
||||
pkg-config libprotobuf-c++ protobuf-compiler libprotobuf-dev python-pip python3-pip
|
||||
apt-get install -y build-essential cmake git pkg-config python-pip python3-pip
|
||||
|
||||
. /etc/os-release
|
||||
if [ "${VERSION_ID}" = "14.04" ]; then
|
||||
@ -34,7 +33,7 @@ setup_debian() {
|
||||
|
||||
setup_fedora() {
|
||||
dnf update -y
|
||||
dnf install -y rpm-build gcc-c++ make protobuf-devel cmake pkg-config python-pip python-devel
|
||||
dnf install -y rpm-build gcc-c++ make cmake pkg-config python-pip python-devel
|
||||
}
|
||||
|
||||
build_generic() {
|
||||
|
5
third_party/CMakeLists.txt
vendored
5
third_party/CMakeLists.txt
vendored
@ -1 +1,4 @@
|
||||
include_directories(absl/strings darts_clone esaxx)
|
||||
include_directories(absl/strings darts_clone esaxx protobuf-lite)
|
||||
|
||||
|
||||
|
||||
|
415
third_party/protobuf-lite/arena.cc
vendored
Normal file
415
third_party/protobuf-lite/arena.cc
vendored
Normal file
@ -0,0 +1,415 @@
|
||||
// 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.
|
||||
|
||||
#include <google/protobuf/arena.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
|
||||
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
#include <sanitizer/asan_interface.h>
|
||||
#endif // ADDRESS_SANITIZER
|
||||
|
||||
#include <google/protobuf/stubs/port.h>
|
||||
|
||||
namespace google {
|
||||
static const size_t kMinCleanupListElements = 8;
|
||||
static const size_t kMaxCleanupListElements = 64; // 1kB on 64-bit.
|
||||
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
|
||||
std::atomic<int64> ArenaImpl::lifecycle_id_generator_;
|
||||
#if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL)
|
||||
ArenaImpl::ThreadCache& ArenaImpl::thread_cache() {
|
||||
static internal::ThreadLocalStorage<ThreadCache>* thread_cache_ =
|
||||
new internal::ThreadLocalStorage<ThreadCache>();
|
||||
return *thread_cache_->Get();
|
||||
}
|
||||
#elif defined(PROTOBUF_USE_DLLS)
|
||||
ArenaImpl::ThreadCache& ArenaImpl::thread_cache() {
|
||||
static GOOGLE_THREAD_LOCAL ThreadCache thread_cache_ = { -1, NULL };
|
||||
return thread_cache_;
|
||||
}
|
||||
#else
|
||||
GOOGLE_THREAD_LOCAL ArenaImpl::ThreadCache ArenaImpl::thread_cache_ = {-1, NULL};
|
||||
#endif
|
||||
|
||||
void ArenaImpl::Init() {
|
||||
lifecycle_id_ =
|
||||
lifecycle_id_generator_.fetch_add(1, std::memory_order_relaxed);
|
||||
hint_.store(nullptr, std::memory_order_relaxed);
|
||||
threads_.store(nullptr, std::memory_order_relaxed);
|
||||
|
||||
if (initial_block_) {
|
||||
// Thread which calls Init() owns the first block. This allows the
|
||||
// single-threaded case to allocate on the first block without having to
|
||||
// perform atomic operations.
|
||||
new (initial_block_) Block(options_.initial_block_size, NULL);
|
||||
SerialArena* serial =
|
||||
SerialArena::New(initial_block_, &thread_cache(), this);
|
||||
serial->set_next(NULL);
|
||||
threads_.store(serial, std::memory_order_relaxed);
|
||||
space_allocated_.store(options_.initial_block_size,
|
||||
std::memory_order_relaxed);
|
||||
CacheSerialArena(serial);
|
||||
} else {
|
||||
space_allocated_.store(0, std::memory_order_relaxed);
|
||||
}
|
||||
}
|
||||
|
||||
ArenaImpl::~ArenaImpl() {
|
||||
// Have to do this in a first pass, because some of the destructors might
|
||||
// refer to memory in other blocks.
|
||||
CleanupList();
|
||||
FreeBlocks();
|
||||
}
|
||||
|
||||
uint64 ArenaImpl::Reset() {
|
||||
// Have to do this in a first pass, because some of the destructors might
|
||||
// refer to memory in other blocks.
|
||||
CleanupList();
|
||||
uint64 space_allocated = FreeBlocks();
|
||||
Init();
|
||||
|
||||
return space_allocated;
|
||||
}
|
||||
|
||||
ArenaImpl::Block* ArenaImpl::NewBlock(Block* last_block, size_t min_bytes) {
|
||||
size_t size;
|
||||
if (last_block) {
|
||||
// Double the current block size, up to a limit.
|
||||
size = std::min(2 * last_block->size(), options_.max_block_size);
|
||||
} else {
|
||||
size = options_.start_block_size;
|
||||
}
|
||||
// Verify that min_bytes + kBlockHeaderSize won't overflow.
|
||||
GOOGLE_CHECK_LE(min_bytes, std::numeric_limits<size_t>::max() - kBlockHeaderSize);
|
||||
size = std::max(size, kBlockHeaderSize + min_bytes);
|
||||
|
||||
void* mem = options_.block_alloc(size);
|
||||
Block* b = new (mem) Block(size, last_block);
|
||||
space_allocated_.fetch_add(size, std::memory_order_relaxed);
|
||||
return b;
|
||||
}
|
||||
|
||||
ArenaImpl::Block::Block(size_t size, Block* next)
|
||||
: next_(next), pos_(kBlockHeaderSize), size_(size) {}
|
||||
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE
|
||||
void ArenaImpl::SerialArena::AddCleanupFallback(void* elem,
|
||||
void (*cleanup)(void*)) {
|
||||
size_t size = cleanup_ ? cleanup_->size * 2 : kMinCleanupListElements;
|
||||
size = std::min(size, kMaxCleanupListElements);
|
||||
size_t bytes = internal::AlignUpTo8(CleanupChunk::SizeOf(size));
|
||||
CleanupChunk* list = reinterpret_cast<CleanupChunk*>(AllocateAligned(bytes));
|
||||
list->next = cleanup_;
|
||||
list->size = size;
|
||||
|
||||
cleanup_ = list;
|
||||
cleanup_ptr_ = &list->nodes[0];
|
||||
cleanup_limit_ = &list->nodes[size];
|
||||
|
||||
AddCleanup(elem, cleanup);
|
||||
}
|
||||
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_FUNC_ALIGN(32)
|
||||
void* ArenaImpl::AllocateAligned(size_t n) {
|
||||
SerialArena* arena;
|
||||
if (GOOGLE_PREDICT_TRUE(GetSerialArenaFast(&arena))) {
|
||||
return arena->AllocateAligned(n);
|
||||
} else {
|
||||
return AllocateAlignedFallback(n);
|
||||
}
|
||||
}
|
||||
|
||||
void* ArenaImpl::AllocateAlignedAndAddCleanup(size_t n,
|
||||
void (*cleanup)(void*)) {
|
||||
SerialArena* arena;
|
||||
if (GOOGLE_PREDICT_TRUE(GetSerialArenaFast(&arena))) {
|
||||
return arena->AllocateAlignedAndAddCleanup(n, cleanup);
|
||||
} else {
|
||||
return AllocateAlignedAndAddCleanupFallback(n, cleanup);
|
||||
}
|
||||
}
|
||||
|
||||
void ArenaImpl::AddCleanup(void* elem, void (*cleanup)(void*)) {
|
||||
SerialArena* arena;
|
||||
if (GOOGLE_PREDICT_TRUE(GetSerialArenaFast(&arena))) {
|
||||
arena->AddCleanup(elem, cleanup);
|
||||
} else {
|
||||
return AddCleanupFallback(elem, cleanup);
|
||||
}
|
||||
}
|
||||
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE
|
||||
void* ArenaImpl::AllocateAlignedFallback(size_t n) {
|
||||
return GetSerialArena()->AllocateAligned(n);
|
||||
}
|
||||
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE
|
||||
void* ArenaImpl::AllocateAlignedAndAddCleanupFallback(size_t n,
|
||||
void (*cleanup)(void*)) {
|
||||
return GetSerialArena()->AllocateAlignedAndAddCleanup(n, cleanup);
|
||||
}
|
||||
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE
|
||||
void ArenaImpl::AddCleanupFallback(void* elem, void (*cleanup)(void*)) {
|
||||
GetSerialArena()->AddCleanup(elem, cleanup);
|
||||
}
|
||||
|
||||
inline GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE
|
||||
bool ArenaImpl::GetSerialArenaFast(ArenaImpl::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 (GOOGLE_PREDICT_TRUE(tc->last_lifecycle_id_seen == lifecycle_id_)) {
|
||||
*arena = tc->last_serial_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.
|
||||
SerialArena* serial = hint_.load(std::memory_order_acquire);
|
||||
if (GOOGLE_PREDICT_TRUE(serial != NULL && serial->owner() == tc)) {
|
||||
*arena = serial;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ArenaImpl::SerialArena* ArenaImpl::GetSerialArena() {
|
||||
SerialArena* arena;
|
||||
if (GOOGLE_PREDICT_TRUE(GetSerialArenaFast(&arena))) {
|
||||
return arena;
|
||||
} else {
|
||||
return GetSerialArenaFallback(&thread_cache());
|
||||
}
|
||||
}
|
||||
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE
|
||||
void* ArenaImpl::SerialArena::AllocateAlignedFallback(size_t n) {
|
||||
// Sync back to current's pos.
|
||||
head_->set_pos(head_->size() - (limit_ - ptr_));
|
||||
|
||||
head_ = arena_->NewBlock(head_, n);
|
||||
ptr_ = head_->Pointer(head_->pos());
|
||||
limit_ = head_->Pointer(head_->size());
|
||||
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
ASAN_POISON_MEMORY_REGION(ptr_, limit_ - ptr_);
|
||||
#endif // ADDRESS_SANITIZER
|
||||
|
||||
return AllocateAligned(n);
|
||||
}
|
||||
|
||||
uint64 ArenaImpl::SpaceAllocated() const {
|
||||
return space_allocated_.load(std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
uint64 ArenaImpl::SpaceUsed() const {
|
||||
SerialArena* serial = threads_.load(std::memory_order_acquire);
|
||||
uint64 space_used = 0;
|
||||
for ( ; serial; serial = serial->next()) {
|
||||
space_used += serial->SpaceUsed();
|
||||
}
|
||||
return space_used;
|
||||
}
|
||||
|
||||
uint64 ArenaImpl::SerialArena::SpaceUsed() const {
|
||||
// Get current block's size from ptr_ (since we can't trust head_->pos().
|
||||
uint64 space_used = ptr_ - head_->Pointer(kBlockHeaderSize);
|
||||
// Get subsequent block size from b->pos().
|
||||
for (Block* b = head_->next(); b; b = b->next()) {
|
||||
space_used += (b->pos() - kBlockHeaderSize);
|
||||
}
|
||||
// Remove the overhead of the SerialArena itself.
|
||||
space_used -= kSerialArenaSize;
|
||||
return space_used;
|
||||
}
|
||||
|
||||
uint64 ArenaImpl::FreeBlocks() {
|
||||
uint64 space_allocated = 0;
|
||||
// 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);
|
||||
|
||||
while (serial) {
|
||||
// This is inside a block we are freeing, so we need to read it now.
|
||||
SerialArena* next = serial->next();
|
||||
space_allocated += ArenaImpl::SerialArena::Free(serial, initial_block_,
|
||||
options_.block_dealloc);
|
||||
// serial is dead now.
|
||||
serial = next;
|
||||
}
|
||||
|
||||
return space_allocated;
|
||||
}
|
||||
|
||||
uint64 ArenaImpl::SerialArena::Free(ArenaImpl::SerialArena* serial,
|
||||
Block* initial_block,
|
||||
void (*block_dealloc)(void*, size_t)) {
|
||||
uint64 space_allocated = 0;
|
||||
|
||||
// We have to be careful in this function, since we will be freeing the Block
|
||||
// that contains this SerialArena. Be careful about accessing |serial|.
|
||||
|
||||
for (Block* b = serial->head_; b; ) {
|
||||
// This is inside the block we are freeing, so we need to read it now.
|
||||
Block* next_block = b->next();
|
||||
space_allocated += (b->size());
|
||||
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
// This memory was provided by the underlying allocator as unpoisoned, so
|
||||
// return it in an unpoisoned state.
|
||||
ASAN_UNPOISON_MEMORY_REGION(b->Pointer(0), b->size());
|
||||
#endif // ADDRESS_SANITIZER
|
||||
|
||||
if (b != initial_block) {
|
||||
block_dealloc(b, b->size());
|
||||
}
|
||||
|
||||
b = next_block;
|
||||
}
|
||||
|
||||
return space_allocated;
|
||||
}
|
||||
|
||||
void ArenaImpl::CleanupList() {
|
||||
// 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()) {
|
||||
serial->CleanupList();
|
||||
}
|
||||
}
|
||||
|
||||
void ArenaImpl::SerialArena::CleanupList() {
|
||||
if (cleanup_ != NULL) {
|
||||
CleanupListFallback();
|
||||
}
|
||||
}
|
||||
|
||||
void ArenaImpl::SerialArena::CleanupListFallback() {
|
||||
// Cleanup newest chunk: ptrs give us length.
|
||||
size_t n = cleanup_ptr_ - &cleanup_->nodes[0];
|
||||
CleanupNode* node = cleanup_ptr_;
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
--node;
|
||||
node->cleanup(node->elem);
|
||||
}
|
||||
|
||||
// Cleanup older chunks, which are known to be full.
|
||||
CleanupChunk* list = cleanup_->next;
|
||||
while (list) {
|
||||
size_t n = list->size;
|
||||
CleanupNode* node = &list->nodes[list->size];
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
--node;
|
||||
node->cleanup(node->elem);
|
||||
}
|
||||
list = list->next;
|
||||
}
|
||||
}
|
||||
|
||||
ArenaImpl::SerialArena* ArenaImpl::SerialArena::New(Block* b, void* owner,
|
||||
ArenaImpl* arena) {
|
||||
GOOGLE_DCHECK_EQ(b->pos(), kBlockHeaderSize); // Should be a fresh block
|
||||
GOOGLE_DCHECK_LE(kBlockHeaderSize + kSerialArenaSize, b->size());
|
||||
SerialArena* serial =
|
||||
reinterpret_cast<SerialArena*>(b->Pointer(kBlockHeaderSize));
|
||||
b->set_pos(kBlockHeaderSize + kSerialArenaSize);
|
||||
serial->arena_ = arena;
|
||||
serial->owner_ = owner;
|
||||
serial->head_ = b;
|
||||
serial->ptr_ = b->Pointer(b->pos());
|
||||
serial->limit_ = b->Pointer(b->size());
|
||||
serial->cleanup_ = NULL;
|
||||
serial->cleanup_ptr_ = NULL;
|
||||
serial->cleanup_limit_ = NULL;
|
||||
return serial;
|
||||
}
|
||||
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE
|
||||
ArenaImpl::SerialArena* ArenaImpl::GetSerialArenaFallback(void* me) {
|
||||
// Look for this SerialArena in our linked list.
|
||||
SerialArena* serial = threads_.load(std::memory_order_acquire);
|
||||
for ( ; serial; serial = serial->next()) {
|
||||
if (serial->owner() == me) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!serial) {
|
||||
// This thread doesn't have any SerialArena, which also means it doesn't
|
||||
// have any blocks yet. So we'll allocate its first block now.
|
||||
Block* b = NewBlock(NULL, kSerialArenaSize);
|
||||
serial = SerialArena::New(b, me, this);
|
||||
|
||||
SerialArena* head = threads_.load(std::memory_order_relaxed);
|
||||
do {
|
||||
serial->set_next(head);
|
||||
} while (!threads_.compare_exchange_weak(
|
||||
head, serial, std::memory_order_release, std::memory_order_relaxed));
|
||||
}
|
||||
|
||||
CacheSerialArena(serial);
|
||||
return serial;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
void Arena::CallDestructorHooks() {
|
||||
uint64 space_allocated = impl_.SpaceAllocated();
|
||||
// Call the reset hook
|
||||
if (on_arena_reset_ != NULL) {
|
||||
on_arena_reset_(this, hooks_cookie_, space_allocated);
|
||||
}
|
||||
|
||||
// Call the destruction hook
|
||||
if (on_arena_destruction_ != NULL) {
|
||||
on_arena_destruction_(this, hooks_cookie_, space_allocated);
|
||||
}
|
||||
}
|
||||
|
||||
void Arena::OnArenaAllocation(const std::type_info* allocated_type,
|
||||
size_t n) const {
|
||||
if (on_arena_allocation_ != NULL) {
|
||||
on_arena_allocation_(allocated_type, n, hooks_cookie_);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
43
third_party/protobuf-lite/arenastring.cc
vendored
Normal file
43
third_party/protobuf-lite/arenastring.cc
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
// 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.
|
||||
|
||||
// The ArenaString implementation is not included in the open-source release. Do
|
||||
// not include this file in the distribution.
|
||||
|
||||
#include <google/protobuf/arenastring.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
196
third_party/protobuf-lite/bytestream.cc
vendored
Normal file
196
third_party/protobuf-lite/bytestream.cc
vendored
Normal file
@ -0,0 +1,196 @@
|
||||
// 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.
|
||||
|
||||
#include <google/protobuf/stubs/bytestream.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <algorithm>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace strings {
|
||||
|
||||
void ByteSource::CopyTo(ByteSink* sink, size_t n) {
|
||||
while (n > 0) {
|
||||
StringPiece fragment = Peek();
|
||||
if (fragment.empty()) {
|
||||
GOOGLE_LOG(DFATAL) << "ByteSource::CopyTo() overran input.";
|
||||
break;
|
||||
}
|
||||
std::size_t fragment_size = std::min<std::size_t>(n, fragment.size());
|
||||
sink->Append(fragment.data(), fragment_size);
|
||||
Skip(fragment_size);
|
||||
n -= fragment_size;
|
||||
}
|
||||
}
|
||||
|
||||
void ByteSink::Flush() {}
|
||||
|
||||
void UncheckedArrayByteSink::Append(const char* data, size_t n) {
|
||||
if (data != dest_) {
|
||||
// Catch cases where the pointer returned by GetAppendBuffer() was modified.
|
||||
GOOGLE_DCHECK(!(dest_ <= data && data < (dest_ + n)))
|
||||
<< "Append() data[] overlaps with dest_[]";
|
||||
memcpy(dest_, data, n);
|
||||
}
|
||||
dest_ += n;
|
||||
}
|
||||
|
||||
CheckedArrayByteSink::CheckedArrayByteSink(char* outbuf, size_t capacity)
|
||||
: outbuf_(outbuf), capacity_(capacity), size_(0), overflowed_(false) {
|
||||
}
|
||||
|
||||
void CheckedArrayByteSink::Append(const char* bytes, size_t n) {
|
||||
size_t available = capacity_ - size_;
|
||||
if (n > available) {
|
||||
n = available;
|
||||
overflowed_ = true;
|
||||
}
|
||||
if (n > 0 && bytes != (outbuf_ + size_)) {
|
||||
// Catch cases where the pointer returned by GetAppendBuffer() was modified.
|
||||
GOOGLE_DCHECK(!(outbuf_ <= bytes && bytes < (outbuf_ + capacity_)))
|
||||
<< "Append() bytes[] overlaps with outbuf_[]";
|
||||
memcpy(outbuf_ + size_, bytes, n);
|
||||
}
|
||||
size_ += n;
|
||||
}
|
||||
|
||||
GrowingArrayByteSink::GrowingArrayByteSink(size_t estimated_size)
|
||||
: capacity_(estimated_size),
|
||||
buf_(new char[estimated_size]),
|
||||
size_(0) {
|
||||
}
|
||||
|
||||
GrowingArrayByteSink::~GrowingArrayByteSink() {
|
||||
delete[] buf_; // Just in case the user didn't call GetBuffer.
|
||||
}
|
||||
|
||||
void GrowingArrayByteSink::Append(const char* bytes, size_t n) {
|
||||
size_t available = capacity_ - size_;
|
||||
if (bytes != (buf_ + size_)) {
|
||||
// Catch cases where the pointer returned by GetAppendBuffer() was modified.
|
||||
// We need to test for this before calling Expand() which may reallocate.
|
||||
GOOGLE_DCHECK(!(buf_ <= bytes && bytes < (buf_ + capacity_)))
|
||||
<< "Append() bytes[] overlaps with buf_[]";
|
||||
}
|
||||
if (n > available) {
|
||||
Expand(n - available);
|
||||
}
|
||||
if (n > 0 && bytes != (buf_ + size_)) {
|
||||
memcpy(buf_ + size_, bytes, n);
|
||||
}
|
||||
size_ += n;
|
||||
}
|
||||
|
||||
char* GrowingArrayByteSink::GetBuffer(size_t* nbytes) {
|
||||
ShrinkToFit();
|
||||
char* b = buf_;
|
||||
*nbytes = size_;
|
||||
buf_ = NULL;
|
||||
size_ = capacity_ = 0;
|
||||
return b;
|
||||
}
|
||||
|
||||
void GrowingArrayByteSink::Expand(size_t amount) { // Expand by at least 50%.
|
||||
size_t new_capacity = std::max(capacity_ + amount, (3 * capacity_) / 2);
|
||||
char* bigger = new char[new_capacity];
|
||||
memcpy(bigger, buf_, size_);
|
||||
delete[] buf_;
|
||||
buf_ = bigger;
|
||||
capacity_ = new_capacity;
|
||||
}
|
||||
|
||||
void GrowingArrayByteSink::ShrinkToFit() {
|
||||
// Shrink only if the buffer is large and size_ is less than 3/4
|
||||
// of capacity_.
|
||||
if (capacity_ > 256 && size_ < (3 * capacity_) / 4) {
|
||||
char* just_enough = new char[size_];
|
||||
memcpy(just_enough, buf_, size_);
|
||||
delete[] buf_;
|
||||
buf_ = just_enough;
|
||||
capacity_ = size_;
|
||||
}
|
||||
}
|
||||
|
||||
void StringByteSink::Append(const char* data, size_t n) {
|
||||
dest_->append(data, n);
|
||||
}
|
||||
|
||||
size_t ArrayByteSource::Available() const {
|
||||
return input_.size();
|
||||
}
|
||||
|
||||
StringPiece ArrayByteSource::Peek() {
|
||||
return input_;
|
||||
}
|
||||
|
||||
void ArrayByteSource::Skip(size_t n) {
|
||||
GOOGLE_DCHECK_LE(n, input_.size());
|
||||
input_.remove_prefix(n);
|
||||
}
|
||||
|
||||
LimitByteSource::LimitByteSource(ByteSource *source, size_t limit)
|
||||
: source_(source),
|
||||
limit_(limit) {
|
||||
}
|
||||
|
||||
size_t LimitByteSource::Available() const {
|
||||
size_t available = source_->Available();
|
||||
if (available > limit_) {
|
||||
available = limit_;
|
||||
}
|
||||
|
||||
return available;
|
||||
}
|
||||
|
||||
StringPiece LimitByteSource::Peek() {
|
||||
StringPiece piece(source_->Peek());
|
||||
if (piece.size() > limit_) {
|
||||
piece.set(piece.data(), limit_);
|
||||
}
|
||||
|
||||
return piece;
|
||||
}
|
||||
|
||||
void LimitByteSource::Skip(size_t n) {
|
||||
GOOGLE_DCHECK_LE(n, limit_);
|
||||
source_->Skip(n);
|
||||
limit_ -= n;
|
||||
}
|
||||
|
||||
void LimitByteSource::CopyTo(ByteSink *sink, size_t n) {
|
||||
GOOGLE_DCHECK_LE(n, limit_);
|
||||
source_->CopyTo(sink, n);
|
||||
limit_ -= n;
|
||||
}
|
||||
|
||||
} // namespace strings
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
780
third_party/protobuf-lite/coded_stream.cc
vendored
Normal file
780
third_party/protobuf-lite/coded_stream.cc
vendored
Normal file
@ -0,0 +1,780 @@
|
||||
// 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 implementation is heavily optimized to make reads and writes
|
||||
// of small values (especially varints) as fast as possible. In
|
||||
// particular, we optimize for the common case that a read or a write
|
||||
// will not cross the end of the buffer, since we can avoid a lot
|
||||
// of branching in this case.
|
||||
|
||||
#include <google/protobuf/io/coded_stream_inl.h>
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
#include <limits.h>
|
||||
#include <google/protobuf/io/zero_copy_stream.h>
|
||||
#include <google/protobuf/arena.h>
|
||||
#include <google/protobuf/stubs/logging.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/stl_util.h>
|
||||
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace io {
|
||||
|
||||
namespace {
|
||||
|
||||
static const int kMaxVarintBytes = 10;
|
||||
static const int kMaxVarint32Bytes = 5;
|
||||
|
||||
|
||||
inline bool NextNonEmpty(ZeroCopyInputStream* input,
|
||||
const void** data, int* size) {
|
||||
bool success;
|
||||
do {
|
||||
success = input->Next(data, size);
|
||||
} while (success && *size == 0);
|
||||
return success;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// CodedInputStream ==================================================
|
||||
|
||||
CodedInputStream::~CodedInputStream() {
|
||||
if (input_ != NULL) {
|
||||
BackUpInputToCurrentPosition();
|
||||
}
|
||||
}
|
||||
|
||||
// Static.
|
||||
int CodedInputStream::default_recursion_limit_ = 100;
|
||||
|
||||
|
||||
void CodedOutputStream::EnableAliasing(bool enabled) {
|
||||
aliasing_enabled_ = enabled && output_->AllowsAliasing();
|
||||
}
|
||||
|
||||
void CodedInputStream::BackUpInputToCurrentPosition() {
|
||||
int backup_bytes = BufferSize() + buffer_size_after_limit_ + overflow_bytes_;
|
||||
if (backup_bytes > 0) {
|
||||
input_->BackUp(backup_bytes);
|
||||
|
||||
// total_bytes_read_ doesn't include overflow_bytes_.
|
||||
total_bytes_read_ -= BufferSize() + buffer_size_after_limit_;
|
||||
buffer_end_ = buffer_;
|
||||
buffer_size_after_limit_ = 0;
|
||||
overflow_bytes_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
inline void CodedInputStream::RecomputeBufferLimits() {
|
||||
buffer_end_ += buffer_size_after_limit_;
|
||||
int closest_limit = std::min(current_limit_, total_bytes_limit_);
|
||||
if (closest_limit < total_bytes_read_) {
|
||||
// The limit position is in the current buffer. We must adjust
|
||||
// the buffer size accordingly.
|
||||
buffer_size_after_limit_ = total_bytes_read_ - closest_limit;
|
||||
buffer_end_ -= buffer_size_after_limit_;
|
||||
} else {
|
||||
buffer_size_after_limit_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
CodedInputStream::Limit CodedInputStream::PushLimit(int byte_limit) {
|
||||
// Current position relative to the beginning of the stream.
|
||||
int current_position = CurrentPosition();
|
||||
|
||||
Limit old_limit = current_limit_;
|
||||
|
||||
// security: byte_limit is possibly evil, so check for negative values
|
||||
// and overflow. Also check that the new requested limit is before the
|
||||
// previous limit; otherwise we continue to enforce the previous limit.
|
||||
if (GOOGLE_PREDICT_TRUE(byte_limit >= 0 &&
|
||||
byte_limit <= INT_MAX - current_position &&
|
||||
byte_limit < current_limit_ - current_position)) {
|
||||
current_limit_ = current_position + byte_limit;
|
||||
RecomputeBufferLimits();
|
||||
}
|
||||
|
||||
return old_limit;
|
||||
}
|
||||
|
||||
void CodedInputStream::PopLimit(Limit limit) {
|
||||
// The limit passed in is actually the *old* limit, which we returned from
|
||||
// PushLimit().
|
||||
current_limit_ = limit;
|
||||
RecomputeBufferLimits();
|
||||
|
||||
// We may no longer be at a legitimate message end. ReadTag() needs to be
|
||||
// called again to find out.
|
||||
legitimate_message_end_ = false;
|
||||
}
|
||||
|
||||
std::pair<CodedInputStream::Limit, int>
|
||||
CodedInputStream::IncrementRecursionDepthAndPushLimit(int byte_limit) {
|
||||
return std::make_pair(PushLimit(byte_limit), --recursion_budget_);
|
||||
}
|
||||
|
||||
CodedInputStream::Limit CodedInputStream::ReadLengthAndPushLimit() {
|
||||
uint32 length;
|
||||
return PushLimit(ReadVarint32(&length) ? length : 0);
|
||||
}
|
||||
|
||||
bool CodedInputStream::DecrementRecursionDepthAndPopLimit(Limit limit) {
|
||||
bool result = ConsumedEntireMessage();
|
||||
PopLimit(limit);
|
||||
GOOGLE_DCHECK_LT(recursion_budget_, recursion_limit_);
|
||||
++recursion_budget_;
|
||||
return result;
|
||||
}
|
||||
|
||||
bool CodedInputStream::CheckEntireMessageConsumedAndPopLimit(Limit limit) {
|
||||
bool result = ConsumedEntireMessage();
|
||||
PopLimit(limit);
|
||||
return result;
|
||||
}
|
||||
|
||||
int CodedInputStream::BytesUntilLimit() const {
|
||||
if (current_limit_ == INT_MAX) return -1;
|
||||
int current_position = CurrentPosition();
|
||||
|
||||
return current_limit_ - current_position;
|
||||
}
|
||||
|
||||
void CodedInputStream::SetTotalBytesLimit(int total_bytes_limit) {
|
||||
// Make sure the limit isn't already past, since this could confuse other
|
||||
// code.
|
||||
int current_position = CurrentPosition();
|
||||
total_bytes_limit_ = std::max(current_position, total_bytes_limit);
|
||||
RecomputeBufferLimits();
|
||||
}
|
||||
|
||||
int CodedInputStream::BytesUntilTotalBytesLimit() const {
|
||||
if (total_bytes_limit_ == INT_MAX) return -1;
|
||||
return total_bytes_limit_ - CurrentPosition();
|
||||
}
|
||||
|
||||
void CodedInputStream::PrintTotalBytesLimitError() {
|
||||
GOOGLE_LOG(ERROR) << "A protocol message was rejected because it was too "
|
||||
"big (more than " << total_bytes_limit_
|
||||
<< " bytes). To increase the limit (or to disable these "
|
||||
"warnings), see CodedInputStream::SetTotalBytesLimit() "
|
||||
"in google/protobuf/io/coded_stream.h.";
|
||||
}
|
||||
|
||||
bool CodedInputStream::SkipFallback(int count, int original_buffer_size) {
|
||||
if (buffer_size_after_limit_ > 0) {
|
||||
// We hit a limit inside this buffer. Advance to the limit and fail.
|
||||
Advance(original_buffer_size);
|
||||
return false;
|
||||
}
|
||||
|
||||
count -= original_buffer_size;
|
||||
buffer_ = NULL;
|
||||
buffer_end_ = buffer_;
|
||||
|
||||
// Make sure this skip doesn't try to skip past the current limit.
|
||||
int closest_limit = std::min(current_limit_, total_bytes_limit_);
|
||||
int bytes_until_limit = closest_limit - total_bytes_read_;
|
||||
if (bytes_until_limit < count) {
|
||||
// We hit the limit. Skip up to it then fail.
|
||||
if (bytes_until_limit > 0) {
|
||||
total_bytes_read_ = closest_limit;
|
||||
input_->Skip(bytes_until_limit);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!input_->Skip(count)) {
|
||||
total_bytes_read_ = input_->ByteCount();
|
||||
return false;
|
||||
}
|
||||
total_bytes_read_ += count;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CodedInputStream::GetDirectBufferPointer(const void** data, int* size) {
|
||||
if (BufferSize() == 0 && !Refresh()) return false;
|
||||
|
||||
*data = buffer_;
|
||||
*size = BufferSize();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CodedInputStream::ReadRaw(void* buffer, int size) {
|
||||
return InternalReadRawInline(buffer, size);
|
||||
}
|
||||
|
||||
bool CodedInputStream::ReadString(string* buffer, int size) {
|
||||
if (size < 0) return false; // security: size is often user-supplied
|
||||
return InternalReadStringInline(buffer, size);
|
||||
}
|
||||
|
||||
bool CodedInputStream::ReadStringFallback(string* buffer, int size) {
|
||||
if (!buffer->empty()) {
|
||||
buffer->clear();
|
||||
}
|
||||
|
||||
int closest_limit = std::min(current_limit_, total_bytes_limit_);
|
||||
if (closest_limit != INT_MAX) {
|
||||
int bytes_to_limit = closest_limit - CurrentPosition();
|
||||
if (bytes_to_limit > 0 && size > 0 && size <= bytes_to_limit) {
|
||||
buffer->reserve(size);
|
||||
}
|
||||
}
|
||||
|
||||
int current_buffer_size;
|
||||
while ((current_buffer_size = BufferSize()) < size) {
|
||||
// Some STL implementations "helpfully" crash on buffer->append(NULL, 0).
|
||||
if (current_buffer_size != 0) {
|
||||
// Note: string1.append(string2) is O(string2.size()) (as opposed to
|
||||
// O(string1.size() + string2.size()), which would be bad).
|
||||
buffer->append(reinterpret_cast<const char*>(buffer_),
|
||||
current_buffer_size);
|
||||
}
|
||||
size -= current_buffer_size;
|
||||
Advance(current_buffer_size);
|
||||
if (!Refresh()) return false;
|
||||
}
|
||||
|
||||
buffer->append(reinterpret_cast<const char*>(buffer_), size);
|
||||
Advance(size);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CodedInputStream::ReadLittleEndian32Fallback(uint32* value) {
|
||||
uint8 bytes[sizeof(*value)];
|
||||
|
||||
const uint8* ptr;
|
||||
if (BufferSize() >= sizeof(*value)) {
|
||||
// Fast path: Enough bytes in the buffer to read directly.
|
||||
ptr = buffer_;
|
||||
Advance(sizeof(*value));
|
||||
} else {
|
||||
// Slow path: Had to read past the end of the buffer.
|
||||
if (!ReadRaw(bytes, sizeof(*value))) return false;
|
||||
ptr = bytes;
|
||||
}
|
||||
ReadLittleEndian32FromArray(ptr, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CodedInputStream::ReadLittleEndian64Fallback(uint64* value) {
|
||||
uint8 bytes[sizeof(*value)];
|
||||
|
||||
const uint8* ptr;
|
||||
if (BufferSize() >= sizeof(*value)) {
|
||||
// Fast path: Enough bytes in the buffer to read directly.
|
||||
ptr = buffer_;
|
||||
Advance(sizeof(*value));
|
||||
} else {
|
||||
// Slow path: Had to read past the end of the buffer.
|
||||
if (!ReadRaw(bytes, sizeof(*value))) return false;
|
||||
ptr = bytes;
|
||||
}
|
||||
ReadLittleEndian64FromArray(ptr, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
// Read a varint from the given buffer, write it to *value, and return a pair.
|
||||
// The first part of the pair is true iff the read was successful. The second
|
||||
// part is buffer + (number of bytes read). This function is always inlined,
|
||||
// so returning a pair is costless.
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE
|
||||
::std::pair<bool, const uint8*> ReadVarint32FromArray(
|
||||
uint32 first_byte, const uint8* buffer,
|
||||
uint32* value);
|
||||
inline ::std::pair<bool, const uint8*> ReadVarint32FromArray(
|
||||
uint32 first_byte, const uint8* buffer, uint32* value) {
|
||||
// Fast path: We have enough bytes left in the buffer to guarantee that
|
||||
// this read won't cross the end, so we can skip the checks.
|
||||
GOOGLE_DCHECK_EQ(*buffer, first_byte);
|
||||
GOOGLE_DCHECK_EQ(first_byte & 0x80, 0x80) << first_byte;
|
||||
const uint8* ptr = buffer;
|
||||
uint32 b;
|
||||
uint32 result = first_byte - 0x80;
|
||||
++ptr; // We just processed the first byte. Move on to the second.
|
||||
b = *(ptr++); result += b << 7; if (!(b & 0x80)) goto done;
|
||||
result -= 0x80 << 7;
|
||||
b = *(ptr++); result += b << 14; if (!(b & 0x80)) goto done;
|
||||
result -= 0x80 << 14;
|
||||
b = *(ptr++); result += b << 21; if (!(b & 0x80)) goto done;
|
||||
result -= 0x80 << 21;
|
||||
b = *(ptr++); result += b << 28; if (!(b & 0x80)) goto done;
|
||||
// "result -= 0x80 << 28" is irrevelant.
|
||||
|
||||
// If the input is larger than 32 bits, we still need to read it all
|
||||
// and discard the high-order bits.
|
||||
for (int i = 0; i < kMaxVarintBytes - kMaxVarint32Bytes; i++) {
|
||||
b = *(ptr++); if (!(b & 0x80)) goto done;
|
||||
}
|
||||
|
||||
// We have overrun the maximum size of a varint (10 bytes). Assume
|
||||
// the data is corrupt.
|
||||
return std::make_pair(false, ptr);
|
||||
|
||||
done:
|
||||
*value = result;
|
||||
return std::make_pair(true, ptr);
|
||||
}
|
||||
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE::std::pair<bool, const uint8*>
|
||||
ReadVarint64FromArray(const uint8* buffer, uint64* value);
|
||||
inline ::std::pair<bool, const uint8*> ReadVarint64FromArray(
|
||||
const uint8* buffer, uint64* value) {
|
||||
const uint8* ptr = buffer;
|
||||
uint32 b;
|
||||
|
||||
// Splitting into 32-bit pieces gives better performance on 32-bit
|
||||
// processors.
|
||||
uint32 part0 = 0, part1 = 0, part2 = 0;
|
||||
|
||||
b = *(ptr++); part0 = b ; if (!(b & 0x80)) goto done;
|
||||
part0 -= 0x80;
|
||||
b = *(ptr++); part0 += b << 7; if (!(b & 0x80)) goto done;
|
||||
part0 -= 0x80 << 7;
|
||||
b = *(ptr++); part0 += b << 14; if (!(b & 0x80)) goto done;
|
||||
part0 -= 0x80 << 14;
|
||||
b = *(ptr++); part0 += b << 21; if (!(b & 0x80)) goto done;
|
||||
part0 -= 0x80 << 21;
|
||||
b = *(ptr++); part1 = b ; if (!(b & 0x80)) goto done;
|
||||
part1 -= 0x80;
|
||||
b = *(ptr++); part1 += b << 7; if (!(b & 0x80)) goto done;
|
||||
part1 -= 0x80 << 7;
|
||||
b = *(ptr++); part1 += b << 14; if (!(b & 0x80)) goto done;
|
||||
part1 -= 0x80 << 14;
|
||||
b = *(ptr++); part1 += b << 21; if (!(b & 0x80)) goto done;
|
||||
part1 -= 0x80 << 21;
|
||||
b = *(ptr++); part2 = b ; if (!(b & 0x80)) goto done;
|
||||
part2 -= 0x80;
|
||||
b = *(ptr++); part2 += b << 7; if (!(b & 0x80)) goto done;
|
||||
// "part2 -= 0x80 << 7" is irrelevant because (0x80 << 7) << 56 is 0.
|
||||
|
||||
// We have overrun the maximum size of a varint (10 bytes). Assume
|
||||
// the data is corrupt.
|
||||
return std::make_pair(false, ptr);
|
||||
|
||||
done:
|
||||
*value = (static_cast<uint64>(part0)) |
|
||||
(static_cast<uint64>(part1) << 28) |
|
||||
(static_cast<uint64>(part2) << 56);
|
||||
return std::make_pair(true, ptr);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool CodedInputStream::ReadVarint32Slow(uint32* value) {
|
||||
// Directly invoke ReadVarint64Fallback, since we already tried to optimize
|
||||
// for one-byte varints.
|
||||
std::pair<uint64, bool> p = ReadVarint64Fallback();
|
||||
*value = static_cast<uint32>(p.first);
|
||||
return p.second;
|
||||
}
|
||||
|
||||
int64 CodedInputStream::ReadVarint32Fallback(uint32 first_byte_or_zero) {
|
||||
if (BufferSize() >= kMaxVarintBytes ||
|
||||
// Optimization: We're also safe if the buffer is non-empty and it ends
|
||||
// with a byte that would terminate a varint.
|
||||
(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 temp;
|
||||
::std::pair<bool, const uint8*> p =
|
||||
ReadVarint32FromArray(first_byte_or_zero, buffer_, &temp);
|
||||
if (!p.first) return -1;
|
||||
buffer_ = p.second;
|
||||
return temp;
|
||||
} else {
|
||||
// Really slow case: we will incur the cost of an extra function call here,
|
||||
// but moving this out of line reduces the size of this function, which
|
||||
// improves the common case. In micro benchmarks, this is worth about 10-15%
|
||||
uint32 temp;
|
||||
return ReadVarint32Slow(&temp) ? static_cast<int64>(temp) : -1;
|
||||
}
|
||||
}
|
||||
|
||||
int CodedInputStream::ReadVarintSizeAsIntSlow() {
|
||||
// Directly invoke ReadVarint64Fallback, since we already tried to optimize
|
||||
// for one-byte varints.
|
||||
std::pair<uint64, bool> p = ReadVarint64Fallback();
|
||||
if (!p.second || p.first > static_cast<uint64>(INT_MAX)) return -1;
|
||||
return p.first;
|
||||
}
|
||||
|
||||
int CodedInputStream::ReadVarintSizeAsIntFallback() {
|
||||
if (BufferSize() >= kMaxVarintBytes ||
|
||||
// Optimization: We're also safe if the buffer is non-empty and it ends
|
||||
// with a byte that would terminate a varint.
|
||||
(buffer_end_ > buffer_ && !(buffer_end_[-1] & 0x80))) {
|
||||
uint64 temp;
|
||||
::std::pair<bool, const uint8*> p = ReadVarint64FromArray(buffer_, &temp);
|
||||
if (!p.first || temp > static_cast<uint64>(INT_MAX)) return -1;
|
||||
buffer_ = p.second;
|
||||
return temp;
|
||||
} else {
|
||||
// Really slow case: we will incur the cost of an extra function call here,
|
||||
// but moving this out of line reduces the size of this function, which
|
||||
// improves the common case. In micro benchmarks, this is worth about 10-15%
|
||||
return ReadVarintSizeAsIntSlow();
|
||||
}
|
||||
}
|
||||
|
||||
uint32 CodedInputStream::ReadTagSlow() {
|
||||
if (buffer_ == buffer_end_) {
|
||||
// Call refresh.
|
||||
if (!Refresh()) {
|
||||
// Refresh failed. Make sure that it failed due to EOF, not because
|
||||
// we hit total_bytes_limit_, which, unlike normal limits, is not a
|
||||
// valid place to end a message.
|
||||
int current_position = total_bytes_read_ - buffer_size_after_limit_;
|
||||
if (current_position >= total_bytes_limit_) {
|
||||
// Hit total_bytes_limit_. But if we also hit the normal limit,
|
||||
// we're still OK.
|
||||
legitimate_message_end_ = current_limit_ == total_bytes_limit_;
|
||||
} else {
|
||||
legitimate_message_end_ = true;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// For the slow path, just do a 64-bit read. Try to optimize for one-byte tags
|
||||
// again, since we have now refreshed the buffer.
|
||||
uint64 result = 0;
|
||||
if (!ReadVarint64(&result)) return 0;
|
||||
return static_cast<uint32>(result);
|
||||
}
|
||||
|
||||
uint32 CodedInputStream::ReadTagFallback(uint32 first_byte_or_zero) {
|
||||
const int buf_size = BufferSize();
|
||||
if (buf_size >= kMaxVarintBytes ||
|
||||
// Optimization: We're also safe if the buffer is non-empty and it ends
|
||||
// with a byte that would terminate a varint.
|
||||
(buf_size > 0 && !(buffer_end_[-1] & 0x80))) {
|
||||
GOOGLE_DCHECK_EQ(first_byte_or_zero, buffer_[0]);
|
||||
if (first_byte_or_zero == 0) {
|
||||
++buffer_;
|
||||
return 0;
|
||||
}
|
||||
uint32 tag;
|
||||
::std::pair<bool, const uint8*> p =
|
||||
ReadVarint32FromArray(first_byte_or_zero, buffer_, &tag);
|
||||
if (!p.first) {
|
||||
return 0;
|
||||
}
|
||||
buffer_ = p.second;
|
||||
return tag;
|
||||
} else {
|
||||
// We are commonly at a limit when attempting to read tags. Try to quickly
|
||||
// detect this case without making another function call.
|
||||
if ((buf_size == 0) &&
|
||||
((buffer_size_after_limit_ > 0) ||
|
||||
(total_bytes_read_ == current_limit_)) &&
|
||||
// Make sure that the limit we hit is not total_bytes_limit_, since
|
||||
// in that case we still need to call Refresh() so that it prints an
|
||||
// error.
|
||||
total_bytes_read_ - buffer_size_after_limit_ < total_bytes_limit_) {
|
||||
// We hit a byte limit.
|
||||
legitimate_message_end_ = true;
|
||||
return 0;
|
||||
}
|
||||
return ReadTagSlow();
|
||||
}
|
||||
}
|
||||
|
||||
bool CodedInputStream::ReadVarint64Slow(uint64* value) {
|
||||
// Slow path: This read might cross the end of the buffer, so we
|
||||
// need to check and refresh the buffer if and when it does.
|
||||
|
||||
uint64 result = 0;
|
||||
int count = 0;
|
||||
uint32 b;
|
||||
|
||||
do {
|
||||
if (count == kMaxVarintBytes) {
|
||||
*value = 0;
|
||||
return false;
|
||||
}
|
||||
while (buffer_ == buffer_end_) {
|
||||
if (!Refresh()) {
|
||||
*value = 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
b = *buffer_;
|
||||
result |= static_cast<uint64>(b & 0x7F) << (7 * count);
|
||||
Advance(1);
|
||||
++count;
|
||||
} while (b & 0x80);
|
||||
|
||||
*value = result;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::pair<uint64, bool> CodedInputStream::ReadVarint64Fallback() {
|
||||
if (BufferSize() >= kMaxVarintBytes ||
|
||||
// Optimization: We're also safe if the buffer is non-empty and it ends
|
||||
// with a byte that would terminate a varint.
|
||||
(buffer_end_ > buffer_ && !(buffer_end_[-1] & 0x80))) {
|
||||
uint64 temp;
|
||||
::std::pair<bool, const uint8*> p = ReadVarint64FromArray(buffer_, &temp);
|
||||
if (!p.first) {
|
||||
return std::make_pair(0, false);
|
||||
}
|
||||
buffer_ = p.second;
|
||||
return std::make_pair(temp, true);
|
||||
} else {
|
||||
uint64 temp;
|
||||
bool success = ReadVarint64Slow(&temp);
|
||||
return std::make_pair(temp, success);
|
||||
}
|
||||
}
|
||||
|
||||
bool CodedInputStream::Refresh() {
|
||||
GOOGLE_DCHECK_EQ(0, BufferSize());
|
||||
|
||||
if (buffer_size_after_limit_ > 0 || overflow_bytes_ > 0 ||
|
||||
total_bytes_read_ == current_limit_) {
|
||||
// We've hit a limit. Stop.
|
||||
int current_position = total_bytes_read_ - buffer_size_after_limit_;
|
||||
|
||||
if (current_position >= total_bytes_limit_ &&
|
||||
total_bytes_limit_ != current_limit_) {
|
||||
// Hit total_bytes_limit_.
|
||||
PrintTotalBytesLimitError();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const void* void_buffer;
|
||||
int buffer_size;
|
||||
if (NextNonEmpty(input_, &void_buffer, &buffer_size)) {
|
||||
buffer_ = reinterpret_cast<const uint8*>(void_buffer);
|
||||
buffer_end_ = buffer_ + buffer_size;
|
||||
GOOGLE_CHECK_GE(buffer_size, 0);
|
||||
|
||||
if (total_bytes_read_ <= INT_MAX - buffer_size) {
|
||||
total_bytes_read_ += buffer_size;
|
||||
} else {
|
||||
// Overflow. Reset buffer_end_ to not include the bytes beyond INT_MAX.
|
||||
// We can't get that far anyway, because total_bytes_limit_ is guaranteed
|
||||
// to be less than it. We need to keep track of the number of bytes
|
||||
// we discarded, though, so that we can call input_->BackUp() to back
|
||||
// up over them on destruction.
|
||||
|
||||
// The following line is equivalent to:
|
||||
// overflow_bytes_ = total_bytes_read_ + buffer_size - INT_MAX;
|
||||
// except that it avoids overflows. Signed integer overflow has
|
||||
// undefined results according to the C standard.
|
||||
overflow_bytes_ = total_bytes_read_ - (INT_MAX - buffer_size);
|
||||
buffer_end_ -= overflow_bytes_;
|
||||
total_bytes_read_ = INT_MAX;
|
||||
}
|
||||
|
||||
RecomputeBufferLimits();
|
||||
return true;
|
||||
} else {
|
||||
buffer_ = NULL;
|
||||
buffer_end_ = NULL;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// CodedOutputStream =================================================
|
||||
|
||||
std::atomic<bool> CodedOutputStream::default_serialization_deterministic_{
|
||||
false};
|
||||
|
||||
CodedOutputStream::CodedOutputStream(ZeroCopyOutputStream* output)
|
||||
: CodedOutputStream(output, true) {}
|
||||
|
||||
CodedOutputStream::CodedOutputStream(ZeroCopyOutputStream* output,
|
||||
bool do_eager_refresh)
|
||||
: output_(output),
|
||||
buffer_(NULL),
|
||||
buffer_size_(0),
|
||||
total_bytes_(0),
|
||||
had_error_(false),
|
||||
aliasing_enabled_(false),
|
||||
is_serialization_deterministic_(IsDefaultSerializationDeterministic()) {
|
||||
if (do_eager_refresh) {
|
||||
// Eagerly Refresh() so buffer space is immediately available.
|
||||
Refresh();
|
||||
// The Refresh() may have failed. If the client doesn't write any data,
|
||||
// though, don't consider this an error. If the client does write data, then
|
||||
// another Refresh() will be attempted and it will set the error once again.
|
||||
had_error_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
CodedOutputStream::~CodedOutputStream() {
|
||||
Trim();
|
||||
}
|
||||
|
||||
void CodedOutputStream::Trim() {
|
||||
if (buffer_size_ > 0) {
|
||||
output_->BackUp(buffer_size_);
|
||||
total_bytes_ -= buffer_size_;
|
||||
buffer_size_ = 0;
|
||||
buffer_ = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool CodedOutputStream::Skip(int count) {
|
||||
if (count < 0) return false;
|
||||
|
||||
while (count > buffer_size_) {
|
||||
count -= buffer_size_;
|
||||
if (!Refresh()) return false;
|
||||
}
|
||||
|
||||
Advance(count);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CodedOutputStream::GetDirectBufferPointer(void** data, int* size) {
|
||||
if (buffer_size_ == 0 && !Refresh()) return false;
|
||||
|
||||
*data = buffer_;
|
||||
*size = buffer_size_;
|
||||
return true;
|
||||
}
|
||||
|
||||
void CodedOutputStream::WriteRaw(const void* data, int size) {
|
||||
while (buffer_size_ < size) {
|
||||
memcpy(buffer_, data, buffer_size_);
|
||||
size -= buffer_size_;
|
||||
data = reinterpret_cast<const uint8*>(data) + buffer_size_;
|
||||
if (!Refresh()) return;
|
||||
}
|
||||
|
||||
memcpy(buffer_, data, size);
|
||||
Advance(size);
|
||||
}
|
||||
|
||||
uint8* CodedOutputStream::WriteRawToArray(
|
||||
const void* data, int size, uint8* target) {
|
||||
memcpy(target, data, size);
|
||||
return target + size;
|
||||
}
|
||||
|
||||
|
||||
void CodedOutputStream::WriteAliasedRaw(const void* data, int size) {
|
||||
if (size < buffer_size_
|
||||
) {
|
||||
WriteRaw(data, size);
|
||||
} else {
|
||||
Trim();
|
||||
|
||||
total_bytes_ += size;
|
||||
had_error_ |= !output_->WriteAliasedRaw(data, size);
|
||||
}
|
||||
}
|
||||
|
||||
void CodedOutputStream::WriteLittleEndian32(uint32 value) {
|
||||
uint8 bytes[sizeof(value)];
|
||||
|
||||
bool use_fast = buffer_size_ >= sizeof(value);
|
||||
uint8* ptr = use_fast ? buffer_ : bytes;
|
||||
|
||||
WriteLittleEndian32ToArray(value, ptr);
|
||||
|
||||
if (use_fast) {
|
||||
Advance(sizeof(value));
|
||||
} else {
|
||||
WriteRaw(bytes, sizeof(value));
|
||||
}
|
||||
}
|
||||
|
||||
void CodedOutputStream::WriteLittleEndian64(uint64 value) {
|
||||
uint8 bytes[sizeof(value)];
|
||||
|
||||
bool use_fast = buffer_size_ >= sizeof(value);
|
||||
uint8* ptr = use_fast ? buffer_ : bytes;
|
||||
|
||||
WriteLittleEndian64ToArray(value, ptr);
|
||||
|
||||
if (use_fast) {
|
||||
Advance(sizeof(value));
|
||||
} else {
|
||||
WriteRaw(bytes, sizeof(value));
|
||||
}
|
||||
}
|
||||
|
||||
void CodedOutputStream::WriteVarint32SlowPath(uint32 value) {
|
||||
uint8 bytes[kMaxVarint32Bytes];
|
||||
uint8* target = &bytes[0];
|
||||
uint8* end = WriteVarint32ToArray(value, target);
|
||||
int size = end - target;
|
||||
WriteRaw(bytes, size);
|
||||
}
|
||||
|
||||
void CodedOutputStream::WriteVarint64SlowPath(uint64 value) {
|
||||
uint8 bytes[kMaxVarintBytes];
|
||||
uint8* target = &bytes[0];
|
||||
uint8* end = WriteVarint64ToArray(value, target);
|
||||
int size = end - target;
|
||||
WriteRaw(bytes, size);
|
||||
}
|
||||
|
||||
bool CodedOutputStream::Refresh() {
|
||||
void* void_buffer;
|
||||
if (output_->Next(&void_buffer, &buffer_size_)) {
|
||||
buffer_ = reinterpret_cast<uint8*>(void_buffer);
|
||||
total_bytes_ += buffer_size_;
|
||||
return true;
|
||||
} else {
|
||||
buffer_ = NULL;
|
||||
buffer_size_ = 0;
|
||||
had_error_ = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
uint8* CodedOutputStream::WriteStringWithSizeToArray(const string& str,
|
||||
uint8* target) {
|
||||
GOOGLE_DCHECK_LE(str.size(), kuint32max);
|
||||
target = WriteVarint32ToArray(str.size(), target);
|
||||
return WriteStringToArray(str, target);
|
||||
}
|
||||
|
||||
} // namespace io
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
389
third_party/protobuf-lite/common.cc
vendored
Normal file
389
third_party/protobuf-lite/common.cc
vendored
Normal file
@ -0,0 +1,389 @@
|
||||
// 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)
|
||||
|
||||
#include <google/protobuf/message_lite.h> // TODO(gerbens) ideally remove this.
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/once.h>
|
||||
#include <google/protobuf/stubs/status.h>
|
||||
#include <google/protobuf/stubs/stringpiece.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
#include <google/protobuf/stubs/int128.h>
|
||||
#include <errno.h>
|
||||
#include <sstream>
|
||||
#include <stdio.h>
|
||||
#include <vector>
|
||||
|
||||
#ifdef _WIN32
|
||||
#define WIN32_LEAN_AND_MEAN // We only need minimal includes
|
||||
#include <windows.h>
|
||||
#define snprintf _snprintf // see comment in strutil.cc
|
||||
#elif defined(HAVE_PTHREAD)
|
||||
#include <pthread.h>
|
||||
#else
|
||||
#error "No suitable threading library available."
|
||||
#endif
|
||||
#if defined(__ANDROID__)
|
||||
#include <android/log.h>
|
||||
#endif
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
namespace internal {
|
||||
|
||||
void VerifyVersion(int headerVersion,
|
||||
int minLibraryVersion,
|
||||
const char* filename) {
|
||||
if (GOOGLE_PROTOBUF_VERSION < minLibraryVersion) {
|
||||
// Library is too old for headers.
|
||||
GOOGLE_LOG(FATAL)
|
||||
<< "This program requires version " << VersionString(minLibraryVersion)
|
||||
<< " of the Protocol Buffer runtime library, but the installed version "
|
||||
"is " << VersionString(GOOGLE_PROTOBUF_VERSION) << ". Please update "
|
||||
"your library. If you compiled the program yourself, make sure that "
|
||||
"your headers are from the same version of Protocol Buffers as your "
|
||||
"link-time library. (Version verification failed in \""
|
||||
<< filename << "\".)";
|
||||
}
|
||||
if (headerVersion < kMinHeaderVersionForLibrary) {
|
||||
// Headers are too old for library.
|
||||
GOOGLE_LOG(FATAL)
|
||||
<< "This program was compiled against version "
|
||||
<< VersionString(headerVersion) << " of the Protocol Buffer runtime "
|
||||
"library, which is not compatible with the installed version ("
|
||||
<< VersionString(GOOGLE_PROTOBUF_VERSION) << "). Contact the program "
|
||||
"author for an update. If you compiled the program yourself, make "
|
||||
"sure that your headers are from the same version of Protocol Buffers "
|
||||
"as your link-time library. (Version verification failed in \""
|
||||
<< filename << "\".)";
|
||||
}
|
||||
}
|
||||
|
||||
string VersionString(int version) {
|
||||
int major = version / 1000000;
|
||||
int minor = (version / 1000) % 1000;
|
||||
int micro = version % 1000;
|
||||
|
||||
// 128 bytes should always be enough, but we use snprintf() anyway to be
|
||||
// safe.
|
||||
char buffer[128];
|
||||
snprintf(buffer, sizeof(buffer), "%d.%d.%d", major, minor, micro);
|
||||
|
||||
// Guard against broken MSVC snprintf().
|
||||
buffer[sizeof(buffer)-1] = '\0';
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// ===================================================================
|
||||
// emulates google3/base/logging.cc
|
||||
|
||||
// If the minimum logging level is not set, we default to logging messages for
|
||||
// all levels.
|
||||
#ifndef GOOGLE_PROTOBUF_MIN_LOG_LEVEL
|
||||
#define GOOGLE_PROTOBUF_MIN_LOG_LEVEL LOGLEVEL_INFO
|
||||
#endif
|
||||
|
||||
namespace internal {
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
inline void DefaultLogHandler(LogLevel level, const char* filename, int line,
|
||||
const string& message) {
|
||||
if (level < GOOGLE_PROTOBUF_MIN_LOG_LEVEL) {
|
||||
return;
|
||||
}
|
||||
static const char* level_names[] = {"INFO", "WARNING", "ERROR", "FATAL"};
|
||||
|
||||
static const int android_log_levels[] = {
|
||||
ANDROID_LOG_INFO, // LOG(INFO),
|
||||
ANDROID_LOG_WARN, // LOG(WARNING)
|
||||
ANDROID_LOG_ERROR, // LOG(ERROR)
|
||||
ANDROID_LOG_FATAL, // LOG(FATAL)
|
||||
};
|
||||
|
||||
// Bound the logging level.
|
||||
const int android_log_level = android_log_levels[level];
|
||||
::std::ostringstream ostr;
|
||||
ostr << "[libprotobuf " << level_names[level] << " " << filename << ":"
|
||||
<< line << "] " << message.c_str();
|
||||
|
||||
// Output the log string the Android log at the appropriate level.
|
||||
__android_log_write(android_log_level, "libprotobuf-native",
|
||||
ostr.str().c_str());
|
||||
// Also output to std::cerr.
|
||||
fprintf(stderr, "%s", ostr.str().c_str());
|
||||
fflush(stderr);
|
||||
|
||||
// Indicate termination if needed.
|
||||
if (android_log_level == ANDROID_LOG_FATAL) {
|
||||
__android_log_write(ANDROID_LOG_FATAL, "libprotobuf-native",
|
||||
"terminating.\n");
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
void DefaultLogHandler(LogLevel level, const char* filename, int line,
|
||||
const string& message) {
|
||||
if (level < GOOGLE_PROTOBUF_MIN_LOG_LEVEL) {
|
||||
return;
|
||||
}
|
||||
static const char* level_names[] = { "INFO", "WARNING", "ERROR", "FATAL" };
|
||||
|
||||
// We use fprintf() instead of cerr because we want this to work at static
|
||||
// initialization time.
|
||||
fprintf(stderr, "[libprotobuf %s %s:%d] %s\n",
|
||||
level_names[level], filename, line, message.c_str());
|
||||
fflush(stderr); // Needed on MSVC.
|
||||
}
|
||||
#endif
|
||||
|
||||
void NullLogHandler(LogLevel /* level */, const char* /* filename */,
|
||||
int /* line */, const string& /* message */) {
|
||||
// Nothing.
|
||||
}
|
||||
|
||||
static LogHandler* log_handler_ = &DefaultLogHandler;
|
||||
static int log_silencer_count_ = 0;
|
||||
|
||||
static Mutex* log_silencer_count_mutex_ = NULL;
|
||||
GOOGLE_PROTOBUF_DECLARE_ONCE(log_silencer_count_init_);
|
||||
|
||||
void DeleteLogSilencerCount() {
|
||||
delete log_silencer_count_mutex_;
|
||||
log_silencer_count_mutex_ = NULL;
|
||||
}
|
||||
void InitLogSilencerCount() {
|
||||
log_silencer_count_mutex_ = new Mutex;
|
||||
OnShutdown(&DeleteLogSilencerCount);
|
||||
}
|
||||
void InitLogSilencerCountOnce() {
|
||||
GoogleOnceInit(&log_silencer_count_init_, &InitLogSilencerCount);
|
||||
}
|
||||
|
||||
LogMessage& LogMessage::operator<<(const string& value) {
|
||||
message_ += value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
LogMessage& LogMessage::operator<<(const char* value) {
|
||||
message_ += value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
LogMessage& LogMessage::operator<<(const StringPiece& value) {
|
||||
message_ += value.ToString();
|
||||
return *this;
|
||||
}
|
||||
|
||||
LogMessage& LogMessage::operator<<(
|
||||
const ::google::protobuf::util::Status& status) {
|
||||
message_ += status.ToString();
|
||||
return *this;
|
||||
}
|
||||
|
||||
LogMessage& LogMessage::operator<<(const uint128& value) {
|
||||
std::ostringstream str;
|
||||
str << value;
|
||||
message_ += str.str();
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Since this is just for logging, we don't care if the current locale changes
|
||||
// the results -- in fact, we probably prefer that. So we use snprintf()
|
||||
// instead of Simple*toa().
|
||||
#undef DECLARE_STREAM_OPERATOR
|
||||
#define DECLARE_STREAM_OPERATOR(TYPE, FORMAT) \
|
||||
LogMessage& LogMessage::operator<<(TYPE value) { \
|
||||
/* 128 bytes should be big enough for any of the primitive */ \
|
||||
/* values which we print with this, but well use snprintf() */ \
|
||||
/* anyway to be extra safe. */ \
|
||||
char buffer[128]; \
|
||||
snprintf(buffer, sizeof(buffer), FORMAT, value); \
|
||||
/* Guard against broken MSVC snprintf(). */ \
|
||||
buffer[sizeof(buffer)-1] = '\0'; \
|
||||
message_ += buffer; \
|
||||
return *this; \
|
||||
}
|
||||
|
||||
DECLARE_STREAM_OPERATOR(char , "%c" )
|
||||
DECLARE_STREAM_OPERATOR(int , "%d" )
|
||||
DECLARE_STREAM_OPERATOR(unsigned int , "%u" )
|
||||
DECLARE_STREAM_OPERATOR(long , "%ld")
|
||||
DECLARE_STREAM_OPERATOR(unsigned long, "%lu")
|
||||
DECLARE_STREAM_OPERATOR(double , "%g" )
|
||||
DECLARE_STREAM_OPERATOR(void* , "%p" )
|
||||
DECLARE_STREAM_OPERATOR(long long , "%" GOOGLE_LL_FORMAT "d")
|
||||
DECLARE_STREAM_OPERATOR(unsigned long long, "%" GOOGLE_LL_FORMAT "u")
|
||||
#undef DECLARE_STREAM_OPERATOR
|
||||
|
||||
LogMessage::LogMessage(LogLevel level, const char* filename, int line)
|
||||
: level_(level), filename_(filename), line_(line) {}
|
||||
LogMessage::~LogMessage() {}
|
||||
|
||||
void LogMessage::Finish() {
|
||||
bool suppress = false;
|
||||
|
||||
if (level_ != LOGLEVEL_FATAL) {
|
||||
InitLogSilencerCountOnce();
|
||||
MutexLock lock(log_silencer_count_mutex_);
|
||||
suppress = log_silencer_count_ > 0;
|
||||
}
|
||||
|
||||
if (!suppress) {
|
||||
log_handler_(level_, filename_, line_, message_);
|
||||
}
|
||||
|
||||
if (level_ == LOGLEVEL_FATAL) {
|
||||
#if PROTOBUF_USE_EXCEPTIONS
|
||||
throw FatalException(filename_, line_, message_);
|
||||
#else
|
||||
abort();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void LogFinisher::operator=(LogMessage& other) {
|
||||
other.Finish();
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
LogHandler* SetLogHandler(LogHandler* new_func) {
|
||||
LogHandler* old = internal::log_handler_;
|
||||
if (old == &internal::NullLogHandler) {
|
||||
old = NULL;
|
||||
}
|
||||
if (new_func == NULL) {
|
||||
internal::log_handler_ = &internal::NullLogHandler;
|
||||
} else {
|
||||
internal::log_handler_ = new_func;
|
||||
}
|
||||
return old;
|
||||
}
|
||||
|
||||
LogSilencer::LogSilencer() {
|
||||
internal::InitLogSilencerCountOnce();
|
||||
MutexLock lock(internal::log_silencer_count_mutex_);
|
||||
++internal::log_silencer_count_;
|
||||
};
|
||||
|
||||
LogSilencer::~LogSilencer() {
|
||||
internal::InitLogSilencerCountOnce();
|
||||
MutexLock lock(internal::log_silencer_count_mutex_);
|
||||
--internal::log_silencer_count_;
|
||||
};
|
||||
|
||||
// ===================================================================
|
||||
// emulates google3/base/callback.cc
|
||||
|
||||
Closure::~Closure() {}
|
||||
|
||||
namespace internal { FunctionClosure0::~FunctionClosure0() {} }
|
||||
|
||||
void DoNothing() {}
|
||||
|
||||
// ===================================================================
|
||||
// emulates google3/util/endian/endian.h
|
||||
//
|
||||
// TODO(xiaofeng): PROTOBUF_LITTLE_ENDIAN is unfortunately defined in
|
||||
// google/protobuf/io/coded_stream.h and therefore can not be used here.
|
||||
// Maybe move that macro definition here in the furture.
|
||||
uint32 ghtonl(uint32 x) {
|
||||
union {
|
||||
uint32 result;
|
||||
uint8 result_array[4];
|
||||
};
|
||||
result_array[0] = static_cast<uint8>(x >> 24);
|
||||
result_array[1] = static_cast<uint8>((x >> 16) & 0xFF);
|
||||
result_array[2] = static_cast<uint8>((x >> 8) & 0xFF);
|
||||
result_array[3] = static_cast<uint8>(x & 0xFF);
|
||||
return result;
|
||||
}
|
||||
|
||||
// ===================================================================
|
||||
// Shutdown support.
|
||||
|
||||
namespace internal {
|
||||
|
||||
typedef void OnShutdownFunc();
|
||||
struct ShutdownData {
|
||||
~ShutdownData() {
|
||||
std::reverse(functions.begin(), functions.end());
|
||||
for (auto pair : functions) pair.first(pair.second);
|
||||
}
|
||||
|
||||
static ShutdownData* get() {
|
||||
static auto* data = new ShutdownData;
|
||||
return data;
|
||||
}
|
||||
|
||||
std::vector<std::pair<void (*)(const void*), const void*>> functions;
|
||||
Mutex mutex;
|
||||
};
|
||||
|
||||
static void RunZeroArgFunc(const void* arg) {
|
||||
reinterpret_cast<void (*)()>(const_cast<void*>(arg))();
|
||||
}
|
||||
|
||||
void OnShutdown(void (*func)()) {
|
||||
OnShutdownRun(RunZeroArgFunc, reinterpret_cast<void*>(func));
|
||||
}
|
||||
|
||||
void OnShutdownRun(void (*f)(const void*), const void* arg) {
|
||||
auto shutdown_data = ShutdownData::get();
|
||||
MutexLock lock(&shutdown_data->mutex);
|
||||
shutdown_data->functions.push_back(std::make_pair(f, arg));
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
void ShutdownProtobufLibrary() {
|
||||
// This function should be called only once, but accepts multiple calls.
|
||||
static bool is_shutdown = false;
|
||||
if (!is_shutdown) {
|
||||
delete internal::ShutdownData::get();
|
||||
is_shutdown = true;
|
||||
}
|
||||
}
|
||||
|
||||
#if PROTOBUF_USE_EXCEPTIONS
|
||||
FatalException::~FatalException() throw() {}
|
||||
|
||||
const char* FatalException::what() const throw() {
|
||||
return message_.c_str();
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
1916
third_party/protobuf-lite/extension_set.cc
vendored
Normal file
1916
third_party/protobuf-lite/extension_set.cc
vendored
Normal file
File diff suppressed because it is too large
Load Diff
109
third_party/protobuf-lite/generated_message_table_driven_lite.cc
vendored
Normal file
109
third_party/protobuf-lite/generated_message_table_driven_lite.cc
vendored
Normal file
@ -0,0 +1,109 @@
|
||||
// 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.
|
||||
|
||||
#include <google/protobuf/generated_message_table_driven_lite.h>
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
|
||||
#include <google/protobuf/metadata_lite.h>
|
||||
#include <google/protobuf/repeated_field.h>
|
||||
#include <google/protobuf/wire_format_lite.h>
|
||||
#include <google/protobuf/wire_format_lite_inl.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
namespace {
|
||||
|
||||
string* MutableUnknownFields(MessageLite* msg, int64 arena_offset) {
|
||||
return Raw<InternalMetadataWithArenaLite>(msg, arena_offset)
|
||||
->mutable_unknown_fields();
|
||||
}
|
||||
|
||||
struct UnknownFieldHandlerLite {
|
||||
static bool Skip(MessageLite* msg, const ParseTable& table,
|
||||
io::CodedInputStream* input,
|
||||
int tag) {
|
||||
GOOGLE_DCHECK(!table.unknown_field_set);
|
||||
::google::protobuf::io::StringOutputStream unknown_fields_string(
|
||||
MutableUnknownFields(msg, table.arena_offset));
|
||||
::google::protobuf::io::CodedOutputStream unknown_fields_stream(
|
||||
&unknown_fields_string, false);
|
||||
|
||||
return ::google::protobuf::internal::WireFormatLite::SkipField(
|
||||
input, tag, &unknown_fields_stream);
|
||||
}
|
||||
|
||||
static void Varint(MessageLite* msg, const ParseTable& table,
|
||||
int tag, int value) {
|
||||
GOOGLE_DCHECK(!table.unknown_field_set);
|
||||
|
||||
::google::protobuf::io::StringOutputStream unknown_fields_string(
|
||||
MutableUnknownFields(msg, table.arena_offset));
|
||||
::google::protobuf::io::CodedOutputStream unknown_fields_stream(
|
||||
&unknown_fields_string, false);
|
||||
unknown_fields_stream.WriteVarint32(tag);
|
||||
unknown_fields_stream.WriteVarint32(value);
|
||||
}
|
||||
|
||||
static bool ParseExtension(
|
||||
MessageLite* msg, const ParseTable& table,
|
||||
io::CodedInputStream* input, int tag) {
|
||||
ExtensionSet* extensions = GetExtensionSet(msg, table.extension_offset);
|
||||
if (extensions == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const MessageLite* prototype = table.default_instance();
|
||||
|
||||
GOOGLE_DCHECK(!table.unknown_field_set);
|
||||
::google::protobuf::io::StringOutputStream unknown_fields_string(
|
||||
MutableUnknownFields(msg, table.arena_offset));
|
||||
::google::protobuf::io::CodedOutputStream unknown_fields_stream(
|
||||
&unknown_fields_string, false);
|
||||
return extensions->ParseField(
|
||||
tag, input, prototype, &unknown_fields_stream);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
bool MergePartialFromCodedStreamLite(
|
||||
MessageLite* msg, const ParseTable& table, io::CodedInputStream* input) {
|
||||
return MergePartialFromCodedStreamImpl<UnknownFieldHandlerLite,
|
||||
InternalMetadataWithArenaLite>(
|
||||
msg, table, input);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
814
third_party/protobuf-lite/generated_message_util.cc
vendored
Normal file
814
third_party/protobuf-lite/generated_message_util.cc
vendored
Normal file
@ -0,0 +1,814 @@
|
||||
// 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.
|
||||
|
||||
#include <google/protobuf/generated_message_util.h>
|
||||
|
||||
#include <limits>
|
||||
// We're only using this as a standard way for getting the thread id.
|
||||
// We're not using any thread functionality.
|
||||
#include <thread> // NOLINT
|
||||
#include <vector>
|
||||
|
||||
#include <google/protobuf/io/coded_stream_inl.h>
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/arenastring.h>
|
||||
#include <google/protobuf/extension_set.h>
|
||||
#include <google/protobuf/message_lite.h>
|
||||
#include <google/protobuf/metadata_lite.h>
|
||||
#include <google/protobuf/stubs/mutex.h>
|
||||
#include <google/protobuf/stubs/port.h>
|
||||
#include <google/protobuf/repeated_field.h>
|
||||
#include <google/protobuf/wire_format_lite.h>
|
||||
#include <google/protobuf/wire_format_lite_inl.h>
|
||||
|
||||
namespace google {
|
||||
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
void DestroyMessage(const void* message) {
|
||||
static_cast<const MessageLite*>(message)->~MessageLite();
|
||||
}
|
||||
void DestroyString(const void* s) { static_cast<const string*>(s)->~string(); }
|
||||
|
||||
ExplicitlyConstructed<std::string> fixed_address_empty_string;
|
||||
|
||||
double Infinity() {
|
||||
return std::numeric_limits<double>::infinity();
|
||||
}
|
||||
double NaN() {
|
||||
return std::numeric_limits<double>::quiet_NaN();
|
||||
}
|
||||
|
||||
static bool InitProtobufDefaultsImpl() {
|
||||
fixed_address_empty_string.DefaultConstruct();
|
||||
OnShutdownDestroyString(fixed_address_empty_string.get_mutable());
|
||||
return true;
|
||||
}
|
||||
|
||||
void InitProtobufDefaults() {
|
||||
static bool is_inited = InitProtobufDefaultsImpl();
|
||||
(void)is_inited;
|
||||
}
|
||||
|
||||
size_t StringSpaceUsedExcludingSelfLong(const string& str) {
|
||||
const void* start = &str;
|
||||
const void* end = &str + 1;
|
||||
if (start <= str.data() && str.data() < end) {
|
||||
// The string's data is stored inside the string object itself.
|
||||
return 0;
|
||||
} else {
|
||||
return str.capacity();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
const T& Get(const void* ptr) {
|
||||
return *static_cast<const T*>(ptr);
|
||||
}
|
||||
|
||||
// PrimitiveTypeHelper is a wrapper around the interface of WireFormatLite.
|
||||
// WireFormatLite has a very inconvenient interface with respect to template
|
||||
// meta-programming. This class wraps the different named functions into
|
||||
// a single Serialize / SerializeToArray interface.
|
||||
template <int type>
|
||||
struct PrimitiveTypeHelper;
|
||||
|
||||
template <>
|
||||
struct PrimitiveTypeHelper<WireFormatLite::TYPE_BOOL> {
|
||||
typedef bool Type;
|
||||
static void Serialize(const void* ptr,
|
||||
::google::protobuf::io::CodedOutputStream* output) {
|
||||
WireFormatLite::WriteBoolNoTag(Get<bool>(ptr), output);
|
||||
}
|
||||
static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
|
||||
return WireFormatLite::WriteBoolNoTagToArray(Get<Type>(ptr), buffer);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct PrimitiveTypeHelper<WireFormatLite::TYPE_INT32> {
|
||||
typedef int32 Type;
|
||||
static void Serialize(const void* ptr,
|
||||
::google::protobuf::io::CodedOutputStream* output) {
|
||||
WireFormatLite::WriteInt32NoTag(Get<int32>(ptr), output);
|
||||
}
|
||||
static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
|
||||
return WireFormatLite::WriteInt32NoTagToArray(Get<Type>(ptr), buffer);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct PrimitiveTypeHelper<WireFormatLite::TYPE_SINT32> {
|
||||
typedef int32 Type;
|
||||
static void Serialize(const void* ptr,
|
||||
::google::protobuf::io::CodedOutputStream* output) {
|
||||
WireFormatLite::WriteSInt32NoTag(Get<int32>(ptr), output);
|
||||
}
|
||||
static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
|
||||
return WireFormatLite::WriteSInt32NoTagToArray(Get<Type>(ptr), buffer);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct PrimitiveTypeHelper<WireFormatLite::TYPE_UINT32> {
|
||||
typedef uint32 Type;
|
||||
static void Serialize(const void* ptr,
|
||||
::google::protobuf::io::CodedOutputStream* output) {
|
||||
WireFormatLite::WriteUInt32NoTag(Get<uint32>(ptr), output);
|
||||
}
|
||||
static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
|
||||
return WireFormatLite::WriteUInt32NoTagToArray(Get<Type>(ptr), buffer);
|
||||
}
|
||||
};
|
||||
template <>
|
||||
struct PrimitiveTypeHelper<WireFormatLite::TYPE_INT64> {
|
||||
typedef int64 Type;
|
||||
static void Serialize(const void* ptr,
|
||||
::google::protobuf::io::CodedOutputStream* output) {
|
||||
WireFormatLite::WriteInt64NoTag(Get<int64>(ptr), output);
|
||||
}
|
||||
static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
|
||||
return WireFormatLite::WriteInt64NoTagToArray(Get<Type>(ptr), buffer);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct PrimitiveTypeHelper<WireFormatLite::TYPE_SINT64> {
|
||||
typedef int64 Type;
|
||||
static void Serialize(const void* ptr,
|
||||
::google::protobuf::io::CodedOutputStream* output) {
|
||||
WireFormatLite::WriteSInt64NoTag(Get<int64>(ptr), output);
|
||||
}
|
||||
static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
|
||||
return WireFormatLite::WriteSInt64NoTagToArray(Get<Type>(ptr), buffer);
|
||||
}
|
||||
};
|
||||
template <>
|
||||
struct PrimitiveTypeHelper<WireFormatLite::TYPE_UINT64> {
|
||||
typedef uint64 Type;
|
||||
static void Serialize(const void* ptr,
|
||||
::google::protobuf::io::CodedOutputStream* output) {
|
||||
WireFormatLite::WriteUInt64NoTag(Get<uint64>(ptr), output);
|
||||
}
|
||||
static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
|
||||
return WireFormatLite::WriteUInt64NoTagToArray(Get<Type>(ptr), buffer);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED32> {
|
||||
typedef uint32 Type;
|
||||
static void Serialize(const void* ptr,
|
||||
::google::protobuf::io::CodedOutputStream* output) {
|
||||
WireFormatLite::WriteFixed32NoTag(Get<uint32>(ptr), output);
|
||||
}
|
||||
static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
|
||||
return WireFormatLite::WriteFixed32NoTagToArray(Get<Type>(ptr), buffer);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED64> {
|
||||
typedef uint64 Type;
|
||||
static void Serialize(const void* ptr,
|
||||
::google::protobuf::io::CodedOutputStream* output) {
|
||||
WireFormatLite::WriteFixed64NoTag(Get<uint64>(ptr), output);
|
||||
}
|
||||
static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
|
||||
return WireFormatLite::WriteFixed64NoTagToArray(Get<Type>(ptr), buffer);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct PrimitiveTypeHelper<WireFormatLite::TYPE_ENUM>
|
||||
: PrimitiveTypeHelper<WireFormatLite::TYPE_INT32> {};
|
||||
|
||||
template <>
|
||||
struct PrimitiveTypeHelper<WireFormatLite::TYPE_SFIXED32>
|
||||
: PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED32> {
|
||||
typedef int32 Type;
|
||||
};
|
||||
template <>
|
||||
struct PrimitiveTypeHelper<WireFormatLite::TYPE_SFIXED64>
|
||||
: PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED64> {
|
||||
typedef int64 Type;
|
||||
};
|
||||
template <>
|
||||
struct PrimitiveTypeHelper<WireFormatLite::TYPE_FLOAT>
|
||||
: PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED32> {
|
||||
typedef float Type;
|
||||
};
|
||||
template <>
|
||||
struct PrimitiveTypeHelper<WireFormatLite::TYPE_DOUBLE>
|
||||
: PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED64> {
|
||||
typedef double Type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct PrimitiveTypeHelper<WireFormatLite::TYPE_STRING> {
|
||||
typedef string Type;
|
||||
static void Serialize(const void* ptr,
|
||||
::google::protobuf::io::CodedOutputStream* output) {
|
||||
const Type& value = *static_cast<const Type*>(ptr);
|
||||
output->WriteVarint32(value.size());
|
||||
output->WriteRawMaybeAliased(value.data(), value.size());
|
||||
}
|
||||
static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
|
||||
const Type& value = *static_cast<const Type*>(ptr);
|
||||
return io::CodedOutputStream::WriteStringWithSizeToArray(value, buffer);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct PrimitiveTypeHelper<WireFormatLite::TYPE_BYTES>
|
||||
: PrimitiveTypeHelper<WireFormatLite::TYPE_STRING> {};
|
||||
|
||||
|
||||
template <>
|
||||
struct PrimitiveTypeHelper<FieldMetadata::kInlinedType>
|
||||
: PrimitiveTypeHelper<WireFormatLite::TYPE_STRING> {};
|
||||
|
||||
// We want to serialize to both CodedOutputStream and directly into byte arrays
|
||||
// without duplicating the code. In fact we might want extra output channels in
|
||||
// the future.
|
||||
template <typename O, int type>
|
||||
struct OutputHelper;
|
||||
|
||||
template <int type, typename O>
|
||||
void SerializeTo(const void* ptr, O* output) {
|
||||
OutputHelper<O, type>::Serialize(ptr, output);
|
||||
}
|
||||
|
||||
template <typename O>
|
||||
void WriteTagTo(uint32 tag, O* output) {
|
||||
SerializeTo<WireFormatLite::TYPE_UINT32>(&tag, output);
|
||||
}
|
||||
|
||||
template <typename O>
|
||||
void WriteLengthTo(uint32 length, O* output) {
|
||||
SerializeTo<WireFormatLite::TYPE_UINT32>(&length, output);
|
||||
}
|
||||
|
||||
// Specialization for coded output stream
|
||||
template <int type>
|
||||
struct OutputHelper<::google::protobuf::io::CodedOutputStream, type> {
|
||||
static void Serialize(const void* ptr,
|
||||
::google::protobuf::io::CodedOutputStream* output) {
|
||||
PrimitiveTypeHelper<type>::Serialize(ptr, output);
|
||||
}
|
||||
};
|
||||
|
||||
// Specialization for writing into a plain array
|
||||
struct ArrayOutput {
|
||||
uint8* ptr;
|
||||
bool is_deterministic;
|
||||
};
|
||||
|
||||
template <int type>
|
||||
struct OutputHelper<ArrayOutput, type> {
|
||||
static void Serialize(const void* ptr, ArrayOutput* output) {
|
||||
output->ptr = PrimitiveTypeHelper<type>::SerializeToArray(ptr, output->ptr);
|
||||
}
|
||||
};
|
||||
|
||||
void SerializeMessageNoTable(const MessageLite* msg,
|
||||
::google::protobuf::io::CodedOutputStream* output) {
|
||||
msg->SerializeWithCachedSizes(output);
|
||||
}
|
||||
|
||||
void SerializeMessageNoTable(const MessageLite* msg, ArrayOutput* output) {
|
||||
output->ptr = msg->InternalSerializeWithCachedSizesToArray(
|
||||
output->is_deterministic, output->ptr);
|
||||
}
|
||||
|
||||
// Helper to branch to fast path if possible
|
||||
void SerializeMessageDispatch(const ::google::protobuf::MessageLite& msg,
|
||||
const FieldMetadata* field_table, int num_fields,
|
||||
int32 cached_size,
|
||||
::google::protobuf::io::CodedOutputStream* output) {
|
||||
const uint8* base = reinterpret_cast<const uint8*>(&msg);
|
||||
// Try the fast path
|
||||
uint8* ptr = output->GetDirectBufferForNBytesAndAdvance(cached_size);
|
||||
if (ptr) {
|
||||
// We use virtual dispatch to enable dedicated generated code for the
|
||||
// fast path.
|
||||
msg.InternalSerializeWithCachedSizesToArray(
|
||||
output->IsSerializationDeterministic(), ptr);
|
||||
return;
|
||||
}
|
||||
SerializeInternal(base, field_table, num_fields, output);
|
||||
}
|
||||
|
||||
// Helper to branch to fast path if possible
|
||||
void SerializeMessageDispatch(const ::google::protobuf::MessageLite& msg,
|
||||
const FieldMetadata* field_table, int num_fields,
|
||||
int32 cached_size, ArrayOutput* output) {
|
||||
const uint8* base = reinterpret_cast<const uint8*>(&msg);
|
||||
output->ptr = SerializeInternalToArray(base, field_table, num_fields,
|
||||
output->is_deterministic, output->ptr);
|
||||
}
|
||||
|
||||
// Serializing messages is special as it's not a primitive type and needs an
|
||||
// explicit overload for each output type.
|
||||
template <typename O>
|
||||
void SerializeMessageTo(const MessageLite* msg, const void* table_ptr,
|
||||
O* output) {
|
||||
const SerializationTable* table =
|
||||
static_cast<const SerializationTable*>(table_ptr);
|
||||
if (!table) {
|
||||
// Proto1
|
||||
WriteLengthTo(msg->GetCachedSize(), output);
|
||||
SerializeMessageNoTable(msg, output);
|
||||
return;
|
||||
}
|
||||
const FieldMetadata* field_table = table->field_table;
|
||||
const uint8* base = reinterpret_cast<const uint8*>(msg);
|
||||
int cached_size = *reinterpret_cast<const int32*>(base + field_table->offset);
|
||||
WriteLengthTo(cached_size, output);
|
||||
int num_fields = table->num_fields - 1;
|
||||
SerializeMessageDispatch(*msg, field_table + 1, num_fields, cached_size,
|
||||
output);
|
||||
}
|
||||
|
||||
// Almost the same as above only it doesn't output the length field.
|
||||
template <typename O>
|
||||
void SerializeGroupTo(const MessageLite* msg, const void* table_ptr,
|
||||
O* output) {
|
||||
const SerializationTable* table =
|
||||
static_cast<const SerializationTable*>(table_ptr);
|
||||
if (!table) {
|
||||
// Proto1
|
||||
SerializeMessageNoTable(msg, output);
|
||||
return;
|
||||
}
|
||||
const FieldMetadata* field_table = table->field_table;
|
||||
const uint8* base = reinterpret_cast<const uint8*>(msg);
|
||||
int cached_size = *reinterpret_cast<const int32*>(base + field_table->offset);
|
||||
int num_fields = table->num_fields - 1;
|
||||
SerializeMessageDispatch(*msg, field_table + 1, num_fields, cached_size,
|
||||
output);
|
||||
}
|
||||
|
||||
template <int type>
|
||||
struct SingularFieldHelper {
|
||||
template <typename O>
|
||||
static void Serialize(const void* field, const FieldMetadata& md, O* output) {
|
||||
WriteTagTo(md.tag, output);
|
||||
SerializeTo<type>(field, output);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct SingularFieldHelper<WireFormatLite::TYPE_STRING> {
|
||||
template <typename O>
|
||||
static void Serialize(const void* field, const FieldMetadata& md, O* output) {
|
||||
WriteTagTo(md.tag, output);
|
||||
SerializeTo<WireFormatLite::TYPE_STRING>(&Get<ArenaStringPtr>(field).Get(),
|
||||
output);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct SingularFieldHelper<WireFormatLite::TYPE_BYTES>
|
||||
: SingularFieldHelper<WireFormatLite::TYPE_STRING> {};
|
||||
|
||||
template <>
|
||||
struct SingularFieldHelper<WireFormatLite::TYPE_GROUP> {
|
||||
template <typename O>
|
||||
static void Serialize(const void* field, const FieldMetadata& md, O* output) {
|
||||
WriteTagTo(md.tag, output);
|
||||
SerializeGroupTo(Get<const MessageLite*>(field),
|
||||
static_cast<const SerializationTable*>(md.ptr), output);
|
||||
WriteTagTo(md.tag + 1, output);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct SingularFieldHelper<WireFormatLite::TYPE_MESSAGE> {
|
||||
template <typename O>
|
||||
static void Serialize(const void* field, const FieldMetadata& md, O* output) {
|
||||
WriteTagTo(md.tag, output);
|
||||
SerializeMessageTo(Get<const MessageLite*>(field),
|
||||
static_cast<const SerializationTable*>(md.ptr), output);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct SingularFieldHelper<FieldMetadata::kInlinedType> {
|
||||
template <typename O>
|
||||
static void Serialize(const void* field, const FieldMetadata& md, O* output) {
|
||||
WriteTagTo(md.tag, output);
|
||||
SerializeTo<FieldMetadata::kInlinedType>(&Get<::std::string>(field), output);
|
||||
}
|
||||
};
|
||||
|
||||
template <int type>
|
||||
struct RepeatedFieldHelper {
|
||||
template <typename O>
|
||||
static void Serialize(const void* field, const FieldMetadata& md, O* output) {
|
||||
typedef typename PrimitiveTypeHelper<type>::Type T;
|
||||
const RepeatedField<T>& array = Get<RepeatedField<T> >(field);
|
||||
for (int i = 0; i < array.size(); i++) {
|
||||
WriteTagTo(md.tag, output);
|
||||
SerializeTo<type>(&array[i], output);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// We need to use a helper class to get access to the private members
|
||||
class AccessorHelper {
|
||||
public:
|
||||
static int Size(const RepeatedPtrFieldBase& x) { return x.size(); }
|
||||
static void const* Get(const RepeatedPtrFieldBase& x, int idx) {
|
||||
return x.raw_data()[idx];
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct RepeatedFieldHelper<WireFormatLite::TYPE_STRING> {
|
||||
template <typename O>
|
||||
static void Serialize(const void* field, const FieldMetadata& md, O* output) {
|
||||
const internal::RepeatedPtrFieldBase& array =
|
||||
Get<internal::RepeatedPtrFieldBase>(field);
|
||||
for (int i = 0; i < AccessorHelper::Size(array); i++) {
|
||||
WriteTagTo(md.tag, output);
|
||||
SerializeTo<WireFormatLite::TYPE_STRING>(AccessorHelper::Get(array, i),
|
||||
output);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct RepeatedFieldHelper<WireFormatLite::TYPE_BYTES>
|
||||
: RepeatedFieldHelper<WireFormatLite::TYPE_STRING> {};
|
||||
|
||||
template <>
|
||||
struct RepeatedFieldHelper<WireFormatLite::TYPE_GROUP> {
|
||||
template <typename O>
|
||||
static void Serialize(const void* field, const FieldMetadata& md, O* output) {
|
||||
const internal::RepeatedPtrFieldBase& array =
|
||||
Get<internal::RepeatedPtrFieldBase>(field);
|
||||
for (int i = 0; i < AccessorHelper::Size(array); i++) {
|
||||
WriteTagTo(md.tag, output);
|
||||
SerializeGroupTo(
|
||||
static_cast<const MessageLite*>(AccessorHelper::Get(array, i)),
|
||||
static_cast<const SerializationTable*>(md.ptr), output);
|
||||
WriteTagTo(md.tag + 1, output);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct RepeatedFieldHelper<WireFormatLite::TYPE_MESSAGE> {
|
||||
template <typename O>
|
||||
static void Serialize(const void* field, const FieldMetadata& md, O* output) {
|
||||
const internal::RepeatedPtrFieldBase& array =
|
||||
Get<internal::RepeatedPtrFieldBase>(field);
|
||||
for (int i = 0; i < AccessorHelper::Size(array); i++) {
|
||||
WriteTagTo(md.tag, output);
|
||||
SerializeMessageTo(
|
||||
static_cast<const MessageLite*>(AccessorHelper::Get(array, i)), md.ptr,
|
||||
output);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <>
|
||||
struct RepeatedFieldHelper<FieldMetadata::kInlinedType>
|
||||
: RepeatedFieldHelper<WireFormatLite::TYPE_STRING> {};
|
||||
|
||||
template <int type>
|
||||
struct PackedFieldHelper {
|
||||
template <typename O>
|
||||
static void Serialize(const void* field, const FieldMetadata& md, O* output) {
|
||||
typedef typename PrimitiveTypeHelper<type>::Type T;
|
||||
const RepeatedField<T>& array = Get<RepeatedField<T> >(field);
|
||||
if (array.empty()) return;
|
||||
WriteTagTo(md.tag, output);
|
||||
int cached_size =
|
||||
Get<int>(static_cast<const uint8*>(field) + sizeof(RepeatedField<T>));
|
||||
WriteLengthTo(cached_size, output);
|
||||
for (int i = 0; i < array.size(); i++) {
|
||||
SerializeTo<type>(&array[i], output);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct PackedFieldHelper<WireFormatLite::TYPE_STRING> {
|
||||
template <typename O>
|
||||
static void Serialize(const void* field, const FieldMetadata& md, O* output) {
|
||||
GOOGLE_LOG(FATAL) << "Not implemented field number " << md.tag << " with type "
|
||||
<< md.type;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct PackedFieldHelper<WireFormatLite::TYPE_BYTES>
|
||||
: PackedFieldHelper<WireFormatLite::TYPE_STRING> {};
|
||||
template <>
|
||||
struct PackedFieldHelper<WireFormatLite::TYPE_GROUP>
|
||||
: PackedFieldHelper<WireFormatLite::TYPE_STRING> {};
|
||||
template <>
|
||||
struct PackedFieldHelper<WireFormatLite::TYPE_MESSAGE>
|
||||
: PackedFieldHelper<WireFormatLite::TYPE_STRING> {};
|
||||
template <>
|
||||
struct PackedFieldHelper<FieldMetadata::kInlinedType>
|
||||
: PackedFieldHelper<WireFormatLite::TYPE_STRING> {};
|
||||
|
||||
template <int type>
|
||||
struct OneOfFieldHelper {
|
||||
template <typename O>
|
||||
static void Serialize(const void* field, const FieldMetadata& md, O* output) {
|
||||
SingularFieldHelper<type>::Serialize(field, md, output);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <>
|
||||
struct OneOfFieldHelper<FieldMetadata::kInlinedType> {
|
||||
template <typename O>
|
||||
static void Serialize(const void* field, const FieldMetadata& md, O* output) {
|
||||
SingularFieldHelper<FieldMetadata::kInlinedType>::Serialize(
|
||||
Get<const ::std::string*>(field), md, output);
|
||||
}
|
||||
};
|
||||
|
||||
void SerializeNotImplemented(int field) {
|
||||
GOOGLE_LOG(FATAL) << "Not implemented field number " << field;
|
||||
}
|
||||
|
||||
// When switching to c++11 we should make these constexpr functions
|
||||
#define SERIALIZE_TABLE_OP(type, type_class) \
|
||||
((type - 1) + static_cast<int>(type_class) * FieldMetadata::kNumTypes)
|
||||
|
||||
int FieldMetadata::CalculateType(int type,
|
||||
FieldMetadata::FieldTypeClass type_class) {
|
||||
return SERIALIZE_TABLE_OP(type, type_class);
|
||||
}
|
||||
|
||||
template <int type>
|
||||
bool IsNull(const void* ptr) {
|
||||
return *static_cast<const typename PrimitiveTypeHelper<type>::Type*>(ptr) ==
|
||||
0;
|
||||
}
|
||||
|
||||
template <>
|
||||
bool IsNull<WireFormatLite::TYPE_STRING>(const void* ptr) {
|
||||
return static_cast<const ArenaStringPtr*>(ptr)->Get().size() == 0;
|
||||
}
|
||||
|
||||
template <>
|
||||
bool IsNull<WireFormatLite::TYPE_BYTES>(const void* ptr) {
|
||||
return static_cast<const ArenaStringPtr*>(ptr)->Get().size() == 0;
|
||||
}
|
||||
|
||||
template <>
|
||||
bool IsNull<WireFormatLite::TYPE_GROUP>(const void* ptr) {
|
||||
return Get<const MessageLite*>(ptr) == NULL;
|
||||
}
|
||||
|
||||
template <>
|
||||
bool IsNull<WireFormatLite::TYPE_MESSAGE>(const void* ptr) {
|
||||
return Get<const MessageLite*>(ptr) == NULL;
|
||||
}
|
||||
|
||||
|
||||
template <>
|
||||
bool IsNull<FieldMetadata::kInlinedType>(const void* ptr) {
|
||||
return static_cast<const ::std::string*>(ptr)->empty();
|
||||
}
|
||||
|
||||
#define SERIALIZERS_FOR_TYPE(type) \
|
||||
case SERIALIZE_TABLE_OP(type, FieldMetadata::kPresence): \
|
||||
if (!IsPresent(base, field_metadata.has_offset)) continue; \
|
||||
SingularFieldHelper<type>::Serialize(ptr, field_metadata, output); \
|
||||
break; \
|
||||
case SERIALIZE_TABLE_OP(type, FieldMetadata::kNoPresence): \
|
||||
if (IsNull<type>(ptr)) continue; \
|
||||
SingularFieldHelper<type>::Serialize(ptr, field_metadata, output); \
|
||||
break; \
|
||||
case SERIALIZE_TABLE_OP(type, FieldMetadata::kRepeated): \
|
||||
RepeatedFieldHelper<type>::Serialize(ptr, field_metadata, output); \
|
||||
break; \
|
||||
case SERIALIZE_TABLE_OP(type, FieldMetadata::kPacked): \
|
||||
PackedFieldHelper<type>::Serialize(ptr, field_metadata, output); \
|
||||
break; \
|
||||
case SERIALIZE_TABLE_OP(type, FieldMetadata::kOneOf): \
|
||||
if (!IsOneofPresent(base, field_metadata.has_offset, field_metadata.tag)) \
|
||||
continue; \
|
||||
OneOfFieldHelper<type>::Serialize(ptr, field_metadata, output); \
|
||||
break
|
||||
|
||||
void SerializeInternal(const uint8* base,
|
||||
const FieldMetadata* field_metadata_table,
|
||||
int32 num_fields,
|
||||
::google::protobuf::io::CodedOutputStream* output) {
|
||||
for (int i = 0; i < num_fields; i++) {
|
||||
const FieldMetadata& field_metadata = field_metadata_table[i];
|
||||
const uint8* ptr = base + field_metadata.offset;
|
||||
switch (field_metadata.type) {
|
||||
SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_DOUBLE);
|
||||
SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_FLOAT);
|
||||
SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_INT64);
|
||||
SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_UINT64);
|
||||
SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_INT32);
|
||||
SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_FIXED64);
|
||||
SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_FIXED32);
|
||||
SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_BOOL);
|
||||
SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_STRING);
|
||||
SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_GROUP);
|
||||
SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_MESSAGE);
|
||||
SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_BYTES);
|
||||
SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_UINT32);
|
||||
SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_ENUM);
|
||||
SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SFIXED32);
|
||||
SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SFIXED64);
|
||||
SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SINT32);
|
||||
SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SINT64);
|
||||
SERIALIZERS_FOR_TYPE(FieldMetadata::kInlinedType);
|
||||
|
||||
// Special cases
|
||||
case FieldMetadata::kSpecial:
|
||||
reinterpret_cast<SpecialSerializer>(
|
||||
const_cast<void*>(field_metadata.ptr))(
|
||||
base, field_metadata.offset, field_metadata.tag,
|
||||
field_metadata.has_offset, output);
|
||||
break;
|
||||
default:
|
||||
// __builtin_unreachable()
|
||||
SerializeNotImplemented(field_metadata.type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8* SerializeInternalToArray(const uint8* base,
|
||||
const FieldMetadata* field_metadata_table,
|
||||
int32 num_fields, bool is_deterministic,
|
||||
uint8* buffer) {
|
||||
ArrayOutput array_output = {buffer, is_deterministic};
|
||||
ArrayOutput* output = &array_output;
|
||||
for (int i = 0; i < num_fields; i++) {
|
||||
const FieldMetadata& field_metadata = field_metadata_table[i];
|
||||
const uint8* ptr = base + field_metadata.offset;
|
||||
switch (field_metadata.type) {
|
||||
SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_DOUBLE);
|
||||
SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_FLOAT);
|
||||
SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_INT64);
|
||||
SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_UINT64);
|
||||
SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_INT32);
|
||||
SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_FIXED64);
|
||||
SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_FIXED32);
|
||||
SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_BOOL);
|
||||
SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_STRING);
|
||||
SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_GROUP);
|
||||
SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_MESSAGE);
|
||||
SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_BYTES);
|
||||
SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_UINT32);
|
||||
SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_ENUM);
|
||||
SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SFIXED32);
|
||||
SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SFIXED64);
|
||||
SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SINT32);
|
||||
SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SINT64);
|
||||
SERIALIZERS_FOR_TYPE(FieldMetadata::kInlinedType);
|
||||
// Special cases
|
||||
case FieldMetadata::kSpecial: {
|
||||
io::ArrayOutputStream array_stream(array_output.ptr, INT_MAX);
|
||||
io::CodedOutputStream output(&array_stream);
|
||||
output.SetSerializationDeterministic(is_deterministic);
|
||||
reinterpret_cast<SpecialSerializer>(
|
||||
const_cast<void*>(field_metadata.ptr))(
|
||||
base, field_metadata.offset, field_metadata.tag,
|
||||
field_metadata.has_offset, &output);
|
||||
array_output.ptr += output.ByteCount();
|
||||
} break;
|
||||
default:
|
||||
// __builtin_unreachable()
|
||||
SerializeNotImplemented(field_metadata.type);
|
||||
}
|
||||
}
|
||||
return array_output.ptr;
|
||||
}
|
||||
#undef SERIALIZERS_FOR_TYPE
|
||||
|
||||
void ExtensionSerializer(const uint8* ptr, uint32 offset, uint32 tag,
|
||||
uint32 has_offset,
|
||||
::google::protobuf::io::CodedOutputStream* output) {
|
||||
reinterpret_cast<const ExtensionSet*>(ptr + offset)
|
||||
->SerializeWithCachedSizes(tag, has_offset, output);
|
||||
}
|
||||
|
||||
void UnknownFieldSerializerLite(const uint8* ptr, uint32 offset, uint32 tag,
|
||||
uint32 has_offset,
|
||||
::google::protobuf::io::CodedOutputStream* output) {
|
||||
output->WriteString(
|
||||
reinterpret_cast<const InternalMetadataWithArenaLite*>(ptr + offset)
|
||||
->unknown_fields());
|
||||
}
|
||||
|
||||
MessageLite* DuplicateIfNonNullInternal(MessageLite* message) {
|
||||
if (message) {
|
||||
MessageLite* ret = message->New();
|
||||
ret->CheckTypeAndMergeFrom(*message);
|
||||
return ret;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Returns a message owned by this Arena. This may require Own()ing or
|
||||
// duplicating the message.
|
||||
MessageLite* GetOwnedMessageInternal(Arena* message_arena,
|
||||
MessageLite* submessage,
|
||||
Arena* submessage_arena) {
|
||||
GOOGLE_DCHECK(submessage->GetArena() == submessage_arena);
|
||||
GOOGLE_DCHECK(message_arena != submessage_arena);
|
||||
if (message_arena != NULL && submessage_arena == NULL) {
|
||||
message_arena->Own(submessage);
|
||||
return submessage;
|
||||
} else {
|
||||
MessageLite* ret = submessage->New(message_arena);
|
||||
ret->CheckTypeAndMergeFrom(*submessage);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
void InitSCC_DFS(SCCInfoBase* scc) {
|
||||
if (scc->visit_status.load(std::memory_order_relaxed) !=
|
||||
SCCInfoBase::kUninitialized) return;
|
||||
scc->visit_status.store(SCCInfoBase::kRunning, std::memory_order_relaxed);
|
||||
// Each base is followed by an array of pointers to deps
|
||||
auto deps = reinterpret_cast<SCCInfoBase* const*>(scc + 1);
|
||||
for (int i = 0; i < scc->num_deps; i++) {
|
||||
if (deps[i]) InitSCC_DFS(deps[i]);
|
||||
}
|
||||
scc->init_func();
|
||||
// Mark done (note we use memory order release here), other threads could
|
||||
// now see this as initialized and thus the initialization must have happened
|
||||
// before.
|
||||
scc->visit_status.store(SCCInfoBase::kInitialized, std::memory_order_release);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void InitSCCImpl(SCCInfoBase* scc) {
|
||||
static WrappedMutex mu{GOOGLE_PROTOBUF_LINKER_INITIALIZED};
|
||||
// Either the default in case no initialization is running or the id of the
|
||||
// thread that is currently initializing.
|
||||
static std::atomic<std::thread::id> runner;
|
||||
auto me = std::this_thread::get_id();
|
||||
// This will only happen because the constructor will call InitSCC while
|
||||
// constructing the default instance.
|
||||
if (runner.load(std::memory_order_relaxed) == me) {
|
||||
// Because we're in the process of constructing the default instance.
|
||||
// We can be assured that we're already exploring this SCC.
|
||||
GOOGLE_CHECK_EQ(scc->visit_status.load(std::memory_order_relaxed),
|
||||
SCCInfoBase::kRunning);
|
||||
return;
|
||||
}
|
||||
InitProtobufDefaults();
|
||||
mu.Lock();
|
||||
runner.store(me, std::memory_order_relaxed);
|
||||
InitSCC_DFS(scc);
|
||||
runner.store(std::thread::id{}, std::memory_order_relaxed);
|
||||
mu.Unlock();
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
703
third_party/protobuf-lite/google/protobuf/arena.h
vendored
Normal file
703
third_party/protobuf-lite/google/protobuf/arena.h
vendored
Normal file
@ -0,0 +1,703 @@
|
||||
// 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>
|
||||
#ifdef max
|
||||
#undef max // Visual Studio defines this macro
|
||||
#endif
|
||||
#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 <google/protobuf/arena_impl.h>
|
||||
#include <google/protobuf/stubs/port.h>
|
||||
#include <type_traits>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
struct ArenaOptions; // defined below
|
||||
|
||||
} // namespace protobuf
|
||||
|
||||
namespace quality_webanswers {
|
||||
|
||||
void TempPrivateWorkAround(::google::protobuf::ArenaOptions* arena_options);
|
||||
|
||||
} // namespace quality_webanswers
|
||||
|
||||
namespace protobuf {
|
||||
|
||||
class Arena; // defined below
|
||||
class Message; // defined in message.h
|
||||
class MessageLite;
|
||||
|
||||
namespace arena_metrics {
|
||||
|
||||
void EnableArenaMetrics(::google::protobuf::ArenaOptions* options);
|
||||
|
||||
} // namespace arena_metrics
|
||||
|
||||
namespace internal {
|
||||
|
||||
struct ArenaStringPtr; // defined in arenastring.h
|
||||
class LazyField; // defined in lazy_field.h
|
||||
|
||||
template <typename Type>
|
||||
class GenericTypeHandler; // defined in repeated_field.h
|
||||
|
||||
// Templated cleanup methods.
|
||||
template <typename T>
|
||||
void arena_destruct_object(void* object) {
|
||||
reinterpret_cast<T*>(object)->~T();
|
||||
}
|
||||
template <typename T>
|
||||
void arena_delete_object(void* object) {
|
||||
delete reinterpret_cast<T*>(object);
|
||||
}
|
||||
inline void arena_free(void* object, size_t size) {
|
||||
#if defined(__GXX_DELETE_WITH_SIZE__) || defined(__cpp_sized_deallocation)
|
||||
::operator delete(object, size);
|
||||
#else
|
||||
(void)size;
|
||||
::operator delete(object);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // 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(kDefaultStartBlockSize),
|
||||
max_block_size(kDefaultMaxBlockSize),
|
||||
initial_block(NULL),
|
||||
initial_block_size(0),
|
||||
block_alloc(&::operator new),
|
||||
block_dealloc(&internal::arena_free),
|
||||
on_arena_init(NULL),
|
||||
on_arena_reset(NULL),
|
||||
on_arena_destruction(NULL),
|
||||
on_arena_allocation(NULL) {}
|
||||
|
||||
private:
|
||||
// Hooks for adding external functionality such as user-specific metrics
|
||||
// collection, specific debugging abilities, etc.
|
||||
// Init hook may return a pointer to a cookie to be stored in the arena.
|
||||
// reset and destruction hooks will then be called with the same cookie
|
||||
// pointer. This allows us to save an external object per arena instance and
|
||||
// use it on the other hooks (Note: It is just as legal for init to return
|
||||
// NULL and not use the cookie feature).
|
||||
// on_arena_reset and on_arena_destruction also receive the space used in
|
||||
// the arena just before the reset.
|
||||
void* (*on_arena_init)(Arena* arena);
|
||||
void (*on_arena_reset)(Arena* arena, void* cookie, uint64 space_used);
|
||||
void (*on_arena_destruction)(Arena* arena, void* cookie, uint64 space_used);
|
||||
|
||||
// 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)
|
||||
void (*on_arena_allocation)(const std::type_info* allocated_type,
|
||||
uint64 alloc_size, void* cookie);
|
||||
|
||||
// Constants define default starting block size and max block size for
|
||||
// arena allocator behavior -- see descriptions above.
|
||||
static const size_t kDefaultStartBlockSize = 256;
|
||||
static const size_t kDefaultMaxBlockSize = 8192;
|
||||
|
||||
friend void ::google::protobuf::arena_metrics::EnableArenaMetrics(ArenaOptions*);
|
||||
friend void quality_webanswers::TempPrivateWorkAround(ArenaOptions*);
|
||||
friend class Arena;
|
||||
friend class ArenaOptionsTestFriend;
|
||||
};
|
||||
|
||||
// Support for non-RTTI environments. (The metrics hooks API uses type
|
||||
// information.)
|
||||
#ifndef GOOGLE_PROTOBUF_NO_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>, is as
|
||||
// follows:
|
||||
//
|
||||
// - The type T must have (at least) two constructors: a constructor with no
|
||||
// arguments, called when a T is allocated on the heap; and a constructor with
|
||||
// a google::protobuf::Arena* argument, 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 (no-argument) 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.
|
||||
//
|
||||
// - One- and two-user-argument forms of CreateMessage<T>() also exist that
|
||||
// forward these constructor arguments to T's constructor: for example,
|
||||
// CreateMessage<T>(Arena*, arg1, arg2) forwards to a constructor T(Arena*,
|
||||
// arg1, arg2).
|
||||
//
|
||||
// This protocol is implemented by all arena-enabled proto2 message classes as
|
||||
// well as RepeatedPtrField.
|
||||
//
|
||||
// Do NOT subclass Arena. This class will be marked as final when C++11 is
|
||||
// enabled.
|
||||
class LIBPROTOBUF_EXPORT Arena {
|
||||
public:
|
||||
// Arena constructor taking custom options. See ArenaOptions below for
|
||||
// descriptions of the options available.
|
||||
explicit Arena(const ArenaOptions& options) : impl_(options) {
|
||||
Init(options);
|
||||
}
|
||||
|
||||
// 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::ArenaImpl::kBlockHeaderSize +
|
||||
internal::ArenaImpl::kSerialArenaSize;
|
||||
|
||||
// Default constructor with sensible default options, tuned for average
|
||||
// use-cases.
|
||||
Arena() : impl_(ArenaOptions()) { Init(ArenaOptions()); }
|
||||
|
||||
~Arena() {
|
||||
if (hooks_cookie_) {
|
||||
CallDestructorHooks();
|
||||
}
|
||||
}
|
||||
|
||||
void Init(const ArenaOptions& options) {
|
||||
on_arena_allocation_ = options.on_arena_allocation;
|
||||
on_arena_reset_ = options.on_arena_reset;
|
||||
on_arena_destruction_ = options.on_arena_destruction;
|
||||
// Call the initialization hook
|
||||
if (options.on_arena_init != NULL) {
|
||||
hooks_cookie_ = options.on_arena_init(this);
|
||||
} else {
|
||||
hooks_cookie_ = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// 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>
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_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, std::forward<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>
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE static T* Create(Arena* arena,
|
||||
Args&&... args) {
|
||||
return CreateNoMessage<T>(arena, is_arena_constructable<T>(),
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
// 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>
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE static T* CreateArray(
|
||||
Arena* arena, size_t num_elements) {
|
||||
static_assert(std::is_pod<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);
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the total space allocated by the arena, which is the sum of the
|
||||
// sizes of the underlying blocks. This method is relatively fast; a counter
|
||||
// is kept as blocks are allocated.
|
||||
uint64 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 SpaceUsed() const { return impl_.SpaceUsed(); }
|
||||
// DEPRECATED. Please use SpaceAllocated() and SpaceUsed().
|
||||
//
|
||||
// Combines SpaceAllocated and SpaceUsed. Returns a pair of
|
||||
// <space_allocated, space_used>.
|
||||
PROTOBUF_RUNTIME_DEPRECATED("Please use SpaceAllocated() and SpaceUsed()")
|
||||
std::pair<uint64, uint64> SpaceAllocatedAndUsed() const {
|
||||
return std::make_pair(SpaceAllocated(), 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.
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE uint64 Reset() {
|
||||
// Call the reset hook
|
||||
if (on_arena_reset_ != NULL) {
|
||||
on_arena_reset_(this, hooks_cookie_, impl_.SpaceAllocated());
|
||||
}
|
||||
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>
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE void Own(T* object) {
|
||||
OwnInternal(object, std::is_convertible<T*, Message*>());
|
||||
}
|
||||
|
||||
// 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>
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE 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.
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE 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. This differs from value->GetArena() in that the
|
||||
// latter is a virtual call, while this method is a templated call that
|
||||
// resolves at compile-time.
|
||||
template <typename T>
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE static Arena* GetArena(
|
||||
const T* value) {
|
||||
return GetArenaInternal(value, is_arena_constructable<T>());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
class InternalHelper {
|
||||
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... Args>
|
||||
static T* Construct(void* ptr, Args&&... args) {
|
||||
return new (ptr) T(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
static Arena* GetArena(const T* p) { return p->GetArenaNoVirtual(); }
|
||||
|
||||
friend class Arena;
|
||||
};
|
||||
|
||||
// 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:
|
||||
template <typename T, typename... Args>
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_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, std::forward<Args>(args)...);
|
||||
} else {
|
||||
return arena->DoCreateMessage<T>(std::forward<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>
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_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) {
|
||||
return new T();
|
||||
} else {
|
||||
return arena->DoCreateMessage<T>();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE static T* CreateInternal(
|
||||
Arena* arena, Args&&... args) {
|
||||
if (arena == NULL) {
|
||||
return new T(std::forward<Args>(args)...);
|
||||
} else {
|
||||
return arena->DoCreate<T>(std::is_trivially_destructible<T>::value,
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
}
|
||||
|
||||
void CallDestructorHooks();
|
||||
void OnArenaAllocation(const std::type_info* allocated_type, size_t n) const;
|
||||
inline void AllocHook(const std::type_info* allocated_type, size_t n) const {
|
||||
if (GOOGLE_PREDICT_FALSE(hooks_cookie_ != NULL)) {
|
||||
OnArenaAllocation(allocated_type, n);
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate and also optionally call on_arena_allocation callback with the
|
||||
// allocated type info when the hooks are in place in ArenaOptions and
|
||||
// the cookie is not null.
|
||||
template <typename T>
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE void* AllocateInternal(
|
||||
bool skip_explicit_ownership) {
|
||||
const size_t n = internal::AlignUpTo8(sizeof(T));
|
||||
AllocHook(RTTI_TYPE_ID(T), n);
|
||||
// Monitor allocation if needed.
|
||||
if (skip_explicit_ownership) {
|
||||
return impl_.AllocateAligned(n);
|
||||
} else {
|
||||
return impl_.AllocateAlignedAndAddCleanup(
|
||||
n, &internal::arena_destruct_object<T>);
|
||||
}
|
||||
}
|
||||
|
||||
// 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>
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_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>
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE static T* DoCreateMaybeMessage(
|
||||
Arena* arena, std::false_type, Args&&... args) {
|
||||
return CreateInternal<T>(arena, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE static T* CreateMaybeMessage(
|
||||
Arena* arena, Args&&... args) {
|
||||
return DoCreateMaybeMessage<T>(arena, is_arena_constructable<T>(),
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE static T* CreateNoMessage(
|
||||
Arena* arena, std::true_type, Args&&... args) {
|
||||
// User is constructing with Create() despite the fact that T supports arena
|
||||
// construction. In this case we have to delegate to CreateInternal(), and
|
||||
// we can't use any CreateMaybeMessage() specialization that may be defined.
|
||||
return CreateInternal<T>(arena, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE static T* CreateNoMessage(
|
||||
Arena* arena, std::false_type, Args&&... args) {
|
||||
// User is constructing with Create() and the type does not support arena
|
||||
// construction. In this case we can delegate to CreateMaybeMessage() and
|
||||
// use any specialization that may be available for that.
|
||||
return CreateMaybeMessage<T>(arena, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
// Just allocate the required size for the given type assuming the
|
||||
// type has a trivial constructor.
|
||||
template <typename T>
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_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.";
|
||||
const size_t n = internal::AlignUpTo8(sizeof(T) * num_elements);
|
||||
// Monitor allocation if needed.
|
||||
AllocHook(RTTI_TYPE_ID(T), n);
|
||||
return static_cast<T*>(impl_.AllocateAligned(n));
|
||||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE T* DoCreate(
|
||||
bool skip_explicit_ownership, Args&&... args) {
|
||||
return new (AllocateInternal<T>(skip_explicit_ownership))
|
||||
T(std::forward<Args>(args)...);
|
||||
}
|
||||
template <typename T, typename... Args>
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE T* DoCreateMessage(Args&&... args) {
|
||||
return InternalHelper<T>::Construct(
|
||||
AllocateInternal<T>(InternalHelper<T>::is_destructor_skippable::value),
|
||||
this, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
// CreateInArenaStorage is used to implement map field. Without it,
|
||||
// google::protobuf::Map need to call generated message's protected arena constructor,
|
||||
// which needs to declare google::protobuf::Map as friend of generated message.
|
||||
template <typename T>
|
||||
static void CreateInArenaStorage(T* ptr, Arena* arena) {
|
||||
CreateInArenaStorageInternal(ptr, arena,
|
||||
typename is_arena_constructable<T>::type());
|
||||
RegisterDestructorInternal(
|
||||
ptr, arena,
|
||||
typename InternalHelper<T>::is_destructor_skippable::type());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static void CreateInArenaStorageInternal(T* ptr, Arena* arena,
|
||||
std::true_type) {
|
||||
InternalHelper<T>::Construct(ptr, arena);
|
||||
}
|
||||
template <typename T>
|
||||
static void CreateInArenaStorageInternal(T* ptr, Arena* /* arena */,
|
||||
std::false_type) {
|
||||
new (ptr) T();
|
||||
}
|
||||
|
||||
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 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 ::google::protobuf::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>
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE void OwnInternal(T* object,
|
||||
std::true_type) {
|
||||
if (object != NULL) {
|
||||
impl_.AddCleanup(object, &internal::arena_delete_object<Message>);
|
||||
}
|
||||
}
|
||||
template <typename T>
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_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 GetArenaNoVirtual() method.
|
||||
template <typename T>
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE static Arena* GetArenaInternal(
|
||||
const T* value, std::true_type) {
|
||||
return InternalHelper<T>::GetArena(value);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE static Arena* GetArenaInternal(
|
||||
const T* /* value */, std::false_type) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// For friends of arena.
|
||||
void* AllocateAligned(size_t n) {
|
||||
AllocHook(NULL, n);
|
||||
return impl_.AllocateAligned(internal::AlignUpTo8(n));
|
||||
}
|
||||
|
||||
internal::ArenaImpl impl_;
|
||||
|
||||
void (*on_arena_allocation_)(const std::type_info* allocated_type,
|
||||
uint64 alloc_size, void* cookie);
|
||||
void (*on_arena_reset_)(Arena* arena, void* cookie, uint64 space_used);
|
||||
void (*on_arena_destruction_)(Arena* arena, void* cookie, uint64 space_used);
|
||||
|
||||
// The arena may save a cookie it receives from the external on_init hook
|
||||
// and then use it when calling the on_reset and on_destruction hooks.
|
||||
void* hooks_cookie_;
|
||||
|
||||
template <typename Type>
|
||||
friend class internal::GenericTypeHandler;
|
||||
friend struct internal::ArenaStringPtr; // For AllocateAligned.
|
||||
friend class internal::LazyField; // For CreateMaybeMessage.
|
||||
friend class MessageLite;
|
||||
template <typename Key, typename T>
|
||||
friend class Map;
|
||||
};
|
||||
|
||||
// Defined above for supporting environments without RTTI.
|
||||
#undef RTTI_TYPE_ID
|
||||
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_ARENA_H__
|
321
third_party/protobuf-lite/google/protobuf/arena_impl.h
vendored
Normal file
321
third_party/protobuf-lite/google/protobuf/arena_impl.h
vendored
Normal file
@ -0,0 +1,321 @@
|
||||
// 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 <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
|
||||
|
||||
namespace google {
|
||||
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
inline size_t AlignUpTo8(size_t n) {
|
||||
// Align n to next multiple of 8 (from Hacker's Delight, Chapter 3.)
|
||||
return (n + 7) & -8;
|
||||
}
|
||||
|
||||
// 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 LIBPROTOBUF_EXPORT ArenaImpl {
|
||||
public:
|
||||
struct Options {
|
||||
size_t start_block_size;
|
||||
size_t max_block_size;
|
||||
char* initial_block;
|
||||
size_t initial_block_size;
|
||||
void* (*block_alloc)(size_t);
|
||||
void (*block_dealloc)(void*, size_t);
|
||||
|
||||
template <typename O>
|
||||
explicit Options(const O& options)
|
||||
: start_block_size(options.start_block_size),
|
||||
max_block_size(options.max_block_size),
|
||||
initial_block(options.initial_block),
|
||||
initial_block_size(options.initial_block_size),
|
||||
block_alloc(options.block_alloc),
|
||||
block_dealloc(options.block_dealloc) {}
|
||||
};
|
||||
|
||||
template <typename O>
|
||||
explicit ArenaImpl(const O& options) : options_(options) {
|
||||
if (options_.initial_block != NULL && options_.initial_block_size > 0) {
|
||||
GOOGLE_CHECK_GE(options_.initial_block_size, sizeof(Block))
|
||||
<< ": Initial block size too small for header.";
|
||||
initial_block_ = reinterpret_cast<Block*>(options_.initial_block);
|
||||
} else {
|
||||
initial_block_ = NULL;
|
||||
}
|
||||
|
||||
Init();
|
||||
}
|
||||
|
||||
// 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.
|
||||
~ArenaImpl();
|
||||
|
||||
uint64 Reset();
|
||||
|
||||
uint64 SpaceAllocated() const;
|
||||
uint64 SpaceUsed() const;
|
||||
|
||||
void* AllocateAligned(size_t n);
|
||||
|
||||
void* AllocateAlignedAndAddCleanup(size_t n, void (*cleanup)(void*));
|
||||
|
||||
// Add object pointer and cleanup function pointer to the list.
|
||||
void AddCleanup(void* elem, void (*cleanup)(void*));
|
||||
|
||||
private:
|
||||
void* AllocateAlignedFallback(size_t n);
|
||||
void* AllocateAlignedAndAddCleanupFallback(size_t n, void (*cleanup)(void*));
|
||||
void AddCleanupFallback(void* elem, void (*cleanup)(void*));
|
||||
|
||||
// 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.
|
||||
};
|
||||
|
||||
// Cleanup uses a chunked linked list, to reduce pointer chasing.
|
||||
struct CleanupChunk {
|
||||
static size_t SizeOf(size_t i) {
|
||||
return sizeof(CleanupChunk) + (sizeof(CleanupNode) * (i - 1));
|
||||
}
|
||||
size_t size; // Total elements in the list.
|
||||
CleanupChunk* next; // Next node in the list.
|
||||
CleanupNode nodes[1]; // True length is |size|.
|
||||
};
|
||||
|
||||
class Block;
|
||||
|
||||
// A thread-unsafe Arena that can only be used within its owning thread.
|
||||
class LIBPROTOBUF_EXPORT SerialArena {
|
||||
public:
|
||||
// The allocate/free methods here are a little strange, since SerialArena is
|
||||
// allocated inside a Block which it also manages. This is to avoid doing
|
||||
// an extra allocation for the SerialArena itself.
|
||||
|
||||
// Creates a new SerialArena inside Block* and returns it.
|
||||
static SerialArena* New(Block* b, void* owner, ArenaImpl* arena);
|
||||
|
||||
// Destroys this SerialArena, freeing all blocks with the given dealloc
|
||||
// function, except any block equal to |initial_block|.
|
||||
static uint64 Free(SerialArena* serial, Block* initial_block,
|
||||
void (*block_dealloc)(void*, size_t));
|
||||
|
||||
void CleanupList();
|
||||
uint64 SpaceUsed() const;
|
||||
|
||||
void* AllocateAligned(size_t n) {
|
||||
GOOGLE_DCHECK_EQ(internal::AlignUpTo8(n), n); // Must be already aligned.
|
||||
GOOGLE_DCHECK_GE(limit_, ptr_);
|
||||
if (GOOGLE_PREDICT_FALSE(static_cast<size_t>(limit_ - ptr_) < n)) {
|
||||
return AllocateAlignedFallback(n);
|
||||
}
|
||||
void* ret = ptr_;
|
||||
ptr_ += n;
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
ASAN_UNPOISON_MEMORY_REGION(ret, n);
|
||||
#endif // ADDRESS_SANITIZER
|
||||
return ret;
|
||||
}
|
||||
|
||||
void AddCleanup(void* elem, void (*cleanup)(void*)) {
|
||||
if (GOOGLE_PREDICT_FALSE(cleanup_ptr_ == cleanup_limit_)) {
|
||||
AddCleanupFallback(elem, cleanup);
|
||||
return;
|
||||
}
|
||||
cleanup_ptr_->elem = elem;
|
||||
cleanup_ptr_->cleanup = cleanup;
|
||||
cleanup_ptr_++;
|
||||
}
|
||||
|
||||
void* AllocateAlignedAndAddCleanup(size_t n, void (*cleanup)(void*)) {
|
||||
void* ret = AllocateAligned(n);
|
||||
AddCleanup(ret, cleanup);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void* owner() const { return owner_; }
|
||||
SerialArena* next() const { return next_; }
|
||||
void set_next(SerialArena* next) { next_ = next; }
|
||||
|
||||
private:
|
||||
void* AllocateAlignedFallback(size_t n);
|
||||
void AddCleanupFallback(void* elem, void (*cleanup)(void*));
|
||||
void CleanupListFallback();
|
||||
|
||||
ArenaImpl* arena_; // Containing arena.
|
||||
void* owner_; // &ThreadCache of this thread;
|
||||
Block* head_; // Head of linked list of blocks.
|
||||
CleanupChunk* cleanup_; // Head of cleanup list.
|
||||
SerialArena* next_; // Next SerialArena in this linked list.
|
||||
|
||||
// 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_;
|
||||
char* limit_;
|
||||
|
||||
// Next CleanupList members to append to. These point inside cleanup_.
|
||||
CleanupNode* cleanup_ptr_;
|
||||
CleanupNode* cleanup_limit_;
|
||||
};
|
||||
|
||||
// Blocks are variable length malloc-ed objects. The following structure
|
||||
// describes the common header for all blocks.
|
||||
class LIBPROTOBUF_EXPORT Block {
|
||||
public:
|
||||
Block(size_t size, Block* next);
|
||||
|
||||
char* Pointer(size_t n) {
|
||||
GOOGLE_DCHECK(n <= size_);
|
||||
return reinterpret_cast<char*>(this) + n;
|
||||
}
|
||||
|
||||
Block* next() const { return next_; }
|
||||
size_t pos() const { return pos_; }
|
||||
size_t size() const { return size_; }
|
||||
void set_pos(size_t pos) { pos_ = pos; }
|
||||
|
||||
private:
|
||||
Block* next_; // Next block for this thread.
|
||||
size_t pos_;
|
||||
size_t size_;
|
||||
// data follows
|
||||
};
|
||||
|
||||
struct 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() : last_lifecycle_id_seen(-1), last_serial_arena(NULL) {}
|
||||
#endif
|
||||
|
||||
// The ThreadCache is considered valid as long as this matches the
|
||||
// lifecycle_id of the arena being used.
|
||||
int64 last_lifecycle_id_seen;
|
||||
SerialArena* last_serial_arena;
|
||||
};
|
||||
static std::atomic<int64> lifecycle_id_generator_;
|
||||
#if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL)
|
||||
// Android ndk does not support GOOGLE_THREAD_LOCAL keyword so we use a custom thread
|
||||
// local storage class we implemented.
|
||||
// iOS also does not support the GOOGLE_THREAD_LOCAL keyword.
|
||||
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 GOOGLE_THREAD_LOCAL ThreadCache thread_cache_;
|
||||
static ThreadCache& thread_cache() { return thread_cache_; }
|
||||
#endif
|
||||
|
||||
void Init();
|
||||
|
||||
// Free all blocks and return the total space used which is the sums of sizes
|
||||
// of the all the allocated blocks.
|
||||
uint64 FreeBlocks();
|
||||
// Delete or Destruct all objects owned by the arena.
|
||||
void CleanupList();
|
||||
|
||||
inline void CacheSerialArena(SerialArena* serial) {
|
||||
thread_cache().last_serial_arena = serial;
|
||||
thread_cache().last_lifecycle_id_seen = lifecycle_id_;
|
||||
// TODO(haberman): evaluate whether we would gain efficiency by getting rid
|
||||
// of hint_. It's the only write we do to ArenaImpl in the allocation path,
|
||||
// which will dirty the cache line.
|
||||
|
||||
hint_.store(serial, std::memory_order_release);
|
||||
}
|
||||
|
||||
|
||||
std::atomic<SerialArena*>
|
||||
threads_; // Pointer to a linked list of SerialArena.
|
||||
std::atomic<SerialArena*> hint_; // Fast thread-local block access
|
||||
std::atomic<size_t> space_allocated_; // Total size of all allocated blocks.
|
||||
|
||||
Block *initial_block_; // If non-NULL, points to the block that came from
|
||||
// user data.
|
||||
|
||||
Block* NewBlock(Block* last_block, size_t min_bytes);
|
||||
|
||||
SerialArena* GetSerialArena();
|
||||
bool GetSerialArenaFast(SerialArena** arena);
|
||||
SerialArena* GetSerialArenaFallback(void* me);
|
||||
int64 lifecycle_id_; // Unique for each arena. Changes on Reset().
|
||||
|
||||
Options options_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ArenaImpl);
|
||||
// All protos have pointers back to the arena hence Arena must have
|
||||
// pointer stability.
|
||||
ArenaImpl(ArenaImpl&&) = delete;
|
||||
ArenaImpl& operator=(ArenaImpl&&) = 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 const size_t kBlockHeaderSize = (sizeof(Block) + 7) & -8;
|
||||
static const size_t kSerialArenaSize = (sizeof(SerialArena) + 7) & -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
|
||||
#endif // GOOGLE_PROTOBUF_ARENA_IMPL_H__
|
403
third_party/protobuf-lite/google/protobuf/arenastring.h
vendored
Normal file
403
third_party/protobuf-lite/google/protobuf/arenastring.h
vendored
Normal file
@ -0,0 +1,403 @@
|
||||
// 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 <string>
|
||||
|
||||
#include <google/protobuf/arena.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/fastmem.h>
|
||||
#include <google/protobuf/stubs/logging.h>
|
||||
#include <google/protobuf/stubs/port.h>
|
||||
|
||||
// This is the implementation of arena string fields written for the open-source
|
||||
// release. The ArenaStringPtr struct below is an internal implementation class
|
||||
// and *should not be used* by user code. It is used to collect string
|
||||
// operations together into one place and abstract away the underlying
|
||||
// string-field pointer representation, so that (for example) an alternate
|
||||
// implementation that knew more about ::std::string's internals could integrate more
|
||||
// closely with the arena allocator.
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
template <typename T>
|
||||
class TaggedPtr {
|
||||
public:
|
||||
void Set(T* p) { ptr_ = reinterpret_cast<uintptr_t>(p); }
|
||||
T* Get() const { return reinterpret_cast<T*>(ptr_); }
|
||||
|
||||
bool IsNull() { return ptr_ == 0; }
|
||||
|
||||
private:
|
||||
uintptr_t ptr_;
|
||||
};
|
||||
|
||||
struct LIBPROTOBUF_EXPORT ArenaStringPtr {
|
||||
inline void Set(const ::std::string* default_value,
|
||||
const ::std::string& value, ::google::protobuf::Arena* arena) {
|
||||
if (ptr_ == default_value) {
|
||||
CreateInstance(arena, &value);
|
||||
} else {
|
||||
*ptr_ = value;
|
||||
}
|
||||
}
|
||||
|
||||
inline void SetLite(const ::std::string* default_value,
|
||||
const ::std::string& value,
|
||||
::google::protobuf::Arena* arena) {
|
||||
Set(default_value, value, arena);
|
||||
}
|
||||
|
||||
// Basic accessors.
|
||||
inline const ::std::string& Get() const { return *ptr_; }
|
||||
|
||||
inline ::std::string* Mutable(const ::std::string* default_value,
|
||||
::google::protobuf::Arena* arena) {
|
||||
if (ptr_ == default_value) {
|
||||
CreateInstance(arena, default_value);
|
||||
}
|
||||
return ptr_;
|
||||
}
|
||||
|
||||
// Release returns a ::std::string* instance that is heap-allocated and is not
|
||||
// Own()'d by any arena. If the field was not set, it returns NULL. The caller
|
||||
// retains ownership. Clears this field back to NULL state. Used to implement
|
||||
// release_<field>() methods on generated classes.
|
||||
inline ::std::string* Release(const ::std::string* default_value,
|
||||
::google::protobuf::Arena* arena) {
|
||||
if (ptr_ == default_value) {
|
||||
return NULL;
|
||||
}
|
||||
return ReleaseNonDefault(default_value, arena);
|
||||
}
|
||||
|
||||
// Similar to Release, but ptr_ cannot be the default_value.
|
||||
inline ::std::string* ReleaseNonDefault(
|
||||
const ::std::string* default_value, ::google::protobuf::Arena* arena) {
|
||||
GOOGLE_DCHECK(!IsDefault(default_value));
|
||||
::std::string* released = NULL;
|
||||
if (arena != NULL) {
|
||||
// ptr_ is owned by the arena.
|
||||
released = new ::std::string;
|
||||
released->swap(*ptr_);
|
||||
} else {
|
||||
released = ptr_;
|
||||
}
|
||||
ptr_ = const_cast< ::std::string* >(default_value);
|
||||
return released;
|
||||
}
|
||||
|
||||
// UnsafeArenaRelease returns a ::std::string*, but it may be arena-owned (i.e.
|
||||
// have its destructor already registered) if arena != NULL. If the field was
|
||||
// not set, this returns NULL. This method clears this field back to NULL
|
||||
// state. Used to implement unsafe_arena_release_<field>() methods on
|
||||
// generated classes.
|
||||
inline ::std::string* UnsafeArenaRelease(const ::std::string* default_value,
|
||||
::google::protobuf::Arena* /* arena */) {
|
||||
if (ptr_ == default_value) {
|
||||
return NULL;
|
||||
}
|
||||
::std::string* released = ptr_;
|
||||
ptr_ = const_cast< ::std::string* >(default_value);
|
||||
return released;
|
||||
}
|
||||
|
||||
// Takes a string that is heap-allocated, and takes ownership. The string's
|
||||
// destructor is registered with the arena. Used to implement
|
||||
// set_allocated_<field> in generated classes.
|
||||
inline void SetAllocated(const ::std::string* default_value,
|
||||
::std::string* value, ::google::protobuf::Arena* arena) {
|
||||
if (arena == NULL && ptr_ != default_value) {
|
||||
Destroy(default_value, arena);
|
||||
}
|
||||
if (value != NULL) {
|
||||
ptr_ = value;
|
||||
if (arena != NULL) {
|
||||
arena->Own(value);
|
||||
}
|
||||
} else {
|
||||
ptr_ = const_cast< ::std::string* >(default_value);
|
||||
}
|
||||
}
|
||||
|
||||
// Takes a string that has lifetime equal to the arena's lifetime. The arena
|
||||
// must be non-null. It is safe only to pass this method a value returned by
|
||||
// UnsafeArenaRelease() on another field of a message in the same arena. Used
|
||||
// to implement unsafe_arena_set_allocated_<field> in generated classes.
|
||||
inline void UnsafeArenaSetAllocated(const ::std::string* default_value,
|
||||
::std::string* value,
|
||||
::google::protobuf::Arena* /* arena */) {
|
||||
if (value != NULL) {
|
||||
ptr_ = value;
|
||||
} else {
|
||||
ptr_ = const_cast< ::std::string* >(default_value);
|
||||
}
|
||||
}
|
||||
|
||||
// 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.
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE void Swap(ArenaStringPtr* other) {
|
||||
std::swap(ptr_, other->ptr_);
|
||||
}
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE void Swap(
|
||||
ArenaStringPtr* other, const ::std::string* default_value, Arena* arena) {
|
||||
#ifndef NDEBUG
|
||||
// For debug builds, we swap the contents of the string, rather than the
|
||||
// string instances themselves. This invalidates previously taken const
|
||||
// references that are (per our documentation) invalidated by calling Swap()
|
||||
// on the message.
|
||||
//
|
||||
// If both strings are the default_value, swapping is uninteresting.
|
||||
// Otherwise, we use ArenaStringPtr::Mutable() to access the string, to
|
||||
// ensure that we do not try to mutate default_value itself.
|
||||
if (IsDefault(default_value) && other->IsDefault(default_value)) {
|
||||
return;
|
||||
}
|
||||
|
||||
::std::string* this_ptr = Mutable(default_value, arena);
|
||||
::std::string* other_ptr = other->Mutable(default_value, arena);
|
||||
|
||||
this_ptr->swap(*other_ptr);
|
||||
#else
|
||||
std::swap(ptr_, other->ptr_);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Frees storage (if not on an arena).
|
||||
inline void Destroy(const ::std::string* default_value,
|
||||
::google::protobuf::Arena* arena) {
|
||||
if (arena == NULL && ptr_ != default_value) {
|
||||
delete ptr_;
|
||||
}
|
||||
}
|
||||
|
||||
// Clears content, but keeps allocated string if arena != NULL, to avoid the
|
||||
// overhead of heap operations. After this returns, the content (as seen by
|
||||
// the user) will always be the empty string. Assumes that |default_value|
|
||||
// is an empty string.
|
||||
inline void ClearToEmpty(const ::std::string* default_value,
|
||||
::google::protobuf::Arena* /* arena */) {
|
||||
if (ptr_ == default_value) {
|
||||
// Already set to default (which is empty) -- do nothing.
|
||||
} else {
|
||||
ptr_->clear();
|
||||
}
|
||||
}
|
||||
|
||||
// Clears content, assuming that the current value is not the empty string
|
||||
// default.
|
||||
inline void ClearNonDefaultToEmpty() {
|
||||
ptr_->clear();
|
||||
}
|
||||
inline void ClearNonDefaultToEmptyNoArena() {
|
||||
ptr_->clear();
|
||||
}
|
||||
|
||||
// Clears content, but keeps allocated string if arena != NULL, to avoid the
|
||||
// overhead of heap operations. After this returns, the content (as seen by
|
||||
// the user) will always be equal to |default_value|.
|
||||
inline void ClearToDefault(const ::std::string* default_value,
|
||||
::google::protobuf::Arena* /* arena */) {
|
||||
if (ptr_ == default_value) {
|
||||
// Already set to default -- do nothing.
|
||||
} else {
|
||||
// Have another allocated string -- rather than throwing this away and
|
||||
// resetting ptr_ to the canonical default string instance, we just reuse
|
||||
// this instance.
|
||||
*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 UnsafeSetDefault(const ::std::string* default_value) {
|
||||
// Casting away 'const' is safe here: accessors ensure that ptr_ is only
|
||||
// returned as a const if it is equal to default_value.
|
||||
ptr_ = const_cast< ::std::string* >(default_value);
|
||||
}
|
||||
|
||||
// The 'NoArena' variants of methods below assume arena == NULL and are
|
||||
// optimized to provide very little overhead relative to a raw string pointer
|
||||
// (while still being in-memory compatible with other code that assumes
|
||||
// ArenaStringPtr). Note the invariant that a class instance that has only
|
||||
// ever been mutated by NoArena methods must *only* be in the String state
|
||||
// (i.e., tag bits are not used), *NEVER* ArenaString. This allows all
|
||||
// tagged-pointer manipulations to be avoided.
|
||||
inline void SetNoArena(const ::std::string* default_value,
|
||||
const ::std::string& value) {
|
||||
if (ptr_ == default_value) {
|
||||
CreateInstanceNoArena(&value);
|
||||
} else {
|
||||
*ptr_ = value;
|
||||
}
|
||||
}
|
||||
|
||||
#if LANG_CXX11
|
||||
void SetNoArena(const ::std::string* default_value, ::std::string&& value) {
|
||||
if (IsDefault(default_value)) {
|
||||
ptr_ = new ::std::string(std::move(value));
|
||||
} else {
|
||||
*ptr_ = std::move(value);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void AssignWithDefault(const ::std::string* default_value, ArenaStringPtr value);
|
||||
|
||||
inline const ::std::string& GetNoArena() const { return *ptr_; }
|
||||
|
||||
inline ::std::string* MutableNoArena(const ::std::string* default_value) {
|
||||
if (ptr_ == default_value) {
|
||||
CreateInstanceNoArena(default_value);
|
||||
}
|
||||
return ptr_;
|
||||
}
|
||||
|
||||
inline ::std::string* ReleaseNoArena(const ::std::string* default_value) {
|
||||
if (ptr_ == default_value) {
|
||||
return NULL;
|
||||
} else {
|
||||
return ReleaseNonDefaultNoArena(default_value);
|
||||
}
|
||||
}
|
||||
|
||||
inline ::std::string* ReleaseNonDefaultNoArena(
|
||||
const ::std::string* default_value) {
|
||||
GOOGLE_DCHECK(!IsDefault(default_value));
|
||||
::std::string* released = ptr_;
|
||||
ptr_ = const_cast< ::std::string* >(default_value);
|
||||
return released;
|
||||
}
|
||||
|
||||
|
||||
inline void SetAllocatedNoArena(const ::std::string* default_value,
|
||||
::std::string* value) {
|
||||
if (ptr_ != default_value) {
|
||||
delete ptr_;
|
||||
}
|
||||
if (value != NULL) {
|
||||
ptr_ = value;
|
||||
} else {
|
||||
ptr_ = const_cast< ::std::string* >(default_value);
|
||||
}
|
||||
}
|
||||
|
||||
inline void DestroyNoArena(const ::std::string* default_value) {
|
||||
if (ptr_ != default_value) {
|
||||
delete ptr_;
|
||||
}
|
||||
}
|
||||
|
||||
inline void ClearToEmptyNoArena(const ::std::string* default_value) {
|
||||
if (ptr_ == default_value) {
|
||||
// Nothing: already equal to default (which is the empty string).
|
||||
} else {
|
||||
ptr_->clear();
|
||||
}
|
||||
}
|
||||
|
||||
inline void ClearToDefaultNoArena(const ::std::string* default_value) {
|
||||
if (ptr_ == default_value) {
|
||||
// Nothing: already set to default.
|
||||
} else {
|
||||
// Reuse existing allocated instance.
|
||||
*ptr_ = *default_value;
|
||||
}
|
||||
}
|
||||
|
||||
// Internal accessor used only at parse time to provide direct access to the
|
||||
// raw pointer from the shared parse routine (in the non-arenas case). The
|
||||
// parse routine does the string allocation in order to save code size in the
|
||||
// generated parsing code.
|
||||
inline ::std::string** UnsafeRawStringPointer() {
|
||||
return &ptr_;
|
||||
}
|
||||
|
||||
inline bool IsDefault(const ::std::string* default_value) const {
|
||||
return ptr_ == default_value;
|
||||
}
|
||||
|
||||
// Internal accessors!!!!
|
||||
void UnsafeSetTaggedPointer(TaggedPtr< ::std::string> value) {
|
||||
ptr_ = value.Get();
|
||||
}
|
||||
// Generated code only! An optimization, in certain cases the generated
|
||||
// code is certain we can obtain a string with no default checks and
|
||||
// tag tests.
|
||||
::std::string* UnsafeMutablePointer() { return ptr_; }
|
||||
|
||||
private:
|
||||
::std::string* ptr_;
|
||||
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE
|
||||
void CreateInstance(::google::protobuf::Arena* arena,
|
||||
const ::std::string* initial_value) {
|
||||
GOOGLE_DCHECK(initial_value != NULL);
|
||||
// uses "new ::std::string" when arena is nullptr
|
||||
ptr_ = Arena::Create< ::std::string >(arena, *initial_value);
|
||||
}
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE
|
||||
void CreateInstanceNoArena(const ::std::string* initial_value) {
|
||||
GOOGLE_DCHECK(initial_value != NULL);
|
||||
ptr_ = new ::std::string(*initial_value);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
|
||||
|
||||
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
inline void ArenaStringPtr::AssignWithDefault(const ::std::string* default_value,
|
||||
ArenaStringPtr value) {
|
||||
const ::std::string* me = *UnsafeRawStringPointer();
|
||||
const ::std::string* other = *value.UnsafeRawStringPointer();
|
||||
// If the pointers are the same then do nothing.
|
||||
if (me != other) {
|
||||
SetNoArena(default_value, value.GetNoArena());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_ARENASTRING_H__
|
1462
third_party/protobuf-lite/google/protobuf/extension_set.h
vendored
Normal file
1462
third_party/protobuf-lite/google/protobuf/extension_set.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
46
third_party/protobuf-lite/google/protobuf/generated_enum_util.h
vendored
Normal file
46
third_party/protobuf-lite/google/protobuf/generated_enum_util.h
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
// 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>
|
||||
|
||||
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 protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_GENERATED_ENUM_UTIL_H__
|
200
third_party/protobuf-lite/google/protobuf/generated_message_table_driven.h
vendored
Normal file
200
third_party/protobuf-lite/google/protobuf/generated_message_table_driven.h
vendored
Normal file
@ -0,0 +1,200 @@
|
||||
// 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_TABLE_DRIVEN_H__
|
||||
#define GOOGLE_PROTOBUF_GENERATED_MESSAGE_TABLE_DRIVEN_H__
|
||||
|
||||
#include <google/protobuf/map.h>
|
||||
#include <google/protobuf/map_entry_lite.h>
|
||||
#include <google/protobuf/map_field_lite.h>
|
||||
#include <google/protobuf/message_lite.h>
|
||||
#include <google/protobuf/wire_format_lite.h>
|
||||
#include <google/protobuf/wire_format_lite_inl.h>
|
||||
|
||||
// We require C++11 and Clang to use constexpr for variables, as GCC 4.8
|
||||
// requires constexpr to be consistent between declarations of variables
|
||||
// unnecessarily (see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58541).
|
||||
// VS 2017 Update 3 also supports this usage of constexpr.
|
||||
#if defined(__clang__) || (defined(_MSC_VER) && _MSC_VER >= 1911)
|
||||
#define PROTOBUF_CONSTEXPR_VAR constexpr
|
||||
#else // !__clang__
|
||||
#define PROTOBUF_CONSTEXPR_VAR
|
||||
#endif // !_clang
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
// Processing-type masks.
|
||||
static constexpr const unsigned char kOneofMask = 0x40;
|
||||
static constexpr const unsigned char kRepeatedMask = 0x20;
|
||||
// Mask for the raw type: either a WireFormatLite::FieldType or one of the
|
||||
// ProcessingTypes below, without the oneof or repeated flag.
|
||||
static constexpr const unsigned char kTypeMask = 0x1f;
|
||||
|
||||
// Wire type masks.
|
||||
static constexpr const unsigned char kNotPackedMask = 0x10;
|
||||
static constexpr const unsigned char kInvalidMask = 0x20;
|
||||
|
||||
enum ProcessingTypes {
|
||||
TYPE_STRING_INLINED = 23,
|
||||
TYPE_BYTES_INLINED = 24,
|
||||
TYPE_MAP = 25,
|
||||
};
|
||||
|
||||
static_assert(TYPE_MAP < kRepeatedMask, "Invalid enum");
|
||||
|
||||
// TODO(ckennelly): Add a static assertion to ensure that these masks do not
|
||||
// conflict with wiretypes.
|
||||
|
||||
// ParseTableField is kept small to help simplify instructions for computing
|
||||
// offsets, as we will always need this information to parse a field.
|
||||
// Additional data, needed for some types, is stored in
|
||||
// AuxillaryParseTableField.
|
||||
struct ParseTableField {
|
||||
uint32 offset;
|
||||
// The presence_index ordinarily represents a has_bit index, but for fields
|
||||
// inside a oneof it represents the index in _oneof_case_.
|
||||
uint32 presence_index;
|
||||
unsigned char normal_wiretype;
|
||||
unsigned char packed_wiretype;
|
||||
|
||||
// processing_type is given by:
|
||||
// (FieldDescriptor->type() << 1) | FieldDescriptor->is_packed()
|
||||
unsigned char processing_type;
|
||||
|
||||
unsigned char tag_size;
|
||||
};
|
||||
|
||||
struct ParseTable;
|
||||
|
||||
union AuxillaryParseTableField {
|
||||
typedef bool (*EnumValidator)(int);
|
||||
|
||||
// Enums
|
||||
struct enum_aux {
|
||||
EnumValidator validator;
|
||||
};
|
||||
enum_aux enums;
|
||||
// Group, messages
|
||||
struct message_aux {
|
||||
// ExplicitlyInitialized<T> -> T requires a reinterpret_cast, which prevents
|
||||
// the tables from being constructed as a constexpr. We use void to avoid
|
||||
// the cast.
|
||||
const void* default_message_void;
|
||||
const MessageLite* default_message() const {
|
||||
return static_cast<const MessageLite*>(default_message_void);
|
||||
}
|
||||
};
|
||||
message_aux messages;
|
||||
// Strings
|
||||
struct string_aux {
|
||||
const void* default_ptr;
|
||||
const char* field_name;
|
||||
};
|
||||
string_aux strings;
|
||||
|
||||
struct map_aux {
|
||||
bool (*parse_map)(io::CodedInputStream*, void*);
|
||||
};
|
||||
map_aux maps;
|
||||
|
||||
AuxillaryParseTableField() = default;
|
||||
constexpr AuxillaryParseTableField(AuxillaryParseTableField::enum_aux e)
|
||||
: enums(e) {}
|
||||
constexpr AuxillaryParseTableField(AuxillaryParseTableField::message_aux m)
|
||||
: messages(m) {}
|
||||
constexpr AuxillaryParseTableField(AuxillaryParseTableField::string_aux s)
|
||||
: strings(s) {}
|
||||
constexpr AuxillaryParseTableField(AuxillaryParseTableField::map_aux m)
|
||||
: maps(m) {}
|
||||
};
|
||||
|
||||
struct ParseTable {
|
||||
const ParseTableField* fields;
|
||||
const AuxillaryParseTableField* aux;
|
||||
int max_field_number;
|
||||
// TODO(ckennelly): Do something with this padding.
|
||||
|
||||
// TODO(ckennelly): Vet these for sign extension.
|
||||
int64 has_bits_offset;
|
||||
int64 oneof_case_offset;
|
||||
int64 extension_offset;
|
||||
int64 arena_offset;
|
||||
|
||||
// ExplicitlyInitialized<T> -> T requires a reinterpret_cast, which prevents
|
||||
// the tables from being constructed as a constexpr. We use void to avoid
|
||||
// the cast.
|
||||
const void* default_instance_void;
|
||||
const MessageLite* default_instance() const {
|
||||
return static_cast<const MessageLite*>(default_instance_void);
|
||||
}
|
||||
|
||||
bool unknown_field_set;
|
||||
};
|
||||
|
||||
static_assert(sizeof(ParseTableField) <= 16, "ParseTableField is too large");
|
||||
// The tables must be composed of POD components to ensure link-time
|
||||
// initialization.
|
||||
static_assert(std::is_pod<ParseTableField>::value, "");
|
||||
static_assert(std::is_pod<AuxillaryParseTableField::enum_aux>::value, "");
|
||||
static_assert(std::is_pod<AuxillaryParseTableField::message_aux>::value, "");
|
||||
static_assert(std::is_pod<AuxillaryParseTableField::string_aux>::value, "");
|
||||
static_assert(std::is_pod<ParseTable>::value, "");
|
||||
|
||||
#ifndef __NVCC__ // This assertion currently fails under NVCC.
|
||||
static_assert(std::is_pod<AuxillaryParseTableField>::value, "");
|
||||
#endif
|
||||
|
||||
// TODO(ckennelly): Consolidate these implementations into a single one, using
|
||||
// dynamic dispatch to the appropriate unknown field handler.
|
||||
bool MergePartialFromCodedStream(MessageLite* msg, const ParseTable& table,
|
||||
io::CodedInputStream* input);
|
||||
bool MergePartialFromCodedStreamLite(MessageLite* msg, const ParseTable& table,
|
||||
io::CodedInputStream* input);
|
||||
|
||||
template <typename Entry>
|
||||
bool ParseMap(io::CodedInputStream* input, void* map_field) {
|
||||
typedef typename MapEntryToMapField<Entry>::MapFieldType MapFieldType;
|
||||
typedef google::protobuf::Map<typename Entry::EntryKeyType,
|
||||
typename Entry::EntryValueType>
|
||||
MapType;
|
||||
typedef typename Entry::template Parser<MapFieldType, MapType> ParserType;
|
||||
|
||||
ParserType parser(static_cast<MapFieldType*>(map_field));
|
||||
return ::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(input,
|
||||
&parser);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_GENERATED_MESSAGE_TABLE_DRIVEN_H__
|
873
third_party/protobuf-lite/google/protobuf/generated_message_table_driven_lite.h
vendored
Normal file
873
third_party/protobuf-lite/google/protobuf/generated_message_table_driven_lite.h
vendored
Normal file
@ -0,0 +1,873 @@
|
||||
// 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_TABLE_DRIVEN_LITE_H__
|
||||
#define GOOGLE_PROTOBUF_GENERATED_MESSAGE_TABLE_DRIVEN_LITE_H__
|
||||
|
||||
#include <google/protobuf/generated_message_table_driven.h>
|
||||
|
||||
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
|
||||
#include <google/protobuf/extension_set.h>
|
||||
#include <google/protobuf/implicit_weak_message.h>
|
||||
#include <google/protobuf/inlined_string_field.h>
|
||||
#include <google/protobuf/metadata_lite.h>
|
||||
#include <google/protobuf/repeated_field.h>
|
||||
#include <google/protobuf/wire_format_lite.h>
|
||||
#include <google/protobuf/wire_format_lite_inl.h>
|
||||
#include <type_traits>
|
||||
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
|
||||
enum StringType {
|
||||
StringType_STRING = 0,
|
||||
StringType_INLINED = 3
|
||||
};
|
||||
|
||||
// Logically a superset of StringType, consisting of all field types that
|
||||
// require special initialization.
|
||||
enum ProcessingType {
|
||||
ProcessingType_STRING = 0,
|
||||
ProcessingType_CORD = 1,
|
||||
ProcessingType_STRING_PIECE = 2,
|
||||
ProcessingType_INLINED = 3,
|
||||
ProcessingType_MESSAGE = 4,
|
||||
};
|
||||
|
||||
enum Cardinality {
|
||||
Cardinality_SINGULAR = 0,
|
||||
Cardinality_REPEATED = 1,
|
||||
Cardinality_ONEOF = 3
|
||||
};
|
||||
|
||||
template <typename Type>
|
||||
inline Type* Raw(MessageLite* msg, int64 offset) {
|
||||
return reinterpret_cast<Type*>(reinterpret_cast<uint8*>(msg) + offset);
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
inline const Type* Raw(const MessageLite* msg, int64 offset) {
|
||||
return reinterpret_cast<const Type*>(reinterpret_cast<const uint8*>(msg) +
|
||||
offset);
|
||||
}
|
||||
|
||||
template <typename InternalMetadata>
|
||||
inline Arena* GetArena(MessageLite* msg, int64 arena_offset) {
|
||||
if (GOOGLE_PREDICT_FALSE(arena_offset == -1)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return Raw<InternalMetadata>(msg, arena_offset)->arena();
|
||||
}
|
||||
|
||||
inline ExtensionSet* GetExtensionSet(MessageLite* msg, int64 extension_offset) {
|
||||
if (extension_offset == -1) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return Raw<ExtensionSet>(msg, extension_offset);
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
inline Type* AddField(MessageLite* msg, int64 offset) {
|
||||
static_assert(std::is_pod<Type>::value ||
|
||||
std::is_same<Type, InlinedStringField>::value,
|
||||
"Do not assign");
|
||||
|
||||
google::protobuf::RepeatedField<Type>* repeated =
|
||||
Raw<google::protobuf::RepeatedField<Type> >(msg, offset);
|
||||
return repeated->Add();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline string* AddField<string>(MessageLite* msg, int64 offset) {
|
||||
google::protobuf::RepeatedPtrField<string>* repeated =
|
||||
Raw<google::protobuf::RepeatedPtrField<string> >(msg, offset);
|
||||
return repeated->Add();
|
||||
}
|
||||
|
||||
|
||||
template <typename Type>
|
||||
inline void AddField(MessageLite* msg, int64 offset, Type value) {
|
||||
static_assert(std::is_pod<Type>::value,
|
||||
"Do not assign");
|
||||
*AddField<Type>(msg, offset) = value;
|
||||
}
|
||||
|
||||
inline void SetBit(uint32* has_bits, uint32 has_bit_index) {
|
||||
GOOGLE_DCHECK(has_bits != nullptr);
|
||||
|
||||
uint32 mask = static_cast<uint32>(1u) << (has_bit_index % 32);
|
||||
has_bits[has_bit_index / 32u] |= mask;
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
inline Type* MutableField(MessageLite* msg, uint32* has_bits,
|
||||
uint32 has_bit_index, int64 offset) {
|
||||
SetBit(has_bits, has_bit_index);
|
||||
return Raw<Type>(msg, offset);
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
inline void SetField(MessageLite* msg, uint32* has_bits, uint32 has_bit_index,
|
||||
int64 offset, Type value) {
|
||||
static_assert(std::is_pod<Type>::value,
|
||||
"Do not assign");
|
||||
*MutableField<Type>(msg, has_bits, has_bit_index, offset) = value;
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
inline void SetOneofField(MessageLite* msg, uint32* oneof_case,
|
||||
uint32 oneof_case_index, int64 offset,
|
||||
int field_number, Type value) {
|
||||
oneof_case[oneof_case_index] = field_number;
|
||||
*Raw<Type>(msg, offset) = value;
|
||||
}
|
||||
|
||||
// Clears a oneof field. The field argument should correspond to the particular
|
||||
// field that is currently set in the oneof.
|
||||
inline void ClearOneofField(const ParseTableField& field, Arena* arena,
|
||||
MessageLite* msg) {
|
||||
switch (field.processing_type & kTypeMask) {
|
||||
case WireFormatLite::TYPE_MESSAGE:
|
||||
if (arena == NULL) {
|
||||
delete *Raw<MessageLite*>(msg, field.offset);
|
||||
}
|
||||
break;
|
||||
|
||||
case WireFormatLite::TYPE_STRING:
|
||||
case WireFormatLite::TYPE_BYTES:
|
||||
Raw<ArenaStringPtr>(msg, field.offset)
|
||||
->Destroy(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), arena);
|
||||
break;
|
||||
|
||||
case TYPE_STRING_INLINED:
|
||||
case TYPE_BYTES_INLINED:
|
||||
Raw<InlinedStringField>(msg, field.offset)->DestroyNoArena(NULL);
|
||||
break;
|
||||
|
||||
default:
|
||||
// No cleanup needed.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Clears and reinitializes a oneof field as necessary, in preparation for
|
||||
// parsing a new value with type field_type and field number field_number.
|
||||
//
|
||||
// Note: the oneof_case argument should point directly to the _oneof_case_
|
||||
// element corresponding to this particular oneof, not to the beginning of the
|
||||
// _oneof_case_ array.
|
||||
template <ProcessingType field_type>
|
||||
inline void ResetOneofField(const ParseTable& table, int field_number,
|
||||
Arena* arena, MessageLite* msg, uint32* oneof_case,
|
||||
int64 offset, const void* default_ptr) {
|
||||
if (*oneof_case == field_number) {
|
||||
// The oneof is already set to the right type, so there is no need to clear
|
||||
// it.
|
||||
return;
|
||||
}
|
||||
|
||||
if (*oneof_case != 0) {
|
||||
ClearOneofField(table.fields[*oneof_case], arena, msg);
|
||||
}
|
||||
*oneof_case = field_number;
|
||||
|
||||
switch (field_type) {
|
||||
case ProcessingType_STRING:
|
||||
Raw<ArenaStringPtr>(msg, offset)
|
||||
->UnsafeSetDefault(static_cast<const string*>(default_ptr));
|
||||
break;
|
||||
case ProcessingType_INLINED:
|
||||
new (Raw<InlinedStringField>(msg, offset))
|
||||
InlinedStringField(*static_cast<const string*>(default_ptr));
|
||||
break;
|
||||
case ProcessingType_MESSAGE:
|
||||
MessageLite** submessage = Raw<MessageLite*>(msg, offset);
|
||||
const MessageLite* prototype =
|
||||
table.aux[field_number].messages.default_message();
|
||||
*submessage = prototype->New(arena);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
template <Cardinality cardinality, bool validate, StringType ctype>
|
||||
static inline bool HandleString(io::CodedInputStream* input, MessageLite* msg,
|
||||
Arena* arena, uint32* has_bits,
|
||||
uint32 has_bit_index, int64 offset,
|
||||
const void* default_ptr,
|
||||
const char* field_name) {
|
||||
#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
|
||||
const char* sdata;
|
||||
size_t size;
|
||||
#endif
|
||||
|
||||
switch (ctype) {
|
||||
case StringType_INLINED: {
|
||||
InlinedStringField* s;
|
||||
switch (cardinality) {
|
||||
case Cardinality_SINGULAR:
|
||||
// TODO(ckennelly): Is this optimal?
|
||||
s = MutableField<InlinedStringField>(
|
||||
msg, has_bits, has_bit_index, offset);
|
||||
break;
|
||||
case Cardinality_REPEATED:
|
||||
s = AddField<InlinedStringField>(msg, offset);
|
||||
break;
|
||||
case Cardinality_ONEOF:
|
||||
s = Raw<InlinedStringField>(msg, offset);
|
||||
break;
|
||||
}
|
||||
GOOGLE_DCHECK(s != nullptr);
|
||||
::std::string* value = s->MutableNoArena(NULL);
|
||||
|
||||
if (GOOGLE_PREDICT_FALSE(!WireFormatLite::ReadString(input, value))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
|
||||
sdata = value->data();
|
||||
size = value->size();
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case StringType_STRING: {
|
||||
string* value;
|
||||
switch (cardinality) {
|
||||
case Cardinality_SINGULAR:
|
||||
// TODO(ckennelly): Is this optimal?
|
||||
value =
|
||||
MutableField<ArenaStringPtr>(msg, has_bits, has_bit_index, offset)
|
||||
->Mutable(static_cast<const string*>(default_ptr), arena);
|
||||
break;
|
||||
case Cardinality_REPEATED:
|
||||
value = AddField<string>(msg, offset);
|
||||
break;
|
||||
case Cardinality_ONEOF:
|
||||
value = Raw<ArenaStringPtr>(msg, offset)
|
||||
->Mutable(static_cast<const string*>(default_ptr), arena);
|
||||
break;
|
||||
}
|
||||
GOOGLE_DCHECK(value != nullptr);
|
||||
|
||||
if (GOOGLE_PREDICT_FALSE(!WireFormatLite::ReadString(input, value))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
|
||||
sdata = value->data();
|
||||
size = value->size();
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
|
||||
if (validate) {
|
||||
WireFormatLite::VerifyUtf8String(sdata, size, WireFormatLite::PARSE,
|
||||
field_name);
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename UnknownFieldHandler, typename InternalMetadata,
|
||||
Cardinality cardinality>
|
||||
inline bool HandleEnum(const ParseTable& table, io::CodedInputStream* input,
|
||||
MessageLite* msg, uint32* presence,
|
||||
uint32 presence_index, int64 offset, uint32 tag,
|
||||
int field_number) {
|
||||
int value;
|
||||
if (GOOGLE_PREDICT_FALSE(
|
||||
(!WireFormatLite::ReadPrimitive<int, WireFormatLite::TYPE_ENUM>(
|
||||
input, &value)))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
AuxillaryParseTableField::EnumValidator validator =
|
||||
table.aux[field_number].enums.validator;
|
||||
if (validator(value)) {
|
||||
switch (cardinality) {
|
||||
case Cardinality_SINGULAR:
|
||||
SetField(msg, presence, presence_index, offset, value);
|
||||
break;
|
||||
case Cardinality_REPEATED:
|
||||
AddField(msg, offset, value);
|
||||
break;
|
||||
case Cardinality_ONEOF:
|
||||
ClearOneofField(table.fields[presence[presence_index]],
|
||||
GetArena<InternalMetadata>(msg, table.arena_offset),
|
||||
msg);
|
||||
SetOneofField(msg, presence, presence_index, offset, field_number,
|
||||
value);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
UnknownFieldHandler::Varint(msg, table, tag, value);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// RepeatedMessageTypeHandler allows us to operate on RepeatedPtrField fields
|
||||
// without instantiating the specific template.
|
||||
class RepeatedMessageTypeHandler {
|
||||
public:
|
||||
typedef MessageLite Type;
|
||||
typedef MessageLite WeakType;
|
||||
static Arena* GetArena(Type* t) { return t->GetArena(); }
|
||||
static void* GetMaybeArenaPointer(Type* t) {
|
||||
return t->GetMaybeArenaPointer();
|
||||
}
|
||||
static inline Type* NewFromPrototype(const Type* prototype,
|
||||
Arena* arena = NULL) {
|
||||
return prototype->New(arena);
|
||||
}
|
||||
static void Delete(Type* t, Arena* arena = NULL) {
|
||||
if (arena == NULL) {
|
||||
delete t;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class MergePartialFromCodedStreamHelper {
|
||||
public:
|
||||
static MessageLite* Add(RepeatedPtrFieldBase* field,
|
||||
const MessageLite* prototype) {
|
||||
return field->Add<RepeatedMessageTypeHandler>(
|
||||
const_cast<MessageLite*>(prototype));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename UnknownFieldHandler, typename InternalMetadata>
|
||||
bool MergePartialFromCodedStreamImpl(MessageLite* msg, const ParseTable& table,
|
||||
io::CodedInputStream* input) {
|
||||
// We require that has_bits are present, as to avoid having to check for them
|
||||
// for every field.
|
||||
//
|
||||
// TODO(ckennelly): Make this a compile-time parameter with templates.
|
||||
GOOGLE_DCHECK_GE(table.has_bits_offset, 0);
|
||||
uint32* has_bits = Raw<uint32>(msg, table.has_bits_offset);
|
||||
GOOGLE_DCHECK(has_bits != NULL);
|
||||
|
||||
while (true) {
|
||||
uint32 tag = input->ReadTag();
|
||||
|
||||
const WireFormatLite::WireType wire_type =
|
||||
WireFormatLite::GetTagWireType(tag);
|
||||
const int field_number = WireFormatLite::GetTagFieldNumber(tag);
|
||||
|
||||
if (field_number > table.max_field_number) {
|
||||
// check for possible extensions
|
||||
if (UnknownFieldHandler::ParseExtension(msg, table, input, tag)) {
|
||||
// successfully parsed
|
||||
continue;
|
||||
}
|
||||
|
||||
if (GOOGLE_PREDICT_FALSE(
|
||||
!UnknownFieldHandler::Skip(msg, table, input, tag))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// We implicitly verify that data points to a valid field as we check the
|
||||
// wire types. Entries in table.fields[i] that do not correspond to valid
|
||||
// field numbers have their normal_wiretype and packed_wiretype fields set
|
||||
// with the kInvalidMask value. As wire_type cannot take on that value, we
|
||||
// will never match.
|
||||
const ParseTableField* data = table.fields + field_number;
|
||||
|
||||
// TODO(ckennelly): Avoid sign extension
|
||||
const int64 presence_index = data->presence_index;
|
||||
const int64 offset = data->offset;
|
||||
const unsigned char processing_type = data->processing_type;
|
||||
|
||||
if (data->normal_wiretype == static_cast<unsigned char>(wire_type)) {
|
||||
// TODO(ckennelly): Use a computed goto on GCC/LLVM or otherwise eliminate
|
||||
// the bounds check on processing_type.
|
||||
|
||||
switch (processing_type) {
|
||||
#define HANDLE_TYPE(TYPE, CPPTYPE) \
|
||||
case (WireFormatLite::TYPE_##TYPE): { \
|
||||
CPPTYPE value; \
|
||||
if (GOOGLE_PREDICT_FALSE( \
|
||||
(!WireFormatLite::ReadPrimitive< \
|
||||
CPPTYPE, WireFormatLite::TYPE_##TYPE>(input, &value)))) { \
|
||||
return false; \
|
||||
} \
|
||||
SetField(msg, has_bits, presence_index, offset, value); \
|
||||
break; \
|
||||
} \
|
||||
case (WireFormatLite::TYPE_##TYPE) | kRepeatedMask: { \
|
||||
google::protobuf::RepeatedField<CPPTYPE>* values = \
|
||||
Raw<google::protobuf::RepeatedField<CPPTYPE> >(msg, offset); \
|
||||
if (GOOGLE_PREDICT_FALSE((!WireFormatLite::ReadRepeatedPrimitive< \
|
||||
CPPTYPE, WireFormatLite::TYPE_##TYPE>( \
|
||||
data->tag_size, tag, input, values)))) { \
|
||||
return false; \
|
||||
} \
|
||||
break; \
|
||||
} \
|
||||
case (WireFormatLite::TYPE_##TYPE) | kOneofMask: { \
|
||||
uint32* oneof_case = Raw<uint32>(msg, table.oneof_case_offset); \
|
||||
CPPTYPE value; \
|
||||
if (GOOGLE_PREDICT_FALSE( \
|
||||
(!WireFormatLite::ReadPrimitive< \
|
||||
CPPTYPE, WireFormatLite::TYPE_##TYPE>(input, &value)))) { \
|
||||
return false; \
|
||||
} \
|
||||
ClearOneofField(table.fields[oneof_case[presence_index]], \
|
||||
GetArena<InternalMetadata>(msg, table.arena_offset), msg); \
|
||||
SetOneofField(msg, oneof_case, presence_index, offset, field_number, \
|
||||
value); \
|
||||
break; \
|
||||
}
|
||||
|
||||
HANDLE_TYPE(INT32, int32)
|
||||
HANDLE_TYPE(INT64, int64)
|
||||
HANDLE_TYPE(SINT32, int32)
|
||||
HANDLE_TYPE(SINT64, int64)
|
||||
HANDLE_TYPE(UINT32, uint32)
|
||||
HANDLE_TYPE(UINT64, uint64)
|
||||
|
||||
HANDLE_TYPE(FIXED32, uint32)
|
||||
HANDLE_TYPE(FIXED64, uint64)
|
||||
HANDLE_TYPE(SFIXED32, int32)
|
||||
HANDLE_TYPE(SFIXED64, int64)
|
||||
|
||||
HANDLE_TYPE(FLOAT, float)
|
||||
HANDLE_TYPE(DOUBLE, double)
|
||||
|
||||
HANDLE_TYPE(BOOL, bool)
|
||||
#undef HANDLE_TYPE
|
||||
case WireFormatLite::TYPE_BYTES:
|
||||
#ifndef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
|
||||
case WireFormatLite::TYPE_STRING:
|
||||
#endif
|
||||
{
|
||||
Arena* const arena =
|
||||
GetArena<InternalMetadata>(msg, table.arena_offset);
|
||||
const void* default_ptr = table.aux[field_number].strings.default_ptr;
|
||||
|
||||
if (GOOGLE_PREDICT_FALSE((
|
||||
!HandleString<Cardinality_SINGULAR, false, StringType_STRING>(
|
||||
input, msg, arena, has_bits, presence_index, offset,
|
||||
default_ptr, NULL)))) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TYPE_BYTES_INLINED:
|
||||
#ifndef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
|
||||
case TYPE_STRING_INLINED:
|
||||
#endif
|
||||
{
|
||||
Arena* const arena =
|
||||
GetArena<InternalMetadata>(msg, table.arena_offset);
|
||||
const void* default_ptr = table.aux[field_number].strings.default_ptr;
|
||||
|
||||
if (GOOGLE_PREDICT_FALSE((!HandleString<Cardinality_SINGULAR, false,
|
||||
StringType_INLINED>(
|
||||
input, msg, arena, has_bits, presence_index, offset,
|
||||
default_ptr, NULL)))) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WireFormatLite::TYPE_BYTES | kOneofMask:
|
||||
#ifndef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
|
||||
case WireFormatLite::TYPE_STRING | kOneofMask:
|
||||
#endif
|
||||
{
|
||||
Arena* const arena =
|
||||
GetArena<InternalMetadata>(msg, table.arena_offset);
|
||||
uint32* oneof_case = Raw<uint32>(msg, table.oneof_case_offset);
|
||||
const void* default_ptr = table.aux[field_number].strings.default_ptr;
|
||||
|
||||
ResetOneofField<ProcessingType_STRING>(
|
||||
table, field_number, arena, msg, oneof_case + presence_index,
|
||||
offset, default_ptr);
|
||||
|
||||
if (GOOGLE_PREDICT_FALSE(
|
||||
(!HandleString<Cardinality_ONEOF, false, StringType_STRING>(
|
||||
input, msg, arena, has_bits, presence_index, offset,
|
||||
default_ptr, NULL)))) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case (WireFormatLite::TYPE_BYTES) | kRepeatedMask:
|
||||
case TYPE_BYTES_INLINED | kRepeatedMask:
|
||||
#ifndef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
|
||||
case (WireFormatLite::TYPE_STRING) | kRepeatedMask:
|
||||
case TYPE_STRING_INLINED | kRepeatedMask:
|
||||
#endif
|
||||
{
|
||||
Arena* const arena =
|
||||
GetArena<InternalMetadata>(msg, table.arena_offset);
|
||||
const void* default_ptr =
|
||||
table.aux[field_number].strings.default_ptr;
|
||||
|
||||
if (GOOGLE_PREDICT_FALSE((
|
||||
!HandleString<Cardinality_REPEATED, false, StringType_STRING>(
|
||||
input, msg, arena, has_bits, presence_index, offset,
|
||||
default_ptr, NULL)))) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
|
||||
case (WireFormatLite::TYPE_STRING): {
|
||||
Arena* const arena =
|
||||
GetArena<InternalMetadata>(msg, table.arena_offset);
|
||||
const void* default_ptr = table.aux[field_number].strings.default_ptr;
|
||||
const char* field_name = table.aux[field_number].strings.field_name;
|
||||
|
||||
if (GOOGLE_PREDICT_FALSE(
|
||||
(!HandleString<Cardinality_SINGULAR, true, StringType_STRING>(
|
||||
input, msg, arena, has_bits, presence_index, offset,
|
||||
default_ptr, field_name)))) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TYPE_STRING_INLINED | kRepeatedMask:
|
||||
case (WireFormatLite::TYPE_STRING) | kRepeatedMask: {
|
||||
Arena* const arena =
|
||||
GetArena<InternalMetadata>(msg, table.arena_offset);
|
||||
const void* default_ptr = table.aux[field_number].strings.default_ptr;
|
||||
const char* field_name = table.aux[field_number].strings.field_name;
|
||||
|
||||
if (GOOGLE_PREDICT_FALSE(
|
||||
(!HandleString<Cardinality_REPEATED, true, StringType_STRING>(
|
||||
input, msg, arena, has_bits, presence_index, offset,
|
||||
default_ptr, field_name)))) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case (WireFormatLite::TYPE_STRING) | kOneofMask: {
|
||||
Arena* const arena =
|
||||
GetArena<InternalMetadata>(msg, table.arena_offset);
|
||||
uint32* oneof_case = Raw<uint32>(msg, table.oneof_case_offset);
|
||||
const void* default_ptr = table.aux[field_number].strings.default_ptr;
|
||||
const char* field_name = table.aux[field_number].strings.field_name;
|
||||
|
||||
ResetOneofField<ProcessingType_STRING>(
|
||||
table, field_number, arena, msg, oneof_case + presence_index,
|
||||
offset, default_ptr);
|
||||
|
||||
if (GOOGLE_PREDICT_FALSE(
|
||||
(!HandleString<Cardinality_ONEOF, true, StringType_STRING>(
|
||||
input, msg, arena, has_bits, presence_index, offset,
|
||||
default_ptr, field_name)))) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case WireFormatLite::TYPE_ENUM: {
|
||||
if (GOOGLE_PREDICT_FALSE(
|
||||
(!HandleEnum<UnknownFieldHandler, InternalMetadata,
|
||||
Cardinality_SINGULAR>(
|
||||
table, input, msg, has_bits, presence_index, offset, tag,
|
||||
field_number)))) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WireFormatLite::TYPE_ENUM | kRepeatedMask: {
|
||||
if (GOOGLE_PREDICT_FALSE(
|
||||
(!HandleEnum<UnknownFieldHandler, InternalMetadata,
|
||||
Cardinality_REPEATED>(
|
||||
table, input, msg, has_bits, presence_index, offset, tag,
|
||||
field_number)))) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WireFormatLite::TYPE_ENUM | kOneofMask: {
|
||||
uint32* oneof_case = Raw<uint32>(msg, table.oneof_case_offset);
|
||||
if (GOOGLE_PREDICT_FALSE(
|
||||
(!HandleEnum<UnknownFieldHandler, InternalMetadata,
|
||||
Cardinality_ONEOF>(table, input, msg, oneof_case,
|
||||
presence_index, offset, tag,
|
||||
field_number)))) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WireFormatLite::TYPE_GROUP: {
|
||||
MessageLite** submsg_holder =
|
||||
MutableField<MessageLite*>(msg, has_bits, presence_index, offset);
|
||||
MessageLite* submsg = *submsg_holder;
|
||||
|
||||
if (submsg == NULL) {
|
||||
Arena* const arena =
|
||||
GetArena<InternalMetadata>(msg, table.arena_offset);
|
||||
const MessageLite* prototype =
|
||||
table.aux[field_number].messages.default_message();
|
||||
submsg = prototype->New(arena);
|
||||
*submsg_holder = submsg;
|
||||
}
|
||||
|
||||
if (GOOGLE_PREDICT_FALSE(
|
||||
!WireFormatLite::ReadGroup(field_number, input, submsg))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case WireFormatLite::TYPE_GROUP | kRepeatedMask: {
|
||||
RepeatedPtrFieldBase* field = Raw<RepeatedPtrFieldBase>(msg, offset);
|
||||
const MessageLite* prototype =
|
||||
table.aux[field_number].messages.default_message();
|
||||
GOOGLE_DCHECK(prototype != NULL);
|
||||
|
||||
MessageLite* submsg =
|
||||
MergePartialFromCodedStreamHelper::Add(field, prototype);
|
||||
|
||||
if (GOOGLE_PREDICT_FALSE(
|
||||
!WireFormatLite::ReadGroup(field_number, input, submsg))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case WireFormatLite::TYPE_MESSAGE: {
|
||||
MessageLite** submsg_holder =
|
||||
MutableField<MessageLite*>(msg, has_bits, presence_index, offset);
|
||||
MessageLite* submsg = *submsg_holder;
|
||||
|
||||
if (submsg == NULL) {
|
||||
Arena* const arena =
|
||||
GetArena<InternalMetadata>(msg, table.arena_offset);
|
||||
const MessageLite* prototype =
|
||||
table.aux[field_number].messages.default_message();
|
||||
if (prototype == NULL) {
|
||||
prototype =
|
||||
::google::protobuf::internal::ImplicitWeakMessage::default_instance();
|
||||
}
|
||||
submsg = prototype->New(arena);
|
||||
*submsg_holder = submsg;
|
||||
}
|
||||
|
||||
if (GOOGLE_PREDICT_FALSE(!WireFormatLite::ReadMessage(input, submsg))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
// TODO(ckennelly): Adapt ReadMessageNoVirtualNoRecursionDepth and
|
||||
// manage input->IncrementRecursionDepth() here.
|
||||
case WireFormatLite::TYPE_MESSAGE | kRepeatedMask: {
|
||||
RepeatedPtrFieldBase* field = Raw<RepeatedPtrFieldBase>(msg, offset);
|
||||
const MessageLite* prototype =
|
||||
table.aux[field_number].messages.default_message();
|
||||
if (prototype == NULL) {
|
||||
prototype =
|
||||
::google::protobuf::internal::ImplicitWeakMessage::default_instance();
|
||||
}
|
||||
|
||||
MessageLite* submsg =
|
||||
MergePartialFromCodedStreamHelper::Add(field, prototype);
|
||||
|
||||
if (GOOGLE_PREDICT_FALSE(!WireFormatLite::ReadMessage(input, submsg))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case WireFormatLite::TYPE_MESSAGE | kOneofMask: {
|
||||
Arena* const arena =
|
||||
GetArena<InternalMetadata>(msg, table.arena_offset);
|
||||
uint32* oneof_case = Raw<uint32>(msg, table.oneof_case_offset);
|
||||
MessageLite** submsg_holder = Raw<MessageLite*>(msg, offset);
|
||||
ResetOneofField<ProcessingType_MESSAGE>(
|
||||
table, field_number, arena, msg, oneof_case + presence_index,
|
||||
offset, NULL);
|
||||
MessageLite* submsg = *submsg_holder;
|
||||
|
||||
if (GOOGLE_PREDICT_FALSE(!WireFormatLite::ReadMessage(input, submsg))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
|
||||
case TYPE_STRING_INLINED: {
|
||||
Arena* const arena =
|
||||
GetArena<InternalMetadata>(msg, table.arena_offset);
|
||||
const void* default_ptr = table.aux[field_number].strings.default_ptr;
|
||||
const char* field_name = table.aux[field_number].strings.field_name;
|
||||
|
||||
if (GOOGLE_PREDICT_FALSE((
|
||||
!HandleString<Cardinality_SINGULAR, true, StringType_INLINED>(
|
||||
input, msg, arena, has_bits, presence_index, offset,
|
||||
default_ptr, field_name)))) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif // GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
|
||||
case TYPE_MAP: {
|
||||
if (GOOGLE_PREDICT_FALSE(!(*table.aux[field_number].maps.parse_map)(
|
||||
input, Raw<void>(msg, offset)))) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0: {
|
||||
// Done.
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (data->packed_wiretype == static_cast<unsigned char>(wire_type)) {
|
||||
// Non-packable fields have their packed_wiretype masked with
|
||||
// kNotPackedMask, which is impossible to match here.
|
||||
GOOGLE_DCHECK(processing_type & kRepeatedMask);
|
||||
GOOGLE_DCHECK_NE(processing_type, kRepeatedMask);
|
||||
GOOGLE_DCHECK_EQ(0, processing_type & kOneofMask);
|
||||
|
||||
GOOGLE_DCHECK_NE(TYPE_BYTES_INLINED | kRepeatedMask, processing_type);
|
||||
GOOGLE_DCHECK_NE(TYPE_STRING_INLINED | kRepeatedMask, processing_type);
|
||||
|
||||
// TODO(ckennelly): Use a computed goto on GCC/LLVM.
|
||||
//
|
||||
// Mask out kRepeatedMask bit, allowing the jump table to be smaller.
|
||||
switch (static_cast<WireFormatLite::FieldType>(
|
||||
processing_type ^ kRepeatedMask)) {
|
||||
#define HANDLE_PACKED_TYPE(TYPE, CPPTYPE, CPPTYPE_METHOD) \
|
||||
case WireFormatLite::TYPE_##TYPE: { \
|
||||
google::protobuf::RepeatedField<CPPTYPE>* values = \
|
||||
Raw<google::protobuf::RepeatedField<CPPTYPE> >(msg, offset); \
|
||||
if (GOOGLE_PREDICT_FALSE( \
|
||||
(!WireFormatLite::ReadPackedPrimitive< \
|
||||
CPPTYPE, WireFormatLite::TYPE_##TYPE>(input, values)))) { \
|
||||
return false; \
|
||||
} \
|
||||
break; \
|
||||
}
|
||||
|
||||
HANDLE_PACKED_TYPE(INT32, int32, Int32)
|
||||
HANDLE_PACKED_TYPE(INT64, int64, Int64)
|
||||
HANDLE_PACKED_TYPE(SINT32, int32, Int32)
|
||||
HANDLE_PACKED_TYPE(SINT64, int64, Int64)
|
||||
HANDLE_PACKED_TYPE(UINT32, uint32, UInt32)
|
||||
HANDLE_PACKED_TYPE(UINT64, uint64, UInt64)
|
||||
|
||||
HANDLE_PACKED_TYPE(FIXED32, uint32, UInt32)
|
||||
HANDLE_PACKED_TYPE(FIXED64, uint64, UInt64)
|
||||
HANDLE_PACKED_TYPE(SFIXED32, int32, Int32)
|
||||
HANDLE_PACKED_TYPE(SFIXED64, int64, Int64)
|
||||
|
||||
HANDLE_PACKED_TYPE(FLOAT, float, Float)
|
||||
HANDLE_PACKED_TYPE(DOUBLE, double, Double)
|
||||
|
||||
HANDLE_PACKED_TYPE(BOOL, bool, Bool)
|
||||
#undef HANDLE_PACKED_TYPE
|
||||
case WireFormatLite::TYPE_ENUM: {
|
||||
// To avoid unnecessarily calling MutableUnknownFields (which mutates
|
||||
// InternalMetadataWithArena) when all inputs in the repeated series
|
||||
// are valid, we implement our own parser rather than call
|
||||
// WireFormat::ReadPackedEnumPreserveUnknowns.
|
||||
uint32 length;
|
||||
if (GOOGLE_PREDICT_FALSE(!input->ReadVarint32(&length))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
AuxillaryParseTableField::EnumValidator validator =
|
||||
table.aux[field_number].enums.validator;
|
||||
google::protobuf::RepeatedField<int>* values =
|
||||
Raw<google::protobuf::RepeatedField<int> >(msg, offset);
|
||||
|
||||
io::CodedInputStream::Limit limit = input->PushLimit(length);
|
||||
while (input->BytesUntilLimit() > 0) {
|
||||
int value;
|
||||
if (GOOGLE_PREDICT_FALSE(
|
||||
(!google::protobuf::internal::WireFormatLite::ReadPrimitive<
|
||||
int, WireFormatLite::TYPE_ENUM>(input, &value)))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (validator(value)) {
|
||||
values->Add(value);
|
||||
} else {
|
||||
// TODO(ckennelly): Consider caching here.
|
||||
UnknownFieldHandler::Varint(msg, table, tag, value);
|
||||
}
|
||||
}
|
||||
input->PopLimit(limit);
|
||||
|
||||
break;
|
||||
}
|
||||
case WireFormatLite::TYPE_STRING:
|
||||
case WireFormatLite::TYPE_GROUP:
|
||||
case WireFormatLite::TYPE_MESSAGE:
|
||||
case WireFormatLite::TYPE_BYTES:
|
||||
GOOGLE_DCHECK(false);
|
||||
return false;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (wire_type == WireFormatLite::WIRETYPE_END_GROUP) {
|
||||
// Must be the end of the message.
|
||||
return true;
|
||||
}
|
||||
|
||||
// check for possible extensions
|
||||
if (UnknownFieldHandler::ParseExtension(msg, table, input, tag)) {
|
||||
// successfully parsed
|
||||
continue;
|
||||
}
|
||||
|
||||
// process unknown field.
|
||||
if (GOOGLE_PREDICT_FALSE(
|
||||
!UnknownFieldHandler::Skip(msg, table, input, tag))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_GENERATED_MESSAGE_TABLE_DRIVEN_LITE_H__
|
391
third_party/protobuf-lite/google/protobuf/generated_message_util.h
vendored
Normal file
391
third_party/protobuf-lite/google/protobuf/generated_message_util.h
vendored
Normal file
@ -0,0 +1,391 @@
|
||||
// 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/logging.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/once.h> // Add direct dep on port for pb.cc
|
||||
#include <google/protobuf/has_bits.h>
|
||||
#include <google/protobuf/implicit_weak_message.h>
|
||||
#include <google/protobuf/map_entry_lite.h>
|
||||
#include <google/protobuf/message_lite.h>
|
||||
#include <google/protobuf/wire_format_lite.h>
|
||||
|
||||
namespace google {
|
||||
|
||||
namespace protobuf {
|
||||
|
||||
class Arena;
|
||||
|
||||
namespace io { class CodedInputStream; }
|
||||
|
||||
namespace internal {
|
||||
|
||||
|
||||
// Annotation for the compiler to emit a deprecation message if a field marked
|
||||
// with option 'deprecated=true' is used in the code, or for other things in
|
||||
// generated code which are deprecated.
|
||||
//
|
||||
// For internal use in the pb.cc files, deprecation warnings are suppressed
|
||||
// there.
|
||||
#undef DEPRECATED_PROTOBUF_FIELD
|
||||
#define PROTOBUF_DEPRECATED
|
||||
|
||||
#define GOOGLE_PROTOBUF_DEPRECATED_ATTR
|
||||
|
||||
|
||||
// Returns the offset of the given field within the given aggregate type.
|
||||
// This is equivalent to the ANSI C offsetof() macro. However, according
|
||||
// to the C++ standard, offsetof() only works on POD types, and GCC
|
||||
// enforces this requirement with a warning. In practice, this rule is
|
||||
// unnecessarily strict; there is probably no compiler or platform on
|
||||
// which the offsets of the direct fields of a class are non-constant.
|
||||
// Fields inherited from superclasses *can* have non-constant offsets,
|
||||
// but that's not what this macro will be used for.
|
||||
#if defined(__clang__)
|
||||
// For Clang we use __builtin_offsetof() and suppress the warning,
|
||||
// to avoid Control Flow Integrity and UBSan vptr sanitizers from
|
||||
// crashing while trying to validate the invalid reinterpet_casts.
|
||||
#define GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(TYPE, FIELD) \
|
||||
_Pragma("clang diagnostic push") \
|
||||
_Pragma("clang diagnostic ignored \"-Winvalid-offsetof\"") \
|
||||
__builtin_offsetof(TYPE, FIELD) \
|
||||
_Pragma("clang diagnostic pop")
|
||||
#else
|
||||
// Note that we calculate relative to the pointer value 16 here since if we
|
||||
// just use zero, GCC complains about dereferencing a NULL pointer. We
|
||||
// choose 16 rather than some other number just in case the compiler would
|
||||
// be confused by an unaligned pointer.
|
||||
#define GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(TYPE, FIELD) \
|
||||
static_cast< ::google::protobuf::uint32>( \
|
||||
reinterpret_cast<const char*>( \
|
||||
&reinterpret_cast<const TYPE*>(16)->FIELD) - \
|
||||
reinterpret_cast<const char*>(16))
|
||||
#endif
|
||||
|
||||
// Constants for special floating point values.
|
||||
LIBPROTOBUF_EXPORT double Infinity();
|
||||
LIBPROTOBUF_EXPORT double NaN();
|
||||
|
||||
LIBPROTOBUF_EXPORT void InitProtobufDefaults();
|
||||
|
||||
// This used by proto1
|
||||
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 <class Type> bool AllAreInitialized(const Type& 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 ::google::protobuf::RepeatedPtrField<T>& t) {
|
||||
for (int i = t.size(); --i >= 0;) {
|
||||
if (!reinterpret_cast<const ::google::protobuf::internal::RepeatedPtrFieldBase&>(t)
|
||||
.Get<::google::protobuf::internal::ImplicitWeakTypeHandler<T> >(i)
|
||||
.IsInitialized()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
struct LIBPROTOBUF_EXPORT FieldMetadata {
|
||||
uint32 offset; // offset of this field in the struct
|
||||
uint32 tag; // field * 8 + wire_type
|
||||
// byte offset * 8 + bit_offset;
|
||||
// if the high bit is set then this is the byte offset of the oneof_case
|
||||
// for this field.
|
||||
uint32 has_offset;
|
||||
uint32 type; // the type of this field.
|
||||
const void* ptr; // auxiliary data
|
||||
|
||||
// From the serializer point of view each fundamental type can occur in
|
||||
// 4 different ways. For simplicity we treat all combinations as a cartesion
|
||||
// product although not all combinations are allowed.
|
||||
enum FieldTypeClass {
|
||||
kPresence,
|
||||
kNoPresence,
|
||||
kRepeated,
|
||||
kPacked,
|
||||
kOneOf,
|
||||
kNumTypeClasses // must be last enum
|
||||
};
|
||||
// C++ protobuf has 20 fundamental types, were we added Cord and StringPiece
|
||||
// and also distinquish the same types if they have different wire format.
|
||||
enum {
|
||||
kCordType = 19,
|
||||
kStringPieceType = 20,
|
||||
kInlinedType = 21,
|
||||
kNumTypes = 21,
|
||||
kSpecial = kNumTypes * kNumTypeClasses,
|
||||
};
|
||||
|
||||
static int CalculateType(int fundamental_type, FieldTypeClass type_class);
|
||||
};
|
||||
|
||||
inline bool IsPresent(const void* base, uint32 hasbit) {
|
||||
const uint32* has_bits_array = static_cast<const uint32*>(base);
|
||||
return (has_bits_array[hasbit / 32] & (1u << (hasbit & 31))) != 0;
|
||||
}
|
||||
|
||||
inline bool IsOneofPresent(const void* base, uint32 offset, uint32 tag) {
|
||||
const uint32* oneof =
|
||||
reinterpret_cast<const uint32*>(static_cast<const uint8*>(base) + offset);
|
||||
return *oneof == tag >> 3;
|
||||
}
|
||||
|
||||
typedef void (*SpecialSerializer)(const uint8* base, uint32 offset, uint32 tag,
|
||||
uint32 has_offset,
|
||||
::google::protobuf::io::CodedOutputStream* output);
|
||||
|
||||
LIBPROTOBUF_EXPORT void ExtensionSerializer(const uint8* base, uint32 offset, uint32 tag,
|
||||
uint32 has_offset,
|
||||
::google::protobuf::io::CodedOutputStream* output);
|
||||
LIBPROTOBUF_EXPORT void UnknownFieldSerializerLite(const uint8* base, uint32 offset, uint32 tag,
|
||||
uint32 has_offset,
|
||||
::google::protobuf::io::CodedOutputStream* output);
|
||||
|
||||
struct SerializationTable {
|
||||
int num_fields;
|
||||
const FieldMetadata* field_table;
|
||||
};
|
||||
|
||||
LIBPROTOBUF_EXPORT void SerializeInternal(const uint8* base, const FieldMetadata* table,
|
||||
int num_fields, ::google::protobuf::io::CodedOutputStream* output);
|
||||
|
||||
inline void TableSerialize(const ::google::protobuf::MessageLite& msg,
|
||||
const SerializationTable* table,
|
||||
::google::protobuf::io::CodedOutputStream* output) {
|
||||
const FieldMetadata* field_table = table->field_table;
|
||||
int num_fields = table->num_fields - 1;
|
||||
const uint8* base = reinterpret_cast<const uint8*>(&msg);
|
||||
// TODO(gerbens) This skips the first test if we could use the fast
|
||||
// array serialization path, we should make this
|
||||
// int cached_size =
|
||||
// *reinterpret_cast<const int32*>(base + field_table->offset);
|
||||
// SerializeWithCachedSize(msg, field_table + 1, num_fields, cached_size, ...)
|
||||
// But we keep conformance with the old way for now.
|
||||
SerializeInternal(base, field_table + 1, num_fields, output);
|
||||
}
|
||||
|
||||
uint8* SerializeInternalToArray(const uint8* base, const FieldMetadata* table,
|
||||
int num_fields, bool is_deterministic,
|
||||
uint8* buffer);
|
||||
|
||||
inline uint8* TableSerializeToArray(const ::google::protobuf::MessageLite& msg,
|
||||
const SerializationTable* table,
|
||||
bool is_deterministic, uint8* buffer) {
|
||||
const uint8* base = reinterpret_cast<const uint8*>(&msg);
|
||||
const FieldMetadata* field_table = table->field_table + 1;
|
||||
int num_fields = table->num_fields - 1;
|
||||
return SerializeInternalToArray(base, field_table, num_fields,
|
||||
is_deterministic, buffer);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
struct CompareHelper {
|
||||
bool operator()(const T& a, const T& b) { return a < b; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct CompareHelper<ArenaStringPtr> {
|
||||
bool operator()(const ArenaStringPtr& a, const ArenaStringPtr& b) {
|
||||
return a.Get() < b.Get();
|
||||
}
|
||||
};
|
||||
|
||||
struct CompareMapKey {
|
||||
template <typename T>
|
||||
bool operator()(const MapEntryHelper<T>& a, const MapEntryHelper<T>& b) {
|
||||
return Compare(a.key_, b.key_);
|
||||
}
|
||||
template <typename T>
|
||||
bool Compare(const T& a, const T& b) {
|
||||
return CompareHelper<T>()(a, b);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename MapFieldType, const SerializationTable* table>
|
||||
void MapFieldSerializer(const uint8* base, uint32 offset, uint32 tag,
|
||||
uint32 has_offset,
|
||||
::google::protobuf::io::CodedOutputStream* output) {
|
||||
typedef MapEntryHelper<typename MapFieldType::EntryTypeTrait> Entry;
|
||||
typedef typename MapFieldType::MapType::const_iterator Iter;
|
||||
|
||||
const MapFieldType& map_field =
|
||||
*reinterpret_cast<const MapFieldType*>(base + offset);
|
||||
const SerializationTable* t =
|
||||
table +
|
||||
has_offset; // has_offset is overloaded for maps to mean table offset
|
||||
if (!output->IsSerializationDeterministic()) {
|
||||
for (Iter it = map_field.GetMap().begin(); it != map_field.GetMap().end();
|
||||
++it) {
|
||||
Entry map_entry(*it);
|
||||
output->WriteVarint32(tag);
|
||||
output->WriteVarint32(map_entry._cached_size_);
|
||||
SerializeInternal(reinterpret_cast<const uint8*>(&map_entry),
|
||||
t->field_table, t->num_fields, output);
|
||||
}
|
||||
} else {
|
||||
std::vector<Entry> v;
|
||||
for (Iter it = map_field.GetMap().begin(); it != map_field.GetMap().end();
|
||||
++it) {
|
||||
v.push_back(Entry(*it));
|
||||
}
|
||||
std::sort(v.begin(), v.end(), CompareMapKey());
|
||||
for (int i = 0; i < v.size(); i++) {
|
||||
output->WriteVarint32(tag);
|
||||
output->WriteVarint32(v[i]._cached_size_);
|
||||
SerializeInternal(reinterpret_cast<const uint8*>(&v[i]), t->field_table,
|
||||
t->num_fields, output);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LIBPROTOBUF_EXPORT MessageLite* DuplicateIfNonNullInternal(MessageLite* message);
|
||||
LIBPROTOBUF_EXPORT MessageLite* GetOwnedMessageInternal(Arena* message_arena,
|
||||
MessageLite* submessage,
|
||||
Arena* submessage_arena);
|
||||
|
||||
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 LIBPROTOBUF_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};
|
||||
};
|
||||
|
||||
// SCCInfo represents information of a strongly connected component of
|
||||
// mutual dependent messages.
|
||||
struct LIBPROTOBUF_EXPORT SCCInfoBase {
|
||||
// We use 0 for the Initialized state, because test eax,eax, jnz is smaller
|
||||
// and is subject to macro fusion.
|
||||
enum {
|
||||
kInitialized = 0, // final state
|
||||
kRunning = 1,
|
||||
kUninitialized = -1, // initial state
|
||||
};
|
||||
#ifndef _MSC_VER
|
||||
std::atomic<int> visit_status;
|
||||
#else
|
||||
// MSVC doesnt make std::atomic constant initialized. This union trick
|
||||
// makes it so.
|
||||
union {
|
||||
int visit_status_to_make_linker_init;
|
||||
std::atomic<int> visit_status;
|
||||
};
|
||||
#endif
|
||||
int num_deps;
|
||||
void (*init_func)();
|
||||
// This is followed by an array of num_deps
|
||||
// const SCCInfoBase* deps[];
|
||||
};
|
||||
|
||||
template <int N>
|
||||
struct SCCInfo {
|
||||
SCCInfoBase base;
|
||||
// Semantically this is const SCCInfo<T>* which is is a templated type.
|
||||
// The obvious inheriting from SCCInfoBase mucks with struct initialization.
|
||||
// Attempts showed the compiler was generating dynamic initialization code.
|
||||
// Zero length arrays produce warnings with MSVC.
|
||||
SCCInfoBase* deps[N ? N : 1];
|
||||
};
|
||||
|
||||
LIBPROTOBUF_EXPORT void InitSCCImpl(SCCInfoBase* scc);
|
||||
|
||||
inline void InitSCC(SCCInfoBase* scc) {
|
||||
auto status = scc->visit_status.load(std::memory_order_acquire);
|
||||
if (GOOGLE_PREDICT_FALSE(status != SCCInfoBase::kInitialized)) InitSCCImpl(scc);
|
||||
}
|
||||
|
||||
LIBPROTOBUF_EXPORT void DestroyMessage(const void* message);
|
||||
LIBPROTOBUF_EXPORT void DestroyString(const void* s);
|
||||
// Destroy (not delete) the message
|
||||
inline void OnShutdownDestroyMessage(const void* ptr) {
|
||||
OnShutdownRun(DestroyMessage, ptr);
|
||||
}
|
||||
// Destroy the string (call string destructor)
|
||||
inline void OnShutdownDestroyString(const std::string* ptr) {
|
||||
OnShutdownRun(DestroyString, ptr);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__
|
105
third_party/protobuf-lite/google/protobuf/has_bits.h
vendored
Normal file
105
third_party/protobuf-lite/google/protobuf/has_bits.h
vendored
Normal file
@ -0,0 +1,105 @@
|
||||
// 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/stubs/port.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
template<size_t doublewords>
|
||||
class HasBits {
|
||||
public:
|
||||
HasBits() GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE { Clear(); }
|
||||
|
||||
void Clear() GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE {
|
||||
memset(has_bits_, 0, sizeof(has_bits_));
|
||||
}
|
||||
|
||||
::google::protobuf::uint32& operator[](int index) GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE {
|
||||
return has_bits_[index];
|
||||
}
|
||||
|
||||
const ::google::protobuf::uint32& operator[](int index) const
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE {
|
||||
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);
|
||||
}
|
||||
|
||||
bool empty() const;
|
||||
|
||||
private:
|
||||
::google::protobuf::uint32 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
|
||||
#endif // GOOGLE_PROTOBUF_HAS_BITS_H__
|
135
third_party/protobuf-lite/google/protobuf/implicit_weak_message.h
vendored
Normal file
135
third_party/protobuf-lite/google/protobuf/implicit_weak_message.h
vendored
Normal file
@ -0,0 +1,135 @@
|
||||
// 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 <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/arena.h>
|
||||
#include <google/protobuf/message_lite.h>
|
||||
|
||||
// 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 LIBPROTOBUF_EXPORT ImplicitWeakMessage : public MessageLite {
|
||||
public:
|
||||
ImplicitWeakMessage() : arena_(NULL) {}
|
||||
explicit ImplicitWeakMessage(Arena* arena) : arena_(arena) {}
|
||||
|
||||
static const ImplicitWeakMessage* default_instance();
|
||||
|
||||
string GetTypeName() const { return ""; }
|
||||
|
||||
MessageLite* New() const { return new ImplicitWeakMessage; }
|
||||
MessageLite* New(Arena* arena) const {
|
||||
return Arena::CreateMessage<ImplicitWeakMessage>(arena);
|
||||
}
|
||||
|
||||
Arena* GetArena() const { return arena_; }
|
||||
|
||||
void Clear() { data_.clear(); }
|
||||
|
||||
bool IsInitialized() const { return true; }
|
||||
|
||||
void CheckTypeAndMergeFrom(const MessageLite& other) {
|
||||
data_.append(static_cast<const ImplicitWeakMessage&>(other).data_);
|
||||
}
|
||||
|
||||
bool MergePartialFromCodedStream(io::CodedInputStream* input);
|
||||
|
||||
size_t ByteSizeLong() const { return data_.size(); }
|
||||
|
||||
void SerializeWithCachedSizes(io::CodedOutputStream* output) const {
|
||||
output->WriteString(data_);
|
||||
}
|
||||
|
||||
int GetCachedSize() const { return static_cast<int>(data_.size()); }
|
||||
|
||||
typedef void InternalArenaConstructable_;
|
||||
|
||||
private:
|
||||
Arena* const arena_;
|
||||
string data_;
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImplicitWeakMessage);
|
||||
};
|
||||
|
||||
// A type handler for use with implicit weak repeated message fields.
|
||||
template <typename ImplicitWeakType>
|
||||
class ImplicitWeakTypeHandler {
|
||||
public:
|
||||
typedef ImplicitWeakType Type;
|
||||
typedef ::google::protobuf::MessageLite WeakType;
|
||||
static const bool Moveable = false;
|
||||
|
||||
// With implicit weak fields, we need separate NewFromPrototype and
|
||||
// NewFromPrototypeWeak functions. The former is used when we want to create a
|
||||
// strong dependency on the message type, and it just delegates to the
|
||||
// GenericTypeHandler. The latter avoids creating a strong dependency, by
|
||||
// simply calling MessageLite::New.
|
||||
static inline ::google::protobuf::MessageLite* NewFromPrototype(
|
||||
const ::google::protobuf::MessageLite* prototype, ::google::protobuf::Arena* arena = NULL) {
|
||||
return prototype->New(arena);
|
||||
}
|
||||
|
||||
static inline void Delete(::google::protobuf::MessageLite* value, Arena* arena) {
|
||||
if (arena == NULL) {
|
||||
delete value;
|
||||
}
|
||||
}
|
||||
static inline ::google::protobuf::Arena* GetArena(::google::protobuf::MessageLite* value) {
|
||||
return value->GetArena();
|
||||
}
|
||||
static inline void* GetMaybeArenaPointer(::google::protobuf::MessageLite* value) {
|
||||
return value->GetArena();
|
||||
}
|
||||
static inline void Clear(::google::protobuf::MessageLite* value) {
|
||||
value->Clear();
|
||||
}
|
||||
static void Merge(const ::google::protobuf::MessageLite& from,
|
||||
::google::protobuf::MessageLite* to) {
|
||||
to->CheckTypeAndMergeFrom(from);
|
||||
}
|
||||
static inline size_t SpaceUsedLong(const Type& value) {
|
||||
return value.SpaceUsedLong();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_IMPLICIT_WEAK_MESSAGE_H__
|
271
third_party/protobuf-lite/google/protobuf/inlined_string_field.h
vendored
Normal file
271
third_party/protobuf-lite/google/protobuf/inlined_string_field.h
vendored
Normal file
@ -0,0 +1,271 @@
|
||||
// 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 <google/protobuf/stubs/port.h>
|
||||
#include <google/protobuf/stubs/stringpiece.h>
|
||||
|
||||
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. As ::std::string is never
|
||||
// allocated on the Arena, we expose only the *NoArena methods of
|
||||
// ArenaStringPtr.
|
||||
//
|
||||
// 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.
|
||||
class LIBPROTOBUF_EXPORT InlinedStringField {
|
||||
public:
|
||||
InlinedStringField()
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE;
|
||||
explicit InlinedStringField(const ::std::string& default_value);
|
||||
|
||||
void AssignWithDefault(const ::std::string* default_value,
|
||||
const InlinedStringField& from)
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE;
|
||||
|
||||
void ClearToEmpty(const ::std::string* default_value, Arena* arena)
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE {
|
||||
ClearToEmptyNoArena(default_value);
|
||||
}
|
||||
void ClearNonDefaultToEmpty() GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE {
|
||||
ClearNonDefaultToEmptyNoArena();
|
||||
}
|
||||
void ClearToEmptyNoArena(const ::std::string* default_value)
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE {
|
||||
ClearNonDefaultToEmptyNoArena();
|
||||
}
|
||||
void ClearNonDefaultToEmptyNoArena()
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE;
|
||||
|
||||
void ClearToDefault(const ::std::string* default_value, Arena* arena)
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE {
|
||||
ClearToDefaultNoArena(default_value);
|
||||
}
|
||||
void ClearToDefaultNoArena(const ::std::string* default_value)
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE;
|
||||
|
||||
void Destroy(const ::std::string* default_value, Arena* arena)
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE {
|
||||
DestroyNoArena(default_value);
|
||||
}
|
||||
void DestroyNoArena(const ::std::string* default_value)
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE;
|
||||
|
||||
const ::std::string& Get() const GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE {
|
||||
return GetNoArena();
|
||||
}
|
||||
const ::std::string& GetNoArena() const GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE;
|
||||
|
||||
::std::string* Mutable(const ::std::string* default_value, Arena* arena)
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE {
|
||||
return MutableNoArena(default_value);
|
||||
}
|
||||
::std::string* MutableNoArena(const ::std::string* default_value)
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE;
|
||||
|
||||
::std::string* Release(const ::std::string* default_value, Arena* arena) {
|
||||
return ReleaseNoArena(default_value);
|
||||
}
|
||||
::std::string* ReleaseNonDefault(const ::std::string* default_value, Arena* arena) {
|
||||
return ReleaseNonDefaultNoArena(default_value);
|
||||
}
|
||||
::std::string* ReleaseNoArena(const ::std::string* default_value) {
|
||||
return ReleaseNonDefaultNoArena(default_value);
|
||||
}
|
||||
::std::string* ReleaseNonDefaultNoArena(const ::std::string* default_value);
|
||||
|
||||
void Set(const ::std::string* default_value,
|
||||
StringPiece value,
|
||||
Arena* arena) GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE {
|
||||
SetNoArena(default_value, value);
|
||||
}
|
||||
void SetLite(const ::std::string* default_value,
|
||||
StringPiece value,
|
||||
Arena* arena) GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE {
|
||||
SetNoArena(default_value, value);
|
||||
}
|
||||
void SetNoArena(const ::std::string* default_value,
|
||||
StringPiece value) GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE;
|
||||
|
||||
void Set(const ::std::string* default_value,
|
||||
const ::std::string& value,
|
||||
Arena* arena) GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE {
|
||||
SetNoArena(default_value, value);
|
||||
}
|
||||
void SetLite(const ::std::string* default_value,
|
||||
const ::std::string& value,
|
||||
Arena* arena) GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE {
|
||||
SetNoArena(default_value, value);
|
||||
}
|
||||
void SetNoArena(const ::std::string* default_value,
|
||||
const ::std::string& value)
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE;
|
||||
|
||||
#if LANG_CXX11
|
||||
void SetNoArena(const ::std::string* default_value,
|
||||
::std::string&& value)
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE;
|
||||
#endif
|
||||
void SetAllocated(const ::std::string* default_value,
|
||||
::std::string* value,
|
||||
Arena* arena) {
|
||||
SetAllocatedNoArena(default_value, value);
|
||||
}
|
||||
void SetAllocatedNoArena(const ::std::string* default_value,
|
||||
::std::string* value);
|
||||
void Swap(InlinedStringField* from)
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE;
|
||||
::std::string* UnsafeMutablePointer();
|
||||
void UnsafeSetDefault(const ::std::string* default_value);
|
||||
::std::string* UnsafeArenaRelease(const ::std::string* default_value, Arena* arena);
|
||||
void UnsafeArenaSetAllocated(
|
||||
const ::std::string* default_value, ::std::string* value, Arena* arena);
|
||||
|
||||
bool IsDefault(const ::std::string* default_value) {
|
||||
return false;
|
||||
}
|
||||
private:
|
||||
::std::string value_;
|
||||
};
|
||||
|
||||
inline InlinedStringField::InlinedStringField() {}
|
||||
|
||||
inline InlinedStringField::InlinedStringField(const ::std::string& default_value) :
|
||||
value_(default_value) {}
|
||||
|
||||
inline void InlinedStringField::AssignWithDefault(
|
||||
const ::std::string* default_value, const InlinedStringField& from) {
|
||||
value_ = from.value_;
|
||||
}
|
||||
|
||||
inline const ::std::string& InlinedStringField::GetNoArena() const {
|
||||
return value_;
|
||||
}
|
||||
|
||||
inline ::std::string* InlinedStringField::MutableNoArena(const ::std::string*) {
|
||||
return &value_;
|
||||
}
|
||||
|
||||
inline void InlinedStringField::SetAllocatedNoArena(
|
||||
const ::std::string* default_value, ::std::string* value) {
|
||||
if (value == NULL) {
|
||||
value_.assign(*default_value);
|
||||
} else {
|
||||
#if LANG_CXX11
|
||||
value_.assign(std::move(*value));
|
||||
#else
|
||||
value_.swap(*value);
|
||||
#endif
|
||||
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::ClearNonDefaultToEmptyNoArena() {
|
||||
value_.clear();
|
||||
}
|
||||
|
||||
inline void InlinedStringField::ClearToDefaultNoArena(
|
||||
const ::std::string* default_value) {
|
||||
value_.assign(*default_value);
|
||||
}
|
||||
|
||||
inline ::std::string* InlinedStringField::ReleaseNonDefaultNoArena(
|
||||
const ::std::string* default_value) {
|
||||
::std::string* released = new ::std::string(*default_value);
|
||||
value_.swap(*released);
|
||||
return released;
|
||||
}
|
||||
|
||||
inline void InlinedStringField::SetNoArena(
|
||||
const ::std::string* default_value, StringPiece value) {
|
||||
value_.assign(value.data(), value.length());
|
||||
}
|
||||
|
||||
inline void InlinedStringField::SetNoArena(
|
||||
const ::std::string* default_value, const ::std::string& value) {
|
||||
value_.assign(value);
|
||||
}
|
||||
|
||||
#if LANG_CXX11
|
||||
inline void InlinedStringField::SetNoArena(
|
||||
const ::std::string* default_value, ::std::string&& value) {
|
||||
value_.assign(std::move(value));
|
||||
}
|
||||
#endif
|
||||
|
||||
inline void InlinedStringField::Swap(InlinedStringField* from) {
|
||||
value_.swap(from->value_);
|
||||
}
|
||||
|
||||
inline ::std::string* InlinedStringField::UnsafeMutablePointer() {
|
||||
return &value_;
|
||||
}
|
||||
|
||||
inline void InlinedStringField::UnsafeSetDefault(
|
||||
const ::std::string* default_value) {
|
||||
value_.assign(*default_value);
|
||||
}
|
||||
|
||||
inline ::std::string* InlinedStringField::UnsafeArenaRelease(
|
||||
const ::std::string* default_value, Arena* arena) {
|
||||
return ReleaseNoArena(default_value);
|
||||
}
|
||||
|
||||
inline void InlinedStringField::UnsafeArenaSetAllocated(
|
||||
const ::std::string* default_value, ::std::string* value, Arena* arena) {
|
||||
if (value == NULL) {
|
||||
value_.assign(*default_value);
|
||||
} else {
|
||||
value_.assign(*value);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_INLINED_STRING_FIELD_H__
|
1400
third_party/protobuf-lite/google/protobuf/io/coded_stream.h
vendored
Normal file
1400
third_party/protobuf-lite/google/protobuf/io/coded_stream.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
90
third_party/protobuf-lite/google/protobuf/io/coded_stream_inl.h
vendored
Normal file
90
third_party/protobuf-lite/google/protobuf/io/coded_stream_inl.h
vendored
Normal file
@ -0,0 +1,90 @@
|
||||
// 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)
|
||||
//
|
||||
// Implements methods of coded_stream.h that need to be inlined for performance
|
||||
// reasons, but should not be defined in a public header.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_IO_CODED_STREAM_INL_H__
|
||||
#define GOOGLE_PROTOBUF_IO_CODED_STREAM_INL_H__
|
||||
|
||||
#include <google/protobuf/stubs/logging.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
|
||||
#include <string>
|
||||
#include <google/protobuf/stubs/stl_util.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace io {
|
||||
|
||||
inline bool CodedInputStream::InternalReadStringInline(string* buffer,
|
||||
int size) {
|
||||
if (size < 0) return false; // security: size is often user-supplied
|
||||
|
||||
if (BufferSize() >= size) {
|
||||
STLStringResizeUninitialized(buffer, size);
|
||||
std::pair<char*, bool> z = as_string_data(buffer);
|
||||
if (z.second) {
|
||||
// Oddly enough, memcpy() requires its first two args to be non-NULL even
|
||||
// if we copy 0 bytes. So, we have ensured that z.first is non-NULL here.
|
||||
GOOGLE_DCHECK(z.first != NULL);
|
||||
memcpy(z.first, buffer_, size);
|
||||
Advance(size);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return ReadStringFallback(buffer, size);
|
||||
}
|
||||
|
||||
inline bool CodedInputStream::InternalReadRawInline(void* buffer, int size) {
|
||||
int current_buffer_size;
|
||||
while ((current_buffer_size = BufferSize()) < size) {
|
||||
// Reading past end of buffer. Copy what we have, then refresh.
|
||||
memcpy(buffer, buffer_, current_buffer_size);
|
||||
buffer = reinterpret_cast<uint8*>(buffer) + current_buffer_size;
|
||||
size -= current_buffer_size;
|
||||
Advance(current_buffer_size);
|
||||
if (!Refresh()) return false;
|
||||
}
|
||||
|
||||
memcpy(buffer, buffer_, size);
|
||||
Advance(size);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace io
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_IO_CODED_STREAM_INL_H__
|
248
third_party/protobuf-lite/google/protobuf/io/zero_copy_stream.h
vendored
Normal file
248
third_party/protobuf-lite/google/protobuf/io/zero_copy_stream.h
vendored
Normal file
@ -0,0 +1,248 @@
|
||||
// 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 <string>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
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 LIBPROTOBUF_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.
|
||||
//
|
||||
// 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 ByteCount() const = 0;
|
||||
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ZeroCopyInputStream);
|
||||
};
|
||||
|
||||
// Abstract interface similar to an output stream but designed to minimize
|
||||
// copying.
|
||||
class LIBPROTOBUF_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 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
|
||||
#endif // GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_H__
|
383
third_party/protobuf-lite/google/protobuf/io/zero_copy_stream_impl_lite.h
vendored
Normal file
383
third_party/protobuf-lite/google/protobuf/io/zero_copy_stream_impl_lite.h
vendored
Normal file
@ -0,0 +1,383 @@
|
||||
// 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 <memory>
|
||||
#include <string>
|
||||
#include <iosfwd>
|
||||
#include <google/protobuf/io/zero_copy_stream.h>
|
||||
#include <google/protobuf/stubs/callback.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/stl_util.h>
|
||||
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace io {
|
||||
|
||||
// ===================================================================
|
||||
|
||||
// A ZeroCopyInputStream backed by an in-memory array of bytes.
|
||||
class LIBPROTOBUF_EXPORT ArrayInputStream : 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);
|
||||
|
||||
// implements ZeroCopyInputStream ----------------------------------
|
||||
bool Next(const void** data, int* size);
|
||||
void BackUp(int count);
|
||||
bool Skip(int count);
|
||||
int64 ByteCount() const;
|
||||
|
||||
|
||||
private:
|
||||
const uint8* 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 LIBPROTOBUF_EXPORT ArrayOutputStream : 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);
|
||||
|
||||
// implements ZeroCopyOutputStream ---------------------------------
|
||||
bool Next(void** data, int* size);
|
||||
void BackUp(int count);
|
||||
int64 ByteCount() const;
|
||||
|
||||
private:
|
||||
uint8* 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 LIBPROTOBUF_EXPORT StringOutputStream : 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(string* target);
|
||||
|
||||
// implements ZeroCopyOutputStream ---------------------------------
|
||||
bool Next(void** data, int* size);
|
||||
void BackUp(int count);
|
||||
int64 ByteCount() const;
|
||||
|
||||
protected:
|
||||
void SetString(string* target);
|
||||
|
||||
private:
|
||||
static const int kMinimumSize = 16;
|
||||
|
||||
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 LIBPROTOBUF_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 LIBPROTOBUF_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();
|
||||
|
||||
// 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);
|
||||
void BackUp(int count);
|
||||
bool Skip(int count);
|
||||
int64 ByteCount() const;
|
||||
|
||||
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 permenant error from the underlying stream.
|
||||
bool failed_;
|
||||
|
||||
// The current position of copying_stream_, relative to the point where
|
||||
// we started reading.
|
||||
int64 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[]> 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 LIBPROTOBUF_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 LIBPROTOBUF_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();
|
||||
|
||||
// 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);
|
||||
void BackUp(int count);
|
||||
int64 ByteCount() const;
|
||||
|
||||
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 permenant error from the underlying stream.
|
||||
bool failed_;
|
||||
|
||||
// The current position of copying_stream_, relative to the point where
|
||||
// we started writing.
|
||||
int64 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[]> 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);
|
||||
};
|
||||
|
||||
// ===================================================================
|
||||
|
||||
// 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(string* s) {
|
||||
#ifdef LANG_CXX11
|
||||
// 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];
|
||||
#else
|
||||
return string_as_array(s);
|
||||
#endif
|
||||
}
|
||||
|
||||
// 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(string* s) {
|
||||
char *p = mutable_string_data(s);
|
||||
#ifdef LANG_CXX11
|
||||
return std::make_pair(p, true);
|
||||
#else
|
||||
return std::make_pair(p, p != NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace io
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_LITE_H__
|
1219
third_party/protobuf-lite/google/protobuf/map.h
vendored
Normal file
1219
third_party/protobuf-lite/google/protobuf/map.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
671
third_party/protobuf-lite/google/protobuf/map_entry_lite.h
vendored
Normal file
671
third_party/protobuf-lite/google/protobuf/map_entry_lite.h
vendored
Normal file
@ -0,0 +1,671 @@
|
||||
// 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 <google/protobuf/stubs/casts.h>
|
||||
#include <google/protobuf/arena.h>
|
||||
#include <google/protobuf/arenastring.h>
|
||||
#include <google/protobuf/map.h>
|
||||
#include <google/protobuf/map_type_handler.h>
|
||||
#include <google/protobuf/stubs/port.h>
|
||||
#include <google/protobuf/wire_format_lite_inl.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
template <typename Derived, typename Key, typename Value,
|
||||
WireFormatLite::FieldType kKeyFieldType,
|
||||
WireFormatLite::FieldType kValueFieldType, int default_enum_value>
|
||||
class MapEntry;
|
||||
template <typename Derived, typename Key, typename Value,
|
||||
WireFormatLite::FieldType kKeyFieldType,
|
||||
WireFormatLite::FieldType kValueFieldType, int default_enum_value>
|
||||
class MapFieldLite;
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
|
||||
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) {
|
||||
#if __cplusplus >= 201103L
|
||||
*dest = std::move(*src);
|
||||
#else
|
||||
dest->swap(*src);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
// 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, int default_enum_value>
|
||||
class MapEntryImpl : public Base {
|
||||
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 kKeyTag = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(
|
||||
kKeyFieldNumber, KeyTypeHandler::kWireType);
|
||||
static const uint8 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;
|
||||
static const int kEntryDefaultEnumValue = default_enum_value;
|
||||
|
||||
MapEntryImpl() : arena_(NULL) {
|
||||
KeyTypeHandler::Initialize(&key_, NULL);
|
||||
ValueTypeHandler::InitializeMaybeByDefaultEnum(&value_, default_enum_value,
|
||||
NULL);
|
||||
_has_bits_[0] = 0;
|
||||
}
|
||||
|
||||
explicit MapEntryImpl(Arena* arena) : arena_(arena) {
|
||||
KeyTypeHandler::Initialize(&key_, arena);
|
||||
ValueTypeHandler::InitializeMaybeByDefaultEnum(&value_, default_enum_value,
|
||||
arena);
|
||||
_has_bits_[0] = 0;
|
||||
}
|
||||
|
||||
~MapEntryImpl() {
|
||||
if (GetArenaNoVirtual() != NULL) 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_, Derived::internal_default_instance()->value_);
|
||||
}
|
||||
inline KeyMapEntryAccessorType* mutable_key() {
|
||||
set_has_key();
|
||||
return KeyTypeHandler::EnsureMutable(&key_, GetArenaNoVirtual());
|
||||
}
|
||||
inline ValueMapEntryAccessorType* mutable_value() {
|
||||
set_has_value();
|
||||
return ValueTypeHandler::EnsureMutable(&value_, GetArenaNoVirtual());
|
||||
}
|
||||
|
||||
// implements MessageLite =========================================
|
||||
|
||||
// MapEntryImpl is for implementation only and this function isn't called
|
||||
// anywhere. Just provide a fake implementation here for MessageLite.
|
||||
string GetTypeName() const { return ""; }
|
||||
|
||||
void CheckTypeAndMergeFrom(const MessageLite& other) {
|
||||
MergeFromInternal(*::google::protobuf::down_cast<const Derived*>(&other));
|
||||
}
|
||||
|
||||
bool MergePartialFromCodedStream(::google::protobuf::io::CodedInputStream* input) {
|
||||
uint32 tag;
|
||||
|
||||
for (;;) {
|
||||
// 1) corrupted data: return false;
|
||||
// 2) unknown field: skip without putting into unknown field set;
|
||||
// 3) unknown enum value: keep it in parsing. In proto2, caller should
|
||||
// check the value and put this entry into containing message's unknown
|
||||
// field set if the value is an unknown enum. In proto3, caller doesn't
|
||||
// need to care whether the value is unknown enum;
|
||||
// 4) missing key/value: missed key/value will have default value. caller
|
||||
// should take this entry as if key/value is set to default value.
|
||||
tag = input->ReadTagNoLastTag();
|
||||
switch (tag) {
|
||||
case kKeyTag:
|
||||
if (!KeyTypeHandler::Read(input, mutable_key())) {
|
||||
return false;
|
||||
}
|
||||
set_has_key();
|
||||
break;
|
||||
|
||||
case kValueTag:
|
||||
if (!ValueTypeHandler::Read(input, mutable_value())) {
|
||||
return false;
|
||||
}
|
||||
set_has_value();
|
||||
if (input->ExpectAtEnd()) return true;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (tag == 0 ||
|
||||
WireFormatLite::GetTagWireType(tag) ==
|
||||
WireFormatLite::WIRETYPE_END_GROUP) {
|
||||
return true;
|
||||
}
|
||||
if (!WireFormatLite::SkipField(input, tag)) return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t ByteSizeLong() const {
|
||||
size_t size = 0;
|
||||
size += has_key() ?
|
||||
kTagSize + static_cast<size_t>(KeyTypeHandler::ByteSize(key())) : 0;
|
||||
size += has_value() ?
|
||||
kTagSize + static_cast<size_t>(ValueTypeHandler::ByteSize(value())) : 0;
|
||||
return size;
|
||||
}
|
||||
|
||||
void SerializeWithCachedSizes(::google::protobuf::io::CodedOutputStream* output) const {
|
||||
KeyTypeHandler::Write(kKeyFieldNumber, key(), output);
|
||||
ValueTypeHandler::Write(kValueFieldNumber, value(), output);
|
||||
}
|
||||
|
||||
::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(bool deterministic,
|
||||
::google::protobuf::uint8* output) const {
|
||||
output = KeyTypeHandler::InternalWriteToArray(kKeyFieldNumber, key(),
|
||||
deterministic, output);
|
||||
output = ValueTypeHandler::InternalWriteToArray(kValueFieldNumber, value(),
|
||||
deterministic, output);
|
||||
return output;
|
||||
}
|
||||
|
||||
// Don't override SerializeWithCachedSizesToArray. Use MessageLite's.
|
||||
|
||||
int GetCachedSize() const {
|
||||
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 { return ValueTypeHandler::IsInitialized(value_); }
|
||||
|
||||
Base* New() const {
|
||||
Derived* entry = new Derived;
|
||||
return entry;
|
||||
}
|
||||
|
||||
Base* New(Arena* arena) const {
|
||||
Derived* entry = Arena::CreateMessage<Derived>(arena);
|
||||
return entry;
|
||||
}
|
||||
|
||||
size_t SpaceUsedLong() const {
|
||||
size_t size = sizeof(Derived);
|
||||
size += KeyTypeHandler::SpaceUsedInMapEntryLong(key_);
|
||||
size += ValueTypeHandler::SpaceUsedInMapEntryLong(value_);
|
||||
return size;
|
||||
}
|
||||
|
||||
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_, GetArenaNoVirtual());
|
||||
KeyTypeHandler::Merge(from.key(), &key_, GetArenaNoVirtual());
|
||||
set_has_key();
|
||||
}
|
||||
if (from.has_value()) {
|
||||
ValueTypeHandler::EnsureMutable(&value_, GetArenaNoVirtual());
|
||||
ValueTypeHandler::Merge(from.value(), &value_, GetArenaNoVirtual());
|
||||
set_has_value();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
void Clear() {
|
||||
KeyTypeHandler::Clear(&key_, GetArenaNoVirtual());
|
||||
ValueTypeHandler::ClearMaybeByDefaultEnum(
|
||||
&value_, GetArenaNoVirtual(), default_enum_value);
|
||||
clear_has_key();
|
||||
clear_has_value();
|
||||
}
|
||||
|
||||
static void InitAsDefaultInstance() {
|
||||
Derived* d = const_cast<Derived*>(Derived::internal_default_instance());
|
||||
KeyTypeHandler::AssignDefaultValue(&d->key_);
|
||||
ValueTypeHandler::AssignDefaultValue(&d->value_);
|
||||
}
|
||||
|
||||
Arena* GetArena() const {
|
||||
return GetArenaNoVirtual();
|
||||
}
|
||||
|
||||
// Create a MapEntryImpl for given key and value from google::protobuf::Map in
|
||||
// serialization. This function is only called when value is enum. Enum is
|
||||
// treated differently because its type in MapEntry is int and its type in
|
||||
// google::protobuf::Map is enum. We cannot create a reference to int from an enum.
|
||||
static Derived* EnumWrap(const Key& key, const Value value, Arena* arena) {
|
||||
return Arena::CreateMessage<MapEnumEntryWrapper>(arena, key, value);
|
||||
}
|
||||
|
||||
// Like above, but for all the other types. This avoids value copy to create
|
||||
// MapEntryImpl from google::protobuf::Map in serialization.
|
||||
static Derived* Wrap(const Key& key, const Value& value, Arena* arena) {
|
||||
return Arena::CreateMessage<MapEntryWrapper>(arena, key, 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()) {}
|
||||
|
||||
// This does what the typical MergePartialFromCodedStream() is expected to
|
||||
// do, with the additional side-effect that if successful (i.e., if true is
|
||||
// going to be its return value) it inserts the key-value pair into map_.
|
||||
bool MergePartialFromCodedStream(::google::protobuf::io::CodedInputStream* input) {
|
||||
// Look for the expected thing: a key and then a value. If it fails,
|
||||
// invoke the enclosing class's MergePartialFromCodedStream, or return
|
||||
// false if that would be pointless.
|
||||
if (input->ExpectTag(kKeyTag)) {
|
||||
if (!KeyTypeHandler::Read(input, &key_)) {
|
||||
return false;
|
||||
}
|
||||
// Peek at the next byte to see if it is kValueTag. If not, bail out.
|
||||
const void* data;
|
||||
int size;
|
||||
input->GetDirectBufferPointerInline(&data, &size);
|
||||
// We could use memcmp here, but we don't bother. The tag is one byte.
|
||||
GOOGLE_COMPILE_ASSERT(kTagSize == 1, tag_size_error);
|
||||
if (size > 0 && *reinterpret_cast<const char*>(data) == kValueTag) {
|
||||
typename Map::size_type map_size = map_->size();
|
||||
value_ptr_ = &(*map_)[key_];
|
||||
if (GOOGLE_PREDICT_TRUE(map_size != map_->size())) {
|
||||
// We created a new key-value pair. Fill in the value.
|
||||
typedef
|
||||
typename MapIf<ValueTypeHandler::kIsEnum, int*, Value*>::type T;
|
||||
input->Skip(kTagSize); // Skip kValueTag.
|
||||
if (!ValueTypeHandler::Read(input,
|
||||
reinterpret_cast<T>(value_ptr_))) {
|
||||
map_->erase(key_); // Failure! Undo insertion.
|
||||
return false;
|
||||
}
|
||||
if (input->ExpectAtEnd()) return true;
|
||||
return ReadBeyondKeyValuePair(input);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
key_ = Key();
|
||||
}
|
||||
|
||||
entry_.reset(mf_->NewEntry());
|
||||
*entry_->mutable_key() = key_;
|
||||
const bool result = entry_->MergePartialFromCodedStream(input);
|
||||
if (result) UseKeyAndValueFromEntry();
|
||||
if (entry_->GetArena() != NULL) entry_.release();
|
||||
return result;
|
||||
}
|
||||
|
||||
const Key& key() const { return key_; }
|
||||
const Value& value() const { return *value_ptr_; }
|
||||
|
||||
private:
|
||||
void UseKeyAndValueFromEntry() GOOGLE_PROTOBUF_ATTRIBUTE_COLD {
|
||||
// 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_];
|
||||
MoveHelper<ValueTypeHandler::kIsEnum,
|
||||
ValueTypeHandler::kIsMessage,
|
||||
ValueTypeHandler::kWireType ==
|
||||
WireFormatLite::WIRETYPE_LENGTH_DELIMITED,
|
||||
Value>::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(::google::protobuf::io::CodedInputStream* input)
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_COLD {
|
||||
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;
|
||||
entry_.reset(mf_->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();
|
||||
if (entry_->GetArena() != NULL) entry_.release();
|
||||
return result;
|
||||
}
|
||||
|
||||
MapField* const mf_;
|
||||
Map* const map_;
|
||||
Key key_;
|
||||
Value* value_ptr_;
|
||||
// On the fast path entry_ is not used. And, when entry_ is used, it's set
|
||||
// to mf_->NewEntry(), so in the arena case we must call entry_.release.
|
||||
std::unique_ptr<MapEntryImpl> entry_;
|
||||
};
|
||||
|
||||
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; }
|
||||
|
||||
private:
|
||||
// Serializing a generated message containing map field involves serializing
|
||||
// key-value pairs from google::protobuf::Map. The wire format of each key-value pair
|
||||
// after serialization should be the same as that of a MapEntry message
|
||||
// containing the same key and value inside it. However, google::protobuf::Map doesn't
|
||||
// store key and value as MapEntry message, which disables us to use existing
|
||||
// code to serialize message. In order to use existing code to serialize
|
||||
// message, we need to construct a MapEntry from key-value pair. But it
|
||||
// involves copy of key and value to construct a MapEntry. In order to avoid
|
||||
// this copy in constructing a MapEntry, we need the following class which
|
||||
// only takes references of given key and value.
|
||||
class MapEntryWrapper : public Derived {
|
||||
typedef Derived BaseClass;
|
||||
typedef typename BaseClass::KeyMapEntryAccessorType KeyMapEntryAccessorType;
|
||||
typedef
|
||||
typename BaseClass::ValueMapEntryAccessorType ValueMapEntryAccessorType;
|
||||
|
||||
public:
|
||||
MapEntryWrapper(Arena* arena, const Key& key, const Value& value)
|
||||
: Derived(arena), key_(key), value_(value) {
|
||||
BaseClass::set_has_key();
|
||||
BaseClass::set_has_value();
|
||||
}
|
||||
inline const KeyMapEntryAccessorType& key() const { return key_; }
|
||||
inline const ValueMapEntryAccessorType& value() const { return value_; }
|
||||
|
||||
private:
|
||||
const Key& key_;
|
||||
const Value& value_;
|
||||
|
||||
friend class ::google::protobuf::Arena;
|
||||
typedef void InternalArenaConstructable_;
|
||||
typedef void DestructorSkippable_;
|
||||
};
|
||||
|
||||
// Like above, but for enum value only, which stores value instead of
|
||||
// reference of value field inside. This is needed because the type of value
|
||||
// field in constructor is an enum, while we need to store it as an int. If we
|
||||
// initialize a reference to int with a reference to enum, compiler will
|
||||
// generate a temporary int from enum and initialize the reference to int with
|
||||
// the temporary.
|
||||
class MapEnumEntryWrapper : public Derived {
|
||||
typedef Derived BaseClass;
|
||||
typedef typename BaseClass::KeyMapEntryAccessorType KeyMapEntryAccessorType;
|
||||
typedef
|
||||
typename BaseClass::ValueMapEntryAccessorType ValueMapEntryAccessorType;
|
||||
|
||||
public:
|
||||
MapEnumEntryWrapper(Arena* arena, const Key& key, const Value& value)
|
||||
: Derived(arena), key_(key), value_(value) {
|
||||
BaseClass::set_has_key();
|
||||
BaseClass::set_has_value();
|
||||
}
|
||||
inline const KeyMapEntryAccessorType& key() const { return key_; }
|
||||
inline const ValueMapEntryAccessorType& value() const { return value_; }
|
||||
|
||||
private:
|
||||
const KeyMapEntryAccessorType& key_;
|
||||
const ValueMapEntryAccessorType value_;
|
||||
|
||||
friend class google::protobuf::Arena;
|
||||
typedef void DestructorSkippable_;
|
||||
};
|
||||
|
||||
inline Arena* GetArenaNoVirtual() const {
|
||||
return arena_;
|
||||
}
|
||||
|
||||
public: // Needed for constructing tables
|
||||
KeyOnMemory key_;
|
||||
ValueOnMemory value_;
|
||||
Arena* arena_;
|
||||
uint32 _has_bits_[1];
|
||||
|
||||
private:
|
||||
friend class ::google::protobuf::Arena;
|
||||
typedef void InternalArenaConstructable_;
|
||||
typedef void DestructorSkippable_;
|
||||
template <typename C, typename K, typename V, WireFormatLite::FieldType,
|
||||
WireFormatLite::FieldType, int>
|
||||
friend class internal::MapEntry;
|
||||
template <typename C, typename K, typename V, WireFormatLite::FieldType,
|
||||
WireFormatLite::FieldType, int>
|
||||
friend class internal::MapFieldLite;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntryImpl);
|
||||
};
|
||||
|
||||
template <typename T, typename Key, typename Value,
|
||||
WireFormatLite::FieldType kKeyFieldType,
|
||||
WireFormatLite::FieldType kValueFieldType, int default_enum_value>
|
||||
class MapEntryLite
|
||||
: public MapEntryImpl<T, MessageLite, Key, Value, kKeyFieldType,
|
||||
kValueFieldType, default_enum_value> {
|
||||
public:
|
||||
typedef MapEntryImpl<T, MessageLite, Key, Value, kKeyFieldType,
|
||||
kValueFieldType, default_enum_value>
|
||||
SuperType;
|
||||
MapEntryLite() {}
|
||||
explicit MapEntryLite(Arena* arena) : SuperType(arena) {}
|
||||
void MergeFrom(const MapEntryLite& other) { MergeFromInternal(other); }
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntryLite);
|
||||
};
|
||||
// The completely unprincipled and unwieldy use of template parameters in
|
||||
// the map code necessitates wrappers to make the code a little bit more
|
||||
// manageable.
|
||||
template <typename Derived>
|
||||
struct DeconstructMapEntry;
|
||||
|
||||
template <typename T, typename K, typename V, WireFormatLite::FieldType key,
|
||||
WireFormatLite::FieldType value, int default_enum>
|
||||
struct DeconstructMapEntry<MapEntryLite<T, K, V, key, value, default_enum> > {
|
||||
typedef K Key;
|
||||
typedef V Value;
|
||||
static const WireFormatLite::FieldType kKeyFieldType = key;
|
||||
static const WireFormatLite::FieldType kValueFieldType = value;
|
||||
static const int default_enum_value = default_enum;
|
||||
};
|
||||
|
||||
// Helpers for deterministic serialization =============================
|
||||
|
||||
// This struct can be used with any generic sorting algorithm. If the Key
|
||||
// type is relatively small and easy to copy then copying Keys into an
|
||||
// array of SortItems can be beneficial. Then all the data the sorting
|
||||
// algorithm needs to touch is in that one array.
|
||||
template <typename Key, typename PtrToKeyValuePair> struct SortItem {
|
||||
SortItem() {}
|
||||
explicit SortItem(PtrToKeyValuePair p) : first(p->first), second(p) {}
|
||||
|
||||
Key first;
|
||||
PtrToKeyValuePair second;
|
||||
};
|
||||
|
||||
template <typename T> struct CompareByFirstField {
|
||||
bool operator()(const T& a, const T& b) const {
|
||||
return a.first < b.first;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T> struct CompareByDerefFirst {
|
||||
bool operator()(const T& a, const T& b) const {
|
||||
return a->first < b->first;
|
||||
}
|
||||
};
|
||||
|
||||
// Helper for table driven serialization
|
||||
|
||||
template <WireFormatLite::FieldType FieldType>
|
||||
struct FromHelper {
|
||||
template <typename T>
|
||||
static const T& From(const T& x) {
|
||||
return x;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct FromHelper<WireFormatLite::TYPE_STRING> {
|
||||
static ArenaStringPtr From(const string& x) {
|
||||
ArenaStringPtr res;
|
||||
TaggedPtr<::std::string> ptr;
|
||||
ptr.Set(const_cast<string*>(&x));
|
||||
res.UnsafeSetTaggedPointer(ptr);
|
||||
return res;
|
||||
}
|
||||
};
|
||||
template <>
|
||||
struct FromHelper<WireFormatLite::TYPE_BYTES> {
|
||||
static ArenaStringPtr From(const string& x) {
|
||||
ArenaStringPtr res;
|
||||
TaggedPtr<::std::string> ptr;
|
||||
ptr.Set(const_cast<string*>(&x));
|
||||
res.UnsafeSetTaggedPointer(ptr);
|
||||
return res;
|
||||
}
|
||||
};
|
||||
template <>
|
||||
struct FromHelper<WireFormatLite::TYPE_MESSAGE> {
|
||||
template <typename T>
|
||||
static T* From(const T& x) {
|
||||
return const_cast<T*>(&x);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename MapEntryType>
|
||||
struct MapEntryHelper;
|
||||
|
||||
template <typename T, typename Key, typename Value,
|
||||
WireFormatLite::FieldType kKeyFieldType,
|
||||
WireFormatLite::FieldType kValueFieldType, int default_enum_value>
|
||||
struct MapEntryHelper<MapEntryLite<T, Key, Value, kKeyFieldType,
|
||||
kValueFieldType, default_enum_value> > {
|
||||
// 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;
|
||||
|
||||
explicit MapEntryHelper(const MapPair<Key, Value>& map_pair)
|
||||
: _has_bits_(3),
|
||||
_cached_size_(2 + KeyTypeHandler::GetCachedSize(map_pair.first) +
|
||||
ValueTypeHandler::GetCachedSize(map_pair.second)),
|
||||
key_(FromHelper<kKeyFieldType>::From(map_pair.first)),
|
||||
value_(FromHelper<kValueFieldType>::From(map_pair.second)) {}
|
||||
|
||||
// Purposely not folowing the style guide naming. These are the names
|
||||
// the proto compiler would generate given the map entry descriptor.
|
||||
// The proto compiler generates the offsets in this struct as if this was
|
||||
// a regular message. This way the table driven code barely notices it's
|
||||
// dealing with a map field.
|
||||
uint32 _has_bits_; // NOLINT
|
||||
uint32 _cached_size_; // NOLINT
|
||||
KeyOnMemory key_; // NOLINT
|
||||
ValueOnMemory value_; // NOLINT
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_MAP_ENTRY_LITE_H__
|
143
third_party/protobuf-lite/google/protobuf/map_field_lite.h
vendored
Normal file
143
third_party/protobuf-lite/google/protobuf/map_field_lite.h
vendored
Normal file
@ -0,0 +1,143 @@
|
||||
// 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 <google/protobuf/map.h>
|
||||
#include <google/protobuf/map_entry_lite.h>
|
||||
#include <google/protobuf/wire_format_lite.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
// This class provides access to map field using generated api. It is used for
|
||||
// internal generated message implentation only. Users should never use this
|
||||
// directly.
|
||||
template <typename Derived, typename Key, typename T,
|
||||
WireFormatLite::FieldType key_wire_type,
|
||||
WireFormatLite::FieldType value_wire_type, int default_enum_value = 0>
|
||||
class MapFieldLite {
|
||||
// Define message type for internal repeated field.
|
||||
typedef Derived EntryType;
|
||||
|
||||
public:
|
||||
typedef Map<Key, T> MapType;
|
||||
typedef EntryType EntryTypeTrait;
|
||||
|
||||
MapFieldLite() : arena_(NULL) { SetDefaultEnumValue(); }
|
||||
|
||||
explicit MapFieldLite(Arena* arena) : arena_(arena), map_(arena) {
|
||||
SetDefaultEnumValue();
|
||||
}
|
||||
|
||||
// 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_); }
|
||||
|
||||
// Set default enum value only for proto2 map field whose value is enum type.
|
||||
void SetDefaultEnumValue() {
|
||||
MutableMap()->SetDefaultEnumValue(default_enum_value);
|
||||
}
|
||||
|
||||
// Used in the implementation of parsing. Caller should take the ownership iff
|
||||
// arena_ is NULL.
|
||||
EntryType* NewEntry() const {
|
||||
if (arena_ == NULL) {
|
||||
return new EntryType();
|
||||
} else {
|
||||
return Arena::CreateMessage<EntryType>(arena_);
|
||||
}
|
||||
}
|
||||
// Used in the implementation of serializing enum value type. Caller should
|
||||
// take the ownership iff arena_ is NULL.
|
||||
EntryType* NewEnumEntryWrapper(const Key& key, const T t) const {
|
||||
return EntryType::EnumWrap(key, t, arena_);
|
||||
}
|
||||
// Used in the implementation of serializing other value types. Caller should
|
||||
// take the ownership iff arena_ is NULL.
|
||||
EntryType* NewEntryWrapper(const Key& key, const T& t) const {
|
||||
return EntryType::Wrap(key, t, arena_);
|
||||
}
|
||||
|
||||
private:
|
||||
typedef void DestructorSkippable_;
|
||||
|
||||
Arena* arena_;
|
||||
Map<Key, T> map_;
|
||||
|
||||
friend class ::google::protobuf::Arena;
|
||||
};
|
||||
|
||||
// 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 Key, typename T>
|
||||
bool AllAreInitialized(const Map<Key, T>& t) {
|
||||
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, int default_enum_value>
|
||||
struct MapEntryToMapField<MapEntryLite<T, Key, Value, kKeyFieldType,
|
||||
kValueFieldType, default_enum_value> > {
|
||||
typedef MapFieldLite<MapEntryLite<T, Key, Value, kKeyFieldType,
|
||||
kValueFieldType, default_enum_value>,
|
||||
Key, Value, kKeyFieldType, kValueFieldType,
|
||||
default_enum_value>
|
||||
MapFieldType;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_MAP_FIELD_LITE_H__
|
739
third_party/protobuf-lite/google/protobuf/map_type_handler.h
vendored
Normal file
739
third_party/protobuf-lite/google/protobuf/map_type_handler.h
vendored
Normal file
@ -0,0 +1,739 @@
|
||||
// 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_TYPE_HANDLER_H__
|
||||
#define GOOGLE_PROTOBUF_TYPE_HANDLER_H__
|
||||
|
||||
#include <google/protobuf/arena.h>
|
||||
#include <google/protobuf/wire_format_lite_inl.h>
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
// In proto2 Map, enum needs to be initialized to given default value, while
|
||||
// other types' default value can be inferred from the type.
|
||||
template <bool IsEnum, typename Type>
|
||||
class MapValueInitializer {
|
||||
public:
|
||||
static inline void Initialize(Type& type, int default_enum_value);
|
||||
};
|
||||
|
||||
template <typename Type>
|
||||
class MapValueInitializer<true, Type> {
|
||||
public:
|
||||
static inline void Initialize(Type& value, int default_enum_value) {
|
||||
value = static_cast<Type>(default_enum_value);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Type>
|
||||
class MapValueInitializer<false, Type> {
|
||||
public:
|
||||
static inline void Initialize(Type& /* value */, int /* default_enum_value */) {}
|
||||
};
|
||||
|
||||
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 , VARINT , false, false)
|
||||
TYPE_TRAITS(UINT64 , uint64 , VARINT , false, false)
|
||||
TYPE_TRAITS(INT32 , int32 , VARINT , false, false)
|
||||
TYPE_TRAITS(UINT32 , uint32 , VARINT , false, false)
|
||||
TYPE_TRAITS(SINT64 , int64 , VARINT , false, false)
|
||||
TYPE_TRAITS(SINT32 , int32 , 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 , FIXED64, false, false)
|
||||
TYPE_TRAITS(FIXED32 , uint32 , FIXED32, false, false)
|
||||
TYPE_TRAITS(SFIXED64, int64 , FIXED64, false, false)
|
||||
TYPE_TRAITS(SFIXED32, int32 , 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 const WireFormatLite::WireType kWireType =
|
||||
MapWireFieldTypeTraits<WireFormatLite::TYPE_MESSAGE, Type>::kWireType;
|
||||
// Whether wire type is for message.
|
||||
static const bool kIsMessage =
|
||||
MapWireFieldTypeTraits<WireFormatLite::TYPE_MESSAGE, Type>::kIsMessage;
|
||||
// Whether wire type is for enum.
|
||||
static const 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 void Write(int field, const MapEntryAccessorType& value,
|
||||
io::CodedOutputStream* output);
|
||||
static inline uint8* InternalWriteToArray(int field,
|
||||
const MapEntryAccessorType& value,
|
||||
bool deterministic, uint8* target);
|
||||
static inline uint8* WriteToArray(int field,
|
||||
const MapEntryAccessorType& value,
|
||||
uint8* target);
|
||||
|
||||
// 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 inline void ClearMaybeByDefaultEnum(Type** value, Arena* arena,
|
||||
int default_enum_value);
|
||||
static inline void Initialize(Type** x, Arena* arena);
|
||||
|
||||
static inline void InitializeMaybeByDefaultEnum(Type** x,
|
||||
int default_enum_value,
|
||||
Arena* arena);
|
||||
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 bytes used by value in Map.
|
||||
static inline size_t SpaceUsedInMapLong(const Type& value);
|
||||
// Assign default value to given instance.
|
||||
static inline void AssignDefaultValue(Type** value);
|
||||
// Return default instance if value is not initialized when calling const
|
||||
// reference accessor.
|
||||
static inline const Type& DefaultIfNotInitialized(
|
||||
const Type* value, const Type* default_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 void Write(int field, const MapEntryAccessorType& value, \
|
||||
io::CodedOutputStream* output); \
|
||||
static inline uint8* InternalWriteToArray( \
|
||||
int field, const MapEntryAccessorType& value, bool deterministic, \
|
||||
uint8* target); \
|
||||
static inline uint8* WriteToArray(int field, \
|
||||
const MapEntryAccessorType& value, \
|
||||
uint8* target) { \
|
||||
return InternalWriteToArray(field, value, false, target); \
|
||||
} \
|
||||
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 void ClearMaybeByDefaultEnum(TypeOnMemory* value, \
|
||||
Arena* arena, \
|
||||
int default_enum); \
|
||||
static inline size_t SpaceUsedInMapEntryLong(const TypeOnMemory& value); \
|
||||
static inline size_t SpaceUsedInMapLong(const TypeOnMemory& value); \
|
||||
static inline size_t SpaceUsedInMapLong(const string& value); \
|
||||
static inline void AssignDefaultValue(TypeOnMemory* value); \
|
||||
static inline const MapEntryAccessorType& DefaultIfNotInitialized( \
|
||||
const TypeOnMemory& value, const TypeOnMemory& default_value); \
|
||||
static inline bool IsInitialized(const TypeOnMemory& value); \
|
||||
static void DeleteNoArena(TypeOnMemory& value); \
|
||||
static inline void Initialize(TypeOnMemory* value, Arena* arena); \
|
||||
static inline void InitializeMaybeByDefaultEnum(TypeOnMemory* value, \
|
||||
int default_enum_value, \
|
||||
Arena* arena); \
|
||||
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 void MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::Write(
|
||||
int field, const MapEntryAccessorType& value,
|
||||
io::CodedOutputStream* output) {
|
||||
WireFormatLite::WriteMessageMaybeToArray(field, value, output);
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
inline uint8*
|
||||
MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::InternalWriteToArray(
|
||||
int field, const MapEntryAccessorType& value, bool deterministic,
|
||||
uint8* target) {
|
||||
return WireFormatLite::InternalWriteMessageToArray(field, value,
|
||||
deterministic, target);
|
||||
}
|
||||
|
||||
#define WRITE_METHOD(FieldType, DeclaredType) \
|
||||
template <typename Type> \
|
||||
inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Write( \
|
||||
int field, const MapEntryAccessorType& value, \
|
||||
io::CodedOutputStream* output) { \
|
||||
return WireFormatLite::Write##DeclaredType(field, value, output); \
|
||||
} \
|
||||
template <typename Type> \
|
||||
inline uint8* \
|
||||
MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
|
||||
Type>::InternalWriteToArray( \
|
||||
int field, const MapEntryAccessorType& value, bool, uint8* target) { \
|
||||
return WireFormatLite::Write##DeclaredType##ToArray(field, value, target); \
|
||||
}
|
||||
|
||||
WRITE_METHOD(STRING , String)
|
||||
WRITE_METHOD(BYTES , Bytes)
|
||||
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);
|
||||
}
|
||||
|
||||
#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); \
|
||||
}
|
||||
|
||||
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>
|
||||
size_t MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::SpaceUsedInMapLong(
|
||||
const Type& value) {
|
||||
return value.SpaceUsedLong();
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
inline void MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::Clear(
|
||||
Type** value, Arena* /* arena */) {
|
||||
if (*value != NULL) (*value)->Clear();
|
||||
}
|
||||
template <typename Type>
|
||||
inline void
|
||||
MapTypeHandler<WireFormatLite::TYPE_MESSAGE,
|
||||
Type>::ClearMaybeByDefaultEnum(Type** value,
|
||||
Arena* /* arena */,
|
||||
int /* default_enum_value */) {
|
||||
if (*value != NULL) (*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>
|
||||
inline void MapTypeHandler<WireFormatLite::TYPE_MESSAGE,
|
||||
Type>::AssignDefaultValue(Type** value) {
|
||||
*value = const_cast<Type*>(Type::internal_default_instance());
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
inline void MapTypeHandler<WireFormatLite::TYPE_MESSAGE,
|
||||
Type>::Initialize(Type** x,
|
||||
Arena* /* arena */) {
|
||||
*x = NULL;
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
inline void MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::
|
||||
InitializeMaybeByDefaultEnum(Type** x, int /* default_enum_value */,
|
||||
Arena* /* arena */) {
|
||||
*x = NULL;
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
inline Type* MapTypeHandler<WireFormatLite::TYPE_MESSAGE,
|
||||
Type>::EnsureMutable(Type** value,
|
||||
Arena* arena) {
|
||||
if (*value == NULL) {
|
||||
*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, const Type* default_value) {
|
||||
return value != NULL ? *value : *default_value;
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
inline bool MapTypeHandler<WireFormatLite::TYPE_MESSAGE,
|
||||
Type>::IsInitialized(Type* value) {
|
||||
return value->IsInitialized();
|
||||
}
|
||||
|
||||
// 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 size_t \
|
||||
MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::SpaceUsedInMapLong( \
|
||||
const TypeOnMemory& value) { \
|
||||
return sizeof(value); \
|
||||
} \
|
||||
template <typename Type> \
|
||||
inline size_t \
|
||||
MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::SpaceUsedInMapLong( \
|
||||
const string& value) { \
|
||||
return sizeof(value); \
|
||||
} \
|
||||
template <typename Type> \
|
||||
inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Clear( \
|
||||
TypeOnMemory* value, Arena* arena) { \
|
||||
value->ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), \
|
||||
arena); \
|
||||
} \
|
||||
template <typename Type> \
|
||||
inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>:: \
|
||||
ClearMaybeByDefaultEnum(TypeOnMemory* value, Arena* arena, \
|
||||
int /* default_enum */) { \
|
||||
Clear(value, arena); \
|
||||
} \
|
||||
template <typename Type> \
|
||||
inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Merge( \
|
||||
const MapEntryAccessorType& from, TypeOnMemory* to, Arena* arena) { \
|
||||
to->Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from, arena); \
|
||||
} \
|
||||
template <typename Type> \
|
||||
void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::DeleteNoArena( \
|
||||
TypeOnMemory& value) { \
|
||||
value.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); \
|
||||
} \
|
||||
template <typename Type> \
|
||||
inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
|
||||
Type>::AssignDefaultValue(TypeOnMemory* /* value */) {} \
|
||||
template <typename Type> \
|
||||
inline void \
|
||||
MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Initialize( \
|
||||
TypeOnMemory* value, Arena* /* arena */) { \
|
||||
value->UnsafeSetDefault( \
|
||||
&::google::protobuf::internal::GetEmptyStringAlreadyInited()); \
|
||||
} \
|
||||
template <typename Type> \
|
||||
inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>:: \
|
||||
InitializeMaybeByDefaultEnum(TypeOnMemory* value, \
|
||||
int /* default_enum_value */, \
|
||||
Arena* arena) { \
|
||||
Initialize(value, arena); \
|
||||
} \
|
||||
template <typename Type> \
|
||||
inline typename MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
|
||||
Type>::MapEntryAccessorType* \
|
||||
MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::EnsureMutable( \
|
||||
TypeOnMemory* value, Arena* arena) { \
|
||||
return value->Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), \
|
||||
arena); \
|
||||
} \
|
||||
template <typename Type> \
|
||||
inline const typename MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
|
||||
Type>::MapEntryAccessorType& \
|
||||
MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
|
||||
Type>::DefaultIfNotInitialized(const TypeOnMemory& value, \
|
||||
const TypeOnMemory& \
|
||||
/* default_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 size_t \
|
||||
MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::SpaceUsedInMapLong( \
|
||||
const TypeOnMemory& /* value */) { \
|
||||
return sizeof(Type); \
|
||||
} \
|
||||
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>:: \
|
||||
ClearMaybeByDefaultEnum(TypeOnMemory* value, Arena* /* arena */, \
|
||||
int default_enum_value) { \
|
||||
*value = static_cast<TypeOnMemory>(default_enum_value); \
|
||||
} \
|
||||
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> \
|
||||
inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
|
||||
Type>::AssignDefaultValue(TypeOnMemory* /* value */) {} \
|
||||
template <typename Type> \
|
||||
inline void \
|
||||
MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Initialize( \
|
||||
TypeOnMemory* value, Arena* /* arena */) { \
|
||||
*value = 0; \
|
||||
} \
|
||||
template <typename Type> \
|
||||
inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>:: \
|
||||
InitializeMaybeByDefaultEnum(TypeOnMemory* value, \
|
||||
int default_enum_value, \
|
||||
Arena* /* arena */) { \
|
||||
*value = static_cast<TypeOnMemory>(default_enum_value); \
|
||||
} \
|
||||
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, \
|
||||
const TypeOnMemory& \
|
||||
/* default_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
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_TYPE_HANDLER_H__
|
424
third_party/protobuf-lite/google/protobuf/message_lite.h
vendored
Normal file
424
third_party/protobuf-lite/google/protobuf/message_lite.h
vendored
Normal file
@ -0,0 +1,424 @@
|
||||
// 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 <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/logging.h>
|
||||
#include <google/protobuf/stubs/once.h>
|
||||
#include <google/protobuf/arena.h>
|
||||
#include <google/protobuf/stubs/port.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
template <typename T>
|
||||
class RepeatedPtrField;
|
||||
namespace io {
|
||||
class CodedInputStream;
|
||||
class CodedOutputStream;
|
||||
class ZeroCopyInputStream;
|
||||
class ZeroCopyOutputStream;
|
||||
}
|
||||
namespace internal {
|
||||
|
||||
class RepeatedPtrFieldBase;
|
||||
class WireFormatLite;
|
||||
class WeakFieldMap;
|
||||
|
||||
#ifndef SWIG
|
||||
// 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);
|
||||
}
|
||||
|
||||
// This type 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 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>
|
||||
class ExplicitlyConstructed {
|
||||
public:
|
||||
void DefaultConstruct() {
|
||||
new (&union_) T();
|
||||
}
|
||||
|
||||
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:
|
||||
// Prefer c++14 aligned_storage, but for compatibility this will do.
|
||||
union AlignedUnion {
|
||||
char space[sizeof(T)];
|
||||
int64 align_to_int64;
|
||||
void* align_to_ptr;
|
||||
} union_;
|
||||
};
|
||||
|
||||
// Default empty string object. Don't use this directly. Instead, call
|
||||
// GetEmptyString() to get the reference.
|
||||
LIBPROTOBUF_EXPORT extern ExplicitlyConstructed<::std::string> fixed_address_empty_string;
|
||||
|
||||
LIBPROTOBUF_EXPORT inline const ::std::string& GetEmptyStringAlreadyInited() {
|
||||
return fixed_address_empty_string.get();
|
||||
}
|
||||
|
||||
LIBPROTOBUF_EXPORT size_t StringSpaceUsedExcludingSelfLong(const string& str);
|
||||
#endif // SWIG
|
||||
} // 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.
|
||||
class LIBPROTOBUF_EXPORT MessageLite {
|
||||
public:
|
||||
inline MessageLite() {}
|
||||
virtual ~MessageLite() {}
|
||||
|
||||
// Basic Operations ------------------------------------------------
|
||||
|
||||
// Get the name of this message type, e.g. "foo.bar.BazProto".
|
||||
virtual string GetTypeName() const = 0;
|
||||
|
||||
// Construct a new instance of the same type. Ownership is passed to the
|
||||
// caller.
|
||||
virtual MessageLite* New() const = 0;
|
||||
|
||||
// Construct a new instance on the arena. Ownership is passed to the caller
|
||||
// if arena is a NULL. Default implementation for backwards compatibility.
|
||||
virtual MessageLite* New(::google::protobuf::Arena* arena) const;
|
||||
|
||||
// Get the arena, if any, associated with this message. Virtual method
|
||||
// required for generic operations but most arena-related operations should
|
||||
// use the GetArenaNoVirtual() generated-code method. Default implementation
|
||||
// to reduce code size by avoiding the need for per-type implementations
|
||||
// when types do not implement arena support.
|
||||
virtual ::google::protobuf::Arena* GetArena() const { return NULL; }
|
||||
|
||||
// Get a pointer that may be equal to this message's arena, or may not be.
|
||||
// If the value returned by this method is equal to some arena pointer, then
|
||||
// this message is on that arena; however, if this message is on some arena,
|
||||
// this method may or may not return that arena's pointer. As a tradeoff,
|
||||
// this method may be more efficient than GetArena(). The intent is to allow
|
||||
// underlying representations that use e.g. tagged pointers to sometimes
|
||||
// store the arena pointer directly, and sometimes in a more indirect way,
|
||||
// and allow a fastpath comparison against the arena pointer when it's easy
|
||||
// to obtain.
|
||||
virtual void* GetMaybeArenaPointer() const { return GetArena(); }
|
||||
|
||||
// Clear all fields of the message and set them to their default values.
|
||||
// Clear() avoids freeing memory, assuming that any memory allocated
|
||||
// to hold parts of the message will be needed again to hold the next
|
||||
// message. If you actually want to free the memory used by a Message,
|
||||
// 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 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;
|
||||
|
||||
// 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.
|
||||
bool ParseFromCodedStream(io::CodedInputStream* input);
|
||||
// Like ParseFromCodedStream(), but accepts messages that are missing
|
||||
// required fields.
|
||||
bool ParsePartialFromCodedStream(io::CodedInputStream* input);
|
||||
// Read a protocol buffer from the given zero-copy input stream. If
|
||||
// successful, the entire input will be consumed.
|
||||
bool ParseFromZeroCopyStream(io::ZeroCopyInputStream* input);
|
||||
// Like ParseFromZeroCopyStream(), but accepts messages that are missing
|
||||
// required fields.
|
||||
bool ParsePartialFromZeroCopyStream(io::ZeroCopyInputStream* 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 ParseFromBoundedZeroCopyStream(io::ZeroCopyInputStream* input, int size);
|
||||
// Like ParseFromBoundedZeroCopyStream(), but accepts messages that are
|
||||
// missing required fields.
|
||||
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().
|
||||
bool ParseFromString(const string& data);
|
||||
// Like ParseFromString(), but accepts messages that are missing
|
||||
// required fields.
|
||||
bool ParsePartialFromString(const string& data);
|
||||
// Parse a protocol buffer contained in an array of bytes.
|
||||
bool ParseFromArray(const void* data, int size);
|
||||
// Like ParseFromArray(), but accepts messages that are missing
|
||||
// required fields.
|
||||
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().
|
||||
virtual bool MergePartialFromCodedStream(io::CodedInputStream* input) = 0;
|
||||
|
||||
|
||||
// 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(string* output) const;
|
||||
// Like SerializeToString(), but allows missing required fields.
|
||||
bool SerializePartialToString(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().
|
||||
string SerializeAsString() const;
|
||||
// Like SerializeAsString(), but allows missing required fields.
|
||||
string SerializePartialAsString() const;
|
||||
|
||||
// Like SerializeToString(), but appends to the data to the string's existing
|
||||
// contents. All required fields must be set.
|
||||
bool AppendToString(string* output) const;
|
||||
// Like AppendToString(), but allows missing required fields.
|
||||
bool AppendPartialToString(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_RUNTIME_DEPRECATED("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.
|
||||
virtual void SerializeWithCachedSizes(
|
||||
io::CodedOutputStream* output) const;
|
||||
|
||||
// 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().
|
||||
virtual uint8* SerializeWithCachedSizesToArray(uint8* 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 uint8* InternalSerializeWithCachedSizesToArray(bool deterministic,
|
||||
uint8* target) const;
|
||||
|
||||
protected:
|
||||
// CastToBase allows generated code to cast a RepeatedPtrField<T> to
|
||||
// RepeatedPtrFieldBase. We try to restrict access to RepeatedPtrFieldBase
|
||||
// because it is an implementation detail that user code should not access
|
||||
// directly.
|
||||
template <typename T>
|
||||
static ::google::protobuf::internal::RepeatedPtrFieldBase* CastToBase(
|
||||
::google::protobuf::RepeatedPtrField<T>* repeated) {
|
||||
return repeated;
|
||||
}
|
||||
template <typename T>
|
||||
static const ::google::protobuf::internal::RepeatedPtrFieldBase& CastToBase(
|
||||
const ::google::protobuf::RepeatedPtrField<T>& repeated) {
|
||||
return repeated;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static T* CreateMaybeMessage(Arena* arena) {
|
||||
return Arena::CreateMaybeMessage<T>(arena);
|
||||
}
|
||||
|
||||
private:
|
||||
// TODO(gerbens) make this a pure abstract function
|
||||
virtual const void* InternalGetTable() const { return NULL; }
|
||||
|
||||
friend class internal::WireFormatLite;
|
||||
friend class Message;
|
||||
friend class internal::WeakFieldMap;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageLite);
|
||||
};
|
||||
|
||||
namespace internal {
|
||||
|
||||
extern bool LIBPROTOBUF_EXPORT proto3_preserve_unknown_;
|
||||
|
||||
// DO NOT USE: For migration only. Will be removed when Proto3 defaults to
|
||||
// preserve unknowns.
|
||||
inline bool GetProto3PreserveUnknownsDefault() {
|
||||
return proto3_preserve_unknown_;
|
||||
}
|
||||
|
||||
// DO NOT USE: For migration only. Will be removed when Proto3 defaults to
|
||||
// preserve unknowns.
|
||||
void LIBPROTOBUF_EXPORT SetProto3PreserveUnknownsDefault(bool preserve);
|
||||
} // namespace internal
|
||||
|
||||
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_MESSAGE_LITE_H__
|
224
third_party/protobuf-lite/google/protobuf/metadata_lite.h
vendored
Normal file
224
third_party/protobuf-lite/google/protobuf/metadata_lite.h
vendored
Normal file
@ -0,0 +1,224 @@
|
||||
// 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 <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/arena.h>
|
||||
#include <google/protobuf/message_lite.h>
|
||||
#include <google/protobuf/stubs/port.h>
|
||||
|
||||
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 Arena pointer, if there are no
|
||||
// unknown fields, or a pointer to a block of memory with both the Arena pointer
|
||||
// and the UnknownFieldSet, if there are unknown fields. This optimization
|
||||
// allows for "zero-overhead" storage of the Arena pointer, relative to the
|
||||
// above baseline implementation.
|
||||
//
|
||||
// The tagged pointer uses the LSB to disambiguate cases, and uses bit 0 == 0 to
|
||||
// indicate an arena pointer and bit 0 == 1 to indicate a UFS+Arena-container
|
||||
// pointer.
|
||||
template <class T, class Derived>
|
||||
class InternalMetadataWithArenaBase {
|
||||
public:
|
||||
InternalMetadataWithArenaBase() : ptr_(NULL) {}
|
||||
explicit InternalMetadataWithArenaBase(Arena* arena) : ptr_(arena) {}
|
||||
|
||||
~InternalMetadataWithArenaBase() {
|
||||
if (have_unknown_fields() && arena() == NULL) {
|
||||
delete PtrValue<Container>();
|
||||
}
|
||||
ptr_ = NULL;
|
||||
}
|
||||
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE const T& unknown_fields() const {
|
||||
if (GOOGLE_PREDICT_FALSE(have_unknown_fields())) {
|
||||
return PtrValue<Container>()->unknown_fields;
|
||||
} else {
|
||||
return Derived::default_instance();
|
||||
}
|
||||
}
|
||||
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE T* mutable_unknown_fields() {
|
||||
if (GOOGLE_PREDICT_TRUE(have_unknown_fields())) {
|
||||
return &PtrValue<Container>()->unknown_fields;
|
||||
} else {
|
||||
return mutable_unknown_fields_slow();
|
||||
}
|
||||
}
|
||||
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE Arena* arena() const {
|
||||
if (GOOGLE_PREDICT_FALSE(have_unknown_fields())) {
|
||||
return PtrValue<Container>()->arena;
|
||||
} else {
|
||||
return PtrValue<Arena>();
|
||||
}
|
||||
}
|
||||
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE bool have_unknown_fields() const {
|
||||
return PtrTag() == kTagContainer;
|
||||
}
|
||||
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE void Swap(Derived* 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()) {
|
||||
static_cast<Derived*>(this)->DoSwap(other->mutable_unknown_fields());
|
||||
}
|
||||
}
|
||||
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE void MergeFrom(const Derived& other) {
|
||||
if (other.have_unknown_fields()) {
|
||||
static_cast<Derived*>(this)->DoMergeFrom(other.unknown_fields());
|
||||
}
|
||||
}
|
||||
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE void Clear() {
|
||||
if (have_unknown_fields()) {
|
||||
static_cast<Derived*>(this)->DoClear();
|
||||
}
|
||||
}
|
||||
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE void* raw_arena_ptr() const {
|
||||
return ptr_;
|
||||
}
|
||||
|
||||
private:
|
||||
void* ptr_;
|
||||
|
||||
// Tagged pointer implementation.
|
||||
enum {
|
||||
// ptr_ is an Arena*.
|
||||
kTagArena = 0,
|
||||
// ptr_ is a Container*.
|
||||
kTagContainer = 1,
|
||||
};
|
||||
static const intptr_t kPtrTagMask = 1;
|
||||
static const intptr_t kPtrValueMask = ~kPtrTagMask;
|
||||
|
||||
// Accessors for pointer tag and pointer value.
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE int PtrTag() const {
|
||||
return reinterpret_cast<intptr_t>(ptr_) & kPtrTagMask;
|
||||
}
|
||||
|
||||
template<typename U> U* PtrValue() const {
|
||||
return reinterpret_cast<U*>(
|
||||
reinterpret_cast<intptr_t>(ptr_) & kPtrValueMask);
|
||||
}
|
||||
|
||||
// If ptr_'s tag is kTagContainer, it points to an instance of this struct.
|
||||
struct Container {
|
||||
T unknown_fields;
|
||||
Arena* arena;
|
||||
};
|
||||
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE T* mutable_unknown_fields_slow() {
|
||||
Arena* my_arena = arena();
|
||||
Container* container = Arena::Create<Container>(my_arena);
|
||||
// Two-step assignment works around a bug in clang's static analyzer:
|
||||
// https://bugs.llvm.org/show_bug.cgi?id=34198.
|
||||
ptr_ = container;
|
||||
ptr_ = reinterpret_cast<void*>(
|
||||
reinterpret_cast<intptr_t>(ptr_) | kTagContainer);
|
||||
container->arena = my_arena;
|
||||
return &(container->unknown_fields);
|
||||
}
|
||||
};
|
||||
|
||||
// We store unknown fields as a string right now, because there is currently no
|
||||
// good interface for reading unknown fields into an ArenaString. We may want
|
||||
// to revisit this to allow unknown fields to be parsed onto the Arena.
|
||||
class InternalMetadataWithArenaLite
|
||||
: public InternalMetadataWithArenaBase<string,
|
||||
InternalMetadataWithArenaLite> {
|
||||
public:
|
||||
InternalMetadataWithArenaLite() {}
|
||||
|
||||
explicit InternalMetadataWithArenaLite(Arena* arena)
|
||||
: InternalMetadataWithArenaBase<string,
|
||||
InternalMetadataWithArenaLite>(arena) {}
|
||||
|
||||
void DoSwap(string* other) {
|
||||
mutable_unknown_fields()->swap(*other);
|
||||
}
|
||||
|
||||
void DoMergeFrom(const string& other) {
|
||||
mutable_unknown_fields()->append(other);
|
||||
}
|
||||
|
||||
void DoClear() {
|
||||
mutable_unknown_fields()->clear();
|
||||
}
|
||||
|
||||
static const string& default_instance() {
|
||||
return GetEmptyStringAlreadyInited();
|
||||
}
|
||||
};
|
||||
|
||||
// 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 LIBPROTOBUF_EXPORT LiteUnknownFieldSetter {
|
||||
public:
|
||||
explicit LiteUnknownFieldSetter(InternalMetadataWithArenaLite* metadata)
|
||||
: metadata_(metadata) {
|
||||
if (metadata->have_unknown_fields()) {
|
||||
buffer_.swap(*metadata->mutable_unknown_fields());
|
||||
}
|
||||
}
|
||||
~LiteUnknownFieldSetter() {
|
||||
if (!buffer_.empty()) metadata_->mutable_unknown_fields()->swap(buffer_);
|
||||
}
|
||||
string* buffer() { return &buffer_; }
|
||||
|
||||
private:
|
||||
InternalMetadataWithArenaLite* metadata_;
|
||||
string buffer_;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_METADATA_LITE_H__
|
2630
third_party/protobuf-lite/google/protobuf/repeated_field.h
vendored
Normal file
2630
third_party/protobuf-lite/google/protobuf/repeated_field.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
348
third_party/protobuf-lite/google/protobuf/stubs/bytestream.h
vendored
Normal file
348
third_party/protobuf-lite/google/protobuf/stubs/bytestream.h
vendored
Normal file
@ -0,0 +1,348 @@
|
||||
// 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 declares the ByteSink and ByteSource abstract interfaces. These
|
||||
// interfaces represent objects that consume (ByteSink) or produce (ByteSource)
|
||||
// a sequence of bytes. Using these abstract interfaces in your APIs can help
|
||||
// make your code work with a variety of input and output types.
|
||||
//
|
||||
// This file also declares the following commonly used implementations of these
|
||||
// interfaces.
|
||||
//
|
||||
// ByteSink:
|
||||
// UncheckedArrayByteSink Writes to an array, without bounds checking
|
||||
// CheckedArrayByteSink Writes to an array, with bounds checking
|
||||
// GrowingArrayByteSink Allocates and writes to a growable buffer
|
||||
// StringByteSink Writes to an STL string
|
||||
// NullByteSink Consumes a never-ending stream of bytes
|
||||
//
|
||||
// ByteSource:
|
||||
// ArrayByteSource Reads from an array or string/StringPiece
|
||||
// LimitedByteSource Limits the number of bytes read from an
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_STUBS_BYTESTREAM_H_
|
||||
#define GOOGLE_PROTOBUF_STUBS_BYTESTREAM_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/stringpiece.h>
|
||||
|
||||
class CordByteSink;
|
||||
class MemBlock;
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace strings {
|
||||
|
||||
// An abstract interface for an object that consumes a sequence of bytes. This
|
||||
// interface offers a way to append data as well as a Flush() function.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// string my_data;
|
||||
// ...
|
||||
// ByteSink* sink = ...
|
||||
// sink->Append(my_data.data(), my_data.size());
|
||||
// sink->Flush();
|
||||
//
|
||||
class LIBPROTOBUF_EXPORT ByteSink {
|
||||
public:
|
||||
ByteSink() {}
|
||||
virtual ~ByteSink() {}
|
||||
|
||||
// Appends the "n" bytes starting at "bytes".
|
||||
virtual void Append(const char* bytes, size_t n) = 0;
|
||||
|
||||
// Flushes internal buffers. The default implemenation does nothing. ByteSink
|
||||
// subclasses may use internal buffers that require calling Flush() at the end
|
||||
// of the stream.
|
||||
virtual void Flush();
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ByteSink);
|
||||
};
|
||||
|
||||
// An abstract interface for an object that produces a fixed-size sequence of
|
||||
// bytes.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// ByteSource* source = ...
|
||||
// while (source->Available() > 0) {
|
||||
// StringPiece data = source->Peek();
|
||||
// ... do something with "data" ...
|
||||
// source->Skip(data.length());
|
||||
// }
|
||||
//
|
||||
class LIBPROTOBUF_EXPORT ByteSource {
|
||||
public:
|
||||
ByteSource() {}
|
||||
virtual ~ByteSource() {}
|
||||
|
||||
// Returns the number of bytes left to read from the source. Available()
|
||||
// should decrease by N each time Skip(N) is called. Available() may not
|
||||
// increase. Available() returning 0 indicates that the ByteSource is
|
||||
// exhausted.
|
||||
//
|
||||
// Note: Size() may have been a more appropriate name as it's more
|
||||
// indicative of the fixed-size nature of a ByteSource.
|
||||
virtual size_t Available() const = 0;
|
||||
|
||||
// Returns a StringPiece of the next contiguous region of the source. Does not
|
||||
// reposition the source. The returned region is empty iff Available() == 0.
|
||||
//
|
||||
// The returned region is valid until the next call to Skip() or until this
|
||||
// object is destroyed, whichever occurs first.
|
||||
//
|
||||
// The length of the returned StringPiece will be <= Available().
|
||||
virtual StringPiece Peek() = 0;
|
||||
|
||||
// Skips the next n bytes. Invalidates any StringPiece returned by a previous
|
||||
// call to Peek().
|
||||
//
|
||||
// REQUIRES: Available() >= n
|
||||
virtual void Skip(size_t n) = 0;
|
||||
|
||||
// Writes the next n bytes in this ByteSource to the given ByteSink, and
|
||||
// advances this ByteSource past the copied bytes. The default implementation
|
||||
// of this method just copies the bytes normally, but subclasses might
|
||||
// override CopyTo to optimize certain cases.
|
||||
//
|
||||
// REQUIRES: Available() >= n
|
||||
virtual void CopyTo(ByteSink* sink, size_t n);
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ByteSource);
|
||||
};
|
||||
|
||||
//
|
||||
// Some commonly used implementations of ByteSink
|
||||
//
|
||||
|
||||
// Implementation of ByteSink that writes to an unsized byte array. No
|
||||
// bounds-checking is performed--it is the caller's responsibility to ensure
|
||||
// that the destination array is large enough.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// char buf[10];
|
||||
// UncheckedArrayByteSink sink(buf);
|
||||
// sink.Append("hi", 2); // OK
|
||||
// sink.Append(data, 100); // WOOPS! Overflows buf[10].
|
||||
//
|
||||
class LIBPROTOBUF_EXPORT UncheckedArrayByteSink : public ByteSink {
|
||||
public:
|
||||
explicit UncheckedArrayByteSink(char* dest) : dest_(dest) {}
|
||||
virtual void Append(const char* data, size_t n);
|
||||
|
||||
// Returns the current output pointer so that a caller can see how many bytes
|
||||
// were produced.
|
||||
//
|
||||
// Note: this method is not part of the ByteSink interface.
|
||||
char* CurrentDestination() const { return dest_; }
|
||||
|
||||
private:
|
||||
char* dest_;
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(UncheckedArrayByteSink);
|
||||
};
|
||||
|
||||
// Implementation of ByteSink that writes to a sized byte array. This sink will
|
||||
// not write more than "capacity" bytes to outbuf. Once "capacity" bytes are
|
||||
// appended, subsequent bytes will be ignored and Overflowed() will return true.
|
||||
// Overflowed() does not cause a runtime error (i.e., it does not CHECK fail).
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// char buf[10];
|
||||
// CheckedArrayByteSink sink(buf, 10);
|
||||
// sink.Append("hi", 2); // OK
|
||||
// sink.Append(data, 100); // Will only write 8 more bytes
|
||||
//
|
||||
class LIBPROTOBUF_EXPORT CheckedArrayByteSink : public ByteSink {
|
||||
public:
|
||||
CheckedArrayByteSink(char* outbuf, size_t capacity);
|
||||
virtual void Append(const char* bytes, size_t n);
|
||||
|
||||
// Returns the number of bytes actually written to the sink.
|
||||
size_t NumberOfBytesWritten() const { return size_; }
|
||||
|
||||
// Returns true if any bytes were discarded, i.e., if there was an
|
||||
// attempt to write more than 'capacity' bytes.
|
||||
bool Overflowed() const { return overflowed_; }
|
||||
|
||||
private:
|
||||
char* outbuf_;
|
||||
const size_t capacity_;
|
||||
size_t size_;
|
||||
bool overflowed_;
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CheckedArrayByteSink);
|
||||
};
|
||||
|
||||
// Implementation of ByteSink that allocates an internal buffer (a char array)
|
||||
// and expands it as needed to accommodate appended data (similar to a string),
|
||||
// and allows the caller to take ownership of the internal buffer via the
|
||||
// GetBuffer() method. The buffer returned from GetBuffer() must be deleted by
|
||||
// the caller with delete[]. GetBuffer() also sets the internal buffer to be
|
||||
// empty, and subsequent appends to the sink will create a new buffer. The
|
||||
// destructor will free the internal buffer if GetBuffer() was not called.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// GrowingArrayByteSink sink(10);
|
||||
// sink.Append("hi", 2);
|
||||
// sink.Append(data, n);
|
||||
// const char* buf = sink.GetBuffer(); // Ownership transferred
|
||||
// delete[] buf;
|
||||
//
|
||||
class LIBPROTOBUF_EXPORT GrowingArrayByteSink : public strings::ByteSink {
|
||||
public:
|
||||
explicit GrowingArrayByteSink(size_t estimated_size);
|
||||
virtual ~GrowingArrayByteSink();
|
||||
virtual void Append(const char* bytes, size_t n);
|
||||
|
||||
// Returns the allocated buffer, and sets nbytes to its size. The caller takes
|
||||
// ownership of the buffer and must delete it with delete[].
|
||||
char* GetBuffer(size_t* nbytes);
|
||||
|
||||
private:
|
||||
void Expand(size_t amount);
|
||||
void ShrinkToFit();
|
||||
|
||||
size_t capacity_;
|
||||
char* buf_;
|
||||
size_t size_;
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GrowingArrayByteSink);
|
||||
};
|
||||
|
||||
// Implementation of ByteSink that appends to the given string.
|
||||
// Existing contents of "dest" are not modified; new data is appended.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// string dest = "Hello ";
|
||||
// StringByteSink sink(&dest);
|
||||
// sink.Append("World", 5);
|
||||
// assert(dest == "Hello World");
|
||||
//
|
||||
class LIBPROTOBUF_EXPORT StringByteSink : public ByteSink {
|
||||
public:
|
||||
explicit StringByteSink(string* dest) : dest_(dest) {}
|
||||
virtual void Append(const char* data, size_t n);
|
||||
|
||||
private:
|
||||
string* dest_;
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringByteSink);
|
||||
};
|
||||
|
||||
// Implementation of ByteSink that discards all data.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// NullByteSink sink;
|
||||
// sink.Append(data, data.size()); // All data ignored.
|
||||
//
|
||||
class LIBPROTOBUF_EXPORT NullByteSink : public ByteSink {
|
||||
public:
|
||||
NullByteSink() {}
|
||||
virtual void Append(const char *data, size_t n) {}
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(NullByteSink);
|
||||
};
|
||||
|
||||
//
|
||||
// Some commonly used implementations of ByteSource
|
||||
//
|
||||
|
||||
// Implementation of ByteSource that reads from a StringPiece.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// string data = "Hello";
|
||||
// ArrayByteSource source(data);
|
||||
// assert(source.Available() == 5);
|
||||
// assert(source.Peek() == "Hello");
|
||||
//
|
||||
class LIBPROTOBUF_EXPORT ArrayByteSource : public ByteSource {
|
||||
public:
|
||||
explicit ArrayByteSource(StringPiece s) : input_(s) {}
|
||||
|
||||
virtual size_t Available() const;
|
||||
virtual StringPiece Peek();
|
||||
virtual void Skip(size_t n);
|
||||
|
||||
private:
|
||||
StringPiece input_;
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ArrayByteSource);
|
||||
};
|
||||
|
||||
// Implementation of ByteSource that wraps another ByteSource, limiting the
|
||||
// number of bytes returned.
|
||||
//
|
||||
// The caller maintains ownership of the underlying source, and may not use the
|
||||
// underlying source while using the LimitByteSource object. The underlying
|
||||
// source's pointer is advanced by n bytes every time this LimitByteSource
|
||||
// object is advanced by n.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// string data = "Hello World";
|
||||
// ArrayByteSource abs(data);
|
||||
// assert(abs.Available() == data.size());
|
||||
//
|
||||
// LimitByteSource limit(abs, 5);
|
||||
// assert(limit.Available() == 5);
|
||||
// assert(limit.Peek() == "Hello");
|
||||
//
|
||||
class LIBPROTOBUF_EXPORT LimitByteSource : public ByteSource {
|
||||
public:
|
||||
// Returns at most "limit" bytes from "source".
|
||||
LimitByteSource(ByteSource* source, size_t limit);
|
||||
|
||||
virtual size_t Available() const;
|
||||
virtual StringPiece Peek();
|
||||
virtual void Skip(size_t n);
|
||||
|
||||
// We override CopyTo so that we can forward to the underlying source, in
|
||||
// case it has an efficient implementation of CopyTo.
|
||||
virtual void CopyTo(ByteSink* sink, size_t n);
|
||||
|
||||
private:
|
||||
ByteSource* source_;
|
||||
size_t limit_;
|
||||
};
|
||||
|
||||
} // namespace strings
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_STUBS_BYTESTREAM_H_
|
577
third_party/protobuf-lite/google/protobuf/stubs/callback.h
vendored
Normal file
577
third_party/protobuf-lite/google/protobuf/stubs/callback.h
vendored
Normal file
@ -0,0 +1,577 @@
|
||||
#ifndef GOOGLE_PROTOBUF_STUBS_CALLBACK_H_
|
||||
#define GOOGLE_PROTOBUF_STUBS_CALLBACK_H_
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include <google/protobuf/stubs/macros.h>
|
||||
|
||||
// ===================================================================
|
||||
// emulates google3/base/callback.h
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
// Abstract interface for a callback. When calling an RPC, you must provide
|
||||
// a Closure to call when the procedure completes. See the Service interface
|
||||
// in service.h.
|
||||
//
|
||||
// To automatically construct a Closure which calls a particular function or
|
||||
// method with a particular set of parameters, use the NewCallback() function.
|
||||
// Example:
|
||||
// void FooDone(const FooResponse* response) {
|
||||
// ...
|
||||
// }
|
||||
//
|
||||
// void CallFoo() {
|
||||
// ...
|
||||
// // When done, call FooDone() and pass it a pointer to the response.
|
||||
// Closure* callback = NewCallback(&FooDone, response);
|
||||
// // Make the call.
|
||||
// service->Foo(controller, request, response, callback);
|
||||
// }
|
||||
//
|
||||
// Example that calls a method:
|
||||
// class Handler {
|
||||
// public:
|
||||
// ...
|
||||
//
|
||||
// void FooDone(const FooResponse* response) {
|
||||
// ...
|
||||
// }
|
||||
//
|
||||
// void CallFoo() {
|
||||
// ...
|
||||
// // When done, call FooDone() and pass it a pointer to the response.
|
||||
// Closure* callback = NewCallback(this, &Handler::FooDone, response);
|
||||
// // Make the call.
|
||||
// service->Foo(controller, request, response, callback);
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// Currently NewCallback() supports binding zero, one, or two arguments.
|
||||
//
|
||||
// Callbacks created with NewCallback() automatically delete themselves when
|
||||
// executed. They should be used when a callback is to be called exactly
|
||||
// once (usually the case with RPC callbacks). If a callback may be called
|
||||
// a different number of times (including zero), create it with
|
||||
// NewPermanentCallback() instead. You are then responsible for deleting the
|
||||
// callback (using the "delete" keyword as normal).
|
||||
//
|
||||
// Note that NewCallback() is a bit touchy regarding argument types. Generally,
|
||||
// the values you provide for the parameter bindings must exactly match the
|
||||
// types accepted by the callback function. For example:
|
||||
// void Foo(string s);
|
||||
// NewCallback(&Foo, "foo"); // WON'T WORK: const char* != string
|
||||
// NewCallback(&Foo, string("foo")); // WORKS
|
||||
// Also note that the arguments cannot be references:
|
||||
// void Foo(const string& s);
|
||||
// string my_str;
|
||||
// NewCallback(&Foo, my_str); // WON'T WORK: Can't use referecnes.
|
||||
// However, correctly-typed pointers will work just fine.
|
||||
class LIBPROTOBUF_EXPORT Closure {
|
||||
public:
|
||||
Closure() {}
|
||||
virtual ~Closure();
|
||||
|
||||
virtual void Run() = 0;
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Closure);
|
||||
};
|
||||
|
||||
template<typename R>
|
||||
class ResultCallback {
|
||||
public:
|
||||
ResultCallback() {}
|
||||
virtual ~ResultCallback() {}
|
||||
|
||||
virtual R Run() = 0;
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ResultCallback);
|
||||
};
|
||||
|
||||
template<typename R, typename A1>
|
||||
class LIBPROTOBUF_EXPORT ResultCallback1 {
|
||||
public:
|
||||
ResultCallback1() {}
|
||||
virtual ~ResultCallback1() {}
|
||||
|
||||
virtual R Run(A1) = 0;
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ResultCallback1);
|
||||
};
|
||||
|
||||
template<typename R, typename A1, typename A2>
|
||||
class LIBPROTOBUF_EXPORT ResultCallback2 {
|
||||
public:
|
||||
ResultCallback2() {}
|
||||
virtual ~ResultCallback2() {}
|
||||
|
||||
virtual R Run(A1,A2) = 0;
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ResultCallback2);
|
||||
};
|
||||
|
||||
namespace internal {
|
||||
|
||||
class LIBPROTOBUF_EXPORT FunctionClosure0 : public Closure {
|
||||
public:
|
||||
typedef void (*FunctionType)();
|
||||
|
||||
FunctionClosure0(FunctionType function, bool self_deleting)
|
||||
: function_(function), self_deleting_(self_deleting) {}
|
||||
~FunctionClosure0();
|
||||
|
||||
void Run() {
|
||||
bool needs_delete = self_deleting_; // read in case callback deletes
|
||||
function_();
|
||||
if (needs_delete) delete this;
|
||||
}
|
||||
|
||||
private:
|
||||
FunctionType function_;
|
||||
bool self_deleting_;
|
||||
};
|
||||
|
||||
template <typename Class>
|
||||
class MethodClosure0 : public Closure {
|
||||
public:
|
||||
typedef void (Class::*MethodType)();
|
||||
|
||||
MethodClosure0(Class* object, MethodType method, bool self_deleting)
|
||||
: object_(object), method_(method), self_deleting_(self_deleting) {}
|
||||
~MethodClosure0() {}
|
||||
|
||||
void Run() {
|
||||
bool needs_delete = self_deleting_; // read in case callback deletes
|
||||
(object_->*method_)();
|
||||
if (needs_delete) delete this;
|
||||
}
|
||||
|
||||
private:
|
||||
Class* object_;
|
||||
MethodType method_;
|
||||
bool self_deleting_;
|
||||
};
|
||||
|
||||
template <typename Arg1>
|
||||
class FunctionClosure1 : public Closure {
|
||||
public:
|
||||
typedef void (*FunctionType)(Arg1 arg1);
|
||||
|
||||
FunctionClosure1(FunctionType function, bool self_deleting,
|
||||
Arg1 arg1)
|
||||
: function_(function), self_deleting_(self_deleting),
|
||||
arg1_(arg1) {}
|
||||
~FunctionClosure1() {}
|
||||
|
||||
void Run() {
|
||||
bool needs_delete = self_deleting_; // read in case callback deletes
|
||||
function_(arg1_);
|
||||
if (needs_delete) delete this;
|
||||
}
|
||||
|
||||
private:
|
||||
FunctionType function_;
|
||||
bool self_deleting_;
|
||||
Arg1 arg1_;
|
||||
};
|
||||
|
||||
template <typename Class, typename Arg1>
|
||||
class MethodClosure1 : public Closure {
|
||||
public:
|
||||
typedef void (Class::*MethodType)(Arg1 arg1);
|
||||
|
||||
MethodClosure1(Class* object, MethodType method, bool self_deleting,
|
||||
Arg1 arg1)
|
||||
: object_(object), method_(method), self_deleting_(self_deleting),
|
||||
arg1_(arg1) {}
|
||||
~MethodClosure1() {}
|
||||
|
||||
void Run() {
|
||||
bool needs_delete = self_deleting_; // read in case callback deletes
|
||||
(object_->*method_)(arg1_);
|
||||
if (needs_delete) delete this;
|
||||
}
|
||||
|
||||
private:
|
||||
Class* object_;
|
||||
MethodType method_;
|
||||
bool self_deleting_;
|
||||
Arg1 arg1_;
|
||||
};
|
||||
|
||||
template <typename Arg1, typename Arg2>
|
||||
class FunctionClosure2 : public Closure {
|
||||
public:
|
||||
typedef void (*FunctionType)(Arg1 arg1, Arg2 arg2);
|
||||
|
||||
FunctionClosure2(FunctionType function, bool self_deleting,
|
||||
Arg1 arg1, Arg2 arg2)
|
||||
: function_(function), self_deleting_(self_deleting),
|
||||
arg1_(arg1), arg2_(arg2) {}
|
||||
~FunctionClosure2() {}
|
||||
|
||||
void Run() {
|
||||
bool needs_delete = self_deleting_; // read in case callback deletes
|
||||
function_(arg1_, arg2_);
|
||||
if (needs_delete) delete this;
|
||||
}
|
||||
|
||||
private:
|
||||
FunctionType function_;
|
||||
bool self_deleting_;
|
||||
Arg1 arg1_;
|
||||
Arg2 arg2_;
|
||||
};
|
||||
|
||||
template <typename Class, typename Arg1, typename Arg2>
|
||||
class MethodClosure2 : public Closure {
|
||||
public:
|
||||
typedef void (Class::*MethodType)(Arg1 arg1, Arg2 arg2);
|
||||
|
||||
MethodClosure2(Class* object, MethodType method, bool self_deleting,
|
||||
Arg1 arg1, Arg2 arg2)
|
||||
: object_(object), method_(method), self_deleting_(self_deleting),
|
||||
arg1_(arg1), arg2_(arg2) {}
|
||||
~MethodClosure2() {}
|
||||
|
||||
void Run() {
|
||||
bool needs_delete = self_deleting_; // read in case callback deletes
|
||||
(object_->*method_)(arg1_, arg2_);
|
||||
if (needs_delete) delete this;
|
||||
}
|
||||
|
||||
private:
|
||||
Class* object_;
|
||||
MethodType method_;
|
||||
bool self_deleting_;
|
||||
Arg1 arg1_;
|
||||
Arg2 arg2_;
|
||||
};
|
||||
|
||||
template<typename R>
|
||||
class FunctionResultCallback_0_0 : public ResultCallback<R> {
|
||||
public:
|
||||
typedef R (*FunctionType)();
|
||||
|
||||
FunctionResultCallback_0_0(FunctionType function, bool self_deleting)
|
||||
: function_(function), self_deleting_(self_deleting) {}
|
||||
~FunctionResultCallback_0_0() {}
|
||||
|
||||
R Run() {
|
||||
bool needs_delete = self_deleting_; // read in case callback deletes
|
||||
R result = function_();
|
||||
if (needs_delete) delete this;
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
FunctionType function_;
|
||||
bool self_deleting_;
|
||||
};
|
||||
|
||||
template<typename R, typename P1>
|
||||
class FunctionResultCallback_1_0 : public ResultCallback<R> {
|
||||
public:
|
||||
typedef R (*FunctionType)(P1);
|
||||
|
||||
FunctionResultCallback_1_0(FunctionType function, bool self_deleting,
|
||||
P1 p1)
|
||||
: function_(function), self_deleting_(self_deleting), p1_(p1) {}
|
||||
~FunctionResultCallback_1_0() {}
|
||||
|
||||
R Run() {
|
||||
bool needs_delete = self_deleting_; // read in case callback deletes
|
||||
R result = function_(p1_);
|
||||
if (needs_delete) delete this;
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
FunctionType function_;
|
||||
bool self_deleting_;
|
||||
P1 p1_;
|
||||
};
|
||||
|
||||
template<typename R, typename Arg1>
|
||||
class FunctionResultCallback_0_1 : public ResultCallback1<R, Arg1> {
|
||||
public:
|
||||
typedef R (*FunctionType)(Arg1 arg1);
|
||||
|
||||
FunctionResultCallback_0_1(FunctionType function, bool self_deleting)
|
||||
: function_(function), self_deleting_(self_deleting) {}
|
||||
~FunctionResultCallback_0_1() {}
|
||||
|
||||
R Run(Arg1 a1) {
|
||||
bool needs_delete = self_deleting_; // read in case callback deletes
|
||||
R result = function_(a1);
|
||||
if (needs_delete) delete this;
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
FunctionType function_;
|
||||
bool self_deleting_;
|
||||
};
|
||||
|
||||
template<typename R, typename P1, typename A1>
|
||||
class FunctionResultCallback_1_1 : public ResultCallback1<R, A1> {
|
||||
public:
|
||||
typedef R (*FunctionType)(P1, A1);
|
||||
|
||||
FunctionResultCallback_1_1(FunctionType function, bool self_deleting,
|
||||
P1 p1)
|
||||
: function_(function), self_deleting_(self_deleting), p1_(p1) {}
|
||||
~FunctionResultCallback_1_1() {}
|
||||
|
||||
R Run(A1 a1) {
|
||||
bool needs_delete = self_deleting_; // read in case callback deletes
|
||||
R result = function_(p1_, a1);
|
||||
if (needs_delete) delete this;
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
FunctionType function_;
|
||||
bool self_deleting_;
|
||||
P1 p1_;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct InternalConstRef {
|
||||
typedef typename std::remove_reference<T>::type base_type;
|
||||
typedef const base_type& type;
|
||||
};
|
||||
|
||||
template<typename R, typename T>
|
||||
class MethodResultCallback_0_0 : public ResultCallback<R> {
|
||||
public:
|
||||
typedef R (T::*MethodType)();
|
||||
MethodResultCallback_0_0(T* object, MethodType method, bool self_deleting)
|
||||
: object_(object),
|
||||
method_(method),
|
||||
self_deleting_(self_deleting) {}
|
||||
~MethodResultCallback_0_0() {}
|
||||
|
||||
R Run() {
|
||||
bool needs_delete = self_deleting_;
|
||||
R result = (object_->*method_)();
|
||||
if (needs_delete) delete this;
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
T* object_;
|
||||
MethodType method_;
|
||||
bool self_deleting_;
|
||||
};
|
||||
|
||||
template <typename R, typename T, typename P1, typename P2, typename P3,
|
||||
typename P4, typename P5, typename A1, typename A2>
|
||||
class MethodResultCallback_5_2 : public ResultCallback2<R, A1, A2> {
|
||||
public:
|
||||
typedef R (T::*MethodType)(P1, P2, P3, P4, P5, A1, A2);
|
||||
MethodResultCallback_5_2(T* object, MethodType method, bool self_deleting,
|
||||
P1 p1, P2 p2, P3 p3, P4 p4, P5 p5)
|
||||
: object_(object),
|
||||
method_(method),
|
||||
self_deleting_(self_deleting),
|
||||
p1_(p1),
|
||||
p2_(p2),
|
||||
p3_(p3),
|
||||
p4_(p4),
|
||||
p5_(p5) {}
|
||||
~MethodResultCallback_5_2() {}
|
||||
|
||||
R Run(A1 a1, A2 a2) {
|
||||
bool needs_delete = self_deleting_;
|
||||
R result = (object_->*method_)(p1_, p2_, p3_, p4_, p5_, a1, a2);
|
||||
if (needs_delete) delete this;
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
T* object_;
|
||||
MethodType method_;
|
||||
bool self_deleting_;
|
||||
typename std::remove_reference<P1>::type p1_;
|
||||
typename std::remove_reference<P2>::type p2_;
|
||||
typename std::remove_reference<P3>::type p3_;
|
||||
typename std::remove_reference<P4>::type p4_;
|
||||
typename std::remove_reference<P5>::type p5_;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// See Closure.
|
||||
inline Closure* NewCallback(void (*function)()) {
|
||||
return new internal::FunctionClosure0(function, true);
|
||||
}
|
||||
|
||||
// See Closure.
|
||||
inline Closure* NewPermanentCallback(void (*function)()) {
|
||||
return new internal::FunctionClosure0(function, false);
|
||||
}
|
||||
|
||||
// See Closure.
|
||||
template <typename Class>
|
||||
inline Closure* NewCallback(Class* object, void (Class::*method)()) {
|
||||
return new internal::MethodClosure0<Class>(object, method, true);
|
||||
}
|
||||
|
||||
// See Closure.
|
||||
template <typename Class>
|
||||
inline Closure* NewPermanentCallback(Class* object, void (Class::*method)()) {
|
||||
return new internal::MethodClosure0<Class>(object, method, false);
|
||||
}
|
||||
|
||||
// See Closure.
|
||||
template <typename Arg1>
|
||||
inline Closure* NewCallback(void (*function)(Arg1),
|
||||
Arg1 arg1) {
|
||||
return new internal::FunctionClosure1<Arg1>(function, true, arg1);
|
||||
}
|
||||
|
||||
// See Closure.
|
||||
template <typename Arg1>
|
||||
inline Closure* NewPermanentCallback(void (*function)(Arg1),
|
||||
Arg1 arg1) {
|
||||
return new internal::FunctionClosure1<Arg1>(function, false, arg1);
|
||||
}
|
||||
|
||||
// See Closure.
|
||||
template <typename Class, typename Arg1>
|
||||
inline Closure* NewCallback(Class* object, void (Class::*method)(Arg1),
|
||||
Arg1 arg1) {
|
||||
return new internal::MethodClosure1<Class, Arg1>(object, method, true, arg1);
|
||||
}
|
||||
|
||||
// See Closure.
|
||||
template <typename Class, typename Arg1>
|
||||
inline Closure* NewPermanentCallback(Class* object, void (Class::*method)(Arg1),
|
||||
Arg1 arg1) {
|
||||
return new internal::MethodClosure1<Class, Arg1>(object, method, false, arg1);
|
||||
}
|
||||
|
||||
// See Closure.
|
||||
template <typename Arg1, typename Arg2>
|
||||
inline Closure* NewCallback(void (*function)(Arg1, Arg2),
|
||||
Arg1 arg1, Arg2 arg2) {
|
||||
return new internal::FunctionClosure2<Arg1, Arg2>(
|
||||
function, true, arg1, arg2);
|
||||
}
|
||||
|
||||
// See Closure.
|
||||
template <typename Arg1, typename Arg2>
|
||||
inline Closure* NewPermanentCallback(void (*function)(Arg1, Arg2),
|
||||
Arg1 arg1, Arg2 arg2) {
|
||||
return new internal::FunctionClosure2<Arg1, Arg2>(
|
||||
function, false, arg1, arg2);
|
||||
}
|
||||
|
||||
// See Closure.
|
||||
template <typename Class, typename Arg1, typename Arg2>
|
||||
inline Closure* NewCallback(Class* object, void (Class::*method)(Arg1, Arg2),
|
||||
Arg1 arg1, Arg2 arg2) {
|
||||
return new internal::MethodClosure2<Class, Arg1, Arg2>(
|
||||
object, method, true, arg1, arg2);
|
||||
}
|
||||
|
||||
// See Closure.
|
||||
template <typename Class, typename Arg1, typename Arg2>
|
||||
inline Closure* NewPermanentCallback(
|
||||
Class* object, void (Class::*method)(Arg1, Arg2),
|
||||
Arg1 arg1, Arg2 arg2) {
|
||||
return new internal::MethodClosure2<Class, Arg1, Arg2>(
|
||||
object, method, false, arg1, arg2);
|
||||
}
|
||||
|
||||
// See ResultCallback
|
||||
template<typename R>
|
||||
inline ResultCallback<R>* NewCallback(R (*function)()) {
|
||||
return new internal::FunctionResultCallback_0_0<R>(function, true);
|
||||
}
|
||||
|
||||
// See ResultCallback
|
||||
template<typename R>
|
||||
inline ResultCallback<R>* NewPermanentCallback(R (*function)()) {
|
||||
return new internal::FunctionResultCallback_0_0<R>(function, false);
|
||||
}
|
||||
|
||||
// See ResultCallback
|
||||
template<typename R, typename P1>
|
||||
inline ResultCallback<R>* NewCallback(R (*function)(P1), P1 p1) {
|
||||
return new internal::FunctionResultCallback_1_0<R, P1>(
|
||||
function, true, p1);
|
||||
}
|
||||
|
||||
// See ResultCallback
|
||||
template<typename R, typename P1>
|
||||
inline ResultCallback<R>* NewPermanentCallback(
|
||||
R (*function)(P1), P1 p1) {
|
||||
return new internal::FunctionResultCallback_1_0<R, P1>(
|
||||
function, false, p1);
|
||||
}
|
||||
|
||||
// See ResultCallback1
|
||||
template<typename R, typename A1>
|
||||
inline ResultCallback1<R, A1>* NewCallback(R (*function)(A1)) {
|
||||
return new internal::FunctionResultCallback_0_1<R, A1>(function, true);
|
||||
}
|
||||
|
||||
// See ResultCallback1
|
||||
template<typename R, typename A1>
|
||||
inline ResultCallback1<R, A1>* NewPermanentCallback(R (*function)(A1)) {
|
||||
return new internal::FunctionResultCallback_0_1<R, A1>(function, false);
|
||||
}
|
||||
|
||||
// See ResultCallback1
|
||||
template<typename R, typename P1, typename A1>
|
||||
inline ResultCallback1<R, A1>* NewCallback(R (*function)(P1, A1), P1 p1) {
|
||||
return new internal::FunctionResultCallback_1_1<R, P1, A1>(
|
||||
function, true, p1);
|
||||
}
|
||||
|
||||
// See ResultCallback1
|
||||
template<typename R, typename P1, typename A1>
|
||||
inline ResultCallback1<R, A1>* NewPermanentCallback(
|
||||
R (*function)(P1, A1), P1 p1) {
|
||||
return new internal::FunctionResultCallback_1_1<R, P1, A1>(
|
||||
function, false, p1);
|
||||
}
|
||||
|
||||
// See MethodResultCallback_0_0
|
||||
template <typename R, typename T1, typename T2>
|
||||
inline ResultCallback<R>* NewPermanentCallback(
|
||||
T1* object, R (T2::*function)()) {
|
||||
return new internal::MethodResultCallback_0_0<R, T1>(object, function, false);
|
||||
}
|
||||
|
||||
// See MethodResultCallback_5_2
|
||||
template <typename R, typename T, typename P1, typename P2, typename P3,
|
||||
typename P4, typename P5, typename A1, typename A2>
|
||||
inline ResultCallback2<R, A1, A2>* NewPermanentCallback(
|
||||
T* object, R (T::*function)(P1, P2, P3, P4, P5, A1, A2),
|
||||
typename internal::InternalConstRef<P1>::type p1,
|
||||
typename internal::InternalConstRef<P2>::type p2,
|
||||
typename internal::InternalConstRef<P3>::type p3,
|
||||
typename internal::InternalConstRef<P4>::type p4,
|
||||
typename internal::InternalConstRef<P5>::type p5) {
|
||||
return new internal::MethodResultCallback_5_2<R, T, P1, P2, P3, P4, P5, A1,
|
||||
A2>(object, function, false, p1,
|
||||
p2, p3, p4, p5);
|
||||
}
|
||||
|
||||
// A function which does nothing. Useful for creating no-op callbacks, e.g.:
|
||||
// Closure* nothing = NewCallback(&DoNothing);
|
||||
void LIBPROTOBUF_EXPORT DoNothing();
|
||||
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_STUBS_CALLBACK_H_
|
134
third_party/protobuf-lite/google/protobuf/stubs/casts.h
vendored
Normal file
134
third_party/protobuf-lite/google/protobuf/stubs/casts.h
vendored
Normal file
@ -0,0 +1,134 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2014 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_CASTS_H__
|
||||
#define GOOGLE_PROTOBUF_CASTS_H__
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
// Use implicit_cast as a safe version of static_cast or const_cast
|
||||
// for upcasting in the type hierarchy (i.e. casting a pointer to Foo
|
||||
// to a pointer to SuperclassOfFoo or casting a pointer to Foo to
|
||||
// a const pointer to Foo).
|
||||
// When you use implicit_cast, the compiler checks that the cast is safe.
|
||||
// Such explicit implicit_casts are necessary in surprisingly many
|
||||
// situations where C++ demands an exact type match instead of an
|
||||
// argument type convertable to a target type.
|
||||
//
|
||||
// The From type can be inferred, so the preferred syntax for using
|
||||
// implicit_cast is the same as for static_cast etc.:
|
||||
//
|
||||
// implicit_cast<ToType>(expr)
|
||||
//
|
||||
// implicit_cast would have been part of the C++ standard library,
|
||||
// but the proposal was submitted too late. It will probably make
|
||||
// its way into the language in the future.
|
||||
template<typename To, typename From>
|
||||
inline To implicit_cast(From const &f) {
|
||||
return f;
|
||||
}
|
||||
|
||||
// When you upcast (that is, cast a pointer from type Foo to type
|
||||
// SuperclassOfFoo), it's fine to use implicit_cast<>, since upcasts
|
||||
// always succeed. When you downcast (that is, cast a pointer from
|
||||
// type Foo to type SubclassOfFoo), static_cast<> isn't safe, because
|
||||
// how do you know the pointer is really of type SubclassOfFoo? It
|
||||
// could be a bare Foo, or of type DifferentSubclassOfFoo. Thus,
|
||||
// when you downcast, you should use this macro. In debug mode, we
|
||||
// use dynamic_cast<> to double-check the downcast is legal (we die
|
||||
// if it's not). In normal mode, we do the efficient static_cast<>
|
||||
// instead. Thus, it's important to test in debug mode to make sure
|
||||
// the cast is legal!
|
||||
// This is the only place in the code we should use dynamic_cast<>.
|
||||
// In particular, you SHOULDN'T be using dynamic_cast<> in order to
|
||||
// do RTTI (eg code like this:
|
||||
// if (dynamic_cast<Subclass1>(foo)) HandleASubclass1Object(foo);
|
||||
// if (dynamic_cast<Subclass2>(foo)) HandleASubclass2Object(foo);
|
||||
// You should design the code some other way not to need this.
|
||||
|
||||
template<typename To, typename From> // use like this: down_cast<T*>(foo);
|
||||
inline To down_cast(From* f) { // so we only accept pointers
|
||||
// Ensures that To is a sub-type of From *. This test is here only
|
||||
// for compile-time type checking, and has no overhead in an
|
||||
// optimized build at run-time, as it will be optimized away
|
||||
// completely.
|
||||
if (false) {
|
||||
implicit_cast<From*, To>(0);
|
||||
}
|
||||
|
||||
#if !defined(NDEBUG) && !defined(GOOGLE_PROTOBUF_NO_RTTI)
|
||||
assert(f == NULL || dynamic_cast<To>(f) != NULL); // RTTI: debug mode only!
|
||||
#endif
|
||||
return static_cast<To>(f);
|
||||
}
|
||||
|
||||
template<typename To, typename From> // use like this: down_cast<T&>(foo);
|
||||
inline To down_cast(From& f) {
|
||||
typedef typename std::remove_reference<To>::type* ToAsPointer;
|
||||
// Ensures that To is a sub-type of From *. This test is here only
|
||||
// for compile-time type checking, and has no overhead in an
|
||||
// optimized build at run-time, as it will be optimized away
|
||||
// completely.
|
||||
if (false) {
|
||||
implicit_cast<From*, ToAsPointer>(0);
|
||||
}
|
||||
|
||||
#if !defined(NDEBUG) && !defined(GOOGLE_PROTOBUF_NO_RTTI)
|
||||
// RTTI: debug mode only!
|
||||
assert(dynamic_cast<ToAsPointer>(&f) != NULL);
|
||||
#endif
|
||||
return *static_cast<ToAsPointer>(&f);
|
||||
}
|
||||
|
||||
template<typename To, typename From>
|
||||
inline To bit_cast(const From& from) {
|
||||
GOOGLE_COMPILE_ASSERT(sizeof(From) == sizeof(To),
|
||||
bit_cast_with_different_sizes);
|
||||
To dest;
|
||||
memcpy(&dest, &from, sizeof(dest));
|
||||
return dest;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// We made these internal so that they would show up as such in the docs,
|
||||
// but we don't want to stick "internal::" in front of them everywhere.
|
||||
using internal::implicit_cast;
|
||||
using internal::down_cast;
|
||||
using internal::bit_cast;
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_CASTS_H__
|
242
third_party/protobuf-lite/google/protobuf/stubs/common.h
vendored
Normal file
242
third_party/protobuf-lite/google/protobuf/stubs/common.h
vendored
Normal file
@ -0,0 +1,242 @@
|
||||
// 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) and others
|
||||
//
|
||||
// Contains basic types and utilities used by the rest of the library.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_COMMON_H__
|
||||
#define GOOGLE_PROTOBUF_COMMON_H__
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <google/protobuf/stubs/port.h>
|
||||
#include <google/protobuf/stubs/macros.h>
|
||||
#include <google/protobuf/stubs/platform_macros.h>
|
||||
|
||||
// TODO(liujisi): Remove the following includes after the include clean-up.
|
||||
#include <google/protobuf/stubs/logging.h>
|
||||
#include <google/protobuf/stubs/mutex.h>
|
||||
#include <google/protobuf/stubs/callback.h>
|
||||
|
||||
#ifndef PROTOBUF_USE_EXCEPTIONS
|
||||
#if defined(_MSC_VER) && defined(_CPPUNWIND)
|
||||
#define PROTOBUF_USE_EXCEPTIONS 1
|
||||
#elif defined(__EXCEPTIONS)
|
||||
#define PROTOBUF_USE_EXCEPTIONS 1
|
||||
#else
|
||||
#define PROTOBUF_USE_EXCEPTIONS 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if PROTOBUF_USE_EXCEPTIONS
|
||||
#include <exception>
|
||||
#endif
|
||||
#if defined(__APPLE__)
|
||||
#include <TargetConditionals.h> // for TARGET_OS_IPHONE
|
||||
#endif
|
||||
|
||||
#if defined(__ANDROID__) || defined(GOOGLE_PROTOBUF_OS_ANDROID) || (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) || defined(GOOGLE_PROTOBUF_OS_IPHONE)
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) && defined(GetMessage)
|
||||
// Allow GetMessage to be used as a valid method name in protobuf classes.
|
||||
// windows.h defines GetMessage() as a macro. Let's re-define it as an inline
|
||||
// function. The inline function should be equivalent for C++ users.
|
||||
inline BOOL GetMessage_Win32(
|
||||
LPMSG lpMsg, HWND hWnd,
|
||||
UINT wMsgFilterMin, UINT wMsgFilterMax) {
|
||||
return GetMessage(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax);
|
||||
}
|
||||
#undef GetMessage
|
||||
inline BOOL GetMessage(
|
||||
LPMSG lpMsg, HWND hWnd,
|
||||
UINT wMsgFilterMin, UINT wMsgFilterMax) {
|
||||
return GetMessage_Win32(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax);
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace std {}
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
// Some of these constants are macros rather than const ints so that they can
|
||||
// be used in #if directives.
|
||||
|
||||
// The current version, represented as a single integer to make comparison
|
||||
// easier: major * 10^6 + minor * 10^3 + micro
|
||||
#define GOOGLE_PROTOBUF_VERSION 3006001
|
||||
|
||||
// A suffix string for alpha, beta or rc releases. Empty for stable releases.
|
||||
#define GOOGLE_PROTOBUF_VERSION_SUFFIX ""
|
||||
|
||||
// The minimum library version which works with the current version of the
|
||||
// headers.
|
||||
#define GOOGLE_PROTOBUF_MIN_LIBRARY_VERSION 3006001
|
||||
|
||||
// The minimum header version which works with the current version of
|
||||
// the library. This constant should only be used by protoc's C++ code
|
||||
// generator.
|
||||
static const int kMinHeaderVersionForLibrary = 3006001;
|
||||
|
||||
// The minimum protoc version which works with the current version of the
|
||||
// headers.
|
||||
#define GOOGLE_PROTOBUF_MIN_PROTOC_VERSION 3006001
|
||||
|
||||
// The minimum header version which works with the current version of
|
||||
// protoc. This constant should only be used in VerifyVersion().
|
||||
static const int kMinHeaderVersionForProtoc = 3006001;
|
||||
|
||||
// Verifies that the headers and libraries are compatible. Use the macro
|
||||
// below to call this.
|
||||
void LIBPROTOBUF_EXPORT VerifyVersion(int headerVersion, int minLibraryVersion,
|
||||
const char* filename);
|
||||
|
||||
// Converts a numeric version number to a string.
|
||||
std::string LIBPROTOBUF_EXPORT VersionString(int version);
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// Place this macro in your main() function (or somewhere before you attempt
|
||||
// to use the protobuf library) to verify that the version you link against
|
||||
// matches the headers you compiled against. If a version mismatch is
|
||||
// detected, the process will abort.
|
||||
#define GOOGLE_PROTOBUF_VERIFY_VERSION \
|
||||
::google::protobuf::internal::VerifyVersion( \
|
||||
GOOGLE_PROTOBUF_VERSION, GOOGLE_PROTOBUF_MIN_LIBRARY_VERSION, \
|
||||
__FILE__)
|
||||
|
||||
|
||||
// ===================================================================
|
||||
// from google3/util/utf8/public/unilib.h
|
||||
|
||||
class StringPiece;
|
||||
namespace internal {
|
||||
|
||||
// Checks if the buffer contains structurally-valid UTF-8. Implemented in
|
||||
// structurally_valid.cc.
|
||||
LIBPROTOBUF_EXPORT bool IsStructurallyValidUTF8(const char* buf, int len);
|
||||
|
||||
inline bool IsStructurallyValidUTF8(const std::string& str) {
|
||||
return IsStructurallyValidUTF8(str.data(), static_cast<int>(str.length()));
|
||||
}
|
||||
|
||||
// Returns initial number of bytes of structually valid UTF-8.
|
||||
LIBPROTOBUF_EXPORT int UTF8SpnStructurallyValid(const StringPiece& str);
|
||||
|
||||
// Coerce UTF-8 byte string in src_str to be
|
||||
// a structurally-valid equal-length string by selectively
|
||||
// overwriting illegal bytes with replace_char (typically ' ' or '?').
|
||||
// replace_char must be legal printable 7-bit Ascii 0x20..0x7e.
|
||||
// src_str is read-only.
|
||||
//
|
||||
// Returns pointer to output buffer, src_str.data() if no changes were made,
|
||||
// or idst if some bytes were changed. idst is allocated by the caller
|
||||
// and must be at least as big as src_str
|
||||
//
|
||||
// Optimized for: all structurally valid and no byte copying is done.
|
||||
//
|
||||
LIBPROTOBUF_EXPORT char* UTF8CoerceToStructurallyValid(
|
||||
const StringPiece& str, char* dst, char replace_char);
|
||||
|
||||
} // namespace internal
|
||||
|
||||
|
||||
// ===================================================================
|
||||
// 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.
|
||||
LIBPROTOBUF_EXPORT void ShutdownProtobufLibrary();
|
||||
|
||||
namespace internal {
|
||||
|
||||
// Register a function to be called when ShutdownProtocolBuffers() is called.
|
||||
LIBPROTOBUF_EXPORT void OnShutdown(void (*func)());
|
||||
// Run an arbitrary function on an arg
|
||||
LIBPROTOBUF_EXPORT void OnShutdownRun(void (*f)(const void*), const void* arg);
|
||||
|
||||
template <typename T>
|
||||
T* OnShutdownDelete(T* p) {
|
||||
OnShutdownRun([](const void* p) { delete static_cast<const T*>(p); }, p);
|
||||
return p;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
#if PROTOBUF_USE_EXCEPTIONS
|
||||
class FatalException : public std::exception {
|
||||
public:
|
||||
FatalException(const char* filename, int line, const std::string& message)
|
||||
: filename_(filename), line_(line), message_(message) {}
|
||||
virtual ~FatalException() throw();
|
||||
|
||||
virtual const char* what() const throw();
|
||||
|
||||
const char* filename() const { return filename_; }
|
||||
int line() const { return line_; }
|
||||
const std::string& message() const { return message_; }
|
||||
|
||||
private:
|
||||
const char* filename_;
|
||||
const int line_;
|
||||
const std::string message_;
|
||||
};
|
||||
#endif
|
||||
|
||||
// This is at the end of the file instead of the beginning to work around a bug
|
||||
// in some versions of MSVC.
|
||||
using std::string;
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_COMMON_H__
|
153
third_party/protobuf-lite/google/protobuf/stubs/fastmem.h
vendored
Normal file
153
third_party/protobuf-lite/google/protobuf/stubs/fastmem.h
vendored
Normal file
@ -0,0 +1,153 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2014 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.
|
||||
|
||||
// Fast memory copying and comparison routines.
|
||||
// strings::fastmemcmp_inlined() replaces memcmp()
|
||||
// strings::memcpy_inlined() replaces memcpy()
|
||||
// strings::memeq(a, b, n) replaces memcmp(a, b, n) == 0
|
||||
//
|
||||
// strings::*_inlined() routines are inline versions of the
|
||||
// routines exported by this module. Sometimes using the inlined
|
||||
// versions is faster. Measure before using the inlined versions.
|
||||
//
|
||||
// Performance measurement:
|
||||
// strings::fastmemcmp_inlined
|
||||
// Analysis: memcmp, fastmemcmp_inlined, fastmemcmp
|
||||
// 2012-01-30
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_STUBS_FASTMEM_H_
|
||||
#define GOOGLE_PROTOBUF_STUBS_FASTMEM_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
// Return true if the n bytes at a equal the n bytes at b.
|
||||
// The regions are allowed to overlap.
|
||||
//
|
||||
// The performance is similar to the performance memcmp(), but faster for
|
||||
// moderately-sized inputs, or inputs that share a common prefix and differ
|
||||
// somewhere in their last 8 bytes. Further optimizations can be added later
|
||||
// if it makes sense to do so.:w
|
||||
inline bool memeq(const char* a, const char* b, size_t n) {
|
||||
size_t n_rounded_down = n & ~static_cast<size_t>(7);
|
||||
if (GOOGLE_PREDICT_FALSE(n_rounded_down == 0)) { // n <= 7
|
||||
return memcmp(a, b, n) == 0;
|
||||
}
|
||||
// n >= 8
|
||||
uint64 u = GOOGLE_UNALIGNED_LOAD64(a) ^ GOOGLE_UNALIGNED_LOAD64(b);
|
||||
uint64 v = GOOGLE_UNALIGNED_LOAD64(a + n - 8) ^ GOOGLE_UNALIGNED_LOAD64(b + n - 8);
|
||||
if ((u | v) != 0) { // The first or last 8 bytes differ.
|
||||
return false;
|
||||
}
|
||||
a += 8;
|
||||
b += 8;
|
||||
n = n_rounded_down - 8;
|
||||
if (n > 128) {
|
||||
// As of 2012, memcmp on x86-64 uses a big unrolled loop with SSE2
|
||||
// instructions, and while we could try to do something faster, it
|
||||
// doesn't seem worth pursuing.
|
||||
return memcmp(a, b, n) == 0;
|
||||
}
|
||||
for (; n >= 16; n -= 16) {
|
||||
uint64 x = GOOGLE_UNALIGNED_LOAD64(a) ^ GOOGLE_UNALIGNED_LOAD64(b);
|
||||
uint64 y = GOOGLE_UNALIGNED_LOAD64(a + 8) ^ GOOGLE_UNALIGNED_LOAD64(b + 8);
|
||||
if ((x | y) != 0) {
|
||||
return false;
|
||||
}
|
||||
a += 16;
|
||||
b += 16;
|
||||
}
|
||||
// n must be 0 or 8 now because it was a multiple of 8 at the top of the loop.
|
||||
return n == 0 || GOOGLE_UNALIGNED_LOAD64(a) == GOOGLE_UNALIGNED_LOAD64(b);
|
||||
}
|
||||
|
||||
inline int fastmemcmp_inlined(const char *a, const char *b, size_t n) {
|
||||
if (n >= 64) {
|
||||
return memcmp(a, b, n);
|
||||
}
|
||||
const char* a_limit = a + n;
|
||||
while (a + sizeof(uint64) <= a_limit &&
|
||||
GOOGLE_UNALIGNED_LOAD64(a) == GOOGLE_UNALIGNED_LOAD64(b)) {
|
||||
a += sizeof(uint64);
|
||||
b += sizeof(uint64);
|
||||
}
|
||||
if (a + sizeof(uint32) <= a_limit &&
|
||||
GOOGLE_UNALIGNED_LOAD32(a) == GOOGLE_UNALIGNED_LOAD32(b)) {
|
||||
a += sizeof(uint32);
|
||||
b += sizeof(uint32);
|
||||
}
|
||||
while (a < a_limit) {
|
||||
int d =
|
||||
static_cast<int>(static_cast<uint32>(*a++) - static_cast<uint32>(*b++));
|
||||
if (d) return d;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// The standard memcpy operation is slow for variable small sizes.
|
||||
// This implementation inlines the optimal realization for sizes 1 to 16.
|
||||
// To avoid code bloat don't use it in case of not performance-critical spots,
|
||||
// nor when you don't expect very frequent values of size <= 16.
|
||||
inline void memcpy_inlined(char *dst, const char *src, size_t size) {
|
||||
// Compiler inlines code with minimal amount of data movement when third
|
||||
// parameter of memcpy is a constant.
|
||||
switch (size) {
|
||||
case 1: memcpy(dst, src, 1); break;
|
||||
case 2: memcpy(dst, src, 2); break;
|
||||
case 3: memcpy(dst, src, 3); break;
|
||||
case 4: memcpy(dst, src, 4); break;
|
||||
case 5: memcpy(dst, src, 5); break;
|
||||
case 6: memcpy(dst, src, 6); break;
|
||||
case 7: memcpy(dst, src, 7); break;
|
||||
case 8: memcpy(dst, src, 8); break;
|
||||
case 9: memcpy(dst, src, 9); break;
|
||||
case 10: memcpy(dst, src, 10); break;
|
||||
case 11: memcpy(dst, src, 11); break;
|
||||
case 12: memcpy(dst, src, 12); break;
|
||||
case 13: memcpy(dst, src, 13); break;
|
||||
case 14: memcpy(dst, src, 14); break;
|
||||
case 15: memcpy(dst, src, 15); break;
|
||||
case 16: memcpy(dst, src, 16); break;
|
||||
default: memcpy(dst, src, size); break;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_STUBS_FASTMEM_H_
|
441
third_party/protobuf-lite/google/protobuf/stubs/hash.h
vendored
Normal file
441
third_party/protobuf-lite/google/protobuf/stubs/hash.h
vendored
Normal file
@ -0,0 +1,441 @@
|
||||
// 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)
|
||||
//
|
||||
// Deals with the fact that hash_map is not defined everywhere.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_STUBS_HASH_H__
|
||||
#define GOOGLE_PROTOBUF_STUBS_HASH_H__
|
||||
|
||||
#include <string.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
#define GOOGLE_PROTOBUF_HAVE_HASH_MAP 1
|
||||
#define GOOGLE_PROTOBUF_HAVE_HASH_SET 1
|
||||
|
||||
// Use C++11 unordered_{map|set} if available.
|
||||
#if ((defined(_LIBCPP_STD_VER) && _LIBCPP_STD_VER >= 11) || \
|
||||
(((__cplusplus >= 201103L) || defined(__GXX_EXPERIMENTAL_CXX0X)) && \
|
||||
(__GLIBCXX__ > 20090421)))
|
||||
# define GOOGLE_PROTOBUF_HAS_CXX11_HASH
|
||||
|
||||
// For XCode >= 4.6: the compiler is clang with libc++.
|
||||
// For earlier XCode version: the compiler is gcc-4.2.1 with libstdc++.
|
||||
// libc++ provides <unordered_map> and friends even in non C++11 mode,
|
||||
// and it does not provide the tr1 library. Therefore the following macro
|
||||
// checks against this special case.
|
||||
// Note that we should not test the __APPLE_CC__ version number or the
|
||||
// __clang__ macro, since the new compiler can still use -stdlib=libstdc++, in
|
||||
// which case <unordered_map> is not compilable without -std=c++11
|
||||
#elif defined(__APPLE_CC__)
|
||||
# if __GNUC__ >= 4
|
||||
# define GOOGLE_PROTOBUF_HAS_TR1
|
||||
# else
|
||||
// Not tested for gcc < 4... These setting can compile under 4.2.1 though.
|
||||
# define GOOGLE_PROTOBUF_HASH_NAMESPACE __gnu_cxx
|
||||
# include <ext/hash_map>
|
||||
# define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map
|
||||
# include <ext/hash_set>
|
||||
# define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set
|
||||
# endif
|
||||
|
||||
// Version checks for gcc.
|
||||
#elif defined(__GNUC__)
|
||||
// For GCC 4.x+, use tr1::unordered_map/set; otherwise, follow the
|
||||
// instructions from:
|
||||
// https://gcc.gnu.org/onlinedocs/libstdc++/manual/backwards.html
|
||||
# if __GNUC__ >= 4
|
||||
# define GOOGLE_PROTOBUF_HAS_TR1
|
||||
# elif __GNUC__ >= 3
|
||||
# include <backward/hash_map>
|
||||
# define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map
|
||||
# include <backward/hash_set>
|
||||
# define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set
|
||||
# if __GNUC__ == 3 && __GNUC_MINOR__ == 0
|
||||
# define GOOGLE_PROTOBUF_HASH_NAMESPACE std // GCC 3.0
|
||||
# else
|
||||
# define GOOGLE_PROTOBUF_HASH_NAMESPACE __gnu_cxx // GCC 3.1 and later
|
||||
# endif
|
||||
# else
|
||||
# define GOOGLE_PROTOBUF_HASH_NAMESPACE
|
||||
# include <hash_map>
|
||||
# define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map
|
||||
# include <hash_set>
|
||||
# define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set
|
||||
# endif
|
||||
|
||||
// GCC <= 4.1 does not define std::tr1::hash for `long long int` or `long long unsigned int`
|
||||
# if __GNUC__ == 4 && defined(__GNUC_MINOR__) && __GNUC_MINOR__ <= 1
|
||||
# undef GOOGLE_PROTOBUF_HAS_TR1
|
||||
# undef GOOGLE_PROTOBUF_HAVE_HASH_MAP
|
||||
# undef GOOGLE_PROTOBUF_HAVE_HASH_SET
|
||||
# endif
|
||||
|
||||
// Version checks for MSC.
|
||||
// Apparently Microsoft decided to move hash_map *back* to the std namespace in
|
||||
// MSVC 2010:
|
||||
// http://blogs.msdn.com/vcblog/archive/2009/05/25/stl-breaking-changes-in-visual-studio-2010-beta-1.aspx
|
||||
// And.. they are moved back to stdext in MSVC 2013 (haven't checked 2012). That
|
||||
// said, use unordered_map for MSVC 2010 and beyond is our safest bet.
|
||||
#elif defined(_MSC_VER)
|
||||
# if _MSC_VER >= 1600 // Since Visual Studio 2010
|
||||
# define GOOGLE_PROTOBUF_HAS_CXX11_HASH
|
||||
# define GOOGLE_PROTOBUF_HASH_COMPARE std::hash_compare
|
||||
# elif _MSC_VER >= 1500 // Since Visual Studio 2008
|
||||
# define GOOGLE_PROTOBUF_HASH_NAMESPACE stdext
|
||||
# include <hash_map>
|
||||
# define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map
|
||||
# include <hash_set>
|
||||
# define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set
|
||||
# define GOOGLE_PROTOBUF_HASH_COMPARE stdext::hash_compare
|
||||
# define GOOGLE_PROTOBUF_CONTAINERS_NEED_HASH_COMPARE
|
||||
# elif _MSC_VER >= 1310
|
||||
# define GOOGLE_PROTOBUF_HASH_NAMESPACE stdext
|
||||
# include <hash_map>
|
||||
# define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map
|
||||
# include <hash_set>
|
||||
# define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set
|
||||
# define GOOGLE_PROTOBUF_HASH_COMPARE stdext::hash_compare
|
||||
# else
|
||||
# define GOOGLE_PROTOBUF_HASH_NAMESPACE std
|
||||
# include <hash_map>
|
||||
# define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map
|
||||
# include <hash_set>
|
||||
# define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set
|
||||
# define GOOGLE_PROTOBUF_HASH_COMPARE stdext::hash_compare
|
||||
# endif
|
||||
|
||||
// **ADD NEW COMPILERS SUPPORT HERE.**
|
||||
// For other compilers, undefine the macro and fallback to use std::map, in
|
||||
// google/protobuf/stubs/hash.h
|
||||
#else
|
||||
# undef GOOGLE_PROTOBUF_HAVE_HASH_MAP
|
||||
# undef GOOGLE_PROTOBUF_HAVE_HASH_SET
|
||||
#endif
|
||||
|
||||
#if defined(GOOGLE_PROTOBUF_HAS_CXX11_HASH)
|
||||
# define GOOGLE_PROTOBUF_HASH_NAMESPACE std
|
||||
# include <unordered_map>
|
||||
# define GOOGLE_PROTOBUF_HASH_MAP_CLASS unordered_map
|
||||
# include <unordered_set>
|
||||
# define GOOGLE_PROTOBUF_HASH_SET_CLASS unordered_set
|
||||
#elif defined(GOOGLE_PROTOBUF_HAS_TR1)
|
||||
# define GOOGLE_PROTOBUF_HASH_NAMESPACE std::tr1
|
||||
# include <tr1/unordered_map>
|
||||
# define GOOGLE_PROTOBUF_HASH_MAP_CLASS unordered_map
|
||||
# include <tr1/unordered_set>
|
||||
# define GOOGLE_PROTOBUF_HASH_SET_CLASS unordered_set
|
||||
#endif
|
||||
|
||||
# define GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_START \
|
||||
namespace google { \
|
||||
namespace protobuf {
|
||||
# define GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_END }}
|
||||
|
||||
#undef GOOGLE_PROTOBUF_HAS_CXX11_HASH
|
||||
#undef GOOGLE_PROTOBUF_HAS_TR1
|
||||
|
||||
#if defined(GOOGLE_PROTOBUF_HAVE_HASH_MAP) && \
|
||||
defined(GOOGLE_PROTOBUF_HAVE_HASH_SET)
|
||||
#else
|
||||
#define GOOGLE_PROTOBUF_MISSING_HASH
|
||||
#include <map>
|
||||
#include <set>
|
||||
#endif
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
#ifdef GOOGLE_PROTOBUF_MISSING_HASH
|
||||
#undef GOOGLE_PROTOBUF_MISSING_HASH
|
||||
|
||||
// This system doesn't have hash_map or hash_set. Emulate them using map and
|
||||
// set.
|
||||
|
||||
// Make hash<T> be the same as less<T>. Note that everywhere where custom
|
||||
// hash functions are defined in the protobuf code, they are also defined such
|
||||
// that they can be used as "less" functions, which is required by MSVC anyway.
|
||||
template <typename Key>
|
||||
struct hash {
|
||||
// Dummy, just to make derivative hash functions compile.
|
||||
int operator()(const Key& key) {
|
||||
GOOGLE_LOG(FATAL) << "Should never be called.";
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline bool operator()(const Key& a, const Key& b) const {
|
||||
return a < b;
|
||||
}
|
||||
};
|
||||
|
||||
// Make sure char* is compared by value.
|
||||
template <>
|
||||
struct hash<const char*> {
|
||||
// Dummy, just to make derivative hash functions compile.
|
||||
int operator()(const char* key) {
|
||||
GOOGLE_LOG(FATAL) << "Should never be called.";
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline bool operator()(const char* a, const char* b) const {
|
||||
return strcmp(a, b) < 0;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Key, typename Data,
|
||||
typename HashFcn = hash<Key>,
|
||||
typename EqualKey = std::equal_to<Key>,
|
||||
typename Alloc = std::allocator< std::pair<const Key, Data> > >
|
||||
class hash_map : public std::map<Key, Data, HashFcn, Alloc> {
|
||||
typedef std::map<Key, Data, HashFcn, Alloc> BaseClass;
|
||||
|
||||
public:
|
||||
hash_map(int a = 0, const HashFcn& b = HashFcn(),
|
||||
const EqualKey& c = EqualKey(),
|
||||
const Alloc& d = Alloc()) : BaseClass(b, d) {}
|
||||
|
||||
HashFcn hash_function() const { return HashFcn(); }
|
||||
};
|
||||
|
||||
template <typename Key,
|
||||
typename HashFcn = hash<Key>,
|
||||
typename EqualKey = std::equal_to<Key> >
|
||||
class hash_set : public std::set<Key, HashFcn> {
|
||||
public:
|
||||
hash_set(int = 0) {}
|
||||
|
||||
HashFcn hash_function() const { return HashFcn(); }
|
||||
};
|
||||
|
||||
#elif defined(_MSC_VER) && !defined(_STLPORT_VERSION) && \
|
||||
!(defined(_LIBCPP_STD_VER) && _LIBCPP_STD_VER >= 11)
|
||||
|
||||
template <typename Key>
|
||||
struct hash : public GOOGLE_PROTOBUF_HASH_COMPARE<Key> {
|
||||
};
|
||||
|
||||
// MSVC's hash_compare<const char*> hashes based on the string contents but
|
||||
// compares based on the string pointer. WTF?
|
||||
class CstringLess {
|
||||
public:
|
||||
inline bool operator()(const char* a, const char* b) const {
|
||||
return strcmp(a, b) < 0;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct hash<const char*>
|
||||
: public GOOGLE_PROTOBUF_HASH_COMPARE<const char*, CstringLess> {};
|
||||
|
||||
#ifdef GOOGLE_PROTOBUF_CONTAINERS_NEED_HASH_COMPARE
|
||||
|
||||
template <typename Key, typename HashFcn, typename EqualKey>
|
||||
struct InternalHashCompare : public GOOGLE_PROTOBUF_HASH_COMPARE<Key> {
|
||||
InternalHashCompare() {}
|
||||
InternalHashCompare(HashFcn hashfcn, EqualKey equalkey)
|
||||
: hashfcn_(hashfcn), equalkey_(equalkey) {}
|
||||
size_t operator()(const Key& key) const { return hashfcn_(key); }
|
||||
bool operator()(const Key& key1, const Key& key2) const {
|
||||
return !equalkey_(key1, key2);
|
||||
}
|
||||
HashFcn hashfcn_;
|
||||
EqualKey equalkey_;
|
||||
};
|
||||
|
||||
template <typename Key, typename Data,
|
||||
typename HashFcn = hash<Key>,
|
||||
typename EqualKey = std::equal_to<Key>,
|
||||
typename Alloc = std::allocator< std::pair<const Key, Data> > >
|
||||
class hash_map
|
||||
: public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_MAP_CLASS<
|
||||
Key, Data, InternalHashCompare<Key, HashFcn, EqualKey>, Alloc> {
|
||||
typedef GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_MAP_CLASS<
|
||||
Key, Data, InternalHashCompare<Key, HashFcn, EqualKey>, Alloc> BaseClass;
|
||||
|
||||
public:
|
||||
hash_map(int a = 0, const HashFcn& b = HashFcn(),
|
||||
const EqualKey& c = EqualKey(), const Alloc& d = Alloc())
|
||||
: BaseClass(InternalHashCompare<Key, HashFcn, EqualKey>(b, c), d) {}
|
||||
|
||||
HashFcn hash_function() const { return HashFcn(); }
|
||||
};
|
||||
|
||||
template <typename Key, typename HashFcn = hash<Key>,
|
||||
typename EqualKey = std::equal_to<Key> >
|
||||
class hash_set
|
||||
: public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_SET_CLASS<
|
||||
Key, InternalHashCompare<Key, HashFcn, EqualKey> > {
|
||||
public:
|
||||
hash_set(int = 0) {}
|
||||
|
||||
HashFcn hash_function() const { return HashFcn(); }
|
||||
};
|
||||
|
||||
#else // GOOGLE_PROTOBUF_CONTAINERS_NEED_HASH_COMPARE
|
||||
|
||||
template <typename Key, typename Data,
|
||||
typename HashFcn = hash<Key>,
|
||||
typename EqualKey = std::equal_to<Key>,
|
||||
typename Alloc = std::allocator< std::pair<const Key, Data> > >
|
||||
class hash_map
|
||||
: public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_MAP_CLASS<
|
||||
Key, Data, HashFcn, EqualKey, Alloc> {
|
||||
typedef GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_MAP_CLASS<
|
||||
Key, Data, HashFcn, EqualKey, Alloc> BaseClass;
|
||||
|
||||
public:
|
||||
hash_map(int a = 0, const HashFcn& b = HashFcn(),
|
||||
const EqualKey& c = EqualKey(),
|
||||
const Alloc& d = Alloc()) : BaseClass(a, b, c, d) {}
|
||||
|
||||
HashFcn hash_function() const { return HashFcn(); }
|
||||
};
|
||||
|
||||
template <typename Key, typename HashFcn = hash<Key>,
|
||||
typename EqualKey = std::equal_to<Key> >
|
||||
class hash_set
|
||||
: public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_SET_CLASS<
|
||||
Key, HashFcn, EqualKey> {
|
||||
public:
|
||||
hash_set(int = 0) {}
|
||||
|
||||
HashFcn hash_function() const { return HashFcn(); }
|
||||
};
|
||||
#endif // GOOGLE_PROTOBUF_CONTAINERS_NEED_HASH_COMPARE
|
||||
|
||||
#else // defined(_MSC_VER) && !defined(_STLPORT_VERSION)
|
||||
|
||||
template <typename Key>
|
||||
struct hash : public GOOGLE_PROTOBUF_HASH_NAMESPACE::hash<Key> {
|
||||
};
|
||||
|
||||
template <typename Key>
|
||||
struct hash<const Key*> {
|
||||
inline size_t operator()(const Key* key) const {
|
||||
return reinterpret_cast<size_t>(key);
|
||||
}
|
||||
};
|
||||
|
||||
// Unlike the old SGI version, the TR1 "hash" does not special-case char*. So,
|
||||
// we go ahead and provide our own implementation.
|
||||
template <>
|
||||
struct hash<const char*> {
|
||||
inline size_t operator()(const char* str) const {
|
||||
size_t result = 0;
|
||||
for (; *str != '\0'; str++) {
|
||||
result = 5 * result + static_cast<size_t>(*str);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct hash<bool> {
|
||||
size_t operator()(bool x) const {
|
||||
return static_cast<size_t>(x);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Key, typename Data,
|
||||
typename HashFcn = hash<Key>,
|
||||
typename EqualKey = std::equal_to<Key>,
|
||||
typename Alloc = std::allocator< std::pair<const Key, Data> > >
|
||||
class hash_map
|
||||
: public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_MAP_CLASS<
|
||||
Key, Data, HashFcn, EqualKey, Alloc> {
|
||||
typedef GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_MAP_CLASS<
|
||||
Key, Data, HashFcn, EqualKey, Alloc> BaseClass;
|
||||
|
||||
public:
|
||||
hash_map(int a = 0, const HashFcn& b = HashFcn(),
|
||||
const EqualKey& c = EqualKey(),
|
||||
const Alloc& d = Alloc()) : BaseClass(a, b, c, d) {}
|
||||
|
||||
HashFcn hash_function() const { return HashFcn(); }
|
||||
};
|
||||
|
||||
template <typename Key, typename HashFcn = hash<Key>,
|
||||
typename EqualKey = std::equal_to<Key> >
|
||||
class hash_set
|
||||
: public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_SET_CLASS<
|
||||
Key, HashFcn, EqualKey> {
|
||||
public:
|
||||
hash_set(int = 0) {}
|
||||
|
||||
HashFcn hash_function() const { return HashFcn(); }
|
||||
};
|
||||
|
||||
#endif // !GOOGLE_PROTOBUF_MISSING_HASH
|
||||
|
||||
template <>
|
||||
struct hash<string> {
|
||||
inline size_t operator()(const string& key) const {
|
||||
return hash<const char*>()(key.c_str());
|
||||
}
|
||||
|
||||
static const size_t bucket_size = 4;
|
||||
static const size_t min_buckets = 8;
|
||||
inline bool operator()(const string& a, const string& b) const {
|
||||
return a < b;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename First, typename Second>
|
||||
struct hash<std::pair<First, Second> > {
|
||||
inline size_t operator()(const std::pair<First, Second>& key) const {
|
||||
size_t first_hash = hash<First>()(key.first);
|
||||
size_t second_hash = hash<Second>()(key.second);
|
||||
|
||||
// FIXME(kenton): What is the best way to compute this hash? I have
|
||||
// no idea! This seems a bit better than an XOR.
|
||||
return first_hash * ((1 << 16) - 1) + second_hash;
|
||||
}
|
||||
|
||||
static const size_t bucket_size = 4;
|
||||
static const size_t min_buckets = 8;
|
||||
inline bool operator()(const std::pair<First, Second>& a,
|
||||
const std::pair<First, Second>& b) const {
|
||||
return a < b;
|
||||
}
|
||||
};
|
||||
|
||||
// Used by GCC/SGI STL only. (Why isn't this provided by the standard
|
||||
// library? :( )
|
||||
struct streq {
|
||||
inline bool operator()(const char* a, const char* b) const {
|
||||
return strcmp(a, b) == 0;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_STUBS_HASH_H__
|
383
third_party/protobuf-lite/google/protobuf/stubs/int128.h
vendored
Normal file
383
third_party/protobuf-lite/google/protobuf/stubs/int128.h
vendored
Normal file
@ -0,0 +1,383 @@
|
||||
// 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_STUBS_INT128_H_
|
||||
#define GOOGLE_PROTOBUF_STUBS_INT128_H_
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
#include <iosfwd>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
struct uint128_pod;
|
||||
|
||||
// TODO(xiaofeng): Define GOOGLE_PROTOBUF_HAS_CONSTEXPR when constexpr is
|
||||
// available.
|
||||
#ifdef GOOGLE_PROTOBUF_HAS_CONSTEXPR
|
||||
# define UINT128_CONSTEXPR constexpr
|
||||
#else
|
||||
# define UINT128_CONSTEXPR
|
||||
#endif
|
||||
|
||||
// An unsigned 128-bit integer type. Thread-compatible.
|
||||
class LIBPROTOBUF_EXPORT uint128 {
|
||||
public:
|
||||
UINT128_CONSTEXPR uint128(); // Sets to 0, but don't trust on this behavior.
|
||||
UINT128_CONSTEXPR uint128(uint64 top, uint64 bottom);
|
||||
#ifndef SWIG
|
||||
UINT128_CONSTEXPR uint128(int bottom);
|
||||
UINT128_CONSTEXPR uint128(uint32 bottom); // Top 96 bits = 0
|
||||
#endif
|
||||
UINT128_CONSTEXPR uint128(uint64 bottom); // hi_ = 0
|
||||
UINT128_CONSTEXPR uint128(const uint128_pod &val);
|
||||
|
||||
// Trivial copy constructor, assignment operator and destructor.
|
||||
|
||||
void Initialize(uint64 top, uint64 bottom);
|
||||
|
||||
// Arithmetic operators.
|
||||
uint128& operator+=(const uint128& b);
|
||||
uint128& operator-=(const uint128& b);
|
||||
uint128& operator*=(const uint128& b);
|
||||
// Long division/modulo for uint128.
|
||||
uint128& operator/=(const uint128& b);
|
||||
uint128& operator%=(const uint128& b);
|
||||
uint128 operator++(int);
|
||||
uint128 operator--(int);
|
||||
uint128& operator<<=(int);
|
||||
uint128& operator>>=(int);
|
||||
uint128& operator&=(const uint128& b);
|
||||
uint128& operator|=(const uint128& b);
|
||||
uint128& operator^=(const uint128& b);
|
||||
uint128& operator++();
|
||||
uint128& operator--();
|
||||
|
||||
friend uint64 Uint128Low64(const uint128& v);
|
||||
friend uint64 Uint128High64(const uint128& v);
|
||||
|
||||
// We add "std::" to avoid including all of port.h.
|
||||
LIBPROTOBUF_EXPORT friend std::ostream& operator<<(std::ostream& o,
|
||||
const uint128& b);
|
||||
|
||||
private:
|
||||
static void DivModImpl(uint128 dividend, uint128 divisor,
|
||||
uint128* quotient_ret, uint128* remainder_ret);
|
||||
|
||||
// Little-endian memory order optimizations can benefit from
|
||||
// having lo_ first, hi_ last.
|
||||
// See util/endian/endian.h and Load128/Store128 for storing a uint128.
|
||||
uint64 lo_;
|
||||
uint64 hi_;
|
||||
|
||||
// Not implemented, just declared for catching automatic type conversions.
|
||||
uint128(uint8);
|
||||
uint128(uint16);
|
||||
uint128(float v);
|
||||
uint128(double v);
|
||||
};
|
||||
|
||||
// This is a POD form of uint128 which can be used for static variables which
|
||||
// need to be operated on as uint128.
|
||||
struct uint128_pod {
|
||||
// Note: The ordering of fields is different than 'class uint128' but the
|
||||
// same as its 2-arg constructor. This enables more obvious initialization
|
||||
// of static instances, which is the primary reason for this struct in the
|
||||
// first place. This does not seem to defeat any optimizations wrt
|
||||
// operations involving this struct.
|
||||
uint64 hi;
|
||||
uint64 lo;
|
||||
};
|
||||
|
||||
LIBPROTOBUF_EXPORT extern const uint128_pod kuint128max;
|
||||
|
||||
// allow uint128 to be logged
|
||||
LIBPROTOBUF_EXPORT extern std::ostream& operator<<(std::ostream& o,
|
||||
const uint128& b);
|
||||
|
||||
// Methods to access low and high pieces of 128-bit value.
|
||||
// Defined externally from uint128 to facilitate conversion
|
||||
// to native 128-bit types when compilers support them.
|
||||
inline uint64 Uint128Low64(const uint128& v) { return v.lo_; }
|
||||
inline uint64 Uint128High64(const uint128& v) { return v.hi_; }
|
||||
|
||||
// TODO: perhaps it would be nice to have int128, a signed 128-bit type?
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Implementation details follow
|
||||
// --------------------------------------------------------------------------
|
||||
inline bool operator==(const uint128& lhs, const uint128& rhs) {
|
||||
return (Uint128Low64(lhs) == Uint128Low64(rhs) &&
|
||||
Uint128High64(lhs) == Uint128High64(rhs));
|
||||
}
|
||||
inline bool operator!=(const uint128& lhs, const uint128& rhs) {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
inline UINT128_CONSTEXPR uint128::uint128() : lo_(0), hi_(0) {}
|
||||
inline UINT128_CONSTEXPR uint128::uint128(uint64 top, uint64 bottom)
|
||||
: lo_(bottom), hi_(top) {}
|
||||
inline UINT128_CONSTEXPR uint128::uint128(const uint128_pod& v)
|
||||
: lo_(v.lo), hi_(v.hi) {}
|
||||
inline UINT128_CONSTEXPR uint128::uint128(uint64 bottom)
|
||||
: lo_(bottom), hi_(0) {}
|
||||
#ifndef SWIG
|
||||
inline UINT128_CONSTEXPR uint128::uint128(uint32 bottom)
|
||||
: lo_(bottom), hi_(0) {}
|
||||
inline UINT128_CONSTEXPR uint128::uint128(int bottom)
|
||||
: lo_(bottom), hi_(static_cast<int64>((bottom < 0) ? -1 : 0)) {}
|
||||
#endif
|
||||
|
||||
#undef UINT128_CONSTEXPR
|
||||
|
||||
inline void uint128::Initialize(uint64 top, uint64 bottom) {
|
||||
hi_ = top;
|
||||
lo_ = bottom;
|
||||
}
|
||||
|
||||
// Comparison operators.
|
||||
|
||||
#define CMP128(op) \
|
||||
inline bool operator op(const uint128& lhs, const uint128& rhs) { \
|
||||
return (Uint128High64(lhs) == Uint128High64(rhs)) ? \
|
||||
(Uint128Low64(lhs) op Uint128Low64(rhs)) : \
|
||||
(Uint128High64(lhs) op Uint128High64(rhs)); \
|
||||
}
|
||||
|
||||
CMP128(<)
|
||||
CMP128(>)
|
||||
CMP128(>=)
|
||||
CMP128(<=)
|
||||
|
||||
#undef CMP128
|
||||
|
||||
// Unary operators
|
||||
|
||||
inline uint128 operator-(const uint128& val) {
|
||||
const uint64 hi_flip = ~Uint128High64(val);
|
||||
const uint64 lo_flip = ~Uint128Low64(val);
|
||||
const uint64 lo_add = lo_flip + 1;
|
||||
if (lo_add < lo_flip) {
|
||||
return uint128(hi_flip + 1, lo_add);
|
||||
}
|
||||
return uint128(hi_flip, lo_add);
|
||||
}
|
||||
|
||||
inline bool operator!(const uint128& val) {
|
||||
return !Uint128High64(val) && !Uint128Low64(val);
|
||||
}
|
||||
|
||||
// Logical operators.
|
||||
|
||||
inline uint128 operator~(const uint128& val) {
|
||||
return uint128(~Uint128High64(val), ~Uint128Low64(val));
|
||||
}
|
||||
|
||||
#define LOGIC128(op) \
|
||||
inline uint128 operator op(const uint128& lhs, const uint128& rhs) { \
|
||||
return uint128(Uint128High64(lhs) op Uint128High64(rhs), \
|
||||
Uint128Low64(lhs) op Uint128Low64(rhs)); \
|
||||
}
|
||||
|
||||
LOGIC128(|)
|
||||
LOGIC128(&)
|
||||
LOGIC128(^)
|
||||
|
||||
#undef LOGIC128
|
||||
|
||||
#define LOGICASSIGN128(op) \
|
||||
inline uint128& uint128::operator op(const uint128& other) { \
|
||||
hi_ op other.hi_; \
|
||||
lo_ op other.lo_; \
|
||||
return *this; \
|
||||
}
|
||||
|
||||
LOGICASSIGN128(|=)
|
||||
LOGICASSIGN128(&=)
|
||||
LOGICASSIGN128(^=)
|
||||
|
||||
#undef LOGICASSIGN128
|
||||
|
||||
// Shift operators.
|
||||
|
||||
inline uint128 operator<<(const uint128& val, int amount) {
|
||||
// uint64 shifts of >= 64 are undefined, so we will need some special-casing.
|
||||
if (amount < 64) {
|
||||
if (amount == 0) {
|
||||
return val;
|
||||
}
|
||||
uint64 new_hi = (Uint128High64(val) << amount) |
|
||||
(Uint128Low64(val) >> (64 - amount));
|
||||
uint64 new_lo = Uint128Low64(val) << amount;
|
||||
return uint128(new_hi, new_lo);
|
||||
} else if (amount < 128) {
|
||||
return uint128(Uint128Low64(val) << (amount - 64), 0);
|
||||
} else {
|
||||
return uint128(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
inline uint128 operator>>(const uint128& val, int amount) {
|
||||
// uint64 shifts of >= 64 are undefined, so we will need some special-casing.
|
||||
if (amount < 64) {
|
||||
if (amount == 0) {
|
||||
return val;
|
||||
}
|
||||
uint64 new_hi = Uint128High64(val) >> amount;
|
||||
uint64 new_lo = (Uint128Low64(val) >> amount) |
|
||||
(Uint128High64(val) << (64 - amount));
|
||||
return uint128(new_hi, new_lo);
|
||||
} else if (amount < 128) {
|
||||
return uint128(0, Uint128High64(val) >> (amount - 64));
|
||||
} else {
|
||||
return uint128(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
inline uint128& uint128::operator<<=(int amount) {
|
||||
// uint64 shifts of >= 64 are undefined, so we will need some special-casing.
|
||||
if (amount < 64) {
|
||||
if (amount != 0) {
|
||||
hi_ = (hi_ << amount) | (lo_ >> (64 - amount));
|
||||
lo_ = lo_ << amount;
|
||||
}
|
||||
} else if (amount < 128) {
|
||||
hi_ = lo_ << (amount - 64);
|
||||
lo_ = 0;
|
||||
} else {
|
||||
hi_ = 0;
|
||||
lo_ = 0;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline uint128& uint128::operator>>=(int amount) {
|
||||
// uint64 shifts of >= 64 are undefined, so we will need some special-casing.
|
||||
if (amount < 64) {
|
||||
if (amount != 0) {
|
||||
lo_ = (lo_ >> amount) | (hi_ << (64 - amount));
|
||||
hi_ = hi_ >> amount;
|
||||
}
|
||||
} else if (amount < 128) {
|
||||
lo_ = hi_ >> (amount - 64);
|
||||
hi_ = 0;
|
||||
} else {
|
||||
lo_ = 0;
|
||||
hi_ = 0;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline uint128 operator+(const uint128& lhs, const uint128& rhs) {
|
||||
return uint128(lhs) += rhs;
|
||||
}
|
||||
|
||||
inline uint128 operator-(const uint128& lhs, const uint128& rhs) {
|
||||
return uint128(lhs) -= rhs;
|
||||
}
|
||||
|
||||
inline uint128 operator*(const uint128& lhs, const uint128& rhs) {
|
||||
return uint128(lhs) *= rhs;
|
||||
}
|
||||
|
||||
inline uint128 operator/(const uint128& lhs, const uint128& rhs) {
|
||||
return uint128(lhs) /= rhs;
|
||||
}
|
||||
|
||||
inline uint128 operator%(const uint128& lhs, const uint128& rhs) {
|
||||
return uint128(lhs) %= rhs;
|
||||
}
|
||||
|
||||
inline uint128& uint128::operator+=(const uint128& b) {
|
||||
hi_ += b.hi_;
|
||||
uint64 lolo = lo_ + b.lo_;
|
||||
if (lolo < lo_)
|
||||
++hi_;
|
||||
lo_ = lolo;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline uint128& uint128::operator-=(const uint128& b) {
|
||||
hi_ -= b.hi_;
|
||||
if (b.lo_ > lo_)
|
||||
--hi_;
|
||||
lo_ -= b.lo_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline uint128& uint128::operator*=(const uint128& b) {
|
||||
uint64 a96 = hi_ >> 32;
|
||||
uint64 a64 = hi_ & 0xffffffffu;
|
||||
uint64 a32 = lo_ >> 32;
|
||||
uint64 a00 = lo_ & 0xffffffffu;
|
||||
uint64 b96 = b.hi_ >> 32;
|
||||
uint64 b64 = b.hi_ & 0xffffffffu;
|
||||
uint64 b32 = b.lo_ >> 32;
|
||||
uint64 b00 = b.lo_ & 0xffffffffu;
|
||||
// multiply [a96 .. a00] x [b96 .. b00]
|
||||
// terms higher than c96 disappear off the high side
|
||||
// terms c96 and c64 are safe to ignore carry bit
|
||||
uint64 c96 = a96 * b00 + a64 * b32 + a32 * b64 + a00 * b96;
|
||||
uint64 c64 = a64 * b00 + a32 * b32 + a00 * b64;
|
||||
this->hi_ = (c96 << 32) + c64;
|
||||
this->lo_ = 0;
|
||||
// add terms after this one at a time to capture carry
|
||||
*this += uint128(a32 * b00) << 32;
|
||||
*this += uint128(a00 * b32) << 32;
|
||||
*this += a00 * b00;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline uint128 uint128::operator++(int) {
|
||||
uint128 tmp(*this);
|
||||
*this += 1;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
inline uint128 uint128::operator--(int) {
|
||||
uint128 tmp(*this);
|
||||
*this -= 1;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
inline uint128& uint128::operator++() {
|
||||
*this += 1;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline uint128& uint128::operator--() {
|
||||
*this -= 1;
|
||||
return *this;
|
||||
}
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_STUBS_INT128_H_
|
115
third_party/protobuf-lite/google/protobuf/stubs/io_win32.h
vendored
Normal file
115
third_party/protobuf-lite/google/protobuf/stubs/io_win32.h
vendored
Normal file
@ -0,0 +1,115 @@
|
||||
// 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)
|
||||
//
|
||||
// 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::internal::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_STUBS_IO_WIN32_H__
|
||||
#define GOOGLE_PROTOBUF_STUBS_IO_WIN32_H__
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
||||
#include <string>
|
||||
#include <google/protobuf/stubs/port.h>
|
||||
|
||||
// Compilers on Windows other than MSVC (e.g. Cygwin, MinGW32) define the
|
||||
// following functions already, except for mkdir.
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
namespace win32 {
|
||||
|
||||
LIBPROTOBUF_EXPORT FILE* fopen(const char* path, const char* mode);
|
||||
LIBPROTOBUF_EXPORT int access(const char* path, int mode);
|
||||
LIBPROTOBUF_EXPORT int chdir(const char* path);
|
||||
LIBPROTOBUF_EXPORT int close(int fd);
|
||||
LIBPROTOBUF_EXPORT int dup(int fd);
|
||||
LIBPROTOBUF_EXPORT int dup2(int fd1, int fd2);
|
||||
LIBPROTOBUF_EXPORT int mkdir(const char* path, int _mode);
|
||||
LIBPROTOBUF_EXPORT int open(const char* path, int flags, int mode = 0);
|
||||
LIBPROTOBUF_EXPORT int read(int fd, void* buffer, size_t size);
|
||||
LIBPROTOBUF_EXPORT int setmode(int fd, int mode);
|
||||
LIBPROTOBUF_EXPORT int stat(const char* path, struct _stat* buffer);
|
||||
LIBPROTOBUF_EXPORT int write(int fd, const void* buffer, size_t size);
|
||||
LIBPROTOBUF_EXPORT std::wstring testonly_utf8_to_winpath(const char* path);
|
||||
|
||||
namespace strings {
|
||||
|
||||
// Convert from UTF-16 to Active-Code-Page-encoded or to UTF-8-encoded text.
|
||||
LIBPROTOBUF_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.
|
||||
LIBPROTOBUF_EXPORT bool mbs_to_wcs(
|
||||
const char* s, std::wstring* out, bool inUtf8);
|
||||
|
||||
// Convert from UTF-8-encoded text to UTF-16.
|
||||
LIBPROTOBUF_EXPORT bool utf8_to_wcs(const char* input, std::wstring* out);
|
||||
|
||||
// Convert from UTF-16-encoded text to UTF-8.
|
||||
LIBPROTOBUF_EXPORT bool wcs_to_utf8(const wchar_t* input, std::string* out);
|
||||
|
||||
} // namespace strings
|
||||
|
||||
} // namespace win32
|
||||
} // namespace internal
|
||||
} // 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
|
||||
|
||||
#endif // defined(_WIN32)
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_STUBS_IO_WIN32_H__
|
237
third_party/protobuf-lite/google/protobuf/stubs/logging.h
vendored
Normal file
237
third_party/protobuf-lite/google/protobuf/stubs/logging.h
vendored
Normal file
@ -0,0 +1,237 @@
|
||||
// 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_STUBS_LOGGING_H_
|
||||
#define GOOGLE_PROTOBUF_STUBS_LOGGING_H_
|
||||
|
||||
#include <google/protobuf/stubs/macros.h>
|
||||
#include <google/protobuf/stubs/port.h>
|
||||
|
||||
// ===================================================================
|
||||
// emulates google3/base/logging.h
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
enum LogLevel {
|
||||
LOGLEVEL_INFO, // Informational. This is never actually used by
|
||||
// libprotobuf.
|
||||
LOGLEVEL_WARNING, // Warns about issues that, although not technically a
|
||||
// problem now, could cause problems in the future. For
|
||||
// example, a // warning will be printed when parsing a
|
||||
// message that is near the message size limit.
|
||||
LOGLEVEL_ERROR, // An error occurred which should never happen during
|
||||
// normal use.
|
||||
LOGLEVEL_FATAL, // An error occurred from which the library cannot
|
||||
// recover. This usually indicates a programming error
|
||||
// in the code which calls the library, especially when
|
||||
// compiled in debug mode.
|
||||
|
||||
#ifdef NDEBUG
|
||||
LOGLEVEL_DFATAL = LOGLEVEL_ERROR
|
||||
#else
|
||||
LOGLEVEL_DFATAL = LOGLEVEL_FATAL
|
||||
#endif
|
||||
};
|
||||
|
||||
class StringPiece;
|
||||
namespace util {
|
||||
class Status;
|
||||
}
|
||||
class uint128;
|
||||
namespace internal {
|
||||
|
||||
class LogFinisher;
|
||||
|
||||
class LIBPROTOBUF_EXPORT LogMessage {
|
||||
public:
|
||||
LogMessage(LogLevel level, const char* filename, int line);
|
||||
~LogMessage();
|
||||
|
||||
LogMessage& operator<<(const std::string& value);
|
||||
LogMessage& operator<<(const char* value);
|
||||
LogMessage& operator<<(char value);
|
||||
LogMessage& operator<<(int value);
|
||||
LogMessage& operator<<(uint value);
|
||||
LogMessage& operator<<(long value);
|
||||
LogMessage& operator<<(unsigned long value);
|
||||
LogMessage& operator<<(long long value);
|
||||
LogMessage& operator<<(unsigned long long value);
|
||||
LogMessage& operator<<(double value);
|
||||
LogMessage& operator<<(void* value);
|
||||
LogMessage& operator<<(const StringPiece& value);
|
||||
LogMessage& operator<<(const ::google::protobuf::util::Status& status);
|
||||
LogMessage& operator<<(const uint128& value);
|
||||
|
||||
private:
|
||||
friend class LogFinisher;
|
||||
void Finish();
|
||||
|
||||
LogLevel level_;
|
||||
const char* filename_;
|
||||
int line_;
|
||||
std::string message_;
|
||||
};
|
||||
|
||||
// Used to make the entire "LOG(BLAH) << etc." expression have a void return
|
||||
// type and print a newline after each message.
|
||||
class LIBPROTOBUF_EXPORT LogFinisher {
|
||||
public:
|
||||
void operator=(LogMessage& other);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
bool IsOk(T status) { return status.ok(); }
|
||||
template<>
|
||||
inline bool IsOk(bool status) { return status; }
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// Undef everything in case we're being mixed with some other Google library
|
||||
// which already defined them itself. Presumably all Google libraries will
|
||||
// support the same syntax for these so it should not be a big deal if they
|
||||
// end up using our definitions instead.
|
||||
#undef GOOGLE_LOG
|
||||
#undef GOOGLE_LOG_IF
|
||||
|
||||
#undef GOOGLE_CHECK
|
||||
#undef GOOGLE_CHECK_OK
|
||||
#undef GOOGLE_CHECK_EQ
|
||||
#undef GOOGLE_CHECK_NE
|
||||
#undef GOOGLE_CHECK_LT
|
||||
#undef GOOGLE_CHECK_LE
|
||||
#undef GOOGLE_CHECK_GT
|
||||
#undef GOOGLE_CHECK_GE
|
||||
#undef GOOGLE_CHECK_NOTNULL
|
||||
|
||||
#undef GOOGLE_DLOG
|
||||
#undef GOOGLE_DCHECK
|
||||
#undef GOOGLE_DCHECK_OK
|
||||
#undef GOOGLE_DCHECK_EQ
|
||||
#undef GOOGLE_DCHECK_NE
|
||||
#undef GOOGLE_DCHECK_LT
|
||||
#undef GOOGLE_DCHECK_LE
|
||||
#undef GOOGLE_DCHECK_GT
|
||||
#undef GOOGLE_DCHECK_GE
|
||||
|
||||
#define GOOGLE_LOG(LEVEL) \
|
||||
::google::protobuf::internal::LogFinisher() = \
|
||||
::google::protobuf::internal::LogMessage( \
|
||||
::google::protobuf::LOGLEVEL_##LEVEL, __FILE__, __LINE__)
|
||||
#define GOOGLE_LOG_IF(LEVEL, CONDITION) \
|
||||
!(CONDITION) ? (void)0 : GOOGLE_LOG(LEVEL)
|
||||
|
||||
#define GOOGLE_CHECK(EXPRESSION) \
|
||||
GOOGLE_LOG_IF(FATAL, !(EXPRESSION)) << "CHECK failed: " #EXPRESSION ": "
|
||||
#define GOOGLE_CHECK_OK(A) GOOGLE_CHECK(::google::protobuf::internal::IsOk(A))
|
||||
#define GOOGLE_CHECK_EQ(A, B) GOOGLE_CHECK((A) == (B))
|
||||
#define GOOGLE_CHECK_NE(A, B) GOOGLE_CHECK((A) != (B))
|
||||
#define GOOGLE_CHECK_LT(A, B) GOOGLE_CHECK((A) < (B))
|
||||
#define GOOGLE_CHECK_LE(A, B) GOOGLE_CHECK((A) <= (B))
|
||||
#define GOOGLE_CHECK_GT(A, B) GOOGLE_CHECK((A) > (B))
|
||||
#define GOOGLE_CHECK_GE(A, B) GOOGLE_CHECK((A) >= (B))
|
||||
|
||||
namespace internal {
|
||||
template<typename T>
|
||||
T* CheckNotNull(const char* /* file */, int /* line */,
|
||||
const char* name, T* val) {
|
||||
if (val == NULL) {
|
||||
GOOGLE_LOG(FATAL) << name;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
} // namespace internal
|
||||
#define GOOGLE_CHECK_NOTNULL(A) \
|
||||
::google::protobuf::internal::CheckNotNull(\
|
||||
__FILE__, __LINE__, "'" #A "' must not be NULL", (A))
|
||||
|
||||
#ifdef NDEBUG
|
||||
|
||||
#define GOOGLE_DLOG(LEVEL) GOOGLE_LOG_IF(LEVEL, false)
|
||||
|
||||
#define GOOGLE_DCHECK(EXPRESSION) while(false) GOOGLE_CHECK(EXPRESSION)
|
||||
#define GOOGLE_DCHECK_OK(E) GOOGLE_DCHECK(::google::protobuf::internal::IsOk(E))
|
||||
#define GOOGLE_DCHECK_EQ(A, B) GOOGLE_DCHECK((A) == (B))
|
||||
#define GOOGLE_DCHECK_NE(A, B) GOOGLE_DCHECK((A) != (B))
|
||||
#define GOOGLE_DCHECK_LT(A, B) GOOGLE_DCHECK((A) < (B))
|
||||
#define GOOGLE_DCHECK_LE(A, B) GOOGLE_DCHECK((A) <= (B))
|
||||
#define GOOGLE_DCHECK_GT(A, B) GOOGLE_DCHECK((A) > (B))
|
||||
#define GOOGLE_DCHECK_GE(A, B) GOOGLE_DCHECK((A) >= (B))
|
||||
|
||||
#else // NDEBUG
|
||||
|
||||
#define GOOGLE_DLOG GOOGLE_LOG
|
||||
|
||||
#define GOOGLE_DCHECK GOOGLE_CHECK
|
||||
#define GOOGLE_DCHECK_OK GOOGLE_CHECK_OK
|
||||
#define GOOGLE_DCHECK_EQ GOOGLE_CHECK_EQ
|
||||
#define GOOGLE_DCHECK_NE GOOGLE_CHECK_NE
|
||||
#define GOOGLE_DCHECK_LT GOOGLE_CHECK_LT
|
||||
#define GOOGLE_DCHECK_LE GOOGLE_CHECK_LE
|
||||
#define GOOGLE_DCHECK_GT GOOGLE_CHECK_GT
|
||||
#define GOOGLE_DCHECK_GE GOOGLE_CHECK_GE
|
||||
|
||||
#endif // !NDEBUG
|
||||
|
||||
typedef void LogHandler(LogLevel level, const char* filename, int line,
|
||||
const std::string& message);
|
||||
|
||||
// The protobuf library sometimes writes warning and error messages to
|
||||
// stderr. These messages are primarily useful for developers, but may
|
||||
// also help end users figure out a problem. If you would prefer that
|
||||
// these messages be sent somewhere other than stderr, call SetLogHandler()
|
||||
// to set your own handler. This returns the old handler. Set the handler
|
||||
// to NULL to ignore log messages (but see also LogSilencer, below).
|
||||
//
|
||||
// Obviously, SetLogHandler is not thread-safe. You should only call it
|
||||
// at initialization time, and probably not from library code. If you
|
||||
// simply want to suppress log messages temporarily (e.g. because you
|
||||
// have some code that tends to trigger them frequently and you know
|
||||
// the warnings are not important to you), use the LogSilencer class
|
||||
// below.
|
||||
LIBPROTOBUF_EXPORT LogHandler* SetLogHandler(LogHandler* new_func);
|
||||
|
||||
// Create a LogSilencer if you want to temporarily suppress all log
|
||||
// messages. As long as any LogSilencer objects exist, non-fatal
|
||||
// log messages will be discarded (the current LogHandler will *not*
|
||||
// be called). Constructing a LogSilencer is thread-safe. You may
|
||||
// accidentally suppress log messages occurring in another thread, but
|
||||
// since messages are generally for debugging purposes only, this isn't
|
||||
// a big deal. If you want to intercept log messages, use SetLogHandler().
|
||||
class LIBPROTOBUF_EXPORT LogSilencer {
|
||||
public:
|
||||
LogSilencer();
|
||||
~LogSilencer();
|
||||
};
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_STUBS_LOGGING_H_
|
168
third_party/protobuf-lite/google/protobuf/stubs/macros.h
vendored
Normal file
168
third_party/protobuf-lite/google/protobuf/stubs/macros.h
vendored
Normal file
@ -0,0 +1,168 @@
|
||||
// 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_MACROS_H__
|
||||
#define GOOGLE_PROTOBUF_MACROS_H__
|
||||
|
||||
#include <google/protobuf/stubs/port.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
#undef GOOGLE_DISALLOW_EVIL_CONSTRUCTORS
|
||||
#define GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TypeName) \
|
||||
TypeName(const TypeName&); \
|
||||
void operator=(const TypeName&)
|
||||
|
||||
#undef GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS
|
||||
#define GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
|
||||
TypeName(); \
|
||||
TypeName(const TypeName&); \
|
||||
void operator=(const TypeName&)
|
||||
|
||||
// ===================================================================
|
||||
// from google3/base/basictypes.h
|
||||
|
||||
// The GOOGLE_ARRAYSIZE(arr) macro returns the # of elements in an array arr.
|
||||
// The expression is a compile-time constant, and therefore can be
|
||||
// used in defining new arrays, for example.
|
||||
//
|
||||
// GOOGLE_ARRAYSIZE catches a few type errors. If you see a compiler error
|
||||
//
|
||||
// "warning: division by zero in ..."
|
||||
//
|
||||
// when using GOOGLE_ARRAYSIZE, you are (wrongfully) giving it a pointer.
|
||||
// You should only use GOOGLE_ARRAYSIZE on statically allocated arrays.
|
||||
//
|
||||
// The following comments are on the implementation details, and can
|
||||
// be ignored by the users.
|
||||
//
|
||||
// ARRAYSIZE(arr) works by inspecting sizeof(arr) (the # of bytes in
|
||||
// the array) and sizeof(*(arr)) (the # of bytes in one array
|
||||
// element). If the former is divisible by the latter, perhaps arr is
|
||||
// indeed an array, in which case the division result is the # of
|
||||
// elements in the array. Otherwise, arr cannot possibly be an array,
|
||||
// and we generate a compiler error to prevent the code from
|
||||
// compiling.
|
||||
//
|
||||
// Since the size of bool is implementation-defined, we need to cast
|
||||
// !(sizeof(a) & sizeof(*(a))) to size_t in order to ensure the final
|
||||
// result has type size_t.
|
||||
//
|
||||
// This macro is not perfect as it wrongfully accepts certain
|
||||
// pointers, namely where the pointer size is divisible by the pointee
|
||||
// size. Since all our code has to go through a 32-bit compiler,
|
||||
// where a pointer is 4 bytes, this means all pointers to a type whose
|
||||
// size is 3 or greater than 4 will be (righteously) rejected.
|
||||
//
|
||||
// Kudos to Jorg Brown for this simple and elegant implementation.
|
||||
|
||||
#undef GOOGLE_ARRAYSIZE
|
||||
#define GOOGLE_ARRAYSIZE(a) \
|
||||
((sizeof(a) / sizeof(*(a))) / \
|
||||
static_cast<size_t>(!(sizeof(a) % sizeof(*(a)))))
|
||||
|
||||
// The COMPILE_ASSERT macro can be used to verify that a compile time
|
||||
// expression is true. For example, you could use it to verify the
|
||||
// size of a static array:
|
||||
//
|
||||
// COMPILE_ASSERT(ARRAYSIZE(content_type_names) == CONTENT_NUM_TYPES,
|
||||
// content_type_names_incorrect_size);
|
||||
//
|
||||
// or to make sure a struct is smaller than a certain size:
|
||||
//
|
||||
// COMPILE_ASSERT(sizeof(foo) < 128, foo_too_large);
|
||||
//
|
||||
// The second argument to the macro is the name of the variable. If
|
||||
// the expression is false, most compilers will issue a warning/error
|
||||
// containing the name of the variable.
|
||||
|
||||
namespace internal {
|
||||
|
||||
template <bool>
|
||||
struct CompileAssert {
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
#undef GOOGLE_COMPILE_ASSERT
|
||||
#if __cplusplus >= 201103L
|
||||
#define GOOGLE_COMPILE_ASSERT(expr, msg) static_assert(expr, #msg)
|
||||
#else
|
||||
#define GOOGLE_COMPILE_ASSERT(expr, msg) \
|
||||
::google::protobuf::internal::CompileAssert<(bool(expr))> \
|
||||
msg[bool(expr) ? 1 : -1]; \
|
||||
(void)msg
|
||||
// Implementation details of COMPILE_ASSERT:
|
||||
//
|
||||
// - COMPILE_ASSERT works by defining an array type that has -1
|
||||
// elements (and thus is invalid) when the expression is false.
|
||||
//
|
||||
// - The simpler definition
|
||||
//
|
||||
// #define COMPILE_ASSERT(expr, msg) typedef char msg[(expr) ? 1 : -1]
|
||||
//
|
||||
// does not work, as gcc supports variable-length arrays whose sizes
|
||||
// are determined at run-time (this is gcc's extension and not part
|
||||
// of the C++ standard). As a result, gcc fails to reject the
|
||||
// following code with the simple definition:
|
||||
//
|
||||
// int foo;
|
||||
// COMPILE_ASSERT(foo, msg); // not supposed to compile as foo is
|
||||
// // not a compile-time constant.
|
||||
//
|
||||
// - By using the type CompileAssert<(bool(expr))>, we ensures that
|
||||
// expr is a compile-time constant. (Template arguments must be
|
||||
// determined at compile-time.)
|
||||
//
|
||||
// - The outter parentheses in CompileAssert<(bool(expr))> are necessary
|
||||
// to work around a bug in gcc 3.4.4 and 4.0.1. If we had written
|
||||
//
|
||||
// CompileAssert<bool(expr)>
|
||||
//
|
||||
// instead, these compilers will refuse to compile
|
||||
//
|
||||
// COMPILE_ASSERT(5 > 0, some_message);
|
||||
//
|
||||
// (They seem to think the ">" in "5 > 0" marks the end of the
|
||||
// template argument list.)
|
||||
//
|
||||
// - The array size is (bool(expr) ? 1 : -1), instead of simply
|
||||
//
|
||||
// ((expr) ? 1 : -1).
|
||||
//
|
||||
// This is to avoid running into a bug in MS VC 7.1, which
|
||||
// causes ((0.0) ? 1 : -1) to incorrectly evaluate to 1.
|
||||
#endif // __cplusplus >= 201103L
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_MACROS_H__
|
771
third_party/protobuf-lite/google/protobuf/stubs/map_util.h
vendored
Normal file
771
third_party/protobuf-lite/google/protobuf/stubs/map_util.h
vendored
Normal file
@ -0,0 +1,771 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2014 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.
|
||||
|
||||
// from google3/util/gtl/map_util.h
|
||||
// Author: Anton Carver
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_STUBS_MAP_UTIL_H__
|
||||
#define GOOGLE_PROTOBUF_STUBS_MAP_UTIL_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
// Local implementation of RemoveConst to avoid including base/type_traits.h.
|
||||
template <class T> struct RemoveConst { typedef T type; };
|
||||
template <class T> struct RemoveConst<const T> : RemoveConst<T> {};
|
||||
} // namespace internal
|
||||
|
||||
//
|
||||
// Find*()
|
||||
//
|
||||
|
||||
// Returns a const reference to the value associated with the given key if it
|
||||
// exists. Crashes otherwise.
|
||||
//
|
||||
// This is intended as a replacement for operator[] as an rvalue (for reading)
|
||||
// when the key is guaranteed to exist.
|
||||
//
|
||||
// operator[] for lookup is discouraged for several reasons:
|
||||
// * It has a side-effect of inserting missing keys
|
||||
// * It is not thread-safe (even when it is not inserting, it can still
|
||||
// choose to resize the underlying storage)
|
||||
// * It invalidates iterators (when it chooses to resize)
|
||||
// * It default constructs a value object even if it doesn't need to
|
||||
//
|
||||
// This version assumes the key is printable, and includes it in the fatal log
|
||||
// message.
|
||||
template <class Collection>
|
||||
const typename Collection::value_type::second_type&
|
||||
FindOrDie(const Collection& collection,
|
||||
const typename Collection::value_type::first_type& key) {
|
||||
typename Collection::const_iterator it = collection.find(key);
|
||||
GOOGLE_CHECK(it != collection.end()) << "Map key not found: " << key;
|
||||
return it->second;
|
||||
}
|
||||
|
||||
// Same as above, but returns a non-const reference.
|
||||
template <class Collection>
|
||||
typename Collection::value_type::second_type&
|
||||
FindOrDie(Collection& collection, // NOLINT
|
||||
const typename Collection::value_type::first_type& key) {
|
||||
typename Collection::iterator it = collection.find(key);
|
||||
GOOGLE_CHECK(it != collection.end()) << "Map key not found: " << key;
|
||||
return it->second;
|
||||
}
|
||||
|
||||
// Same as FindOrDie above, but doesn't log the key on failure.
|
||||
template <class Collection>
|
||||
const typename Collection::value_type::second_type&
|
||||
FindOrDieNoPrint(const Collection& collection,
|
||||
const typename Collection::value_type::first_type& key) {
|
||||
typename Collection::const_iterator it = collection.find(key);
|
||||
GOOGLE_CHECK(it != collection.end()) << "Map key not found";
|
||||
return it->second;
|
||||
}
|
||||
|
||||
// Same as above, but returns a non-const reference.
|
||||
template <class Collection>
|
||||
typename Collection::value_type::second_type&
|
||||
FindOrDieNoPrint(Collection& collection, // NOLINT
|
||||
const typename Collection::value_type::first_type& key) {
|
||||
typename Collection::iterator it = collection.find(key);
|
||||
GOOGLE_CHECK(it != collection.end()) << "Map key not found";
|
||||
return it->second;
|
||||
}
|
||||
|
||||
// Returns a const reference to the value associated with the given key if it
|
||||
// exists, otherwise returns a const reference to the provided default value.
|
||||
//
|
||||
// WARNING: If a temporary object is passed as the default "value,"
|
||||
// this function will return a reference to that temporary object,
|
||||
// which will be destroyed at the end of the statement. A common
|
||||
// example: if you have a map with string values, and you pass a char*
|
||||
// as the default "value," either use the returned value immediately
|
||||
// or store it in a string (not string&).
|
||||
// Details: http://go/findwithdefault
|
||||
template <class Collection>
|
||||
const typename Collection::value_type::second_type&
|
||||
FindWithDefault(const Collection& collection,
|
||||
const typename Collection::value_type::first_type& key,
|
||||
const typename Collection::value_type::second_type& value) {
|
||||
typename Collection::const_iterator it = collection.find(key);
|
||||
if (it == collection.end()) {
|
||||
return value;
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
|
||||
// Returns a pointer to the const value associated with the given key if it
|
||||
// exists, or NULL otherwise.
|
||||
template <class Collection>
|
||||
const typename Collection::value_type::second_type*
|
||||
FindOrNull(const Collection& collection,
|
||||
const typename Collection::value_type::first_type& key) {
|
||||
typename Collection::const_iterator it = collection.find(key);
|
||||
if (it == collection.end()) {
|
||||
return 0;
|
||||
}
|
||||
return &it->second;
|
||||
}
|
||||
|
||||
// Same as above but returns a pointer to the non-const value.
|
||||
template <class Collection>
|
||||
typename Collection::value_type::second_type*
|
||||
FindOrNull(Collection& collection, // NOLINT
|
||||
const typename Collection::value_type::first_type& key) {
|
||||
typename Collection::iterator it = collection.find(key);
|
||||
if (it == collection.end()) {
|
||||
return 0;
|
||||
}
|
||||
return &it->second;
|
||||
}
|
||||
|
||||
// Returns the pointer value associated with the given key. If none is found,
|
||||
// NULL is returned. The function is designed to be used with a map of keys to
|
||||
// pointers.
|
||||
//
|
||||
// This function does not distinguish between a missing key and a key mapped
|
||||
// to a NULL value.
|
||||
template <class Collection>
|
||||
typename Collection::value_type::second_type
|
||||
FindPtrOrNull(const Collection& collection,
|
||||
const typename Collection::value_type::first_type& key) {
|
||||
typename Collection::const_iterator it = collection.find(key);
|
||||
if (it == collection.end()) {
|
||||
return typename Collection::value_type::second_type();
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
|
||||
// Same as above, except takes non-const reference to collection.
|
||||
//
|
||||
// This function is needed for containers that propagate constness to the
|
||||
// pointee, such as boost::ptr_map.
|
||||
template <class Collection>
|
||||
typename Collection::value_type::second_type
|
||||
FindPtrOrNull(Collection& collection, // NOLINT
|
||||
const typename Collection::value_type::first_type& key) {
|
||||
typename Collection::iterator it = collection.find(key);
|
||||
if (it == collection.end()) {
|
||||
return typename Collection::value_type::second_type();
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
|
||||
// Finds the pointer value associated with the given key in a map whose values
|
||||
// are linked_ptrs. Returns NULL if key is not found.
|
||||
template <class Collection>
|
||||
typename Collection::value_type::second_type::element_type*
|
||||
FindLinkedPtrOrNull(const Collection& collection,
|
||||
const typename Collection::value_type::first_type& key) {
|
||||
typename Collection::const_iterator it = collection.find(key);
|
||||
if (it == collection.end()) {
|
||||
return 0;
|
||||
}
|
||||
// Since linked_ptr::get() is a const member returning a non const,
|
||||
// we do not need a version of this function taking a non const collection.
|
||||
return it->second.get();
|
||||
}
|
||||
|
||||
// Same as above, but dies if the key is not found.
|
||||
template <class Collection>
|
||||
typename Collection::value_type::second_type::element_type&
|
||||
FindLinkedPtrOrDie(const Collection& collection,
|
||||
const typename Collection::value_type::first_type& key) {
|
||||
typename Collection::const_iterator it = collection.find(key);
|
||||
GOOGLE_CHECK(it != collection.end()) << "key not found: " << key;
|
||||
// Since linked_ptr::operator*() is a const member returning a non const,
|
||||
// we do not need a version of this function taking a non const collection.
|
||||
return *it->second;
|
||||
}
|
||||
|
||||
// Finds the value associated with the given key and copies it to *value (if not
|
||||
// NULL). Returns false if the key was not found, true otherwise.
|
||||
template <class Collection, class Key, class Value>
|
||||
bool FindCopy(const Collection& collection,
|
||||
const Key& key,
|
||||
Value* const value) {
|
||||
typename Collection::const_iterator it = collection.find(key);
|
||||
if (it == collection.end()) {
|
||||
return false;
|
||||
}
|
||||
if (value) {
|
||||
*value = it->second;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// Contains*()
|
||||
//
|
||||
|
||||
// Returns true if and only if the given collection contains the given key.
|
||||
template <class Collection, class Key>
|
||||
bool ContainsKey(const Collection& collection, const Key& key) {
|
||||
return collection.find(key) != collection.end();
|
||||
}
|
||||
|
||||
// Returns true if and only if the given collection contains the given key-value
|
||||
// pair.
|
||||
template <class Collection, class Key, class Value>
|
||||
bool ContainsKeyValuePair(const Collection& collection,
|
||||
const Key& key,
|
||||
const Value& value) {
|
||||
typedef typename Collection::const_iterator const_iterator;
|
||||
std::pair<const_iterator, const_iterator> range = collection.equal_range(key);
|
||||
for (const_iterator it = range.first; it != range.second; ++it) {
|
||||
if (it->second == value) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// Insert*()
|
||||
//
|
||||
|
||||
// Inserts the given key-value pair into the collection. Returns true if and
|
||||
// only if the key from the given pair didn't previously exist. Otherwise, the
|
||||
// value in the map is replaced with the value from the given pair.
|
||||
template <class Collection>
|
||||
bool InsertOrUpdate(Collection* const collection,
|
||||
const typename Collection::value_type& vt) {
|
||||
std::pair<typename Collection::iterator, bool> ret = collection->insert(vt);
|
||||
if (!ret.second) {
|
||||
// update
|
||||
ret.first->second = vt.second;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Same as above, except that the key and value are passed separately.
|
||||
template <class Collection>
|
||||
bool InsertOrUpdate(Collection* const collection,
|
||||
const typename Collection::value_type::first_type& key,
|
||||
const typename Collection::value_type::second_type& value) {
|
||||
return InsertOrUpdate(
|
||||
collection, typename Collection::value_type(key, value));
|
||||
}
|
||||
|
||||
// Inserts/updates all the key-value pairs from the range defined by the
|
||||
// iterators "first" and "last" into the given collection.
|
||||
template <class Collection, class InputIterator>
|
||||
void InsertOrUpdateMany(Collection* const collection,
|
||||
InputIterator first, InputIterator last) {
|
||||
for (; first != last; ++first) {
|
||||
InsertOrUpdate(collection, *first);
|
||||
}
|
||||
}
|
||||
|
||||
// Change the value associated with a particular key in a map or hash_map
|
||||
// of the form map<Key, Value*> which owns the objects pointed to by the
|
||||
// value pointers. If there was an existing value for the key, it is deleted.
|
||||
// True indicates an insert took place, false indicates an update + delete.
|
||||
template <class Collection>
|
||||
bool InsertAndDeleteExisting(
|
||||
Collection* const collection,
|
||||
const typename Collection::value_type::first_type& key,
|
||||
const typename Collection::value_type::second_type& value) {
|
||||
std::pair<typename Collection::iterator, bool> ret =
|
||||
collection->insert(typename Collection::value_type(key, value));
|
||||
if (!ret.second) {
|
||||
delete ret.first->second;
|
||||
ret.first->second = value;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Inserts the given key and value into the given collection if and only if the
|
||||
// given key did NOT already exist in the collection. If the key previously
|
||||
// existed in the collection, the value is not changed. Returns true if the
|
||||
// key-value pair was inserted; returns false if the key was already present.
|
||||
template <class Collection>
|
||||
bool InsertIfNotPresent(Collection* const collection,
|
||||
const typename Collection::value_type& vt) {
|
||||
return collection->insert(vt).second;
|
||||
}
|
||||
|
||||
// Same as above except the key and value are passed separately.
|
||||
template <class Collection>
|
||||
bool InsertIfNotPresent(
|
||||
Collection* const collection,
|
||||
const typename Collection::value_type::first_type& key,
|
||||
const typename Collection::value_type::second_type& value) {
|
||||
return InsertIfNotPresent(
|
||||
collection, typename Collection::value_type(key, value));
|
||||
}
|
||||
|
||||
// Same as above except dies if the key already exists in the collection.
|
||||
template <class Collection>
|
||||
void InsertOrDie(Collection* const collection,
|
||||
const typename Collection::value_type& value) {
|
||||
GOOGLE_CHECK(InsertIfNotPresent(collection, value))
|
||||
<< "duplicate value: " << value;
|
||||
}
|
||||
|
||||
// Same as above except doesn't log the value on error.
|
||||
template <class Collection>
|
||||
void InsertOrDieNoPrint(Collection* const collection,
|
||||
const typename Collection::value_type& value) {
|
||||
GOOGLE_CHECK(InsertIfNotPresent(collection, value)) << "duplicate value.";
|
||||
}
|
||||
|
||||
// Inserts the key-value pair into the collection. Dies if key was already
|
||||
// present.
|
||||
template <class Collection>
|
||||
void InsertOrDie(Collection* const collection,
|
||||
const typename Collection::value_type::first_type& key,
|
||||
const typename Collection::value_type::second_type& data) {
|
||||
GOOGLE_CHECK(InsertIfNotPresent(collection, key, data))
|
||||
<< "duplicate key: " << key;
|
||||
}
|
||||
|
||||
// Same as above except doesn't log the key on error.
|
||||
template <class Collection>
|
||||
void InsertOrDieNoPrint(
|
||||
Collection* const collection,
|
||||
const typename Collection::value_type::first_type& key,
|
||||
const typename Collection::value_type::second_type& data) {
|
||||
GOOGLE_CHECK(InsertIfNotPresent(collection, key, data)) << "duplicate key.";
|
||||
}
|
||||
|
||||
// Inserts a new key and default-initialized value. Dies if the key was already
|
||||
// present. Returns a reference to the value. Example usage:
|
||||
//
|
||||
// map<int, SomeProto> m;
|
||||
// SomeProto& proto = InsertKeyOrDie(&m, 3);
|
||||
// proto.set_field("foo");
|
||||
template <class Collection>
|
||||
typename Collection::value_type::second_type& InsertKeyOrDie(
|
||||
Collection* const collection,
|
||||
const typename Collection::value_type::first_type& key) {
|
||||
typedef typename Collection::value_type value_type;
|
||||
std::pair<typename Collection::iterator, bool> res =
|
||||
collection->insert(value_type(key, typename value_type::second_type()));
|
||||
GOOGLE_CHECK(res.second) << "duplicate key: " << key;
|
||||
return res.first->second;
|
||||
}
|
||||
|
||||
//
|
||||
// Lookup*()
|
||||
//
|
||||
|
||||
// Looks up a given key and value pair in a collection and inserts the key-value
|
||||
// pair if it's not already present. Returns a reference to the value associated
|
||||
// with the key.
|
||||
template <class Collection>
|
||||
typename Collection::value_type::second_type&
|
||||
LookupOrInsert(Collection* const collection,
|
||||
const typename Collection::value_type& vt) {
|
||||
return collection->insert(vt).first->second;
|
||||
}
|
||||
|
||||
// Same as above except the key-value are passed separately.
|
||||
template <class Collection>
|
||||
typename Collection::value_type::second_type&
|
||||
LookupOrInsert(Collection* const collection,
|
||||
const typename Collection::value_type::first_type& key,
|
||||
const typename Collection::value_type::second_type& value) {
|
||||
return LookupOrInsert(
|
||||
collection, typename Collection::value_type(key, value));
|
||||
}
|
||||
|
||||
// Counts the number of equivalent elements in the given "sequence", and stores
|
||||
// the results in "count_map" with element as the key and count as the value.
|
||||
//
|
||||
// Example:
|
||||
// vector<string> v = {"a", "b", "c", "a", "b"};
|
||||
// map<string, int> m;
|
||||
// AddTokenCounts(v, 1, &m);
|
||||
// assert(m["a"] == 2);
|
||||
// assert(m["b"] == 2);
|
||||
// assert(m["c"] == 1);
|
||||
template <typename Sequence, typename Collection>
|
||||
void AddTokenCounts(
|
||||
const Sequence& sequence,
|
||||
const typename Collection::value_type::second_type& increment,
|
||||
Collection* const count_map) {
|
||||
for (typename Sequence::const_iterator it = sequence.begin();
|
||||
it != sequence.end(); ++it) {
|
||||
typename Collection::value_type::second_type& value =
|
||||
LookupOrInsert(count_map, *it,
|
||||
typename Collection::value_type::second_type());
|
||||
value += increment;
|
||||
}
|
||||
}
|
||||
|
||||
// Returns a reference to the value associated with key. If not found, a value
|
||||
// is default constructed on the heap and added to the map.
|
||||
//
|
||||
// This function is useful for containers of the form map<Key, Value*>, where
|
||||
// inserting a new key, value pair involves constructing a new heap-allocated
|
||||
// Value, and storing a pointer to that in the collection.
|
||||
template <class Collection>
|
||||
typename Collection::value_type::second_type&
|
||||
LookupOrInsertNew(Collection* const collection,
|
||||
const typename Collection::value_type::first_type& key) {
|
||||
typedef typename std::iterator_traits<
|
||||
typename Collection::value_type::second_type>::value_type Element;
|
||||
std::pair<typename Collection::iterator, bool> ret =
|
||||
collection->insert(typename Collection::value_type(
|
||||
key,
|
||||
static_cast<typename Collection::value_type::second_type>(NULL)));
|
||||
if (ret.second) {
|
||||
ret.first->second = new Element();
|
||||
}
|
||||
return ret.first->second;
|
||||
}
|
||||
|
||||
// Same as above but constructs the value using the single-argument constructor
|
||||
// and the given "arg".
|
||||
template <class Collection, class Arg>
|
||||
typename Collection::value_type::second_type&
|
||||
LookupOrInsertNew(Collection* const collection,
|
||||
const typename Collection::value_type::first_type& key,
|
||||
const Arg& arg) {
|
||||
typedef typename std::iterator_traits<
|
||||
typename Collection::value_type::second_type>::value_type Element;
|
||||
std::pair<typename Collection::iterator, bool> ret =
|
||||
collection->insert(typename Collection::value_type(
|
||||
key,
|
||||
static_cast<typename Collection::value_type::second_type>(NULL)));
|
||||
if (ret.second) {
|
||||
ret.first->second = new Element(arg);
|
||||
}
|
||||
return ret.first->second;
|
||||
}
|
||||
|
||||
// Lookup of linked/shared pointers is used in two scenarios:
|
||||
//
|
||||
// Use LookupOrInsertNewLinkedPtr if the container owns the elements.
|
||||
// In this case it is fine working with the raw pointer as long as it is
|
||||
// guaranteed that no other thread can delete/update an accessed element.
|
||||
// A mutex will need to lock the container operation as well as the use
|
||||
// of the returned elements. Finding an element may be performed using
|
||||
// FindLinkedPtr*().
|
||||
//
|
||||
// Use LookupOrInsertNewSharedPtr if the container does not own the elements
|
||||
// for their whole lifetime. This is typically the case when a reader allows
|
||||
// parallel updates to the container. In this case a Mutex only needs to lock
|
||||
// container operations, but all element operations must be performed on the
|
||||
// shared pointer. Finding an element must be performed using FindPtr*() and
|
||||
// cannot be done with FindLinkedPtr*() even though it compiles.
|
||||
|
||||
// Lookup a key in a map or hash_map whose values are linked_ptrs. If it is
|
||||
// missing, set collection[key].reset(new Value::element_type) and return that.
|
||||
// Value::element_type must be default constructable.
|
||||
template <class Collection>
|
||||
typename Collection::value_type::second_type::element_type*
|
||||
LookupOrInsertNewLinkedPtr(
|
||||
Collection* const collection,
|
||||
const typename Collection::value_type::first_type& key) {
|
||||
typedef typename Collection::value_type::second_type Value;
|
||||
std::pair<typename Collection::iterator, bool> ret =
|
||||
collection->insert(typename Collection::value_type(key, Value()));
|
||||
if (ret.second) {
|
||||
ret.first->second.reset(new typename Value::element_type);
|
||||
}
|
||||
return ret.first->second.get();
|
||||
}
|
||||
|
||||
// A variant of LookupOrInsertNewLinkedPtr where the value is constructed using
|
||||
// a single-parameter constructor. Note: the constructor argument is computed
|
||||
// even if it will not be used, so only values cheap to compute should be passed
|
||||
// here. On the other hand it does not matter how expensive the construction of
|
||||
// the actual stored value is, as that only occurs if necessary.
|
||||
template <class Collection, class Arg>
|
||||
typename Collection::value_type::second_type::element_type*
|
||||
LookupOrInsertNewLinkedPtr(
|
||||
Collection* const collection,
|
||||
const typename Collection::value_type::first_type& key,
|
||||
const Arg& arg) {
|
||||
typedef typename Collection::value_type::second_type Value;
|
||||
std::pair<typename Collection::iterator, bool> ret =
|
||||
collection->insert(typename Collection::value_type(key, Value()));
|
||||
if (ret.second) {
|
||||
ret.first->second.reset(new typename Value::element_type(arg));
|
||||
}
|
||||
return ret.first->second.get();
|
||||
}
|
||||
|
||||
// Lookup a key in a map or hash_map whose values are shared_ptrs. If it is
|
||||
// missing, set collection[key].reset(new Value::element_type). Unlike
|
||||
// LookupOrInsertNewLinkedPtr, this function returns the shared_ptr instead of
|
||||
// the raw pointer. Value::element_type must be default constructable.
|
||||
template <class Collection>
|
||||
typename Collection::value_type::second_type&
|
||||
LookupOrInsertNewSharedPtr(
|
||||
Collection* const collection,
|
||||
const typename Collection::value_type::first_type& key) {
|
||||
typedef typename Collection::value_type::second_type SharedPtr;
|
||||
typedef typename Collection::value_type::second_type::element_type Element;
|
||||
std::pair<typename Collection::iterator, bool> ret =
|
||||
collection->insert(typename Collection::value_type(key, SharedPtr()));
|
||||
if (ret.second) {
|
||||
ret.first->second.reset(new Element());
|
||||
}
|
||||
return ret.first->second;
|
||||
}
|
||||
|
||||
// A variant of LookupOrInsertNewSharedPtr where the value is constructed using
|
||||
// a single-parameter constructor. Note: the constructor argument is computed
|
||||
// even if it will not be used, so only values cheap to compute should be passed
|
||||
// here. On the other hand it does not matter how expensive the construction of
|
||||
// the actual stored value is, as that only occurs if necessary.
|
||||
template <class Collection, class Arg>
|
||||
typename Collection::value_type::second_type&
|
||||
LookupOrInsertNewSharedPtr(
|
||||
Collection* const collection,
|
||||
const typename Collection::value_type::first_type& key,
|
||||
const Arg& arg) {
|
||||
typedef typename Collection::value_type::second_type SharedPtr;
|
||||
typedef typename Collection::value_type::second_type::element_type Element;
|
||||
std::pair<typename Collection::iterator, bool> ret =
|
||||
collection->insert(typename Collection::value_type(key, SharedPtr()));
|
||||
if (ret.second) {
|
||||
ret.first->second.reset(new Element(arg));
|
||||
}
|
||||
return ret.first->second;
|
||||
}
|
||||
|
||||
//
|
||||
// Misc Utility Functions
|
||||
//
|
||||
|
||||
// Updates the value associated with the given key. If the key was not already
|
||||
// present, then the key-value pair are inserted and "previous" is unchanged. If
|
||||
// the key was already present, the value is updated and "*previous" will
|
||||
// contain a copy of the old value.
|
||||
//
|
||||
// InsertOrReturnExisting has complementary behavior that returns the
|
||||
// address of an already existing value, rather than updating it.
|
||||
template <class Collection>
|
||||
bool UpdateReturnCopy(Collection* const collection,
|
||||
const typename Collection::value_type::first_type& key,
|
||||
const typename Collection::value_type::second_type& value,
|
||||
typename Collection::value_type::second_type* previous) {
|
||||
std::pair<typename Collection::iterator, bool> ret =
|
||||
collection->insert(typename Collection::value_type(key, value));
|
||||
if (!ret.second) {
|
||||
// update
|
||||
if (previous) {
|
||||
*previous = ret.first->second;
|
||||
}
|
||||
ret.first->second = value;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Same as above except that the key and value are passed as a pair.
|
||||
template <class Collection>
|
||||
bool UpdateReturnCopy(Collection* const collection,
|
||||
const typename Collection::value_type& vt,
|
||||
typename Collection::value_type::second_type* previous) {
|
||||
std::pair<typename Collection::iterator, bool> ret = collection->insert(vt);
|
||||
if (!ret.second) {
|
||||
// update
|
||||
if (previous) {
|
||||
*previous = ret.first->second;
|
||||
}
|
||||
ret.first->second = vt.second;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Tries to insert the given key-value pair into the collection. Returns NULL if
|
||||
// the insert succeeds. Otherwise, returns a pointer to the existing value.
|
||||
//
|
||||
// This complements UpdateReturnCopy in that it allows to update only after
|
||||
// verifying the old value and still insert quickly without having to look up
|
||||
// twice. Unlike UpdateReturnCopy this also does not come with the issue of an
|
||||
// undefined previous* in case new data was inserted.
|
||||
template <class Collection>
|
||||
typename Collection::value_type::second_type* const
|
||||
InsertOrReturnExisting(Collection* const collection,
|
||||
const typename Collection::value_type& vt) {
|
||||
std::pair<typename Collection::iterator, bool> ret = collection->insert(vt);
|
||||
if (ret.second) {
|
||||
return NULL; // Inserted, no existing previous value.
|
||||
} else {
|
||||
return &ret.first->second; // Return address of already existing value.
|
||||
}
|
||||
}
|
||||
|
||||
// Same as above, except for explicit key and data.
|
||||
template <class Collection>
|
||||
typename Collection::value_type::second_type* const
|
||||
InsertOrReturnExisting(
|
||||
Collection* const collection,
|
||||
const typename Collection::value_type::first_type& key,
|
||||
const typename Collection::value_type::second_type& data) {
|
||||
return InsertOrReturnExisting(collection,
|
||||
typename Collection::value_type(key, data));
|
||||
}
|
||||
|
||||
// Erases the collection item identified by the given key, and returns the value
|
||||
// associated with that key. It is assumed that the value (i.e., the
|
||||
// mapped_type) is a pointer. Returns NULL if the key was not found in the
|
||||
// collection.
|
||||
//
|
||||
// Examples:
|
||||
// map<string, MyType*> my_map;
|
||||
//
|
||||
// One line cleanup:
|
||||
// delete EraseKeyReturnValuePtr(&my_map, "abc");
|
||||
//
|
||||
// Use returned value:
|
||||
// std::unique_ptr<MyType> value_ptr(
|
||||
// EraseKeyReturnValuePtr(&my_map, "abc"));
|
||||
// if (value_ptr.get())
|
||||
// value_ptr->DoSomething();
|
||||
//
|
||||
template <class Collection>
|
||||
typename Collection::value_type::second_type EraseKeyReturnValuePtr(
|
||||
Collection* const collection,
|
||||
const typename Collection::value_type::first_type& key) {
|
||||
typename Collection::iterator it = collection->find(key);
|
||||
if (it == collection->end()) {
|
||||
return NULL;
|
||||
}
|
||||
typename Collection::value_type::second_type v = it->second;
|
||||
collection->erase(it);
|
||||
return v;
|
||||
}
|
||||
|
||||
// Inserts all the keys from map_container into key_container, which must
|
||||
// support insert(MapContainer::key_type).
|
||||
//
|
||||
// Note: any initial contents of the key_container are not cleared.
|
||||
template <class MapContainer, class KeyContainer>
|
||||
void InsertKeysFromMap(const MapContainer& map_container,
|
||||
KeyContainer* key_container) {
|
||||
GOOGLE_CHECK(key_container != NULL);
|
||||
for (typename MapContainer::const_iterator it = map_container.begin();
|
||||
it != map_container.end(); ++it) {
|
||||
key_container->insert(it->first);
|
||||
}
|
||||
}
|
||||
|
||||
// Appends all the keys from map_container into key_container, which must
|
||||
// support push_back(MapContainer::key_type).
|
||||
//
|
||||
// Note: any initial contents of the key_container are not cleared.
|
||||
template <class MapContainer, class KeyContainer>
|
||||
void AppendKeysFromMap(const MapContainer& map_container,
|
||||
KeyContainer* key_container) {
|
||||
GOOGLE_CHECK(key_container != NULL);
|
||||
for (typename MapContainer::const_iterator it = map_container.begin();
|
||||
it != map_container.end(); ++it) {
|
||||
key_container->push_back(it->first);
|
||||
}
|
||||
}
|
||||
|
||||
// A more specialized overload of AppendKeysFromMap to optimize reallocations
|
||||
// for the common case in which we're appending keys to a vector and hence can
|
||||
// (and sometimes should) call reserve() first.
|
||||
//
|
||||
// (It would be possible to play SFINAE games to call reserve() for any
|
||||
// container that supports it, but this seems to get us 99% of what we need
|
||||
// without the complexity of a SFINAE-based solution.)
|
||||
template <class MapContainer, class KeyType>
|
||||
void AppendKeysFromMap(const MapContainer& map_container,
|
||||
std::vector<KeyType>* key_container) {
|
||||
GOOGLE_CHECK(key_container != NULL);
|
||||
// We now have the opportunity to call reserve(). Calling reserve() every
|
||||
// time is a bad idea for some use cases: libstdc++'s implementation of
|
||||
// vector<>::reserve() resizes the vector's backing store to exactly the
|
||||
// given size (unless it's already at least that big). Because of this,
|
||||
// the use case that involves appending a lot of small maps (total size
|
||||
// N) one by one to a vector would be O(N^2). But never calling reserve()
|
||||
// loses the opportunity to improve the use case of adding from a large
|
||||
// map to an empty vector (this improves performance by up to 33%). A
|
||||
// number of heuristics are possible; see the discussion in
|
||||
// cl/34081696. Here we use the simplest one.
|
||||
if (key_container->empty()) {
|
||||
key_container->reserve(map_container.size());
|
||||
}
|
||||
for (typename MapContainer::const_iterator it = map_container.begin();
|
||||
it != map_container.end(); ++it) {
|
||||
key_container->push_back(it->first);
|
||||
}
|
||||
}
|
||||
|
||||
// Inserts all the values from map_container into value_container, which must
|
||||
// support push_back(MapContainer::mapped_type).
|
||||
//
|
||||
// Note: any initial contents of the value_container are not cleared.
|
||||
template <class MapContainer, class ValueContainer>
|
||||
void AppendValuesFromMap(const MapContainer& map_container,
|
||||
ValueContainer* value_container) {
|
||||
GOOGLE_CHECK(value_container != NULL);
|
||||
for (typename MapContainer::const_iterator it = map_container.begin();
|
||||
it != map_container.end(); ++it) {
|
||||
value_container->push_back(it->second);
|
||||
}
|
||||
}
|
||||
|
||||
// A more specialized overload of AppendValuesFromMap to optimize reallocations
|
||||
// for the common case in which we're appending values to a vector and hence
|
||||
// can (and sometimes should) call reserve() first.
|
||||
//
|
||||
// (It would be possible to play SFINAE games to call reserve() for any
|
||||
// container that supports it, but this seems to get us 99% of what we need
|
||||
// without the complexity of a SFINAE-based solution.)
|
||||
template <class MapContainer, class ValueType>
|
||||
void AppendValuesFromMap(const MapContainer& map_container,
|
||||
std::vector<ValueType>* value_container) {
|
||||
GOOGLE_CHECK(value_container != NULL);
|
||||
// See AppendKeysFromMap for why this is done.
|
||||
if (value_container->empty()) {
|
||||
value_container->reserve(map_container.size());
|
||||
}
|
||||
for (typename MapContainer::const_iterator it = map_container.begin();
|
||||
it != map_container.end(); ++it) {
|
||||
value_container->push_back(it->second);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_STUBS_MAP_UTIL_H__
|
303
third_party/protobuf-lite/google/protobuf/stubs/mathlimits.h
vendored
Normal file
303
third_party/protobuf-lite/google/protobuf/stubs/mathlimits.h
vendored
Normal file
@ -0,0 +1,303 @@
|
||||
// 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.
|
||||
|
||||
// All Rights Reserved.
|
||||
//
|
||||
// Author: Maxim Lifantsev
|
||||
//
|
||||
// Useful integer and floating point limits and type traits.
|
||||
//
|
||||
// This partially replaces/duplictes numeric_limits<> from <limits>.
|
||||
// We get a Google-style class that we have a greater control over
|
||||
// and thus can add new features to it or fix whatever happens to be broken in
|
||||
// numeric_limits for the compilers we use.
|
||||
//
|
||||
|
||||
#ifndef UTIL_MATH_MATHLIMITS_H__
|
||||
#define UTIL_MATH_MATHLIMITS_H__
|
||||
|
||||
// Note that for Windows we do something different because it does not support
|
||||
// the plain isinf and isnan.
|
||||
#if __cplusplus >= 201103L
|
||||
// GCC 4.9 has a bug that makes isinf and isnan ambigious when both <math.h>
|
||||
// and <cmath> get pulled into the same translation unit. We use the ones in
|
||||
// std:: namespace explicitly for C++11
|
||||
#include <cmath>
|
||||
#define GOOGLE_PROTOBUF_USE_STD_CMATH
|
||||
#elif _GLIBCXX_USE_C99_MATH && !_GLIBCXX_USE_C99_FP_MACROS_DYNAMIC
|
||||
// libstdc++ <cmath> header undefines the global macros and put functions in
|
||||
// std:: namespace even before C++11. Use the ones in std:: instead too.
|
||||
#include <cmath>
|
||||
#define GOOGLE_PROTOBUF_USE_STD_CMATH
|
||||
#else
|
||||
#include <math.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <cfloat>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
// ========================================================================= //
|
||||
|
||||
// Useful integer and floating point limits and type traits.
|
||||
// This is just for the documentation;
|
||||
// real members are defined in our specializations below.
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
template<typename T> struct MathLimits {
|
||||
// Type name.
|
||||
typedef T Type;
|
||||
// Unsigned version of the Type with the same byte size.
|
||||
// Same as Type for floating point and unsigned types.
|
||||
typedef T UnsignedType;
|
||||
// If the type supports negative values.
|
||||
static const bool kIsSigned;
|
||||
// If the type supports only integer values.
|
||||
static const bool kIsInteger;
|
||||
// Magnitude-wise smallest representable positive value.
|
||||
static const Type kPosMin;
|
||||
// Magnitude-wise largest representable positive value.
|
||||
static const Type kPosMax;
|
||||
// Smallest representable value.
|
||||
static const Type kMin;
|
||||
// Largest representable value.
|
||||
static const Type kMax;
|
||||
// Magnitude-wise smallest representable negative value.
|
||||
// Present only if kIsSigned.
|
||||
static const Type kNegMin;
|
||||
// Magnitude-wise largest representable negative value.
|
||||
// Present only if kIsSigned.
|
||||
static const Type kNegMax;
|
||||
// Smallest integer x such that 10^x is representable.
|
||||
static const int kMin10Exp;
|
||||
// Largest integer x such that 10^x is representable.
|
||||
static const int kMax10Exp;
|
||||
// Smallest positive value such that Type(1) + kEpsilon != Type(1)
|
||||
static const Type kEpsilon;
|
||||
// Typical rounding error that is enough to cover
|
||||
// a few simple floating-point operations.
|
||||
// Slightly larger than kEpsilon to account for a few rounding errors.
|
||||
// Is zero if kIsInteger.
|
||||
static const Type kStdError;
|
||||
// Number of decimal digits of mantissa precision.
|
||||
// Present only if !kIsInteger.
|
||||
static const int kPrecisionDigits;
|
||||
// Not a number, i.e. result of 0/0.
|
||||
// Present only if !kIsInteger.
|
||||
static const Type kNaN;
|
||||
// Positive infinity, i.e. result of 1/0.
|
||||
// Present only if !kIsInteger.
|
||||
static const Type kPosInf;
|
||||
// Negative infinity, i.e. result of -1/0.
|
||||
// Present only if !kIsInteger.
|
||||
static const Type kNegInf;
|
||||
|
||||
// NOTE: Special floating point values behave
|
||||
// in a special (but mathematically-logical) way
|
||||
// in terms of (in)equalty comparison and mathematical operations
|
||||
// -- see out unittest for examples.
|
||||
|
||||
// Special floating point value testers.
|
||||
// Present in integer types for convenience.
|
||||
static bool IsFinite(const Type x);
|
||||
static bool IsNaN(const Type x);
|
||||
static bool IsInf(const Type x);
|
||||
static bool IsPosInf(const Type x);
|
||||
static bool IsNegInf(const Type x);
|
||||
};
|
||||
|
||||
// ========================================================================= //
|
||||
|
||||
// All #define-s below are simply to refactor the declarations of
|
||||
// MathLimits template specializations.
|
||||
// They are all #undef-ined below.
|
||||
|
||||
// The hoop-jumping in *_INT_(MAX|MIN) below is so that the compiler does not
|
||||
// get an overflow while computing the constants.
|
||||
|
||||
#define SIGNED_INT_MAX(Type) \
|
||||
(((Type(1) << (sizeof(Type)*8 - 2)) - 1) + (Type(1) << (sizeof(Type)*8 - 2)))
|
||||
|
||||
#define SIGNED_INT_MIN(Type) \
|
||||
(-(Type(1) << (sizeof(Type)*8 - 2)) - (Type(1) << (sizeof(Type)*8 - 2)))
|
||||
|
||||
#define UNSIGNED_INT_MAX(Type) \
|
||||
(((Type(1) << (sizeof(Type)*8 - 1)) - 1) + (Type(1) << (sizeof(Type)*8 - 1)))
|
||||
|
||||
// Compile-time selected log10-related constants for integer types.
|
||||
#define SIGNED_MAX_10_EXP(Type) \
|
||||
(sizeof(Type) == 1 ? 2 : ( \
|
||||
sizeof(Type) == 2 ? 4 : ( \
|
||||
sizeof(Type) == 4 ? 9 : ( \
|
||||
sizeof(Type) == 8 ? 18 : -1))))
|
||||
|
||||
#define UNSIGNED_MAX_10_EXP(Type) \
|
||||
(sizeof(Type) == 1 ? 2 : ( \
|
||||
sizeof(Type) == 2 ? 4 : ( \
|
||||
sizeof(Type) == 4 ? 9 : ( \
|
||||
sizeof(Type) == 8 ? 19 : -1))))
|
||||
|
||||
#define DECL_INT_LIMIT_FUNCS \
|
||||
static bool IsFinite(const Type /*x*/) { return true; } \
|
||||
static bool IsNaN(const Type /*x*/) { return false; } \
|
||||
static bool IsInf(const Type /*x*/) { return false; } \
|
||||
static bool IsPosInf(const Type /*x*/) { return false; } \
|
||||
static bool IsNegInf(const Type /*x*/) { return false; }
|
||||
|
||||
#define DECL_SIGNED_INT_LIMITS(IntType, UnsignedIntType) \
|
||||
template<> \
|
||||
struct LIBPROTOBUF_EXPORT MathLimits<IntType> { \
|
||||
typedef IntType Type; \
|
||||
typedef UnsignedIntType UnsignedType; \
|
||||
static const bool kIsSigned = true; \
|
||||
static const bool kIsInteger = true; \
|
||||
static const Type kPosMin = 1; \
|
||||
static const Type kPosMax = SIGNED_INT_MAX(Type); \
|
||||
static const Type kMin = SIGNED_INT_MIN(Type); \
|
||||
static const Type kMax = kPosMax; \
|
||||
static const Type kNegMin = -1; \
|
||||
static const Type kNegMax = kMin; \
|
||||
static const int kMin10Exp = 0; \
|
||||
static const int kMax10Exp = SIGNED_MAX_10_EXP(Type); \
|
||||
static const Type kEpsilon = 1; \
|
||||
static const Type kStdError = 0; \
|
||||
DECL_INT_LIMIT_FUNCS \
|
||||
};
|
||||
|
||||
#define DECL_UNSIGNED_INT_LIMITS(IntType) \
|
||||
template<> \
|
||||
struct LIBPROTOBUF_EXPORT MathLimits<IntType> { \
|
||||
typedef IntType Type; \
|
||||
typedef IntType UnsignedType; \
|
||||
static const bool kIsSigned = false; \
|
||||
static const bool kIsInteger = true; \
|
||||
static const Type kPosMin = 1; \
|
||||
static const Type kPosMax = UNSIGNED_INT_MAX(Type); \
|
||||
static const Type kMin = 0; \
|
||||
static const Type kMax = kPosMax; \
|
||||
static const int kMin10Exp = 0; \
|
||||
static const int kMax10Exp = UNSIGNED_MAX_10_EXP(Type); \
|
||||
static const Type kEpsilon = 1; \
|
||||
static const Type kStdError = 0; \
|
||||
DECL_INT_LIMIT_FUNCS \
|
||||
};
|
||||
|
||||
DECL_SIGNED_INT_LIMITS(signed char, unsigned char)
|
||||
DECL_SIGNED_INT_LIMITS(signed short int, unsigned short int)
|
||||
DECL_SIGNED_INT_LIMITS(signed int, unsigned int)
|
||||
DECL_SIGNED_INT_LIMITS(signed long int, unsigned long int)
|
||||
DECL_SIGNED_INT_LIMITS(signed long long int, unsigned long long int)
|
||||
DECL_UNSIGNED_INT_LIMITS(unsigned char)
|
||||
DECL_UNSIGNED_INT_LIMITS(unsigned short int)
|
||||
DECL_UNSIGNED_INT_LIMITS(unsigned int)
|
||||
DECL_UNSIGNED_INT_LIMITS(unsigned long int)
|
||||
DECL_UNSIGNED_INT_LIMITS(unsigned long long int)
|
||||
|
||||
#undef DECL_SIGNED_INT_LIMITS
|
||||
#undef DECL_UNSIGNED_INT_LIMITS
|
||||
#undef SIGNED_INT_MAX
|
||||
#undef SIGNED_INT_MIN
|
||||
#undef UNSIGNED_INT_MAX
|
||||
#undef SIGNED_MAX_10_EXP
|
||||
#undef UNSIGNED_MAX_10_EXP
|
||||
#undef DECL_INT_LIMIT_FUNCS
|
||||
|
||||
// For non-Windows builds we use the std:: versions of isinf and isnan if they
|
||||
// are available; see the comment about <cmath> at the top of this file for the
|
||||
// details on why we need to do this.
|
||||
#ifdef GOOGLE_PROTOBUF_USE_STD_CMATH
|
||||
#define ISINF std::isinf
|
||||
#define ISNAN std::isnan
|
||||
#else
|
||||
#define ISINF isinf
|
||||
#define ISNAN isnan
|
||||
#endif
|
||||
|
||||
// ========================================================================= //
|
||||
#if WIN32 && !__MINGW32__ // Lacks built-in isnan() and isinf()
|
||||
#define DECL_FP_LIMIT_FUNCS \
|
||||
static bool IsFinite(const Type x) { return _finite(x); } \
|
||||
static bool IsNaN(const Type x) { return _isnan(x); } \
|
||||
static bool IsInf(const Type x) { return (_fpclass(x) & (_FPCLASS_NINF | _FPCLASS_PINF)) != 0; } \
|
||||
static bool IsPosInf(const Type x) { return _fpclass(x) == _FPCLASS_PINF; } \
|
||||
static bool IsNegInf(const Type x) { return _fpclass(x) == _FPCLASS_NINF; }
|
||||
#else
|
||||
#define DECL_FP_LIMIT_FUNCS \
|
||||
static bool IsFinite(const Type x) { return !ISINF(x) && !ISNAN(x); } \
|
||||
static bool IsNaN(const Type x) { return ISNAN(x); } \
|
||||
static bool IsInf(const Type x) { return ISINF(x); } \
|
||||
static bool IsPosInf(const Type x) { return ISINF(x) && x > 0; } \
|
||||
static bool IsNegInf(const Type x) { return ISINF(x) && x < 0; }
|
||||
#endif
|
||||
|
||||
// We can't put floating-point constant values in the header here because
|
||||
// such constants are not considered to be primitive-type constants by gcc.
|
||||
// CAVEAT: Hence, they are going to be initialized only during
|
||||
// the global objects construction time.
|
||||
#define DECL_FP_LIMITS(FP_Type, PREFIX) \
|
||||
template<> \
|
||||
struct LIBPROTOBUF_EXPORT MathLimits<FP_Type> { \
|
||||
typedef FP_Type Type; \
|
||||
typedef FP_Type UnsignedType; \
|
||||
static const bool kIsSigned = true; \
|
||||
static const bool kIsInteger = false; \
|
||||
static const Type kPosMin; \
|
||||
static const Type kPosMax; \
|
||||
static const Type kMin; \
|
||||
static const Type kMax; \
|
||||
static const Type kNegMin; \
|
||||
static const Type kNegMax; \
|
||||
static const int kMin10Exp = PREFIX##_MIN_10_EXP; \
|
||||
static const int kMax10Exp = PREFIX##_MAX_10_EXP; \
|
||||
static const Type kEpsilon; \
|
||||
static const Type kStdError; \
|
||||
static const int kPrecisionDigits = PREFIX##_DIG; \
|
||||
static const Type kNaN; \
|
||||
static const Type kPosInf; \
|
||||
static const Type kNegInf; \
|
||||
DECL_FP_LIMIT_FUNCS \
|
||||
};
|
||||
|
||||
DECL_FP_LIMITS(float, FLT)
|
||||
DECL_FP_LIMITS(double, DBL)
|
||||
DECL_FP_LIMITS(long double, LDBL)
|
||||
|
||||
#undef ISINF
|
||||
#undef ISNAN
|
||||
#undef DECL_FP_LIMITS
|
||||
#undef DECL_FP_LIMIT_FUNCS
|
||||
|
||||
// ========================================================================= //
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // UTIL_MATH_MATHLIMITS_H__
|
130
third_party/protobuf-lite/google/protobuf/stubs/mutex.h
vendored
Normal file
130
third_party/protobuf-lite/google/protobuf/stubs/mutex.h
vendored
Normal file
@ -0,0 +1,130 @@
|
||||
// Copyright (c) 2006, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google 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_STUBS_MUTEX_H_
|
||||
#define GOOGLE_PROTOBUF_STUBS_MUTEX_H_
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#include <google/protobuf/stubs/macros.h>
|
||||
|
||||
// ===================================================================
|
||||
// emulates google3/base/mutex.h
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
#define GOOGLE_PROTOBUF_LINKER_INITIALIZED
|
||||
|
||||
// Mutex is a natural type to wrap. As both google and other organization have
|
||||
// specialized mutexes. gRPC also provides an injection mechanism for custom
|
||||
// mutexes.
|
||||
class LIBPROTOBUF_EXPORT WrappedMutex {
|
||||
public:
|
||||
WrappedMutex() = default;
|
||||
void Lock() { mu_.lock(); }
|
||||
void Unlock() { mu_.unlock(); }
|
||||
// Crash if this Mutex is not held exclusively by this thread.
|
||||
// May fail to crash when it should; will never crash when it should not.
|
||||
void AssertHeld() const {}
|
||||
|
||||
private:
|
||||
std::mutex mu_;
|
||||
};
|
||||
|
||||
using Mutex = WrappedMutex;
|
||||
|
||||
// MutexLock(mu) acquires mu when constructed and releases it when destroyed.
|
||||
class LIBPROTOBUF_EXPORT MutexLock {
|
||||
public:
|
||||
explicit MutexLock(Mutex *mu) : mu_(mu) { this->mu_->Lock(); }
|
||||
~MutexLock() { this->mu_->Unlock(); }
|
||||
private:
|
||||
Mutex *const mu_;
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MutexLock);
|
||||
};
|
||||
|
||||
// TODO(kenton): Implement these? Hard to implement portably.
|
||||
typedef MutexLock ReaderMutexLock;
|
||||
typedef MutexLock WriterMutexLock;
|
||||
|
||||
// MutexLockMaybe is like MutexLock, but is a no-op when mu is NULL.
|
||||
class LIBPROTOBUF_EXPORT MutexLockMaybe {
|
||||
public:
|
||||
explicit MutexLockMaybe(Mutex *mu) :
|
||||
mu_(mu) { if (this->mu_ != NULL) { this->mu_->Lock(); } }
|
||||
~MutexLockMaybe() { if (this->mu_ != NULL) { this->mu_->Unlock(); } }
|
||||
private:
|
||||
Mutex *const mu_;
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MutexLockMaybe);
|
||||
};
|
||||
|
||||
#if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL)
|
||||
template<typename T>
|
||||
class ThreadLocalStorage {
|
||||
public:
|
||||
ThreadLocalStorage() {
|
||||
pthread_key_create(&key_, &ThreadLocalStorage::Delete);
|
||||
}
|
||||
~ThreadLocalStorage() {
|
||||
pthread_key_delete(key_);
|
||||
}
|
||||
T* Get() {
|
||||
T* result = static_cast<T*>(pthread_getspecific(key_));
|
||||
if (result == NULL) {
|
||||
result = new T();
|
||||
pthread_setspecific(key_, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
private:
|
||||
static void Delete(void* value) {
|
||||
delete static_cast<T*>(value);
|
||||
}
|
||||
pthread_key_t key_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ThreadLocalStorage);
|
||||
};
|
||||
#endif
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// We made these internal so that they would show up as such in the docs,
|
||||
// but we don't want to stick "internal::" in front of them everywhere.
|
||||
using internal::Mutex;
|
||||
using internal::MutexLock;
|
||||
using internal::ReaderMutexLock;
|
||||
using internal::WriterMutexLock;
|
||||
using internal::MutexLockMaybe;
|
||||
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_STUBS_MUTEX_H_
|
157
third_party/protobuf-lite/google/protobuf/stubs/once.h
vendored
Normal file
157
third_party/protobuf-lite/google/protobuf/stubs/once.h
vendored
Normal file
@ -0,0 +1,157 @@
|
||||
// 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)
|
||||
//
|
||||
// emulates google3/base/once.h
|
||||
//
|
||||
// This header is intended to be included only by internal .cc files and
|
||||
// generated .pb.cc files. Users should not use this directly.
|
||||
//
|
||||
// This is basically a portable version of pthread_once().
|
||||
//
|
||||
// This header declares:
|
||||
// * A type called ProtobufOnceType.
|
||||
// * A macro GOOGLE_PROTOBUF_DECLARE_ONCE() which declares a variable of type
|
||||
// ProtobufOnceType. This is the only legal way to declare such a variable.
|
||||
// The macro may only be used at the global scope (you cannot create local or
|
||||
// class member variables of this type).
|
||||
// * A function GoogleOnceInit(ProtobufOnceType* once, void (*init_func)()).
|
||||
// This function, when invoked multiple times given the same ProtobufOnceType
|
||||
// object, will invoke init_func on the first call only, and will make sure
|
||||
// none of the calls return before that first call to init_func has finished.
|
||||
// * The user can provide a parameter which GoogleOnceInit() forwards to the
|
||||
// user-provided function when it is called. Usage example:
|
||||
// int a = 10;
|
||||
// GoogleOnceInit(&my_once, &MyFunctionExpectingIntArgument, &a);
|
||||
// * This implementation guarantees that ProtobufOnceType is a POD (i.e. no
|
||||
// static initializer generated).
|
||||
//
|
||||
// This implements a way to perform lazy initialization. It's more efficient
|
||||
// than using mutexes as no lock is needed if initialization has already
|
||||
// happened.
|
||||
//
|
||||
// Example usage:
|
||||
// void Init();
|
||||
// GOOGLE_PROTOBUF_DECLARE_ONCE(once_init);
|
||||
//
|
||||
// // Calls Init() exactly once.
|
||||
// void InitOnce() {
|
||||
// GoogleOnceInit(&once_init, &Init);
|
||||
// }
|
||||
//
|
||||
// Note that if GoogleOnceInit() is called before main() has begun, it must
|
||||
// only be called by the thread that will eventually call main() -- that is,
|
||||
// the thread that performs dynamic initialization. In general this is a safe
|
||||
// assumption since people don't usually construct threads before main() starts,
|
||||
// but it is technically not guaranteed. Unfortunately, Win32 provides no way
|
||||
// whatsoever to statically-initialize its synchronization primitives, so our
|
||||
// only choice is to assume that dynamic initialization is single-threaded.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_STUBS_ONCE_H__
|
||||
#define GOOGLE_PROTOBUF_STUBS_ONCE_H__
|
||||
|
||||
#include <sched.h>
|
||||
#include <atomic>
|
||||
#include <mutex>
|
||||
#include <utility>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
using once_flag = std::atomic<int>;
|
||||
|
||||
template <typename Callable, typename... Args>
|
||||
void my_call_once(once_flag& once, Callable&& fn, Args&&... args) {
|
||||
enum CallOnceState {
|
||||
ONCE_INIT = 0,
|
||||
ONCE_RUNNING = 1,
|
||||
ONCE_DONE = 2,
|
||||
};
|
||||
|
||||
int expected_state = ONCE_INIT;
|
||||
if (once.compare_exchange_strong(expected_state, ONCE_RUNNING)) {
|
||||
fn(std::forward<Args>(args)...);
|
||||
once.store(ONCE_DONE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (expected_state == ONCE_DONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (once.load() == ONCE_RUNNING) {
|
||||
sched_yield();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
void call_once(Args&&... args) {
|
||||
my_call_once(std::forward<Args>(args)...);
|
||||
}
|
||||
} // namespace internal
|
||||
|
||||
// TODO(gerbens) remove this once third_party is fully extracted
|
||||
using ProtobufOnceType = internal::once_flag;
|
||||
|
||||
inline void GoogleOnceInit(ProtobufOnceType* once, void (*init_func)()) {
|
||||
internal::my_call_once(*once, init_func);
|
||||
}
|
||||
|
||||
template <typename Arg>
|
||||
inline void GoogleOnceInitArg(ProtobufOnceType* once, void (*init_func)(Arg*),
|
||||
Arg* arg) {
|
||||
internal::my_call_once(*once, init_func, arg);
|
||||
}
|
||||
|
||||
class GoogleOnceDynamic {
|
||||
public:
|
||||
// If this->Init() has not been called before by any thread,
|
||||
// execute (*func_with_arg)(arg) then return.
|
||||
// Otherwise, wait until that prior invocation has finished
|
||||
// executing its function, then return.
|
||||
template <typename T>
|
||||
void Init(void (*func_with_arg)(T*), T* arg) {
|
||||
GoogleOnceInitArg<T>(&this->state_, func_with_arg, arg);
|
||||
}
|
||||
|
||||
private:
|
||||
ProtobufOnceType state_;
|
||||
};
|
||||
|
||||
#define GOOGLE_PROTOBUF_ONCE_TYPE ::google::protobuf::ProtobufOnceType
|
||||
#define GOOGLE_PROTOBUF_DECLARE_ONCE(NAME) \
|
||||
::google::protobuf::ProtobufOnceType NAME
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_STUBS_ONCE_H__
|
130
third_party/protobuf-lite/google/protobuf/stubs/once.h.org
vendored
Normal file
130
third_party/protobuf-lite/google/protobuf/stubs/once.h.org
vendored
Normal file
@ -0,0 +1,130 @@
|
||||
// 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)
|
||||
//
|
||||
// emulates google3/base/once.h
|
||||
//
|
||||
// This header is intended to be included only by internal .cc files and
|
||||
// generated .pb.cc files. Users should not use this directly.
|
||||
//
|
||||
// This is basically a portable version of pthread_once().
|
||||
//
|
||||
// This header declares:
|
||||
// * A type called ProtobufOnceType.
|
||||
// * A macro GOOGLE_PROTOBUF_DECLARE_ONCE() which declares a variable of type
|
||||
// ProtobufOnceType. This is the only legal way to declare such a variable.
|
||||
// The macro may only be used at the global scope (you cannot create local or
|
||||
// class member variables of this type).
|
||||
// * A function GoogleOnceInit(ProtobufOnceType* once, void (*init_func)()).
|
||||
// This function, when invoked multiple times given the same ProtobufOnceType
|
||||
// object, will invoke init_func on the first call only, and will make sure
|
||||
// none of the calls return before that first call to init_func has finished.
|
||||
// * The user can provide a parameter which GoogleOnceInit() forwards to the
|
||||
// user-provided function when it is called. Usage example:
|
||||
// int a = 10;
|
||||
// GoogleOnceInit(&my_once, &MyFunctionExpectingIntArgument, &a);
|
||||
// * This implementation guarantees that ProtobufOnceType is a POD (i.e. no
|
||||
// static initializer generated).
|
||||
//
|
||||
// This implements a way to perform lazy initialization. It's more efficient
|
||||
// than using mutexes as no lock is needed if initialization has already
|
||||
// happened.
|
||||
//
|
||||
// Example usage:
|
||||
// void Init();
|
||||
// GOOGLE_PROTOBUF_DECLARE_ONCE(once_init);
|
||||
//
|
||||
// // Calls Init() exactly once.
|
||||
// void InitOnce() {
|
||||
// GoogleOnceInit(&once_init, &Init);
|
||||
// }
|
||||
//
|
||||
// Note that if GoogleOnceInit() is called before main() has begun, it must
|
||||
// only be called by the thread that will eventually call main() -- that is,
|
||||
// the thread that performs dynamic initialization. In general this is a safe
|
||||
// assumption since people don't usually construct threads before main() starts,
|
||||
// but it is technically not guaranteed. Unfortunately, Win32 provides no way
|
||||
// whatsoever to statically-initialize its synchronization primitives, so our
|
||||
// only choice is to assume that dynamic initialization is single-threaded.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_STUBS_ONCE_H__
|
||||
#define GOOGLE_PROTOBUF_STUBS_ONCE_H__
|
||||
|
||||
#include <mutex>
|
||||
#include <utility>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
using once_flag = std::once_flag;
|
||||
template <typename... Args>
|
||||
void call_once(Args&&... args ) {
|
||||
std::call_once(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// TODO(gerbens) remove this once third_party is fully extracted
|
||||
using ProtobufOnceType = internal::once_flag;
|
||||
|
||||
inline void GoogleOnceInit(ProtobufOnceType* once, void (*init_func)()) {
|
||||
std::call_once(*once, init_func);
|
||||
}
|
||||
|
||||
template <typename Arg>
|
||||
inline void GoogleOnceInitArg(ProtobufOnceType* once, void (*init_func)(Arg*),
|
||||
Arg* arg) {
|
||||
std::call_once(*once, init_func, arg);
|
||||
}
|
||||
|
||||
class GoogleOnceDynamic {
|
||||
public:
|
||||
// If this->Init() has not been called before by any thread,
|
||||
// execute (*func_with_arg)(arg) then return.
|
||||
// Otherwise, wait until that prior invocation has finished
|
||||
// executing its function, then return.
|
||||
template<typename T>
|
||||
void Init(void (*func_with_arg)(T*), T* arg) {
|
||||
GoogleOnceInitArg<T>(&this->state_, func_with_arg, arg);
|
||||
}
|
||||
private:
|
||||
ProtobufOnceType state_;
|
||||
};
|
||||
|
||||
#define GOOGLE_PROTOBUF_ONCE_TYPE ::google::protobuf::ProtobufOnceType
|
||||
#define GOOGLE_PROTOBUF_DECLARE_ONCE(NAME) \
|
||||
::google::protobuf::ProtobufOnceType NAME
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_STUBS_ONCE_H__
|
128
third_party/protobuf-lite/google/protobuf/stubs/platform_macros.h
vendored
Normal file
128
third_party/protobuf-lite/google/protobuf/stubs/platform_macros.h
vendored
Normal file
@ -0,0 +1,128 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2012 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_PLATFORM_MACROS_H_
|
||||
#define GOOGLE_PROTOBUF_PLATFORM_MACROS_H_
|
||||
|
||||
#define GOOGLE_PROTOBUF_PLATFORM_ERROR \
|
||||
#error "Host platform was not detected as supported by protobuf"
|
||||
|
||||
// Processor architecture detection. For more info on what's defined, see:
|
||||
// http://msdn.microsoft.com/en-us/library/b0084kay.aspx
|
||||
// http://www.agner.org/optimize/calling_conventions.pdf
|
||||
// or with gcc, run: "echo | gcc -E -dM -"
|
||||
#if defined(_M_X64) || defined(__x86_64__)
|
||||
#define GOOGLE_PROTOBUF_ARCH_X64 1
|
||||
#define GOOGLE_PROTOBUF_ARCH_64_BIT 1
|
||||
#elif defined(_M_IX86) || defined(__i386__)
|
||||
#define GOOGLE_PROTOBUF_ARCH_IA32 1
|
||||
#define GOOGLE_PROTOBUF_ARCH_32_BIT 1
|
||||
#elif defined(__QNX__)
|
||||
#define GOOGLE_PROTOBUF_ARCH_ARM_QNX 1
|
||||
#define GOOGLE_PROTOBUF_ARCH_32_BIT 1
|
||||
#elif defined(_M_ARM) || defined(__ARMEL__)
|
||||
#define GOOGLE_PROTOBUF_ARCH_ARM 1
|
||||
#define GOOGLE_PROTOBUF_ARCH_32_BIT 1
|
||||
#elif defined(_M_ARM64)
|
||||
#define GOOGLE_PROTOBUF_ARCH_ARM 1
|
||||
#define GOOGLE_PROTOBUF_ARCH_64_BIT 1
|
||||
#elif defined(__aarch64__)
|
||||
#define GOOGLE_PROTOBUF_ARCH_AARCH64 1
|
||||
#define GOOGLE_PROTOBUF_ARCH_64_BIT 1
|
||||
#elif defined(__MIPSEL__)
|
||||
#if defined(__LP64__)
|
||||
#define GOOGLE_PROTOBUF_ARCH_MIPS64 1
|
||||
#define GOOGLE_PROTOBUF_ARCH_64_BIT 1
|
||||
#else
|
||||
#define GOOGLE_PROTOBUF_ARCH_MIPS 1
|
||||
#define GOOGLE_PROTOBUF_ARCH_32_BIT 1
|
||||
#endif
|
||||
#elif defined(__pnacl__)
|
||||
#define GOOGLE_PROTOBUF_ARCH_32_BIT 1
|
||||
#elif defined(sparc)
|
||||
#define GOOGLE_PROTOBUF_ARCH_SPARC 1
|
||||
#if defined(__sparc_v9__) || defined(__sparcv9) || defined(__arch64__)
|
||||
#define GOOGLE_PROTOBUF_ARCH_64_BIT 1
|
||||
#else
|
||||
#define GOOGLE_PROTOBUF_ARCH_32_BIT 1
|
||||
#endif
|
||||
#elif defined(_POWER) || defined(__powerpc64__) || defined(__PPC64__)
|
||||
#define GOOGLE_PROTOBUF_ARCH_POWER 1
|
||||
#define GOOGLE_PROTOBUF_ARCH_64_BIT 1
|
||||
#elif defined(__PPC__)
|
||||
#define GOOGLE_PROTOBUF_ARCH_PPC 1
|
||||
#define GOOGLE_PROTOBUF_ARCH_32_BIT 1
|
||||
#elif defined(__GNUC__)
|
||||
# if (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4))
|
||||
// We fallback to the generic Clang/GCC >= 4.7 implementation in atomicops.h
|
||||
# elif defined(__clang__)
|
||||
# if !__has_extension(c_atomic)
|
||||
GOOGLE_PROTOBUF_PLATFORM_ERROR
|
||||
# endif
|
||||
// We fallback to the generic Clang/GCC >= 4.7 implementation in atomicops.h
|
||||
# endif
|
||||
# if __LP64__
|
||||
# define GOOGLE_PROTOBUF_ARCH_64_BIT 1
|
||||
# else
|
||||
# define GOOGLE_PROTOBUF_ARCH_32_BIT 1
|
||||
# endif
|
||||
#else
|
||||
GOOGLE_PROTOBUF_PLATFORM_ERROR
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#define GOOGLE_PROTOBUF_OS_APPLE
|
||||
#include <TargetConditionals.h>
|
||||
#if TARGET_OS_IPHONE
|
||||
#define GOOGLE_PROTOBUF_OS_IPHONE
|
||||
#endif
|
||||
#elif defined(__EMSCRIPTEN__)
|
||||
#define GOOGLE_PROTOBUF_OS_EMSCRIPTEN
|
||||
#elif defined(__native_client__)
|
||||
#define GOOGLE_PROTOBUF_OS_NACL
|
||||
#elif defined(sun)
|
||||
#define GOOGLE_PROTOBUF_OS_SOLARIS
|
||||
#elif defined(_AIX)
|
||||
#define GOOGLE_PROTOBUF_OS_AIX
|
||||
#elif defined(__ANDROID__)
|
||||
#define GOOGLE_PROTOBUF_OS_ANDROID
|
||||
#endif
|
||||
|
||||
#undef GOOGLE_PROTOBUF_PLATFORM_ERROR
|
||||
|
||||
#if defined(GOOGLE_PROTOBUF_OS_ANDROID) || defined(GOOGLE_PROTOBUF_OS_IPHONE) || defined(__OpenBSD__)
|
||||
// Android ndk does not support the __thread keyword very well yet. Here
|
||||
// we use pthread_key_create()/pthread_getspecific()/... methods for
|
||||
// TLS support on android.
|
||||
// iOS and OpenBSD also do not support the __thread keyword.
|
||||
#define GOOGLE_PROTOBUF_NO_THREADLOCAL
|
||||
#endif
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_PLATFORM_MACROS_H_
|
542
third_party/protobuf-lite/google/protobuf/stubs/port.h
vendored
Normal file
542
third_party/protobuf-lite/google/protobuf/stubs/port.h
vendored
Normal file
@ -0,0 +1,542 @@
|
||||
// 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_STUBS_PORT_H_
|
||||
#define GOOGLE_PROTOBUF_STUBS_PORT_H_
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
#include <string.h>
|
||||
#if defined(__osf__)
|
||||
// Tru64 lacks stdint.h, but has inttypes.h which defines a superset of
|
||||
// what stdint.h would define.
|
||||
#include <inttypes.h>
|
||||
#elif !defined(_MSC_VER)
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#include <google/protobuf/stubs/platform_macros.h>
|
||||
|
||||
#undef PROTOBUF_LITTLE_ENDIAN
|
||||
#ifdef _WIN32
|
||||
// Assuming windows is always little-endian.
|
||||
// TODO(xiaofeng): The PROTOBUF_LITTLE_ENDIAN is not only used for
|
||||
// optimization but also for correctness. We should define an
|
||||
// different macro to test the big-endian code path in coded_stream.
|
||||
#if !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST)
|
||||
#define PROTOBUF_LITTLE_ENDIAN 1
|
||||
#endif
|
||||
#if _MSC_VER >= 1300 && !defined(__INTEL_COMPILER)
|
||||
// If MSVC has "/RTCc" set, it will complain about truncating casts at
|
||||
// runtime. This file contains some intentional truncating casts.
|
||||
#pragma runtime_checks("c", off)
|
||||
#endif
|
||||
#else
|
||||
#include <sys/param.h> // __BYTE_ORDER
|
||||
#if defined(__OpenBSD__)
|
||||
#include <endian.h>
|
||||
#endif
|
||||
#if ((defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)) || \
|
||||
(defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN) || \
|
||||
(defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN)) && \
|
||||
!defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST)
|
||||
#define PROTOBUF_LITTLE_ENDIAN 1
|
||||
#endif
|
||||
#endif
|
||||
#if defined(_MSC_VER) && defined(PROTOBUF_USE_DLLS)
|
||||
#ifdef LIBPROTOBUF_EXPORTS
|
||||
#define LIBPROTOBUF_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define LIBPROTOBUF_EXPORT __declspec(dllimport)
|
||||
#endif
|
||||
#ifdef LIBPROTOC_EXPORTS
|
||||
#define LIBPROTOC_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define LIBPROTOC_EXPORT __declspec(dllimport)
|
||||
#endif
|
||||
#else
|
||||
#define LIBPROTOBUF_EXPORT
|
||||
#define LIBPROTOC_EXPORT
|
||||
#endif
|
||||
|
||||
// These #includes are for the byte swap functions declared later on.
|
||||
#ifdef _MSC_VER
|
||||
#include <stdlib.h> // NOLINT(build/include)
|
||||
#include <intrin.h>
|
||||
#elif defined(__APPLE__)
|
||||
#include <libkern/OSByteOrder.h>
|
||||
#elif defined(__GLIBC__) || defined(__BIONIC__) || defined(__CYGWIN__)
|
||||
#include <byteswap.h> // IWYU pragma: export
|
||||
#endif
|
||||
|
||||
#define PROTOBUF_RUNTIME_DEPRECATED(message)
|
||||
|
||||
// ===================================================================
|
||||
// from google3/base/port.h
|
||||
|
||||
#if (defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L || \
|
||||
(defined(_MSC_VER) && _MSC_VER >= 1900))
|
||||
// Define this to 1 if the code is compiled in C++11 mode; leave it
|
||||
// undefined otherwise. Do NOT define it to 0 -- that causes
|
||||
// '#ifdef LANG_CXX11' to behave differently from '#if LANG_CXX11'.
|
||||
#define LANG_CXX11 1
|
||||
#endif
|
||||
|
||||
#if LANG_CXX11 && !defined(__NVCC__)
|
||||
#define PROTOBUF_CXX11 1
|
||||
#else
|
||||
#define PROTOBUF_CXX11 0
|
||||
#endif
|
||||
|
||||
#if PROTOBUF_CXX11
|
||||
#define PROTOBUF_FINAL final
|
||||
#else
|
||||
#define PROTOBUF_FINAL
|
||||
#endif
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
typedef unsigned int uint;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
typedef signed __int8 int8;
|
||||
typedef __int16 int16;
|
||||
typedef __int32 int32;
|
||||
typedef __int64 int64;
|
||||
|
||||
typedef unsigned __int8 uint8;
|
||||
typedef unsigned __int16 uint16;
|
||||
typedef unsigned __int32 uint32;
|
||||
typedef unsigned __int64 uint64;
|
||||
#else
|
||||
typedef int8_t int8;
|
||||
typedef int16_t int16;
|
||||
typedef int32_t int32;
|
||||
typedef int64_t int64;
|
||||
|
||||
typedef uint8_t uint8;
|
||||
typedef uint16_t uint16;
|
||||
typedef uint32_t uint32;
|
||||
typedef uint64_t uint64;
|
||||
#endif
|
||||
|
||||
// long long macros to be used because gcc and vc++ use different suffixes,
|
||||
// and different size specifiers in format strings
|
||||
#undef GOOGLE_LONGLONG
|
||||
#undef GOOGLE_ULONGLONG
|
||||
#undef GOOGLE_LL_FORMAT
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define GOOGLE_LONGLONG(x) x##I64
|
||||
#define GOOGLE_ULONGLONG(x) x##UI64
|
||||
#define GOOGLE_LL_FORMAT "I64" // As in printf("%I64d", ...)
|
||||
#else
|
||||
// By long long, we actually mean int64.
|
||||
#define GOOGLE_LONGLONG(x) x##LL
|
||||
#define GOOGLE_ULONGLONG(x) x##ULL
|
||||
// Used to format real long long integers.
|
||||
#define GOOGLE_LL_FORMAT "ll" // As in "%lld". Note that "q" is poor form also.
|
||||
#endif
|
||||
|
||||
static const int32 kint32max = 0x7FFFFFFF;
|
||||
static const int32 kint32min = -kint32max - 1;
|
||||
static const int64 kint64max = GOOGLE_LONGLONG(0x7FFFFFFFFFFFFFFF);
|
||||
static const int64 kint64min = -kint64max - 1;
|
||||
static const uint32 kuint32max = 0xFFFFFFFFu;
|
||||
static const uint64 kuint64max = GOOGLE_ULONGLONG(0xFFFFFFFFFFFFFFFF);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Annotations: Some parts of the code have been annotated in ways that might
|
||||
// be useful to some compilers or tools, but are not supported universally.
|
||||
// You can #define these annotations yourself if the default implementation
|
||||
// is not right for you.
|
||||
|
||||
#ifndef GOOGLE_ATTRIBUTE_ALWAYS_INLINE
|
||||
#if defined(__GNUC__) && (__GNUC__ > 3 ||(__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
|
||||
// For functions we want to force inline.
|
||||
// Introduced in gcc 3.1.
|
||||
#define GOOGLE_ATTRIBUTE_ALWAYS_INLINE __attribute__ ((always_inline))
|
||||
#else
|
||||
// Other compilers will have to figure it out for themselves.
|
||||
#define GOOGLE_ATTRIBUTE_ALWAYS_INLINE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE GOOGLE_ATTRIBUTE_ALWAYS_INLINE
|
||||
|
||||
#ifndef GOOGLE_ATTRIBUTE_NOINLINE
|
||||
#if defined(__GNUC__) && (__GNUC__ > 3 ||(__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
|
||||
// For functions we want to force not inline.
|
||||
// Introduced in gcc 3.1.
|
||||
#define GOOGLE_ATTRIBUTE_NOINLINE __attribute__ ((noinline))
|
||||
#elif defined(_MSC_VER) && (_MSC_VER >= 1400)
|
||||
// Seems to have been around since at least Visual Studio 2005
|
||||
#define GOOGLE_ATTRIBUTE_NOINLINE __declspec(noinline)
|
||||
#else
|
||||
// Other compilers will have to figure it out for themselves.
|
||||
#define GOOGLE_ATTRIBUTE_NOINLINE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE GOOGLE_ATTRIBUTE_NOINLINE
|
||||
|
||||
#ifndef GOOGLE_ATTRIBUTE_FUNC_ALIGN
|
||||
#if defined(__clang__) || \
|
||||
defined(__GNUC__) && (__GNUC__ > 4 ||(__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
|
||||
// Function alignment attribute introduced in gcc 4.3
|
||||
#define GOOGLE_ATTRIBUTE_FUNC_ALIGN(bytes) __attribute__ ((aligned(bytes)))
|
||||
#else
|
||||
#define GOOGLE_ATTRIBUTE_FUNC_ALIGN(bytes)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define GOOGLE_PROTOBUF_ATTRIBUTE_FUNC_ALIGN(bytes) \
|
||||
GOOGLE_ATTRIBUTE_FUNC_ALIGN(bytes)
|
||||
|
||||
#ifndef GOOGLE_PREDICT_TRUE
|
||||
#ifdef __GNUC__
|
||||
// Provided at least since GCC 3.0.
|
||||
#define GOOGLE_PREDICT_TRUE(x) (__builtin_expect(!!(x), 1))
|
||||
#else
|
||||
#define GOOGLE_PREDICT_TRUE(x) (x)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef GOOGLE_PREDICT_FALSE
|
||||
#ifdef __GNUC__
|
||||
// Provided at least since GCC 3.0.
|
||||
#define GOOGLE_PREDICT_FALSE(x) (__builtin_expect(x, 0))
|
||||
#else
|
||||
#define GOOGLE_PREDICT_FALSE(x) (x)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_ATTRIBUTE_RETURNS_NONNULL
|
||||
#ifdef __GNUC__
|
||||
#define GOOGLE_PROTOBUF_ATTRIBUTE_RETURNS_NONNULL \
|
||||
__attribute__((returns_nonnull))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Delimits a block of code which may write to memory which is simultaneously
|
||||
// written by other threads, but which has been determined to be thread-safe
|
||||
// (e.g. because it is an idempotent write).
|
||||
#ifndef GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN
|
||||
#define GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN()
|
||||
#endif
|
||||
#ifndef GOOGLE_SAFE_CONCURRENT_WRITES_END
|
||||
#define GOOGLE_SAFE_CONCURRENT_WRITES_END()
|
||||
#endif
|
||||
|
||||
#define GOOGLE_GUARDED_BY(x)
|
||||
#define GOOGLE_ATTRIBUTE_COLD
|
||||
|
||||
#ifdef GOOGLE_PROTOBUF_DONT_USE_UNALIGNED
|
||||
# define GOOGLE_PROTOBUF_USE_UNALIGNED 0
|
||||
#else
|
||||
# if defined(_M_X64) || defined(__x86_64__) || defined(_M_IX86) || defined(__i386__)
|
||||
# define GOOGLE_PROTOBUF_USE_UNALIGNED 1
|
||||
# else
|
||||
# define GOOGLE_PROTOBUF_USE_UNALIGNED 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define GOOGLE_PROTOBUF_ATTRIBUTE_COLD GOOGLE_ATTRIBUTE_COLD
|
||||
|
||||
#if defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER) ||\
|
||||
defined(MEMORY_SANITIZER)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
uint16_t __sanitizer_unaligned_load16(const void *p);
|
||||
uint32_t __sanitizer_unaligned_load32(const void *p);
|
||||
uint64_t __sanitizer_unaligned_load64(const void *p);
|
||||
void __sanitizer_unaligned_store16(void *p, uint16_t v);
|
||||
void __sanitizer_unaligned_store32(void *p, uint32_t v);
|
||||
void __sanitizer_unaligned_store64(void *p, uint64_t v);
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif // __cplusplus
|
||||
|
||||
inline uint16 GOOGLE_UNALIGNED_LOAD16(const void *p) {
|
||||
return __sanitizer_unaligned_load16(p);
|
||||
}
|
||||
|
||||
inline uint32 GOOGLE_UNALIGNED_LOAD32(const void *p) {
|
||||
return __sanitizer_unaligned_load32(p);
|
||||
}
|
||||
|
||||
inline uint64 GOOGLE_UNALIGNED_LOAD64(const void *p) {
|
||||
return __sanitizer_unaligned_load64(p);
|
||||
}
|
||||
|
||||
inline void GOOGLE_UNALIGNED_STORE16(void *p, uint16 v) {
|
||||
__sanitizer_unaligned_store16(p, v);
|
||||
}
|
||||
|
||||
inline void GOOGLE_UNALIGNED_STORE32(void *p, uint32 v) {
|
||||
__sanitizer_unaligned_store32(p, v);
|
||||
}
|
||||
|
||||
inline void GOOGLE_UNALIGNED_STORE64(void *p, uint64 v) {
|
||||
__sanitizer_unaligned_store64(p, v);
|
||||
}
|
||||
|
||||
#elif GOOGLE_PROTOBUF_USE_UNALIGNED
|
||||
|
||||
#define GOOGLE_UNALIGNED_LOAD16(_p) (*reinterpret_cast<const uint16 *>(_p))
|
||||
#define GOOGLE_UNALIGNED_LOAD32(_p) (*reinterpret_cast<const uint32 *>(_p))
|
||||
#define GOOGLE_UNALIGNED_LOAD64(_p) (*reinterpret_cast<const uint64 *>(_p))
|
||||
|
||||
#define GOOGLE_UNALIGNED_STORE16(_p, _val) (*reinterpret_cast<uint16 *>(_p) = (_val))
|
||||
#define GOOGLE_UNALIGNED_STORE32(_p, _val) (*reinterpret_cast<uint32 *>(_p) = (_val))
|
||||
#define GOOGLE_UNALIGNED_STORE64(_p, _val) (*reinterpret_cast<uint64 *>(_p) = (_val))
|
||||
|
||||
#else
|
||||
inline uint16 GOOGLE_UNALIGNED_LOAD16(const void *p) {
|
||||
uint16 t;
|
||||
memcpy(&t, p, sizeof t);
|
||||
return t;
|
||||
}
|
||||
|
||||
inline uint32 GOOGLE_UNALIGNED_LOAD32(const void *p) {
|
||||
uint32 t;
|
||||
memcpy(&t, p, sizeof t);
|
||||
return t;
|
||||
}
|
||||
|
||||
inline uint64 GOOGLE_UNALIGNED_LOAD64(const void *p) {
|
||||
uint64 t;
|
||||
memcpy(&t, p, sizeof t);
|
||||
return t;
|
||||
}
|
||||
|
||||
inline void GOOGLE_UNALIGNED_STORE16(void *p, uint16 v) {
|
||||
memcpy(p, &v, sizeof v);
|
||||
}
|
||||
|
||||
inline void GOOGLE_UNALIGNED_STORE32(void *p, uint32 v) {
|
||||
memcpy(p, &v, sizeof v);
|
||||
}
|
||||
|
||||
inline void GOOGLE_UNALIGNED_STORE64(void *p, uint64 v) {
|
||||
memcpy(p, &v, sizeof v);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(GOOGLE_PROTOBUF_OS_NACL) \
|
||||
|| (defined(__ANDROID__) && defined(__clang__) \
|
||||
&& (__clang_major__ == 3 && __clang_minor__ == 8) \
|
||||
&& (__clang_patchlevel__ < 275480))
|
||||
# define GOOGLE_PROTOBUF_USE_PORTABLE_LOG2
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define GOOGLE_THREAD_LOCAL __declspec(thread)
|
||||
#else
|
||||
#define GOOGLE_THREAD_LOCAL __thread
|
||||
#endif
|
||||
|
||||
// The following guarantees declaration of the byte swap functions.
|
||||
#ifdef _MSC_VER
|
||||
#define bswap_16(x) _byteswap_ushort(x)
|
||||
#define bswap_32(x) _byteswap_ulong(x)
|
||||
#define bswap_64(x) _byteswap_uint64(x)
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
// Mac OS X / Darwin features
|
||||
#define bswap_16(x) OSSwapInt16(x)
|
||||
#define bswap_32(x) OSSwapInt32(x)
|
||||
#define bswap_64(x) OSSwapInt64(x)
|
||||
|
||||
#elif !defined(__GLIBC__) && !defined(__BIONIC__) && !defined(__CYGWIN__)
|
||||
|
||||
static inline uint16 bswap_16(uint16 x) {
|
||||
return static_cast<uint16>(((x & 0xFF) << 8) | ((x & 0xFF00) >> 8));
|
||||
}
|
||||
#define bswap_16(x) bswap_16(x)
|
||||
static inline uint32 bswap_32(uint32 x) {
|
||||
return (((x & 0xFF) << 24) |
|
||||
((x & 0xFF00) << 8) |
|
||||
((x & 0xFF0000) >> 8) |
|
||||
((x & 0xFF000000) >> 24));
|
||||
}
|
||||
#define bswap_32(x) bswap_32(x)
|
||||
static inline uint64 bswap_64(uint64 x) {
|
||||
return (((x & GOOGLE_ULONGLONG(0xFF)) << 56) |
|
||||
((x & GOOGLE_ULONGLONG(0xFF00)) << 40) |
|
||||
((x & GOOGLE_ULONGLONG(0xFF0000)) << 24) |
|
||||
((x & GOOGLE_ULONGLONG(0xFF000000)) << 8) |
|
||||
((x & GOOGLE_ULONGLONG(0xFF00000000)) >> 8) |
|
||||
((x & GOOGLE_ULONGLONG(0xFF0000000000)) >> 24) |
|
||||
((x & GOOGLE_ULONGLONG(0xFF000000000000)) >> 40) |
|
||||
((x & GOOGLE_ULONGLONG(0xFF00000000000000)) >> 56));
|
||||
}
|
||||
#define bswap_64(x) bswap_64(x)
|
||||
|
||||
#endif
|
||||
|
||||
// ===================================================================
|
||||
// from google3/util/bits/bits.h
|
||||
|
||||
class Bits {
|
||||
public:
|
||||
static uint32 Log2FloorNonZero(uint32 n) {
|
||||
#if defined(__GNUC__)
|
||||
return 31 ^ static_cast<uint32>(__builtin_clz(n));
|
||||
#elif defined(_MSC_VER)
|
||||
unsigned long where;
|
||||
_BitScanReverse(&where, n);
|
||||
return where;
|
||||
#else
|
||||
return Log2FloorNonZero_Portable(n);
|
||||
#endif
|
||||
}
|
||||
|
||||
static uint32 Log2FloorNonZero64(uint64 n) {
|
||||
// Older versions of clang run into an instruction-selection failure when
|
||||
// it encounters __builtin_clzll:
|
||||
// https://bugs.chromium.org/p/nativeclient/issues/detail?id=4395
|
||||
// This includes arm-nacl-clang and clang in older Android NDK versions.
|
||||
// To work around this, when we build with those we use the portable
|
||||
// implementation instead.
|
||||
#if defined(__GNUC__) && !defined(GOOGLE_PROTOBUF_USE_PORTABLE_LOG2)
|
||||
return 63 ^ static_cast<uint32>(__builtin_clzll(n));
|
||||
#elif defined(_MSC_VER) && defined(_M_X64)
|
||||
unsigned long where;
|
||||
_BitScanReverse64(&where, n);
|
||||
return where;
|
||||
#else
|
||||
return Log2FloorNonZero64_Portable(n);
|
||||
#endif
|
||||
}
|
||||
private:
|
||||
static int Log2FloorNonZero_Portable(uint32 n) {
|
||||
if (n == 0)
|
||||
return -1;
|
||||
int log = 0;
|
||||
uint32 value = n;
|
||||
for (int i = 4; i >= 0; --i) {
|
||||
int shift = (1 << i);
|
||||
uint32 x = value >> shift;
|
||||
if (x != 0) {
|
||||
value = x;
|
||||
log += shift;
|
||||
}
|
||||
}
|
||||
assert(value == 1);
|
||||
return log;
|
||||
}
|
||||
|
||||
static int Log2FloorNonZero64_Portable(uint64 n) {
|
||||
const uint32 topbits = static_cast<uint32>(n >> 32);
|
||||
if (topbits == 0) {
|
||||
// Top bits are zero, so scan in bottom bits
|
||||
return static_cast<int>(Log2FloorNonZero(static_cast<uint32>(n)));
|
||||
} else {
|
||||
return 32 + static_cast<int>(Log2FloorNonZero(topbits));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// ===================================================================
|
||||
// from google3/util/endian/endian.h
|
||||
LIBPROTOBUF_EXPORT uint32 ghtonl(uint32 x);
|
||||
|
||||
class BigEndian {
|
||||
public:
|
||||
#ifdef PROTOBUF_LITTLE_ENDIAN
|
||||
|
||||
static uint16 FromHost16(uint16 x) { return bswap_16(x); }
|
||||
static uint16 ToHost16(uint16 x) { return bswap_16(x); }
|
||||
|
||||
static uint32 FromHost32(uint32 x) { return bswap_32(x); }
|
||||
static uint32 ToHost32(uint32 x) { return bswap_32(x); }
|
||||
|
||||
static uint64 FromHost64(uint64 x) { return bswap_64(x); }
|
||||
static uint64 ToHost64(uint64 x) { return bswap_64(x); }
|
||||
|
||||
static bool IsLittleEndian() { return true; }
|
||||
|
||||
#else
|
||||
|
||||
static uint16 FromHost16(uint16 x) { return x; }
|
||||
static uint16 ToHost16(uint16 x) { return x; }
|
||||
|
||||
static uint32 FromHost32(uint32 x) { return x; }
|
||||
static uint32 ToHost32(uint32 x) { return x; }
|
||||
|
||||
static uint64 FromHost64(uint64 x) { return x; }
|
||||
static uint64 ToHost64(uint64 x) { return x; }
|
||||
|
||||
static bool IsLittleEndian() { return false; }
|
||||
|
||||
#endif /* ENDIAN */
|
||||
|
||||
// Functions to do unaligned loads and stores in big-endian order.
|
||||
static uint16 Load16(const void *p) {
|
||||
return ToHost16(GOOGLE_UNALIGNED_LOAD16(p));
|
||||
}
|
||||
|
||||
static void Store16(void *p, uint16 v) {
|
||||
GOOGLE_UNALIGNED_STORE16(p, FromHost16(v));
|
||||
}
|
||||
|
||||
static uint32 Load32(const void *p) {
|
||||
return ToHost32(GOOGLE_UNALIGNED_LOAD32(p));
|
||||
}
|
||||
|
||||
static void Store32(void *p, uint32 v) {
|
||||
GOOGLE_UNALIGNED_STORE32(p, FromHost32(v));
|
||||
}
|
||||
|
||||
static uint64 Load64(const void *p) {
|
||||
return ToHost64(GOOGLE_UNALIGNED_LOAD64(p));
|
||||
}
|
||||
|
||||
static void Store64(void *p, uint64 v) {
|
||||
GOOGLE_UNALIGNED_STORE64(p, FromHost64(v));
|
||||
}
|
||||
};
|
||||
|
||||
#ifndef GOOGLE_ATTRIBUTE_SECTION_VARIABLE
|
||||
#define GOOGLE_ATTRIBUTE_SECTION_VARIABLE(name)
|
||||
#endif
|
||||
|
||||
#define GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(name)
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_STUBS_PORT_H_
|
116
third_party/protobuf-lite/google/protobuf/stubs/status.h
vendored
Normal file
116
third_party/protobuf-lite/google/protobuf/stubs/status.h
vendored
Normal file
@ -0,0 +1,116 @@
|
||||
// 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_STUBS_STATUS_H_
|
||||
#define GOOGLE_PROTOBUF_STUBS_STATUS_H_
|
||||
|
||||
#include <iosfwd>
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/stringpiece.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace util {
|
||||
namespace error {
|
||||
// These values must match error codes defined in google/rpc/code.proto.
|
||||
enum Code {
|
||||
OK = 0,
|
||||
CANCELLED = 1,
|
||||
UNKNOWN = 2,
|
||||
INVALID_ARGUMENT = 3,
|
||||
DEADLINE_EXCEEDED = 4,
|
||||
NOT_FOUND = 5,
|
||||
ALREADY_EXISTS = 6,
|
||||
PERMISSION_DENIED = 7,
|
||||
UNAUTHENTICATED = 16,
|
||||
RESOURCE_EXHAUSTED = 8,
|
||||
FAILED_PRECONDITION = 9,
|
||||
ABORTED = 10,
|
||||
OUT_OF_RANGE = 11,
|
||||
UNIMPLEMENTED = 12,
|
||||
INTERNAL = 13,
|
||||
UNAVAILABLE = 14,
|
||||
DATA_LOSS = 15,
|
||||
};
|
||||
} // namespace error
|
||||
|
||||
class LIBPROTOBUF_EXPORT Status {
|
||||
public:
|
||||
// Creates a "successful" status.
|
||||
Status();
|
||||
|
||||
// Create a status in the canonical error space with the specified
|
||||
// code, and error message. If "code == 0", error_message is
|
||||
// ignored and a Status object identical to Status::OK is
|
||||
// constructed.
|
||||
Status(error::Code error_code, StringPiece error_message);
|
||||
Status(const Status&);
|
||||
Status& operator=(const Status& x);
|
||||
~Status() {}
|
||||
|
||||
// Some pre-defined Status objects
|
||||
static const Status OK; // Identical to 0-arg constructor
|
||||
static const Status CANCELLED;
|
||||
static const Status UNKNOWN;
|
||||
|
||||
// Accessor
|
||||
bool ok() const {
|
||||
return error_code_ == error::OK;
|
||||
}
|
||||
int error_code() const {
|
||||
return error_code_;
|
||||
}
|
||||
StringPiece error_message() const {
|
||||
return error_message_;
|
||||
}
|
||||
|
||||
bool operator==(const Status& x) const;
|
||||
bool operator!=(const Status& x) const {
|
||||
return !operator==(x);
|
||||
}
|
||||
|
||||
// Return a combination of the error code name and message.
|
||||
string ToString() const;
|
||||
|
||||
private:
|
||||
error::Code error_code_;
|
||||
string error_message_;
|
||||
};
|
||||
|
||||
// Prints a human-readable representation of 'x' to 'os'.
|
||||
LIBPROTOBUF_EXPORT std::ostream& operator<<(std::ostream& os, const Status& x);
|
||||
|
||||
#define EXPECT_OK(value) EXPECT_TRUE((value).ok())
|
||||
|
||||
} // namespace util
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_STUBS_STATUS_H_
|
259
third_party/protobuf-lite/google/protobuf/stubs/statusor.h
vendored
Normal file
259
third_party/protobuf-lite/google/protobuf/stubs/statusor.h
vendored
Normal file
@ -0,0 +1,259 @@
|
||||
// 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.
|
||||
|
||||
// StatusOr<T> is the union of a Status object and a T
|
||||
// object. StatusOr models the concept of an object that is either a
|
||||
// usable value, or an error Status explaining why such a value is
|
||||
// not present. To this end, StatusOr<T> does not allow its Status
|
||||
// value to be Status::OK. Further, StatusOr<T*> does not allow the
|
||||
// contained pointer to be NULL.
|
||||
//
|
||||
// The primary use-case for StatusOr<T> is as the return value of a
|
||||
// function which may fail.
|
||||
//
|
||||
// Example client usage for a StatusOr<T>, where T is not a pointer:
|
||||
//
|
||||
// StatusOr<float> result = DoBigCalculationThatCouldFail();
|
||||
// if (result.ok()) {
|
||||
// float answer = result.ValueOrDie();
|
||||
// printf("Big calculation yielded: %f", answer);
|
||||
// } else {
|
||||
// LOG(ERROR) << result.status();
|
||||
// }
|
||||
//
|
||||
// Example client usage for a StatusOr<T*>:
|
||||
//
|
||||
// StatusOr<Foo*> result = FooFactory::MakeNewFoo(arg);
|
||||
// if (result.ok()) {
|
||||
// std::unique_ptr<Foo> foo(result.ValueOrDie());
|
||||
// foo->DoSomethingCool();
|
||||
// } else {
|
||||
// LOG(ERROR) << result.status();
|
||||
// }
|
||||
//
|
||||
// Example client usage for a StatusOr<std::unique_ptr<T>>:
|
||||
//
|
||||
// StatusOr<std::unique_ptr<Foo>> result = FooFactory::MakeNewFoo(arg);
|
||||
// if (result.ok()) {
|
||||
// std::unique_ptr<Foo> foo = result.ConsumeValueOrDie();
|
||||
// foo->DoSomethingCool();
|
||||
// } else {
|
||||
// LOG(ERROR) << result.status();
|
||||
// }
|
||||
//
|
||||
// Example factory implementation returning StatusOr<T*>:
|
||||
//
|
||||
// StatusOr<Foo*> FooFactory::MakeNewFoo(int arg) {
|
||||
// if (arg <= 0) {
|
||||
// return ::util::Status(::util::error::INVALID_ARGUMENT,
|
||||
// "Arg must be positive");
|
||||
// } else {
|
||||
// return new Foo(arg);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_STUBS_STATUSOR_H_
|
||||
#define GOOGLE_PROTOBUF_STUBS_STATUSOR_H_
|
||||
|
||||
#include <new>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include <google/protobuf/stubs/status.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace util {
|
||||
|
||||
template<typename T>
|
||||
class StatusOr {
|
||||
template<typename U> friend class StatusOr;
|
||||
|
||||
public:
|
||||
// Construct a new StatusOr with Status::UNKNOWN status
|
||||
StatusOr();
|
||||
|
||||
// Construct a new StatusOr with the given non-ok status. After calling
|
||||
// this constructor, calls to ValueOrDie() will CHECK-fail.
|
||||
//
|
||||
// NOTE: Not explicit - we want to use StatusOr<T> as a return
|
||||
// value, so it is convenient and sensible to be able to do 'return
|
||||
// Status()' when the return type is StatusOr<T>.
|
||||
//
|
||||
// REQUIRES: status != Status::OK. This requirement is DCHECKed.
|
||||
// In optimized builds, passing Status::OK here will have the effect
|
||||
// of passing PosixErrorSpace::EINVAL as a fallback.
|
||||
StatusOr(const Status& status); // NOLINT
|
||||
|
||||
// Construct a new StatusOr with the given value. If T is a plain pointer,
|
||||
// value must not be NULL. After calling this constructor, calls to
|
||||
// ValueOrDie() will succeed, and calls to status() will return OK.
|
||||
//
|
||||
// NOTE: Not explicit - we want to use StatusOr<T> as a return type
|
||||
// so it is convenient and sensible to be able to do 'return T()'
|
||||
// when when the return type is StatusOr<T>.
|
||||
//
|
||||
// REQUIRES: if T is a plain pointer, value != NULL. This requirement is
|
||||
// DCHECKed. In optimized builds, passing a NULL pointer here will have
|
||||
// the effect of passing PosixErrorSpace::EINVAL as a fallback.
|
||||
StatusOr(const T& value); // NOLINT
|
||||
|
||||
// Copy constructor.
|
||||
StatusOr(const StatusOr& other);
|
||||
|
||||
// Conversion copy constructor, T must be copy constructible from U
|
||||
template<typename U>
|
||||
StatusOr(const StatusOr<U>& other);
|
||||
|
||||
// Assignment operator.
|
||||
StatusOr& operator=(const StatusOr& other);
|
||||
|
||||
// Conversion assignment operator, T must be assignable from U
|
||||
template<typename U>
|
||||
StatusOr& operator=(const StatusOr<U>& other);
|
||||
|
||||
// Returns a reference to our status. If this contains a T, then
|
||||
// returns Status::OK.
|
||||
const Status& status() const;
|
||||
|
||||
// Returns this->status().ok()
|
||||
bool ok() const;
|
||||
|
||||
// Returns a reference to our current value, or CHECK-fails if !this->ok().
|
||||
// If you need to initialize a T object from the stored value,
|
||||
// ConsumeValueOrDie() may be more efficient.
|
||||
const T& ValueOrDie() const;
|
||||
|
||||
private:
|
||||
Status status_;
|
||||
T value_;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Implementation details for StatusOr<T>
|
||||
|
||||
namespace internal {
|
||||
|
||||
class LIBPROTOBUF_EXPORT StatusOrHelper {
|
||||
public:
|
||||
// Move type-agnostic error handling to the .cc.
|
||||
static void Crash(const util::Status& status);
|
||||
|
||||
// Customized behavior for StatusOr<T> vs. StatusOr<T*>
|
||||
template<typename T>
|
||||
struct Specialize;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct StatusOrHelper::Specialize {
|
||||
// For non-pointer T, a reference can never be NULL.
|
||||
static inline bool IsValueNull(const T& t) { return false; }
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct StatusOrHelper::Specialize<T*> {
|
||||
static inline bool IsValueNull(const T* t) { return t == NULL; }
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
template<typename T>
|
||||
inline StatusOr<T>::StatusOr()
|
||||
: status_(util::Status::UNKNOWN) {
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline StatusOr<T>::StatusOr(const Status& status) {
|
||||
if (status.ok()) {
|
||||
status_ = Status(error::INTERNAL, "Status::OK is not a valid argument.");
|
||||
} else {
|
||||
status_ = status;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline StatusOr<T>::StatusOr(const T& value) {
|
||||
if (internal::StatusOrHelper::Specialize<T>::IsValueNull(value)) {
|
||||
status_ = Status(error::INTERNAL, "NULL is not a vaild argument.");
|
||||
} else {
|
||||
status_ = Status::OK;
|
||||
value_ = value;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline StatusOr<T>::StatusOr(const StatusOr<T>& other)
|
||||
: status_(other.status_), value_(other.value_) {
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline StatusOr<T>& StatusOr<T>::operator=(const StatusOr<T>& other) {
|
||||
status_ = other.status_;
|
||||
value_ = other.value_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
inline StatusOr<T>::StatusOr(const StatusOr<U>& other)
|
||||
: status_(other.status_), value_(other.status_.ok() ? other.value_ : T()) {
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
inline StatusOr<T>& StatusOr<T>::operator=(const StatusOr<U>& other) {
|
||||
status_ = other.status_;
|
||||
if (status_.ok()) value_ = other.value_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline const Status& StatusOr<T>::status() const {
|
||||
return status_;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline bool StatusOr<T>::ok() const {
|
||||
return status().ok();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline const T& StatusOr<T>::ValueOrDie() const {
|
||||
if (!status_.ok()) {
|
||||
internal::StatusOrHelper::Crash(status_);
|
||||
}
|
||||
return value_;
|
||||
}
|
||||
} // namespace util
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_STUBS_STATUSOR_H_
|
121
third_party/protobuf-lite/google/protobuf/stubs/stl_util.h
vendored
Normal file
121
third_party/protobuf-lite/google/protobuf/stubs/stl_util.h
vendored
Normal file
@ -0,0 +1,121 @@
|
||||
// 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.
|
||||
|
||||
// from google3/util/gtl/stl_util.h
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_STUBS_STL_UTIL_H__
|
||||
#define GOOGLE_PROTOBUF_STUBS_STL_UTIL_H__
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
// STLDeleteContainerPointers()
|
||||
// For a range within a container of pointers, calls delete
|
||||
// (non-array version) on these pointers.
|
||||
// NOTE: for these three functions, we could just implement a DeleteObject
|
||||
// functor and then call for_each() on the range and functor, but this
|
||||
// requires us to pull in all of algorithm.h, which seems expensive.
|
||||
// For hash_[multi]set, it is important that this deletes behind the iterator
|
||||
// because the hash_set may call the hash function on the iterator when it is
|
||||
// advanced, which could result in the hash function trying to deference a
|
||||
// stale pointer.
|
||||
template <class ForwardIterator>
|
||||
void STLDeleteContainerPointers(ForwardIterator begin,
|
||||
ForwardIterator end) {
|
||||
while (begin != end) {
|
||||
ForwardIterator temp = begin;
|
||||
++begin;
|
||||
delete *temp;
|
||||
}
|
||||
}
|
||||
|
||||
// Inside Google, this function implements a horrible, disgusting hack in which
|
||||
// we reach into the string's private implementation and resize it without
|
||||
// initializing the new bytes. In some cases doing this can significantly
|
||||
// improve performance. However, since it's totally non-portable it has no
|
||||
// place in open source code. Feel free to fill this function in with your
|
||||
// own disgusting hack if you want the perf boost.
|
||||
inline void STLStringResizeUninitialized(string* s, size_t new_size) {
|
||||
s->resize(new_size);
|
||||
}
|
||||
|
||||
// Return a mutable char* pointing to a string's internal buffer,
|
||||
// which may not be null-terminated. Writing through this pointer will
|
||||
// modify the string.
|
||||
//
|
||||
// string_as_array(&str)[i] is valid for 0 <= i < str.size() until the
|
||||
// next call to a string method that invalidates iterators.
|
||||
//
|
||||
// As of 2006-04, there is no standard-blessed way of getting a
|
||||
// mutable reference to a string's internal buffer. However, issue 530
|
||||
// (http://www.open-std.org/JTC1/SC22/WG21/docs/lwg-active.html#530)
|
||||
// proposes this as the method. According to Matt Austern, this should
|
||||
// already work on all current implementations.
|
||||
inline char* string_as_array(string* str) {
|
||||
// DO NOT USE const_cast<char*>(str->data())! See the unittest for why.
|
||||
return str->empty() ? NULL : &*str->begin();
|
||||
}
|
||||
|
||||
// STLDeleteElements() deletes all the elements in an STL container and clears
|
||||
// the container. This function is suitable for use with a vector, set,
|
||||
// hash_set, or any other STL container which defines sensible begin(), end(),
|
||||
// and clear() methods.
|
||||
//
|
||||
// If container is NULL, this function is a no-op.
|
||||
//
|
||||
// As an alternative to calling STLDeleteElements() directly, consider
|
||||
// ElementDeleter (defined below), which ensures that your container's elements
|
||||
// are deleted when the ElementDeleter goes out of scope.
|
||||
template <class T>
|
||||
void STLDeleteElements(T *container) {
|
||||
if (!container) return;
|
||||
STLDeleteContainerPointers(container->begin(), container->end());
|
||||
container->clear();
|
||||
}
|
||||
|
||||
// Given an STL container consisting of (key, value) pairs, STLDeleteValues
|
||||
// deletes all the "value" components and clears the container. Does nothing
|
||||
// in the case it's given a NULL pointer.
|
||||
|
||||
template <class T>
|
||||
void STLDeleteValues(T *v) {
|
||||
if (!v) return;
|
||||
for (typename T::iterator i = v->begin(); i != v->end(); ++i) {
|
||||
delete i->second;
|
||||
}
|
||||
v->clear();
|
||||
}
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_STUBS_STL_UTIL_H__
|
487
third_party/protobuf-lite/google/protobuf/stubs/stringpiece.h
vendored
Normal file
487
third_party/protobuf-lite/google/protobuf/stubs/stringpiece.h
vendored
Normal file
@ -0,0 +1,487 @@
|
||||
// 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 StringPiece points to part or all of a string, Cord, double-quoted string
|
||||
// literal, or other string-like object. A StringPiece does *not* own the
|
||||
// string to which it points. A StringPiece is not null-terminated.
|
||||
//
|
||||
// You can use StringPiece as a function or method parameter. A StringPiece
|
||||
// parameter can receive a double-quoted string literal argument, a "const
|
||||
// char*" argument, a string argument, or a StringPiece argument with no data
|
||||
// copying. Systematic use of StringPiece for arguments reduces data
|
||||
// copies and strlen() calls.
|
||||
//
|
||||
// Prefer passing StringPieces by value:
|
||||
// void MyFunction(StringPiece arg);
|
||||
// If circumstances require, you may also pass by const reference:
|
||||
// void MyFunction(const StringPiece& arg); // not preferred
|
||||
// Both of these have the same lifetime semantics. Passing by value
|
||||
// generates slightly smaller code. For more discussion, see the thread
|
||||
// go/stringpiecebyvalue on c-users.
|
||||
//
|
||||
// StringPiece is also suitable for local variables if you know that
|
||||
// the lifetime of the underlying object is longer than the lifetime
|
||||
// of your StringPiece variable.
|
||||
//
|
||||
// Beware of binding a StringPiece to a temporary:
|
||||
// StringPiece sp = obj.MethodReturningString(); // BAD: lifetime problem
|
||||
//
|
||||
// This code is okay:
|
||||
// string str = obj.MethodReturningString(); // str owns its contents
|
||||
// StringPiece sp(str); // GOOD, because str outlives sp
|
||||
//
|
||||
// StringPiece is sometimes a poor choice for a return value and usually a poor
|
||||
// choice for a data member. If you do use a StringPiece this way, it is your
|
||||
// responsibility to ensure that the object pointed to by the StringPiece
|
||||
// outlives the StringPiece.
|
||||
//
|
||||
// A StringPiece may represent just part of a string; thus the name "Piece".
|
||||
// For example, when splitting a string, vector<StringPiece> is a natural data
|
||||
// type for the output. For another example, a Cord is a non-contiguous,
|
||||
// potentially very long string-like object. The Cord class has an interface
|
||||
// that iteratively provides StringPiece objects that point to the
|
||||
// successive pieces of a Cord object.
|
||||
//
|
||||
// A StringPiece is not null-terminated. If you write code that scans a
|
||||
// StringPiece, you must check its length before reading any characters.
|
||||
// Common idioms that work on null-terminated strings do not work on
|
||||
// StringPiece objects.
|
||||
//
|
||||
// There are several ways to create a null StringPiece:
|
||||
// StringPiece()
|
||||
// StringPiece(NULL)
|
||||
// StringPiece(NULL, 0)
|
||||
// For all of the above, sp.data() == NULL, sp.length() == 0,
|
||||
// and sp.empty() == true. Also, if you create a StringPiece with
|
||||
// a non-NULL pointer then sp.data() != NULL. Once created,
|
||||
// sp.data() will stay either NULL or not-NULL, except if you call
|
||||
// sp.clear() or sp.set().
|
||||
//
|
||||
// Thus, you can use StringPiece(NULL) to signal an out-of-band value
|
||||
// that is different from other StringPiece values. This is similar
|
||||
// to the way that const char* p1 = NULL; is different from
|
||||
// const char* p2 = "";.
|
||||
//
|
||||
// There are many ways to create an empty StringPiece:
|
||||
// StringPiece()
|
||||
// StringPiece(NULL)
|
||||
// StringPiece(NULL, 0)
|
||||
// StringPiece("")
|
||||
// StringPiece("", 0)
|
||||
// StringPiece("abcdef", 0)
|
||||
// StringPiece("abcdef"+6, 0)
|
||||
// For all of the above, sp.length() will be 0 and sp.empty() will be true.
|
||||
// For some empty StringPiece values, sp.data() will be NULL.
|
||||
// For some empty StringPiece values, sp.data() will not be NULL.
|
||||
//
|
||||
// Be careful not to confuse: null StringPiece and empty StringPiece.
|
||||
// The set of empty StringPieces properly includes the set of null StringPieces.
|
||||
// That is, every null StringPiece is an empty StringPiece,
|
||||
// but some non-null StringPieces are empty Stringpieces too.
|
||||
//
|
||||
// All empty StringPiece values compare equal to each other.
|
||||
// Even a null StringPieces compares equal to a non-null empty StringPiece:
|
||||
// StringPiece() == StringPiece("", 0)
|
||||
// StringPiece(NULL) == StringPiece("abc", 0)
|
||||
// StringPiece(NULL, 0) == StringPiece("abcdef"+6, 0)
|
||||
//
|
||||
// Look carefully at this example:
|
||||
// StringPiece("") == NULL
|
||||
// True or false? TRUE, because StringPiece::operator== converts
|
||||
// the right-hand side from NULL to StringPiece(NULL),
|
||||
// and then compares two zero-length spans of characters.
|
||||
// However, we are working to make this example produce a compile error.
|
||||
//
|
||||
// Suppose you want to write:
|
||||
// bool TestWhat?(StringPiece sp) { return sp == NULL; } // BAD
|
||||
// Do not do that. Write one of these instead:
|
||||
// bool TestNull(StringPiece sp) { return sp.data() == NULL; }
|
||||
// bool TestEmpty(StringPiece sp) { return sp.empty(); }
|
||||
// The intent of TestWhat? is unclear. Did you mean TestNull or TestEmpty?
|
||||
// Right now, TestWhat? behaves likes TestEmpty.
|
||||
// We are working to make TestWhat? produce a compile error.
|
||||
// TestNull is good to test for an out-of-band signal.
|
||||
// TestEmpty is good to test for an empty StringPiece.
|
||||
//
|
||||
// Caveats (again):
|
||||
// (1) The lifetime of the pointed-to string (or piece of a string)
|
||||
// must be longer than the lifetime of the StringPiece.
|
||||
// (2) There may or may not be a '\0' character after the end of
|
||||
// StringPiece data.
|
||||
// (3) A null StringPiece is empty.
|
||||
// An empty StringPiece may or may not be a null StringPiece.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_STUBS_STRINGPIECE_H_
|
||||
#define GOOGLE_PROTOBUF_STUBS_STRINGPIECE_H_
|
||||
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <iosfwd>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/hash.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
// StringPiece has *two* size types.
|
||||
// StringPiece::size_type
|
||||
// is unsigned
|
||||
// is 32 bits in LP32, 64 bits in LP64, 64 bits in LLP64
|
||||
// no future changes intended
|
||||
// stringpiece_ssize_type
|
||||
// is signed
|
||||
// is 32 bits in LP32, 64 bits in LP64, 64 bits in LLP64
|
||||
// future changes intended: http://go/64BitStringPiece
|
||||
//
|
||||
typedef string::difference_type stringpiece_ssize_type;
|
||||
|
||||
// STRINGPIECE_CHECK_SIZE protects us from 32-bit overflows.
|
||||
// TODO(mec): delete this after stringpiece_ssize_type goes 64 bit.
|
||||
#if !defined(NDEBUG)
|
||||
#define STRINGPIECE_CHECK_SIZE 1
|
||||
#elif defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0
|
||||
#define STRINGPIECE_CHECK_SIZE 1
|
||||
#else
|
||||
#define STRINGPIECE_CHECK_SIZE 0
|
||||
#endif
|
||||
|
||||
class LIBPROTOBUF_EXPORT StringPiece {
|
||||
private:
|
||||
const char* ptr_;
|
||||
stringpiece_ssize_type length_;
|
||||
|
||||
// Prevent overflow in debug mode or fortified mode.
|
||||
// sizeof(stringpiece_ssize_type) may be smaller than sizeof(size_t).
|
||||
static stringpiece_ssize_type CheckedSsizeTFromSizeT(size_t size) {
|
||||
#if STRINGPIECE_CHECK_SIZE > 0
|
||||
#ifdef max
|
||||
#undef max
|
||||
#endif
|
||||
if (size > static_cast<size_t>(
|
||||
std::numeric_limits<stringpiece_ssize_type>::max())) {
|
||||
// Some people grep for this message in logs
|
||||
// so take care if you ever change it.
|
||||
LogFatalSizeTooBig(size, "size_t to int conversion");
|
||||
}
|
||||
#endif
|
||||
return static_cast<stringpiece_ssize_type>(size);
|
||||
}
|
||||
|
||||
// Out-of-line error path.
|
||||
static void LogFatalSizeTooBig(size_t size, const char* details);
|
||||
|
||||
public:
|
||||
// We provide non-explicit singleton constructors so users can pass
|
||||
// in a "const char*" or a "string" wherever a "StringPiece" is
|
||||
// expected.
|
||||
//
|
||||
// Style guide exception granted:
|
||||
// http://goto/style-guide-exception-20978288
|
||||
StringPiece() : ptr_(NULL), length_(0) {}
|
||||
|
||||
StringPiece(const char* str) // NOLINT(runtime/explicit)
|
||||
: ptr_(str), length_(0) {
|
||||
if (str != NULL) {
|
||||
length_ = CheckedSsizeTFromSizeT(strlen(str));
|
||||
}
|
||||
}
|
||||
|
||||
template <class Allocator>
|
||||
StringPiece( // NOLINT(runtime/explicit)
|
||||
const std::basic_string<char, std::char_traits<char>, Allocator>& str)
|
||||
: ptr_(str.data()), length_(0) {
|
||||
length_ = CheckedSsizeTFromSizeT(str.size());
|
||||
}
|
||||
|
||||
StringPiece(const char* offset, stringpiece_ssize_type len)
|
||||
: ptr_(offset), length_(len) {
|
||||
assert(len >= 0);
|
||||
}
|
||||
|
||||
// Substring of another StringPiece.
|
||||
// pos must be non-negative and <= x.length().
|
||||
StringPiece(StringPiece x, stringpiece_ssize_type pos);
|
||||
// Substring of another StringPiece.
|
||||
// pos must be non-negative and <= x.length().
|
||||
// len must be non-negative and will be pinned to at most x.length() - pos.
|
||||
StringPiece(StringPiece x,
|
||||
stringpiece_ssize_type pos,
|
||||
stringpiece_ssize_type len);
|
||||
|
||||
// data() may return a pointer to a buffer with embedded NULs, and the
|
||||
// returned buffer may or may not be null terminated. Therefore it is
|
||||
// typically a mistake to pass data() to a routine that expects a NUL
|
||||
// terminated string.
|
||||
const char* data() const { return ptr_; }
|
||||
stringpiece_ssize_type size() const { return length_; }
|
||||
stringpiece_ssize_type length() const { return length_; }
|
||||
bool empty() const { return length_ == 0; }
|
||||
|
||||
void clear() {
|
||||
ptr_ = NULL;
|
||||
length_ = 0;
|
||||
}
|
||||
|
||||
void set(const char* data, stringpiece_ssize_type len) {
|
||||
assert(len >= 0);
|
||||
ptr_ = data;
|
||||
length_ = len;
|
||||
}
|
||||
|
||||
void set(const char* str) {
|
||||
ptr_ = str;
|
||||
if (str != NULL)
|
||||
length_ = CheckedSsizeTFromSizeT(strlen(str));
|
||||
else
|
||||
length_ = 0;
|
||||
}
|
||||
|
||||
void set(const void* data, stringpiece_ssize_type len) {
|
||||
ptr_ = reinterpret_cast<const char*>(data);
|
||||
length_ = len;
|
||||
}
|
||||
|
||||
char operator[](stringpiece_ssize_type i) const {
|
||||
assert(0 <= i);
|
||||
assert(i < length_);
|
||||
return ptr_[i];
|
||||
}
|
||||
|
||||
void remove_prefix(stringpiece_ssize_type n) {
|
||||
assert(length_ >= n);
|
||||
ptr_ += n;
|
||||
length_ -= n;
|
||||
}
|
||||
|
||||
void remove_suffix(stringpiece_ssize_type n) {
|
||||
assert(length_ >= n);
|
||||
length_ -= n;
|
||||
}
|
||||
|
||||
// returns {-1, 0, 1}
|
||||
int compare(StringPiece x) const {
|
||||
const stringpiece_ssize_type min_size =
|
||||
length_ < x.length_ ? length_ : x.length_;
|
||||
int r = memcmp(ptr_, x.ptr_, static_cast<size_t>(min_size));
|
||||
if (r < 0) return -1;
|
||||
if (r > 0) return 1;
|
||||
if (length_ < x.length_) return -1;
|
||||
if (length_ > x.length_) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
string as_string() const {
|
||||
return ToString();
|
||||
}
|
||||
// We also define ToString() here, since many other string-like
|
||||
// interfaces name the routine that converts to a C++ string
|
||||
// "ToString", and it's confusing to have the method that does that
|
||||
// for a StringPiece be called "as_string()". We also leave the
|
||||
// "as_string()" method defined here for existing code.
|
||||
string ToString() const {
|
||||
if (ptr_ == NULL) return string();
|
||||
return string(data(), static_cast<size_type>(size()));
|
||||
}
|
||||
|
||||
operator string() const {
|
||||
return ToString();
|
||||
}
|
||||
|
||||
void CopyToString(string* target) const;
|
||||
void AppendToString(string* target) const;
|
||||
|
||||
bool starts_with(StringPiece x) const {
|
||||
return (length_ >= x.length_) &&
|
||||
(memcmp(ptr_, x.ptr_, static_cast<size_t>(x.length_)) == 0);
|
||||
}
|
||||
|
||||
bool ends_with(StringPiece x) const {
|
||||
return ((length_ >= x.length_) &&
|
||||
(memcmp(ptr_ + (length_-x.length_), x.ptr_,
|
||||
static_cast<size_t>(x.length_)) == 0));
|
||||
}
|
||||
|
||||
// Checks whether StringPiece starts with x and if so advances the beginning
|
||||
// of it to past the match. It's basically a shortcut for starts_with
|
||||
// followed by remove_prefix.
|
||||
bool Consume(StringPiece x);
|
||||
// Like above but for the end of the string.
|
||||
bool ConsumeFromEnd(StringPiece x);
|
||||
|
||||
// standard STL container boilerplate
|
||||
typedef char value_type;
|
||||
typedef const char* pointer;
|
||||
typedef const char& reference;
|
||||
typedef const char& const_reference;
|
||||
typedef size_t size_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
static const size_type npos;
|
||||
typedef const char* const_iterator;
|
||||
typedef const char* iterator;
|
||||
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
|
||||
typedef std::reverse_iterator<iterator> reverse_iterator;
|
||||
iterator begin() const { return ptr_; }
|
||||
iterator end() const { return ptr_ + length_; }
|
||||
const_reverse_iterator rbegin() const {
|
||||
return const_reverse_iterator(ptr_ + length_);
|
||||
}
|
||||
const_reverse_iterator rend() const {
|
||||
return const_reverse_iterator(ptr_);
|
||||
}
|
||||
stringpiece_ssize_type max_size() const { return length_; }
|
||||
stringpiece_ssize_type capacity() const { return length_; }
|
||||
|
||||
// cpplint.py emits a false positive [build/include_what_you_use]
|
||||
stringpiece_ssize_type copy(char* buf, size_type n, size_type pos = 0) const; // NOLINT
|
||||
|
||||
bool contains(StringPiece s) const;
|
||||
|
||||
stringpiece_ssize_type find(StringPiece s, size_type pos = 0) const;
|
||||
stringpiece_ssize_type find(char c, size_type pos = 0) const;
|
||||
stringpiece_ssize_type rfind(StringPiece s, size_type pos = npos) const;
|
||||
stringpiece_ssize_type rfind(char c, size_type pos = npos) const;
|
||||
|
||||
stringpiece_ssize_type find_first_of(StringPiece s, size_type pos = 0) const;
|
||||
stringpiece_ssize_type find_first_of(char c, size_type pos = 0) const {
|
||||
return find(c, pos);
|
||||
}
|
||||
stringpiece_ssize_type find_first_not_of(StringPiece s,
|
||||
size_type pos = 0) const;
|
||||
stringpiece_ssize_type find_first_not_of(char c, size_type pos = 0) const;
|
||||
stringpiece_ssize_type find_last_of(StringPiece s,
|
||||
size_type pos = npos) const;
|
||||
stringpiece_ssize_type find_last_of(char c, size_type pos = npos) const {
|
||||
return rfind(c, pos);
|
||||
}
|
||||
stringpiece_ssize_type find_last_not_of(StringPiece s,
|
||||
size_type pos = npos) const;
|
||||
stringpiece_ssize_type find_last_not_of(char c, size_type pos = npos) const;
|
||||
|
||||
StringPiece substr(size_type pos, size_type n = npos) const;
|
||||
};
|
||||
|
||||
// This large function is defined inline so that in a fairly common case where
|
||||
// one of the arguments is a literal, the compiler can elide a lot of the
|
||||
// following comparisons.
|
||||
inline bool operator==(StringPiece x, StringPiece y) {
|
||||
stringpiece_ssize_type len = x.size();
|
||||
if (len != y.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return x.data() == y.data() || len <= 0 ||
|
||||
memcmp(x.data(), y.data(), static_cast<size_t>(len)) == 0;
|
||||
}
|
||||
|
||||
inline bool operator!=(StringPiece x, StringPiece y) {
|
||||
return !(x == y);
|
||||
}
|
||||
|
||||
inline bool operator<(StringPiece x, StringPiece y) {
|
||||
const stringpiece_ssize_type min_size =
|
||||
x.size() < y.size() ? x.size() : y.size();
|
||||
const int r = memcmp(x.data(), y.data(), static_cast<size_t>(min_size));
|
||||
return (r < 0) || (r == 0 && x.size() < y.size());
|
||||
}
|
||||
|
||||
inline bool operator>(StringPiece x, StringPiece y) {
|
||||
return y < x;
|
||||
}
|
||||
|
||||
inline bool operator<=(StringPiece x, StringPiece y) {
|
||||
return !(x > y);
|
||||
}
|
||||
|
||||
inline bool operator>=(StringPiece x, StringPiece y) {
|
||||
return !(x < y);
|
||||
}
|
||||
|
||||
// allow StringPiece to be logged
|
||||
extern std::ostream& operator<<(std::ostream& o, StringPiece piece);
|
||||
|
||||
namespace internal {
|
||||
// StringPiece is not a POD and can not be used in an union (pre C++11). We
|
||||
// need a POD version of it.
|
||||
struct StringPiecePod {
|
||||
// Create from a StringPiece.
|
||||
static StringPiecePod CreateFromStringPiece(StringPiece str) {
|
||||
StringPiecePod pod;
|
||||
pod.data_ = str.data();
|
||||
pod.size_ = str.size();
|
||||
return pod;
|
||||
}
|
||||
|
||||
// Cast to StringPiece.
|
||||
operator StringPiece() const { return StringPiece(data_, size_); }
|
||||
|
||||
bool operator==(const char* value) const {
|
||||
return StringPiece(data_, size_) == StringPiece(value);
|
||||
}
|
||||
|
||||
char operator[](stringpiece_ssize_type i) const {
|
||||
assert(0 <= i);
|
||||
assert(i < size_);
|
||||
return data_[i];
|
||||
}
|
||||
|
||||
const char* data() const { return data_; }
|
||||
|
||||
stringpiece_ssize_type size() const {
|
||||
return size_;
|
||||
}
|
||||
|
||||
std::string ToString() const {
|
||||
return std::string(data_, static_cast<size_t>(size_));
|
||||
}
|
||||
private:
|
||||
const char* data_;
|
||||
stringpiece_ssize_type size_;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_START
|
||||
template<> struct hash<StringPiece> {
|
||||
size_t operator()(const StringPiece& s) const {
|
||||
size_t result = 0;
|
||||
for (const char *str = s.data(), *end = str + s.size(); str < end; str++) {
|
||||
result = 5 * result + static_cast<size_t>(*str);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_END
|
||||
|
||||
#endif // STRINGS_STRINGPIECE_H_
|
76
third_party/protobuf-lite/google/protobuf/stubs/stringprintf.h
vendored
Normal file
76
third_party/protobuf-lite/google/protobuf/stubs/stringprintf.h
vendored
Normal file
@ -0,0 +1,76 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2012 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.
|
||||
|
||||
// from google3/base/stringprintf.h
|
||||
//
|
||||
// Printf variants that place their output in a C++ string.
|
||||
//
|
||||
// Usage:
|
||||
// string result = StringPrintf("%d %s\n", 10, "hello");
|
||||
// SStringPrintf(&result, "%d %s\n", 10, "hello");
|
||||
// StringAppendF(&result, "%d %s\n", 20, "there");
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_STUBS_STRINGPRINTF_H
|
||||
#define GOOGLE_PROTOBUF_STUBS_STRINGPRINTF_H
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
// Return a C++ string
|
||||
LIBPROTOBUF_EXPORT extern string StringPrintf(const char* format, ...);
|
||||
|
||||
// Store result into a supplied string and return it
|
||||
LIBPROTOBUF_EXPORT extern const string& SStringPrintf(string* dst, const char* format, ...);
|
||||
|
||||
// Append result to a supplied string
|
||||
LIBPROTOBUF_EXPORT extern void StringAppendF(string* dst, const char* format, ...);
|
||||
|
||||
// Lower-level routine that takes a va_list and appends to a specified
|
||||
// string. All other routines are just convenience wrappers around it.
|
||||
LIBPROTOBUF_EXPORT extern void StringAppendV(string* dst, const char* format, va_list ap);
|
||||
|
||||
// The max arguments supported by StringPrintfVector
|
||||
LIBPROTOBUF_EXPORT extern const int kStringPrintfVectorMaxArgs;
|
||||
|
||||
// You can use this version when all your arguments are strings, but
|
||||
// you don't know how many arguments you'll have at compile time.
|
||||
// StringPrintfVector will LOG(FATAL) if v.size() > kStringPrintfVectorMaxArgs
|
||||
LIBPROTOBUF_EXPORT extern string StringPrintfVector(const char* format, const std::vector<string>& v);
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_STUBS_STRINGPRINTF_H
|
878
third_party/protobuf-lite/google/protobuf/stubs/strutil.h
vendored
Normal file
878
third_party/protobuf-lite/google/protobuf/stubs/strutil.h
vendored
Normal file
@ -0,0 +1,878 @@
|
||||
// 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.
|
||||
|
||||
// from google3/strings/strutil.h
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_STUBS_STRUTIL_H__
|
||||
#define GOOGLE_PROTOBUF_STUBS_STRUTIL_H__
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <vector>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/stringpiece.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define strtoll _strtoi64
|
||||
#define strtoull _strtoui64
|
||||
#elif defined(__DECCXX) && defined(__osf__)
|
||||
// HP C++ on Tru64 does not have strtoll, but strtol is already 64-bit.
|
||||
#define strtoll strtol
|
||||
#define strtoull strtoul
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// ascii_isalnum()
|
||||
// Check if an ASCII character is alphanumeric. We can't use ctype's
|
||||
// isalnum() because it is affected by locale. This function is applied
|
||||
// to identifiers in the protocol buffer language, not to natural-language
|
||||
// strings, so locale should not be taken into account.
|
||||
// ascii_isdigit()
|
||||
// Like above, but only accepts digits.
|
||||
// ascii_isspace()
|
||||
// Check if the character is a space character.
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline bool ascii_isalnum(char c) {
|
||||
return ('a' <= c && c <= 'z') ||
|
||||
('A' <= c && c <= 'Z') ||
|
||||
('0' <= c && c <= '9');
|
||||
}
|
||||
|
||||
inline bool ascii_isdigit(char c) {
|
||||
return ('0' <= c && c <= '9');
|
||||
}
|
||||
|
||||
inline bool ascii_isspace(char c) {
|
||||
return c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\f' ||
|
||||
c == '\r';
|
||||
}
|
||||
|
||||
inline bool ascii_isupper(char c) {
|
||||
return c >= 'A' && c <= 'Z';
|
||||
}
|
||||
|
||||
inline bool ascii_islower(char c) {
|
||||
return c >= 'a' && c <= 'z';
|
||||
}
|
||||
|
||||
inline char ascii_toupper(char c) {
|
||||
return ascii_islower(c) ? c - ('a' - 'A') : c;
|
||||
}
|
||||
|
||||
inline char ascii_tolower(char c) {
|
||||
return ascii_isupper(c) ? c + ('a' - 'A') : c;
|
||||
}
|
||||
|
||||
inline int hex_digit_to_int(char c) {
|
||||
/* Assume ASCII. */
|
||||
int x = static_cast<unsigned char>(c);
|
||||
if (x > '9') {
|
||||
x += 9;
|
||||
}
|
||||
return x & 0xf;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// HasPrefixString()
|
||||
// Check if a string begins with a given prefix.
|
||||
// StripPrefixString()
|
||||
// Given a string and a putative prefix, returns the string minus the
|
||||
// prefix string if the prefix matches, otherwise the original
|
||||
// string.
|
||||
// ----------------------------------------------------------------------
|
||||
inline bool HasPrefixString(const string& str,
|
||||
const string& prefix) {
|
||||
return str.size() >= prefix.size() &&
|
||||
str.compare(0, prefix.size(), prefix) == 0;
|
||||
}
|
||||
|
||||
inline string StripPrefixString(const string& str, const string& prefix) {
|
||||
if (HasPrefixString(str, prefix)) {
|
||||
return str.substr(prefix.size());
|
||||
} else {
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// HasSuffixString()
|
||||
// Return true if str ends in suffix.
|
||||
// StripSuffixString()
|
||||
// Given a string and a putative suffix, returns the string minus the
|
||||
// suffix string if the suffix matches, otherwise the original
|
||||
// string.
|
||||
// ----------------------------------------------------------------------
|
||||
inline bool HasSuffixString(const string& str,
|
||||
const string& suffix) {
|
||||
return str.size() >= suffix.size() &&
|
||||
str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
|
||||
}
|
||||
|
||||
inline string StripSuffixString(const string& str, const string& suffix) {
|
||||
if (HasSuffixString(str, suffix)) {
|
||||
return str.substr(0, str.size() - suffix.size());
|
||||
} else {
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// ReplaceCharacters
|
||||
// Replaces any occurrence of the character 'remove' (or the characters
|
||||
// in 'remove') with the character 'replacewith'.
|
||||
// Good for keeping html characters or protocol characters (\t) out
|
||||
// of places where they might cause a problem.
|
||||
// StripWhitespace
|
||||
// Removes whitespaces from both ends of the given string.
|
||||
// ----------------------------------------------------------------------
|
||||
LIBPROTOBUF_EXPORT void ReplaceCharacters(string* s, const char* remove,
|
||||
char replacewith);
|
||||
LIBPROTOBUF_EXPORT void StripString(string* s, const char* remove,
|
||||
char replacewith);
|
||||
|
||||
LIBPROTOBUF_EXPORT void StripWhitespace(string* s);
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// LowerString()
|
||||
// UpperString()
|
||||
// ToUpper()
|
||||
// Convert the characters in "s" to lowercase or uppercase. ASCII-only:
|
||||
// these functions intentionally ignore locale because they are applied to
|
||||
// identifiers used in the Protocol Buffer language, not to natural-language
|
||||
// strings.
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline void LowerString(string * s) {
|
||||
string::iterator end = s->end();
|
||||
for (string::iterator i = s->begin(); i != end; ++i) {
|
||||
// tolower() changes based on locale. We don't want this!
|
||||
if ('A' <= *i && *i <= 'Z') *i += 'a' - 'A';
|
||||
}
|
||||
}
|
||||
|
||||
inline void UpperString(string * s) {
|
||||
string::iterator end = s->end();
|
||||
for (string::iterator i = s->begin(); i != end; ++i) {
|
||||
// toupper() changes based on locale. We don't want this!
|
||||
if ('a' <= *i && *i <= 'z') *i += 'A' - 'a';
|
||||
}
|
||||
}
|
||||
|
||||
inline string ToUpper(const string& s) {
|
||||
string out = s;
|
||||
UpperString(&out);
|
||||
return out;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// StringReplace()
|
||||
// Give me a string and two patterns "old" and "new", and I replace
|
||||
// the first instance of "old" in the string with "new", if it
|
||||
// exists. RETURN a new string, regardless of whether the replacement
|
||||
// happened or not.
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
LIBPROTOBUF_EXPORT string StringReplace(const string& s, const string& oldsub,
|
||||
const string& newsub, bool replace_all);
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// SplitStringUsing()
|
||||
// Split a string using a character delimiter. Append the components
|
||||
// to 'result'. If there are consecutive delimiters, this function skips
|
||||
// over all of them.
|
||||
// ----------------------------------------------------------------------
|
||||
LIBPROTOBUF_EXPORT void SplitStringUsing(const string& full, const char* delim,
|
||||
std::vector<string>* res);
|
||||
|
||||
// Split a string using one or more byte delimiters, presented
|
||||
// as a nul-terminated c string. Append the components to 'result'.
|
||||
// If there are consecutive delimiters, this function will return
|
||||
// corresponding empty strings. If you want to drop the empty
|
||||
// strings, try SplitStringUsing().
|
||||
//
|
||||
// If "full" is the empty string, yields an empty string as the only value.
|
||||
// ----------------------------------------------------------------------
|
||||
LIBPROTOBUF_EXPORT void SplitStringAllowEmpty(const string& full,
|
||||
const char* delim,
|
||||
std::vector<string>* result);
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Split()
|
||||
// Split a string using a character delimiter.
|
||||
// ----------------------------------------------------------------------
|
||||
inline std::vector<string> Split(
|
||||
const string& full, const char* delim, bool skip_empty = true) {
|
||||
std::vector<string> result;
|
||||
if (skip_empty) {
|
||||
SplitStringUsing(full, delim, &result);
|
||||
} else {
|
||||
SplitStringAllowEmpty(full, delim, &result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// JoinStrings()
|
||||
// These methods concatenate a vector of strings into a C++ string, using
|
||||
// the C-string "delim" as a separator between components. There are two
|
||||
// flavors of the function, one flavor returns the concatenated string,
|
||||
// another takes a pointer to the target string. In the latter case the
|
||||
// target string is cleared and overwritten.
|
||||
// ----------------------------------------------------------------------
|
||||
LIBPROTOBUF_EXPORT void JoinStrings(const std::vector<string>& components,
|
||||
const char* delim, string* result);
|
||||
|
||||
inline string JoinStrings(const std::vector<string>& components,
|
||||
const char* delim) {
|
||||
string result;
|
||||
JoinStrings(components, delim, &result);
|
||||
return result;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// UnescapeCEscapeSequences()
|
||||
// Copies "source" to "dest", rewriting C-style escape sequences
|
||||
// -- '\n', '\r', '\\', '\ooo', etc -- to their ASCII
|
||||
// equivalents. "dest" must be sufficiently large to hold all
|
||||
// the characters in the rewritten string (i.e. at least as large
|
||||
// as strlen(source) + 1 should be safe, since the replacements
|
||||
// are always shorter than the original escaped sequences). It's
|
||||
// safe for source and dest to be the same. RETURNS the length
|
||||
// of dest.
|
||||
//
|
||||
// It allows hex sequences \xhh, or generally \xhhhhh with an
|
||||
// arbitrary number of hex digits, but all of them together must
|
||||
// specify a value of a single byte (e.g. \x0045 is equivalent
|
||||
// to \x45, and \x1234 is erroneous).
|
||||
//
|
||||
// It also allows escape sequences of the form \uhhhh (exactly four
|
||||
// hex digits, upper or lower case) or \Uhhhhhhhh (exactly eight
|
||||
// hex digits, upper or lower case) to specify a Unicode code
|
||||
// point. The dest array will contain the UTF8-encoded version of
|
||||
// that code-point (e.g., if source contains \u2019, then dest will
|
||||
// contain the three bytes 0xE2, 0x80, and 0x99).
|
||||
//
|
||||
// Errors: In the first form of the call, errors are reported with
|
||||
// LOG(ERROR). The same is true for the second form of the call if
|
||||
// the pointer to the string std::vector is NULL; otherwise, error
|
||||
// messages are stored in the std::vector. In either case, the effect on
|
||||
// the dest array is not defined, but rest of the source will be
|
||||
// processed.
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
LIBPROTOBUF_EXPORT int UnescapeCEscapeSequences(const char* source, char* dest);
|
||||
LIBPROTOBUF_EXPORT int UnescapeCEscapeSequences(const char* source, char* dest,
|
||||
std::vector<string> *errors);
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// UnescapeCEscapeString()
|
||||
// This does the same thing as UnescapeCEscapeSequences, but creates
|
||||
// a new string. The caller does not need to worry about allocating
|
||||
// a dest buffer. This should be used for non performance critical
|
||||
// tasks such as printing debug messages. It is safe for src and dest
|
||||
// to be the same.
|
||||
//
|
||||
// The second call stores its errors in a supplied string vector.
|
||||
// If the string vector pointer is NULL, it reports the errors with LOG().
|
||||
//
|
||||
// In the first and second calls, the length of dest is returned. In the
|
||||
// the third call, the new string is returned.
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
LIBPROTOBUF_EXPORT int UnescapeCEscapeString(const string& src, string* dest);
|
||||
LIBPROTOBUF_EXPORT int UnescapeCEscapeString(const string& src, string* dest,
|
||||
std::vector<string> *errors);
|
||||
LIBPROTOBUF_EXPORT string UnescapeCEscapeString(const string& src);
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// CEscape()
|
||||
// Escapes 'src' using C-style escape sequences and returns the resulting
|
||||
// string.
|
||||
//
|
||||
// Escaped chars: \n, \r, \t, ", ', \, and !isprint().
|
||||
// ----------------------------------------------------------------------
|
||||
LIBPROTOBUF_EXPORT string CEscape(const string& src);
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// CEscapeAndAppend()
|
||||
// Escapes 'src' using C-style escape sequences, and appends the escaped
|
||||
// string to 'dest'.
|
||||
// ----------------------------------------------------------------------
|
||||
LIBPROTOBUF_EXPORT void CEscapeAndAppend(StringPiece src, string* dest);
|
||||
|
||||
namespace strings {
|
||||
// Like CEscape() but does not escape bytes with the upper bit set.
|
||||
LIBPROTOBUF_EXPORT string Utf8SafeCEscape(const string& src);
|
||||
|
||||
// Like CEscape() but uses hex (\x) escapes instead of octals.
|
||||
LIBPROTOBUF_EXPORT string CHexEscape(const string& src);
|
||||
} // namespace strings
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// strto32()
|
||||
// strtou32()
|
||||
// strto64()
|
||||
// strtou64()
|
||||
// Architecture-neutral plug compatible replacements for strtol() and
|
||||
// strtoul(). Long's have different lengths on ILP-32 and LP-64
|
||||
// platforms, so using these is safer, from the point of view of
|
||||
// overflow behavior, than using the standard libc functions.
|
||||
// ----------------------------------------------------------------------
|
||||
LIBPROTOBUF_EXPORT int32 strto32_adaptor(const char *nptr, char **endptr,
|
||||
int base);
|
||||
LIBPROTOBUF_EXPORT uint32 strtou32_adaptor(const char *nptr, char **endptr,
|
||||
int base);
|
||||
|
||||
inline int32 strto32(const char *nptr, char **endptr, int base) {
|
||||
if (sizeof(int32) == sizeof(long))
|
||||
return strtol(nptr, endptr, base);
|
||||
else
|
||||
return strto32_adaptor(nptr, endptr, base);
|
||||
}
|
||||
|
||||
inline uint32 strtou32(const char *nptr, char **endptr, int base) {
|
||||
if (sizeof(uint32) == sizeof(unsigned long))
|
||||
return strtoul(nptr, endptr, base);
|
||||
else
|
||||
return strtou32_adaptor(nptr, endptr, base);
|
||||
}
|
||||
|
||||
// For now, long long is 64-bit on all the platforms we care about, so these
|
||||
// functions can simply pass the call to strto[u]ll.
|
||||
inline int64 strto64(const char *nptr, char **endptr, int base) {
|
||||
GOOGLE_COMPILE_ASSERT(sizeof(int64) == sizeof(long long),
|
||||
sizeof_int64_is_not_sizeof_long_long);
|
||||
return strtoll(nptr, endptr, base);
|
||||
}
|
||||
|
||||
inline uint64 strtou64(const char *nptr, char **endptr, int base) {
|
||||
GOOGLE_COMPILE_ASSERT(sizeof(uint64) == sizeof(unsigned long long),
|
||||
sizeof_uint64_is_not_sizeof_long_long);
|
||||
return strtoull(nptr, endptr, base);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// safe_strtob()
|
||||
// safe_strto32()
|
||||
// safe_strtou32()
|
||||
// safe_strto64()
|
||||
// safe_strtou64()
|
||||
// safe_strtof()
|
||||
// safe_strtod()
|
||||
// ----------------------------------------------------------------------
|
||||
LIBPROTOBUF_EXPORT bool safe_strtob(StringPiece str, bool* value);
|
||||
|
||||
LIBPROTOBUF_EXPORT bool safe_strto32(const string& str, int32* value);
|
||||
LIBPROTOBUF_EXPORT bool safe_strtou32(const string& str, uint32* value);
|
||||
inline bool safe_strto32(const char* str, int32* value) {
|
||||
return safe_strto32(string(str), value);
|
||||
}
|
||||
inline bool safe_strto32(StringPiece str, int32* value) {
|
||||
return safe_strto32(str.ToString(), value);
|
||||
}
|
||||
inline bool safe_strtou32(const char* str, uint32* value) {
|
||||
return safe_strtou32(string(str), value);
|
||||
}
|
||||
inline bool safe_strtou32(StringPiece str, uint32* value) {
|
||||
return safe_strtou32(str.ToString(), value);
|
||||
}
|
||||
|
||||
LIBPROTOBUF_EXPORT bool safe_strto64(const string& str, int64* value);
|
||||
LIBPROTOBUF_EXPORT bool safe_strtou64(const string& str, uint64* value);
|
||||
inline bool safe_strto64(const char* str, int64* value) {
|
||||
return safe_strto64(string(str), value);
|
||||
}
|
||||
inline bool safe_strto64(StringPiece str, int64* value) {
|
||||
return safe_strto64(str.ToString(), value);
|
||||
}
|
||||
inline bool safe_strtou64(const char* str, uint64* value) {
|
||||
return safe_strtou64(string(str), value);
|
||||
}
|
||||
inline bool safe_strtou64(StringPiece str, uint64* value) {
|
||||
return safe_strtou64(str.ToString(), value);
|
||||
}
|
||||
|
||||
LIBPROTOBUF_EXPORT bool safe_strtof(const char* str, float* value);
|
||||
LIBPROTOBUF_EXPORT bool safe_strtod(const char* str, double* value);
|
||||
inline bool safe_strtof(const string& str, float* value) {
|
||||
return safe_strtof(str.c_str(), value);
|
||||
}
|
||||
inline bool safe_strtod(const string& str, double* value) {
|
||||
return safe_strtod(str.c_str(), value);
|
||||
}
|
||||
inline bool safe_strtof(StringPiece str, float* value) {
|
||||
return safe_strtof(str.ToString(), value);
|
||||
}
|
||||
inline bool safe_strtod(StringPiece str, double* value) {
|
||||
return safe_strtod(str.ToString(), value);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// FastIntToBuffer()
|
||||
// FastHexToBuffer()
|
||||
// FastHex64ToBuffer()
|
||||
// FastHex32ToBuffer()
|
||||
// FastTimeToBuffer()
|
||||
// These are intended for speed. FastIntToBuffer() assumes the
|
||||
// integer is non-negative. FastHexToBuffer() puts output in
|
||||
// hex rather than decimal. FastTimeToBuffer() puts the output
|
||||
// into RFC822 format.
|
||||
//
|
||||
// FastHex64ToBuffer() puts a 64-bit unsigned value in hex-format,
|
||||
// padded to exactly 16 bytes (plus one byte for '\0')
|
||||
//
|
||||
// FastHex32ToBuffer() puts a 32-bit unsigned value in hex-format,
|
||||
// padded to exactly 8 bytes (plus one byte for '\0')
|
||||
//
|
||||
// All functions take the output buffer as an arg.
|
||||
// They all return a pointer to the beginning of the output,
|
||||
// which may not be the beginning of the input buffer.
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
// Suggested buffer size for FastToBuffer functions. Also works with
|
||||
// DoubleToBuffer() and FloatToBuffer().
|
||||
static const int kFastToBufferSize = 32;
|
||||
|
||||
LIBPROTOBUF_EXPORT char* FastInt32ToBuffer(int32 i, char* buffer);
|
||||
LIBPROTOBUF_EXPORT char* FastInt64ToBuffer(int64 i, char* buffer);
|
||||
char* FastUInt32ToBuffer(uint32 i, char* buffer); // inline below
|
||||
char* FastUInt64ToBuffer(uint64 i, char* buffer); // inline below
|
||||
LIBPROTOBUF_EXPORT char* FastHexToBuffer(int i, char* buffer);
|
||||
LIBPROTOBUF_EXPORT char* FastHex64ToBuffer(uint64 i, char* buffer);
|
||||
LIBPROTOBUF_EXPORT char* FastHex32ToBuffer(uint32 i, char* buffer);
|
||||
|
||||
// at least 22 bytes long
|
||||
inline char* FastIntToBuffer(int i, char* buffer) {
|
||||
return (sizeof(i) == 4 ?
|
||||
FastInt32ToBuffer(i, buffer) : FastInt64ToBuffer(i, buffer));
|
||||
}
|
||||
inline char* FastUIntToBuffer(unsigned int i, char* buffer) {
|
||||
return (sizeof(i) == 4 ?
|
||||
FastUInt32ToBuffer(i, buffer) : FastUInt64ToBuffer(i, buffer));
|
||||
}
|
||||
inline char* FastLongToBuffer(long i, char* buffer) {
|
||||
return (sizeof(i) == 4 ?
|
||||
FastInt32ToBuffer(i, buffer) : FastInt64ToBuffer(i, buffer));
|
||||
}
|
||||
inline char* FastULongToBuffer(unsigned long i, char* buffer) {
|
||||
return (sizeof(i) == 4 ?
|
||||
FastUInt32ToBuffer(i, buffer) : FastUInt64ToBuffer(i, buffer));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// FastInt32ToBufferLeft()
|
||||
// FastUInt32ToBufferLeft()
|
||||
// FastInt64ToBufferLeft()
|
||||
// FastUInt64ToBufferLeft()
|
||||
//
|
||||
// Like the Fast*ToBuffer() functions above, these are intended for speed.
|
||||
// Unlike the Fast*ToBuffer() functions, however, these functions write
|
||||
// their output to the beginning of the buffer (hence the name, as the
|
||||
// output is left-aligned). The caller is responsible for ensuring that
|
||||
// the buffer has enough space to hold the output.
|
||||
//
|
||||
// Returns a pointer to the end of the string (i.e. the null character
|
||||
// terminating the string).
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
LIBPROTOBUF_EXPORT char* FastInt32ToBufferLeft(int32 i, char* buffer);
|
||||
LIBPROTOBUF_EXPORT char* FastUInt32ToBufferLeft(uint32 i, char* buffer);
|
||||
LIBPROTOBUF_EXPORT char* FastInt64ToBufferLeft(int64 i, char* buffer);
|
||||
LIBPROTOBUF_EXPORT char* FastUInt64ToBufferLeft(uint64 i, char* buffer);
|
||||
|
||||
// Just define these in terms of the above.
|
||||
inline char* FastUInt32ToBuffer(uint32 i, char* buffer) {
|
||||
FastUInt32ToBufferLeft(i, buffer);
|
||||
return buffer;
|
||||
}
|
||||
inline char* FastUInt64ToBuffer(uint64 i, char* buffer) {
|
||||
FastUInt64ToBufferLeft(i, buffer);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
inline string SimpleBtoa(bool value) {
|
||||
return value ? "true" : "false";
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// SimpleItoa()
|
||||
// Description: converts an integer to a string.
|
||||
//
|
||||
// Return value: string
|
||||
// ----------------------------------------------------------------------
|
||||
LIBPROTOBUF_EXPORT string SimpleItoa(int i);
|
||||
LIBPROTOBUF_EXPORT string SimpleItoa(unsigned int i);
|
||||
LIBPROTOBUF_EXPORT string SimpleItoa(long i);
|
||||
LIBPROTOBUF_EXPORT string SimpleItoa(unsigned long i);
|
||||
LIBPROTOBUF_EXPORT string SimpleItoa(long long i);
|
||||
LIBPROTOBUF_EXPORT string SimpleItoa(unsigned long long i);
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// SimpleDtoa()
|
||||
// SimpleFtoa()
|
||||
// DoubleToBuffer()
|
||||
// FloatToBuffer()
|
||||
// Description: converts a double or float to a string which, if
|
||||
// passed to NoLocaleStrtod(), will produce the exact same original double
|
||||
// (except in case of NaN; all NaNs are considered the same value).
|
||||
// We try to keep the string short but it's not guaranteed to be as
|
||||
// short as possible.
|
||||
//
|
||||
// DoubleToBuffer() and FloatToBuffer() write the text to the given
|
||||
// buffer and return it. The buffer must be at least
|
||||
// kDoubleToBufferSize bytes for doubles and kFloatToBufferSize
|
||||
// bytes for floats. kFastToBufferSize is also guaranteed to be large
|
||||
// enough to hold either.
|
||||
//
|
||||
// Return value: string
|
||||
// ----------------------------------------------------------------------
|
||||
LIBPROTOBUF_EXPORT string SimpleDtoa(double value);
|
||||
LIBPROTOBUF_EXPORT string SimpleFtoa(float value);
|
||||
|
||||
LIBPROTOBUF_EXPORT char* DoubleToBuffer(double i, char* buffer);
|
||||
LIBPROTOBUF_EXPORT char* FloatToBuffer(float i, char* buffer);
|
||||
|
||||
// In practice, doubles should never need more than 24 bytes and floats
|
||||
// should never need more than 14 (including null terminators), but we
|
||||
// overestimate to be safe.
|
||||
static const int kDoubleToBufferSize = 32;
|
||||
static const int kFloatToBufferSize = 24;
|
||||
|
||||
namespace strings {
|
||||
|
||||
enum PadSpec {
|
||||
NO_PAD = 1,
|
||||
ZERO_PAD_2,
|
||||
ZERO_PAD_3,
|
||||
ZERO_PAD_4,
|
||||
ZERO_PAD_5,
|
||||
ZERO_PAD_6,
|
||||
ZERO_PAD_7,
|
||||
ZERO_PAD_8,
|
||||
ZERO_PAD_9,
|
||||
ZERO_PAD_10,
|
||||
ZERO_PAD_11,
|
||||
ZERO_PAD_12,
|
||||
ZERO_PAD_13,
|
||||
ZERO_PAD_14,
|
||||
ZERO_PAD_15,
|
||||
ZERO_PAD_16,
|
||||
};
|
||||
|
||||
struct Hex {
|
||||
uint64 value;
|
||||
enum PadSpec spec;
|
||||
template <class Int>
|
||||
explicit Hex(Int v, PadSpec s = NO_PAD)
|
||||
: spec(s) {
|
||||
// Prevent sign-extension by casting integers to
|
||||
// their unsigned counterparts.
|
||||
#ifdef LANG_CXX11
|
||||
static_assert(
|
||||
sizeof(v) == 1 || sizeof(v) == 2 || sizeof(v) == 4 || sizeof(v) == 8,
|
||||
"Unknown integer type");
|
||||
#endif
|
||||
value = sizeof(v) == 1 ? static_cast<uint8>(v)
|
||||
: sizeof(v) == 2 ? static_cast<uint16>(v)
|
||||
: sizeof(v) == 4 ? static_cast<uint32>(v)
|
||||
: static_cast<uint64>(v);
|
||||
}
|
||||
};
|
||||
|
||||
struct LIBPROTOBUF_EXPORT AlphaNum {
|
||||
const char *piece_data_; // move these to string_ref eventually
|
||||
size_t piece_size_; // move these to string_ref eventually
|
||||
|
||||
char digits[kFastToBufferSize];
|
||||
|
||||
// No bool ctor -- bools convert to an integral type.
|
||||
// A bool ctor would also convert incoming pointers (bletch).
|
||||
|
||||
AlphaNum(int32 i32)
|
||||
: piece_data_(digits),
|
||||
piece_size_(FastInt32ToBufferLeft(i32, digits) - &digits[0]) {}
|
||||
AlphaNum(uint32 u32)
|
||||
: piece_data_(digits),
|
||||
piece_size_(FastUInt32ToBufferLeft(u32, digits) - &digits[0]) {}
|
||||
AlphaNum(int64 i64)
|
||||
: piece_data_(digits),
|
||||
piece_size_(FastInt64ToBufferLeft(i64, digits) - &digits[0]) {}
|
||||
AlphaNum(uint64 u64)
|
||||
: piece_data_(digits),
|
||||
piece_size_(FastUInt64ToBufferLeft(u64, digits) - &digits[0]) {}
|
||||
|
||||
AlphaNum(float f)
|
||||
: piece_data_(digits), piece_size_(strlen(FloatToBuffer(f, digits))) {}
|
||||
AlphaNum(double f)
|
||||
: piece_data_(digits), piece_size_(strlen(DoubleToBuffer(f, digits))) {}
|
||||
|
||||
AlphaNum(Hex hex);
|
||||
|
||||
AlphaNum(const char* c_str)
|
||||
: piece_data_(c_str), piece_size_(strlen(c_str)) {}
|
||||
// TODO: Add a string_ref constructor, eventually
|
||||
// AlphaNum(const StringPiece &pc) : piece(pc) {}
|
||||
|
||||
AlphaNum(const string& str)
|
||||
: piece_data_(str.data()), piece_size_(str.size()) {}
|
||||
|
||||
AlphaNum(StringPiece str)
|
||||
: piece_data_(str.data()), piece_size_(str.size()) {}
|
||||
|
||||
AlphaNum(internal::StringPiecePod str)
|
||||
: piece_data_(str.data()), piece_size_(str.size()) {}
|
||||
|
||||
size_t size() const { return piece_size_; }
|
||||
const char *data() const { return piece_data_; }
|
||||
|
||||
private:
|
||||
// Use ":" not ':'
|
||||
AlphaNum(char c); // NOLINT(runtime/explicit)
|
||||
|
||||
// Disallow copy and assign.
|
||||
AlphaNum(const AlphaNum&);
|
||||
void operator=(const AlphaNum&);
|
||||
};
|
||||
|
||||
} // namespace strings
|
||||
|
||||
using strings::AlphaNum;
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// StrCat()
|
||||
// This merges the given strings or numbers, with no delimiter. This
|
||||
// is designed to be the fastest possible way to construct a string out
|
||||
// of a mix of raw C strings, strings, bool values,
|
||||
// and numeric values.
|
||||
//
|
||||
// Don't use this for user-visible strings. The localization process
|
||||
// works poorly on strings built up out of fragments.
|
||||
//
|
||||
// For clarity and performance, don't use StrCat when appending to a
|
||||
// string. In particular, avoid using any of these (anti-)patterns:
|
||||
// str.append(StrCat(...)
|
||||
// str += StrCat(...)
|
||||
// str = StrCat(str, ...)
|
||||
// where the last is the worse, with the potential to change a loop
|
||||
// from a linear time operation with O(1) dynamic allocations into a
|
||||
// quadratic time operation with O(n) dynamic allocations. StrAppend
|
||||
// is a better choice than any of the above, subject to the restriction
|
||||
// of StrAppend(&str, a, b, c, ...) that none of the a, b, c, ... may
|
||||
// be a reference into str.
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
LIBPROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b);
|
||||
LIBPROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b,
|
||||
const AlphaNum& c);
|
||||
LIBPROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b,
|
||||
const AlphaNum& c, const AlphaNum& d);
|
||||
LIBPROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b,
|
||||
const AlphaNum& c, const AlphaNum& d,
|
||||
const AlphaNum& e);
|
||||
LIBPROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b,
|
||||
const AlphaNum& c, const AlphaNum& d,
|
||||
const AlphaNum& e, const AlphaNum& f);
|
||||
LIBPROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b,
|
||||
const AlphaNum& c, const AlphaNum& d,
|
||||
const AlphaNum& e, const AlphaNum& f,
|
||||
const AlphaNum& g);
|
||||
LIBPROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b,
|
||||
const AlphaNum& c, const AlphaNum& d,
|
||||
const AlphaNum& e, const AlphaNum& f,
|
||||
const AlphaNum& g, const AlphaNum& h);
|
||||
LIBPROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b,
|
||||
const AlphaNum& c, const AlphaNum& d,
|
||||
const AlphaNum& e, const AlphaNum& f,
|
||||
const AlphaNum& g, const AlphaNum& h,
|
||||
const AlphaNum& i);
|
||||
|
||||
inline string StrCat(const AlphaNum& a) { return string(a.data(), a.size()); }
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// StrAppend()
|
||||
// Same as above, but adds the output to the given string.
|
||||
// WARNING: For speed, StrAppend does not try to check each of its input
|
||||
// arguments to be sure that they are not a subset of the string being
|
||||
// appended to. That is, while this will work:
|
||||
//
|
||||
// string s = "foo";
|
||||
// s += s;
|
||||
//
|
||||
// This will not (necessarily) work:
|
||||
//
|
||||
// string s = "foo";
|
||||
// StrAppend(&s, s);
|
||||
//
|
||||
// Note: while StrCat supports appending up to 9 arguments, StrAppend
|
||||
// is currently limited to 4. That's rarely an issue except when
|
||||
// automatically transforming StrCat to StrAppend, and can easily be
|
||||
// worked around as consecutive calls to StrAppend are quite efficient.
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
LIBPROTOBUF_EXPORT void StrAppend(string* dest, const AlphaNum& a);
|
||||
LIBPROTOBUF_EXPORT void StrAppend(string* dest, const AlphaNum& a,
|
||||
const AlphaNum& b);
|
||||
LIBPROTOBUF_EXPORT void StrAppend(string* dest, const AlphaNum& a,
|
||||
const AlphaNum& b, const AlphaNum& c);
|
||||
LIBPROTOBUF_EXPORT void StrAppend(string* dest, const AlphaNum& a,
|
||||
const AlphaNum& b, const AlphaNum& c,
|
||||
const AlphaNum& d);
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Join()
|
||||
// These methods concatenate a range of components into a C++ string, using
|
||||
// the C-string "delim" as a separator between components.
|
||||
// ----------------------------------------------------------------------
|
||||
template <typename Iterator>
|
||||
void Join(Iterator start, Iterator end,
|
||||
const char* delim, string* result) {
|
||||
for (Iterator it = start; it != end; ++it) {
|
||||
if (it != start) {
|
||||
result->append(delim);
|
||||
}
|
||||
StrAppend(result, *it);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Range>
|
||||
string Join(const Range& components,
|
||||
const char* delim) {
|
||||
string result;
|
||||
Join(components.begin(), components.end(), delim, &result);
|
||||
return result;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// ToHex()
|
||||
// Return a lower-case hex string representation of the given integer.
|
||||
// ----------------------------------------------------------------------
|
||||
LIBPROTOBUF_EXPORT string ToHex(uint64 num);
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// GlobalReplaceSubstring()
|
||||
// Replaces all instances of a substring in a string. Does nothing
|
||||
// if 'substring' is empty. Returns the number of replacements.
|
||||
//
|
||||
// NOTE: The string pieces must not overlap s.
|
||||
// ----------------------------------------------------------------------
|
||||
LIBPROTOBUF_EXPORT int GlobalReplaceSubstring(const string& substring,
|
||||
const string& replacement,
|
||||
string* s);
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Base64Unescape()
|
||||
// Converts "src" which is encoded in Base64 to its binary equivalent and
|
||||
// writes it to "dest". If src contains invalid characters, dest is cleared
|
||||
// and the function returns false. Returns true on success.
|
||||
// ----------------------------------------------------------------------
|
||||
LIBPROTOBUF_EXPORT bool Base64Unescape(StringPiece src, string* dest);
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// WebSafeBase64Unescape()
|
||||
// This is a variation of Base64Unescape which uses '-' instead of '+', and
|
||||
// '_' instead of '/'. src is not null terminated, instead specify len. I
|
||||
// recommend that slen<szdest, but we honor szdest anyway.
|
||||
// RETURNS the length of dest, or -1 if src contains invalid chars.
|
||||
|
||||
// The variation that stores into a string clears the string first, and
|
||||
// returns false (with dest empty) if src contains invalid chars; for
|
||||
// this version src and dest must be different strings.
|
||||
// ----------------------------------------------------------------------
|
||||
LIBPROTOBUF_EXPORT int WebSafeBase64Unescape(const char* src, int slen,
|
||||
char* dest, int szdest);
|
||||
LIBPROTOBUF_EXPORT bool WebSafeBase64Unescape(StringPiece src, string* dest);
|
||||
|
||||
// Return the length to use for the output buffer given to the base64 escape
|
||||
// routines. Make sure to use the same value for do_padding in both.
|
||||
// This function may return incorrect results if given input_len values that
|
||||
// are extremely high, which should happen rarely.
|
||||
LIBPROTOBUF_EXPORT int CalculateBase64EscapedLen(int input_len,
|
||||
bool do_padding);
|
||||
// Use this version when calling Base64Escape without a do_padding arg.
|
||||
LIBPROTOBUF_EXPORT int CalculateBase64EscapedLen(int input_len);
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Base64Escape()
|
||||
// WebSafeBase64Escape()
|
||||
// Encode "src" to "dest" using base64 encoding.
|
||||
// src is not null terminated, instead specify len.
|
||||
// 'dest' should have at least CalculateBase64EscapedLen() length.
|
||||
// RETURNS the length of dest.
|
||||
// The WebSafe variation use '-' instead of '+' and '_' instead of '/'
|
||||
// so that we can place the out in the URL or cookies without having
|
||||
// to escape them. It also has an extra parameter "do_padding",
|
||||
// which when set to false will prevent padding with "=".
|
||||
// ----------------------------------------------------------------------
|
||||
LIBPROTOBUF_EXPORT int Base64Escape(const unsigned char* src, int slen,
|
||||
char* dest, int szdest);
|
||||
LIBPROTOBUF_EXPORT int WebSafeBase64Escape(
|
||||
const unsigned char* src, int slen, char* dest,
|
||||
int szdest, bool do_padding);
|
||||
// Encode src into dest with padding.
|
||||
LIBPROTOBUF_EXPORT void Base64Escape(StringPiece src, string* dest);
|
||||
// Encode src into dest web-safely without padding.
|
||||
LIBPROTOBUF_EXPORT void WebSafeBase64Escape(StringPiece src, string* dest);
|
||||
// Encode src into dest web-safely with padding.
|
||||
LIBPROTOBUF_EXPORT void WebSafeBase64EscapeWithPadding(StringPiece src,
|
||||
string* dest);
|
||||
|
||||
LIBPROTOBUF_EXPORT void Base64Escape(const unsigned char* src, int szsrc,
|
||||
string* dest, bool do_padding);
|
||||
LIBPROTOBUF_EXPORT void WebSafeBase64Escape(const unsigned char* src, int szsrc,
|
||||
string* dest, bool do_padding);
|
||||
|
||||
inline bool IsValidCodePoint(uint32 code_point) {
|
||||
return code_point < 0xD800 ||
|
||||
(code_point >= 0xE000 && code_point <= 0x10FFFF);
|
||||
}
|
||||
|
||||
static const int UTFmax = 4;
|
||||
// ----------------------------------------------------------------------
|
||||
// EncodeAsUTF8Char()
|
||||
// Helper to append a Unicode code point to a string as UTF8, without bringing
|
||||
// in any external dependencies. The output buffer must be as least 4 bytes
|
||||
// large.
|
||||
// ----------------------------------------------------------------------
|
||||
LIBPROTOBUF_EXPORT int EncodeAsUTF8Char(uint32 code_point, char* output);
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// UTF8FirstLetterNumBytes()
|
||||
// Length of the first UTF-8 character.
|
||||
// ----------------------------------------------------------------------
|
||||
LIBPROTOBUF_EXPORT int UTF8FirstLetterNumBytes(const char* src, int len);
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_STUBS_STRUTIL_H__
|
75
third_party/protobuf-lite/google/protobuf/stubs/time.h
vendored
Normal file
75
third_party/protobuf-lite/google/protobuf/stubs/time.h
vendored
Normal file
@ -0,0 +1,75 @@
|
||||
// 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_STUBS_TIME_H_
|
||||
#define GOOGLE_PROTOBUF_STUBS_TIME_H_
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
struct DateTime {
|
||||
int year;
|
||||
int month;
|
||||
int day;
|
||||
int hour;
|
||||
int minute;
|
||||
int second;
|
||||
};
|
||||
|
||||
// Converts a timestamp (seconds elapsed since 1970-01-01T00:00:00, could be
|
||||
// negative to represent time before 1970-01-01) to DateTime. Returns false
|
||||
// if the timestamp is not in the range between 0001-01-01T00:00:00 and
|
||||
// 9999-12-31T23:59:59.
|
||||
bool LIBPROTOBUF_EXPORT SecondsToDateTime(int64 seconds, DateTime* time);
|
||||
// Converts DateTime to a timestamp (seconds since 1970-01-01T00:00:00).
|
||||
// Returns false if the DateTime is not valid or is not in the valid range.
|
||||
bool LIBPROTOBUF_EXPORT DateTimeToSeconds(const DateTime& time, int64* seconds);
|
||||
|
||||
void LIBPROTOBUF_EXPORT GetCurrentTime(int64* seconds, int32* nanos);
|
||||
|
||||
// Formats a time string in RFC3339 fromat.
|
||||
//
|
||||
// For example, "2015-05-20T13:29:35.120Z". For nanos, 0, 3, 6 or 9 fractional
|
||||
// digits will be used depending on how many are required to represent the exact
|
||||
// value.
|
||||
//
|
||||
// Note that "nanos" must in the range of [0, 999999999].
|
||||
string LIBPROTOBUF_EXPORT FormatTime(int64 seconds, int32 nanos);
|
||||
// Parses a time string. This method accepts RFC3339 date/time string with UTC
|
||||
// offset. For example, "2015-05-20T13:29:35.120-08:00".
|
||||
bool LIBPROTOBUF_EXPORT ParseTime(const string& value, int64* seconds, int32* nanos);
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_STUBS_TIME_H_
|
893
third_party/protobuf-lite/google/protobuf/wire_format_lite.h
vendored
Normal file
893
third_party/protobuf-lite/google/protobuf/wire_format_lite.h
vendored
Normal file
@ -0,0 +1,893 @@
|
||||
// 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)
|
||||
// atenasio@google.com (Chris Atenasio) (ZigZag transform)
|
||||
// wink@google.com (Wink Saville) (refactored from wire_format.h)
|
||||
// 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_WIRE_FORMAT_LITE_H__
|
||||
#define GOOGLE_PROTOBUF_WIRE_FORMAT_LITE_H__
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/message_lite.h>
|
||||
#include <google/protobuf/stubs/port.h>
|
||||
#include <google/protobuf/repeated_field.h>
|
||||
|
||||
// Do UTF-8 validation on string type in Debug build only
|
||||
#ifndef NDEBUG
|
||||
#define GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
|
||||
#endif
|
||||
|
||||
// Avoid conflict with iOS where <ConditionalMacros.h> #defines TYPE_BOOL.
|
||||
//
|
||||
// If some one needs the macro TYPE_BOOL in a file that includes this header, it's
|
||||
// possible to bring it back using push/pop_macro as follows.
|
||||
//
|
||||
// #pragma push_macro("TYPE_BOOL")
|
||||
// #include this header and/or all headers that need the macro to be undefined.
|
||||
// #pragma pop_macro("TYPE_BOOL")
|
||||
#undef TYPE_BOOL
|
||||
|
||||
namespace google {
|
||||
|
||||
namespace protobuf {
|
||||
template <typename T> class RepeatedField; // repeated_field.h
|
||||
}
|
||||
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
class StringPieceField;
|
||||
|
||||
// This class is for internal use by the protocol buffer library and by
|
||||
// protocol-complier-generated message classes. It must not be called
|
||||
// directly by clients.
|
||||
//
|
||||
// This class contains helpers for implementing the binary protocol buffer
|
||||
// wire format without the need for reflection. Use WireFormat when using
|
||||
// reflection.
|
||||
//
|
||||
// This class is really a namespace that contains only static methods.
|
||||
class LIBPROTOBUF_EXPORT WireFormatLite {
|
||||
public:
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// Helper constants and functions related to the format. These are
|
||||
// mostly meant for internal and generated code to use.
|
||||
|
||||
// The wire format is composed of a sequence of tag/value pairs, each
|
||||
// of which contains the value of one field (or one element of a repeated
|
||||
// field). Each tag is encoded as a varint. The lower bits of the tag
|
||||
// identify its wire type, which specifies the format of the data to follow.
|
||||
// The rest of the bits contain the field number. Each type of field (as
|
||||
// declared by FieldDescriptor::Type, in descriptor.h) maps to one of
|
||||
// these wire types. Immediately following each tag is the field's value,
|
||||
// encoded in the format specified by the wire type. Because the tag
|
||||
// identifies the encoding of this data, it is possible to skip
|
||||
// unrecognized fields for forwards compatibility.
|
||||
|
||||
enum WireType {
|
||||
WIRETYPE_VARINT = 0,
|
||||
WIRETYPE_FIXED64 = 1,
|
||||
WIRETYPE_LENGTH_DELIMITED = 2,
|
||||
WIRETYPE_START_GROUP = 3,
|
||||
WIRETYPE_END_GROUP = 4,
|
||||
WIRETYPE_FIXED32 = 5,
|
||||
};
|
||||
|
||||
// Lite alternative to FieldDescriptor::Type. Must be kept in sync.
|
||||
enum FieldType {
|
||||
TYPE_DOUBLE = 1,
|
||||
TYPE_FLOAT = 2,
|
||||
TYPE_INT64 = 3,
|
||||
TYPE_UINT64 = 4,
|
||||
TYPE_INT32 = 5,
|
||||
TYPE_FIXED64 = 6,
|
||||
TYPE_FIXED32 = 7,
|
||||
TYPE_BOOL = 8,
|
||||
TYPE_STRING = 9,
|
||||
TYPE_GROUP = 10,
|
||||
TYPE_MESSAGE = 11,
|
||||
TYPE_BYTES = 12,
|
||||
TYPE_UINT32 = 13,
|
||||
TYPE_ENUM = 14,
|
||||
TYPE_SFIXED32 = 15,
|
||||
TYPE_SFIXED64 = 16,
|
||||
TYPE_SINT32 = 17,
|
||||
TYPE_SINT64 = 18,
|
||||
MAX_FIELD_TYPE = 18,
|
||||
};
|
||||
|
||||
// Lite alternative to FieldDescriptor::CppType. Must be kept in sync.
|
||||
enum CppType {
|
||||
CPPTYPE_INT32 = 1,
|
||||
CPPTYPE_INT64 = 2,
|
||||
CPPTYPE_UINT32 = 3,
|
||||
CPPTYPE_UINT64 = 4,
|
||||
CPPTYPE_DOUBLE = 5,
|
||||
CPPTYPE_FLOAT = 6,
|
||||
CPPTYPE_BOOL = 7,
|
||||
CPPTYPE_ENUM = 8,
|
||||
CPPTYPE_STRING = 9,
|
||||
CPPTYPE_MESSAGE = 10,
|
||||
MAX_CPPTYPE = 10,
|
||||
};
|
||||
|
||||
// Helper method to get the CppType for a particular Type.
|
||||
static CppType FieldTypeToCppType(FieldType type);
|
||||
|
||||
// Given a FieldDescriptor::Type return its WireType
|
||||
static inline WireFormatLite::WireType WireTypeForFieldType(
|
||||
WireFormatLite::FieldType type) {
|
||||
return kWireTypeForFieldType[type];
|
||||
}
|
||||
|
||||
// Number of bits in a tag which identify the wire type.
|
||||
static const int kTagTypeBits = 3;
|
||||
// Mask for those bits.
|
||||
static const uint32 kTagTypeMask = (1 << kTagTypeBits) - 1;
|
||||
|
||||
// Helper functions for encoding and decoding tags. (Inlined below and in
|
||||
// _inl.h)
|
||||
//
|
||||
// This is different from MakeTag(field->number(), field->type()) in the case
|
||||
// of packed repeated fields.
|
||||
static uint32 MakeTag(int field_number, WireType type);
|
||||
static WireType GetTagWireType(uint32 tag);
|
||||
static int GetTagFieldNumber(uint32 tag);
|
||||
|
||||
// Compute the byte size of a tag. For groups, this includes both the start
|
||||
// and end tags.
|
||||
static inline size_t TagSize(int field_number,
|
||||
WireFormatLite::FieldType type);
|
||||
|
||||
// Skips a field value with the given tag. The input should start
|
||||
// positioned immediately after the tag. Skipped values are simply discarded,
|
||||
// not recorded anywhere. See WireFormat::SkipField() for a version that
|
||||
// records to an UnknownFieldSet.
|
||||
static bool SkipField(io::CodedInputStream* input, uint32 tag);
|
||||
|
||||
// Skips a field value with the given tag. The input should start
|
||||
// positioned immediately after the tag. Skipped values are recorded to a
|
||||
// CodedOutputStream.
|
||||
static bool SkipField(io::CodedInputStream* input, uint32 tag,
|
||||
io::CodedOutputStream* output);
|
||||
|
||||
// Reads and ignores a message from the input. Skipped values are simply
|
||||
// discarded, not recorded anywhere. See WireFormat::SkipMessage() for a
|
||||
// version that records to an UnknownFieldSet.
|
||||
static bool SkipMessage(io::CodedInputStream* input);
|
||||
|
||||
// Reads and ignores a message from the input. Skipped values are recorded
|
||||
// to a CodedOutputStream.
|
||||
static bool SkipMessage(io::CodedInputStream* input,
|
||||
io::CodedOutputStream* output);
|
||||
|
||||
// This macro does the same thing as WireFormatLite::MakeTag(), but the
|
||||
// result is usable as a compile-time constant, which makes it usable
|
||||
// as a switch case or a template input. WireFormatLite::MakeTag() is more
|
||||
// type-safe, though, so prefer it if possible.
|
||||
#define GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(FIELD_NUMBER, TYPE) \
|
||||
static_cast<uint32>( \
|
||||
(static_cast<uint32>(FIELD_NUMBER) << ::google::protobuf::internal::WireFormatLite::kTagTypeBits) \
|
||||
| (TYPE))
|
||||
|
||||
// These are the tags for the old MessageSet format, which was defined as:
|
||||
// message MessageSet {
|
||||
// repeated group Item = 1 {
|
||||
// required int32 type_id = 2;
|
||||
// required string message = 3;
|
||||
// }
|
||||
// }
|
||||
static const int kMessageSetItemNumber = 1;
|
||||
static const int kMessageSetTypeIdNumber = 2;
|
||||
static const int kMessageSetMessageNumber = 3;
|
||||
static const int kMessageSetItemStartTag =
|
||||
GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(kMessageSetItemNumber,
|
||||
WireFormatLite::WIRETYPE_START_GROUP);
|
||||
static const int kMessageSetItemEndTag =
|
||||
GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(kMessageSetItemNumber,
|
||||
WireFormatLite::WIRETYPE_END_GROUP);
|
||||
static const int kMessageSetTypeIdTag =
|
||||
GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(kMessageSetTypeIdNumber,
|
||||
WireFormatLite::WIRETYPE_VARINT);
|
||||
static const int kMessageSetMessageTag =
|
||||
GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(kMessageSetMessageNumber,
|
||||
WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
|
||||
|
||||
// Byte size of all tags of a MessageSet::Item combined.
|
||||
static const size_t kMessageSetItemTagsSize;
|
||||
|
||||
// Helper functions for converting between floats/doubles and IEEE-754
|
||||
// uint32s/uint64s so that they can be written. (Assumes your platform
|
||||
// uses IEEE-754 floats.)
|
||||
static uint32 EncodeFloat(float value);
|
||||
static float DecodeFloat(uint32 value);
|
||||
static uint64 EncodeDouble(double value);
|
||||
static double DecodeDouble(uint64 value);
|
||||
|
||||
// Helper functions for mapping signed integers to unsigned integers in
|
||||
// such a way that numbers with small magnitudes will encode to smaller
|
||||
// varints. If you simply static_cast a negative number to an unsigned
|
||||
// number and varint-encode it, it will always take 10 bytes, defeating
|
||||
// the purpose of varint. So, for the "sint32" and "sint64" field types,
|
||||
// we ZigZag-encode the values.
|
||||
static uint32 ZigZagEncode32(int32 n);
|
||||
static int32 ZigZagDecode32(uint32 n);
|
||||
static uint64 ZigZagEncode64(int64 n);
|
||||
static int64 ZigZagDecode64(uint64 n);
|
||||
|
||||
// =================================================================
|
||||
// Methods for reading/writing individual field. The implementations
|
||||
// of these methods are defined in wire_format_lite_inl.h; you must #include
|
||||
// that file to use these.
|
||||
|
||||
#ifdef NDEBUG
|
||||
#define INL GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE
|
||||
#else
|
||||
// Avoid excessive inlining in non-optimized builds. Without other optimizations
|
||||
// the inlining is not going to provide benefits anyway and the huge resulting
|
||||
// functions, especially in the proto-generated serialization functions, produce
|
||||
// stack frames so large that many tests run into stack overflows (b/32192897).
|
||||
#define INL
|
||||
#endif
|
||||
|
||||
// Read fields, not including tags. The assumption is that you already
|
||||
// read the tag to determine what field to read.
|
||||
|
||||
// For primitive fields, we just use a templatized routine parameterized by
|
||||
// the represented type and the FieldType. These are specialized with the
|
||||
// appropriate definition for each declared type.
|
||||
template <typename CType, enum FieldType DeclaredType>
|
||||
INL static bool ReadPrimitive(io::CodedInputStream* input, CType* value);
|
||||
|
||||
// Reads repeated primitive values, with optimizations for repeats.
|
||||
// tag_size and tag should both be compile-time constants provided by the
|
||||
// protocol compiler.
|
||||
template <typename CType, enum FieldType DeclaredType>
|
||||
INL static bool ReadRepeatedPrimitive(int tag_size, uint32 tag,
|
||||
io::CodedInputStream* input,
|
||||
RepeatedField<CType>* value);
|
||||
|
||||
// Identical to ReadRepeatedPrimitive, except will not inline the
|
||||
// implementation.
|
||||
template <typename CType, enum FieldType DeclaredType>
|
||||
static bool ReadRepeatedPrimitiveNoInline(int tag_size, uint32 tag,
|
||||
io::CodedInputStream* input,
|
||||
RepeatedField<CType>* value);
|
||||
|
||||
// Reads a primitive value directly from the provided buffer. It returns a
|
||||
// pointer past the segment of data that was read.
|
||||
//
|
||||
// This is only implemented for the types with fixed wire size, e.g.
|
||||
// float, double, and the (s)fixed* types.
|
||||
template <typename CType, enum FieldType DeclaredType> INL
|
||||
static const uint8* ReadPrimitiveFromArray(const uint8* buffer, CType* value);
|
||||
|
||||
// Reads a primitive packed field.
|
||||
//
|
||||
// This is only implemented for packable types.
|
||||
template <typename CType, enum FieldType DeclaredType>
|
||||
INL static bool ReadPackedPrimitive(io::CodedInputStream* input,
|
||||
RepeatedField<CType>* value);
|
||||
|
||||
// Identical to ReadPackedPrimitive, except will not inline the
|
||||
// implementation.
|
||||
template <typename CType, enum FieldType DeclaredType>
|
||||
static bool ReadPackedPrimitiveNoInline(io::CodedInputStream* input,
|
||||
RepeatedField<CType>* value);
|
||||
|
||||
// Read a packed enum field. If the is_valid function is not NULL, values for
|
||||
// which is_valid(value) returns false are silently dropped.
|
||||
static bool ReadPackedEnumNoInline(io::CodedInputStream* input,
|
||||
bool (*is_valid)(int),
|
||||
RepeatedField<int>* values);
|
||||
|
||||
// Read a packed enum field. If the is_valid function is not NULL, values for
|
||||
// which is_valid(value) returns false are appended to unknown_fields_stream.
|
||||
static bool ReadPackedEnumPreserveUnknowns(
|
||||
io::CodedInputStream* input, int field_number, bool (*is_valid)(int),
|
||||
io::CodedOutputStream* unknown_fields_stream, RepeatedField<int>* values);
|
||||
|
||||
// Read a string. ReadString(..., string* value) requires an existing string.
|
||||
static inline bool ReadString(io::CodedInputStream* input, string* value);
|
||||
// ReadString(..., string** p) is internal-only, and should only be called
|
||||
// from generated code. It starts by setting *p to "new string"
|
||||
// if *p == &GetEmptyStringAlreadyInited(). It then invokes
|
||||
// ReadString(io::CodedInputStream* input, *p). This is useful for reducing
|
||||
// code size.
|
||||
static inline bool ReadString(io::CodedInputStream* input, string** p);
|
||||
// Analogous to ReadString().
|
||||
static bool ReadBytes(io::CodedInputStream* input, string* value);
|
||||
static bool ReadBytes(io::CodedInputStream* input, string** p);
|
||||
|
||||
enum Operation {
|
||||
PARSE = 0,
|
||||
SERIALIZE = 1,
|
||||
};
|
||||
|
||||
// Returns true if the data is valid UTF-8.
|
||||
static bool VerifyUtf8String(const char* data, int size,
|
||||
Operation op,
|
||||
const char* field_name);
|
||||
|
||||
template <typename MessageType>
|
||||
static inline bool ReadGroup(int field_number, io::CodedInputStream* input,
|
||||
MessageType* value);
|
||||
|
||||
template <typename MessageType>
|
||||
static inline bool ReadMessage(io::CodedInputStream* input,
|
||||
MessageType* value);
|
||||
|
||||
// Do not use.
|
||||
template <typename MessageType>
|
||||
static inline bool ReadGroupNoVirtual(int field_number,
|
||||
io::CodedInputStream* input,
|
||||
MessageType* value) {
|
||||
return ReadGroup(field_number, input, value);
|
||||
}
|
||||
|
||||
template<typename MessageType>
|
||||
static inline bool ReadMessageNoVirtual(io::CodedInputStream* input,
|
||||
MessageType* value) {
|
||||
return ReadMessage(input, value);
|
||||
}
|
||||
|
||||
// Write a tag. The Write*() functions typically include the tag, so
|
||||
// normally there's no need to call this unless using the Write*NoTag()
|
||||
// variants.
|
||||
INL static void WriteTag(int field_number, WireType type,
|
||||
io::CodedOutputStream* output);
|
||||
|
||||
// Write fields, without tags.
|
||||
INL static void WriteInt32NoTag(int32 value, io::CodedOutputStream* output);
|
||||
INL static void WriteInt64NoTag(int64 value, io::CodedOutputStream* output);
|
||||
INL static void WriteUInt32NoTag(uint32 value, io::CodedOutputStream* output);
|
||||
INL static void WriteUInt64NoTag(uint64 value, io::CodedOutputStream* output);
|
||||
INL static void WriteSInt32NoTag(int32 value, io::CodedOutputStream* output);
|
||||
INL static void WriteSInt64NoTag(int64 value, io::CodedOutputStream* output);
|
||||
INL static void WriteFixed32NoTag(uint32 value,
|
||||
io::CodedOutputStream* output);
|
||||
INL static void WriteFixed64NoTag(uint64 value,
|
||||
io::CodedOutputStream* output);
|
||||
INL static void WriteSFixed32NoTag(int32 value,
|
||||
io::CodedOutputStream* output);
|
||||
INL static void WriteSFixed64NoTag(int64 value,
|
||||
io::CodedOutputStream* output);
|
||||
INL static void WriteFloatNoTag(float value, io::CodedOutputStream* output);
|
||||
INL static void WriteDoubleNoTag(double value, io::CodedOutputStream* output);
|
||||
INL static void WriteBoolNoTag(bool value, io::CodedOutputStream* output);
|
||||
INL static void WriteEnumNoTag(int value, io::CodedOutputStream* output);
|
||||
|
||||
// Write array of primitive fields, without tags
|
||||
static void WriteFloatArray(const float* a, int n,
|
||||
io::CodedOutputStream* output);
|
||||
static void WriteDoubleArray(const double* a, int n,
|
||||
io::CodedOutputStream* output);
|
||||
static void WriteFixed32Array(const uint32* a, int n,
|
||||
io::CodedOutputStream* output);
|
||||
static void WriteFixed64Array(const uint64* a, int n,
|
||||
io::CodedOutputStream* output);
|
||||
static void WriteSFixed32Array(const int32* a, int n,
|
||||
io::CodedOutputStream* output);
|
||||
static void WriteSFixed64Array(const int64* a, int n,
|
||||
io::CodedOutputStream* output);
|
||||
static void WriteBoolArray(const bool* a, int n,
|
||||
io::CodedOutputStream* output);
|
||||
|
||||
// Write fields, including tags.
|
||||
static void WriteInt32(int field_number, int32 value,
|
||||
io::CodedOutputStream* output);
|
||||
static void WriteInt64(int field_number, int64 value,
|
||||
io::CodedOutputStream* output);
|
||||
static void WriteUInt32(int field_number, uint32 value,
|
||||
io::CodedOutputStream* output);
|
||||
static void WriteUInt64(int field_number, uint64 value,
|
||||
io::CodedOutputStream* output);
|
||||
static void WriteSInt32(int field_number, int32 value,
|
||||
io::CodedOutputStream* output);
|
||||
static void WriteSInt64(int field_number, int64 value,
|
||||
io::CodedOutputStream* output);
|
||||
static void WriteFixed32(int field_number, uint32 value,
|
||||
io::CodedOutputStream* output);
|
||||
static void WriteFixed64(int field_number, uint64 value,
|
||||
io::CodedOutputStream* output);
|
||||
static void WriteSFixed32(int field_number, int32 value,
|
||||
io::CodedOutputStream* output);
|
||||
static void WriteSFixed64(int field_number, int64 value,
|
||||
io::CodedOutputStream* output);
|
||||
static void WriteFloat(int field_number, float value,
|
||||
io::CodedOutputStream* output);
|
||||
static void WriteDouble(int field_number, double value,
|
||||
io::CodedOutputStream* output);
|
||||
static void WriteBool(int field_number, bool value,
|
||||
io::CodedOutputStream* output);
|
||||
static void WriteEnum(int field_number, int value,
|
||||
io::CodedOutputStream* output);
|
||||
|
||||
static void WriteString(int field_number, const string& value,
|
||||
io::CodedOutputStream* output);
|
||||
static void WriteBytes(int field_number, const string& value,
|
||||
io::CodedOutputStream* output);
|
||||
static void WriteStringMaybeAliased(int field_number, const string& value,
|
||||
io::CodedOutputStream* output);
|
||||
static void WriteBytesMaybeAliased(int field_number, const string& value,
|
||||
io::CodedOutputStream* output);
|
||||
|
||||
static void WriteGroup(int field_number, const MessageLite& value,
|
||||
io::CodedOutputStream* output);
|
||||
static void WriteMessage(int field_number, const MessageLite& value,
|
||||
io::CodedOutputStream* output);
|
||||
// Like above, but these will check if the output stream has enough
|
||||
// space to write directly to a flat array.
|
||||
static void WriteGroupMaybeToArray(int field_number, const MessageLite& value,
|
||||
io::CodedOutputStream* output);
|
||||
static void WriteMessageMaybeToArray(int field_number,
|
||||
const MessageLite& value,
|
||||
io::CodedOutputStream* output);
|
||||
|
||||
// Like above, but de-virtualize the call to SerializeWithCachedSizes(). The
|
||||
// pointer must point at an instance of MessageType, *not* a subclass (or
|
||||
// the subclass must not override SerializeWithCachedSizes()).
|
||||
template <typename MessageType>
|
||||
static inline void WriteGroupNoVirtual(int field_number,
|
||||
const MessageType& value,
|
||||
io::CodedOutputStream* output);
|
||||
template <typename MessageType>
|
||||
static inline void WriteMessageNoVirtual(int field_number,
|
||||
const MessageType& value,
|
||||
io::CodedOutputStream* output);
|
||||
|
||||
// Like above, but use only *ToArray methods of CodedOutputStream.
|
||||
INL static uint8* WriteTagToArray(int field_number, WireType type,
|
||||
uint8* target);
|
||||
|
||||
// Write fields, without tags.
|
||||
INL static uint8* WriteInt32NoTagToArray(int32 value, uint8* target);
|
||||
INL static uint8* WriteInt64NoTagToArray(int64 value, uint8* target);
|
||||
INL static uint8* WriteUInt32NoTagToArray(uint32 value, uint8* target);
|
||||
INL static uint8* WriteUInt64NoTagToArray(uint64 value, uint8* target);
|
||||
INL static uint8* WriteSInt32NoTagToArray(int32 value, uint8* target);
|
||||
INL static uint8* WriteSInt64NoTagToArray(int64 value, uint8* target);
|
||||
INL static uint8* WriteFixed32NoTagToArray(uint32 value, uint8* target);
|
||||
INL static uint8* WriteFixed64NoTagToArray(uint64 value, uint8* target);
|
||||
INL static uint8* WriteSFixed32NoTagToArray(int32 value, uint8* target);
|
||||
INL static uint8* WriteSFixed64NoTagToArray(int64 value, uint8* target);
|
||||
INL static uint8* WriteFloatNoTagToArray(float value, uint8* target);
|
||||
INL static uint8* WriteDoubleNoTagToArray(double value, uint8* target);
|
||||
INL static uint8* WriteBoolNoTagToArray(bool value, uint8* target);
|
||||
INL static uint8* WriteEnumNoTagToArray(int value, uint8* target);
|
||||
|
||||
// Write fields, without tags. These require that value.size() > 0.
|
||||
template<typename T>
|
||||
INL static uint8* WritePrimitiveNoTagToArray(
|
||||
const RepeatedField<T>& value,
|
||||
uint8* (*Writer)(T, uint8*), uint8* target);
|
||||
template<typename T>
|
||||
INL static uint8* WriteFixedNoTagToArray(
|
||||
const RepeatedField<T>& value,
|
||||
uint8* (*Writer)(T, uint8*), uint8* target);
|
||||
|
||||
INL static uint8* WriteInt32NoTagToArray(
|
||||
const RepeatedField< int32>& value, uint8* output);
|
||||
INL static uint8* WriteInt64NoTagToArray(
|
||||
const RepeatedField< int64>& value, uint8* output);
|
||||
INL static uint8* WriteUInt32NoTagToArray(
|
||||
const RepeatedField<uint32>& value, uint8* output);
|
||||
INL static uint8* WriteUInt64NoTagToArray(
|
||||
const RepeatedField<uint64>& value, uint8* output);
|
||||
INL static uint8* WriteSInt32NoTagToArray(
|
||||
const RepeatedField< int32>& value, uint8* output);
|
||||
INL static uint8* WriteSInt64NoTagToArray(
|
||||
const RepeatedField< int64>& value, uint8* output);
|
||||
INL static uint8* WriteFixed32NoTagToArray(
|
||||
const RepeatedField<uint32>& value, uint8* output);
|
||||
INL static uint8* WriteFixed64NoTagToArray(
|
||||
const RepeatedField<uint64>& value, uint8* output);
|
||||
INL static uint8* WriteSFixed32NoTagToArray(
|
||||
const RepeatedField< int32>& value, uint8* output);
|
||||
INL static uint8* WriteSFixed64NoTagToArray(
|
||||
const RepeatedField< int64>& value, uint8* output);
|
||||
INL static uint8* WriteFloatNoTagToArray(
|
||||
const RepeatedField< float>& value, uint8* output);
|
||||
INL static uint8* WriteDoubleNoTagToArray(
|
||||
const RepeatedField<double>& value, uint8* output);
|
||||
INL static uint8* WriteBoolNoTagToArray(
|
||||
const RepeatedField< bool>& value, uint8* output);
|
||||
INL static uint8* WriteEnumNoTagToArray(
|
||||
const RepeatedField< int>& value, uint8* output);
|
||||
|
||||
// Write fields, including tags.
|
||||
INL static uint8* WriteInt32ToArray(int field_number, int32 value,
|
||||
uint8* target);
|
||||
INL static uint8* WriteInt64ToArray(int field_number, int64 value,
|
||||
uint8* target);
|
||||
INL static uint8* WriteUInt32ToArray(int field_number, uint32 value,
|
||||
uint8* target);
|
||||
INL static uint8* WriteUInt64ToArray(int field_number, uint64 value,
|
||||
uint8* target);
|
||||
INL static uint8* WriteSInt32ToArray(int field_number, int32 value,
|
||||
uint8* target);
|
||||
INL static uint8* WriteSInt64ToArray(int field_number, int64 value,
|
||||
uint8* target);
|
||||
INL static uint8* WriteFixed32ToArray(int field_number, uint32 value,
|
||||
uint8* target);
|
||||
INL static uint8* WriteFixed64ToArray(int field_number, uint64 value,
|
||||
uint8* target);
|
||||
INL static uint8* WriteSFixed32ToArray(int field_number, int32 value,
|
||||
uint8* target);
|
||||
INL static uint8* WriteSFixed64ToArray(int field_number, int64 value,
|
||||
uint8* target);
|
||||
INL static uint8* WriteFloatToArray(int field_number, float value,
|
||||
uint8* target);
|
||||
INL static uint8* WriteDoubleToArray(int field_number, double value,
|
||||
uint8* target);
|
||||
INL static uint8* WriteBoolToArray(int field_number, bool value,
|
||||
uint8* target);
|
||||
INL static uint8* WriteEnumToArray(int field_number, int value,
|
||||
uint8* target);
|
||||
|
||||
template<typename T>
|
||||
INL static uint8* WritePrimitiveToArray(
|
||||
int field_number,
|
||||
const RepeatedField<T>& value,
|
||||
uint8* (*Writer)(int, T, uint8*), uint8* target);
|
||||
|
||||
INL static uint8* WriteInt32ToArray(
|
||||
int field_number, const RepeatedField< int32>& value, uint8* output);
|
||||
INL static uint8* WriteInt64ToArray(
|
||||
int field_number, const RepeatedField< int64>& value, uint8* output);
|
||||
INL static uint8* WriteUInt32ToArray(
|
||||
int field_number, const RepeatedField<uint32>& value, uint8* output);
|
||||
INL static uint8* WriteUInt64ToArray(
|
||||
int field_number, const RepeatedField<uint64>& value, uint8* output);
|
||||
INL static uint8* WriteSInt32ToArray(
|
||||
int field_number, const RepeatedField< int32>& value, uint8* output);
|
||||
INL static uint8* WriteSInt64ToArray(
|
||||
int field_number, const RepeatedField< int64>& value, uint8* output);
|
||||
INL static uint8* WriteFixed32ToArray(
|
||||
int field_number, const RepeatedField<uint32>& value, uint8* output);
|
||||
INL static uint8* WriteFixed64ToArray(
|
||||
int field_number, const RepeatedField<uint64>& value, uint8* output);
|
||||
INL static uint8* WriteSFixed32ToArray(
|
||||
int field_number, const RepeatedField< int32>& value, uint8* output);
|
||||
INL static uint8* WriteSFixed64ToArray(
|
||||
int field_number, const RepeatedField< int64>& value, uint8* output);
|
||||
INL static uint8* WriteFloatToArray(
|
||||
int field_number, const RepeatedField< float>& value, uint8* output);
|
||||
INL static uint8* WriteDoubleToArray(
|
||||
int field_number, const RepeatedField<double>& value, uint8* output);
|
||||
INL static uint8* WriteBoolToArray(
|
||||
int field_number, const RepeatedField< bool>& value, uint8* output);
|
||||
INL static uint8* WriteEnumToArray(
|
||||
int field_number, const RepeatedField< int>& value, uint8* output);
|
||||
|
||||
INL static uint8* WriteStringToArray(int field_number, const string& value,
|
||||
uint8* target);
|
||||
INL static uint8* WriteBytesToArray(int field_number, const string& value,
|
||||
uint8* target);
|
||||
|
||||
// Whether to serialize deterministically (e.g., map keys are
|
||||
// sorted) is a property of a CodedOutputStream, and in the process
|
||||
// of serialization, the "ToArray" variants may be invoked. But they don't
|
||||
// have a CodedOutputStream available, so they get an additional parameter
|
||||
// telling them whether to serialize deterministically.
|
||||
template<typename MessageType>
|
||||
INL static uint8* InternalWriteGroupToArray(int field_number,
|
||||
const MessageType& value,
|
||||
bool deterministic,
|
||||
uint8* target);
|
||||
template<typename MessageType>
|
||||
INL static uint8* InternalWriteMessageToArray(int field_number,
|
||||
const MessageType& value,
|
||||
bool deterministic,
|
||||
uint8* target);
|
||||
|
||||
// Like above, but de-virtualize the call to SerializeWithCachedSizes(). The
|
||||
// pointer must point at an instance of MessageType, *not* a subclass (or
|
||||
// the subclass must not override SerializeWithCachedSizes()).
|
||||
template <typename MessageType>
|
||||
INL static uint8* InternalWriteGroupNoVirtualToArray(int field_number,
|
||||
const MessageType& value,
|
||||
bool deterministic,
|
||||
uint8* target);
|
||||
template <typename MessageType>
|
||||
INL static uint8* InternalWriteMessageNoVirtualToArray(
|
||||
int field_number, const MessageType& value, bool deterministic,
|
||||
uint8* target);
|
||||
|
||||
// For backward-compatibility, the last four methods also have versions
|
||||
// that are non-deterministic always.
|
||||
INL static uint8* WriteGroupToArray(int field_number,
|
||||
const MessageLite& value, uint8* target) {
|
||||
return InternalWriteGroupToArray(field_number, value, false, target);
|
||||
}
|
||||
INL static uint8* WriteMessageToArray(int field_number,
|
||||
const MessageLite& value,
|
||||
uint8* target) {
|
||||
return InternalWriteMessageToArray(field_number, value, false, target);
|
||||
}
|
||||
template <typename MessageType>
|
||||
INL static uint8* WriteGroupNoVirtualToArray(int field_number,
|
||||
const MessageType& value,
|
||||
uint8* target) {
|
||||
return InternalWriteGroupNoVirtualToArray(field_number, value, false,
|
||||
target);
|
||||
}
|
||||
template <typename MessageType>
|
||||
INL static uint8* WriteMessageNoVirtualToArray(int field_number,
|
||||
const MessageType& value,
|
||||
uint8* target) {
|
||||
return InternalWriteMessageNoVirtualToArray(field_number, value, false,
|
||||
target);
|
||||
}
|
||||
|
||||
#undef INL
|
||||
|
||||
// Compute the byte size of a field. The XxSize() functions do NOT include
|
||||
// the tag, so you must also call TagSize(). (This is because, for repeated
|
||||
// fields, you should only call TagSize() once and multiply it by the element
|
||||
// count, but you may have to call XxSize() for each individual element.)
|
||||
static inline size_t Int32Size ( int32 value);
|
||||
static inline size_t Int64Size ( int64 value);
|
||||
static inline size_t UInt32Size (uint32 value);
|
||||
static inline size_t UInt64Size (uint64 value);
|
||||
static inline size_t SInt32Size ( int32 value);
|
||||
static inline size_t SInt64Size ( int64 value);
|
||||
static inline size_t EnumSize ( int value);
|
||||
|
||||
static size_t Int32Size (const RepeatedField< int32>& value);
|
||||
static size_t Int64Size (const RepeatedField< int64>& value);
|
||||
static size_t UInt32Size(const RepeatedField<uint32>& value);
|
||||
static size_t UInt64Size(const RepeatedField<uint64>& value);
|
||||
static size_t SInt32Size(const RepeatedField< int32>& value);
|
||||
static size_t SInt64Size(const RepeatedField< int64>& value);
|
||||
static size_t EnumSize (const RepeatedField< int>& value);
|
||||
|
||||
// These types always have the same size.
|
||||
static const size_t kFixed32Size = 4;
|
||||
static const size_t kFixed64Size = 8;
|
||||
static const size_t kSFixed32Size = 4;
|
||||
static const size_t kSFixed64Size = 8;
|
||||
static const size_t kFloatSize = 4;
|
||||
static const size_t kDoubleSize = 8;
|
||||
static const size_t kBoolSize = 1;
|
||||
|
||||
static inline size_t StringSize(const string& value);
|
||||
static inline size_t BytesSize (const string& value);
|
||||
|
||||
template<typename MessageType>
|
||||
static inline size_t GroupSize (const MessageType& value);
|
||||
template<typename MessageType>
|
||||
static inline size_t MessageSize(const MessageType& value);
|
||||
|
||||
// Like above, but de-virtualize the call to ByteSize(). The
|
||||
// pointer must point at an instance of MessageType, *not* a subclass (or
|
||||
// the subclass must not override ByteSize()).
|
||||
template<typename MessageType>
|
||||
static inline size_t GroupSizeNoVirtual (const MessageType& value);
|
||||
template<typename MessageType>
|
||||
static inline size_t MessageSizeNoVirtual(const MessageType& value);
|
||||
|
||||
// Given the length of data, calculate the byte size of the data on the
|
||||
// wire if we encode the data as a length delimited field.
|
||||
static inline size_t LengthDelimitedSize(size_t length);
|
||||
|
||||
private:
|
||||
// A helper method for the repeated primitive reader. This method has
|
||||
// optimizations for primitive types that have fixed size on the wire, and
|
||||
// can be read using potentially faster paths.
|
||||
template <typename CType, enum FieldType DeclaredType>
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE
|
||||
static bool ReadRepeatedFixedSizePrimitive(
|
||||
int tag_size,
|
||||
uint32 tag,
|
||||
google::protobuf::io::CodedInputStream* input,
|
||||
RepeatedField<CType>* value);
|
||||
|
||||
// Like ReadRepeatedFixedSizePrimitive but for packed primitive fields.
|
||||
template <typename CType, enum FieldType DeclaredType>
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE
|
||||
static bool ReadPackedFixedSizePrimitive(
|
||||
google::protobuf::io::CodedInputStream* input, RepeatedField<CType>* value);
|
||||
|
||||
static const CppType kFieldTypeToCppTypeMap[];
|
||||
static const WireFormatLite::WireType kWireTypeForFieldType[];
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(WireFormatLite);
|
||||
};
|
||||
|
||||
// A class which deals with unknown values. The default implementation just
|
||||
// discards them. WireFormat defines a subclass which writes to an
|
||||
// UnknownFieldSet. This class is used by ExtensionSet::ParseField(), since
|
||||
// ExtensionSet is part of the lite library but UnknownFieldSet is not.
|
||||
class LIBPROTOBUF_EXPORT FieldSkipper {
|
||||
public:
|
||||
FieldSkipper() {}
|
||||
virtual ~FieldSkipper() {}
|
||||
|
||||
// Skip a field whose tag has already been consumed.
|
||||
virtual bool SkipField(io::CodedInputStream* input, uint32 tag);
|
||||
|
||||
// Skip an entire message or group, up to an end-group tag (which is consumed)
|
||||
// or end-of-stream.
|
||||
virtual bool SkipMessage(io::CodedInputStream* input);
|
||||
|
||||
// Deal with an already-parsed unrecognized enum value. The default
|
||||
// implementation does nothing, but the UnknownFieldSet-based implementation
|
||||
// saves it as an unknown varint.
|
||||
virtual void SkipUnknownEnum(int field_number, int value);
|
||||
};
|
||||
|
||||
// Subclass of FieldSkipper which saves skipped fields to a CodedOutputStream.
|
||||
|
||||
class LIBPROTOBUF_EXPORT CodedOutputStreamFieldSkipper : public FieldSkipper {
|
||||
public:
|
||||
explicit CodedOutputStreamFieldSkipper(io::CodedOutputStream* unknown_fields)
|
||||
: unknown_fields_(unknown_fields) {}
|
||||
virtual ~CodedOutputStreamFieldSkipper() {}
|
||||
|
||||
// implements FieldSkipper -----------------------------------------
|
||||
virtual bool SkipField(io::CodedInputStream* input, uint32 tag);
|
||||
virtual bool SkipMessage(io::CodedInputStream* input);
|
||||
virtual void SkipUnknownEnum(int field_number, int value);
|
||||
|
||||
protected:
|
||||
io::CodedOutputStream* unknown_fields_;
|
||||
};
|
||||
|
||||
|
||||
// inline methods ====================================================
|
||||
|
||||
inline WireFormatLite::CppType
|
||||
WireFormatLite::FieldTypeToCppType(FieldType type) {
|
||||
return kFieldTypeToCppTypeMap[type];
|
||||
}
|
||||
|
||||
inline uint32 WireFormatLite::MakeTag(int field_number, WireType type) {
|
||||
return GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(field_number, type);
|
||||
}
|
||||
|
||||
inline WireFormatLite::WireType WireFormatLite::GetTagWireType(uint32 tag) {
|
||||
return static_cast<WireType>(tag & kTagTypeMask);
|
||||
}
|
||||
|
||||
inline int WireFormatLite::GetTagFieldNumber(uint32 tag) {
|
||||
return static_cast<int>(tag >> kTagTypeBits);
|
||||
}
|
||||
|
||||
inline size_t WireFormatLite::TagSize(int field_number,
|
||||
WireFormatLite::FieldType type) {
|
||||
size_t result = io::CodedOutputStream::VarintSize32(
|
||||
static_cast<uint32>(field_number << kTagTypeBits));
|
||||
if (type == TYPE_GROUP) {
|
||||
// Groups have both a start and an end tag.
|
||||
return result * 2;
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
inline uint32 WireFormatLite::EncodeFloat(float value) {
|
||||
union {float f; uint32 i;};
|
||||
f = value;
|
||||
return i;
|
||||
}
|
||||
|
||||
inline float WireFormatLite::DecodeFloat(uint32 value) {
|
||||
union {float f; uint32 i;};
|
||||
i = value;
|
||||
return f;
|
||||
}
|
||||
|
||||
inline uint64 WireFormatLite::EncodeDouble(double value) {
|
||||
union {double f; uint64 i;};
|
||||
f = value;
|
||||
return i;
|
||||
}
|
||||
|
||||
inline double WireFormatLite::DecodeDouble(uint64 value) {
|
||||
union {double f; uint64 i;};
|
||||
i = value;
|
||||
return f;
|
||||
}
|
||||
|
||||
// ZigZag Transform: Encodes signed integers so that they can be
|
||||
// effectively used with varint encoding.
|
||||
//
|
||||
// varint operates on unsigned integers, encoding smaller numbers into
|
||||
// fewer bytes. If you try to use it on a signed integer, it will treat
|
||||
// this number as a very large unsigned integer, which means that even
|
||||
// small signed numbers like -1 will take the maximum number of bytes
|
||||
// (10) to encode. ZigZagEncode() maps signed integers to unsigned
|
||||
// in such a way that those with a small absolute value will have smaller
|
||||
// encoded values, making them appropriate for encoding using varint.
|
||||
//
|
||||
// int32 -> uint32
|
||||
// -------------------------
|
||||
// 0 -> 0
|
||||
// -1 -> 1
|
||||
// 1 -> 2
|
||||
// -2 -> 3
|
||||
// ... -> ...
|
||||
// 2147483647 -> 4294967294
|
||||
// -2147483648 -> 4294967295
|
||||
//
|
||||
// >> encode >>
|
||||
// << decode <<
|
||||
|
||||
inline uint32 WireFormatLite::ZigZagEncode32(int32 n) {
|
||||
// Note: the right-shift must be arithmetic
|
||||
// Note: left shift must be unsigned because of overflow
|
||||
return (static_cast<uint32>(n) << 1) ^ static_cast<uint32>(n >> 31);
|
||||
}
|
||||
|
||||
inline int32 WireFormatLite::ZigZagDecode32(uint32 n) {
|
||||
// Note: Using unsigned types prevent undefined behavior
|
||||
return static_cast<int32>((n >> 1) ^ (~(n & 1) + 1));
|
||||
}
|
||||
|
||||
inline uint64 WireFormatLite::ZigZagEncode64(int64 n) {
|
||||
// Note: the right-shift must be arithmetic
|
||||
// Note: left shift must be unsigned because of overflow
|
||||
return (static_cast<uint64>(n) << 1) ^ static_cast<uint64>(n >> 63);
|
||||
}
|
||||
|
||||
inline int64 WireFormatLite::ZigZagDecode64(uint64 n) {
|
||||
// Note: Using unsigned types prevent undefined behavior
|
||||
return static_cast<int64>((n >> 1) ^ (~(n & 1) + 1));
|
||||
}
|
||||
|
||||
// String is for UTF-8 text only, but, even so, ReadString() can simply
|
||||
// call ReadBytes().
|
||||
|
||||
inline bool WireFormatLite::ReadString(io::CodedInputStream* input,
|
||||
string* value) {
|
||||
return ReadBytes(input, value);
|
||||
}
|
||||
|
||||
inline bool WireFormatLite::ReadString(io::CodedInputStream* input,
|
||||
string** p) {
|
||||
return ReadBytes(input, p);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_WIRE_FORMAT_LITE_H__
|
996
third_party/protobuf-lite/google/protobuf/wire_format_lite_inl.h
vendored
Normal file
996
third_party/protobuf-lite/google/protobuf/wire_format_lite_inl.h
vendored
Normal file
@ -0,0 +1,996 @@
|
||||
// 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)
|
||||
// wink@google.com (Wink Saville) (refactored from wire_format.h)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_WIRE_FORMAT_LITE_INL_H__
|
||||
#define GOOGLE_PROTOBUF_WIRE_FORMAT_LITE_INL_H__
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/logging.h>
|
||||
#include <google/protobuf/message_lite.h>
|
||||
#include <google/protobuf/repeated_field.h>
|
||||
#include <google/protobuf/wire_format_lite.h>
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/arenastring.h>
|
||||
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
// Implementation details of ReadPrimitive.
|
||||
|
||||
template <>
|
||||
inline bool WireFormatLite::ReadPrimitive<int32, WireFormatLite::TYPE_INT32>(
|
||||
io::CodedInputStream* input,
|
||||
int32* value) {
|
||||
uint32 temp;
|
||||
if (!input->ReadVarint32(&temp)) return false;
|
||||
*value = static_cast<int32>(temp);
|
||||
return true;
|
||||
}
|
||||
template <>
|
||||
inline bool WireFormatLite::ReadPrimitive<int64, WireFormatLite::TYPE_INT64>(
|
||||
io::CodedInputStream* input,
|
||||
int64* value) {
|
||||
uint64 temp;
|
||||
if (!input->ReadVarint64(&temp)) return false;
|
||||
*value = static_cast<int64>(temp);
|
||||
return true;
|
||||
}
|
||||
template <>
|
||||
inline bool WireFormatLite::ReadPrimitive<uint32, WireFormatLite::TYPE_UINT32>(
|
||||
io::CodedInputStream* input,
|
||||
uint32* value) {
|
||||
return input->ReadVarint32(value);
|
||||
}
|
||||
template <>
|
||||
inline bool WireFormatLite::ReadPrimitive<uint64, WireFormatLite::TYPE_UINT64>(
|
||||
io::CodedInputStream* input,
|
||||
uint64* value) {
|
||||
return input->ReadVarint64(value);
|
||||
}
|
||||
template <>
|
||||
inline bool WireFormatLite::ReadPrimitive<int32, WireFormatLite::TYPE_SINT32>(
|
||||
io::CodedInputStream* input,
|
||||
int32* value) {
|
||||
uint32 temp;
|
||||
if (!input->ReadVarint32(&temp)) return false;
|
||||
*value = ZigZagDecode32(temp);
|
||||
return true;
|
||||
}
|
||||
template <>
|
||||
inline bool WireFormatLite::ReadPrimitive<int64, WireFormatLite::TYPE_SINT64>(
|
||||
io::CodedInputStream* input,
|
||||
int64* value) {
|
||||
uint64 temp;
|
||||
if (!input->ReadVarint64(&temp)) return false;
|
||||
*value = ZigZagDecode64(temp);
|
||||
return true;
|
||||
}
|
||||
template <>
|
||||
inline bool WireFormatLite::ReadPrimitive<uint32, WireFormatLite::TYPE_FIXED32>(
|
||||
io::CodedInputStream* input,
|
||||
uint32* value) {
|
||||
return input->ReadLittleEndian32(value);
|
||||
}
|
||||
template <>
|
||||
inline bool WireFormatLite::ReadPrimitive<uint64, WireFormatLite::TYPE_FIXED64>(
|
||||
io::CodedInputStream* input,
|
||||
uint64* value) {
|
||||
return input->ReadLittleEndian64(value);
|
||||
}
|
||||
template <>
|
||||
inline bool WireFormatLite::ReadPrimitive<int32, WireFormatLite::TYPE_SFIXED32>(
|
||||
io::CodedInputStream* input,
|
||||
int32* value) {
|
||||
uint32 temp;
|
||||
if (!input->ReadLittleEndian32(&temp)) return false;
|
||||
*value = static_cast<int32>(temp);
|
||||
return true;
|
||||
}
|
||||
template <>
|
||||
inline bool WireFormatLite::ReadPrimitive<int64, WireFormatLite::TYPE_SFIXED64>(
|
||||
io::CodedInputStream* input,
|
||||
int64* value) {
|
||||
uint64 temp;
|
||||
if (!input->ReadLittleEndian64(&temp)) return false;
|
||||
*value = static_cast<int64>(temp);
|
||||
return true;
|
||||
}
|
||||
template <>
|
||||
inline bool WireFormatLite::ReadPrimitive<float, WireFormatLite::TYPE_FLOAT>(
|
||||
io::CodedInputStream* input,
|
||||
float* value) {
|
||||
uint32 temp;
|
||||
if (!input->ReadLittleEndian32(&temp)) return false;
|
||||
*value = DecodeFloat(temp);
|
||||
return true;
|
||||
}
|
||||
template <>
|
||||
inline bool WireFormatLite::ReadPrimitive<double, WireFormatLite::TYPE_DOUBLE>(
|
||||
io::CodedInputStream* input,
|
||||
double* value) {
|
||||
uint64 temp;
|
||||
if (!input->ReadLittleEndian64(&temp)) return false;
|
||||
*value = DecodeDouble(temp);
|
||||
return true;
|
||||
}
|
||||
template <>
|
||||
inline bool WireFormatLite::ReadPrimitive<bool, WireFormatLite::TYPE_BOOL>(
|
||||
io::CodedInputStream* input,
|
||||
bool* value) {
|
||||
uint64 temp;
|
||||
if (!input->ReadVarint64(&temp)) return false;
|
||||
*value = temp != 0;
|
||||
return true;
|
||||
}
|
||||
template <>
|
||||
inline bool WireFormatLite::ReadPrimitive<int, WireFormatLite::TYPE_ENUM>(
|
||||
io::CodedInputStream* input,
|
||||
int* value) {
|
||||
uint32 temp;
|
||||
if (!input->ReadVarint32(&temp)) return false;
|
||||
*value = static_cast<int>(temp);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline const uint8* WireFormatLite::ReadPrimitiveFromArray<
|
||||
uint32, WireFormatLite::TYPE_FIXED32>(
|
||||
const uint8* buffer,
|
||||
uint32* value) {
|
||||
return io::CodedInputStream::ReadLittleEndian32FromArray(buffer, value);
|
||||
}
|
||||
template <>
|
||||
inline const uint8* WireFormatLite::ReadPrimitiveFromArray<
|
||||
uint64, WireFormatLite::TYPE_FIXED64>(
|
||||
const uint8* buffer,
|
||||
uint64* value) {
|
||||
return io::CodedInputStream::ReadLittleEndian64FromArray(buffer, value);
|
||||
}
|
||||
template <>
|
||||
inline const uint8* WireFormatLite::ReadPrimitiveFromArray<
|
||||
int32, WireFormatLite::TYPE_SFIXED32>(
|
||||
const uint8* buffer,
|
||||
int32* value) {
|
||||
uint32 temp;
|
||||
buffer = io::CodedInputStream::ReadLittleEndian32FromArray(buffer, &temp);
|
||||
*value = static_cast<int32>(temp);
|
||||
return buffer;
|
||||
}
|
||||
template <>
|
||||
inline const uint8* WireFormatLite::ReadPrimitiveFromArray<
|
||||
int64, WireFormatLite::TYPE_SFIXED64>(
|
||||
const uint8* buffer,
|
||||
int64* value) {
|
||||
uint64 temp;
|
||||
buffer = io::CodedInputStream::ReadLittleEndian64FromArray(buffer, &temp);
|
||||
*value = static_cast<int64>(temp);
|
||||
return buffer;
|
||||
}
|
||||
template <>
|
||||
inline const uint8* WireFormatLite::ReadPrimitiveFromArray<
|
||||
float, WireFormatLite::TYPE_FLOAT>(
|
||||
const uint8* buffer,
|
||||
float* value) {
|
||||
uint32 temp;
|
||||
buffer = io::CodedInputStream::ReadLittleEndian32FromArray(buffer, &temp);
|
||||
*value = DecodeFloat(temp);
|
||||
return buffer;
|
||||
}
|
||||
template <>
|
||||
inline const uint8* WireFormatLite::ReadPrimitiveFromArray<
|
||||
double, WireFormatLite::TYPE_DOUBLE>(
|
||||
const uint8* buffer,
|
||||
double* value) {
|
||||
uint64 temp;
|
||||
buffer = io::CodedInputStream::ReadLittleEndian64FromArray(buffer, &temp);
|
||||
*value = DecodeDouble(temp);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
template <typename CType, enum WireFormatLite::FieldType DeclaredType>
|
||||
inline bool WireFormatLite::ReadRepeatedPrimitive(
|
||||
int, // tag_size, unused.
|
||||
uint32 tag,
|
||||
io::CodedInputStream* input,
|
||||
RepeatedField<CType>* values) {
|
||||
CType value;
|
||||
if (!ReadPrimitive<CType, DeclaredType>(input, &value)) return false;
|
||||
values->Add(value);
|
||||
int elements_already_reserved = values->Capacity() - values->size();
|
||||
while (elements_already_reserved > 0 && input->ExpectTag(tag)) {
|
||||
if (!ReadPrimitive<CType, DeclaredType>(input, &value)) return false;
|
||||
values->AddAlreadyReserved(value);
|
||||
elements_already_reserved--;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename CType, enum WireFormatLite::FieldType DeclaredType>
|
||||
inline bool WireFormatLite::ReadRepeatedFixedSizePrimitive(
|
||||
int tag_size,
|
||||
uint32 tag,
|
||||
io::CodedInputStream* input,
|
||||
RepeatedField<CType>* values) {
|
||||
GOOGLE_DCHECK_EQ(UInt32Size(tag), static_cast<size_t>(tag_size));
|
||||
CType value;
|
||||
if (!ReadPrimitive<CType, DeclaredType>(input, &value))
|
||||
return false;
|
||||
values->Add(value);
|
||||
|
||||
// For fixed size values, repeated values can be read more quickly by
|
||||
// reading directly from a raw array.
|
||||
//
|
||||
// We can get a tight loop by only reading as many elements as can be
|
||||
// added to the RepeatedField without having to do any resizing. Additionally,
|
||||
// we only try to read as many elements as are available from the current
|
||||
// buffer space. Doing so avoids having to perform boundary checks when
|
||||
// reading the value: the maximum number of elements that can be read is
|
||||
// known outside of the loop.
|
||||
const void* void_pointer;
|
||||
int size;
|
||||
input->GetDirectBufferPointerInline(&void_pointer, &size);
|
||||
if (size > 0) {
|
||||
const uint8* buffer = reinterpret_cast<const uint8*>(void_pointer);
|
||||
// The number of bytes each type occupies on the wire.
|
||||
const int per_value_size = tag_size + static_cast<int>(sizeof(value));
|
||||
|
||||
// parentheses around (std::min) prevents macro expansion of min(...)
|
||||
int elements_available =
|
||||
(std::min)(values->Capacity() - values->size(), size / per_value_size);
|
||||
int num_read = 0;
|
||||
while (num_read < elements_available &&
|
||||
(buffer = io::CodedInputStream::ExpectTagFromArray(
|
||||
buffer, tag)) != NULL) {
|
||||
buffer = ReadPrimitiveFromArray<CType, DeclaredType>(buffer, &value);
|
||||
values->AddAlreadyReserved(value);
|
||||
++num_read;
|
||||
}
|
||||
const int read_bytes = num_read * per_value_size;
|
||||
if (read_bytes > 0) {
|
||||
input->Skip(read_bytes);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Specializations of ReadRepeatedPrimitive for the fixed size types, which use
|
||||
// the optimized code path.
|
||||
#define READ_REPEATED_FIXED_SIZE_PRIMITIVE(CPPTYPE, DECLARED_TYPE) \
|
||||
template <> \
|
||||
inline bool WireFormatLite::ReadRepeatedPrimitive< \
|
||||
CPPTYPE, WireFormatLite::DECLARED_TYPE>( \
|
||||
int tag_size, \
|
||||
uint32 tag, \
|
||||
io::CodedInputStream* input, \
|
||||
RepeatedField<CPPTYPE>* values) { \
|
||||
return ReadRepeatedFixedSizePrimitive< \
|
||||
CPPTYPE, WireFormatLite::DECLARED_TYPE>( \
|
||||
tag_size, tag, input, values); \
|
||||
}
|
||||
|
||||
READ_REPEATED_FIXED_SIZE_PRIMITIVE(uint32, TYPE_FIXED32)
|
||||
READ_REPEATED_FIXED_SIZE_PRIMITIVE(uint64, TYPE_FIXED64)
|
||||
READ_REPEATED_FIXED_SIZE_PRIMITIVE(int32, TYPE_SFIXED32)
|
||||
READ_REPEATED_FIXED_SIZE_PRIMITIVE(int64, TYPE_SFIXED64)
|
||||
READ_REPEATED_FIXED_SIZE_PRIMITIVE(float, TYPE_FLOAT)
|
||||
READ_REPEATED_FIXED_SIZE_PRIMITIVE(double, TYPE_DOUBLE)
|
||||
|
||||
#undef READ_REPEATED_FIXED_SIZE_PRIMITIVE
|
||||
|
||||
template <typename CType, enum WireFormatLite::FieldType DeclaredType>
|
||||
bool WireFormatLite::ReadRepeatedPrimitiveNoInline(
|
||||
int tag_size,
|
||||
uint32 tag,
|
||||
io::CodedInputStream* input,
|
||||
RepeatedField<CType>* value) {
|
||||
return ReadRepeatedPrimitive<CType, DeclaredType>(
|
||||
tag_size, tag, input, value);
|
||||
}
|
||||
|
||||
template <typename CType, enum WireFormatLite::FieldType DeclaredType>
|
||||
inline bool WireFormatLite::ReadPackedPrimitive(io::CodedInputStream* input,
|
||||
RepeatedField<CType>* values) {
|
||||
int length;
|
||||
if (!input->ReadVarintSizeAsInt(&length)) return false;
|
||||
io::CodedInputStream::Limit limit = input->PushLimit(length);
|
||||
while (input->BytesUntilLimit() > 0) {
|
||||
CType value;
|
||||
if (!ReadPrimitive<CType, DeclaredType>(input, &value)) return false;
|
||||
values->Add(value);
|
||||
}
|
||||
input->PopLimit(limit);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename CType, enum WireFormatLite::FieldType DeclaredType>
|
||||
inline bool WireFormatLite::ReadPackedFixedSizePrimitive(
|
||||
io::CodedInputStream* input, RepeatedField<CType>* values) {
|
||||
int length;
|
||||
if (!input->ReadVarintSizeAsInt(&length)) return false;
|
||||
const int old_entries = values->size();
|
||||
const int new_entries = length / static_cast<int>(sizeof(CType));
|
||||
const int new_bytes = new_entries * static_cast<int>(sizeof(CType));
|
||||
if (new_bytes != length) return false;
|
||||
// We would *like* to pre-allocate the buffer to write into (for
|
||||
// speed), but *must* avoid performing a very large allocation due
|
||||
// to a malicious user-supplied "length" above. So we have a fast
|
||||
// path that pre-allocates when the "length" is less than a bound.
|
||||
// We determine the bound by calling BytesUntilTotalBytesLimit() and
|
||||
// BytesUntilLimit(). These return -1 to mean "no limit set".
|
||||
// There are four cases:
|
||||
// TotalBytesLimit Limit
|
||||
// -1 -1 Use slow path.
|
||||
// -1 >= 0 Use fast path if length <= Limit.
|
||||
// >= 0 -1 Use slow path.
|
||||
// >= 0 >= 0 Use fast path if length <= min(both limits).
|
||||
int64 bytes_limit = input->BytesUntilTotalBytesLimit();
|
||||
if (bytes_limit == -1) {
|
||||
bytes_limit = input->BytesUntilLimit();
|
||||
} else {
|
||||
// parentheses around (std::min) prevents macro expansion of min(...)
|
||||
bytes_limit =
|
||||
(std::min)(bytes_limit, static_cast<int64>(input->BytesUntilLimit()));
|
||||
}
|
||||
if (bytes_limit >= new_bytes) {
|
||||
// Fast-path that pre-allocates *values to the final size.
|
||||
#if defined(PROTOBUF_LITTLE_ENDIAN)
|
||||
values->Resize(old_entries + new_entries, 0);
|
||||
// values->mutable_data() may change after Resize(), so do this after:
|
||||
void* dest = reinterpret_cast<void*>(values->mutable_data() + old_entries);
|
||||
if (!input->ReadRaw(dest, new_bytes)) {
|
||||
values->Truncate(old_entries);
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
values->Reserve(old_entries + new_entries);
|
||||
CType value;
|
||||
for (int i = 0; i < new_entries; ++i) {
|
||||
if (!ReadPrimitive<CType, DeclaredType>(input, &value)) return false;
|
||||
values->AddAlreadyReserved(value);
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
// This is the slow-path case where "length" may be too large to
|
||||
// safely allocate. We read as much as we can into *values
|
||||
// without pre-allocating "length" bytes.
|
||||
CType value;
|
||||
for (int i = 0; i < new_entries; ++i) {
|
||||
if (!ReadPrimitive<CType, DeclaredType>(input, &value)) return false;
|
||||
values->Add(value);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Specializations of ReadPackedPrimitive for the fixed size types, which use
|
||||
// an optimized code path.
|
||||
#define READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE(CPPTYPE, DECLARED_TYPE) \
|
||||
template <> \
|
||||
inline bool WireFormatLite::ReadPackedPrimitive< \
|
||||
CPPTYPE, WireFormatLite::DECLARED_TYPE>( \
|
||||
io::CodedInputStream* input, \
|
||||
RepeatedField<CPPTYPE>* values) { \
|
||||
return ReadPackedFixedSizePrimitive< \
|
||||
CPPTYPE, WireFormatLite::DECLARED_TYPE>(input, values); \
|
||||
}
|
||||
|
||||
READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE(uint32, TYPE_FIXED32)
|
||||
READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE(uint64, TYPE_FIXED64)
|
||||
READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE(int32, TYPE_SFIXED32)
|
||||
READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE(int64, TYPE_SFIXED64)
|
||||
READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE(float, TYPE_FLOAT)
|
||||
READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE(double, TYPE_DOUBLE)
|
||||
|
||||
#undef READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE
|
||||
|
||||
template <typename CType, enum WireFormatLite::FieldType DeclaredType>
|
||||
bool WireFormatLite::ReadPackedPrimitiveNoInline(io::CodedInputStream* input,
|
||||
RepeatedField<CType>* values) {
|
||||
return ReadPackedPrimitive<CType, DeclaredType>(input, values);
|
||||
}
|
||||
|
||||
|
||||
template<typename MessageType>
|
||||
inline bool WireFormatLite::ReadGroup(
|
||||
int field_number, io::CodedInputStream* input,
|
||||
MessageType* value) {
|
||||
if (!input->IncrementRecursionDepth()) return false;
|
||||
if (!value->MergePartialFromCodedStream(input)) return false;
|
||||
input->UnsafeDecrementRecursionDepth();
|
||||
// Make sure the last thing read was an end tag for this group.
|
||||
if (!input->LastTagWas(MakeTag(field_number, WIRETYPE_END_GROUP))) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
template<typename MessageType>
|
||||
inline bool WireFormatLite::ReadMessage(
|
||||
io::CodedInputStream* input, MessageType* value) {
|
||||
int length;
|
||||
if (!input->ReadVarintSizeAsInt(&length)) return false;
|
||||
std::pair<io::CodedInputStream::Limit, int> p =
|
||||
input->IncrementRecursionDepthAndPushLimit(length);
|
||||
if (p.second < 0 || !value->MergePartialFromCodedStream(input)) return false;
|
||||
// Make sure that parsing stopped when the limit was hit, not at an endgroup
|
||||
// tag.
|
||||
return input->DecrementRecursionDepthAndPopLimit(p.first);
|
||||
}
|
||||
|
||||
// ===================================================================
|
||||
|
||||
inline void WireFormatLite::WriteTag(int field_number, WireType type,
|
||||
io::CodedOutputStream* output) {
|
||||
output->WriteTag(MakeTag(field_number, type));
|
||||
}
|
||||
|
||||
inline void WireFormatLite::WriteInt32NoTag(int32 value,
|
||||
io::CodedOutputStream* output) {
|
||||
output->WriteVarint32SignExtended(value);
|
||||
}
|
||||
inline void WireFormatLite::WriteInt64NoTag(int64 value,
|
||||
io::CodedOutputStream* output) {
|
||||
output->WriteVarint64(static_cast<uint64>(value));
|
||||
}
|
||||
inline void WireFormatLite::WriteUInt32NoTag(uint32 value,
|
||||
io::CodedOutputStream* output) {
|
||||
output->WriteVarint32(value);
|
||||
}
|
||||
inline void WireFormatLite::WriteUInt64NoTag(uint64 value,
|
||||
io::CodedOutputStream* output) {
|
||||
output->WriteVarint64(value);
|
||||
}
|
||||
inline void WireFormatLite::WriteSInt32NoTag(int32 value,
|
||||
io::CodedOutputStream* output) {
|
||||
output->WriteVarint32(ZigZagEncode32(value));
|
||||
}
|
||||
inline void WireFormatLite::WriteSInt64NoTag(int64 value,
|
||||
io::CodedOutputStream* output) {
|
||||
output->WriteVarint64(ZigZagEncode64(value));
|
||||
}
|
||||
inline void WireFormatLite::WriteFixed32NoTag(uint32 value,
|
||||
io::CodedOutputStream* output) {
|
||||
output->WriteLittleEndian32(value);
|
||||
}
|
||||
inline void WireFormatLite::WriteFixed64NoTag(uint64 value,
|
||||
io::CodedOutputStream* output) {
|
||||
output->WriteLittleEndian64(value);
|
||||
}
|
||||
inline void WireFormatLite::WriteSFixed32NoTag(int32 value,
|
||||
io::CodedOutputStream* output) {
|
||||
output->WriteLittleEndian32(static_cast<uint32>(value));
|
||||
}
|
||||
inline void WireFormatLite::WriteSFixed64NoTag(int64 value,
|
||||
io::CodedOutputStream* output) {
|
||||
output->WriteLittleEndian64(static_cast<uint64>(value));
|
||||
}
|
||||
inline void WireFormatLite::WriteFloatNoTag(float value,
|
||||
io::CodedOutputStream* output) {
|
||||
output->WriteLittleEndian32(EncodeFloat(value));
|
||||
}
|
||||
inline void WireFormatLite::WriteDoubleNoTag(double value,
|
||||
io::CodedOutputStream* output) {
|
||||
output->WriteLittleEndian64(EncodeDouble(value));
|
||||
}
|
||||
inline void WireFormatLite::WriteBoolNoTag(bool value,
|
||||
io::CodedOutputStream* output) {
|
||||
output->WriteVarint32(value ? 1 : 0);
|
||||
}
|
||||
inline void WireFormatLite::WriteEnumNoTag(int value,
|
||||
io::CodedOutputStream* output) {
|
||||
output->WriteVarint32SignExtended(value);
|
||||
}
|
||||
|
||||
// See comment on ReadGroupNoVirtual to understand the need for this template
|
||||
// parameter name.
|
||||
template<typename MessageType_WorkAroundCppLookupDefect>
|
||||
inline void WireFormatLite::WriteGroupNoVirtual(
|
||||
int field_number, const MessageType_WorkAroundCppLookupDefect& value,
|
||||
io::CodedOutputStream* output) {
|
||||
WriteTag(field_number, WIRETYPE_START_GROUP, output);
|
||||
value.MessageType_WorkAroundCppLookupDefect::SerializeWithCachedSizes(output);
|
||||
WriteTag(field_number, WIRETYPE_END_GROUP, output);
|
||||
}
|
||||
template<typename MessageType_WorkAroundCppLookupDefect>
|
||||
inline void WireFormatLite::WriteMessageNoVirtual(
|
||||
int field_number, const MessageType_WorkAroundCppLookupDefect& value,
|
||||
io::CodedOutputStream* output) {
|
||||
WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
|
||||
output->WriteVarint32(
|
||||
value.MessageType_WorkAroundCppLookupDefect::GetCachedSize());
|
||||
value.MessageType_WorkAroundCppLookupDefect::SerializeWithCachedSizes(output);
|
||||
}
|
||||
|
||||
// ===================================================================
|
||||
|
||||
inline uint8* WireFormatLite::WriteTagToArray(int field_number,
|
||||
WireType type,
|
||||
uint8* target) {
|
||||
return io::CodedOutputStream::WriteTagToArray(MakeTag(field_number, type),
|
||||
target);
|
||||
}
|
||||
|
||||
inline uint8* WireFormatLite::WriteInt32NoTagToArray(int32 value,
|
||||
uint8* target) {
|
||||
return io::CodedOutputStream::WriteVarint32SignExtendedToArray(value, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteInt64NoTagToArray(int64 value,
|
||||
uint8* target) {
|
||||
return io::CodedOutputStream::WriteVarint64ToArray(
|
||||
static_cast<uint64>(value), target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteUInt32NoTagToArray(uint32 value,
|
||||
uint8* target) {
|
||||
return io::CodedOutputStream::WriteVarint32ToArray(value, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteUInt64NoTagToArray(uint64 value,
|
||||
uint8* target) {
|
||||
return io::CodedOutputStream::WriteVarint64ToArray(value, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteSInt32NoTagToArray(int32 value,
|
||||
uint8* target) {
|
||||
return io::CodedOutputStream::WriteVarint32ToArray(ZigZagEncode32(value),
|
||||
target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteSInt64NoTagToArray(int64 value,
|
||||
uint8* target) {
|
||||
return io::CodedOutputStream::WriteVarint64ToArray(ZigZagEncode64(value),
|
||||
target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteFixed32NoTagToArray(uint32 value,
|
||||
uint8* target) {
|
||||
return io::CodedOutputStream::WriteLittleEndian32ToArray(value, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteFixed64NoTagToArray(uint64 value,
|
||||
uint8* target) {
|
||||
return io::CodedOutputStream::WriteLittleEndian64ToArray(value, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteSFixed32NoTagToArray(int32 value,
|
||||
uint8* target) {
|
||||
return io::CodedOutputStream::WriteLittleEndian32ToArray(
|
||||
static_cast<uint32>(value), target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteSFixed64NoTagToArray(int64 value,
|
||||
uint8* target) {
|
||||
return io::CodedOutputStream::WriteLittleEndian64ToArray(
|
||||
static_cast<uint64>(value), target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteFloatNoTagToArray(float value,
|
||||
uint8* target) {
|
||||
return io::CodedOutputStream::WriteLittleEndian32ToArray(EncodeFloat(value),
|
||||
target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteDoubleNoTagToArray(double value,
|
||||
uint8* target) {
|
||||
return io::CodedOutputStream::WriteLittleEndian64ToArray(EncodeDouble(value),
|
||||
target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteBoolNoTagToArray(bool value,
|
||||
uint8* target) {
|
||||
return io::CodedOutputStream::WriteVarint32ToArray(value ? 1 : 0, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteEnumNoTagToArray(int value,
|
||||
uint8* target) {
|
||||
return io::CodedOutputStream::WriteVarint32SignExtendedToArray(value, target);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline uint8* WireFormatLite::WritePrimitiveNoTagToArray(
|
||||
const RepeatedField<T>& value,
|
||||
uint8* (*Writer)(T, uint8*), uint8* target) {
|
||||
const int n = value.size();
|
||||
GOOGLE_DCHECK_GT(n, 0);
|
||||
|
||||
const T* ii = value.unsafe_data();
|
||||
int i = 0;
|
||||
do {
|
||||
target = Writer(ii[i], target);
|
||||
} while (++i < n);
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline uint8* WireFormatLite::WriteFixedNoTagToArray(
|
||||
const RepeatedField<T>& value,
|
||||
uint8* (*Writer)(T, uint8*), uint8* target) {
|
||||
#if defined(PROTOBUF_LITTLE_ENDIAN)
|
||||
(void) Writer;
|
||||
|
||||
const int n = value.size();
|
||||
GOOGLE_DCHECK_GT(n, 0);
|
||||
|
||||
const T* ii = value.unsafe_data();
|
||||
const int bytes = n * static_cast<int>(sizeof(ii[0]));
|
||||
memcpy(target, ii, static_cast<size_t>(bytes));
|
||||
return target + bytes;
|
||||
#else
|
||||
return WritePrimitiveNoTagToArray(value, Writer, target);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline uint8* WireFormatLite::WriteInt32NoTagToArray(
|
||||
const RepeatedField< int32>& value, uint8* target) {
|
||||
return WritePrimitiveNoTagToArray(value, WriteInt32NoTagToArray, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteInt64NoTagToArray(
|
||||
const RepeatedField< int64>& value, uint8* target) {
|
||||
return WritePrimitiveNoTagToArray(value, WriteInt64NoTagToArray, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteUInt32NoTagToArray(
|
||||
const RepeatedField<uint32>& value, uint8* target) {
|
||||
return WritePrimitiveNoTagToArray(value, WriteUInt32NoTagToArray, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteUInt64NoTagToArray(
|
||||
const RepeatedField<uint64>& value, uint8* target) {
|
||||
return WritePrimitiveNoTagToArray(value, WriteUInt64NoTagToArray, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteSInt32NoTagToArray(
|
||||
const RepeatedField< int32>& value, uint8* target) {
|
||||
return WritePrimitiveNoTagToArray(value, WriteSInt32NoTagToArray, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteSInt64NoTagToArray(
|
||||
const RepeatedField< int64>& value, uint8* target) {
|
||||
return WritePrimitiveNoTagToArray(value, WriteSInt64NoTagToArray, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteFixed32NoTagToArray(
|
||||
const RepeatedField<uint32>& value, uint8* target) {
|
||||
return WriteFixedNoTagToArray(value, WriteFixed32NoTagToArray, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteFixed64NoTagToArray(
|
||||
const RepeatedField<uint64>& value, uint8* target) {
|
||||
return WriteFixedNoTagToArray(value, WriteFixed64NoTagToArray, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteSFixed32NoTagToArray(
|
||||
const RepeatedField< int32>& value, uint8* target) {
|
||||
return WriteFixedNoTagToArray(value, WriteSFixed32NoTagToArray, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteSFixed64NoTagToArray(
|
||||
const RepeatedField< int64>& value, uint8* target) {
|
||||
return WriteFixedNoTagToArray(value, WriteSFixed64NoTagToArray, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteFloatNoTagToArray(
|
||||
const RepeatedField< float>& value, uint8* target) {
|
||||
return WriteFixedNoTagToArray(value, WriteFloatNoTagToArray, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteDoubleNoTagToArray(
|
||||
const RepeatedField<double>& value, uint8* target) {
|
||||
return WriteFixedNoTagToArray(value, WriteDoubleNoTagToArray, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteBoolNoTagToArray(
|
||||
const RepeatedField< bool>& value, uint8* target) {
|
||||
return WritePrimitiveNoTagToArray(value, WriteBoolNoTagToArray, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteEnumNoTagToArray(
|
||||
const RepeatedField< int>& value, uint8* target) {
|
||||
return WritePrimitiveNoTagToArray(value, WriteEnumNoTagToArray, target);
|
||||
}
|
||||
|
||||
inline uint8* WireFormatLite::WriteInt32ToArray(int field_number,
|
||||
int32 value,
|
||||
uint8* target) {
|
||||
target = WriteTagToArray(field_number, WIRETYPE_VARINT, target);
|
||||
return WriteInt32NoTagToArray(value, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteInt64ToArray(int field_number,
|
||||
int64 value,
|
||||
uint8* target) {
|
||||
target = WriteTagToArray(field_number, WIRETYPE_VARINT, target);
|
||||
return WriteInt64NoTagToArray(value, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteUInt32ToArray(int field_number,
|
||||
uint32 value,
|
||||
uint8* target) {
|
||||
target = WriteTagToArray(field_number, WIRETYPE_VARINT, target);
|
||||
return WriteUInt32NoTagToArray(value, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteUInt64ToArray(int field_number,
|
||||
uint64 value,
|
||||
uint8* target) {
|
||||
target = WriteTagToArray(field_number, WIRETYPE_VARINT, target);
|
||||
return WriteUInt64NoTagToArray(value, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteSInt32ToArray(int field_number,
|
||||
int32 value,
|
||||
uint8* target) {
|
||||
target = WriteTagToArray(field_number, WIRETYPE_VARINT, target);
|
||||
return WriteSInt32NoTagToArray(value, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteSInt64ToArray(int field_number,
|
||||
int64 value,
|
||||
uint8* target) {
|
||||
target = WriteTagToArray(field_number, WIRETYPE_VARINT, target);
|
||||
return WriteSInt64NoTagToArray(value, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteFixed32ToArray(int field_number,
|
||||
uint32 value,
|
||||
uint8* target) {
|
||||
target = WriteTagToArray(field_number, WIRETYPE_FIXED32, target);
|
||||
return WriteFixed32NoTagToArray(value, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteFixed64ToArray(int field_number,
|
||||
uint64 value,
|
||||
uint8* target) {
|
||||
target = WriteTagToArray(field_number, WIRETYPE_FIXED64, target);
|
||||
return WriteFixed64NoTagToArray(value, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteSFixed32ToArray(int field_number,
|
||||
int32 value,
|
||||
uint8* target) {
|
||||
target = WriteTagToArray(field_number, WIRETYPE_FIXED32, target);
|
||||
return WriteSFixed32NoTagToArray(value, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteSFixed64ToArray(int field_number,
|
||||
int64 value,
|
||||
uint8* target) {
|
||||
target = WriteTagToArray(field_number, WIRETYPE_FIXED64, target);
|
||||
return WriteSFixed64NoTagToArray(value, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteFloatToArray(int field_number,
|
||||
float value,
|
||||
uint8* target) {
|
||||
target = WriteTagToArray(field_number, WIRETYPE_FIXED32, target);
|
||||
return WriteFloatNoTagToArray(value, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteDoubleToArray(int field_number,
|
||||
double value,
|
||||
uint8* target) {
|
||||
target = WriteTagToArray(field_number, WIRETYPE_FIXED64, target);
|
||||
return WriteDoubleNoTagToArray(value, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteBoolToArray(int field_number,
|
||||
bool value,
|
||||
uint8* target) {
|
||||
target = WriteTagToArray(field_number, WIRETYPE_VARINT, target);
|
||||
return WriteBoolNoTagToArray(value, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteEnumToArray(int field_number,
|
||||
int value,
|
||||
uint8* target) {
|
||||
target = WriteTagToArray(field_number, WIRETYPE_VARINT, target);
|
||||
return WriteEnumNoTagToArray(value, target);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline uint8* WireFormatLite::WritePrimitiveToArray(
|
||||
int field_number,
|
||||
const RepeatedField<T>& value,
|
||||
uint8* (*Writer)(int, T, uint8*), uint8* target) {
|
||||
const int n = value.size();
|
||||
if (n == 0) {
|
||||
return target;
|
||||
}
|
||||
|
||||
const T* ii = value.unsafe_data();
|
||||
int i = 0;
|
||||
do {
|
||||
target = Writer(field_number, ii[i], target);
|
||||
} while (++i < n);
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
inline uint8* WireFormatLite::WriteInt32ToArray(
|
||||
int field_number, const RepeatedField< int32>& value, uint8* target) {
|
||||
return WritePrimitiveToArray(field_number, value, WriteInt32ToArray, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteInt64ToArray(
|
||||
int field_number, const RepeatedField< int64>& value, uint8* target) {
|
||||
return WritePrimitiveToArray(field_number, value, WriteInt64ToArray, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteUInt32ToArray(
|
||||
int field_number, const RepeatedField<uint32>& value, uint8* target) {
|
||||
return WritePrimitiveToArray(field_number, value, WriteUInt32ToArray, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteUInt64ToArray(
|
||||
int field_number, const RepeatedField<uint64>& value, uint8* target) {
|
||||
return WritePrimitiveToArray(field_number, value, WriteUInt64ToArray, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteSInt32ToArray(
|
||||
int field_number, const RepeatedField< int32>& value, uint8* target) {
|
||||
return WritePrimitiveToArray(field_number, value, WriteSInt32ToArray, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteSInt64ToArray(
|
||||
int field_number, const RepeatedField< int64>& value, uint8* target) {
|
||||
return WritePrimitiveToArray(field_number, value, WriteSInt64ToArray, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteFixed32ToArray(
|
||||
int field_number, const RepeatedField<uint32>& value, uint8* target) {
|
||||
return WritePrimitiveToArray(
|
||||
field_number, value, WriteFixed32ToArray, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteFixed64ToArray(
|
||||
int field_number, const RepeatedField<uint64>& value, uint8* target) {
|
||||
return WritePrimitiveToArray(
|
||||
field_number, value, WriteFixed64ToArray, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteSFixed32ToArray(
|
||||
int field_number, const RepeatedField< int32>& value, uint8* target) {
|
||||
return WritePrimitiveToArray(
|
||||
field_number, value, WriteSFixed32ToArray, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteSFixed64ToArray(
|
||||
int field_number, const RepeatedField< int64>& value, uint8* target) {
|
||||
return WritePrimitiveToArray(
|
||||
field_number, value, WriteSFixed64ToArray, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteFloatToArray(
|
||||
int field_number, const RepeatedField< float>& value, uint8* target) {
|
||||
return WritePrimitiveToArray(field_number, value, WriteFloatToArray, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteDoubleToArray(
|
||||
int field_number, const RepeatedField<double>& value, uint8* target) {
|
||||
return WritePrimitiveToArray(field_number, value, WriteDoubleToArray, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteBoolToArray(
|
||||
int field_number, const RepeatedField< bool>& value, uint8* target) {
|
||||
return WritePrimitiveToArray(field_number, value, WriteBoolToArray, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteEnumToArray(
|
||||
int field_number, const RepeatedField< int>& value, uint8* target) {
|
||||
return WritePrimitiveToArray(field_number, value, WriteEnumToArray, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteStringToArray(int field_number,
|
||||
const string& value,
|
||||
uint8* target) {
|
||||
// String is for UTF-8 text only
|
||||
// WARNING: In wire_format.cc, both strings and bytes are handled by
|
||||
// WriteString() to avoid code duplication. If the implementations become
|
||||
// different, you will need to update that usage.
|
||||
target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target);
|
||||
return io::CodedOutputStream::WriteStringWithSizeToArray(value, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteBytesToArray(int field_number,
|
||||
const string& value,
|
||||
uint8* target) {
|
||||
target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target);
|
||||
return io::CodedOutputStream::WriteStringWithSizeToArray(value, target);
|
||||
}
|
||||
|
||||
|
||||
template<typename MessageType>
|
||||
inline uint8* WireFormatLite::InternalWriteGroupToArray(
|
||||
int field_number, const MessageType& value, bool deterministic,
|
||||
uint8* target) {
|
||||
target = WriteTagToArray(field_number, WIRETYPE_START_GROUP, target);
|
||||
target = value.InternalSerializeWithCachedSizesToArray(deterministic, target);
|
||||
return WriteTagToArray(field_number, WIRETYPE_END_GROUP, target);
|
||||
}
|
||||
template<typename MessageType>
|
||||
inline uint8* WireFormatLite::InternalWriteMessageToArray(
|
||||
int field_number, const MessageType& value, bool deterministic,
|
||||
uint8* target) {
|
||||
target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target);
|
||||
target = io::CodedOutputStream::WriteVarint32ToArray(
|
||||
static_cast<uint32>(value.GetCachedSize()), target);
|
||||
return value.InternalSerializeWithCachedSizesToArray(deterministic, target);
|
||||
}
|
||||
|
||||
// See comment on ReadGroupNoVirtual to understand the need for this template
|
||||
// parameter name.
|
||||
template<typename MessageType_WorkAroundCppLookupDefect>
|
||||
inline uint8* WireFormatLite::InternalWriteGroupNoVirtualToArray(
|
||||
int field_number, const MessageType_WorkAroundCppLookupDefect& value,
|
||||
bool deterministic, uint8* target) {
|
||||
target = WriteTagToArray(field_number, WIRETYPE_START_GROUP, target);
|
||||
target = value.MessageType_WorkAroundCppLookupDefect::
|
||||
InternalSerializeWithCachedSizesToArray(deterministic, target);
|
||||
return WriteTagToArray(field_number, WIRETYPE_END_GROUP, target);
|
||||
}
|
||||
template<typename MessageType_WorkAroundCppLookupDefect>
|
||||
inline uint8* WireFormatLite::InternalWriteMessageNoVirtualToArray(
|
||||
int field_number, const MessageType_WorkAroundCppLookupDefect& value,
|
||||
bool deterministic, uint8* target) {
|
||||
target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target);
|
||||
target = io::CodedOutputStream::WriteVarint32ToArray(
|
||||
static_cast<uint32>(
|
||||
value.MessageType_WorkAroundCppLookupDefect::GetCachedSize()),
|
||||
target);
|
||||
return value.MessageType_WorkAroundCppLookupDefect::
|
||||
InternalSerializeWithCachedSizesToArray(deterministic, target);
|
||||
}
|
||||
|
||||
// ===================================================================
|
||||
|
||||
inline size_t WireFormatLite::Int32Size(int32 value) {
|
||||
return io::CodedOutputStream::VarintSize32SignExtended(value);
|
||||
}
|
||||
inline size_t WireFormatLite::Int64Size(int64 value) {
|
||||
return io::CodedOutputStream::VarintSize64(static_cast<uint64>(value));
|
||||
}
|
||||
inline size_t WireFormatLite::UInt32Size(uint32 value) {
|
||||
return io::CodedOutputStream::VarintSize32(value);
|
||||
}
|
||||
inline size_t WireFormatLite::UInt64Size(uint64 value) {
|
||||
return io::CodedOutputStream::VarintSize64(value);
|
||||
}
|
||||
inline size_t WireFormatLite::SInt32Size(int32 value) {
|
||||
return io::CodedOutputStream::VarintSize32(ZigZagEncode32(value));
|
||||
}
|
||||
inline size_t WireFormatLite::SInt64Size(int64 value) {
|
||||
return io::CodedOutputStream::VarintSize64(ZigZagEncode64(value));
|
||||
}
|
||||
inline size_t WireFormatLite::EnumSize(int value) {
|
||||
return io::CodedOutputStream::VarintSize32SignExtended(value);
|
||||
}
|
||||
|
||||
inline size_t WireFormatLite::StringSize(const string& value) {
|
||||
return LengthDelimitedSize(value.size());
|
||||
}
|
||||
inline size_t WireFormatLite::BytesSize(const string& value) {
|
||||
return LengthDelimitedSize(value.size());
|
||||
}
|
||||
|
||||
|
||||
template<typename MessageType>
|
||||
inline size_t WireFormatLite::GroupSize(const MessageType& value) {
|
||||
return value.ByteSizeLong();
|
||||
}
|
||||
template<typename MessageType>
|
||||
inline size_t WireFormatLite::MessageSize(const MessageType& value) {
|
||||
return LengthDelimitedSize(value.ByteSizeLong());
|
||||
}
|
||||
|
||||
// See comment on ReadGroupNoVirtual to understand the need for this template
|
||||
// parameter name.
|
||||
template<typename MessageType_WorkAroundCppLookupDefect>
|
||||
inline size_t WireFormatLite::GroupSizeNoVirtual(
|
||||
const MessageType_WorkAroundCppLookupDefect& value) {
|
||||
return value.MessageType_WorkAroundCppLookupDefect::ByteSizeLong();
|
||||
}
|
||||
template<typename MessageType_WorkAroundCppLookupDefect>
|
||||
inline size_t WireFormatLite::MessageSizeNoVirtual(
|
||||
const MessageType_WorkAroundCppLookupDefect& value) {
|
||||
return LengthDelimitedSize(
|
||||
value.MessageType_WorkAroundCppLookupDefect::ByteSizeLong());
|
||||
}
|
||||
|
||||
inline size_t WireFormatLite::LengthDelimitedSize(size_t length) {
|
||||
// The static_cast here prevents an error in certain compiler configurations
|
||||
// but is not technically correct--if length is too large to fit in a uint32
|
||||
// then it will be silently truncated. We will need to fix this if we ever
|
||||
// decide to start supporting serialized messages greater than 2 GiB in size.
|
||||
return length + io::CodedOutputStream::VarintSize32(
|
||||
static_cast<uint32>(length));
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_WIRE_FORMAT_LITE_INL_H__
|
63
third_party/protobuf-lite/implicit_weak_message.cc
vendored
Normal file
63
third_party/protobuf-lite/implicit_weak_message.cc
vendored
Normal file
@ -0,0 +1,63 @@
|
||||
// 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.
|
||||
|
||||
#include <google/protobuf/implicit_weak_message.h>
|
||||
|
||||
#include <google/protobuf/stubs/once.h>
|
||||
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
|
||||
#include <google/protobuf/wire_format_lite.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
bool ImplicitWeakMessage::MergePartialFromCodedStream(io::CodedInputStream* input) {
|
||||
io::StringOutputStream string_stream(&data_);
|
||||
io::CodedOutputStream coded_stream(&string_stream, false);
|
||||
return WireFormatLite::SkipMessage(input, &coded_stream);
|
||||
}
|
||||
|
||||
::google::protobuf::internal::ExplicitlyConstructed<ImplicitWeakMessage>
|
||||
implicit_weak_message_default_instance;
|
||||
GOOGLE_PROTOBUF_DECLARE_ONCE(implicit_weak_message_once_init_);
|
||||
|
||||
void InitImplicitWeakMessageDefaultInstance() {
|
||||
implicit_weak_message_default_instance.DefaultConstruct();
|
||||
}
|
||||
|
||||
const ImplicitWeakMessage* ImplicitWeakMessage::default_instance() {
|
||||
::google::protobuf::GoogleOnceInit(&implicit_weak_message_once_init_,
|
||||
&InitImplicitWeakMessageDefaultInstance);
|
||||
return &implicit_weak_message_default_instance.get();
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
201
third_party/protobuf-lite/int128.cc
vendored
Normal file
201
third_party/protobuf-lite/int128.cc
vendored
Normal file
@ -0,0 +1,201 @@
|
||||
// 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.
|
||||
|
||||
#include <google/protobuf/stubs/int128.h>
|
||||
|
||||
#include <iomanip>
|
||||
#include <ostream> // NOLINT(readability/streams)
|
||||
#include <sstream>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
const uint128_pod kuint128max = {
|
||||
static_cast<uint64>(GOOGLE_LONGLONG(0xFFFFFFFFFFFFFFFF)),
|
||||
static_cast<uint64>(GOOGLE_LONGLONG(0xFFFFFFFFFFFFFFFF))
|
||||
};
|
||||
|
||||
// Returns the 0-based position of the last set bit (i.e., most significant bit)
|
||||
// in the given uint64. The argument may not be 0.
|
||||
//
|
||||
// For example:
|
||||
// Given: 5 (decimal) == 101 (binary)
|
||||
// Returns: 2
|
||||
#define STEP(T, n, pos, sh) \
|
||||
do { \
|
||||
if ((n) >= (static_cast<T>(1) << (sh))) { \
|
||||
(n) = (n) >> (sh); \
|
||||
(pos) |= (sh); \
|
||||
} \
|
||||
} while (0)
|
||||
static inline int Fls64(uint64 n) {
|
||||
GOOGLE_DCHECK_NE(0, n);
|
||||
int pos = 0;
|
||||
STEP(uint64, n, pos, 0x20);
|
||||
uint32 n32 = n;
|
||||
STEP(uint32, n32, pos, 0x10);
|
||||
STEP(uint32, n32, pos, 0x08);
|
||||
STEP(uint32, n32, pos, 0x04);
|
||||
return pos + ((GOOGLE_ULONGLONG(0x3333333322221100) >> (n32 << 2)) & 0x3);
|
||||
}
|
||||
#undef STEP
|
||||
|
||||
// Like Fls64() above, but returns the 0-based position of the last set bit
|
||||
// (i.e., most significant bit) in the given uint128. The argument may not be 0.
|
||||
static inline int Fls128(uint128 n) {
|
||||
if (uint64 hi = Uint128High64(n)) {
|
||||
return Fls64(hi) + 64;
|
||||
}
|
||||
return Fls64(Uint128Low64(n));
|
||||
}
|
||||
|
||||
// Long division/modulo for uint128 implemented using the shift-subtract
|
||||
// division algorithm adapted from:
|
||||
// http://stackoverflow.com/questions/5386377/division-without-using
|
||||
void uint128::DivModImpl(uint128 dividend, uint128 divisor,
|
||||
uint128* quotient_ret, uint128* remainder_ret) {
|
||||
if (divisor == 0) {
|
||||
GOOGLE_LOG(FATAL) << "Division or mod by zero: dividend.hi=" << dividend.hi_
|
||||
<< ", lo=" << dividend.lo_;
|
||||
}
|
||||
|
||||
if (divisor > dividend) {
|
||||
*quotient_ret = 0;
|
||||
*remainder_ret = dividend;
|
||||
return;
|
||||
}
|
||||
|
||||
if (divisor == dividend) {
|
||||
*quotient_ret = 1;
|
||||
*remainder_ret = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
uint128 denominator = divisor;
|
||||
uint128 position = 1;
|
||||
uint128 quotient = 0;
|
||||
|
||||
// Left aligns the MSB of the denominator and the dividend.
|
||||
int shift = Fls128(dividend) - Fls128(denominator);
|
||||
denominator <<= shift;
|
||||
position <<= shift;
|
||||
|
||||
// Uses shift-subtract algorithm to divide dividend by denominator. The
|
||||
// remainder will be left in dividend.
|
||||
while (position > 0) {
|
||||
if (dividend >= denominator) {
|
||||
dividend -= denominator;
|
||||
quotient |= position;
|
||||
}
|
||||
position >>= 1;
|
||||
denominator >>= 1;
|
||||
}
|
||||
|
||||
*quotient_ret = quotient;
|
||||
*remainder_ret = dividend;
|
||||
}
|
||||
|
||||
uint128& uint128::operator/=(const uint128& divisor) {
|
||||
uint128 quotient = 0;
|
||||
uint128 remainder = 0;
|
||||
DivModImpl(*this, divisor, "ient, &remainder);
|
||||
*this = quotient;
|
||||
return *this;
|
||||
}
|
||||
uint128& uint128::operator%=(const uint128& divisor) {
|
||||
uint128 quotient = 0;
|
||||
uint128 remainder = 0;
|
||||
DivModImpl(*this, divisor, "ient, &remainder);
|
||||
*this = remainder;
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& o, const uint128& b) {
|
||||
std::ios_base::fmtflags flags = o.flags();
|
||||
|
||||
// Select a divisor which is the largest power of the base < 2^64.
|
||||
uint128 div;
|
||||
std::streamsize div_base_log;
|
||||
switch (flags & std::ios::basefield) {
|
||||
case std::ios::hex:
|
||||
div = static_cast<uint64>(GOOGLE_ULONGLONG(0x1000000000000000)); // 16^15
|
||||
div_base_log = 15;
|
||||
break;
|
||||
case std::ios::oct:
|
||||
div = static_cast<uint64>(GOOGLE_ULONGLONG(01000000000000000000000)); // 8^21
|
||||
div_base_log = 21;
|
||||
break;
|
||||
default: // std::ios::dec
|
||||
div = static_cast<uint64>(GOOGLE_ULONGLONG(10000000000000000000)); // 10^19
|
||||
div_base_log = 19;
|
||||
break;
|
||||
}
|
||||
|
||||
// Now piece together the uint128 representation from three chunks of
|
||||
// the original value, each less than "div" and therefore representable
|
||||
// as a uint64.
|
||||
std::ostringstream os;
|
||||
std::ios_base::fmtflags copy_mask =
|
||||
std::ios::basefield | std::ios::showbase | std::ios::uppercase;
|
||||
os.setf(flags & copy_mask, copy_mask);
|
||||
uint128 high = b;
|
||||
uint128 low;
|
||||
uint128::DivModImpl(high, div, &high, &low);
|
||||
uint128 mid;
|
||||
uint128::DivModImpl(high, div, &high, &mid);
|
||||
if (high.lo_ != 0) {
|
||||
os << high.lo_;
|
||||
os << std::noshowbase << std::setfill('0') << std::setw(div_base_log);
|
||||
os << mid.lo_;
|
||||
os << std::setw(div_base_log);
|
||||
} else if (mid.lo_ != 0) {
|
||||
os << mid.lo_;
|
||||
os << std::noshowbase << std::setfill('0') << std::setw(div_base_log);
|
||||
}
|
||||
os << low.lo_;
|
||||
std::string rep = os.str();
|
||||
|
||||
// Add the requisite padding.
|
||||
std::streamsize width = o.width(0);
|
||||
if (width > rep.size()) {
|
||||
if ((flags & std::ios::adjustfield) == std::ios::left) {
|
||||
rep.append(width - rep.size(), o.fill());
|
||||
} else {
|
||||
rep.insert(static_cast<std::string::size_type>(0),
|
||||
width - rep.size(), o.fill());
|
||||
}
|
||||
}
|
||||
|
||||
// Stream the final representation in a single "<<" call.
|
||||
return o << rep;
|
||||
}
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
414
third_party/protobuf-lite/io_win32.cc
vendored
Normal file
414
third_party/protobuf-lite/io_win32.cc
vendored
Normal file
@ -0,0 +1,414 @@
|
||||
// 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)
|
||||
//
|
||||
// Implementation for long-path-aware open/mkdir/access/etc. on Windows, as well
|
||||
// as for the supporting utility functions.
|
||||
//
|
||||
// These functions convert the input path to an absolute Windows path
|
||||
// with "\\?\" prefix, then pass that to _wopen/_wmkdir/_waccess/etc.
|
||||
// (declared in <io.h>) respectively. This allows working with files/directories
|
||||
// whose paths are longer than MAX_PATH (260 chars).
|
||||
//
|
||||
// This file is only used on Windows, it's empty on other platforms.
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
||||
// Comment this out to fall back to using the ANSI versions (open, mkdir, ...)
|
||||
// instead of the Unicode ones (_wopen, _wmkdir, ...). Doing so can be useful to
|
||||
// debug failing tests if that's caused by the long path support.
|
||||
#define SUPPORT_LONGPATHS
|
||||
|
||||
#include <ctype.h>
|
||||
#include <direct.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <io.h>
|
||||
#include <memory>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <wctype.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include <google/protobuf/stubs/io_win32.h>
|
||||
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
namespace win32 {
|
||||
namespace {
|
||||
|
||||
using std::string;
|
||||
using std::wstring;
|
||||
|
||||
template <typename char_type>
|
||||
struct CharTraits {
|
||||
static bool is_alpha(char_type ch);
|
||||
};
|
||||
|
||||
template <>
|
||||
struct CharTraits<char> {
|
||||
static bool is_alpha(char ch) { return isalpha(ch); }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct CharTraits<wchar_t> {
|
||||
static bool is_alpha(wchar_t ch) { return iswalpha(ch); }
|
||||
};
|
||||
|
||||
template <typename char_type>
|
||||
bool null_or_empty(const char_type* s) {
|
||||
return s == NULL || *s == 0;
|
||||
}
|
||||
|
||||
// Returns true if the path starts with a drive letter, e.g. "c:".
|
||||
// Note that this won't check for the "\" after the drive letter, so this also
|
||||
// returns true for "c:foo" (which is "c:\${PWD}\foo").
|
||||
// This check requires that a path not have a longpath prefix ("\\?\").
|
||||
template <typename char_type>
|
||||
bool has_drive_letter(const char_type* ch) {
|
||||
return CharTraits<char_type>::is_alpha(ch[0]) && ch[1] == ':';
|
||||
}
|
||||
|
||||
// Returns true if the path starts with a longpath prefix ("\\?\").
|
||||
template <typename char_type>
|
||||
bool has_longpath_prefix(const char_type* path) {
|
||||
return path[0] == '\\' && path[1] == '\\' && path[2] == '?' &&
|
||||
path[3] == '\\';
|
||||
}
|
||||
|
||||
template <typename char_type>
|
||||
bool is_separator(char_type c) {
|
||||
return c == '/' || c == '\\';
|
||||
}
|
||||
|
||||
// Returns true if the path starts with a drive specifier (e.g. "c:\").
|
||||
template <typename char_type>
|
||||
bool is_path_absolute(const char_type* path) {
|
||||
return has_drive_letter(path) && is_separator(path[2]);
|
||||
}
|
||||
|
||||
template <typename char_type>
|
||||
bool is_drive_relative(const char_type* path) {
|
||||
return has_drive_letter(path) && (path[2] == 0 || !is_separator(path[2]));
|
||||
}
|
||||
|
||||
wstring join_paths(const wstring& path1, const wstring& path2) {
|
||||
if (path1.empty() || is_path_absolute(path2.c_str()) ||
|
||||
has_longpath_prefix(path2.c_str())) {
|
||||
return path2;
|
||||
}
|
||||
if (path2.empty()) {
|
||||
return path1;
|
||||
}
|
||||
|
||||
if (is_separator(path1[path1.size() - 1])) {
|
||||
return is_separator(path2[0]) ? (path1 + path2.substr(1))
|
||||
: (path1 + path2);
|
||||
} else {
|
||||
return is_separator(path2[0]) ? (path1 + path2)
|
||||
: (path1 + L'\\' + path2);
|
||||
}
|
||||
}
|
||||
|
||||
wstring normalize(wstring path) {
|
||||
if (has_longpath_prefix(path.c_str())) {
|
||||
path = path.substr(4);
|
||||
}
|
||||
|
||||
static const wstring dot(L".");
|
||||
static const wstring dotdot(L"..");
|
||||
const WCHAR* p = path.c_str();
|
||||
|
||||
std::vector<wstring> segments;
|
||||
int segment_start = -1;
|
||||
// Find the path segments in `path` (separated by "/").
|
||||
for (int i = 0;; ++i) {
|
||||
if (!is_separator(p[i]) && p[i] != L'\0') {
|
||||
// The current character does not end a segment, so start one unless it's
|
||||
// already started.
|
||||
if (segment_start < 0) {
|
||||
segment_start = i;
|
||||
}
|
||||
} else if (segment_start >= 0 && i > segment_start) {
|
||||
// The current character is "/" or "\0", so this ends a segment.
|
||||
// Add that to `segments` if there's anything to add; handle "." and "..".
|
||||
wstring segment(p, segment_start, i - segment_start);
|
||||
segment_start = -1;
|
||||
if (segment == dotdot) {
|
||||
if (!segments.empty() &&
|
||||
(!has_drive_letter(segments[0].c_str()) || segments.size() > 1)) {
|
||||
segments.pop_back();
|
||||
}
|
||||
} else if (segment != dot && !segment.empty()) {
|
||||
segments.push_back(segment);
|
||||
}
|
||||
}
|
||||
if (p[i] == L'\0') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle the case when `path` is just a drive specifier (or some degenerate
|
||||
// form of it, e.g. "c:\..").
|
||||
if (segments.size() == 1 && segments[0].size() == 2 &&
|
||||
has_drive_letter(segments[0].c_str())) {
|
||||
return segments[0] + L'\\';
|
||||
}
|
||||
|
||||
// Join all segments.
|
||||
bool first = true;
|
||||
std::wstringstream result;
|
||||
for (int i = 0; i < segments.size(); ++i) {
|
||||
if (!first) {
|
||||
result << L'\\';
|
||||
}
|
||||
first = false;
|
||||
result << segments[i];
|
||||
}
|
||||
// Preserve trailing separator if the input contained it.
|
||||
if (!path.empty() && is_separator(p[path.size() - 1])) {
|
||||
result << L'\\';
|
||||
}
|
||||
return result.str();
|
||||
}
|
||||
|
||||
bool as_windows_path(const char* path, wstring* result) {
|
||||
if (null_or_empty(path)) {
|
||||
result->clear();
|
||||
return true;
|
||||
}
|
||||
wstring wpath;
|
||||
if (!strings::utf8_to_wcs(path, &wpath)) {
|
||||
return false;
|
||||
}
|
||||
if (has_longpath_prefix(wpath.c_str())) {
|
||||
*result = wpath;
|
||||
return true;
|
||||
}
|
||||
if (is_separator(path[0]) || is_drive_relative(path)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (!is_path_absolute(wpath.c_str())) {
|
||||
int size = ::GetCurrentDirectoryW(0, NULL);
|
||||
if (size == 0 && GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
|
||||
return false;
|
||||
}
|
||||
std::unique_ptr<WCHAR[]> wcwd(new WCHAR[size]);
|
||||
::GetCurrentDirectoryW(size, wcwd.get());
|
||||
wpath = join_paths(wcwd.get(), wpath);
|
||||
}
|
||||
wpath = normalize(wpath);
|
||||
if (!has_longpath_prefix(wpath.c_str())) {
|
||||
// Add the "\\?\" prefix unconditionally. This way we prevent the Win32 API
|
||||
// from processing the path and "helpfully" removing trailing dots from the
|
||||
// path, for example.
|
||||
// See https://github.com/bazelbuild/bazel/issues/2935
|
||||
wpath = wstring(L"\\\\?\\") + wpath;
|
||||
}
|
||||
*result = wpath;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int open(const char* path, int flags, int mode) {
|
||||
#ifdef SUPPORT_LONGPATHS
|
||||
wstring wpath;
|
||||
if (!as_windows_path(path, &wpath)) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
return ::_wopen(wpath.c_str(), flags, mode);
|
||||
#else
|
||||
return ::_open(path, flags, mode);
|
||||
#endif
|
||||
}
|
||||
|
||||
int mkdir(const char* path, int _mode) {
|
||||
#ifdef SUPPORT_LONGPATHS
|
||||
wstring wpath;
|
||||
if (!as_windows_path(path, &wpath)) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
return ::_wmkdir(wpath.c_str());
|
||||
#else // not SUPPORT_LONGPATHS
|
||||
return ::_mkdir(path);
|
||||
#endif // not SUPPORT_LONGPATHS
|
||||
}
|
||||
|
||||
int access(const char* path, int mode) {
|
||||
#ifdef SUPPORT_LONGPATHS
|
||||
wstring wpath;
|
||||
if (!as_windows_path(path, &wpath)) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
return ::_waccess(wpath.c_str(), mode);
|
||||
#else
|
||||
return ::_access(path, mode);
|
||||
#endif
|
||||
}
|
||||
|
||||
int chdir(const char* path) {
|
||||
#ifdef SUPPORT_LONGPATHS
|
||||
wstring wpath;
|
||||
if (!as_windows_path(path, &wpath)) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
return ::_wchdir(wpath.c_str());
|
||||
#else
|
||||
return ::_chdir(path);
|
||||
#endif
|
||||
}
|
||||
|
||||
int stat(const char* path, struct _stat* buffer) {
|
||||
#ifdef SUPPORT_LONGPATHS
|
||||
wstring wpath;
|
||||
if (!as_windows_path(path, &wpath)) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
return ::_wstat(wpath.c_str(), buffer);
|
||||
#else // not SUPPORT_LONGPATHS
|
||||
return ::_stat(path, buffer);
|
||||
#endif // not SUPPORT_LONGPATHS
|
||||
}
|
||||
|
||||
FILE* fopen(const char* path, const char* mode) {
|
||||
#ifdef SUPPORT_LONGPATHS
|
||||
if (null_or_empty(path)) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
wstring wpath;
|
||||
if (!as_windows_path(path, &wpath)) {
|
||||
errno = ENOENT;
|
||||
return NULL;
|
||||
}
|
||||
wstring wmode;
|
||||
if (!strings::utf8_to_wcs(mode, &wmode)) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
return ::_wfopen(wpath.c_str(), wmode.c_str());
|
||||
#else
|
||||
return ::fopen(path, mode);
|
||||
#endif
|
||||
}
|
||||
|
||||
int close(int fd) { return ::close(fd); }
|
||||
|
||||
int dup(int fd) { return ::_dup(fd); }
|
||||
|
||||
int dup2(int fd1, int fd2) { return ::_dup2(fd1, fd2); }
|
||||
|
||||
int read(int fd, void* buffer, size_t size) {
|
||||
return ::_read(fd, buffer, size);
|
||||
}
|
||||
|
||||
int setmode(int fd, int mode) { return ::_setmode(fd, mode); }
|
||||
|
||||
int write(int fd, const void* buffer, size_t size) {
|
||||
return ::_write(fd, buffer, size);
|
||||
}
|
||||
|
||||
wstring testonly_utf8_to_winpath(const char* path) {
|
||||
wstring wpath;
|
||||
return as_windows_path(path, &wpath) ? wpath : wstring();
|
||||
}
|
||||
|
||||
namespace strings {
|
||||
|
||||
bool wcs_to_mbs(const WCHAR* s, string* out, bool outUtf8) {
|
||||
if (null_or_empty(s)) {
|
||||
out->clear();
|
||||
return true;
|
||||
}
|
||||
BOOL usedDefaultChar = FALSE;
|
||||
SetLastError(0);
|
||||
int size = WideCharToMultiByte(
|
||||
outUtf8 ? CP_UTF8 : CP_ACP, 0, s, -1, NULL, 0, NULL,
|
||||
outUtf8 ? NULL : &usedDefaultChar);
|
||||
if ((size == 0 && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
|
||||
|| usedDefaultChar) {
|
||||
return false;
|
||||
}
|
||||
std::unique_ptr<CHAR[]> astr(new CHAR[size]);
|
||||
WideCharToMultiByte(
|
||||
outUtf8 ? CP_UTF8 : CP_ACP, 0, s, -1, astr.get(), size, NULL, NULL);
|
||||
out->assign(astr.get());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mbs_to_wcs(const char* s, wstring* out, bool inUtf8) {
|
||||
if (null_or_empty(s)) {
|
||||
out->clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
SetLastError(0);
|
||||
int size =
|
||||
MultiByteToWideChar(inUtf8 ? CP_UTF8 : CP_ACP, 0, s, -1, NULL, 0);
|
||||
if (size == 0 && GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
|
||||
return false;
|
||||
}
|
||||
std::unique_ptr<WCHAR[]> wstr(new WCHAR[size]);
|
||||
MultiByteToWideChar(
|
||||
inUtf8 ? CP_UTF8 : CP_ACP, 0, s, -1, wstr.get(), size + 1);
|
||||
out->assign(wstr.get());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool utf8_to_wcs(const char* input, wstring* out) {
|
||||
return mbs_to_wcs(input, out, true);
|
||||
}
|
||||
|
||||
bool wcs_to_utf8(const wchar_t* input, string* out) {
|
||||
return wcs_to_mbs(input, out, true);
|
||||
}
|
||||
|
||||
} // namespace strings
|
||||
} // namespace win32
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // defined(_WIN32)
|
407
third_party/protobuf-lite/message_lite.cc
vendored
Normal file
407
third_party/protobuf-lite/message_lite.cc
vendored
Normal file
@ -0,0 +1,407 @@
|
||||
// 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.
|
||||
|
||||
#include <climits>
|
||||
|
||||
#include <google/protobuf/arena.h>
|
||||
#include <google/protobuf/generated_message_util.h>
|
||||
#include <google/protobuf/message_lite.h>
|
||||
#include <google/protobuf/repeated_field.h>
|
||||
#include <string>
|
||||
#include <google/protobuf/stubs/logging.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
|
||||
#include <google/protobuf/stubs/stl_util.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
string MessageLite::InitializationErrorString() const {
|
||||
return "(cannot determine missing fields for lite message)";
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
// When serializing, we first compute the byte size, then serialize the message.
|
||||
// If serialization produces a different number of bytes than expected, we
|
||||
// call this function, which crashes. The problem could be due to a bug in the
|
||||
// protobuf implementation but is more likely caused by concurrent modification
|
||||
// of the message. This function attempts to distinguish between the two and
|
||||
// provide a useful error message.
|
||||
void ByteSizeConsistencyError(size_t byte_size_before_serialization,
|
||||
size_t byte_size_after_serialization,
|
||||
size_t bytes_produced_by_serialization,
|
||||
const MessageLite& message) {
|
||||
GOOGLE_CHECK_EQ(byte_size_before_serialization, byte_size_after_serialization)
|
||||
<< message.GetTypeName()
|
||||
<< " was modified concurrently during serialization.";
|
||||
GOOGLE_CHECK_EQ(bytes_produced_by_serialization, byte_size_before_serialization)
|
||||
<< "Byte size calculation and serialization were inconsistent. This "
|
||||
"may indicate a bug in protocol buffers or it may be caused by "
|
||||
"concurrent modification of " << message.GetTypeName() << ".";
|
||||
GOOGLE_LOG(FATAL) << "This shouldn't be called if all the sizes are equal.";
|
||||
}
|
||||
|
||||
string InitializationErrorMessage(const char* action,
|
||||
const MessageLite& message) {
|
||||
// Note: We want to avoid depending on strutil in the lite library, otherwise
|
||||
// we'd use:
|
||||
//
|
||||
// return strings::Substitute(
|
||||
// "Can't $0 message of type \"$1\" because it is missing required "
|
||||
// "fields: $2",
|
||||
// action, message.GetTypeName(),
|
||||
// message.InitializationErrorString());
|
||||
|
||||
string result;
|
||||
result += "Can't ";
|
||||
result += action;
|
||||
result += " message of type \"";
|
||||
result += message.GetTypeName();
|
||||
result += "\" because it is missing required fields: ";
|
||||
result += message.InitializationErrorString();
|
||||
return result;
|
||||
}
|
||||
|
||||
// Several of the Parse methods below just do one thing and then call another
|
||||
// method. In a naive implementation, we might have ParseFromString() call
|
||||
// ParseFromArray() which would call ParseFromZeroCopyStream() which would call
|
||||
// ParseFromCodedStream() which would call MergeFromCodedStream() which would
|
||||
// call MergePartialFromCodedStream(). However, when parsing very small
|
||||
// messages, every function call introduces significant overhead. To avoid
|
||||
// this without reproducing code, we use these forced-inline helpers.
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE bool InlineMergeFromCodedStream(
|
||||
io::CodedInputStream* input, MessageLite* message);
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE bool InlineParseFromCodedStream(
|
||||
io::CodedInputStream* input, MessageLite* message);
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE bool InlineParsePartialFromCodedStream(
|
||||
io::CodedInputStream* input, MessageLite* message);
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE bool InlineParseFromArray(
|
||||
const void* data, int size, MessageLite* message);
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE bool InlineParsePartialFromArray(
|
||||
const void* data, int size, MessageLite* message);
|
||||
|
||||
inline bool InlineMergeFromCodedStream(io::CodedInputStream* input,
|
||||
MessageLite* message) {
|
||||
if (!message->MergePartialFromCodedStream(input)) return false;
|
||||
if (!message->IsInitialized()) {
|
||||
GOOGLE_LOG(ERROR) << InitializationErrorMessage("parse", *message);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool InlineParseFromCodedStream(io::CodedInputStream* input,
|
||||
MessageLite* message) {
|
||||
message->Clear();
|
||||
return InlineMergeFromCodedStream(input, message);
|
||||
}
|
||||
|
||||
inline bool InlineParsePartialFromCodedStream(io::CodedInputStream* input,
|
||||
MessageLite* message) {
|
||||
message->Clear();
|
||||
return message->MergePartialFromCodedStream(input);
|
||||
}
|
||||
|
||||
inline bool InlineParseFromArray(
|
||||
const void* data, int size, MessageLite* message) {
|
||||
io::CodedInputStream input(reinterpret_cast<const uint8*>(data), size);
|
||||
return InlineParseFromCodedStream(&input, message) &&
|
||||
input.ConsumedEntireMessage();
|
||||
}
|
||||
|
||||
inline bool InlineParsePartialFromArray(
|
||||
const void* data, int size, MessageLite* message) {
|
||||
io::CodedInputStream input(reinterpret_cast<const uint8*>(data), size);
|
||||
return InlineParsePartialFromCodedStream(&input, message) &&
|
||||
input.ConsumedEntireMessage();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
MessageLite* MessageLite::New(::google::protobuf::Arena* arena) const {
|
||||
MessageLite* message = New();
|
||||
if (arena != NULL) {
|
||||
arena->Own(message);
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
bool MessageLite::MergeFromCodedStream(io::CodedInputStream* input) {
|
||||
return InlineMergeFromCodedStream(input, this);
|
||||
}
|
||||
|
||||
bool MessageLite::ParseFromCodedStream(io::CodedInputStream* input) {
|
||||
return InlineParseFromCodedStream(input, this);
|
||||
}
|
||||
|
||||
bool MessageLite::ParsePartialFromCodedStream(io::CodedInputStream* input) {
|
||||
return InlineParsePartialFromCodedStream(input, this);
|
||||
}
|
||||
|
||||
bool MessageLite::ParseFromZeroCopyStream(io::ZeroCopyInputStream* input) {
|
||||
io::CodedInputStream decoder(input);
|
||||
return ParseFromCodedStream(&decoder) && decoder.ConsumedEntireMessage();
|
||||
}
|
||||
|
||||
bool MessageLite::ParsePartialFromZeroCopyStream(
|
||||
io::ZeroCopyInputStream* input) {
|
||||
io::CodedInputStream decoder(input);
|
||||
return ParsePartialFromCodedStream(&decoder) &&
|
||||
decoder.ConsumedEntireMessage();
|
||||
}
|
||||
|
||||
bool MessageLite::ParseFromBoundedZeroCopyStream(
|
||||
io::ZeroCopyInputStream* input, int size) {
|
||||
io::CodedInputStream decoder(input);
|
||||
decoder.PushLimit(size);
|
||||
return ParseFromCodedStream(&decoder) &&
|
||||
decoder.ConsumedEntireMessage() &&
|
||||
decoder.BytesUntilLimit() == 0;
|
||||
}
|
||||
|
||||
bool MessageLite::ParsePartialFromBoundedZeroCopyStream(
|
||||
io::ZeroCopyInputStream* input, int size) {
|
||||
io::CodedInputStream decoder(input);
|
||||
decoder.PushLimit(size);
|
||||
return ParsePartialFromCodedStream(&decoder) &&
|
||||
decoder.ConsumedEntireMessage() &&
|
||||
decoder.BytesUntilLimit() == 0;
|
||||
}
|
||||
|
||||
bool MessageLite::ParseFromString(const string& data) {
|
||||
return InlineParseFromArray(data.data(), data.size(), this);
|
||||
}
|
||||
|
||||
bool MessageLite::ParsePartialFromString(const string& data) {
|
||||
return InlineParsePartialFromArray(data.data(), data.size(), this);
|
||||
}
|
||||
|
||||
bool MessageLite::ParseFromArray(const void* data, int size) {
|
||||
return InlineParseFromArray(data, size, this);
|
||||
}
|
||||
|
||||
bool MessageLite::ParsePartialFromArray(const void* data, int size) {
|
||||
return InlineParsePartialFromArray(data, size, this);
|
||||
}
|
||||
|
||||
|
||||
// ===================================================================
|
||||
|
||||
uint8* MessageLite::SerializeWithCachedSizesToArray(uint8* target) const {
|
||||
return InternalSerializeWithCachedSizesToArray(
|
||||
io::CodedOutputStream::IsDefaultSerializationDeterministic(), target);
|
||||
}
|
||||
|
||||
bool MessageLite::SerializeToCodedStream(io::CodedOutputStream* output) const {
|
||||
GOOGLE_DCHECK(IsInitialized()) << InitializationErrorMessage("serialize", *this);
|
||||
return SerializePartialToCodedStream(output);
|
||||
}
|
||||
|
||||
bool MessageLite::SerializePartialToCodedStream(
|
||||
io::CodedOutputStream* output) const {
|
||||
const size_t size = ByteSizeLong(); // Force size to be cached.
|
||||
if (size > INT_MAX) {
|
||||
GOOGLE_LOG(ERROR) << "Exceeded maximum protobuf size of 2GB: " << size;
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8* buffer = output->GetDirectBufferForNBytesAndAdvance(size);
|
||||
if (buffer != NULL) {
|
||||
uint8* end = InternalSerializeWithCachedSizesToArray(
|
||||
output->IsSerializationDeterministic(), buffer);
|
||||
if (end - buffer != size) {
|
||||
ByteSizeConsistencyError(size, ByteSizeLong(), end - buffer, *this);
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
int original_byte_count = output->ByteCount();
|
||||
SerializeWithCachedSizes(output);
|
||||
if (output->HadError()) {
|
||||
return false;
|
||||
}
|
||||
int final_byte_count = output->ByteCount();
|
||||
|
||||
if (final_byte_count - original_byte_count != size) {
|
||||
ByteSizeConsistencyError(size, ByteSizeLong(),
|
||||
final_byte_count - original_byte_count, *this);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool MessageLite::SerializeToZeroCopyStream(
|
||||
io::ZeroCopyOutputStream* output) const {
|
||||
io::CodedOutputStream encoder(output);
|
||||
return SerializeToCodedStream(&encoder);
|
||||
}
|
||||
|
||||
bool MessageLite::SerializePartialToZeroCopyStream(
|
||||
io::ZeroCopyOutputStream* output) const {
|
||||
io::CodedOutputStream encoder(output);
|
||||
return SerializePartialToCodedStream(&encoder);
|
||||
}
|
||||
|
||||
bool MessageLite::AppendToString(string* output) const {
|
||||
GOOGLE_DCHECK(IsInitialized()) << InitializationErrorMessage("serialize", *this);
|
||||
return AppendPartialToString(output);
|
||||
}
|
||||
|
||||
bool MessageLite::AppendPartialToString(string* output) const {
|
||||
size_t old_size = output->size();
|
||||
size_t byte_size = ByteSizeLong();
|
||||
if (byte_size > INT_MAX) {
|
||||
GOOGLE_LOG(ERROR) << "Exceeded maximum protobuf size of 2GB: " << byte_size;
|
||||
return false;
|
||||
}
|
||||
|
||||
STLStringResizeUninitialized(output, old_size + byte_size);
|
||||
uint8* start =
|
||||
reinterpret_cast<uint8*>(io::mutable_string_data(output) + old_size);
|
||||
uint8* end = SerializeWithCachedSizesToArray(start);
|
||||
if (end - start != byte_size) {
|
||||
ByteSizeConsistencyError(byte_size, ByteSizeLong(), end - start, *this);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MessageLite::SerializeToString(string* output) const {
|
||||
output->clear();
|
||||
return AppendToString(output);
|
||||
}
|
||||
|
||||
bool MessageLite::SerializePartialToString(string* output) const {
|
||||
output->clear();
|
||||
return AppendPartialToString(output);
|
||||
}
|
||||
|
||||
bool MessageLite::SerializeToArray(void* data, int size) const {
|
||||
GOOGLE_DCHECK(IsInitialized()) << InitializationErrorMessage("serialize", *this);
|
||||
return SerializePartialToArray(data, size);
|
||||
}
|
||||
|
||||
bool MessageLite::SerializePartialToArray(void* data, int size) const {
|
||||
int byte_size = ByteSizeLong();
|
||||
if (size < byte_size) return false;
|
||||
uint8* start = reinterpret_cast<uint8*>(data);
|
||||
uint8* end = SerializeWithCachedSizesToArray(start);
|
||||
if (end - start != byte_size) {
|
||||
ByteSizeConsistencyError(byte_size, ByteSizeLong(), end - start, *this);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
string MessageLite::SerializeAsString() const {
|
||||
// If the compiler implements the (Named) Return Value Optimization,
|
||||
// the local variable 'output' will not actually reside on the stack
|
||||
// of this function, but will be overlaid with the object that the
|
||||
// caller supplied for the return value to be constructed in.
|
||||
string output;
|
||||
if (!AppendToString(&output))
|
||||
output.clear();
|
||||
return output;
|
||||
}
|
||||
|
||||
string MessageLite::SerializePartialAsString() const {
|
||||
string output;
|
||||
if (!AppendPartialToString(&output))
|
||||
output.clear();
|
||||
return output;
|
||||
}
|
||||
|
||||
void MessageLite::SerializeWithCachedSizes(
|
||||
io::CodedOutputStream* output) const {
|
||||
GOOGLE_DCHECK(InternalGetTable());
|
||||
internal::TableSerialize(
|
||||
*this,
|
||||
static_cast<const internal::SerializationTable*>(InternalGetTable()),
|
||||
output);
|
||||
}
|
||||
|
||||
// The table driven code optimizes the case that the CodedOutputStream buffer
|
||||
// is large enough to serialize into it directly.
|
||||
// If the proto is optimized for speed, this method will be overridden by
|
||||
// generated code for maximum speed. If the proto is optimized for size or
|
||||
// is lite, then we need to specialize this to avoid infinite recursion.
|
||||
uint8* MessageLite::InternalSerializeWithCachedSizesToArray(
|
||||
bool deterministic, uint8* target) const {
|
||||
const internal::SerializationTable* table =
|
||||
static_cast<const internal::SerializationTable*>(InternalGetTable());
|
||||
if (table == NULL) {
|
||||
// We only optimize this when using optimize_for = SPEED. In other cases
|
||||
// we just use the CodedOutputStream path.
|
||||
int size = GetCachedSize();
|
||||
io::ArrayOutputStream out(target, size);
|
||||
io::CodedOutputStream coded_out(&out);
|
||||
coded_out.SetSerializationDeterministic(deterministic);
|
||||
SerializeWithCachedSizes(&coded_out);
|
||||
GOOGLE_CHECK(!coded_out.HadError());
|
||||
return target + size;
|
||||
} else {
|
||||
return internal::TableSerializeToArray(*this, table, deterministic, target);
|
||||
}
|
||||
}
|
||||
|
||||
namespace internal {
|
||||
template<>
|
||||
MessageLite* GenericTypeHandler<MessageLite>::NewFromPrototype(
|
||||
const MessageLite* prototype, google::protobuf::Arena* arena) {
|
||||
return prototype->New(arena);
|
||||
}
|
||||
template <>
|
||||
void GenericTypeHandler<MessageLite>::Merge(const MessageLite& from,
|
||||
MessageLite* to) {
|
||||
to->CheckTypeAndMergeFrom(from);
|
||||
}
|
||||
template<>
|
||||
void GenericTypeHandler<string>::Merge(const string& from,
|
||||
string* to) {
|
||||
*to = from;
|
||||
}
|
||||
|
||||
bool proto3_preserve_unknown_ = true;
|
||||
|
||||
void SetProto3PreserveUnknownsDefault(bool preserve) {
|
||||
proto3_preserve_unknown_ = preserve;
|
||||
}
|
||||
|
||||
|
||||
} // namespace internal
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user