mirror of
https://gitlab.com/kelteseth/ScreenPlay.git
synced 2024-11-07 03:22:33 +01:00
Add protocolbuffer lib
This commit is contained in:
parent
2acb4c4229
commit
8e10948094
11
Common/ProtocolBuffer/.gitattributes
vendored
Normal file
11
Common/ProtocolBuffer/.gitattributes
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
*.uasset filter=lfs diff=lfs merge=lfs -text
|
||||
*.umap filter=lfs diff=lfs merge=lfs -text
|
||||
*.kra filter=lfs diff=lfs merge=lfs -text
|
||||
*.blend filter=lfs diff=lfs merge=lfs -text
|
||||
*.png filter=lfs diff=lfs merge=lfs -text
|
||||
*.jpg filter=lfs diff=lfs merge=lfs -text
|
||||
*.fbx filter=lfs diff=lfs merge=lfs -text
|
||||
*.bmp filter=lfs diff=lfs merge=lfs -text
|
||||
*.lib filter=lfs diff=lfs merge=lfs -text
|
||||
*.exe filter=lfs diff=lfs merge=lfs -text
|
||||
*.dll filter=lfs diff=lfs merge=lfs -text
|
554
Common/ProtocolBuffer/GenCode/account.pb.cc
Normal file
554
Common/ProtocolBuffer/GenCode/account.pb.cc
Normal file
@ -0,0 +1,554 @@
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: account.proto
|
||||
|
||||
#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION
|
||||
#include "account.pb.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/port.h>
|
||||
#include <google/protobuf/stubs/once.h>
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/wire_format_lite_inl.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/generated_message_reflection.h>
|
||||
#include <google/protobuf/reflection_ops.h>
|
||||
#include <google/protobuf/wire_format.h>
|
||||
// @@protoc_insertion_point(includes)
|
||||
|
||||
namespace community {
|
||||
class LoginDefaultTypeInternal {
|
||||
public:
|
||||
::google::protobuf::internal::ExplicitlyConstructed<Login>
|
||||
_instance;
|
||||
} _Login_default_instance_;
|
||||
|
||||
namespace protobuf_account_2eproto {
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
::google::protobuf::Metadata file_level_metadata[1];
|
||||
|
||||
} // namespace
|
||||
|
||||
PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTableField
|
||||
const TableStruct::entries[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
|
||||
{0, 0, 0, ::google::protobuf::internal::kInvalidMask, 0, 0},
|
||||
};
|
||||
|
||||
PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::AuxillaryParseTableField
|
||||
const TableStruct::aux[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
|
||||
::google::protobuf::internal::AuxillaryParseTableField(),
|
||||
};
|
||||
PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTable const
|
||||
TableStruct::schema[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
|
||||
{ NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
|
||||
};
|
||||
|
||||
const ::google::protobuf::uint32 TableStruct::offsets[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
|
||||
~0u, // no _has_bits_
|
||||
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Login, _internal_metadata_),
|
||||
~0u, // no _extensions_
|
||||
~0u, // no _oneof_case_
|
||||
~0u, // no _weak_field_map_
|
||||
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Login, username_),
|
||||
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Login, password_),
|
||||
};
|
||||
static const ::google::protobuf::internal::MigrationSchema schemas[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
|
||||
{ 0, -1, sizeof(Login)},
|
||||
};
|
||||
|
||||
static ::google::protobuf::Message const * const file_default_instances[] = {
|
||||
reinterpret_cast<const ::google::protobuf::Message*>(&_Login_default_instance_),
|
||||
};
|
||||
|
||||
namespace {
|
||||
|
||||
void protobuf_AssignDescriptors() {
|
||||
AddDescriptors();
|
||||
::google::protobuf::MessageFactory* factory = NULL;
|
||||
AssignDescriptors(
|
||||
"account.proto", schemas, file_default_instances, TableStruct::offsets, factory,
|
||||
file_level_metadata, NULL, NULL);
|
||||
}
|
||||
|
||||
void protobuf_AssignDescriptorsOnce() {
|
||||
static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
|
||||
::google::protobuf::GoogleOnceInit(&once, &protobuf_AssignDescriptors);
|
||||
}
|
||||
|
||||
void protobuf_RegisterTypes(const ::std::string&) GOOGLE_ATTRIBUTE_COLD;
|
||||
void protobuf_RegisterTypes(const ::std::string&) {
|
||||
protobuf_AssignDescriptorsOnce();
|
||||
::google::protobuf::internal::RegisterAllTypes(file_level_metadata, 1);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
void TableStruct::InitDefaultsImpl() {
|
||||
GOOGLE_PROTOBUF_VERIFY_VERSION;
|
||||
|
||||
::google::protobuf::internal::InitProtobufDefaults();
|
||||
_Login_default_instance_._instance.DefaultConstruct();
|
||||
::google::protobuf::internal::OnShutdownDestroyMessage(
|
||||
&_Login_default_instance_);}
|
||||
|
||||
void InitDefaults() {
|
||||
static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
|
||||
::google::protobuf::GoogleOnceInit(&once, &TableStruct::InitDefaultsImpl);
|
||||
}
|
||||
namespace {
|
||||
void AddDescriptorsImpl() {
|
||||
InitDefaults();
|
||||
static const char descriptor[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
|
||||
"\n\raccount.proto\022\tcommunity\"+\n\005Login\022\020\n\010u"
|
||||
"sername\030\001 \001(\t\022\020\n\010password\030\002 \001(\tb\006proto3"
|
||||
};
|
||||
::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
|
||||
descriptor, 79);
|
||||
::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
|
||||
"account.proto", &protobuf_RegisterTypes);
|
||||
}
|
||||
} // anonymous namespace
|
||||
|
||||
void AddDescriptors() {
|
||||
static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
|
||||
::google::protobuf::GoogleOnceInit(&once, &AddDescriptorsImpl);
|
||||
}
|
||||
// Force AddDescriptors() to be called at dynamic initialization time.
|
||||
struct StaticDescriptorInitializer {
|
||||
StaticDescriptorInitializer() {
|
||||
AddDescriptors();
|
||||
}
|
||||
} static_descriptor_initializer;
|
||||
|
||||
} // namespace protobuf_account_2eproto
|
||||
|
||||
|
||||
// ===================================================================
|
||||
|
||||
#if !defined(_MSC_VER) || _MSC_VER >= 1900
|
||||
const int Login::kUsernameFieldNumber;
|
||||
const int Login::kPasswordFieldNumber;
|
||||
#endif // !defined(_MSC_VER) || _MSC_VER >= 1900
|
||||
|
||||
Login::Login()
|
||||
: ::google::protobuf::Message(), _internal_metadata_(NULL) {
|
||||
if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) {
|
||||
protobuf_account_2eproto::InitDefaults();
|
||||
}
|
||||
SharedCtor();
|
||||
// @@protoc_insertion_point(constructor:community.Login)
|
||||
}
|
||||
Login::Login(const Login& from)
|
||||
: ::google::protobuf::Message(),
|
||||
_internal_metadata_(NULL),
|
||||
_cached_size_(0) {
|
||||
_internal_metadata_.MergeFrom(from._internal_metadata_);
|
||||
username_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
if (from.username().size() > 0) {
|
||||
username_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.username_);
|
||||
}
|
||||
password_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
if (from.password().size() > 0) {
|
||||
password_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.password_);
|
||||
}
|
||||
// @@protoc_insertion_point(copy_constructor:community.Login)
|
||||
}
|
||||
|
||||
void Login::SharedCtor() {
|
||||
username_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
password_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
_cached_size_ = 0;
|
||||
}
|
||||
|
||||
Login::~Login() {
|
||||
// @@protoc_insertion_point(destructor:community.Login)
|
||||
SharedDtor();
|
||||
}
|
||||
|
||||
void Login::SharedDtor() {
|
||||
username_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
password_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
|
||||
void Login::SetCachedSize(int size) const {
|
||||
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
|
||||
_cached_size_ = size;
|
||||
GOOGLE_SAFE_CONCURRENT_WRITES_END();
|
||||
}
|
||||
const ::google::protobuf::Descriptor* Login::descriptor() {
|
||||
protobuf_account_2eproto::protobuf_AssignDescriptorsOnce();
|
||||
return protobuf_account_2eproto::file_level_metadata[kIndexInFileMessages].descriptor;
|
||||
}
|
||||
|
||||
const Login& Login::default_instance() {
|
||||
protobuf_account_2eproto::InitDefaults();
|
||||
return *internal_default_instance();
|
||||
}
|
||||
|
||||
Login* Login::New(::google::protobuf::Arena* arena) const {
|
||||
Login* n = new Login;
|
||||
if (arena != NULL) {
|
||||
arena->Own(n);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
void Login::Clear() {
|
||||
// @@protoc_insertion_point(message_clear_start:community.Login)
|
||||
::google::protobuf::uint32 cached_has_bits = 0;
|
||||
// Prevent compiler warnings about cached_has_bits being unused
|
||||
(void) cached_has_bits;
|
||||
|
||||
username_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
password_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
_internal_metadata_.Clear();
|
||||
}
|
||||
|
||||
bool Login::MergePartialFromCodedStream(
|
||||
::google::protobuf::io::CodedInputStream* input) {
|
||||
#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
|
||||
::google::protobuf::uint32 tag;
|
||||
// @@protoc_insertion_point(parse_start:community.Login)
|
||||
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)) {
|
||||
// string username = 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_username()));
|
||||
DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
|
||||
this->username().data(), static_cast<int>(this->username().length()),
|
||||
::google::protobuf::internal::WireFormatLite::PARSE,
|
||||
"community.Login.username"));
|
||||
} else {
|
||||
goto handle_unusual;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// string password = 2;
|
||||
case 2: {
|
||||
if (static_cast< ::google::protobuf::uint8>(tag) ==
|
||||
static_cast< ::google::protobuf::uint8>(18u /* 18 & 0xFF */)) {
|
||||
DO_(::google::protobuf::internal::WireFormatLite::ReadString(
|
||||
input, this->mutable_password()));
|
||||
DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
|
||||
this->password().data(), static_cast<int>(this->password().length()),
|
||||
::google::protobuf::internal::WireFormatLite::PARSE,
|
||||
"community.Login.password"));
|
||||
} else {
|
||||
goto handle_unusual;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
handle_unusual:
|
||||
if (tag == 0) {
|
||||
goto success;
|
||||
}
|
||||
DO_(::google::protobuf::internal::WireFormat::SkipField(
|
||||
input, tag, _internal_metadata_.mutable_unknown_fields()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
success:
|
||||
// @@protoc_insertion_point(parse_success:community.Login)
|
||||
return true;
|
||||
failure:
|
||||
// @@protoc_insertion_point(parse_failure:community.Login)
|
||||
return false;
|
||||
#undef DO_
|
||||
}
|
||||
|
||||
void Login::SerializeWithCachedSizes(
|
||||
::google::protobuf::io::CodedOutputStream* output) const {
|
||||
// @@protoc_insertion_point(serialize_start:community.Login)
|
||||
::google::protobuf::uint32 cached_has_bits = 0;
|
||||
(void) cached_has_bits;
|
||||
|
||||
// string username = 1;
|
||||
if (this->username().size() > 0) {
|
||||
::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
|
||||
this->username().data(), static_cast<int>(this->username().length()),
|
||||
::google::protobuf::internal::WireFormatLite::SERIALIZE,
|
||||
"community.Login.username");
|
||||
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
|
||||
1, this->username(), output);
|
||||
}
|
||||
|
||||
// string password = 2;
|
||||
if (this->password().size() > 0) {
|
||||
::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
|
||||
this->password().data(), static_cast<int>(this->password().length()),
|
||||
::google::protobuf::internal::WireFormatLite::SERIALIZE,
|
||||
"community.Login.password");
|
||||
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
|
||||
2, this->password(), output);
|
||||
}
|
||||
|
||||
if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
|
||||
::google::protobuf::internal::WireFormat::SerializeUnknownFields(
|
||||
(::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()), output);
|
||||
}
|
||||
// @@protoc_insertion_point(serialize_end:community.Login)
|
||||
}
|
||||
|
||||
::google::protobuf::uint8* Login::InternalSerializeWithCachedSizesToArray(
|
||||
bool deterministic, ::google::protobuf::uint8* target) const {
|
||||
(void)deterministic; // Unused
|
||||
// @@protoc_insertion_point(serialize_to_array_start:community.Login)
|
||||
::google::protobuf::uint32 cached_has_bits = 0;
|
||||
(void) cached_has_bits;
|
||||
|
||||
// string username = 1;
|
||||
if (this->username().size() > 0) {
|
||||
::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
|
||||
this->username().data(), static_cast<int>(this->username().length()),
|
||||
::google::protobuf::internal::WireFormatLite::SERIALIZE,
|
||||
"community.Login.username");
|
||||
target =
|
||||
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
|
||||
1, this->username(), target);
|
||||
}
|
||||
|
||||
// string password = 2;
|
||||
if (this->password().size() > 0) {
|
||||
::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
|
||||
this->password().data(), static_cast<int>(this->password().length()),
|
||||
::google::protobuf::internal::WireFormatLite::SERIALIZE,
|
||||
"community.Login.password");
|
||||
target =
|
||||
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
|
||||
2, this->password(), target);
|
||||
}
|
||||
|
||||
if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
|
||||
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
|
||||
(::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()), target);
|
||||
}
|
||||
// @@protoc_insertion_point(serialize_to_array_end:community.Login)
|
||||
return target;
|
||||
}
|
||||
|
||||
size_t Login::ByteSizeLong() const {
|
||||
// @@protoc_insertion_point(message_byte_size_start:community.Login)
|
||||
size_t total_size = 0;
|
||||
|
||||
if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
|
||||
total_size +=
|
||||
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
|
||||
(::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()));
|
||||
}
|
||||
// string username = 1;
|
||||
if (this->username().size() > 0) {
|
||||
total_size += 1 +
|
||||
::google::protobuf::internal::WireFormatLite::StringSize(
|
||||
this->username());
|
||||
}
|
||||
|
||||
// string password = 2;
|
||||
if (this->password().size() > 0) {
|
||||
total_size += 1 +
|
||||
::google::protobuf::internal::WireFormatLite::StringSize(
|
||||
this->password());
|
||||
}
|
||||
|
||||
int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
|
||||
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
|
||||
_cached_size_ = cached_size;
|
||||
GOOGLE_SAFE_CONCURRENT_WRITES_END();
|
||||
return total_size;
|
||||
}
|
||||
|
||||
void Login::MergeFrom(const ::google::protobuf::Message& from) {
|
||||
// @@protoc_insertion_point(generalized_merge_from_start:community.Login)
|
||||
GOOGLE_DCHECK_NE(&from, this);
|
||||
const Login* source =
|
||||
::google::protobuf::internal::DynamicCastToGenerated<const Login>(
|
||||
&from);
|
||||
if (source == NULL) {
|
||||
// @@protoc_insertion_point(generalized_merge_from_cast_fail:community.Login)
|
||||
::google::protobuf::internal::ReflectionOps::Merge(from, this);
|
||||
} else {
|
||||
// @@protoc_insertion_point(generalized_merge_from_cast_success:community.Login)
|
||||
MergeFrom(*source);
|
||||
}
|
||||
}
|
||||
|
||||
void Login::MergeFrom(const Login& from) {
|
||||
// @@protoc_insertion_point(class_specific_merge_from_start:community.Login)
|
||||
GOOGLE_DCHECK_NE(&from, this);
|
||||
_internal_metadata_.MergeFrom(from._internal_metadata_);
|
||||
::google::protobuf::uint32 cached_has_bits = 0;
|
||||
(void) cached_has_bits;
|
||||
|
||||
if (from.username().size() > 0) {
|
||||
|
||||
username_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.username_);
|
||||
}
|
||||
if (from.password().size() > 0) {
|
||||
|
||||
password_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.password_);
|
||||
}
|
||||
}
|
||||
|
||||
void Login::CopyFrom(const ::google::protobuf::Message& from) {
|
||||
// @@protoc_insertion_point(generalized_copy_from_start:community.Login)
|
||||
if (&from == this) return;
|
||||
Clear();
|
||||
MergeFrom(from);
|
||||
}
|
||||
|
||||
void Login::CopyFrom(const Login& from) {
|
||||
// @@protoc_insertion_point(class_specific_copy_from_start:community.Login)
|
||||
if (&from == this) return;
|
||||
Clear();
|
||||
MergeFrom(from);
|
||||
}
|
||||
|
||||
bool Login::IsInitialized() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
void Login::Swap(Login* other) {
|
||||
if (other == this) return;
|
||||
InternalSwap(other);
|
||||
}
|
||||
void Login::InternalSwap(Login* other) {
|
||||
using std::swap;
|
||||
username_.Swap(&other->username_);
|
||||
password_.Swap(&other->password_);
|
||||
_internal_metadata_.Swap(&other->_internal_metadata_);
|
||||
swap(_cached_size_, other->_cached_size_);
|
||||
}
|
||||
|
||||
::google::protobuf::Metadata Login::GetMetadata() const {
|
||||
protobuf_account_2eproto::protobuf_AssignDescriptorsOnce();
|
||||
return protobuf_account_2eproto::file_level_metadata[kIndexInFileMessages];
|
||||
}
|
||||
|
||||
#if PROTOBUF_INLINE_NOT_IN_HEADERS
|
||||
// Login
|
||||
|
||||
// string username = 1;
|
||||
void Login::clear_username() {
|
||||
username_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
const ::std::string& Login::username() const {
|
||||
// @@protoc_insertion_point(field_get:community.Login.username)
|
||||
return username_.GetNoArena();
|
||||
}
|
||||
void Login::set_username(const ::std::string& value) {
|
||||
|
||||
username_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
|
||||
// @@protoc_insertion_point(field_set:community.Login.username)
|
||||
}
|
||||
#if LANG_CXX11
|
||||
void Login::set_username(::std::string&& value) {
|
||||
|
||||
username_.SetNoArena(
|
||||
&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
|
||||
// @@protoc_insertion_point(field_set_rvalue:community.Login.username)
|
||||
}
|
||||
#endif
|
||||
void Login::set_username(const char* value) {
|
||||
GOOGLE_DCHECK(value != NULL);
|
||||
|
||||
username_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
|
||||
// @@protoc_insertion_point(field_set_char:community.Login.username)
|
||||
}
|
||||
void Login::set_username(const char* value, size_t size) {
|
||||
|
||||
username_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
|
||||
::std::string(reinterpret_cast<const char*>(value), size));
|
||||
// @@protoc_insertion_point(field_set_pointer:community.Login.username)
|
||||
}
|
||||
::std::string* Login::mutable_username() {
|
||||
|
||||
// @@protoc_insertion_point(field_mutable:community.Login.username)
|
||||
return username_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
::std::string* Login::release_username() {
|
||||
// @@protoc_insertion_point(field_release:community.Login.username)
|
||||
|
||||
return username_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
void Login::set_allocated_username(::std::string* username) {
|
||||
if (username != NULL) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
username_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), username);
|
||||
// @@protoc_insertion_point(field_set_allocated:community.Login.username)
|
||||
}
|
||||
|
||||
// string password = 2;
|
||||
void Login::clear_password() {
|
||||
password_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
const ::std::string& Login::password() const {
|
||||
// @@protoc_insertion_point(field_get:community.Login.password)
|
||||
return password_.GetNoArena();
|
||||
}
|
||||
void Login::set_password(const ::std::string& value) {
|
||||
|
||||
password_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
|
||||
// @@protoc_insertion_point(field_set:community.Login.password)
|
||||
}
|
||||
#if LANG_CXX11
|
||||
void Login::set_password(::std::string&& value) {
|
||||
|
||||
password_.SetNoArena(
|
||||
&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
|
||||
// @@protoc_insertion_point(field_set_rvalue:community.Login.password)
|
||||
}
|
||||
#endif
|
||||
void Login::set_password(const char* value) {
|
||||
GOOGLE_DCHECK(value != NULL);
|
||||
|
||||
password_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
|
||||
// @@protoc_insertion_point(field_set_char:community.Login.password)
|
||||
}
|
||||
void Login::set_password(const char* value, size_t size) {
|
||||
|
||||
password_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
|
||||
::std::string(reinterpret_cast<const char*>(value), size));
|
||||
// @@protoc_insertion_point(field_set_pointer:community.Login.password)
|
||||
}
|
||||
::std::string* Login::mutable_password() {
|
||||
|
||||
// @@protoc_insertion_point(field_mutable:community.Login.password)
|
||||
return password_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
::std::string* Login::release_password() {
|
||||
// @@protoc_insertion_point(field_release:community.Login.password)
|
||||
|
||||
return password_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
void Login::set_allocated_password(::std::string* password) {
|
||||
if (password != NULL) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
password_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), password);
|
||||
// @@protoc_insertion_point(field_set_allocated:community.Login.password)
|
||||
}
|
||||
|
||||
#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
|
||||
|
||||
// @@protoc_insertion_point(namespace_scope)
|
||||
|
||||
} // namespace community
|
||||
|
||||
// @@protoc_insertion_point(global_scope)
|
306
Common/ProtocolBuffer/GenCode/account.pb.h
Normal file
306
Common/ProtocolBuffer/GenCode/account.pb.h
Normal file
@ -0,0 +1,306 @@
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: account.proto
|
||||
|
||||
#ifndef PROTOBUF_account_2eproto__INCLUDED
|
||||
#define PROTOBUF_account_2eproto__INCLUDED
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
#if GOOGLE_PROTOBUF_VERSION < 3004000
|
||||
#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 3004000 < 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/metadata.h>
|
||||
#include <google/protobuf/message.h>
|
||||
#include <google/protobuf/repeated_field.h> // IWYU pragma: export
|
||||
#include <google/protobuf/extension_set.h> // IWYU pragma: export
|
||||
#include <google/protobuf/unknown_field_set.h>
|
||||
// @@protoc_insertion_point(includes)
|
||||
namespace community {
|
||||
class Login;
|
||||
class LoginDefaultTypeInternal;
|
||||
extern LoginDefaultTypeInternal _Login_default_instance_;
|
||||
} // namespace community
|
||||
|
||||
namespace community {
|
||||
|
||||
namespace protobuf_account_2eproto {
|
||||
// Internal implementation detail -- do not call these.
|
||||
struct TableStruct {
|
||||
static const ::google::protobuf::internal::ParseTableField entries[];
|
||||
static const ::google::protobuf::internal::AuxillaryParseTableField aux[];
|
||||
static const ::google::protobuf::internal::ParseTable schema[];
|
||||
static const ::google::protobuf::uint32 offsets[];
|
||||
static const ::google::protobuf::internal::FieldMetadata field_metadata[];
|
||||
static const ::google::protobuf::internal::SerializationTable serialization_table[];
|
||||
static void InitDefaultsImpl();
|
||||
};
|
||||
void AddDescriptors();
|
||||
void InitDefaults();
|
||||
} // namespace protobuf_account_2eproto
|
||||
|
||||
// ===================================================================
|
||||
|
||||
class Login : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:community.Login) */ {
|
||||
public:
|
||||
Login();
|
||||
virtual ~Login();
|
||||
|
||||
Login(const Login& from);
|
||||
|
||||
inline Login& operator=(const Login& from) {
|
||||
CopyFrom(from);
|
||||
return *this;
|
||||
}
|
||||
#if LANG_CXX11
|
||||
Login(Login&& from) noexcept
|
||||
: Login() {
|
||||
*this = ::std::move(from);
|
||||
}
|
||||
|
||||
inline Login& operator=(Login&& from) noexcept {
|
||||
if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
|
||||
if (this != &from) InternalSwap(&from);
|
||||
} else {
|
||||
CopyFrom(from);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
static const ::google::protobuf::Descriptor* descriptor();
|
||||
static const Login& default_instance();
|
||||
|
||||
static inline const Login* internal_default_instance() {
|
||||
return reinterpret_cast<const Login*>(
|
||||
&_Login_default_instance_);
|
||||
}
|
||||
static PROTOBUF_CONSTEXPR int const kIndexInFileMessages =
|
||||
0;
|
||||
|
||||
void Swap(Login* other);
|
||||
friend void swap(Login& a, Login& b) {
|
||||
a.Swap(&b);
|
||||
}
|
||||
|
||||
// implements Message ----------------------------------------------
|
||||
|
||||
inline Login* New() const PROTOBUF_FINAL { return New(NULL); }
|
||||
|
||||
Login* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL;
|
||||
void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
|
||||
void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
|
||||
void CopyFrom(const Login& from);
|
||||
void MergeFrom(const Login& from);
|
||||
void Clear() PROTOBUF_FINAL;
|
||||
bool IsInitialized() const PROTOBUF_FINAL;
|
||||
|
||||
size_t ByteSizeLong() const PROTOBUF_FINAL;
|
||||
bool MergePartialFromCodedStream(
|
||||
::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL;
|
||||
void SerializeWithCachedSizes(
|
||||
::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL;
|
||||
::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
|
||||
bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL;
|
||||
int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; }
|
||||
private:
|
||||
void SharedCtor();
|
||||
void SharedDtor();
|
||||
void SetCachedSize(int size) const PROTOBUF_FINAL;
|
||||
void InternalSwap(Login* other);
|
||||
private:
|
||||
inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
|
||||
return NULL;
|
||||
}
|
||||
inline void* MaybeArenaPtr() const {
|
||||
return NULL;
|
||||
}
|
||||
public:
|
||||
|
||||
::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL;
|
||||
|
||||
// nested types ----------------------------------------------------
|
||||
|
||||
// accessors -------------------------------------------------------
|
||||
|
||||
// string username = 1;
|
||||
void clear_username();
|
||||
static const int kUsernameFieldNumber = 1;
|
||||
const ::std::string& username() const;
|
||||
void set_username(const ::std::string& value);
|
||||
#if LANG_CXX11
|
||||
void set_username(::std::string&& value);
|
||||
#endif
|
||||
void set_username(const char* value);
|
||||
void set_username(const char* value, size_t size);
|
||||
::std::string* mutable_username();
|
||||
::std::string* release_username();
|
||||
void set_allocated_username(::std::string* username);
|
||||
|
||||
// string password = 2;
|
||||
void clear_password();
|
||||
static const int kPasswordFieldNumber = 2;
|
||||
const ::std::string& password() const;
|
||||
void set_password(const ::std::string& value);
|
||||
#if LANG_CXX11
|
||||
void set_password(::std::string&& value);
|
||||
#endif
|
||||
void set_password(const char* value);
|
||||
void set_password(const char* value, size_t size);
|
||||
::std::string* mutable_password();
|
||||
::std::string* release_password();
|
||||
void set_allocated_password(::std::string* password);
|
||||
|
||||
// @@protoc_insertion_point(class_scope:community.Login)
|
||||
private:
|
||||
|
||||
::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
|
||||
::google::protobuf::internal::ArenaStringPtr username_;
|
||||
::google::protobuf::internal::ArenaStringPtr password_;
|
||||
mutable int _cached_size_;
|
||||
friend struct protobuf_account_2eproto::TableStruct;
|
||||
};
|
||||
// ===================================================================
|
||||
|
||||
|
||||
// ===================================================================
|
||||
|
||||
#if !PROTOBUF_INLINE_NOT_IN_HEADERS
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
|
||||
#endif // __GNUC__
|
||||
// Login
|
||||
|
||||
// string username = 1;
|
||||
inline void Login::clear_username() {
|
||||
username_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
inline const ::std::string& Login::username() const {
|
||||
// @@protoc_insertion_point(field_get:community.Login.username)
|
||||
return username_.GetNoArena();
|
||||
}
|
||||
inline void Login::set_username(const ::std::string& value) {
|
||||
|
||||
username_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
|
||||
// @@protoc_insertion_point(field_set:community.Login.username)
|
||||
}
|
||||
#if LANG_CXX11
|
||||
inline void Login::set_username(::std::string&& value) {
|
||||
|
||||
username_.SetNoArena(
|
||||
&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
|
||||
// @@protoc_insertion_point(field_set_rvalue:community.Login.username)
|
||||
}
|
||||
#endif
|
||||
inline void Login::set_username(const char* value) {
|
||||
GOOGLE_DCHECK(value != NULL);
|
||||
|
||||
username_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
|
||||
// @@protoc_insertion_point(field_set_char:community.Login.username)
|
||||
}
|
||||
inline void Login::set_username(const char* value, size_t size) {
|
||||
|
||||
username_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
|
||||
::std::string(reinterpret_cast<const char*>(value), size));
|
||||
// @@protoc_insertion_point(field_set_pointer:community.Login.username)
|
||||
}
|
||||
inline ::std::string* Login::mutable_username() {
|
||||
|
||||
// @@protoc_insertion_point(field_mutable:community.Login.username)
|
||||
return username_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
inline ::std::string* Login::release_username() {
|
||||
// @@protoc_insertion_point(field_release:community.Login.username)
|
||||
|
||||
return username_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
inline void Login::set_allocated_username(::std::string* username) {
|
||||
if (username != NULL) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
username_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), username);
|
||||
// @@protoc_insertion_point(field_set_allocated:community.Login.username)
|
||||
}
|
||||
|
||||
// string password = 2;
|
||||
inline void Login::clear_password() {
|
||||
password_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
inline const ::std::string& Login::password() const {
|
||||
// @@protoc_insertion_point(field_get:community.Login.password)
|
||||
return password_.GetNoArena();
|
||||
}
|
||||
inline void Login::set_password(const ::std::string& value) {
|
||||
|
||||
password_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
|
||||
// @@protoc_insertion_point(field_set:community.Login.password)
|
||||
}
|
||||
#if LANG_CXX11
|
||||
inline void Login::set_password(::std::string&& value) {
|
||||
|
||||
password_.SetNoArena(
|
||||
&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
|
||||
// @@protoc_insertion_point(field_set_rvalue:community.Login.password)
|
||||
}
|
||||
#endif
|
||||
inline void Login::set_password(const char* value) {
|
||||
GOOGLE_DCHECK(value != NULL);
|
||||
|
||||
password_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
|
||||
// @@protoc_insertion_point(field_set_char:community.Login.password)
|
||||
}
|
||||
inline void Login::set_password(const char* value, size_t size) {
|
||||
|
||||
password_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
|
||||
::std::string(reinterpret_cast<const char*>(value), size));
|
||||
// @@protoc_insertion_point(field_set_pointer:community.Login.password)
|
||||
}
|
||||
inline ::std::string* Login::mutable_password() {
|
||||
|
||||
// @@protoc_insertion_point(field_mutable:community.Login.password)
|
||||
return password_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
inline ::std::string* Login::release_password() {
|
||||
// @@protoc_insertion_point(field_release:community.Login.password)
|
||||
|
||||
return password_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
inline void Login::set_allocated_password(::std::string* password) {
|
||||
if (password != NULL) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
password_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), password);
|
||||
// @@protoc_insertion_point(field_set_allocated:community.Login.password)
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif // __GNUC__
|
||||
#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS
|
||||
|
||||
// @@protoc_insertion_point(namespace_scope)
|
||||
|
||||
|
||||
} // namespace community
|
||||
|
||||
// @@protoc_insertion_point(global_scope)
|
||||
|
||||
#endif // PROTOBUF_account_2eproto__INCLUDED
|
109
Common/ProtocolBuffer/GenCode/character.pb.cc
Normal file
109
Common/ProtocolBuffer/GenCode/character.pb.cc
Normal file
@ -0,0 +1,109 @@
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: character.proto
|
||||
|
||||
#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION
|
||||
#include "character.pb.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/port.h>
|
||||
#include <google/protobuf/stubs/once.h>
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/wire_format_lite_inl.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/generated_message_reflection.h>
|
||||
#include <google/protobuf/reflection_ops.h>
|
||||
#include <google/protobuf/wire_format.h>
|
||||
// @@protoc_insertion_point(includes)
|
||||
|
||||
namespace community {
|
||||
|
||||
namespace protobuf_character_2eproto {
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTableField
|
||||
const TableStruct::entries[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
|
||||
{0, 0, 0, ::google::protobuf::internal::kInvalidMask, 0, 0},
|
||||
};
|
||||
|
||||
PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::AuxillaryParseTableField
|
||||
const TableStruct::aux[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
|
||||
::google::protobuf::internal::AuxillaryParseTableField(),
|
||||
};
|
||||
PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTable const
|
||||
TableStruct::schema[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
|
||||
{ NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
|
||||
};
|
||||
|
||||
const ::google::protobuf::uint32 TableStruct::offsets[1] = {};
|
||||
static const ::google::protobuf::internal::MigrationSchema* schemas = NULL;
|
||||
static const ::google::protobuf::Message* const* file_default_instances = NULL;
|
||||
namespace {
|
||||
|
||||
void protobuf_AssignDescriptors() {
|
||||
AddDescriptors();
|
||||
::google::protobuf::MessageFactory* factory = NULL;
|
||||
AssignDescriptors(
|
||||
"character.proto", schemas, file_default_instances, TableStruct::offsets, factory,
|
||||
NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
void protobuf_AssignDescriptorsOnce() {
|
||||
static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
|
||||
::google::protobuf::GoogleOnceInit(&once, &protobuf_AssignDescriptors);
|
||||
}
|
||||
|
||||
void protobuf_RegisterTypes(const ::std::string&) GOOGLE_ATTRIBUTE_COLD;
|
||||
void protobuf_RegisterTypes(const ::std::string&) {
|
||||
protobuf_AssignDescriptorsOnce();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
void TableStruct::InitDefaultsImpl() {
|
||||
GOOGLE_PROTOBUF_VERIFY_VERSION;
|
||||
|
||||
::google::protobuf::internal::InitProtobufDefaults();
|
||||
}
|
||||
|
||||
void InitDefaults() {
|
||||
static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
|
||||
::google::protobuf::GoogleOnceInit(&once, &TableStruct::InitDefaultsImpl);
|
||||
}
|
||||
namespace {
|
||||
void AddDescriptorsImpl() {
|
||||
InitDefaults();
|
||||
static const char descriptor[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
|
||||
"\n\017character.proto\022\tcommunityb\006proto3"
|
||||
};
|
||||
::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
|
||||
descriptor, 36);
|
||||
::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
|
||||
"character.proto", &protobuf_RegisterTypes);
|
||||
}
|
||||
} // anonymous namespace
|
||||
|
||||
void AddDescriptors() {
|
||||
static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
|
||||
::google::protobuf::GoogleOnceInit(&once, &AddDescriptorsImpl);
|
||||
}
|
||||
// Force AddDescriptors() to be called at dynamic initialization time.
|
||||
struct StaticDescriptorInitializer {
|
||||
StaticDescriptorInitializer() {
|
||||
AddDescriptors();
|
||||
}
|
||||
} static_descriptor_initializer;
|
||||
|
||||
} // namespace protobuf_character_2eproto
|
||||
|
||||
|
||||
// @@protoc_insertion_point(namespace_scope)
|
||||
|
||||
} // namespace community
|
||||
|
||||
// @@protoc_insertion_point(global_scope)
|
76
Common/ProtocolBuffer/GenCode/character.pb.h
Normal file
76
Common/ProtocolBuffer/GenCode/character.pb.h
Normal file
@ -0,0 +1,76 @@
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: character.proto
|
||||
|
||||
#ifndef PROTOBUF_character_2eproto__INCLUDED
|
||||
#define PROTOBUF_character_2eproto__INCLUDED
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
#if GOOGLE_PROTOBUF_VERSION < 3004000
|
||||
#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 3004000 < 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/metadata.h>
|
||||
#include <google/protobuf/repeated_field.h> // IWYU pragma: export
|
||||
#include <google/protobuf/extension_set.h> // IWYU pragma: export
|
||||
// @@protoc_insertion_point(includes)
|
||||
namespace community {
|
||||
} // namespace community
|
||||
|
||||
namespace community {
|
||||
|
||||
namespace protobuf_character_2eproto {
|
||||
// Internal implementation detail -- do not call these.
|
||||
struct TableStruct {
|
||||
static const ::google::protobuf::internal::ParseTableField entries[];
|
||||
static const ::google::protobuf::internal::AuxillaryParseTableField aux[];
|
||||
static const ::google::protobuf::internal::ParseTable schema[];
|
||||
static const ::google::protobuf::uint32 offsets[];
|
||||
static const ::google::protobuf::internal::FieldMetadata field_metadata[];
|
||||
static const ::google::protobuf::internal::SerializationTable serialization_table[];
|
||||
static void InitDefaultsImpl();
|
||||
};
|
||||
void AddDescriptors();
|
||||
void InitDefaults();
|
||||
} // namespace protobuf_character_2eproto
|
||||
|
||||
// ===================================================================
|
||||
|
||||
|
||||
// ===================================================================
|
||||
|
||||
|
||||
// ===================================================================
|
||||
|
||||
#if !PROTOBUF_INLINE_NOT_IN_HEADERS
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
|
||||
#endif // __GNUC__
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif // __GNUC__
|
||||
#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS
|
||||
|
||||
// @@protoc_insertion_point(namespace_scope)
|
||||
|
||||
|
||||
} // namespace community
|
||||
|
||||
// @@protoc_insertion_point(global_scope)
|
||||
|
||||
#endif // PROTOBUF_character_2eproto__INCLUDED
|
410
Common/ProtocolBuffer/GenCode/container.pb.cc
Normal file
410
Common/ProtocolBuffer/GenCode/container.pb.cc
Normal file
@ -0,0 +1,410 @@
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: container.proto
|
||||
|
||||
#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION
|
||||
#include "container.pb.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/port.h>
|
||||
#include <google/protobuf/stubs/once.h>
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/wire_format_lite_inl.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/generated_message_reflection.h>
|
||||
#include <google/protobuf/reflection_ops.h>
|
||||
#include <google/protobuf/wire_format.h>
|
||||
// @@protoc_insertion_point(includes)
|
||||
|
||||
namespace community {
|
||||
class MessageContainerDefaultTypeInternal {
|
||||
public:
|
||||
::google::protobuf::internal::ExplicitlyConstructed<MessageContainer>
|
||||
_instance;
|
||||
} _MessageContainer_default_instance_;
|
||||
|
||||
namespace protobuf_container_2eproto {
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
::google::protobuf::Metadata file_level_metadata[1];
|
||||
|
||||
} // namespace
|
||||
|
||||
PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTableField
|
||||
const TableStruct::entries[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
|
||||
{0, 0, 0, ::google::protobuf::internal::kInvalidMask, 0, 0},
|
||||
};
|
||||
|
||||
PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::AuxillaryParseTableField
|
||||
const TableStruct::aux[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
|
||||
::google::protobuf::internal::AuxillaryParseTableField(),
|
||||
};
|
||||
PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTable const
|
||||
TableStruct::schema[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
|
||||
{ NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
|
||||
};
|
||||
|
||||
const ::google::protobuf::uint32 TableStruct::offsets[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
|
||||
~0u, // no _has_bits_
|
||||
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageContainer, _internal_metadata_),
|
||||
~0u, // no _extensions_
|
||||
~0u, // no _oneof_case_
|
||||
~0u, // no _weak_field_map_
|
||||
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageContainer, message_),
|
||||
};
|
||||
static const ::google::protobuf::internal::MigrationSchema schemas[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
|
||||
{ 0, -1, sizeof(MessageContainer)},
|
||||
};
|
||||
|
||||
static ::google::protobuf::Message const * const file_default_instances[] = {
|
||||
reinterpret_cast<const ::google::protobuf::Message*>(&_MessageContainer_default_instance_),
|
||||
};
|
||||
|
||||
namespace {
|
||||
|
||||
void protobuf_AssignDescriptors() {
|
||||
AddDescriptors();
|
||||
::google::protobuf::MessageFactory* factory = NULL;
|
||||
AssignDescriptors(
|
||||
"container.proto", schemas, file_default_instances, TableStruct::offsets, factory,
|
||||
file_level_metadata, NULL, NULL);
|
||||
}
|
||||
|
||||
void protobuf_AssignDescriptorsOnce() {
|
||||
static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
|
||||
::google::protobuf::GoogleOnceInit(&once, &protobuf_AssignDescriptors);
|
||||
}
|
||||
|
||||
void protobuf_RegisterTypes(const ::std::string&) GOOGLE_ATTRIBUTE_COLD;
|
||||
void protobuf_RegisterTypes(const ::std::string&) {
|
||||
protobuf_AssignDescriptorsOnce();
|
||||
::google::protobuf::internal::RegisterAllTypes(file_level_metadata, 1);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
void TableStruct::InitDefaultsImpl() {
|
||||
GOOGLE_PROTOBUF_VERIFY_VERSION;
|
||||
|
||||
::google::protobuf::internal::InitProtobufDefaults();
|
||||
::google::protobuf::protobuf_google_2fprotobuf_2fany_2eproto::InitDefaults();
|
||||
_MessageContainer_default_instance_._instance.DefaultConstruct();
|
||||
::google::protobuf::internal::OnShutdownDestroyMessage(
|
||||
&_MessageContainer_default_instance_);}
|
||||
|
||||
void InitDefaults() {
|
||||
static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
|
||||
::google::protobuf::GoogleOnceInit(&once, &TableStruct::InitDefaultsImpl);
|
||||
}
|
||||
namespace {
|
||||
void AddDescriptorsImpl() {
|
||||
InitDefaults();
|
||||
static const char descriptor[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
|
||||
"\n\017container.proto\022\tcommunity\032\031google/pro"
|
||||
"tobuf/any.proto\"9\n\020MessageContainer\022%\n\007m"
|
||||
"essage\030\001 \003(\0132\024.google.protobuf.Anyb\006prot"
|
||||
"o3"
|
||||
};
|
||||
::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
|
||||
descriptor, 122);
|
||||
::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
|
||||
"container.proto", &protobuf_RegisterTypes);
|
||||
::google::protobuf::protobuf_google_2fprotobuf_2fany_2eproto::AddDescriptors();
|
||||
}
|
||||
} // anonymous namespace
|
||||
|
||||
void AddDescriptors() {
|
||||
static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
|
||||
::google::protobuf::GoogleOnceInit(&once, &AddDescriptorsImpl);
|
||||
}
|
||||
// Force AddDescriptors() to be called at dynamic initialization time.
|
||||
struct StaticDescriptorInitializer {
|
||||
StaticDescriptorInitializer() {
|
||||
AddDescriptors();
|
||||
}
|
||||
} static_descriptor_initializer;
|
||||
|
||||
} // namespace protobuf_container_2eproto
|
||||
|
||||
|
||||
// ===================================================================
|
||||
|
||||
#if !defined(_MSC_VER) || _MSC_VER >= 1900
|
||||
const int MessageContainer::kMessageFieldNumber;
|
||||
#endif // !defined(_MSC_VER) || _MSC_VER >= 1900
|
||||
|
||||
MessageContainer::MessageContainer()
|
||||
: ::google::protobuf::Message(), _internal_metadata_(NULL) {
|
||||
if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) {
|
||||
protobuf_container_2eproto::InitDefaults();
|
||||
}
|
||||
SharedCtor();
|
||||
// @@protoc_insertion_point(constructor:community.MessageContainer)
|
||||
}
|
||||
MessageContainer::MessageContainer(const MessageContainer& from)
|
||||
: ::google::protobuf::Message(),
|
||||
_internal_metadata_(NULL),
|
||||
message_(from.message_),
|
||||
_cached_size_(0) {
|
||||
_internal_metadata_.MergeFrom(from._internal_metadata_);
|
||||
// @@protoc_insertion_point(copy_constructor:community.MessageContainer)
|
||||
}
|
||||
|
||||
void MessageContainer::SharedCtor() {
|
||||
_cached_size_ = 0;
|
||||
}
|
||||
|
||||
MessageContainer::~MessageContainer() {
|
||||
// @@protoc_insertion_point(destructor:community.MessageContainer)
|
||||
SharedDtor();
|
||||
}
|
||||
|
||||
void MessageContainer::SharedDtor() {
|
||||
}
|
||||
|
||||
void MessageContainer::SetCachedSize(int size) const {
|
||||
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
|
||||
_cached_size_ = size;
|
||||
GOOGLE_SAFE_CONCURRENT_WRITES_END();
|
||||
}
|
||||
const ::google::protobuf::Descriptor* MessageContainer::descriptor() {
|
||||
protobuf_container_2eproto::protobuf_AssignDescriptorsOnce();
|
||||
return protobuf_container_2eproto::file_level_metadata[kIndexInFileMessages].descriptor;
|
||||
}
|
||||
|
||||
const MessageContainer& MessageContainer::default_instance() {
|
||||
protobuf_container_2eproto::InitDefaults();
|
||||
return *internal_default_instance();
|
||||
}
|
||||
|
||||
MessageContainer* MessageContainer::New(::google::protobuf::Arena* arena) const {
|
||||
MessageContainer* n = new MessageContainer;
|
||||
if (arena != NULL) {
|
||||
arena->Own(n);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
void MessageContainer::Clear() {
|
||||
// @@protoc_insertion_point(message_clear_start:community.MessageContainer)
|
||||
::google::protobuf::uint32 cached_has_bits = 0;
|
||||
// Prevent compiler warnings about cached_has_bits being unused
|
||||
(void) cached_has_bits;
|
||||
|
||||
message_.Clear();
|
||||
_internal_metadata_.Clear();
|
||||
}
|
||||
|
||||
bool MessageContainer::MergePartialFromCodedStream(
|
||||
::google::protobuf::io::CodedInputStream* input) {
|
||||
#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
|
||||
::google::protobuf::uint32 tag;
|
||||
// @@protoc_insertion_point(parse_start:community.MessageContainer)
|
||||
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 .google.protobuf.Any message = 1;
|
||||
case 1: {
|
||||
if (static_cast< ::google::protobuf::uint8>(tag) ==
|
||||
static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) {
|
||||
DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
|
||||
input, add_message()));
|
||||
} else {
|
||||
goto handle_unusual;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
handle_unusual:
|
||||
if (tag == 0) {
|
||||
goto success;
|
||||
}
|
||||
DO_(::google::protobuf::internal::WireFormat::SkipField(
|
||||
input, tag, _internal_metadata_.mutable_unknown_fields()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
success:
|
||||
// @@protoc_insertion_point(parse_success:community.MessageContainer)
|
||||
return true;
|
||||
failure:
|
||||
// @@protoc_insertion_point(parse_failure:community.MessageContainer)
|
||||
return false;
|
||||
#undef DO_
|
||||
}
|
||||
|
||||
void MessageContainer::SerializeWithCachedSizes(
|
||||
::google::protobuf::io::CodedOutputStream* output) const {
|
||||
// @@protoc_insertion_point(serialize_start:community.MessageContainer)
|
||||
::google::protobuf::uint32 cached_has_bits = 0;
|
||||
(void) cached_has_bits;
|
||||
|
||||
// repeated .google.protobuf.Any message = 1;
|
||||
for (unsigned int i = 0,
|
||||
n = static_cast<unsigned int>(this->message_size()); i < n; i++) {
|
||||
::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
|
||||
1, this->message(static_cast<int>(i)), output);
|
||||
}
|
||||
|
||||
if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
|
||||
::google::protobuf::internal::WireFormat::SerializeUnknownFields(
|
||||
(::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()), output);
|
||||
}
|
||||
// @@protoc_insertion_point(serialize_end:community.MessageContainer)
|
||||
}
|
||||
|
||||
::google::protobuf::uint8* MessageContainer::InternalSerializeWithCachedSizesToArray(
|
||||
bool deterministic, ::google::protobuf::uint8* target) const {
|
||||
(void)deterministic; // Unused
|
||||
// @@protoc_insertion_point(serialize_to_array_start:community.MessageContainer)
|
||||
::google::protobuf::uint32 cached_has_bits = 0;
|
||||
(void) cached_has_bits;
|
||||
|
||||
// repeated .google.protobuf.Any message = 1;
|
||||
for (unsigned int i = 0,
|
||||
n = static_cast<unsigned int>(this->message_size()); i < n; i++) {
|
||||
target = ::google::protobuf::internal::WireFormatLite::
|
||||
InternalWriteMessageNoVirtualToArray(
|
||||
1, this->message(static_cast<int>(i)), deterministic, target);
|
||||
}
|
||||
|
||||
if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
|
||||
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
|
||||
(::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()), target);
|
||||
}
|
||||
// @@protoc_insertion_point(serialize_to_array_end:community.MessageContainer)
|
||||
return target;
|
||||
}
|
||||
|
||||
size_t MessageContainer::ByteSizeLong() const {
|
||||
// @@protoc_insertion_point(message_byte_size_start:community.MessageContainer)
|
||||
size_t total_size = 0;
|
||||
|
||||
if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
|
||||
total_size +=
|
||||
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
|
||||
(::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()));
|
||||
}
|
||||
// repeated .google.protobuf.Any message = 1;
|
||||
{
|
||||
unsigned int count = static_cast<unsigned int>(this->message_size());
|
||||
total_size += 1UL * count;
|
||||
for (unsigned int i = 0; i < count; i++) {
|
||||
total_size +=
|
||||
::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
|
||||
this->message(static_cast<int>(i)));
|
||||
}
|
||||
}
|
||||
|
||||
int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
|
||||
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
|
||||
_cached_size_ = cached_size;
|
||||
GOOGLE_SAFE_CONCURRENT_WRITES_END();
|
||||
return total_size;
|
||||
}
|
||||
|
||||
void MessageContainer::MergeFrom(const ::google::protobuf::Message& from) {
|
||||
// @@protoc_insertion_point(generalized_merge_from_start:community.MessageContainer)
|
||||
GOOGLE_DCHECK_NE(&from, this);
|
||||
const MessageContainer* source =
|
||||
::google::protobuf::internal::DynamicCastToGenerated<const MessageContainer>(
|
||||
&from);
|
||||
if (source == NULL) {
|
||||
// @@protoc_insertion_point(generalized_merge_from_cast_fail:community.MessageContainer)
|
||||
::google::protobuf::internal::ReflectionOps::Merge(from, this);
|
||||
} else {
|
||||
// @@protoc_insertion_point(generalized_merge_from_cast_success:community.MessageContainer)
|
||||
MergeFrom(*source);
|
||||
}
|
||||
}
|
||||
|
||||
void MessageContainer::MergeFrom(const MessageContainer& from) {
|
||||
// @@protoc_insertion_point(class_specific_merge_from_start:community.MessageContainer)
|
||||
GOOGLE_DCHECK_NE(&from, this);
|
||||
_internal_metadata_.MergeFrom(from._internal_metadata_);
|
||||
::google::protobuf::uint32 cached_has_bits = 0;
|
||||
(void) cached_has_bits;
|
||||
|
||||
message_.MergeFrom(from.message_);
|
||||
}
|
||||
|
||||
void MessageContainer::CopyFrom(const ::google::protobuf::Message& from) {
|
||||
// @@protoc_insertion_point(generalized_copy_from_start:community.MessageContainer)
|
||||
if (&from == this) return;
|
||||
Clear();
|
||||
MergeFrom(from);
|
||||
}
|
||||
|
||||
void MessageContainer::CopyFrom(const MessageContainer& from) {
|
||||
// @@protoc_insertion_point(class_specific_copy_from_start:community.MessageContainer)
|
||||
if (&from == this) return;
|
||||
Clear();
|
||||
MergeFrom(from);
|
||||
}
|
||||
|
||||
bool MessageContainer::IsInitialized() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
void MessageContainer::Swap(MessageContainer* other) {
|
||||
if (other == this) return;
|
||||
InternalSwap(other);
|
||||
}
|
||||
void MessageContainer::InternalSwap(MessageContainer* other) {
|
||||
using std::swap;
|
||||
message_.InternalSwap(&other->message_);
|
||||
_internal_metadata_.Swap(&other->_internal_metadata_);
|
||||
swap(_cached_size_, other->_cached_size_);
|
||||
}
|
||||
|
||||
::google::protobuf::Metadata MessageContainer::GetMetadata() const {
|
||||
protobuf_container_2eproto::protobuf_AssignDescriptorsOnce();
|
||||
return protobuf_container_2eproto::file_level_metadata[kIndexInFileMessages];
|
||||
}
|
||||
|
||||
#if PROTOBUF_INLINE_NOT_IN_HEADERS
|
||||
// MessageContainer
|
||||
|
||||
// repeated .google.protobuf.Any message = 1;
|
||||
int MessageContainer::message_size() const {
|
||||
return message_.size();
|
||||
}
|
||||
void MessageContainer::clear_message() {
|
||||
message_.Clear();
|
||||
}
|
||||
const ::google::protobuf::Any& MessageContainer::message(int index) const {
|
||||
// @@protoc_insertion_point(field_get:community.MessageContainer.message)
|
||||
return message_.Get(index);
|
||||
}
|
||||
::google::protobuf::Any* MessageContainer::mutable_message(int index) {
|
||||
// @@protoc_insertion_point(field_mutable:community.MessageContainer.message)
|
||||
return message_.Mutable(index);
|
||||
}
|
||||
::google::protobuf::Any* MessageContainer::add_message() {
|
||||
// @@protoc_insertion_point(field_add:community.MessageContainer.message)
|
||||
return message_.Add();
|
||||
}
|
||||
::google::protobuf::RepeatedPtrField< ::google::protobuf::Any >*
|
||||
MessageContainer::mutable_message() {
|
||||
// @@protoc_insertion_point(field_mutable_list:community.MessageContainer.message)
|
||||
return &message_;
|
||||
}
|
||||
const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Any >&
|
||||
MessageContainer::message() const {
|
||||
// @@protoc_insertion_point(field_list:community.MessageContainer.message)
|
||||
return message_;
|
||||
}
|
||||
|
||||
#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
|
||||
|
||||
// @@protoc_insertion_point(namespace_scope)
|
||||
|
||||
} // namespace community
|
||||
|
||||
// @@protoc_insertion_point(global_scope)
|
214
Common/ProtocolBuffer/GenCode/container.pb.h
Normal file
214
Common/ProtocolBuffer/GenCode/container.pb.h
Normal file
@ -0,0 +1,214 @@
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: container.proto
|
||||
|
||||
#ifndef PROTOBUF_container_2eproto__INCLUDED
|
||||
#define PROTOBUF_container_2eproto__INCLUDED
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
#if GOOGLE_PROTOBUF_VERSION < 3004000
|
||||
#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 3004000 < 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/metadata.h>
|
||||
#include <google/protobuf/message.h>
|
||||
#include <google/protobuf/repeated_field.h> // IWYU pragma: export
|
||||
#include <google/protobuf/extension_set.h> // IWYU pragma: export
|
||||
#include <google/protobuf/unknown_field_set.h>
|
||||
#include <google/protobuf/any.pb.h>
|
||||
// @@protoc_insertion_point(includes)
|
||||
namespace community {
|
||||
class MessageContainer;
|
||||
class MessageContainerDefaultTypeInternal;
|
||||
extern MessageContainerDefaultTypeInternal _MessageContainer_default_instance_;
|
||||
} // namespace community
|
||||
|
||||
namespace community {
|
||||
|
||||
namespace protobuf_container_2eproto {
|
||||
// Internal implementation detail -- do not call these.
|
||||
struct TableStruct {
|
||||
static const ::google::protobuf::internal::ParseTableField entries[];
|
||||
static const ::google::protobuf::internal::AuxillaryParseTableField aux[];
|
||||
static const ::google::protobuf::internal::ParseTable schema[];
|
||||
static const ::google::protobuf::uint32 offsets[];
|
||||
static const ::google::protobuf::internal::FieldMetadata field_metadata[];
|
||||
static const ::google::protobuf::internal::SerializationTable serialization_table[];
|
||||
static void InitDefaultsImpl();
|
||||
};
|
||||
void AddDescriptors();
|
||||
void InitDefaults();
|
||||
} // namespace protobuf_container_2eproto
|
||||
|
||||
// ===================================================================
|
||||
|
||||
class MessageContainer : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:community.MessageContainer) */ {
|
||||
public:
|
||||
MessageContainer();
|
||||
virtual ~MessageContainer();
|
||||
|
||||
MessageContainer(const MessageContainer& from);
|
||||
|
||||
inline MessageContainer& operator=(const MessageContainer& from) {
|
||||
CopyFrom(from);
|
||||
return *this;
|
||||
}
|
||||
#if LANG_CXX11
|
||||
MessageContainer(MessageContainer&& from) noexcept
|
||||
: MessageContainer() {
|
||||
*this = ::std::move(from);
|
||||
}
|
||||
|
||||
inline MessageContainer& operator=(MessageContainer&& from) noexcept {
|
||||
if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
|
||||
if (this != &from) InternalSwap(&from);
|
||||
} else {
|
||||
CopyFrom(from);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
static const ::google::protobuf::Descriptor* descriptor();
|
||||
static const MessageContainer& default_instance();
|
||||
|
||||
static inline const MessageContainer* internal_default_instance() {
|
||||
return reinterpret_cast<const MessageContainer*>(
|
||||
&_MessageContainer_default_instance_);
|
||||
}
|
||||
static PROTOBUF_CONSTEXPR int const kIndexInFileMessages =
|
||||
0;
|
||||
|
||||
void Swap(MessageContainer* other);
|
||||
friend void swap(MessageContainer& a, MessageContainer& b) {
|
||||
a.Swap(&b);
|
||||
}
|
||||
|
||||
// implements Message ----------------------------------------------
|
||||
|
||||
inline MessageContainer* New() const PROTOBUF_FINAL { return New(NULL); }
|
||||
|
||||
MessageContainer* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL;
|
||||
void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
|
||||
void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
|
||||
void CopyFrom(const MessageContainer& from);
|
||||
void MergeFrom(const MessageContainer& from);
|
||||
void Clear() PROTOBUF_FINAL;
|
||||
bool IsInitialized() const PROTOBUF_FINAL;
|
||||
|
||||
size_t ByteSizeLong() const PROTOBUF_FINAL;
|
||||
bool MergePartialFromCodedStream(
|
||||
::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL;
|
||||
void SerializeWithCachedSizes(
|
||||
::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL;
|
||||
::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
|
||||
bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL;
|
||||
int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; }
|
||||
private:
|
||||
void SharedCtor();
|
||||
void SharedDtor();
|
||||
void SetCachedSize(int size) const PROTOBUF_FINAL;
|
||||
void InternalSwap(MessageContainer* other);
|
||||
private:
|
||||
inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
|
||||
return NULL;
|
||||
}
|
||||
inline void* MaybeArenaPtr() const {
|
||||
return NULL;
|
||||
}
|
||||
public:
|
||||
|
||||
::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL;
|
||||
|
||||
// nested types ----------------------------------------------------
|
||||
|
||||
// accessors -------------------------------------------------------
|
||||
|
||||
// repeated .google.protobuf.Any message = 1;
|
||||
int message_size() const;
|
||||
void clear_message();
|
||||
static const int kMessageFieldNumber = 1;
|
||||
const ::google::protobuf::Any& message(int index) const;
|
||||
::google::protobuf::Any* mutable_message(int index);
|
||||
::google::protobuf::Any* add_message();
|
||||
::google::protobuf::RepeatedPtrField< ::google::protobuf::Any >*
|
||||
mutable_message();
|
||||
const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Any >&
|
||||
message() const;
|
||||
|
||||
// @@protoc_insertion_point(class_scope:community.MessageContainer)
|
||||
private:
|
||||
|
||||
::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
|
||||
::google::protobuf::RepeatedPtrField< ::google::protobuf::Any > message_;
|
||||
mutable int _cached_size_;
|
||||
friend struct protobuf_container_2eproto::TableStruct;
|
||||
};
|
||||
// ===================================================================
|
||||
|
||||
|
||||
// ===================================================================
|
||||
|
||||
#if !PROTOBUF_INLINE_NOT_IN_HEADERS
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
|
||||
#endif // __GNUC__
|
||||
// MessageContainer
|
||||
|
||||
// repeated .google.protobuf.Any message = 1;
|
||||
inline int MessageContainer::message_size() const {
|
||||
return message_.size();
|
||||
}
|
||||
inline void MessageContainer::clear_message() {
|
||||
message_.Clear();
|
||||
}
|
||||
inline const ::google::protobuf::Any& MessageContainer::message(int index) const {
|
||||
// @@protoc_insertion_point(field_get:community.MessageContainer.message)
|
||||
return message_.Get(index);
|
||||
}
|
||||
inline ::google::protobuf::Any* MessageContainer::mutable_message(int index) {
|
||||
// @@protoc_insertion_point(field_mutable:community.MessageContainer.message)
|
||||
return message_.Mutable(index);
|
||||
}
|
||||
inline ::google::protobuf::Any* MessageContainer::add_message() {
|
||||
// @@protoc_insertion_point(field_add:community.MessageContainer.message)
|
||||
return message_.Add();
|
||||
}
|
||||
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::Any >*
|
||||
MessageContainer::mutable_message() {
|
||||
// @@protoc_insertion_point(field_mutable_list:community.MessageContainer.message)
|
||||
return &message_;
|
||||
}
|
||||
inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Any >&
|
||||
MessageContainer::message() const {
|
||||
// @@protoc_insertion_point(field_list:community.MessageContainer.message)
|
||||
return message_;
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif // __GNUC__
|
||||
#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS
|
||||
|
||||
// @@protoc_insertion_point(namespace_scope)
|
||||
|
||||
|
||||
} // namespace community
|
||||
|
||||
// @@protoc_insertion_point(global_scope)
|
||||
|
||||
#endif // PROTOBUF_container_2eproto__INCLUDED
|
109
Common/ProtocolBuffer/GenCode/world.pb.cc
Normal file
109
Common/ProtocolBuffer/GenCode/world.pb.cc
Normal file
@ -0,0 +1,109 @@
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: world.proto
|
||||
|
||||
#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION
|
||||
#include "world.pb.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/port.h>
|
||||
#include <google/protobuf/stubs/once.h>
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/wire_format_lite_inl.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/generated_message_reflection.h>
|
||||
#include <google/protobuf/reflection_ops.h>
|
||||
#include <google/protobuf/wire_format.h>
|
||||
// @@protoc_insertion_point(includes)
|
||||
|
||||
namespace community {
|
||||
|
||||
namespace protobuf_world_2eproto {
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTableField
|
||||
const TableStruct::entries[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
|
||||
{0, 0, 0, ::google::protobuf::internal::kInvalidMask, 0, 0},
|
||||
};
|
||||
|
||||
PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::AuxillaryParseTableField
|
||||
const TableStruct::aux[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
|
||||
::google::protobuf::internal::AuxillaryParseTableField(),
|
||||
};
|
||||
PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTable const
|
||||
TableStruct::schema[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
|
||||
{ NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
|
||||
};
|
||||
|
||||
const ::google::protobuf::uint32 TableStruct::offsets[1] = {};
|
||||
static const ::google::protobuf::internal::MigrationSchema* schemas = NULL;
|
||||
static const ::google::protobuf::Message* const* file_default_instances = NULL;
|
||||
namespace {
|
||||
|
||||
void protobuf_AssignDescriptors() {
|
||||
AddDescriptors();
|
||||
::google::protobuf::MessageFactory* factory = NULL;
|
||||
AssignDescriptors(
|
||||
"world.proto", schemas, file_default_instances, TableStruct::offsets, factory,
|
||||
NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
void protobuf_AssignDescriptorsOnce() {
|
||||
static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
|
||||
::google::protobuf::GoogleOnceInit(&once, &protobuf_AssignDescriptors);
|
||||
}
|
||||
|
||||
void protobuf_RegisterTypes(const ::std::string&) GOOGLE_ATTRIBUTE_COLD;
|
||||
void protobuf_RegisterTypes(const ::std::string&) {
|
||||
protobuf_AssignDescriptorsOnce();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
void TableStruct::InitDefaultsImpl() {
|
||||
GOOGLE_PROTOBUF_VERIFY_VERSION;
|
||||
|
||||
::google::protobuf::internal::InitProtobufDefaults();
|
||||
}
|
||||
|
||||
void InitDefaults() {
|
||||
static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
|
||||
::google::protobuf::GoogleOnceInit(&once, &TableStruct::InitDefaultsImpl);
|
||||
}
|
||||
namespace {
|
||||
void AddDescriptorsImpl() {
|
||||
InitDefaults();
|
||||
static const char descriptor[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
|
||||
"\n\013world.proto\022\tcommunityb\006proto3"
|
||||
};
|
||||
::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
|
||||
descriptor, 32);
|
||||
::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
|
||||
"world.proto", &protobuf_RegisterTypes);
|
||||
}
|
||||
} // anonymous namespace
|
||||
|
||||
void AddDescriptors() {
|
||||
static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
|
||||
::google::protobuf::GoogleOnceInit(&once, &AddDescriptorsImpl);
|
||||
}
|
||||
// Force AddDescriptors() to be called at dynamic initialization time.
|
||||
struct StaticDescriptorInitializer {
|
||||
StaticDescriptorInitializer() {
|
||||
AddDescriptors();
|
||||
}
|
||||
} static_descriptor_initializer;
|
||||
|
||||
} // namespace protobuf_world_2eproto
|
||||
|
||||
|
||||
// @@protoc_insertion_point(namespace_scope)
|
||||
|
||||
} // namespace community
|
||||
|
||||
// @@protoc_insertion_point(global_scope)
|
76
Common/ProtocolBuffer/GenCode/world.pb.h
Normal file
76
Common/ProtocolBuffer/GenCode/world.pb.h
Normal file
@ -0,0 +1,76 @@
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: world.proto
|
||||
|
||||
#ifndef PROTOBUF_world_2eproto__INCLUDED
|
||||
#define PROTOBUF_world_2eproto__INCLUDED
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
#if GOOGLE_PROTOBUF_VERSION < 3004000
|
||||
#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 3004000 < 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/metadata.h>
|
||||
#include <google/protobuf/repeated_field.h> // IWYU pragma: export
|
||||
#include <google/protobuf/extension_set.h> // IWYU pragma: export
|
||||
// @@protoc_insertion_point(includes)
|
||||
namespace community {
|
||||
} // namespace community
|
||||
|
||||
namespace community {
|
||||
|
||||
namespace protobuf_world_2eproto {
|
||||
// Internal implementation detail -- do not call these.
|
||||
struct TableStruct {
|
||||
static const ::google::protobuf::internal::ParseTableField entries[];
|
||||
static const ::google::protobuf::internal::AuxillaryParseTableField aux[];
|
||||
static const ::google::protobuf::internal::ParseTable schema[];
|
||||
static const ::google::protobuf::uint32 offsets[];
|
||||
static const ::google::protobuf::internal::FieldMetadata field_metadata[];
|
||||
static const ::google::protobuf::internal::SerializationTable serialization_table[];
|
||||
static void InitDefaultsImpl();
|
||||
};
|
||||
void AddDescriptors();
|
||||
void InitDefaults();
|
||||
} // namespace protobuf_world_2eproto
|
||||
|
||||
// ===================================================================
|
||||
|
||||
|
||||
// ===================================================================
|
||||
|
||||
|
||||
// ===================================================================
|
||||
|
||||
#if !PROTOBUF_INLINE_NOT_IN_HEADERS
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
|
||||
#endif // __GNUC__
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif // __GNUC__
|
||||
#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS
|
||||
|
||||
// @@protoc_insertion_point(namespace_scope)
|
||||
|
||||
|
||||
} // namespace community
|
||||
|
||||
// @@protoc_insertion_point(global_scope)
|
||||
|
||||
#endif // PROTOBUF_world_2eproto__INCLUDED
|
@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
Msys2Path='C:\\msys64\\mingw64\\bin'
|
||||
args=' --proto_path=../ --cpp_out=../GenCode ../*.proto'
|
||||
exec ../GenTools/protoc.exe $args #// for local compile on windows
|
||||
pause
|
@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
Msys2Path='C:\\msys64\\mingw64\\bin'
|
||||
args=' --proto_path=../ --cpp_out=../GenCode ../*.proto'
|
||||
exec $Msys2Path'\\'protoc.exe $args
|
||||
pause
|
3
Common/ProtocolBuffer/GenTools/libprotobuf-lite.dll
Normal file
3
Common/ProtocolBuffer/GenTools/libprotobuf-lite.dll
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:1827ffcf3ef3827ae7f9f4e6189cd88c0ecd9fb01e87c507273844321f42e60c
|
||||
size 394806
|
3
Common/ProtocolBuffer/GenTools/libprotobuf.dll
Normal file
3
Common/ProtocolBuffer/GenTools/libprotobuf.dll
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:88d99ad5e98290bd27d6c7bec4f1303a2cc6924f565e3644a01aac60bf9b04bd
|
||||
size 2461906
|
3
Common/ProtocolBuffer/GenTools/libprotoc.dll
Normal file
3
Common/ProtocolBuffer/GenTools/libprotoc.dll
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:a2ab3641bfc9badfa3365f80305eb051648ce6bc3044a2c2df1bcd32bb508bea
|
||||
size 2564731
|
3
Common/ProtocolBuffer/GenTools/protoc.exe
Normal file
3
Common/ProtocolBuffer/GenTools/protoc.exe
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:4505e4a3643d761e760d7ead2c2492cc9461ce532bd51b8f2c486902bdf0e8d3
|
||||
size 30157
|
8
Common/ProtocolBuffer/account.proto
Normal file
8
Common/ProtocolBuffer/account.proto
Normal file
@ -0,0 +1,8 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package community;
|
||||
|
||||
message Login {
|
||||
string username = 1;
|
||||
string password = 2;
|
||||
}
|
3
Common/ProtocolBuffer/character.proto
Normal file
3
Common/ProtocolBuffer/character.proto
Normal file
@ -0,0 +1,3 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package community;
|
10
Common/ProtocolBuffer/container.proto
Normal file
10
Common/ProtocolBuffer/container.proto
Normal file
@ -0,0 +1,10 @@
|
||||
syntax = "proto3";
|
||||
|
||||
import "google/protobuf/any.proto";
|
||||
|
||||
package community;
|
||||
|
||||
message MessageContainer
|
||||
{
|
||||
repeated google.protobuf.Any message = 1;
|
||||
}
|
123
Common/ProtocolBuffer/google/protobuf/any.cc
Normal file
123
Common/ProtocolBuffer/google/protobuf/any.cc
Normal file
@ -0,0 +1,123 @@
|
||||
// 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/any.h>
|
||||
|
||||
#include <google/protobuf/generated_message_util.h>
|
||||
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
namespace {
|
||||
string GetTypeUrl(const Descriptor* message,
|
||||
const string& type_url_prefix) {
|
||||
if (!type_url_prefix.empty() &&
|
||||
type_url_prefix[type_url_prefix.size() - 1] == '/') {
|
||||
return type_url_prefix + message->full_name();
|
||||
} else {
|
||||
return type_url_prefix + "/" + message->full_name();
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
const char kAnyFullTypeName[] = "google.protobuf.Any";
|
||||
const char kTypeGoogleApisComPrefix[] = "type.googleapis.com/";
|
||||
const char kTypeGoogleProdComPrefix[] = "type.googleprod.com/";
|
||||
|
||||
AnyMetadata::AnyMetadata(UrlType* type_url, ValueType* value)
|
||||
: type_url_(type_url), value_(value) {
|
||||
}
|
||||
|
||||
void AnyMetadata::PackFrom(const Message& message) {
|
||||
PackFrom(message, kTypeGoogleApisComPrefix);
|
||||
}
|
||||
|
||||
void AnyMetadata::PackFrom(const Message& message,
|
||||
const string& type_url_prefix) {
|
||||
type_url_->SetNoArena(&::google::protobuf::internal::GetEmptyString(),
|
||||
GetTypeUrl(message.GetDescriptor(), type_url_prefix));
|
||||
message.SerializeToString(value_->MutableNoArena(
|
||||
&::google::protobuf::internal::GetEmptyStringAlreadyInited()));
|
||||
}
|
||||
|
||||
bool AnyMetadata::UnpackTo(Message* message) const {
|
||||
if (!InternalIs(message->GetDescriptor())) {
|
||||
return false;
|
||||
}
|
||||
return message->ParseFromString(value_->GetNoArena());
|
||||
}
|
||||
|
||||
bool AnyMetadata::InternalIs(const Descriptor* descriptor) const {
|
||||
const string type_url = type_url_->GetNoArena();
|
||||
string full_name;
|
||||
if (!ParseAnyTypeUrl(type_url, &full_name)) {
|
||||
return false;
|
||||
}
|
||||
return full_name == descriptor->full_name();
|
||||
}
|
||||
|
||||
bool ParseAnyTypeUrl(const string& type_url, string* url_prefix,
|
||||
string* full_type_name) {
|
||||
size_t pos = type_url.find_last_of("/");
|
||||
if (pos == string::npos || pos + 1 == type_url.size()) {
|
||||
return false;
|
||||
}
|
||||
if (url_prefix) {
|
||||
*url_prefix = type_url.substr(0, pos + 1);
|
||||
}
|
||||
*full_type_name = type_url.substr(pos + 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ParseAnyTypeUrl(const string& type_url, string* full_type_name) {
|
||||
return ParseAnyTypeUrl(type_url, NULL, full_type_name);
|
||||
}
|
||||
|
||||
|
||||
bool GetAnyFieldDescriptors(const Message& message,
|
||||
const FieldDescriptor** type_url_field,
|
||||
const FieldDescriptor** value_field) {
|
||||
const Descriptor* descriptor = message.GetDescriptor();
|
||||
if (descriptor->full_name() != kAnyFullTypeName) {
|
||||
return false;
|
||||
}
|
||||
*type_url_field = descriptor->FindFieldByNumber(1);
|
||||
*value_field = descriptor->FindFieldByNumber(2);
|
||||
return (*type_url_field != NULL &&
|
||||
(*type_url_field)->type() == FieldDescriptor::TYPE_STRING &&
|
||||
*value_field != NULL &&
|
||||
(*value_field)->type() == FieldDescriptor::TYPE_BYTES);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
118
Common/ProtocolBuffer/google/protobuf/any.h
Normal file
118
Common/ProtocolBuffer/google/protobuf/any.h
Normal file
@ -0,0 +1,118 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_ANY_H__
|
||||
#define GOOGLE_PROTOBUF_ANY_H__
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/message.h>
|
||||
#include <google/protobuf/arenastring.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
// Helper class used to implement google::protobuf::Any.
|
||||
class LIBPROTOBUF_EXPORT AnyMetadata {
|
||||
typedef ArenaStringPtr UrlType;
|
||||
typedef ArenaStringPtr ValueType;
|
||||
public:
|
||||
// AnyMetadata does not take ownership of "type_url" and "value".
|
||||
AnyMetadata(UrlType* type_url, ValueType* value);
|
||||
|
||||
// Packs a message using the default type URL prefix: "type.googleapis.com".
|
||||
// The resulted type URL will be "type.googleapis.com/<message_full_name>".
|
||||
void PackFrom(const Message& message);
|
||||
// Packs a message using the given type URL prefix. The type URL will be
|
||||
// constructed by concatenating the message type's full name to the prefix
|
||||
// with an optional "/" separator if the prefix doesn't already end up "/".
|
||||
// For example, both PackFrom(message, "type.googleapis.com") and
|
||||
// PackFrom(message, "type.googleapis.com/") yield the same result type
|
||||
// URL: "type.googleapis.com/<message_full_name>".
|
||||
void PackFrom(const Message& message, const string& type_url_prefix);
|
||||
|
||||
// Unpacks the payload into the given message. Returns false if the message's
|
||||
// type doesn't match the type specified in the type URL (i.e., the full
|
||||
// name after the last "/" of the type URL doesn't match the message's actual
|
||||
// full name) or parsing the payload has failed.
|
||||
bool UnpackTo(Message* message) const;
|
||||
|
||||
// Checks whether the type specified in the type URL matches the given type.
|
||||
// A type is consdiered matching if its full name matches the full name after
|
||||
// the last "/" in the type URL.
|
||||
template<typename T>
|
||||
bool Is() const {
|
||||
return InternalIs(T::default_instance().GetDescriptor());
|
||||
}
|
||||
|
||||
private:
|
||||
bool InternalIs(const Descriptor* message) const;
|
||||
|
||||
UrlType* type_url_;
|
||||
ValueType* value_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(AnyMetadata);
|
||||
};
|
||||
|
||||
extern const char kAnyFullTypeName[]; // "google.protobuf.Any".
|
||||
extern const char kTypeGoogleApisComPrefix[]; // "type.googleapis.com/".
|
||||
extern const char kTypeGoogleProdComPrefix[]; // "type.googleprod.com/".
|
||||
|
||||
// Get the proto type name from Any::type_url value. For example, passing
|
||||
// "type.googleapis.com/rpc.QueryOrigin" will return "rpc.QueryOrigin" in
|
||||
// *full_type_name. Returns false if the type_url does not have a "/"
|
||||
// in the type url separating the full type name.
|
||||
//
|
||||
// NOTE: this function is available publicly as:
|
||||
// google::protobuf::Any() // static method on the generated message type.
|
||||
bool ParseAnyTypeUrl(const string& type_url, string* full_type_name);
|
||||
|
||||
// Get the proto type name and prefix from Any::type_url value. For example,
|
||||
// passing "type.googleapis.com/rpc.QueryOrigin" will return
|
||||
// "type.googleapis.com/" in *url_prefix and "rpc.QueryOrigin" in
|
||||
// *full_type_name. Returns false if the type_url does not have a "/" in the
|
||||
// type url separating the full type name.
|
||||
bool ParseAnyTypeUrl(const string& type_url, string* url_prefix,
|
||||
string* full_type_name);
|
||||
|
||||
// See if message is of type google.protobuf.Any, if so, return the descriptors
|
||||
// for "type_url" and "value" fields.
|
||||
bool GetAnyFieldDescriptors(const Message& message,
|
||||
const FieldDescriptor** type_url_field,
|
||||
const FieldDescriptor** value_field);
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_ANY_H__
|
435
Common/ProtocolBuffer/google/protobuf/any.pb.cc
Normal file
435
Common/ProtocolBuffer/google/protobuf/any.pb.cc
Normal file
@ -0,0 +1,435 @@
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: google/protobuf/any.proto
|
||||
|
||||
#include <google/protobuf/any.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/descriptor.h>
|
||||
#include <google/protobuf/generated_message_reflection.h>
|
||||
#include <google/protobuf/reflection_ops.h>
|
||||
#include <google/protobuf/wire_format.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 google {
|
||||
namespace protobuf {
|
||||
class AnyDefaultTypeInternal {
|
||||
public:
|
||||
::google::protobuf::internal::ExplicitlyConstructed<Any>
|
||||
_instance;
|
||||
} _Any_default_instance_;
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
namespace protobuf_google_2fprotobuf_2fany_2eproto {
|
||||
static void InitDefaultsAny() {
|
||||
GOOGLE_PROTOBUF_VERIFY_VERSION;
|
||||
|
||||
{
|
||||
void* ptr = &::google::protobuf::_Any_default_instance_;
|
||||
new (ptr) ::google::protobuf::Any();
|
||||
::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
|
||||
}
|
||||
::google::protobuf::Any::InitAsDefaultInstance();
|
||||
}
|
||||
|
||||
LIBPROTOBUF_EXPORT ::google::protobuf::internal::SCCInfo<0> scc_info_Any =
|
||||
{{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 0, InitDefaultsAny}, {}};
|
||||
|
||||
void InitDefaults() {
|
||||
::google::protobuf::internal::InitSCC(&scc_info_Any.base);
|
||||
}
|
||||
|
||||
::google::protobuf::Metadata file_level_metadata[1];
|
||||
|
||||
const ::google::protobuf::uint32 TableStruct::offsets[] GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
|
||||
~0u, // no _has_bits_
|
||||
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::Any, _internal_metadata_),
|
||||
~0u, // no _extensions_
|
||||
~0u, // no _oneof_case_
|
||||
~0u, // no _weak_field_map_
|
||||
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::Any, type_url_),
|
||||
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::Any, value_),
|
||||
};
|
||||
static const ::google::protobuf::internal::MigrationSchema schemas[] GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
|
||||
{ 0, -1, sizeof(::google::protobuf::Any)},
|
||||
};
|
||||
|
||||
static ::google::protobuf::Message const * const file_default_instances[] = {
|
||||
reinterpret_cast<const ::google::protobuf::Message*>(&::google::protobuf::_Any_default_instance_),
|
||||
};
|
||||
|
||||
void protobuf_AssignDescriptors() {
|
||||
AddDescriptors();
|
||||
AssignDescriptors(
|
||||
"google/protobuf/any.proto", schemas, file_default_instances, TableStruct::offsets,
|
||||
file_level_metadata, NULL, NULL);
|
||||
}
|
||||
|
||||
void protobuf_AssignDescriptorsOnce() {
|
||||
static ::google::protobuf::internal::once_flag once;
|
||||
::google::protobuf::internal::call_once(once, protobuf_AssignDescriptors);
|
||||
}
|
||||
|
||||
void protobuf_RegisterTypes(const ::std::string&) GOOGLE_PROTOBUF_ATTRIBUTE_COLD;
|
||||
void protobuf_RegisterTypes(const ::std::string&) {
|
||||
protobuf_AssignDescriptorsOnce();
|
||||
::google::protobuf::internal::RegisterAllTypes(file_level_metadata, 1);
|
||||
}
|
||||
|
||||
void AddDescriptorsImpl() {
|
||||
InitDefaults();
|
||||
static const char descriptor[] GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
|
||||
"\n\031google/protobuf/any.proto\022\017google.prot"
|
||||
"obuf\"&\n\003Any\022\020\n\010type_url\030\001 \001(\t\022\r\n\005value\030\002"
|
||||
" \001(\014Bo\n\023com.google.protobufB\010AnyProtoP\001Z"
|
||||
"%github.com/golang/protobuf/ptypes/any\242\002"
|
||||
"\003GPB\252\002\036Google.Protobuf.WellKnownTypesb\006p"
|
||||
"roto3"
|
||||
};
|
||||
::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
|
||||
descriptor, 205);
|
||||
::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
|
||||
"google/protobuf/any.proto", &protobuf_RegisterTypes);
|
||||
}
|
||||
|
||||
void AddDescriptors() {
|
||||
static ::google::protobuf::internal::once_flag once;
|
||||
::google::protobuf::internal::call_once(once, AddDescriptorsImpl);
|
||||
}
|
||||
// Force AddDescriptors() to be called at dynamic initialization time.
|
||||
struct StaticDescriptorInitializer {
|
||||
StaticDescriptorInitializer() {
|
||||
AddDescriptors();
|
||||
}
|
||||
} static_descriptor_initializer;
|
||||
} // namespace protobuf_google_2fprotobuf_2fany_2eproto
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
// ===================================================================
|
||||
|
||||
void Any::InitAsDefaultInstance() {
|
||||
}
|
||||
void Any::PackFrom(const ::google::protobuf::Message& message) {
|
||||
_any_metadata_.PackFrom(message);
|
||||
}
|
||||
|
||||
void Any::PackFrom(const ::google::protobuf::Message& message,
|
||||
const ::std::string& type_url_prefix) {
|
||||
_any_metadata_.PackFrom(message, type_url_prefix);
|
||||
}
|
||||
|
||||
bool Any::UnpackTo(::google::protobuf::Message* message) const {
|
||||
return _any_metadata_.UnpackTo(message);
|
||||
}
|
||||
bool Any::ParseAnyTypeUrl(const string& type_url,
|
||||
string* full_type_name) {
|
||||
return ::google::protobuf::internal::ParseAnyTypeUrl(type_url,
|
||||
full_type_name);
|
||||
}
|
||||
|
||||
#if !defined(_MSC_VER) || _MSC_VER >= 1900
|
||||
const int Any::kTypeUrlFieldNumber;
|
||||
const int Any::kValueFieldNumber;
|
||||
#endif // !defined(_MSC_VER) || _MSC_VER >= 1900
|
||||
|
||||
Any::Any()
|
||||
: ::google::protobuf::Message(), _internal_metadata_(NULL), _any_metadata_(&type_url_, &value_) {
|
||||
::google::protobuf::internal::InitSCC(
|
||||
&protobuf_google_2fprotobuf_2fany_2eproto::scc_info_Any.base);
|
||||
SharedCtor();
|
||||
// @@protoc_insertion_point(constructor:google.protobuf.Any)
|
||||
}
|
||||
Any::Any(const Any& from)
|
||||
: ::google::protobuf::Message(),
|
||||
_internal_metadata_(NULL),
|
||||
_any_metadata_(&type_url_, &value_) {
|
||||
_internal_metadata_.MergeFrom(from._internal_metadata_);
|
||||
type_url_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
if (from.type_url().size() > 0) {
|
||||
type_url_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.type_url_);
|
||||
}
|
||||
value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
if (from.value().size() > 0) {
|
||||
value_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.value_);
|
||||
}
|
||||
// @@protoc_insertion_point(copy_constructor:google.protobuf.Any)
|
||||
}
|
||||
|
||||
void Any::SharedCtor() {
|
||||
type_url_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
|
||||
Any::~Any() {
|
||||
// @@protoc_insertion_point(destructor:google.protobuf.Any)
|
||||
SharedDtor();
|
||||
}
|
||||
|
||||
void Any::SharedDtor() {
|
||||
type_url_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
value_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
|
||||
void Any::SetCachedSize(int size) const {
|
||||
_cached_size_.Set(size);
|
||||
}
|
||||
const ::google::protobuf::Descriptor* Any::descriptor() {
|
||||
::protobuf_google_2fprotobuf_2fany_2eproto::protobuf_AssignDescriptorsOnce();
|
||||
return ::protobuf_google_2fprotobuf_2fany_2eproto::file_level_metadata[kIndexInFileMessages].descriptor;
|
||||
}
|
||||
|
||||
const Any& Any::default_instance() {
|
||||
::google::protobuf::internal::InitSCC(&protobuf_google_2fprotobuf_2fany_2eproto::scc_info_Any.base);
|
||||
return *internal_default_instance();
|
||||
}
|
||||
|
||||
|
||||
void Any::Clear() {
|
||||
// @@protoc_insertion_point(message_clear_start:google.protobuf.Any)
|
||||
::google::protobuf::uint32 cached_has_bits = 0;
|
||||
// Prevent compiler warnings about cached_has_bits being unused
|
||||
(void) cached_has_bits;
|
||||
|
||||
type_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
_internal_metadata_.Clear();
|
||||
}
|
||||
|
||||
bool Any::MergePartialFromCodedStream(
|
||||
::google::protobuf::io::CodedInputStream* input) {
|
||||
#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
|
||||
::google::protobuf::uint32 tag;
|
||||
// @@protoc_insertion_point(parse_start:google.protobuf.Any)
|
||||
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)) {
|
||||
// string type_url = 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_type_url()));
|
||||
DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
|
||||
this->type_url().data(), static_cast<int>(this->type_url().length()),
|
||||
::google::protobuf::internal::WireFormatLite::PARSE,
|
||||
"google.protobuf.Any.type_url"));
|
||||
} else {
|
||||
goto handle_unusual;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// bytes value = 2;
|
||||
case 2: {
|
||||
if (static_cast< ::google::protobuf::uint8>(tag) ==
|
||||
static_cast< ::google::protobuf::uint8>(18u /* 18 & 0xFF */)) {
|
||||
DO_(::google::protobuf::internal::WireFormatLite::ReadBytes(
|
||||
input, this->mutable_value()));
|
||||
} else {
|
||||
goto handle_unusual;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
handle_unusual:
|
||||
if (tag == 0) {
|
||||
goto success;
|
||||
}
|
||||
DO_(::google::protobuf::internal::WireFormat::SkipField(
|
||||
input, tag, _internal_metadata_.mutable_unknown_fields()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
success:
|
||||
// @@protoc_insertion_point(parse_success:google.protobuf.Any)
|
||||
return true;
|
||||
failure:
|
||||
// @@protoc_insertion_point(parse_failure:google.protobuf.Any)
|
||||
return false;
|
||||
#undef DO_
|
||||
}
|
||||
|
||||
void Any::SerializeWithCachedSizes(
|
||||
::google::protobuf::io::CodedOutputStream* output) const {
|
||||
// @@protoc_insertion_point(serialize_start:google.protobuf.Any)
|
||||
::google::protobuf::uint32 cached_has_bits = 0;
|
||||
(void) cached_has_bits;
|
||||
|
||||
// string type_url = 1;
|
||||
if (this->type_url().size() > 0) {
|
||||
::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
|
||||
this->type_url().data(), static_cast<int>(this->type_url().length()),
|
||||
::google::protobuf::internal::WireFormatLite::SERIALIZE,
|
||||
"google.protobuf.Any.type_url");
|
||||
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
|
||||
1, this->type_url(), output);
|
||||
}
|
||||
|
||||
// bytes value = 2;
|
||||
if (this->value().size() > 0) {
|
||||
::google::protobuf::internal::WireFormatLite::WriteBytesMaybeAliased(
|
||||
2, this->value(), output);
|
||||
}
|
||||
|
||||
if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
|
||||
::google::protobuf::internal::WireFormat::SerializeUnknownFields(
|
||||
(::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()), output);
|
||||
}
|
||||
// @@protoc_insertion_point(serialize_end:google.protobuf.Any)
|
||||
}
|
||||
|
||||
::google::protobuf::uint8* Any::InternalSerializeWithCachedSizesToArray(
|
||||
bool deterministic, ::google::protobuf::uint8* target) const {
|
||||
(void)deterministic; // Unused
|
||||
// @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Any)
|
||||
::google::protobuf::uint32 cached_has_bits = 0;
|
||||
(void) cached_has_bits;
|
||||
|
||||
// string type_url = 1;
|
||||
if (this->type_url().size() > 0) {
|
||||
::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
|
||||
this->type_url().data(), static_cast<int>(this->type_url().length()),
|
||||
::google::protobuf::internal::WireFormatLite::SERIALIZE,
|
||||
"google.protobuf.Any.type_url");
|
||||
target =
|
||||
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
|
||||
1, this->type_url(), target);
|
||||
}
|
||||
|
||||
// bytes value = 2;
|
||||
if (this->value().size() > 0) {
|
||||
target =
|
||||
::google::protobuf::internal::WireFormatLite::WriteBytesToArray(
|
||||
2, this->value(), target);
|
||||
}
|
||||
|
||||
if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
|
||||
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
|
||||
(::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()), target);
|
||||
}
|
||||
// @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Any)
|
||||
return target;
|
||||
}
|
||||
|
||||
size_t Any::ByteSizeLong() const {
|
||||
// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Any)
|
||||
size_t total_size = 0;
|
||||
|
||||
if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
|
||||
total_size +=
|
||||
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
|
||||
(::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()));
|
||||
}
|
||||
// string type_url = 1;
|
||||
if (this->type_url().size() > 0) {
|
||||
total_size += 1 +
|
||||
::google::protobuf::internal::WireFormatLite::StringSize(
|
||||
this->type_url());
|
||||
}
|
||||
|
||||
// bytes value = 2;
|
||||
if (this->value().size() > 0) {
|
||||
total_size += 1 +
|
||||
::google::protobuf::internal::WireFormatLite::BytesSize(
|
||||
this->value());
|
||||
}
|
||||
|
||||
int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
|
||||
SetCachedSize(cached_size);
|
||||
return total_size;
|
||||
}
|
||||
|
||||
void Any::MergeFrom(const ::google::protobuf::Message& from) {
|
||||
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Any)
|
||||
GOOGLE_DCHECK_NE(&from, this);
|
||||
const Any* source =
|
||||
::google::protobuf::internal::DynamicCastToGenerated<const Any>(
|
||||
&from);
|
||||
if (source == NULL) {
|
||||
// @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Any)
|
||||
::google::protobuf::internal::ReflectionOps::Merge(from, this);
|
||||
} else {
|
||||
// @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Any)
|
||||
MergeFrom(*source);
|
||||
}
|
||||
}
|
||||
|
||||
void Any::MergeFrom(const Any& from) {
|
||||
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Any)
|
||||
GOOGLE_DCHECK_NE(&from, this);
|
||||
_internal_metadata_.MergeFrom(from._internal_metadata_);
|
||||
::google::protobuf::uint32 cached_has_bits = 0;
|
||||
(void) cached_has_bits;
|
||||
|
||||
if (from.type_url().size() > 0) {
|
||||
|
||||
type_url_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.type_url_);
|
||||
}
|
||||
if (from.value().size() > 0) {
|
||||
|
||||
value_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.value_);
|
||||
}
|
||||
}
|
||||
|
||||
void Any::CopyFrom(const ::google::protobuf::Message& from) {
|
||||
// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Any)
|
||||
if (&from == this) return;
|
||||
Clear();
|
||||
MergeFrom(from);
|
||||
}
|
||||
|
||||
void Any::CopyFrom(const Any& from) {
|
||||
// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Any)
|
||||
if (&from == this) return;
|
||||
Clear();
|
||||
MergeFrom(from);
|
||||
}
|
||||
|
||||
bool Any::IsInitialized() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
void Any::Swap(Any* other) {
|
||||
if (other == this) return;
|
||||
InternalSwap(other);
|
||||
}
|
||||
void Any::InternalSwap(Any* other) {
|
||||
using std::swap;
|
||||
type_url_.Swap(&other->type_url_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
|
||||
GetArenaNoVirtual());
|
||||
value_.Swap(&other->value_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
|
||||
GetArenaNoVirtual());
|
||||
_internal_metadata_.Swap(&other->_internal_metadata_);
|
||||
}
|
||||
|
||||
::google::protobuf::Metadata Any::GetMetadata() const {
|
||||
protobuf_google_2fprotobuf_2fany_2eproto::protobuf_AssignDescriptorsOnce();
|
||||
return ::protobuf_google_2fprotobuf_2fany_2eproto::file_level_metadata[kIndexInFileMessages];
|
||||
}
|
||||
|
||||
|
||||
// @@protoc_insertion_point(namespace_scope)
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
template<> GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE ::google::protobuf::Any* Arena::CreateMaybeMessage< ::google::protobuf::Any >(Arena* arena) {
|
||||
return Arena::CreateInternal< ::google::protobuf::Any >(arena);
|
||||
}
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
// @@protoc_insertion_point(global_scope)
|
331
Common/ProtocolBuffer/google/protobuf/any.pb.h
Normal file
331
Common/ProtocolBuffer/google/protobuf/any.pb.h
Normal file
@ -0,0 +1,331 @@
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: google/protobuf/any.proto
|
||||
|
||||
#ifndef PROTOBUF_INCLUDED_google_2fprotobuf_2fany_2eproto
|
||||
#define PROTOBUF_INCLUDED_google_2fprotobuf_2fany_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.h>
|
||||
#include <google/protobuf/message.h>
|
||||
#include <google/protobuf/repeated_field.h> // IWYU pragma: export
|
||||
#include <google/protobuf/extension_set.h> // IWYU pragma: export
|
||||
#include <google/protobuf/unknown_field_set.h>
|
||||
#include <google/protobuf/any.h>
|
||||
// @@protoc_insertion_point(includes)
|
||||
#define PROTOBUF_INTERNAL_EXPORT_protobuf_google_2fprotobuf_2fany_2eproto LIBPROTOBUF_EXPORT
|
||||
|
||||
namespace protobuf_google_2fprotobuf_2fany_2eproto {
|
||||
// Internal implementation detail -- do not use these members.
|
||||
struct LIBPROTOBUF_EXPORT TableStruct {
|
||||
static const ::google::protobuf::internal::ParseTableField entries[];
|
||||
static const ::google::protobuf::internal::AuxillaryParseTableField aux[];
|
||||
static const ::google::protobuf::internal::ParseTable schema[1];
|
||||
static const ::google::protobuf::internal::FieldMetadata field_metadata[];
|
||||
static const ::google::protobuf::internal::SerializationTable serialization_table[];
|
||||
static const ::google::protobuf::uint32 offsets[];
|
||||
};
|
||||
void LIBPROTOBUF_EXPORT AddDescriptors();
|
||||
} // namespace protobuf_google_2fprotobuf_2fany_2eproto
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
class Any;
|
||||
class AnyDefaultTypeInternal;
|
||||
LIBPROTOBUF_EXPORT extern AnyDefaultTypeInternal _Any_default_instance_;
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
template<> LIBPROTOBUF_EXPORT ::google::protobuf::Any* Arena::CreateMaybeMessage<::google::protobuf::Any>(Arena*);
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
// ===================================================================
|
||||
|
||||
class LIBPROTOBUF_EXPORT Any : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Any) */ {
|
||||
public:
|
||||
Any();
|
||||
virtual ~Any();
|
||||
|
||||
Any(const Any& from);
|
||||
|
||||
inline Any& operator=(const Any& from) {
|
||||
CopyFrom(from);
|
||||
return *this;
|
||||
}
|
||||
#if LANG_CXX11
|
||||
Any(Any&& from) noexcept
|
||||
: Any() {
|
||||
*this = ::std::move(from);
|
||||
}
|
||||
|
||||
inline Any& operator=(Any&& from) noexcept {
|
||||
if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
|
||||
if (this != &from) InternalSwap(&from);
|
||||
} else {
|
||||
CopyFrom(from);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
static const ::google::protobuf::Descriptor* descriptor();
|
||||
static const Any& default_instance();
|
||||
|
||||
static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY
|
||||
static inline const Any* internal_default_instance() {
|
||||
return reinterpret_cast<const Any*>(
|
||||
&_Any_default_instance_);
|
||||
}
|
||||
static constexpr int kIndexInFileMessages =
|
||||
0;
|
||||
|
||||
// implements Any -----------------------------------------------
|
||||
|
||||
void PackFrom(const ::google::protobuf::Message& message);
|
||||
void PackFrom(const ::google::protobuf::Message& message,
|
||||
const ::std::string& type_url_prefix);
|
||||
bool UnpackTo(::google::protobuf::Message* message) const;
|
||||
template<typename T> bool Is() const {
|
||||
return _any_metadata_.Is<T>();
|
||||
}
|
||||
static bool ParseAnyTypeUrl(const string& type_url,
|
||||
string* full_type_name);
|
||||
|
||||
void Swap(Any* other);
|
||||
friend void swap(Any& a, Any& b) {
|
||||
a.Swap(&b);
|
||||
}
|
||||
|
||||
// implements Message ----------------------------------------------
|
||||
|
||||
inline Any* New() const final {
|
||||
return CreateMaybeMessage<Any>(NULL);
|
||||
}
|
||||
|
||||
Any* New(::google::protobuf::Arena* arena) const final {
|
||||
return CreateMaybeMessage<Any>(arena);
|
||||
}
|
||||
void CopyFrom(const ::google::protobuf::Message& from) final;
|
||||
void MergeFrom(const ::google::protobuf::Message& from) final;
|
||||
void CopyFrom(const Any& from);
|
||||
void MergeFrom(const Any& 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;
|
||||
::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
|
||||
bool deterministic, ::google::protobuf::uint8* target) const final;
|
||||
int GetCachedSize() const final { return _cached_size_.Get(); }
|
||||
|
||||
private:
|
||||
void SharedCtor();
|
||||
void SharedDtor();
|
||||
void SetCachedSize(int size) const final;
|
||||
void InternalSwap(Any* other);
|
||||
private:
|
||||
inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
|
||||
return NULL;
|
||||
}
|
||||
inline void* MaybeArenaPtr() const {
|
||||
return NULL;
|
||||
}
|
||||
public:
|
||||
|
||||
::google::protobuf::Metadata GetMetadata() const final;
|
||||
|
||||
// nested types ----------------------------------------------------
|
||||
|
||||
// accessors -------------------------------------------------------
|
||||
|
||||
// string type_url = 1;
|
||||
void clear_type_url();
|
||||
static const int kTypeUrlFieldNumber = 1;
|
||||
const ::std::string& type_url() const;
|
||||
void set_type_url(const ::std::string& value);
|
||||
#if LANG_CXX11
|
||||
void set_type_url(::std::string&& value);
|
||||
#endif
|
||||
void set_type_url(const char* value);
|
||||
void set_type_url(const char* value, size_t size);
|
||||
::std::string* mutable_type_url();
|
||||
::std::string* release_type_url();
|
||||
void set_allocated_type_url(::std::string* type_url);
|
||||
|
||||
// bytes value = 2;
|
||||
void clear_value();
|
||||
static const int kValueFieldNumber = 2;
|
||||
const ::std::string& value() const;
|
||||
void set_value(const ::std::string& value);
|
||||
#if LANG_CXX11
|
||||
void set_value(::std::string&& value);
|
||||
#endif
|
||||
void set_value(const char* value);
|
||||
void set_value(const void* value, size_t size);
|
||||
::std::string* mutable_value();
|
||||
::std::string* release_value();
|
||||
void set_allocated_value(::std::string* value);
|
||||
|
||||
// @@protoc_insertion_point(class_scope:google.protobuf.Any)
|
||||
private:
|
||||
|
||||
::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
|
||||
::google::protobuf::internal::ArenaStringPtr type_url_;
|
||||
::google::protobuf::internal::ArenaStringPtr value_;
|
||||
mutable ::google::protobuf::internal::CachedSize _cached_size_;
|
||||
::google::protobuf::internal::AnyMetadata _any_metadata_;
|
||||
friend struct ::protobuf_google_2fprotobuf_2fany_2eproto::TableStruct;
|
||||
};
|
||||
// ===================================================================
|
||||
|
||||
|
||||
// ===================================================================
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
|
||||
#endif // __GNUC__
|
||||
// Any
|
||||
|
||||
// string type_url = 1;
|
||||
inline void Any::clear_type_url() {
|
||||
type_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
inline const ::std::string& Any::type_url() const {
|
||||
// @@protoc_insertion_point(field_get:google.protobuf.Any.type_url)
|
||||
return type_url_.GetNoArena();
|
||||
}
|
||||
inline void Any::set_type_url(const ::std::string& value) {
|
||||
|
||||
type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
|
||||
// @@protoc_insertion_point(field_set:google.protobuf.Any.type_url)
|
||||
}
|
||||
#if LANG_CXX11
|
||||
inline void Any::set_type_url(::std::string&& value) {
|
||||
|
||||
type_url_.SetNoArena(
|
||||
&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
|
||||
// @@protoc_insertion_point(field_set_rvalue:google.protobuf.Any.type_url)
|
||||
}
|
||||
#endif
|
||||
inline void Any::set_type_url(const char* value) {
|
||||
GOOGLE_DCHECK(value != NULL);
|
||||
|
||||
type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
|
||||
// @@protoc_insertion_point(field_set_char:google.protobuf.Any.type_url)
|
||||
}
|
||||
inline void Any::set_type_url(const char* value, size_t size) {
|
||||
|
||||
type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
|
||||
::std::string(reinterpret_cast<const char*>(value), size));
|
||||
// @@protoc_insertion_point(field_set_pointer:google.protobuf.Any.type_url)
|
||||
}
|
||||
inline ::std::string* Any::mutable_type_url() {
|
||||
|
||||
// @@protoc_insertion_point(field_mutable:google.protobuf.Any.type_url)
|
||||
return type_url_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
inline ::std::string* Any::release_type_url() {
|
||||
// @@protoc_insertion_point(field_release:google.protobuf.Any.type_url)
|
||||
|
||||
return type_url_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
inline void Any::set_allocated_type_url(::std::string* type_url) {
|
||||
if (type_url != NULL) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
type_url_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), type_url);
|
||||
// @@protoc_insertion_point(field_set_allocated:google.protobuf.Any.type_url)
|
||||
}
|
||||
|
||||
// bytes value = 2;
|
||||
inline void Any::clear_value() {
|
||||
value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
inline const ::std::string& Any::value() const {
|
||||
// @@protoc_insertion_point(field_get:google.protobuf.Any.value)
|
||||
return value_.GetNoArena();
|
||||
}
|
||||
inline void Any::set_value(const ::std::string& value) {
|
||||
|
||||
value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
|
||||
// @@protoc_insertion_point(field_set:google.protobuf.Any.value)
|
||||
}
|
||||
#if LANG_CXX11
|
||||
inline void Any::set_value(::std::string&& value) {
|
||||
|
||||
value_.SetNoArena(
|
||||
&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
|
||||
// @@protoc_insertion_point(field_set_rvalue:google.protobuf.Any.value)
|
||||
}
|
||||
#endif
|
||||
inline void Any::set_value(const char* value) {
|
||||
GOOGLE_DCHECK(value != NULL);
|
||||
|
||||
value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
|
||||
// @@protoc_insertion_point(field_set_char:google.protobuf.Any.value)
|
||||
}
|
||||
inline void Any::set_value(const void* value, size_t size) {
|
||||
|
||||
value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
|
||||
::std::string(reinterpret_cast<const char*>(value), size));
|
||||
// @@protoc_insertion_point(field_set_pointer:google.protobuf.Any.value)
|
||||
}
|
||||
inline ::std::string* Any::mutable_value() {
|
||||
|
||||
// @@protoc_insertion_point(field_mutable:google.protobuf.Any.value)
|
||||
return value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
inline ::std::string* Any::release_value() {
|
||||
// @@protoc_insertion_point(field_release:google.protobuf.Any.value)
|
||||
|
||||
return value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
inline void Any::set_allocated_value(::std::string* value) {
|
||||
if (value != NULL) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
value_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
|
||||
// @@protoc_insertion_point(field_set_allocated:google.protobuf.Any.value)
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif // __GNUC__
|
||||
|
||||
// @@protoc_insertion_point(namespace_scope)
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
// @@protoc_insertion_point(global_scope)
|
||||
|
||||
#endif // PROTOBUF_INCLUDED_google_2fprotobuf_2fany_2eproto
|
154
Common/ProtocolBuffer/google/protobuf/any.proto
Normal file
154
Common/ProtocolBuffer/google/protobuf/any.proto
Normal file
@ -0,0 +1,154 @@
|
||||
// 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.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package google.protobuf;
|
||||
|
||||
option csharp_namespace = "Google.Protobuf.WellKnownTypes";
|
||||
option go_package = "github.com/golang/protobuf/ptypes/any";
|
||||
option java_package = "com.google.protobuf";
|
||||
option java_outer_classname = "AnyProto";
|
||||
option java_multiple_files = true;
|
||||
option objc_class_prefix = "GPB";
|
||||
|
||||
// `Any` contains an arbitrary serialized protocol buffer message along with a
|
||||
// URL that describes the type of the serialized message.
|
||||
//
|
||||
// Protobuf library provides support to pack/unpack Any values in the form
|
||||
// of utility functions or additional generated methods of the Any type.
|
||||
//
|
||||
// Example 1: Pack and unpack a message in C++.
|
||||
//
|
||||
// Foo foo = ...;
|
||||
// Any any;
|
||||
// any.PackFrom(foo);
|
||||
// ...
|
||||
// if (any.UnpackTo(&foo)) {
|
||||
// ...
|
||||
// }
|
||||
//
|
||||
// Example 2: Pack and unpack a message in Java.
|
||||
//
|
||||
// Foo foo = ...;
|
||||
// Any any = Any.pack(foo);
|
||||
// ...
|
||||
// if (any.is(Foo.class)) {
|
||||
// foo = any.unpack(Foo.class);
|
||||
// }
|
||||
//
|
||||
// Example 3: Pack and unpack a message in Python.
|
||||
//
|
||||
// foo = Foo(...)
|
||||
// any = Any()
|
||||
// any.Pack(foo)
|
||||
// ...
|
||||
// if any.Is(Foo.DESCRIPTOR):
|
||||
// any.Unpack(foo)
|
||||
// ...
|
||||
//
|
||||
// Example 4: Pack and unpack a message in Go
|
||||
//
|
||||
// foo := &pb.Foo{...}
|
||||
// any, err := ptypes.MarshalAny(foo)
|
||||
// ...
|
||||
// foo := &pb.Foo{}
|
||||
// if err := ptypes.UnmarshalAny(any, foo); err != nil {
|
||||
// ...
|
||||
// }
|
||||
//
|
||||
// The pack methods provided by protobuf library will by default use
|
||||
// 'type.googleapis.com/full.type.name' as the type URL and the unpack
|
||||
// methods only use the fully qualified type name after the last '/'
|
||||
// in the type URL, for example "foo.bar.com/x/y.z" will yield type
|
||||
// name "y.z".
|
||||
//
|
||||
//
|
||||
// JSON
|
||||
// ====
|
||||
// The JSON representation of an `Any` value uses the regular
|
||||
// representation of the deserialized, embedded message, with an
|
||||
// additional field `@type` which contains the type URL. Example:
|
||||
//
|
||||
// package google.profile;
|
||||
// message Person {
|
||||
// string first_name = 1;
|
||||
// string last_name = 2;
|
||||
// }
|
||||
//
|
||||
// {
|
||||
// "@type": "type.googleapis.com/google.profile.Person",
|
||||
// "firstName": <string>,
|
||||
// "lastName": <string>
|
||||
// }
|
||||
//
|
||||
// If the embedded message type is well-known and has a custom JSON
|
||||
// representation, that representation will be embedded adding a field
|
||||
// `value` which holds the custom JSON in addition to the `@type`
|
||||
// field. Example (for message [google.protobuf.Duration][]):
|
||||
//
|
||||
// {
|
||||
// "@type": "type.googleapis.com/google.protobuf.Duration",
|
||||
// "value": "1.212s"
|
||||
// }
|
||||
//
|
||||
message Any {
|
||||
// A URL/resource name that uniquely identifies the type of the serialized
|
||||
// protocol buffer message. The last segment of the URL's path must represent
|
||||
// the fully qualified name of the type (as in
|
||||
// `path/google.protobuf.Duration`). The name should be in a canonical form
|
||||
// (e.g., leading "." is not accepted).
|
||||
//
|
||||
// In practice, teams usually precompile into the binary all types that they
|
||||
// expect it to use in the context of Any. However, for URLs which use the
|
||||
// scheme `http`, `https`, or no scheme, one can optionally set up a type
|
||||
// server that maps type URLs to message definitions as follows:
|
||||
//
|
||||
// * If no scheme is provided, `https` is assumed.
|
||||
// * An HTTP GET on the URL must yield a [google.protobuf.Type][]
|
||||
// value in binary format, or produce an error.
|
||||
// * Applications are allowed to cache lookup results based on the
|
||||
// URL, or have them precompiled into a binary to avoid any
|
||||
// lookup. Therefore, binary compatibility needs to be preserved
|
||||
// on changes to types. (Use versioned type names to manage
|
||||
// breaking changes.)
|
||||
//
|
||||
// Note: this functionality is not currently available in the official
|
||||
// protobuf release, and it is not used for type URLs beginning with
|
||||
// type.googleapis.com.
|
||||
//
|
||||
// Schemes other than `http`, `https` (or the empty scheme) might be
|
||||
// used with implementation specific semantics.
|
||||
//
|
||||
string type_url = 1;
|
||||
|
||||
// Must be a valid serialized protocol buffer of the above specified type.
|
||||
bytes value = 2;
|
||||
}
|
89
Common/ProtocolBuffer/google/protobuf/any_test.cc
Normal file
89
Common/ProtocolBuffer/google/protobuf/any_test.cc
Normal file
@ -0,0 +1,89 @@
|
||||
// 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/any_test.pb.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace {
|
||||
|
||||
TEST(AnyTest, TestPackAndUnpack) {
|
||||
protobuf_unittest::TestAny submessage;
|
||||
submessage.set_int32_value(12345);
|
||||
protobuf_unittest::TestAny message;
|
||||
message.mutable_any_value()->PackFrom(submessage);
|
||||
|
||||
string data = message.SerializeAsString();
|
||||
|
||||
ASSERT_TRUE(message.ParseFromString(data));
|
||||
EXPECT_TRUE(message.has_any_value());
|
||||
ASSERT_TRUE(message.any_value().UnpackTo(&submessage));
|
||||
EXPECT_EQ(12345, submessage.int32_value());
|
||||
}
|
||||
|
||||
TEST(AnyTest, TestPackAndUnpackAny) {
|
||||
// We can pack a Any message inside another Any message.
|
||||
protobuf_unittest::TestAny submessage;
|
||||
submessage.set_int32_value(12345);
|
||||
google::protobuf::Any any;
|
||||
any.PackFrom(submessage);
|
||||
protobuf_unittest::TestAny message;
|
||||
message.mutable_any_value()->PackFrom(any);
|
||||
|
||||
string data = message.SerializeAsString();
|
||||
|
||||
ASSERT_TRUE(message.ParseFromString(data));
|
||||
EXPECT_TRUE(message.has_any_value());
|
||||
ASSERT_TRUE(message.any_value().UnpackTo(&any));
|
||||
ASSERT_TRUE(any.UnpackTo(&submessage));
|
||||
EXPECT_EQ(12345, submessage.int32_value());
|
||||
}
|
||||
|
||||
TEST(AnyTest, TestIs) {
|
||||
protobuf_unittest::TestAny submessage;
|
||||
submessage.set_int32_value(12345);
|
||||
google::protobuf::Any any;
|
||||
any.PackFrom(submessage);
|
||||
ASSERT_TRUE(any.ParseFromString(any.SerializeAsString()));
|
||||
EXPECT_TRUE(any.Is<protobuf_unittest::TestAny>());
|
||||
EXPECT_FALSE(any.Is<google::protobuf::Any>());
|
||||
|
||||
protobuf_unittest::TestAny message;
|
||||
message.mutable_any_value()->PackFrom(any);
|
||||
ASSERT_TRUE(message.ParseFromString(message.SerializeAsString()));
|
||||
EXPECT_FALSE(message.any_value().Is<protobuf_unittest::TestAny>());
|
||||
EXPECT_TRUE(message.any_value().Is<google::protobuf::Any>());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
41
Common/ProtocolBuffer/google/protobuf/any_test.proto
Normal file
41
Common/ProtocolBuffer/google/protobuf/any_test.proto
Normal file
@ -0,0 +1,41 @@
|
||||
// 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.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package protobuf_unittest;
|
||||
|
||||
import "google/protobuf/any.proto";
|
||||
|
||||
message TestAny {
|
||||
int32 int32_value = 1;
|
||||
google.protobuf.Any any_value = 2;
|
||||
repeated google.protobuf.Any repeated_any_value = 3;
|
||||
}
|
1589
Common/ProtocolBuffer/google/protobuf/api.pb.cc
Normal file
1589
Common/ProtocolBuffer/google/protobuf/api.pb.cc
Normal file
File diff suppressed because it is too large
Load Diff
1182
Common/ProtocolBuffer/google/protobuf/api.pb.h
Normal file
1182
Common/ProtocolBuffer/google/protobuf/api.pb.h
Normal file
File diff suppressed because it is too large
Load Diff
210
Common/ProtocolBuffer/google/protobuf/api.proto
Normal file
210
Common/ProtocolBuffer/google/protobuf/api.proto
Normal file
@ -0,0 +1,210 @@
|
||||
// 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.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package google.protobuf;
|
||||
|
||||
import "google/protobuf/source_context.proto";
|
||||
import "google/protobuf/type.proto";
|
||||
|
||||
option csharp_namespace = "Google.Protobuf.WellKnownTypes";
|
||||
option java_package = "com.google.protobuf";
|
||||
option java_outer_classname = "ApiProto";
|
||||
option java_multiple_files = true;
|
||||
option objc_class_prefix = "GPB";
|
||||
option go_package = "google.golang.org/genproto/protobuf/api;api";
|
||||
|
||||
// Api is a light-weight descriptor for an API Interface.
|
||||
//
|
||||
// Interfaces are also described as "protocol buffer services" in some contexts,
|
||||
// such as by the "service" keyword in a .proto file, but they are different
|
||||
// from API Services, which represent a concrete implementation of an interface
|
||||
// as opposed to simply a description of methods and bindings. They are also
|
||||
// sometimes simply referred to as "APIs" in other contexts, such as the name of
|
||||
// this message itself. See https://cloud.google.com/apis/design/glossary for
|
||||
// detailed terminology.
|
||||
message Api {
|
||||
|
||||
// The fully qualified name of this interface, including package name
|
||||
// followed by the interface's simple name.
|
||||
string name = 1;
|
||||
|
||||
// The methods of this interface, in unspecified order.
|
||||
repeated Method methods = 2;
|
||||
|
||||
// Any metadata attached to the interface.
|
||||
repeated Option options = 3;
|
||||
|
||||
// A version string for this interface. If specified, must have the form
|
||||
// `major-version.minor-version`, as in `1.10`. If the minor version is
|
||||
// omitted, it defaults to zero. If the entire version field is empty, the
|
||||
// major version is derived from the package name, as outlined below. If the
|
||||
// field is not empty, the version in the package name will be verified to be
|
||||
// consistent with what is provided here.
|
||||
//
|
||||
// The versioning schema uses [semantic
|
||||
// versioning](http://semver.org) where the major version number
|
||||
// indicates a breaking change and the minor version an additive,
|
||||
// non-breaking change. Both version numbers are signals to users
|
||||
// what to expect from different versions, and should be carefully
|
||||
// chosen based on the product plan.
|
||||
//
|
||||
// The major version is also reflected in the package name of the
|
||||
// interface, which must end in `v<major-version>`, as in
|
||||
// `google.feature.v1`. For major versions 0 and 1, the suffix can
|
||||
// be omitted. Zero major versions must only be used for
|
||||
// experimental, non-GA interfaces.
|
||||
//
|
||||
//
|
||||
string version = 4;
|
||||
|
||||
// Source context for the protocol buffer service represented by this
|
||||
// message.
|
||||
SourceContext source_context = 5;
|
||||
|
||||
// Included interfaces. See [Mixin][].
|
||||
repeated Mixin mixins = 6;
|
||||
|
||||
// The source syntax of the service.
|
||||
Syntax syntax = 7;
|
||||
}
|
||||
|
||||
// Method represents a method of an API interface.
|
||||
message Method {
|
||||
|
||||
// The simple name of this method.
|
||||
string name = 1;
|
||||
|
||||
// A URL of the input message type.
|
||||
string request_type_url = 2;
|
||||
|
||||
// If true, the request is streamed.
|
||||
bool request_streaming = 3;
|
||||
|
||||
// The URL of the output message type.
|
||||
string response_type_url = 4;
|
||||
|
||||
// If true, the response is streamed.
|
||||
bool response_streaming = 5;
|
||||
|
||||
// Any metadata attached to the method.
|
||||
repeated Option options = 6;
|
||||
|
||||
// The source syntax of this method.
|
||||
Syntax syntax = 7;
|
||||
}
|
||||
|
||||
// Declares an API Interface to be included in this interface. The including
|
||||
// interface must redeclare all the methods from the included interface, but
|
||||
// documentation and options are inherited as follows:
|
||||
//
|
||||
// - If after comment and whitespace stripping, the documentation
|
||||
// string of the redeclared method is empty, it will be inherited
|
||||
// from the original method.
|
||||
//
|
||||
// - Each annotation belonging to the service config (http,
|
||||
// visibility) which is not set in the redeclared method will be
|
||||
// inherited.
|
||||
//
|
||||
// - If an http annotation is inherited, the path pattern will be
|
||||
// modified as follows. Any version prefix will be replaced by the
|
||||
// version of the including interface plus the [root][] path if
|
||||
// specified.
|
||||
//
|
||||
// Example of a simple mixin:
|
||||
//
|
||||
// package google.acl.v1;
|
||||
// service AccessControl {
|
||||
// // Get the underlying ACL object.
|
||||
// rpc GetAcl(GetAclRequest) returns (Acl) {
|
||||
// option (google.api.http).get = "/v1/{resource=**}:getAcl";
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// package google.storage.v2;
|
||||
// service Storage {
|
||||
// rpc GetAcl(GetAclRequest) returns (Acl);
|
||||
//
|
||||
// // Get a data record.
|
||||
// rpc GetData(GetDataRequest) returns (Data) {
|
||||
// option (google.api.http).get = "/v2/{resource=**}";
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// Example of a mixin configuration:
|
||||
//
|
||||
// apis:
|
||||
// - name: google.storage.v2.Storage
|
||||
// mixins:
|
||||
// - name: google.acl.v1.AccessControl
|
||||
//
|
||||
// The mixin construct implies that all methods in `AccessControl` are
|
||||
// also declared with same name and request/response types in
|
||||
// `Storage`. A documentation generator or annotation processor will
|
||||
// see the effective `Storage.GetAcl` method after inherting
|
||||
// documentation and annotations as follows:
|
||||
//
|
||||
// service Storage {
|
||||
// // Get the underlying ACL object.
|
||||
// rpc GetAcl(GetAclRequest) returns (Acl) {
|
||||
// option (google.api.http).get = "/v2/{resource=**}:getAcl";
|
||||
// }
|
||||
// ...
|
||||
// }
|
||||
//
|
||||
// Note how the version in the path pattern changed from `v1` to `v2`.
|
||||
//
|
||||
// If the `root` field in the mixin is specified, it should be a
|
||||
// relative path under which inherited HTTP paths are placed. Example:
|
||||
//
|
||||
// apis:
|
||||
// - name: google.storage.v2.Storage
|
||||
// mixins:
|
||||
// - name: google.acl.v1.AccessControl
|
||||
// root: acls
|
||||
//
|
||||
// This implies the following inherited HTTP annotation:
|
||||
//
|
||||
// service Storage {
|
||||
// // Get the underlying ACL object.
|
||||
// rpc GetAcl(GetAclRequest) returns (Acl) {
|
||||
// option (google.api.http).get = "/v2/acls/{resource=**}:getAcl";
|
||||
// }
|
||||
// ...
|
||||
// }
|
||||
message Mixin {
|
||||
// The fully qualified name of the interface which is included.
|
||||
string name = 1;
|
||||
|
||||
// If non-empty specifies a path under which inherited HTTP paths
|
||||
// are rooted.
|
||||
string root = 2;
|
||||
}
|
415
Common/ProtocolBuffer/google/protobuf/arena.cc
Normal file
415
Common/ProtocolBuffer/google/protobuf/arena.cc
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
|
703
Common/ProtocolBuffer/google/protobuf/arena.h
Normal file
703
Common/ProtocolBuffer/google/protobuf/arena.h
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
Common/ProtocolBuffer/google/protobuf/arena_impl.h
Normal file
321
Common/ProtocolBuffer/google/protobuf/arena_impl.h
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__
|
50
Common/ProtocolBuffer/google/protobuf/arena_test_util.cc
Normal file
50
Common/ProtocolBuffer/google/protobuf/arena_test_util.cc
Normal file
@ -0,0 +1,50 @@
|
||||
// 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/logging.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/arena_test_util.h>
|
||||
|
||||
|
||||
#define EXPECT_EQ GOOGLE_CHECK_EQ
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
NoHeapChecker::~NoHeapChecker() {
|
||||
capture_alloc.Unhook();
|
||||
EXPECT_EQ(0, capture_alloc.alloc_count());
|
||||
EXPECT_EQ(0, capture_alloc.free_count());
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
91
Common/ProtocolBuffer/google/protobuf/arena_test_util.h
Normal file
91
Common/ProtocolBuffer/google/protobuf/arena_test_util.h
Normal file
@ -0,0 +1,91 @@
|
||||
// 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_ARENA_TEST_UTIL_H__
|
||||
#define GOOGLE_PROTOBUF_ARENA_TEST_UTIL_H__
|
||||
|
||||
#include <google/protobuf/stubs/logging.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/arena.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
template <typename T, bool use_arena>
|
||||
void TestParseCorruptedString(const T& message) {
|
||||
int success_count = 0;
|
||||
string s = message.SerializeAsString();
|
||||
const int kMaxIters = 900;
|
||||
const int stride = s.size() <= kMaxIters ? 1 : s.size() / kMaxIters;
|
||||
const int start = stride == 1 || use_arena ? 0 : (stride + 1) / 2;
|
||||
for (int i = start; i < s.size(); i += stride) {
|
||||
for (int c = 1 + (i % 17); c < 256; c += 2 * c + (i & 3)) {
|
||||
s[i] ^= c;
|
||||
google::protobuf::Arena arena;
|
||||
T* message =
|
||||
google::protobuf::Arena::CreateMessage<T>(use_arena ? &arena : nullptr);
|
||||
if (message->ParseFromString(s)) {
|
||||
++success_count;
|
||||
}
|
||||
if (!use_arena) {
|
||||
delete message;
|
||||
}
|
||||
s[i] ^= c; // Restore s to its original state.
|
||||
}
|
||||
}
|
||||
// This next line is a low bar. But getting through the test without crashing
|
||||
// due to use-after-free or other bugs is a big part of what we're checking.
|
||||
GOOGLE_CHECK_GT(success_count, 0);
|
||||
}
|
||||
|
||||
namespace internal {
|
||||
|
||||
class NoHeapChecker {
|
||||
public:
|
||||
NoHeapChecker() {
|
||||
capture_alloc.Hook();
|
||||
}
|
||||
~NoHeapChecker();
|
||||
private:
|
||||
class NewDeleteCapture {
|
||||
public:
|
||||
// TOOD(xiaofeng): Implement this for opensource protobuf.
|
||||
void Hook() {}
|
||||
void Unhook() {}
|
||||
int alloc_count() { return 0; }
|
||||
int free_count() { return 0; }
|
||||
} capture_alloc;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_ARENA_TEST_UTIL_H__
|
1436
Common/ProtocolBuffer/google/protobuf/arena_unittest.cc
Normal file
1436
Common/ProtocolBuffer/google/protobuf/arena_unittest.cc
Normal file
File diff suppressed because it is too large
Load Diff
43
Common/ProtocolBuffer/google/protobuf/arenastring.cc
Normal file
43
Common/ProtocolBuffer/google/protobuf/arenastring.cc
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
|
403
Common/ProtocolBuffer/google/protobuf/arenastring.h
Normal file
403
Common/ProtocolBuffer/google/protobuf/arenastring.h
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__
|
138
Common/ProtocolBuffer/google/protobuf/arenastring_unittest.cc
Normal file
138
Common/ProtocolBuffer/google/protobuf/arenastring_unittest.cc
Normal file
@ -0,0 +1,138 @@
|
||||
// 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.
|
||||
|
||||
// Based on mvels@'s frankenstring.
|
||||
|
||||
#include <google/protobuf/arenastring.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <google/protobuf/stubs/logging.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/io/zero_copy_stream_impl.h>
|
||||
|
||||
|
||||
namespace google {
|
||||
using google::protobuf::internal::ArenaStringPtr;
|
||||
|
||||
namespace protobuf {
|
||||
|
||||
|
||||
static string WrapString(const char* value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
// Test ArenaStringPtr with arena == NULL.
|
||||
TEST(ArenaStringPtrTest, ArenaStringPtrOnHeap) {
|
||||
ArenaStringPtr field;
|
||||
::std::string default_value = "default";
|
||||
field.UnsafeSetDefault(&default_value);
|
||||
EXPECT_EQ(string("default"), field.Get());
|
||||
field.Set(&default_value, WrapString("Test short"), NULL);
|
||||
EXPECT_EQ(string("Test short"), field.Get());
|
||||
field.Set(&default_value, WrapString("Test long long long long value"), NULL);
|
||||
EXPECT_EQ(string("Test long long long long value"), field.Get());
|
||||
field.Set(&default_value, string(""), NULL);
|
||||
field.Destroy(&default_value, NULL);
|
||||
|
||||
ArenaStringPtr field2;
|
||||
field2.UnsafeSetDefault(&default_value);
|
||||
::std::string* mut = field2.Mutable(&default_value, NULL);
|
||||
EXPECT_EQ(mut, field2.Mutable(&default_value, NULL));
|
||||
EXPECT_EQ(mut, &field2.Get());
|
||||
EXPECT_NE(&default_value, mut);
|
||||
EXPECT_EQ(string("default"), *mut);
|
||||
*mut = "Test long long long long value"; // ensure string allocates storage
|
||||
EXPECT_EQ(string("Test long long long long value"), field2.Get());
|
||||
field2.Destroy(&default_value, NULL);
|
||||
}
|
||||
|
||||
TEST(ArenaStringPtrTest, ArenaStringPtrOnArena) {
|
||||
google::protobuf::Arena arena;
|
||||
ArenaStringPtr field;
|
||||
::std::string default_value = "default";
|
||||
field.UnsafeSetDefault(&default_value);
|
||||
EXPECT_EQ(string("default"), field.Get());
|
||||
field.Set(&default_value, WrapString("Test short"), &arena);
|
||||
EXPECT_EQ(string("Test short"), field.Get());
|
||||
field.Set(&default_value, WrapString("Test long long long long value"),
|
||||
&arena);
|
||||
EXPECT_EQ(string("Test long long long long value"), field.Get());
|
||||
field.Set(&default_value, string(""), &arena);
|
||||
field.Destroy(&default_value, &arena);
|
||||
|
||||
ArenaStringPtr field2;
|
||||
field2.UnsafeSetDefault(&default_value);
|
||||
::std::string* mut = field2.Mutable(&default_value, &arena);
|
||||
EXPECT_EQ(mut, field2.Mutable(&default_value, &arena));
|
||||
EXPECT_EQ(mut, &field2.Get());
|
||||
EXPECT_NE(&default_value, mut);
|
||||
EXPECT_EQ(string("default"), *mut);
|
||||
*mut = "Test long long long long value"; // ensure string allocates storage
|
||||
EXPECT_EQ(string("Test long long long long value"), field2.Get());
|
||||
field2.Destroy(&default_value, &arena);
|
||||
}
|
||||
|
||||
TEST(ArenaStringPtrTest, ArenaStringPtrOnArenaNoSSO) {
|
||||
google::protobuf::Arena arena;
|
||||
ArenaStringPtr field;
|
||||
::std::string default_value = "default";
|
||||
field.UnsafeSetDefault(&default_value);
|
||||
EXPECT_EQ(string("default"), field.Get());
|
||||
|
||||
// Avoid triggering the SSO optimization by setting the string to something
|
||||
// larger than the internal buffer.
|
||||
field.Set(&default_value, WrapString("Test long long long long value"),
|
||||
&arena);
|
||||
EXPECT_EQ(string("Test long long long long value"), field.Get());
|
||||
field.Set(&default_value, string(""), &arena);
|
||||
field.Destroy(&default_value, &arena);
|
||||
|
||||
ArenaStringPtr field2;
|
||||
field2.UnsafeSetDefault(&default_value);
|
||||
::std::string* mut = field2.Mutable(&default_value, &arena);
|
||||
EXPECT_EQ(mut, field2.Mutable(&default_value, &arena));
|
||||
EXPECT_EQ(mut, &field2.Get());
|
||||
EXPECT_NE(&default_value, mut);
|
||||
EXPECT_EQ(string("default"), *mut);
|
||||
*mut = "Test long long long long value"; // ensure string allocates storage
|
||||
EXPECT_EQ(string("Test long long long long value"), field2.Get());
|
||||
field2.Destroy(&default_value, &arena);
|
||||
}
|
||||
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
2
Common/ProtocolBuffer/google/protobuf/bin/desktop.ini
Normal file
2
Common/ProtocolBuffer/google/protobuf/bin/desktop.ini
Normal file
@ -0,0 +1,2 @@
|
||||
[LocalizedFileNames]
|
||||
libprotobuf.dll=@libprotobuf.dll,0
|
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:6a632a75d0aa646d4acd68e765ac83277382e373d28c859a3cf8cd36d7948ba0
|
||||
size 2671104
|
@ -0,0 +1,166 @@
|
||||
// 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/compiler/annotation_test_util.h>
|
||||
|
||||
#include <memory>
|
||||
#include <google/protobuf/compiler/code_generator.h>
|
||||
#include <google/protobuf/compiler/command_line_interface.h>
|
||||
#include <google/protobuf/io/printer.h>
|
||||
#include <google/protobuf/io/zero_copy_stream.h>
|
||||
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
|
||||
#include <google/protobuf/descriptor.pb.h>
|
||||
|
||||
#include <google/protobuf/testing/file.h>
|
||||
#include <google/protobuf/testing/file.h>
|
||||
#include <google/protobuf/testing/googletest.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace annotation_test_util {
|
||||
namespace {
|
||||
|
||||
// A CodeGenerator that captures the FileDescriptor it's passed as a
|
||||
// FileDescriptorProto.
|
||||
class DescriptorCapturingGenerator : public CodeGenerator {
|
||||
public:
|
||||
// Does not own file; file must outlive the Generator.
|
||||
explicit DescriptorCapturingGenerator(FileDescriptorProto* file)
|
||||
: file_(file) {}
|
||||
|
||||
virtual bool Generate(const FileDescriptor* file, const string& parameter,
|
||||
GeneratorContext* context, string* error) const {
|
||||
file->CopyTo(file_);
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
FileDescriptorProto* file_;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
void AddFile(const string& filename, const string& data) {
|
||||
GOOGLE_CHECK_OK(File::SetContents(TestTempDir() + "/" + filename, data,
|
||||
true));
|
||||
}
|
||||
|
||||
bool RunProtoCompiler(const string& filename,
|
||||
const string& plugin_specific_args,
|
||||
CommandLineInterface* cli, FileDescriptorProto* file) {
|
||||
cli->SetInputsAreProtoPathRelative(true);
|
||||
|
||||
DescriptorCapturingGenerator capturing_generator(file);
|
||||
cli->RegisterGenerator("--capture_out", &capturing_generator, "");
|
||||
|
||||
string proto_path = "-I" + TestTempDir();
|
||||
string capture_out = "--capture_out=" + TestTempDir();
|
||||
|
||||
const char* argv[] = {"protoc", proto_path.c_str(),
|
||||
plugin_specific_args.c_str(), capture_out.c_str(),
|
||||
filename.c_str()};
|
||||
|
||||
return cli->Run(5, argv) == 0;
|
||||
}
|
||||
|
||||
bool DecodeMetadata(const string& path, GeneratedCodeInfo* info) {
|
||||
string data;
|
||||
GOOGLE_CHECK_OK(File::GetContents(path, &data, true));
|
||||
io::ArrayInputStream input(data.data(), data.size());
|
||||
return info->ParseFromZeroCopyStream(&input);
|
||||
}
|
||||
|
||||
void FindAnnotationsOnPath(
|
||||
const GeneratedCodeInfo& info, const string& source_file,
|
||||
const std::vector<int>& path,
|
||||
std::vector<const GeneratedCodeInfo::Annotation*>* annotations) {
|
||||
for (int i = 0; i < info.annotation_size(); ++i) {
|
||||
const GeneratedCodeInfo::Annotation* annotation = &info.annotation(i);
|
||||
if (annotation->source_file() != source_file ||
|
||||
annotation->path_size() != path.size()) {
|
||||
continue;
|
||||
}
|
||||
int node = 0;
|
||||
for (; node < path.size(); ++node) {
|
||||
if (annotation->path(node) != path[node]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (node == path.size()) {
|
||||
annotations->push_back(annotation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const GeneratedCodeInfo::Annotation* FindAnnotationOnPath(
|
||||
const GeneratedCodeInfo& info, const string& source_file,
|
||||
const std::vector<int>& path) {
|
||||
std::vector<const GeneratedCodeInfo::Annotation*> annotations;
|
||||
FindAnnotationsOnPath(info, source_file, path, &annotations);
|
||||
if (annotations.empty()) {
|
||||
return NULL;
|
||||
}
|
||||
return annotations[0];
|
||||
}
|
||||
|
||||
bool AtLeastOneAnnotationMatchesSubstring(
|
||||
const string& file_content,
|
||||
const std::vector<const GeneratedCodeInfo::Annotation*>& annotations,
|
||||
const string& expected_text) {
|
||||
for (std::vector<const GeneratedCodeInfo::Annotation*>::const_iterator
|
||||
i = annotations.begin(),
|
||||
e = annotations.end();
|
||||
i != e; ++i) {
|
||||
const GeneratedCodeInfo::Annotation* annotation = *i;
|
||||
uint32 begin = annotation->begin();
|
||||
uint32 end = annotation->end();
|
||||
if (end < begin || end > file_content.size()) {
|
||||
return false;
|
||||
}
|
||||
if (file_content.substr(begin, end - begin) == expected_text) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AnnotationMatchesSubstring(const string& file_content,
|
||||
const GeneratedCodeInfo::Annotation* annotation,
|
||||
const string& expected_text) {
|
||||
std::vector<const GeneratedCodeInfo::Annotation*> annotations;
|
||||
annotations.push_back(annotation);
|
||||
return AtLeastOneAnnotationMatchesSubstring(file_content, annotations,
|
||||
expected_text);
|
||||
}
|
||||
} // namespace annotation_test_util
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
@ -0,0 +1,114 @@
|
||||
// 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_COMPILER_ANNOTATION_TEST_UTIL_H__
|
||||
#define GOOGLE_PROTOBUF_COMPILER_ANNOTATION_TEST_UTIL_H__
|
||||
|
||||
#include <google/protobuf/descriptor.pb.h>
|
||||
#include <google/protobuf/testing/googletest.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
// Utilities that assist in writing tests for generator annotations.
|
||||
// See java/internal/annotation_unittest.cc for an example.
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace annotation_test_util {
|
||||
|
||||
// Struct that contains the file generated from a .proto file and its
|
||||
// GeneratedCodeInfo. For example, the Java generator will fill this struct
|
||||
// (for some 'foo.proto') with:
|
||||
// file_path = "Foo.java"
|
||||
// file_content = content of Foo.java
|
||||
// file_info = parsed content of Foo.java.pb.meta
|
||||
struct ExpectedOutput {
|
||||
string file_path;
|
||||
string file_content;
|
||||
GeneratedCodeInfo file_info;
|
||||
explicit ExpectedOutput(const string& file_path) : file_path(file_path) {}
|
||||
};
|
||||
|
||||
// Creates a file with name `filename` and content `data` in temp test
|
||||
// directory.
|
||||
void AddFile(const string& filename, const string& data);
|
||||
|
||||
// Runs proto compiler. Captures proto file structrue in FileDescriptorProto.
|
||||
// Files will be generated in TestTempDir() folder. Callers of this
|
||||
// function must read generated files themselves.
|
||||
//
|
||||
// filename: source .proto file used to generate code.
|
||||
// plugin_specific_args: command line arguments specific to current generator.
|
||||
// For Java, this value might be "--java_out=annotate_code:test_temp_dir"
|
||||
// cli: instance of command line interface to run generator. See Java's
|
||||
// annotation_unittest.cc for an example of how to initialize it.
|
||||
// file: output parameter, will be set to the descriptor of the proto file
|
||||
// specified in filename.
|
||||
bool RunProtoCompiler(const string& filename,
|
||||
const string& plugin_specific_args,
|
||||
CommandLineInterface* cli, FileDescriptorProto* file);
|
||||
|
||||
bool DecodeMetadata(const string& path, GeneratedCodeInfo* info);
|
||||
|
||||
// Finds all of the Annotations for a given source file and path.
|
||||
// See Location.path in http://google/protobuf/descriptor.proto for
|
||||
// explanation of what path vector is.
|
||||
void FindAnnotationsOnPath(
|
||||
const GeneratedCodeInfo& info, const string& source_file,
|
||||
const std::vector<int>& path,
|
||||
std::vector<const GeneratedCodeInfo::Annotation*>* annotations);
|
||||
|
||||
// Finds the Annotation for a given source file and path (or returns null if it
|
||||
// couldn't). If there are several annotations for given path, returns the first
|
||||
// one. See Location.path in
|
||||
// http://google/protobuf/descriptor.proto for explanation of what path
|
||||
// vector is.
|
||||
const GeneratedCodeInfo::Annotation* FindAnnotationOnPath(
|
||||
const GeneratedCodeInfo& info, const string& source_file,
|
||||
const std::vector<int>& path);
|
||||
|
||||
// Returns true if at least one of the provided annotations covers a given
|
||||
// substring in file_content.
|
||||
bool AtLeastOneAnnotationMatchesSubstring(
|
||||
const string& file_content,
|
||||
const std::vector<const GeneratedCodeInfo::Annotation*>& annotations,
|
||||
const string& expected_text);
|
||||
|
||||
// Returns true if the provided annotation covers a given substring in
|
||||
// file_content.
|
||||
bool AnnotationMatchesSubstring(const string& file_content,
|
||||
const GeneratedCodeInfo::Annotation* annotation,
|
||||
const string& expected_text);
|
||||
|
||||
} // namespace annotation_test_util
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_ANNOTATION_TEST_UTIL_H__
|
121
Common/ProtocolBuffer/google/protobuf/compiler/code_generator.cc
Normal file
121
Common/ProtocolBuffer/google/protobuf/compiler/code_generator.cc
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.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
|
||||
#include <google/protobuf/compiler/code_generator.h>
|
||||
|
||||
#include <google/protobuf/stubs/logging.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/compiler/plugin.pb.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
|
||||
CodeGenerator::~CodeGenerator() {}
|
||||
|
||||
bool CodeGenerator::GenerateAll(
|
||||
const std::vector<const FileDescriptor*>& files,
|
||||
const string& parameter,
|
||||
GeneratorContext* generator_context,
|
||||
string* error) const {
|
||||
// Default implemenation is just to call the per file method, and prefix any
|
||||
// error string with the file to provide context.
|
||||
bool succeeded = true;
|
||||
for (int i = 0; i < files.size(); i++) {
|
||||
const FileDescriptor* file = files[i];
|
||||
succeeded = Generate(file, parameter, generator_context, error);
|
||||
if (!succeeded && error && error->empty()) {
|
||||
*error = "Code generator returned false but provided no error "
|
||||
"description.";
|
||||
}
|
||||
if (error && !error->empty()) {
|
||||
*error = file->name() + ": " + *error;
|
||||
break;
|
||||
}
|
||||
if (!succeeded) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return succeeded;
|
||||
}
|
||||
|
||||
GeneratorContext::~GeneratorContext() {}
|
||||
|
||||
io::ZeroCopyOutputStream*
|
||||
GeneratorContext::OpenForAppend(const string& filename) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
io::ZeroCopyOutputStream* GeneratorContext::OpenForInsert(
|
||||
const string& filename, const string& insertion_point) {
|
||||
GOOGLE_LOG(FATAL) << "This GeneratorContext does not support insertion.";
|
||||
return NULL; // make compiler happy
|
||||
}
|
||||
|
||||
void GeneratorContext::ListParsedFiles(
|
||||
std::vector<const FileDescriptor*>* output) {
|
||||
GOOGLE_LOG(FATAL) << "This GeneratorContext does not support ListParsedFiles";
|
||||
}
|
||||
|
||||
void GeneratorContext::GetCompilerVersion(Version* version) const {
|
||||
version->set_major(GOOGLE_PROTOBUF_VERSION / 1000000);
|
||||
version->set_minor(GOOGLE_PROTOBUF_VERSION / 1000 % 1000);
|
||||
version->set_patch(GOOGLE_PROTOBUF_VERSION % 1000);
|
||||
version->set_suffix(GOOGLE_PROTOBUF_VERSION_SUFFIX);
|
||||
}
|
||||
|
||||
// Parses a set of comma-delimited name/value pairs.
|
||||
void ParseGeneratorParameter(const string& text,
|
||||
std::vector<std::pair<string, string> >* output) {
|
||||
std::vector<string> parts = Split(text, ",", true);
|
||||
|
||||
for (int i = 0; i < parts.size(); i++) {
|
||||
string::size_type equals_pos = parts[i].find_first_of('=');
|
||||
std::pair<string, string> value;
|
||||
if (equals_pos == string::npos) {
|
||||
value.first = parts[i];
|
||||
value.second = "";
|
||||
} else {
|
||||
value.first = parts[i].substr(0, equals_pos);
|
||||
value.second = parts[i].substr(equals_pos + 1);
|
||||
}
|
||||
output->push_back(value);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
176
Common/ProtocolBuffer/google/protobuf/compiler/code_generator.h
Normal file
176
Common/ProtocolBuffer/google/protobuf/compiler/code_generator.h
Normal file
@ -0,0 +1,176 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
//
|
||||
// Defines the abstract interface implemented by each of the language-specific
|
||||
// code generators.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_CODE_GENERATOR_H__
|
||||
#define GOOGLE_PROTOBUF_COMPILER_CODE_GENERATOR_H__
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
namespace io { class ZeroCopyOutputStream; }
|
||||
class FileDescriptor;
|
||||
|
||||
namespace compiler {
|
||||
class AccessInfoMap;
|
||||
|
||||
class Version;
|
||||
|
||||
// Defined in this file.
|
||||
class CodeGenerator;
|
||||
class GeneratorContext;
|
||||
|
||||
// The abstract interface to a class which generates code implementing a
|
||||
// particular proto file in a particular language. A number of these may
|
||||
// be registered with CommandLineInterface to support various languages.
|
||||
class LIBPROTOC_EXPORT CodeGenerator {
|
||||
public:
|
||||
inline CodeGenerator() {}
|
||||
virtual ~CodeGenerator();
|
||||
|
||||
// Generates code for the given proto file, generating one or more files in
|
||||
// the given output directory.
|
||||
//
|
||||
// A parameter to be passed to the generator can be specified on the command
|
||||
// line. This is intended to be used to pass generator specific parameters.
|
||||
// It is empty if no parameter was given. ParseGeneratorParameter (below),
|
||||
// can be used to accept multiple parameters within the single parameter
|
||||
// command line flag.
|
||||
//
|
||||
// Returns true if successful. Otherwise, sets *error to a description of
|
||||
// the problem (e.g. "invalid parameter") and returns false.
|
||||
virtual bool Generate(const FileDescriptor* file,
|
||||
const string& parameter,
|
||||
GeneratorContext* generator_context,
|
||||
string* error) const = 0;
|
||||
|
||||
// Generates code for all given proto files.
|
||||
//
|
||||
// WARNING: The canonical code generator design produces one or two output
|
||||
// files per input .proto file, and we do not wish to encourage alternate
|
||||
// designs.
|
||||
//
|
||||
// A parameter is given as passed on the command line, as in |Generate()|
|
||||
// above.
|
||||
//
|
||||
// Returns true if successful. Otherwise, sets *error to a description of
|
||||
// the problem (e.g. "invalid parameter") and returns false.
|
||||
virtual bool GenerateAll(const std::vector<const FileDescriptor*>& files,
|
||||
const string& parameter,
|
||||
GeneratorContext* generator_context,
|
||||
string* error) const;
|
||||
|
||||
// This is no longer used, but this class is part of the opensource protobuf
|
||||
// library, so it has to remain to keep vtables the same for the current
|
||||
// version of the library. When protobufs does a api breaking change, the
|
||||
// method can be removed.
|
||||
virtual bool HasGenerateAll() const { return true; }
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CodeGenerator);
|
||||
};
|
||||
|
||||
// CodeGenerators generate one or more files in a given directory. This
|
||||
// abstract interface represents the directory to which the CodeGenerator is
|
||||
// to write and other information about the context in which the Generator
|
||||
// runs.
|
||||
class LIBPROTOC_EXPORT GeneratorContext {
|
||||
public:
|
||||
inline GeneratorContext() {
|
||||
}
|
||||
virtual ~GeneratorContext();
|
||||
|
||||
// Opens the given file, truncating it if it exists, and returns a
|
||||
// ZeroCopyOutputStream that writes to the file. The caller takes ownership
|
||||
// of the returned object. This method never fails (a dummy stream will be
|
||||
// returned instead).
|
||||
//
|
||||
// The filename given should be relative to the root of the source tree.
|
||||
// E.g. the C++ generator, when generating code for "foo/bar.proto", will
|
||||
// generate the files "foo/bar.pb.h" and "foo/bar.pb.cc"; note that
|
||||
// "foo/" is included in these filenames. The filename is not allowed to
|
||||
// contain "." or ".." components.
|
||||
virtual io::ZeroCopyOutputStream* Open(const string& filename) = 0;
|
||||
|
||||
// Similar to Open() but the output will be appended to the file if exists
|
||||
virtual io::ZeroCopyOutputStream* OpenForAppend(const string& filename);
|
||||
|
||||
// Creates a ZeroCopyOutputStream which will insert code into the given file
|
||||
// at the given insertion point. See plugin.proto (plugin.pb.h) for more
|
||||
// information on insertion points. The default implementation
|
||||
// assert-fails -- it exists only for backwards-compatibility.
|
||||
//
|
||||
// WARNING: This feature is currently EXPERIMENTAL and is subject to change.
|
||||
virtual io::ZeroCopyOutputStream* OpenForInsert(
|
||||
const string& filename, const string& insertion_point);
|
||||
|
||||
// Returns a vector of FileDescriptors for all the files being compiled
|
||||
// in this run. Useful for languages, such as Go, that treat files
|
||||
// differently when compiled as a set rather than individually.
|
||||
virtual void ListParsedFiles(std::vector<const FileDescriptor*>* output);
|
||||
|
||||
// Retrieves the version number of the protocol compiler associated with
|
||||
// this GeneratorContext.
|
||||
virtual void GetCompilerVersion(Version* version) const;
|
||||
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GeneratorContext);
|
||||
};
|
||||
|
||||
// The type GeneratorContext was once called OutputDirectory. This typedef
|
||||
// provides backward compatibility.
|
||||
typedef GeneratorContext OutputDirectory;
|
||||
|
||||
// Several code generators treat the parameter argument as holding a
|
||||
// list of options separated by commas. This helper function parses
|
||||
// a set of comma-delimited name/value pairs: e.g.,
|
||||
// "foo=bar,baz,qux=corge"
|
||||
// parses to the pairs:
|
||||
// ("foo", "bar"), ("baz", ""), ("qux", "corge")
|
||||
LIBPROTOC_EXPORT void ParseGeneratorParameter(
|
||||
const string&, std::vector<std::pair<string, string> >*);
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_CODE_GENERATOR_H__
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,435 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
//
|
||||
// Implements the Protocol Compiler front-end such that it may be reused by
|
||||
// custom compilers written to support other languages.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_COMMAND_LINE_INTERFACE_H__
|
||||
#define GOOGLE_PROTOBUF_COMPILER_COMMAND_LINE_INTERFACE_H__
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/hash.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <utility>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
class Descriptor; // descriptor.h
|
||||
class DescriptorPool; // descriptor.h
|
||||
class FileDescriptor; // descriptor.h
|
||||
class FileDescriptorSet; // descriptor.h
|
||||
class FileDescriptorProto; // descriptor.pb.h
|
||||
template<typename T> class RepeatedPtrField; // repeated_field.h
|
||||
class SimpleDescriptorDatabase; // descriptor_database.h
|
||||
|
||||
namespace compiler {
|
||||
|
||||
class CodeGenerator; // code_generator.h
|
||||
class GeneratorContext; // code_generator.h
|
||||
class DiskSourceTree; // importer.h
|
||||
|
||||
// This class implements the command-line interface to the protocol compiler.
|
||||
// It is designed to make it very easy to create a custom protocol compiler
|
||||
// supporting the languages of your choice. For example, if you wanted to
|
||||
// create a custom protocol compiler binary which includes both the regular
|
||||
// C++ support plus support for your own custom output "Foo", you would
|
||||
// write a class "FooGenerator" which implements the CodeGenerator interface,
|
||||
// then write a main() procedure like this:
|
||||
//
|
||||
// int main(int argc, char* argv[]) {
|
||||
// google::protobuf::compiler::CommandLineInterface cli;
|
||||
//
|
||||
// // Support generation of C++ source and headers.
|
||||
// google::protobuf::compiler::cpp::CppGenerator cpp_generator;
|
||||
// cli.RegisterGenerator("--cpp_out", &cpp_generator,
|
||||
// "Generate C++ source and header.");
|
||||
//
|
||||
// // Support generation of Foo code.
|
||||
// FooGenerator foo_generator;
|
||||
// cli.RegisterGenerator("--foo_out", &foo_generator,
|
||||
// "Generate Foo file.");
|
||||
//
|
||||
// return cli.Run(argc, argv);
|
||||
// }
|
||||
//
|
||||
// The compiler is invoked with syntax like:
|
||||
// protoc --cpp_out=outdir --foo_out=outdir --proto_path=src src/foo.proto
|
||||
//
|
||||
// The .proto file to compile can be specified on the command line using either
|
||||
// its physical file path, or a virtual path relative to a diretory specified
|
||||
// in --proto_path. For example, for src/foo.proto, the following two protoc
|
||||
// invocations work the same way:
|
||||
// 1. protoc --proto_path=src src/foo.proto (physical file path)
|
||||
// 2. protoc --proto_path=src foo.proto (virtual path relative to src)
|
||||
//
|
||||
// If a file path can be interpreted both as a physical file path and as a
|
||||
// relative virtual path, the physical file path takes precendence.
|
||||
//
|
||||
// For a full description of the command-line syntax, invoke it with --help.
|
||||
class LIBPROTOC_EXPORT CommandLineInterface {
|
||||
public:
|
||||
static const char* const kPathSeparator;
|
||||
|
||||
CommandLineInterface();
|
||||
~CommandLineInterface();
|
||||
|
||||
// Register a code generator for a language.
|
||||
//
|
||||
// Parameters:
|
||||
// * flag_name: The command-line flag used to specify an output file of
|
||||
// this type. The name must start with a '-'. If the name is longer
|
||||
// than one letter, it must start with two '-'s.
|
||||
// * generator: The CodeGenerator which will be called to generate files
|
||||
// of this type.
|
||||
// * help_text: Text describing this flag in the --help output.
|
||||
//
|
||||
// Some generators accept extra parameters. You can specify this parameter
|
||||
// on the command-line by placing it before the output directory, separated
|
||||
// by a colon:
|
||||
// protoc --foo_out=enable_bar:outdir
|
||||
// The text before the colon is passed to CodeGenerator::Generate() as the
|
||||
// "parameter".
|
||||
void RegisterGenerator(const string& flag_name,
|
||||
CodeGenerator* generator,
|
||||
const string& help_text);
|
||||
|
||||
// Register a code generator for a language.
|
||||
// Besides flag_name you can specify another option_flag_name that could be
|
||||
// used to pass extra parameters to the registered code generator.
|
||||
// Suppose you have registered a generator by calling:
|
||||
// command_line_interface.RegisterGenerator("--foo_out", "--foo_opt", ...)
|
||||
// Then you could invoke the compiler with a command like:
|
||||
// protoc --foo_out=enable_bar:outdir --foo_opt=enable_baz
|
||||
// This will pass "enable_bar,enable_baz" as the parameter to the generator.
|
||||
void RegisterGenerator(const string& flag_name,
|
||||
const string& option_flag_name,
|
||||
CodeGenerator* generator,
|
||||
const string& help_text);
|
||||
|
||||
// Enables "plugins". In this mode, if a command-line flag ends with "_out"
|
||||
// but does not match any registered generator, the compiler will attempt to
|
||||
// find a "plugin" to implement the generator. Plugins are just executables.
|
||||
// They should live somewhere in the PATH.
|
||||
//
|
||||
// The compiler determines the executable name to search for by concatenating
|
||||
// exe_name_prefix with the unrecognized flag name, removing "_out". So, for
|
||||
// example, if exe_name_prefix is "protoc-" and you pass the flag --foo_out,
|
||||
// the compiler will try to run the program "protoc-foo".
|
||||
//
|
||||
// The plugin program should implement the following usage:
|
||||
// plugin [--out=OUTDIR] [--parameter=PARAMETER] PROTO_FILES < DESCRIPTORS
|
||||
// --out indicates the output directory (as passed to the --foo_out
|
||||
// parameter); if omitted, the current directory should be used. --parameter
|
||||
// gives the generator parameter, if any was provided (see below). The
|
||||
// PROTO_FILES list the .proto files which were given on the compiler
|
||||
// command-line; these are the files for which the plugin is expected to
|
||||
// generate output code. Finally, DESCRIPTORS is an encoded FileDescriptorSet
|
||||
// (as defined in descriptor.proto). This is piped to the plugin's stdin.
|
||||
// The set will include descriptors for all the files listed in PROTO_FILES as
|
||||
// well as all files that they import. The plugin MUST NOT attempt to read
|
||||
// the PROTO_FILES directly -- it must use the FileDescriptorSet.
|
||||
//
|
||||
// The plugin should generate whatever files are necessary, as code generators
|
||||
// normally do. It should write the names of all files it generates to
|
||||
// stdout. The names should be relative to the output directory, NOT absolute
|
||||
// names or relative to the current directory. If any errors occur, error
|
||||
// messages should be written to stderr. If an error is fatal, the plugin
|
||||
// should exit with a non-zero exit code.
|
||||
//
|
||||
// Plugins can have generator parameters similar to normal built-in
|
||||
// generators. Extra generator parameters can be passed in via a matching
|
||||
// "_opt" parameter. For example:
|
||||
// protoc --plug_out=enable_bar:outdir --plug_opt=enable_baz
|
||||
// This will pass "enable_bar,enable_baz" as the parameter to the plugin.
|
||||
//
|
||||
void AllowPlugins(const string& exe_name_prefix);
|
||||
|
||||
// Run the Protocol Compiler with the given command-line parameters.
|
||||
// Returns the error code which should be returned by main().
|
||||
//
|
||||
// It may not be safe to call Run() in a multi-threaded environment because
|
||||
// it calls strerror(). I'm not sure why you'd want to do this anyway.
|
||||
int Run(int argc, const char* const argv[]);
|
||||
|
||||
// DEPRECATED. Calling this method has no effect. Protocol compiler now
|
||||
// always try to find the .proto file relative to the current directory
|
||||
// first and if the file is not found, it will then treat the input path
|
||||
// as a virutal path.
|
||||
void SetInputsAreProtoPathRelative(bool /* enable */) {}
|
||||
|
||||
// Provides some text which will be printed when the --version flag is
|
||||
// used. The version of libprotoc will also be printed on the next line
|
||||
// after this text.
|
||||
void SetVersionInfo(const string& text) {
|
||||
version_info_ = text;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
// -----------------------------------------------------------------
|
||||
|
||||
class ErrorPrinter;
|
||||
class GeneratorContextImpl;
|
||||
class MemoryOutputStream;
|
||||
typedef hash_map<string, GeneratorContextImpl*> GeneratorContextMap;
|
||||
|
||||
// Clear state from previous Run().
|
||||
void Clear();
|
||||
|
||||
// Remaps each file in input_files_ so that it is relative to one of the
|
||||
// directories in proto_path_. Returns false if an error occurred. This
|
||||
// is only used if inputs_are_proto_path_relative_ is false.
|
||||
bool MakeInputsBeProtoPathRelative(
|
||||
DiskSourceTree* source_tree);
|
||||
|
||||
// Return status for ParseArguments() and InterpretArgument().
|
||||
enum ParseArgumentStatus {
|
||||
PARSE_ARGUMENT_DONE_AND_CONTINUE,
|
||||
PARSE_ARGUMENT_DONE_AND_EXIT,
|
||||
PARSE_ARGUMENT_FAIL
|
||||
};
|
||||
|
||||
// Parse all command-line arguments.
|
||||
ParseArgumentStatus ParseArguments(int argc, const char* const argv[]);
|
||||
|
||||
// Read an argument file and append the file's content to the list of
|
||||
// arguments. Return false if the file cannot be read.
|
||||
bool ExpandArgumentFile(const string& file, std::vector<string>* arguments);
|
||||
|
||||
// Parses a command-line argument into a name/value pair. Returns
|
||||
// true if the next argument in the argv should be used as the value,
|
||||
// false otherwise.
|
||||
//
|
||||
// Examples:
|
||||
// "-Isrc/protos" ->
|
||||
// name = "-I", value = "src/protos"
|
||||
// "--cpp_out=src/foo.pb2.cc" ->
|
||||
// name = "--cpp_out", value = "src/foo.pb2.cc"
|
||||
// "foo.proto" ->
|
||||
// name = "", value = "foo.proto"
|
||||
bool ParseArgument(const char* arg, string* name, string* value);
|
||||
|
||||
// Interprets arguments parsed with ParseArgument.
|
||||
ParseArgumentStatus InterpretArgument(const string& name,
|
||||
const string& value);
|
||||
|
||||
// Print the --help text to stderr.
|
||||
void PrintHelpText();
|
||||
|
||||
// Loads proto_path_ into the provided source_tree.
|
||||
bool InitializeDiskSourceTree(DiskSourceTree* source_tree);
|
||||
|
||||
// Loads descriptor_set_in into the provided database
|
||||
bool PopulateSimpleDescriptorDatabase(SimpleDescriptorDatabase* database);
|
||||
|
||||
// Parses input_files_ into parsed_files
|
||||
bool ParseInputFiles(DescriptorPool* descriptor_pool,
|
||||
std::vector<const FileDescriptor*>* parsed_files);
|
||||
|
||||
// Generate the given output file from the given input.
|
||||
struct OutputDirective; // see below
|
||||
bool GenerateOutput(const std::vector<const FileDescriptor*>& parsed_files,
|
||||
const OutputDirective& output_directive,
|
||||
GeneratorContext* generator_context);
|
||||
bool GeneratePluginOutput(
|
||||
const std::vector<const FileDescriptor*>& parsed_files,
|
||||
const string& plugin_name, const string& parameter,
|
||||
GeneratorContext* generator_context, string* error);
|
||||
|
||||
// Implements --encode and --decode.
|
||||
bool EncodeOrDecode(const DescriptorPool* pool);
|
||||
|
||||
// Implements the --descriptor_set_out option.
|
||||
bool WriteDescriptorSet(
|
||||
const std::vector<const FileDescriptor*>& parsed_files);
|
||||
|
||||
// Implements the --dependency_out option
|
||||
bool GenerateDependencyManifestFile(
|
||||
const std::vector<const FileDescriptor*>& parsed_files,
|
||||
const GeneratorContextMap& output_directories,
|
||||
DiskSourceTree* source_tree);
|
||||
|
||||
// Get all transitive dependencies of the given file (including the file
|
||||
// itself), adding them to the given list of FileDescriptorProtos. The
|
||||
// protos will be ordered such that every file is listed before any file that
|
||||
// depends on it, so that you can call DescriptorPool::BuildFile() on them
|
||||
// in order. Any files in *already_seen will not be added, and each file
|
||||
// added will be inserted into *already_seen. If include_source_code_info is
|
||||
// true then include the source code information in the FileDescriptorProtos.
|
||||
// If include_json_name is true, populate the json_name field of
|
||||
// FieldDescriptorProto for all fields.
|
||||
static void GetTransitiveDependencies(
|
||||
const FileDescriptor* file,
|
||||
bool include_json_name,
|
||||
bool include_source_code_info,
|
||||
std::set<const FileDescriptor*>* already_seen,
|
||||
RepeatedPtrField<FileDescriptorProto>* output);
|
||||
|
||||
// Implements the --print_free_field_numbers. This function prints free field
|
||||
// numbers into stdout for the message and it's nested message types in
|
||||
// post-order, i.e. nested types first. Printed range are left-right
|
||||
// inclusive, i.e. [a, b].
|
||||
//
|
||||
// Groups:
|
||||
// For historical reasons, groups are considered to share the same
|
||||
// field number space with the parent message, thus it will not print free
|
||||
// field numbers for groups. The field numbers used in the groups are
|
||||
// excluded in the free field numbers of the parent message.
|
||||
//
|
||||
// Extension Ranges:
|
||||
// Extension ranges are considered ocuppied field numbers and they will not be
|
||||
// listed as free numbers in the output.
|
||||
void PrintFreeFieldNumbers(const Descriptor* descriptor);
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
|
||||
// The name of the executable as invoked (i.e. argv[0]).
|
||||
string executable_name_;
|
||||
|
||||
// Version info set with SetVersionInfo().
|
||||
string version_info_;
|
||||
|
||||
// Registered generators.
|
||||
struct GeneratorInfo {
|
||||
string flag_name;
|
||||
string option_flag_name;
|
||||
CodeGenerator* generator;
|
||||
string help_text;
|
||||
};
|
||||
typedef std::map<string, GeneratorInfo> GeneratorMap;
|
||||
GeneratorMap generators_by_flag_name_;
|
||||
GeneratorMap generators_by_option_name_;
|
||||
// A map from generator names to the parameters specified using the option
|
||||
// flag. For example, if the user invokes the compiler with:
|
||||
// protoc --foo_out=outputdir --foo_opt=enable_bar ...
|
||||
// Then there will be an entry ("--foo_out", "enable_bar") in this map.
|
||||
std::map<string, string> generator_parameters_;
|
||||
// Similar to generator_parameters_, but stores the parameters for plugins.
|
||||
std::map<string, string> plugin_parameters_;
|
||||
|
||||
// See AllowPlugins(). If this is empty, plugins aren't allowed.
|
||||
string plugin_prefix_;
|
||||
|
||||
// Maps specific plugin names to files. When executing a plugin, this map
|
||||
// is searched first to find the plugin executable. If not found here, the
|
||||
// PATH (or other OS-specific search strategy) is searched.
|
||||
std::map<string, string> plugins_;
|
||||
|
||||
// Stuff parsed from command line.
|
||||
enum Mode {
|
||||
MODE_COMPILE, // Normal mode: parse .proto files and compile them.
|
||||
MODE_ENCODE, // --encode: read text from stdin, write binary to stdout.
|
||||
MODE_DECODE, // --decode: read binary from stdin, write text to stdout.
|
||||
MODE_PRINT, // Print mode: print info of the given .proto files and exit.
|
||||
};
|
||||
|
||||
Mode mode_;
|
||||
|
||||
enum PrintMode {
|
||||
PRINT_NONE, // Not in MODE_PRINT
|
||||
PRINT_FREE_FIELDS, // --print_free_fields
|
||||
};
|
||||
|
||||
PrintMode print_mode_;
|
||||
|
||||
enum ErrorFormat {
|
||||
ERROR_FORMAT_GCC, // GCC error output format (default).
|
||||
ERROR_FORMAT_MSVS // Visual Studio output (--error_format=msvs).
|
||||
};
|
||||
|
||||
ErrorFormat error_format_;
|
||||
|
||||
std::vector<std::pair<string, string> >
|
||||
proto_path_; // Search path for proto files.
|
||||
std::vector<string> input_files_; // Names of the input proto files.
|
||||
|
||||
// Names of proto files which are allowed to be imported. Used by build
|
||||
// systems to enforce depend-on-what-you-import.
|
||||
std::set<string> direct_dependencies_;
|
||||
bool direct_dependencies_explicitly_set_;
|
||||
|
||||
// If there's a violation of depend-on-what-you-import, this string will be
|
||||
// presented to the user. "%s" will be replaced with the violating import.
|
||||
string direct_dependencies_violation_msg_;
|
||||
|
||||
// output_directives_ lists all the files we are supposed to output and what
|
||||
// generator to use for each.
|
||||
struct OutputDirective {
|
||||
string name; // E.g. "--foo_out"
|
||||
CodeGenerator* generator; // NULL for plugins
|
||||
string parameter;
|
||||
string output_location;
|
||||
};
|
||||
std::vector<OutputDirective> output_directives_;
|
||||
|
||||
// When using --encode or --decode, this names the type we are encoding or
|
||||
// decoding. (Empty string indicates --decode_raw.)
|
||||
string codec_type_;
|
||||
|
||||
// If --descriptor_set_in was given, these are filenames containing
|
||||
// parsed FileDescriptorSets to be used for loading protos. Otherwise, empty.
|
||||
std::vector<string> descriptor_set_in_names_;
|
||||
|
||||
// If --descriptor_set_out was given, this is the filename to which the
|
||||
// FileDescriptorSet should be written. Otherwise, empty.
|
||||
string descriptor_set_out_name_;
|
||||
|
||||
// If --dependency_out was given, this is the path to the file where the
|
||||
// dependency file will be written. Otherwise, empty.
|
||||
string dependency_out_name_;
|
||||
|
||||
// True if --include_imports was given, meaning that we should
|
||||
// write all transitive dependencies to the DescriptorSet. Otherwise, only
|
||||
// the .proto files listed on the command-line are added.
|
||||
bool imports_in_descriptor_set_;
|
||||
|
||||
// True if --include_source_info was given, meaning that we should not strip
|
||||
// SourceCodeInfo from the DescriptorSet.
|
||||
bool source_info_in_descriptor_set_;
|
||||
|
||||
// Was the --disallow_services flag used?
|
||||
bool disallow_services_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CommandLineInterface);
|
||||
};
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_COMMAND_LINE_INTERFACE_H__
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,172 @@
|
||||
// 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 test insures that google/protobuf/descriptor.pb.{h,cc} match exactly
|
||||
// what would be generated by the protocol compiler. These files are not
|
||||
// generated automatically at build time because they are compiled into the
|
||||
// protocol compiler itself. So, if they were auto-generated, you'd have a
|
||||
// chicken-and-egg problem.
|
||||
//
|
||||
// If this test fails, run the script
|
||||
// "generate_descriptor_proto.sh" and add
|
||||
// descriptor.pb.{h,cc} to your changelist.
|
||||
|
||||
#include <map>
|
||||
|
||||
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_generator.h>
|
||||
#include <google/protobuf/compiler/importer.h>
|
||||
#include <google/protobuf/io/zero_copy_stream_impl.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/stubs/substitute.h>
|
||||
#include <google/protobuf/stubs/map_util.h>
|
||||
#include <google/protobuf/stubs/stl_util.h>
|
||||
|
||||
#include <google/protobuf/testing/file.h>
|
||||
#include <google/protobuf/testing/file.h>
|
||||
#include <google/protobuf/testing/googletest.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
|
||||
namespace {
|
||||
|
||||
class MockErrorCollector : public MultiFileErrorCollector {
|
||||
public:
|
||||
MockErrorCollector() {}
|
||||
~MockErrorCollector() {}
|
||||
|
||||
string text_;
|
||||
|
||||
// implements ErrorCollector ---------------------------------------
|
||||
void AddError(const string& filename, int line, int column,
|
||||
const string& message) {
|
||||
strings::SubstituteAndAppend(&text_, "$0:$1:$2: $3\n",
|
||||
filename, line, column, message);
|
||||
}
|
||||
};
|
||||
|
||||
class MockGeneratorContext : public GeneratorContext {
|
||||
public:
|
||||
MockGeneratorContext() {}
|
||||
~MockGeneratorContext() {
|
||||
STLDeleteValues(&files_);
|
||||
}
|
||||
|
||||
void ExpectFileMatches(const string& virtual_filename,
|
||||
const string& physical_filename) {
|
||||
string* expected_contents = FindPtrOrNull(files_, virtual_filename);
|
||||
ASSERT_TRUE(expected_contents != NULL)
|
||||
<< "Generator failed to generate file: " << virtual_filename;
|
||||
|
||||
string actual_contents;
|
||||
GOOGLE_CHECK_OK(
|
||||
File::GetContents(TestSourceDir() + "/" + physical_filename,
|
||||
&actual_contents, true));
|
||||
EXPECT_TRUE(actual_contents == *expected_contents)
|
||||
<< physical_filename
|
||||
<< " needs to be regenerated. Please run "
|
||||
"generate_descriptor_proto.sh. "
|
||||
"Then add this file to your CL.";
|
||||
}
|
||||
|
||||
// implements GeneratorContext --------------------------------------
|
||||
|
||||
virtual io::ZeroCopyOutputStream* Open(const string& filename) {
|
||||
string** map_slot = &files_[filename];
|
||||
delete *map_slot;
|
||||
*map_slot = new string;
|
||||
|
||||
return new io::StringOutputStream(*map_slot);
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<string, string*> files_;
|
||||
};
|
||||
|
||||
const char kDescriptorParameter[] = "dllexport_decl=LIBPROTOBUF_EXPORT";
|
||||
const char kPluginParameter[] = "dllexport_decl=LIBPROTOC_EXPORT";
|
||||
const char kNormalParameter[] = "";
|
||||
|
||||
const char* test_protos[][2] = {
|
||||
{"google/protobuf/descriptor", kDescriptorParameter},
|
||||
{"google/protobuf/compiler/plugin", kPluginParameter},
|
||||
};
|
||||
|
||||
TEST(BootstrapTest, GeneratedFilesMatch) {
|
||||
// We need a mapping from the actual file to virtual and actual path
|
||||
// of the data to compare to.
|
||||
std::map<string, string> vpath_map;
|
||||
std::map<string, string> rpath_map;
|
||||
rpath_map["third_party/protobuf/src/google/protobuf/test_messages_proto2"] =
|
||||
"net/proto2/z_generated_example/test_messages_proto2";
|
||||
rpath_map["third_party/protobuf/src/google/protobuf/test_messages_proto3"] =
|
||||
"net/proto2/z_generated_example/test_messages_proto3";
|
||||
rpath_map["google/protobuf/proto2_weak"] =
|
||||
"net/proto2/z_generated_example/proto2_weak";
|
||||
|
||||
DiskSourceTree source_tree;
|
||||
source_tree.MapPath("", TestSourceDir());
|
||||
|
||||
for (auto file_parameter : test_protos) {
|
||||
MockErrorCollector error_collector;
|
||||
Importer importer(&source_tree, &error_collector);
|
||||
const FileDescriptor* file =
|
||||
importer.Import(file_parameter[0] + string(".proto"));
|
||||
ASSERT_TRUE(file != nullptr)
|
||||
<< "Can't import file " << file_parameter[0] + string(".proto") << "\n";
|
||||
EXPECT_EQ("", error_collector.text_);
|
||||
CppGenerator generator;
|
||||
MockGeneratorContext context;
|
||||
string error;
|
||||
ASSERT_TRUE(generator.Generate(file, file_parameter[1], &context, &error));
|
||||
|
||||
string vpath =
|
||||
FindWithDefault(vpath_map, file_parameter[0], file_parameter[0]);
|
||||
string rpath =
|
||||
FindWithDefault(rpath_map, file_parameter[0], file_parameter[0]);
|
||||
context.ExpectFileMatches(vpath + ".pb.cc", rpath + ".pb.cc");
|
||||
context.ExpectFileMatches(vpath + ".pb.h", rpath + ".pb.h");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
} // namespace cpp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
327
Common/ProtocolBuffer/google/protobuf/compiler/cpp/cpp_enum.cc
Normal file
327
Common/ProtocolBuffer/google/protobuf/compiler/cpp/cpp_enum.cc
Normal file
@ -0,0 +1,327 @@
|
||||
// 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 <map>
|
||||
|
||||
#include <google/protobuf/compiler/cpp/cpp_enum.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
|
||||
#include <google/protobuf/io/printer.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
|
||||
namespace {
|
||||
// The GOOGLE_ARRAYSIZE constant is the max enum value plus 1. If the max enum value
|
||||
// is ::google::protobuf::kint32max, GOOGLE_ARRAYSIZE will overflow. In such cases we should omit the
|
||||
// generation of the GOOGLE_ARRAYSIZE constant.
|
||||
bool ShouldGenerateArraySize(const EnumDescriptor* descriptor) {
|
||||
int32 max_value = descriptor->value(0)->number();
|
||||
for (int i = 0; i < descriptor->value_count(); i++) {
|
||||
if (descriptor->value(i)->number() > max_value) {
|
||||
max_value = descriptor->value(i)->number();
|
||||
}
|
||||
}
|
||||
return max_value != ::google::protobuf::kint32max;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor,
|
||||
const Options& options)
|
||||
: descriptor_(descriptor),
|
||||
classname_(ClassName(descriptor, false)),
|
||||
options_(options),
|
||||
generate_array_size_(ShouldGenerateArraySize(descriptor)) {
|
||||
}
|
||||
|
||||
EnumGenerator::~EnumGenerator() {}
|
||||
|
||||
void EnumGenerator::FillForwardDeclaration(
|
||||
std::map<string, const EnumDescriptor*>* enum_names) {
|
||||
if (!options_.proto_h) {
|
||||
return;
|
||||
}
|
||||
(*enum_names)[classname_] = descriptor_;
|
||||
}
|
||||
|
||||
void EnumGenerator::GenerateDefinition(io::Printer* printer) {
|
||||
std::map<string, string> vars;
|
||||
vars["classname"] = classname_;
|
||||
vars["short_name"] = descriptor_->name();
|
||||
vars["enumbase"] = options_.proto_h ? " : int" : "";
|
||||
// These variables are placeholders to pick out the beginning and ends of
|
||||
// identifiers for annotations (when doing so with existing variables would
|
||||
// be ambiguous or impossible). They should never be set to anything but the
|
||||
// empty string.
|
||||
vars["{"] = "";
|
||||
vars["}"] = "";
|
||||
|
||||
printer->Print(vars, "enum $classname$$enumbase$ {\n");
|
||||
printer->Annotate("classname", descriptor_);
|
||||
printer->Indent();
|
||||
|
||||
const EnumValueDescriptor* min_value = descriptor_->value(0);
|
||||
const EnumValueDescriptor* max_value = descriptor_->value(0);
|
||||
|
||||
for (int i = 0; i < descriptor_->value_count(); i++) {
|
||||
vars["name"] = EnumValueName(descriptor_->value(i));
|
||||
// In C++, an value of -2147483648 gets interpreted as the negative of
|
||||
// 2147483648, and since 2147483648 can't fit in an integer, this produces a
|
||||
// compiler warning. This works around that issue.
|
||||
vars["number"] = Int32ToString(descriptor_->value(i)->number());
|
||||
vars["prefix"] = (descriptor_->containing_type() == NULL) ?
|
||||
"" : classname_ + "_";
|
||||
vars["deprecation"] = descriptor_->value(i)->options().deprecated() ?
|
||||
" PROTOBUF_DEPRECATED" : "";
|
||||
|
||||
if (i > 0) printer->Print(",\n");
|
||||
printer->Print(vars, "${$$prefix$$name$$}$$deprecation$ = $number$");
|
||||
printer->Annotate("{", "}", descriptor_->value(i));
|
||||
|
||||
if (descriptor_->value(i)->number() < min_value->number()) {
|
||||
min_value = descriptor_->value(i);
|
||||
}
|
||||
if (descriptor_->value(i)->number() > max_value->number()) {
|
||||
max_value = descriptor_->value(i);
|
||||
}
|
||||
}
|
||||
|
||||
if (HasPreservingUnknownEnumSemantics(descriptor_->file())) {
|
||||
// For new enum semantics: generate min and max sentinel values equal to
|
||||
// INT32_MIN and INT32_MAX
|
||||
if (descriptor_->value_count() > 0) printer->Print(",\n");
|
||||
printer->Print(vars,
|
||||
"$classname$_$prefix$INT_MIN_SENTINEL_DO_NOT_USE_ = ::google::protobuf::kint32min,\n"
|
||||
"$classname$_$prefix$INT_MAX_SENTINEL_DO_NOT_USE_ = ::google::protobuf::kint32max");
|
||||
}
|
||||
|
||||
printer->Outdent();
|
||||
printer->Print("\n};\n");
|
||||
|
||||
vars["min_name"] = EnumValueName(min_value);
|
||||
vars["max_name"] = EnumValueName(max_value);
|
||||
|
||||
if (options_.dllexport_decl.empty()) {
|
||||
vars["dllexport"] = "";
|
||||
} else {
|
||||
vars["dllexport"] = options_.dllexport_decl + " ";
|
||||
}
|
||||
|
||||
printer->Print(vars,
|
||||
"$dllexport$bool $classname$_IsValid(int value);\n"
|
||||
"const $classname$ ${$$prefix$$short_name$_MIN$}$ = "
|
||||
"$prefix$$min_name$;\n");
|
||||
printer->Annotate("{", "}", descriptor_);
|
||||
printer->Print(vars,
|
||||
"const $classname$ ${$$prefix$$short_name$_MAX$}$ = "
|
||||
"$prefix$$max_name$;\n");
|
||||
printer->Annotate("{", "}", descriptor_);
|
||||
|
||||
if (generate_array_size_) {
|
||||
printer->Print(vars,
|
||||
"const int ${$$prefix$$short_name$_ARRAYSIZE$}$ = "
|
||||
"$prefix$$short_name$_MAX + 1;\n\n");
|
||||
printer->Annotate("{", "}", descriptor_);
|
||||
}
|
||||
|
||||
if (HasDescriptorMethods(descriptor_->file(), options_)) {
|
||||
printer->Print(vars,
|
||||
"$dllexport$const ::google::protobuf::EnumDescriptor* $classname$_descriptor();\n");
|
||||
// The _Name and _Parse methods
|
||||
printer->Print(
|
||||
vars,
|
||||
"inline const ::std::string& $classname$_Name($classname$ value) {\n"
|
||||
" return ::google::protobuf::internal::NameOfEnum(\n"
|
||||
" $classname$_descriptor(), value);\n"
|
||||
"}\n");
|
||||
printer->Print(vars,
|
||||
"inline bool $classname$_Parse(\n"
|
||||
" const ::std::string& name, $classname$* value) {\n"
|
||||
" return ::google::protobuf::internal::ParseNamedEnum<$classname$>(\n"
|
||||
" $classname$_descriptor(), name, value);\n"
|
||||
"}\n");
|
||||
}
|
||||
}
|
||||
|
||||
void EnumGenerator::
|
||||
GenerateGetEnumDescriptorSpecializations(io::Printer* printer) {
|
||||
printer->Print(
|
||||
"template <> struct is_proto_enum< $classname$> : ::std::true_type "
|
||||
"{};\n",
|
||||
"classname", ClassName(descriptor_, true));
|
||||
if (HasDescriptorMethods(descriptor_->file(), options_)) {
|
||||
printer->Print(
|
||||
"template <>\n"
|
||||
"inline const EnumDescriptor* GetEnumDescriptor< $classname$>() {\n"
|
||||
" return $classname$_descriptor();\n"
|
||||
"}\n",
|
||||
"classname", ClassName(descriptor_, true));
|
||||
}
|
||||
}
|
||||
|
||||
void EnumGenerator::GenerateSymbolImports(io::Printer* printer) {
|
||||
std::map<string, string> vars;
|
||||
vars["nested_name"] = descriptor_->name();
|
||||
vars["classname"] = classname_;
|
||||
vars["constexpr"] = options_.proto_h ? "constexpr " : "";
|
||||
vars["{"] = "";
|
||||
vars["}"] = "";
|
||||
printer->Print(vars, "typedef $classname$ $nested_name$;\n");
|
||||
|
||||
for (int j = 0; j < descriptor_->value_count(); j++) {
|
||||
vars["tag"] = EnumValueName(descriptor_->value(j));
|
||||
vars["deprecated_attr"] = descriptor_->value(j)->options().deprecated() ?
|
||||
"GOOGLE_PROTOBUF_DEPRECATED_ATTR " : "";
|
||||
printer->Print(vars,
|
||||
"$deprecated_attr$static $constexpr$const $nested_name$ ${$$tag$$}$ =\n"
|
||||
" $classname$_$tag$;\n");
|
||||
printer->Annotate("{", "}", descriptor_->value(j));
|
||||
}
|
||||
|
||||
printer->Print(vars,
|
||||
"static inline bool $nested_name$_IsValid(int value) {\n"
|
||||
" return $classname$_IsValid(value);\n"
|
||||
"}\n"
|
||||
"static const $nested_name$ ${$$nested_name$_MIN$}$ =\n"
|
||||
" $classname$_$nested_name$_MIN;\n");
|
||||
printer->Annotate("{", "}", descriptor_);
|
||||
printer->Print(vars,
|
||||
"static const $nested_name$ ${$$nested_name$_MAX$}$ =\n"
|
||||
" $classname$_$nested_name$_MAX;\n");
|
||||
printer->Annotate("{", "}", descriptor_);
|
||||
if (generate_array_size_) {
|
||||
printer->Print(vars,
|
||||
"static const int ${$$nested_name$_ARRAYSIZE$}$ =\n"
|
||||
" $classname$_$nested_name$_ARRAYSIZE;\n");
|
||||
printer->Annotate("{", "}", descriptor_);
|
||||
}
|
||||
|
||||
if (HasDescriptorMethods(descriptor_->file(), options_)) {
|
||||
printer->Print(vars,
|
||||
"static inline const ::google::protobuf::EnumDescriptor*\n"
|
||||
"$nested_name$_descriptor() {\n"
|
||||
" return $classname$_descriptor();\n"
|
||||
"}\n");
|
||||
printer->Print(vars,
|
||||
"static inline const ::std::string& "
|
||||
"$nested_name$_Name($nested_name$ value) {"
|
||||
"\n"
|
||||
" return $classname$_Name(value);\n"
|
||||
"}\n");
|
||||
printer->Print(vars,
|
||||
"static inline bool $nested_name$_Parse(const ::std::string& name,\n"
|
||||
" $nested_name$* value) {\n"
|
||||
" return $classname$_Parse(name, value);\n"
|
||||
"}\n");
|
||||
}
|
||||
}
|
||||
|
||||
void EnumGenerator::GenerateMethods(int idx, io::Printer* printer) {
|
||||
std::map<string, string> vars;
|
||||
vars["classname"] = classname_;
|
||||
vars["index_in_metadata"] = SimpleItoa(idx);
|
||||
vars["constexpr"] = options_.proto_h ? "constexpr " : "";
|
||||
vars["file_namespace"] = FileLevelNamespace(descriptor_->file()->name());
|
||||
|
||||
if (HasDescriptorMethods(descriptor_->file(), options_)) {
|
||||
printer->Print(
|
||||
vars,
|
||||
"const ::google::protobuf::EnumDescriptor* $classname$_descriptor() {\n"
|
||||
" $file_namespace$::protobuf_AssignDescriptorsOnce();\n"
|
||||
" return "
|
||||
"$file_namespace$::file_level_enum_descriptors[$index_in_metadata$];\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
printer->Print(vars,
|
||||
"bool $classname$_IsValid(int value) {\n"
|
||||
" switch (value) {\n");
|
||||
|
||||
// Multiple values may have the same number. Make sure we only cover
|
||||
// each number once by first constructing a set containing all valid
|
||||
// numbers, then printing a case statement for each element.
|
||||
|
||||
std::set<int> numbers;
|
||||
for (int j = 0; j < descriptor_->value_count(); j++) {
|
||||
const EnumValueDescriptor* value = descriptor_->value(j);
|
||||
numbers.insert(value->number());
|
||||
}
|
||||
|
||||
for (std::set<int>::iterator iter = numbers.begin();
|
||||
iter != numbers.end(); ++iter) {
|
||||
printer->Print(
|
||||
" case $number$:\n",
|
||||
"number", Int32ToString(*iter));
|
||||
}
|
||||
|
||||
printer->Print(vars,
|
||||
" return true;\n"
|
||||
" default:\n"
|
||||
" return false;\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"\n");
|
||||
|
||||
if (descriptor_->containing_type() != NULL) {
|
||||
// We need to "define" the static constants which were declared in the
|
||||
// header, to give the linker a place to put them. Or at least the C++
|
||||
// standard says we have to. MSVC actually insists that we do _not_ define
|
||||
// them again in the .cc file, prior to VC++ 2015.
|
||||
printer->Print("#if !defined(_MSC_VER) || _MSC_VER >= 1900\n");
|
||||
|
||||
vars["parent"] = ClassName(descriptor_->containing_type(), false);
|
||||
vars["nested_name"] = descriptor_->name();
|
||||
for (int i = 0; i < descriptor_->value_count(); i++) {
|
||||
vars["value"] = EnumValueName(descriptor_->value(i));
|
||||
printer->Print(vars,
|
||||
"$constexpr$const $classname$ $parent$::$value$;\n");
|
||||
}
|
||||
printer->Print(vars,
|
||||
"const $classname$ $parent$::$nested_name$_MIN;\n"
|
||||
"const $classname$ $parent$::$nested_name$_MAX;\n");
|
||||
if (generate_array_size_) {
|
||||
printer->Print(vars,
|
||||
"const int $parent$::$nested_name$_ARRAYSIZE;\n");
|
||||
}
|
||||
|
||||
printer->Print("#endif // !defined(_MSC_VER) || _MSC_VER >= 1900\n");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace cpp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
110
Common/ProtocolBuffer/google/protobuf/compiler/cpp/cpp_enum.h
Normal file
110
Common/ProtocolBuffer/google/protobuf/compiler/cpp/cpp_enum.h
Normal file
@ -0,0 +1,110 @@
|
||||
// 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.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_H__
|
||||
#define GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_H__
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <google/protobuf/compiler/cpp/cpp_options.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace io {
|
||||
class Printer; // printer.h
|
||||
}
|
||||
}
|
||||
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
|
||||
class EnumGenerator {
|
||||
public:
|
||||
// See generator.cc for the meaning of dllexport_decl.
|
||||
EnumGenerator(const EnumDescriptor* descriptor, const Options& options);
|
||||
~EnumGenerator();
|
||||
|
||||
// Header stuff.
|
||||
|
||||
// Fills the name to use when declaring the enum. This is for use when
|
||||
// generating other .proto.h files. This code should be placed within the
|
||||
// enum's package namespace, but NOT within any class, even for nested
|
||||
// enums. A given key in enum_names will map from an enum class name to the
|
||||
// EnumDescriptor that was responsible for its inclusion in the map. This can
|
||||
// be used to associate the descriptor with the code generated for it.
|
||||
void FillForwardDeclaration(
|
||||
std::map<string, const EnumDescriptor*>* enum_names);
|
||||
|
||||
// Generate header code defining the enum. This code should be placed
|
||||
// within the enum's package namespace, but NOT within any class, even for
|
||||
// nested enums.
|
||||
void GenerateDefinition(io::Printer* printer);
|
||||
|
||||
// Generate specialization of GetEnumDescriptor<MyEnum>().
|
||||
// Precondition: in ::google::protobuf namespace.
|
||||
void GenerateGetEnumDescriptorSpecializations(io::Printer* printer);
|
||||
|
||||
// For enums nested within a message, generate code to import all the enum's
|
||||
// symbols (e.g. the enum type name, all its values, etc.) into the class's
|
||||
// namespace. This should be placed inside the class definition in the
|
||||
// header.
|
||||
void GenerateSymbolImports(io::Printer* printer);
|
||||
|
||||
// Source file stuff.
|
||||
|
||||
// Generate non-inline methods related to the enum, such as IsValidValue().
|
||||
// Goes in the .cc file. EnumDescriptors are stored in an array, idx is
|
||||
// the index in this array that corresponds with this enum.
|
||||
void GenerateMethods(int idx, io::Printer* printer);
|
||||
|
||||
private:
|
||||
const EnumDescriptor* descriptor_;
|
||||
const string classname_;
|
||||
const Options& options_;
|
||||
// whether to generate the *_ARRAYSIZE constant.
|
||||
const bool generate_array_size_;
|
||||
|
||||
friend class FileGenerator;
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumGenerator);
|
||||
};
|
||||
|
||||
} // namespace cpp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_H__
|
@ -0,0 +1,520 @@
|
||||
// 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/compiler/cpp/cpp_enum_field.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
|
||||
#include <google/protobuf/io/printer.h>
|
||||
#include <google/protobuf/wire_format.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
|
||||
namespace {
|
||||
|
||||
void SetEnumVariables(const FieldDescriptor* descriptor,
|
||||
std::map<string, string>* variables,
|
||||
const Options& options) {
|
||||
SetCommonFieldVariables(descriptor, variables, options);
|
||||
const EnumValueDescriptor* default_value = descriptor->default_value_enum();
|
||||
(*variables)["type"] = ClassName(descriptor->enum_type(), true);
|
||||
(*variables)["default"] = Int32ToString(default_value->number());
|
||||
(*variables)["full_name"] = descriptor->full_name();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// ===================================================================
|
||||
|
||||
EnumFieldGenerator::EnumFieldGenerator(const FieldDescriptor* descriptor,
|
||||
const Options& options)
|
||||
: FieldGenerator(options), descriptor_(descriptor) {
|
||||
SetEnumVariables(descriptor, &variables_, options);
|
||||
}
|
||||
|
||||
EnumFieldGenerator::~EnumFieldGenerator() {}
|
||||
|
||||
void EnumFieldGenerator::
|
||||
GeneratePrivateMembers(io::Printer* printer) const {
|
||||
printer->Print(variables_, "int $name$_;\n");
|
||||
}
|
||||
|
||||
void EnumFieldGenerator::
|
||||
GenerateAccessorDeclarations(io::Printer* printer) const {
|
||||
printer->Print(variables_, "$deprecated_attr$$type$ $name$() const;\n");
|
||||
printer->Annotate("name", descriptor_);
|
||||
printer->Print(variables_,
|
||||
"$deprecated_attr$void ${$set_$name$$}$($type$ value);\n");
|
||||
printer->Annotate("{", "}", descriptor_);
|
||||
}
|
||||
|
||||
void EnumFieldGenerator::
|
||||
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"inline $type$ $classname$::$name$() const {\n"
|
||||
" // @@protoc_insertion_point(field_get:$full_name$)\n"
|
||||
" return static_cast< $type$ >($name$_);\n"
|
||||
"}\n"
|
||||
"inline void $classname$::set_$name$($type$ value) {\n");
|
||||
if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) {
|
||||
printer->Print(variables_,
|
||||
" assert($type$_IsValid(value));\n");
|
||||
}
|
||||
printer->Print(variables_,
|
||||
" $set_hasbit$\n"
|
||||
" $name$_ = value;\n"
|
||||
" // @@protoc_insertion_point(field_set:$full_name$)\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void EnumFieldGenerator::
|
||||
GenerateClearingCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "$name$_ = $default$;\n");
|
||||
}
|
||||
|
||||
void EnumFieldGenerator::
|
||||
GenerateMergingCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "set_$name$(from.$name$());\n");
|
||||
}
|
||||
|
||||
void EnumFieldGenerator::
|
||||
GenerateSwappingCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "swap($name$_, other->$name$_);\n");
|
||||
}
|
||||
|
||||
void EnumFieldGenerator::
|
||||
GenerateConstructorCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "$name$_ = $default$;\n");
|
||||
}
|
||||
|
||||
void EnumFieldGenerator::
|
||||
GenerateCopyConstructorCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "$name$_ = from.$name$_;\n");
|
||||
}
|
||||
|
||||
void EnumFieldGenerator::
|
||||
GenerateMergeFromCodedStream(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"int value;\n"
|
||||
"DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
|
||||
" int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(\n"
|
||||
" input, &value)));\n");
|
||||
if (HasPreservingUnknownEnumSemantics(descriptor_->file())) {
|
||||
printer->Print(variables_,
|
||||
"set_$name$(static_cast< $type$ >(value));\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
"if ($type$_IsValid(value)) {\n"
|
||||
" set_$name$(static_cast< $type$ >(value));\n");
|
||||
if (UseUnknownFieldSet(descriptor_->file(), options_)) {
|
||||
printer->Print(variables_,
|
||||
"} else {\n"
|
||||
" mutable_unknown_fields()->AddVarint(\n"
|
||||
" $number$, static_cast< ::google::protobuf::uint64>(value));\n");
|
||||
} else {
|
||||
printer->Print(
|
||||
"} else {\n"
|
||||
" unknown_fields_stream.WriteVarint32($tag$u);\n"
|
||||
" unknown_fields_stream.WriteVarint32(\n"
|
||||
" static_cast< ::google::protobuf::uint32>(value));\n",
|
||||
"tag", SimpleItoa(internal::WireFormat::MakeTag(descriptor_)));
|
||||
}
|
||||
printer->Print(variables_,
|
||||
"}\n");
|
||||
}
|
||||
}
|
||||
|
||||
void EnumFieldGenerator::
|
||||
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"::google::protobuf::internal::WireFormatLite::WriteEnum(\n"
|
||||
" $number$, this->$name$(), output);\n");
|
||||
}
|
||||
|
||||
void EnumFieldGenerator::
|
||||
GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(\n"
|
||||
" $number$, this->$name$(), target);\n");
|
||||
}
|
||||
|
||||
void EnumFieldGenerator::
|
||||
GenerateByteSize(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"total_size += $tag_size$ +\n"
|
||||
" ::google::protobuf::internal::WireFormatLite::EnumSize(this->$name$());\n");
|
||||
}
|
||||
|
||||
// ===================================================================
|
||||
|
||||
EnumOneofFieldGenerator::
|
||||
EnumOneofFieldGenerator(const FieldDescriptor* descriptor,
|
||||
const Options& options)
|
||||
: EnumFieldGenerator(descriptor, options) {
|
||||
SetCommonOneofFieldVariables(descriptor, &variables_);
|
||||
}
|
||||
|
||||
EnumOneofFieldGenerator::~EnumOneofFieldGenerator() {}
|
||||
|
||||
void EnumOneofFieldGenerator::
|
||||
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"inline $type$ $classname$::$name$() const {\n"
|
||||
" // @@protoc_insertion_point(field_get:$full_name$)\n"
|
||||
" if (has_$name$()) {\n"
|
||||
" return static_cast< $type$ >($field_member$);\n"
|
||||
" }\n"
|
||||
" return static_cast< $type$ >($default$);\n"
|
||||
"}\n"
|
||||
"inline void $classname$::set_$name$($type$ value) {\n");
|
||||
if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) {
|
||||
printer->Print(variables_,
|
||||
" assert($type$_IsValid(value));\n");
|
||||
}
|
||||
printer->Print(variables_,
|
||||
" if (!has_$name$()) {\n"
|
||||
" clear_$oneof_name$();\n"
|
||||
" set_has_$name$();\n"
|
||||
" }\n"
|
||||
" $field_member$ = value;\n"
|
||||
" // @@protoc_insertion_point(field_set:$full_name$)\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void EnumOneofFieldGenerator::
|
||||
GenerateClearingCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "$field_member$ = $default$;\n");
|
||||
}
|
||||
|
||||
void EnumOneofFieldGenerator::
|
||||
GenerateSwappingCode(io::Printer* printer) const {
|
||||
// Don't print any swapping code. Swapping the union will swap this field.
|
||||
}
|
||||
|
||||
void EnumOneofFieldGenerator::
|
||||
GenerateConstructorCode(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"$ns$::_$classname$_default_instance_.$name$_ = $default$;\n");
|
||||
}
|
||||
|
||||
// ===================================================================
|
||||
|
||||
RepeatedEnumFieldGenerator::RepeatedEnumFieldGenerator(
|
||||
const FieldDescriptor* descriptor, const Options& options)
|
||||
: FieldGenerator(options), descriptor_(descriptor) {
|
||||
SetEnumVariables(descriptor, &variables_, options);
|
||||
}
|
||||
|
||||
RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {}
|
||||
|
||||
void RepeatedEnumFieldGenerator::
|
||||
GeneratePrivateMembers(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"::google::protobuf::RepeatedField<int> $name$_;\n");
|
||||
if (descriptor_->is_packed() &&
|
||||
HasGeneratedMethods(descriptor_->file(), options_)) {
|
||||
printer->Print(variables_,
|
||||
"mutable int _$name$_cached_byte_size_;\n");
|
||||
}
|
||||
}
|
||||
|
||||
void RepeatedEnumFieldGenerator::
|
||||
GenerateAccessorDeclarations(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"$deprecated_attr$$type$ $name$(int index) const;\n");
|
||||
printer->Annotate("name", descriptor_);
|
||||
printer->Print(
|
||||
variables_,
|
||||
"$deprecated_attr$void ${$set_$name$$}$(int index, $type$ value);\n");
|
||||
printer->Annotate("{", "}", descriptor_);
|
||||
printer->Print(variables_,
|
||||
"$deprecated_attr$void ${$add_$name$$}$($type$ value);\n");
|
||||
printer->Annotate("{", "}", descriptor_);
|
||||
printer->Print(
|
||||
variables_,
|
||||
"$deprecated_attr$const ::google::protobuf::RepeatedField<int>& $name$() const;\n");
|
||||
printer->Annotate("name", descriptor_);
|
||||
printer->Print(variables_,
|
||||
"$deprecated_attr$::google::protobuf::RepeatedField<int>* "
|
||||
"${$mutable_$name$$}$();\n");
|
||||
printer->Annotate("{", "}", descriptor_);
|
||||
}
|
||||
|
||||
void RepeatedEnumFieldGenerator::
|
||||
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"inline $type$ $classname$::$name$(int index) const {\n"
|
||||
" // @@protoc_insertion_point(field_get:$full_name$)\n"
|
||||
" return static_cast< $type$ >($name$_.Get(index));\n"
|
||||
"}\n"
|
||||
"inline void $classname$::set_$name$(int index, $type$ value) {\n");
|
||||
if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) {
|
||||
printer->Print(variables_,
|
||||
" assert($type$_IsValid(value));\n");
|
||||
}
|
||||
printer->Print(variables_,
|
||||
" $name$_.Set(index, value);\n"
|
||||
" // @@protoc_insertion_point(field_set:$full_name$)\n"
|
||||
"}\n"
|
||||
"inline void $classname$::add_$name$($type$ value) {\n");
|
||||
if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) {
|
||||
printer->Print(variables_,
|
||||
" assert($type$_IsValid(value));\n");
|
||||
}
|
||||
printer->Print(variables_,
|
||||
" $name$_.Add(value);\n"
|
||||
" // @@protoc_insertion_point(field_add:$full_name$)\n"
|
||||
"}\n"
|
||||
"inline const ::google::protobuf::RepeatedField<int>&\n"
|
||||
"$classname$::$name$() const {\n"
|
||||
" // @@protoc_insertion_point(field_list:$full_name$)\n"
|
||||
" return $name$_;\n"
|
||||
"}\n"
|
||||
"inline ::google::protobuf::RepeatedField<int>*\n"
|
||||
"$classname$::mutable_$name$() {\n"
|
||||
" // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
|
||||
" return &$name$_;\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void RepeatedEnumFieldGenerator::
|
||||
GenerateClearingCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "$name$_.Clear();\n");
|
||||
}
|
||||
|
||||
void RepeatedEnumFieldGenerator::
|
||||
GenerateMergingCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n");
|
||||
}
|
||||
|
||||
void RepeatedEnumFieldGenerator::
|
||||
GenerateSwappingCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "$name$_.InternalSwap(&other->$name$_);\n");
|
||||
}
|
||||
|
||||
void RepeatedEnumFieldGenerator::
|
||||
GenerateConstructorCode(io::Printer* printer) const {
|
||||
// Not needed for repeated fields.
|
||||
}
|
||||
|
||||
void RepeatedEnumFieldGenerator::
|
||||
GenerateMergeFromCodedStream(io::Printer* printer) const {
|
||||
// Don't use ReadRepeatedPrimitive here so that the enum can be validated.
|
||||
printer->Print(variables_,
|
||||
"int value;\n"
|
||||
"DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
|
||||
" int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(\n"
|
||||
" input, &value)));\n");
|
||||
if (HasPreservingUnknownEnumSemantics(descriptor_->file())) {
|
||||
printer->Print(variables_,
|
||||
"add_$name$(static_cast< $type$ >(value));\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
"if ($type$_IsValid(value)) {\n"
|
||||
" add_$name$(static_cast< $type$ >(value));\n");
|
||||
if (UseUnknownFieldSet(descriptor_->file(), options_)) {
|
||||
printer->Print(variables_,
|
||||
"} else {\n"
|
||||
" mutable_unknown_fields()->AddVarint(\n"
|
||||
" $number$, static_cast< ::google::protobuf::uint64>(value));\n");
|
||||
} else {
|
||||
printer->Print(
|
||||
"} else {\n"
|
||||
" unknown_fields_stream.WriteVarint32(tag);\n"
|
||||
" unknown_fields_stream.WriteVarint32(\n"
|
||||
" static_cast< ::google::protobuf::uint32>(value));\n");
|
||||
}
|
||||
printer->Print("}\n");
|
||||
}
|
||||
}
|
||||
|
||||
void RepeatedEnumFieldGenerator::
|
||||
GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const {
|
||||
if (!descriptor_->is_packed()) {
|
||||
// This path is rarely executed, so we use a non-inlined implementation.
|
||||
if (HasPreservingUnknownEnumSemantics(descriptor_->file())) {
|
||||
printer->Print(variables_,
|
||||
"DO_((::google::protobuf::internal::"
|
||||
"WireFormatLite::ReadPackedEnumPreserveUnknowns(\n"
|
||||
" input,\n"
|
||||
" $number$,\n"
|
||||
" NULL,\n"
|
||||
" NULL,\n"
|
||||
" this->mutable_$name$())));\n");
|
||||
} else if (UseUnknownFieldSet(descriptor_->file(), options_)) {
|
||||
printer->Print(variables_,
|
||||
"DO_((::google::protobuf::internal::WireFormat::ReadPackedEnumPreserveUnknowns(\n"
|
||||
" input,\n"
|
||||
" $number$,\n"
|
||||
" $type$_IsValid,\n"
|
||||
" mutable_unknown_fields(),\n"
|
||||
" this->mutable_$name$())));\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
"DO_((::google::protobuf::internal::"
|
||||
"WireFormatLite::ReadPackedEnumPreserveUnknowns(\n"
|
||||
" input,\n"
|
||||
" $number$,\n"
|
||||
" $type$_IsValid,\n"
|
||||
" &unknown_fields_stream,\n"
|
||||
" this->mutable_$name$())));\n");
|
||||
}
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
"::google::protobuf::uint32 length;\n"
|
||||
"DO_(input->ReadVarint32(&length));\n"
|
||||
"::google::protobuf::io::CodedInputStream::Limit limit = "
|
||||
"input->PushLimit(static_cast<int>(length));\n"
|
||||
"while (input->BytesUntilLimit() > 0) {\n"
|
||||
" int value;\n"
|
||||
" DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
|
||||
" int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(\n"
|
||||
" input, &value)));\n");
|
||||
if (HasPreservingUnknownEnumSemantics(descriptor_->file())) {
|
||||
printer->Print(variables_,
|
||||
" add_$name$(static_cast< $type$ >(value));\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
" if ($type$_IsValid(value)) {\n"
|
||||
" add_$name$(static_cast< $type$ >(value));\n"
|
||||
" } else {\n");
|
||||
if (UseUnknownFieldSet(descriptor_->file(), options_)) {
|
||||
printer->Print(variables_,
|
||||
" mutable_unknown_fields()->AddVarint(\n"
|
||||
" $number$, static_cast< ::google::protobuf::uint64>(value));\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
" unknown_fields_stream.WriteVarint32(tag);\n"
|
||||
" unknown_fields_stream.WriteVarint32(\n"
|
||||
" static_cast< ::google::protobuf::uint32>(value));\n");
|
||||
}
|
||||
printer->Print(
|
||||
" }\n");
|
||||
}
|
||||
printer->Print(variables_,
|
||||
"}\n"
|
||||
"input->PopLimit(limit);\n");
|
||||
}
|
||||
}
|
||||
|
||||
void RepeatedEnumFieldGenerator::
|
||||
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
|
||||
if (descriptor_->is_packed()) {
|
||||
// Write the tag and the size.
|
||||
printer->Print(variables_,
|
||||
"if (this->$name$_size() > 0) {\n"
|
||||
" ::google::protobuf::internal::WireFormatLite::WriteTag(\n"
|
||||
" $number$,\n"
|
||||
" ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,\n"
|
||||
" output);\n"
|
||||
" output->WriteVarint32(\n"
|
||||
" static_cast< ::google::protobuf::uint32>(_$name$_cached_byte_size_));\n"
|
||||
"}\n");
|
||||
}
|
||||
printer->Print(variables_,
|
||||
"for (int i = 0, n = this->$name$_size(); i < n; i++) {\n");
|
||||
if (descriptor_->is_packed()) {
|
||||
printer->Print(variables_,
|
||||
" ::google::protobuf::internal::WireFormatLite::WriteEnumNoTag(\n"
|
||||
" this->$name$(i), output);\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
" ::google::protobuf::internal::WireFormatLite::WriteEnum(\n"
|
||||
" $number$, this->$name$(i), output);\n");
|
||||
}
|
||||
printer->Print("}\n");
|
||||
}
|
||||
|
||||
void RepeatedEnumFieldGenerator::
|
||||
GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
|
||||
if (descriptor_->is_packed()) {
|
||||
// Write the tag and the size.
|
||||
printer->Print(variables_,
|
||||
"if (this->$name$_size() > 0) {\n"
|
||||
" target = ::google::protobuf::internal::WireFormatLite::WriteTagToArray(\n"
|
||||
" $number$,\n"
|
||||
" ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,\n"
|
||||
" target);\n"
|
||||
" target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray("
|
||||
" static_cast< ::google::protobuf::uint32>(\n"
|
||||
" _$name$_cached_byte_size_), target);\n"
|
||||
" target = ::google::protobuf::internal::WireFormatLite::WriteEnumNoTagToArray(\n"
|
||||
" this->$name$_, target);\n"
|
||||
"}\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
"target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(\n"
|
||||
" $number$, this->$name$_, target);\n");
|
||||
}
|
||||
}
|
||||
|
||||
void RepeatedEnumFieldGenerator::
|
||||
GenerateByteSize(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"{\n"
|
||||
" size_t data_size = 0;\n"
|
||||
" unsigned int count = static_cast<unsigned int>(this->$name$_size());");
|
||||
printer->Indent();
|
||||
printer->Print(variables_,
|
||||
"for (unsigned int i = 0; i < count; i++) {\n"
|
||||
" data_size += ::google::protobuf::internal::WireFormatLite::EnumSize(\n"
|
||||
" this->$name$(static_cast<int>(i)));\n"
|
||||
"}\n");
|
||||
|
||||
if (descriptor_->is_packed()) {
|
||||
printer->Print(variables_,
|
||||
"if (data_size > 0) {\n"
|
||||
" total_size += $tag_size$ +\n"
|
||||
" ::google::protobuf::internal::WireFormatLite::Int32Size(\n"
|
||||
" static_cast< ::google::protobuf::int32>(data_size));\n"
|
||||
"}\n"
|
||||
"int cached_size = ::google::protobuf::internal::ToCachedSize(data_size);\n"
|
||||
"GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n"
|
||||
"_$name$_cached_byte_size_ = cached_size;\n"
|
||||
"GOOGLE_SAFE_CONCURRENT_WRITES_END();\n"
|
||||
"total_size += data_size;\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
"total_size += ($tag_size$UL * count) + data_size;\n");
|
||||
}
|
||||
printer->Outdent();
|
||||
printer->Print("}\n");
|
||||
}
|
||||
|
||||
} // namespace cpp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
@ -0,0 +1,123 @@
|
||||
// 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.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_FIELD_H__
|
||||
#define GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_FIELD_H__
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <google/protobuf/compiler/cpp/cpp_field.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
|
||||
class EnumFieldGenerator : public FieldGenerator {
|
||||
public:
|
||||
EnumFieldGenerator(const FieldDescriptor* descriptor, const Options& options);
|
||||
~EnumFieldGenerator();
|
||||
|
||||
// implements FieldGenerator ---------------------------------------
|
||||
void GeneratePrivateMembers(io::Printer* printer) const;
|
||||
void GenerateAccessorDeclarations(io::Printer* printer) const;
|
||||
void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
|
||||
void GenerateClearingCode(io::Printer* printer) const;
|
||||
void GenerateMergingCode(io::Printer* printer) const;
|
||||
void GenerateSwappingCode(io::Printer* printer) const;
|
||||
void GenerateConstructorCode(io::Printer* printer) const;
|
||||
void GenerateCopyConstructorCode(io::Printer* printer) const;
|
||||
void GenerateMergeFromCodedStream(io::Printer* printer) const;
|
||||
void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
|
||||
void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
|
||||
void GenerateByteSize(io::Printer* printer) const;
|
||||
|
||||
protected:
|
||||
const FieldDescriptor* descriptor_;
|
||||
std::map<string, string> variables_;
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumFieldGenerator);
|
||||
};
|
||||
|
||||
class EnumOneofFieldGenerator : public EnumFieldGenerator {
|
||||
public:
|
||||
EnumOneofFieldGenerator(const FieldDescriptor* descriptor,
|
||||
const Options& options);
|
||||
~EnumOneofFieldGenerator();
|
||||
|
||||
// implements FieldGenerator ---------------------------------------
|
||||
void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
|
||||
void GenerateClearingCode(io::Printer* printer) const;
|
||||
void GenerateSwappingCode(io::Printer* printer) const;
|
||||
void GenerateConstructorCode(io::Printer* printer) const;
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumOneofFieldGenerator);
|
||||
};
|
||||
|
||||
class RepeatedEnumFieldGenerator : public FieldGenerator {
|
||||
public:
|
||||
RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor,
|
||||
const Options& options);
|
||||
~RepeatedEnumFieldGenerator();
|
||||
|
||||
// implements FieldGenerator ---------------------------------------
|
||||
void GeneratePrivateMembers(io::Printer* printer) const;
|
||||
void GenerateAccessorDeclarations(io::Printer* printer) const;
|
||||
void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
|
||||
void GenerateClearingCode(io::Printer* printer) const;
|
||||
void GenerateMergingCode(io::Printer* printer) const;
|
||||
void GenerateSwappingCode(io::Printer* printer) const;
|
||||
void GenerateConstructorCode(io::Printer* printer) const;
|
||||
void GenerateCopyConstructorCode(io::Printer* printer) const {}
|
||||
void GenerateMergeFromCodedStream(io::Printer* printer) const;
|
||||
void GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const;
|
||||
void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
|
||||
void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
|
||||
void GenerateByteSize(io::Printer* printer) const;
|
||||
|
||||
private:
|
||||
const FieldDescriptor* descriptor_;
|
||||
std::map<string, string> variables_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedEnumFieldGenerator);
|
||||
};
|
||||
|
||||
} // namespace cpp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_FIELD_H__
|
@ -0,0 +1,172 @@
|
||||
// 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/compiler/cpp/cpp_extension.h>
|
||||
#include <map>
|
||||
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
|
||||
#include <google/protobuf/descriptor.pb.h>
|
||||
#include <google/protobuf/io/printer.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
|
||||
namespace {
|
||||
|
||||
// Returns the fully-qualified class name of the message that this field
|
||||
// extends. This function is used in the Google-internal code to handle some
|
||||
// legacy cases.
|
||||
string ExtendeeClassName(const FieldDescriptor* descriptor) {
|
||||
const Descriptor* extendee = descriptor->containing_type();
|
||||
return ClassName(extendee, true);
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
ExtensionGenerator::ExtensionGenerator(const FieldDescriptor* descriptor,
|
||||
const Options& options)
|
||||
: descriptor_(descriptor),
|
||||
options_(options) {
|
||||
// Construct type_traits_.
|
||||
if (descriptor_->is_repeated()) {
|
||||
type_traits_ = "Repeated";
|
||||
}
|
||||
|
||||
switch (descriptor_->cpp_type()) {
|
||||
case FieldDescriptor::CPPTYPE_ENUM:
|
||||
type_traits_.append("EnumTypeTraits< ");
|
||||
type_traits_.append(ClassName(descriptor_->enum_type(), true));
|
||||
type_traits_.append(", ");
|
||||
type_traits_.append(ClassName(descriptor_->enum_type(), true));
|
||||
type_traits_.append("_IsValid>");
|
||||
break;
|
||||
case FieldDescriptor::CPPTYPE_STRING:
|
||||
type_traits_.append("StringTypeTraits");
|
||||
break;
|
||||
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||
type_traits_.append("MessageTypeTraits< ");
|
||||
type_traits_.append(ClassName(descriptor_->message_type(), true));
|
||||
type_traits_.append(" >");
|
||||
break;
|
||||
default:
|
||||
type_traits_.append("PrimitiveTypeTraits< ");
|
||||
type_traits_.append(PrimitiveTypeName(descriptor_->cpp_type()));
|
||||
type_traits_.append(" >");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ExtensionGenerator::~ExtensionGenerator() {}
|
||||
|
||||
void ExtensionGenerator::GenerateDeclaration(io::Printer* printer) {
|
||||
std::map<string, string> vars;
|
||||
vars["extendee" ] = ExtendeeClassName(descriptor_);
|
||||
vars["number" ] = SimpleItoa(descriptor_->number());
|
||||
vars["type_traits" ] = type_traits_;
|
||||
vars["name" ] = descriptor_->name();
|
||||
vars["field_type" ] = SimpleItoa(static_cast<int>(descriptor_->type()));
|
||||
vars["packed" ] = descriptor_->options().packed() ? "true" : "false";
|
||||
vars["constant_name"] = FieldConstantName(descriptor_);
|
||||
|
||||
// If this is a class member, it needs to be declared "static". Otherwise,
|
||||
// it needs to be "extern". In the latter case, it also needs the DLL
|
||||
// export/import specifier.
|
||||
if (descriptor_->extension_scope() == NULL) {
|
||||
vars["qualifier"] = "extern";
|
||||
if (!options_.dllexport_decl.empty()) {
|
||||
vars["qualifier"] = options_.dllexport_decl + " " + vars["qualifier"];
|
||||
}
|
||||
} else {
|
||||
vars["qualifier"] = "static";
|
||||
}
|
||||
|
||||
printer->Print(vars,
|
||||
"static const int $constant_name$ = $number$;\n"
|
||||
"$qualifier$ ::google::protobuf::internal::ExtensionIdentifier< $extendee$,\n"
|
||||
" ::google::protobuf::internal::$type_traits$, $field_type$, $packed$ >\n"
|
||||
" $name$;\n"
|
||||
);
|
||||
}
|
||||
|
||||
void ExtensionGenerator::GenerateDefinition(io::Printer* printer) {
|
||||
// If this is a class member, it needs to be declared in its class scope.
|
||||
string scope = (descriptor_->extension_scope() == NULL) ? "" :
|
||||
ClassName(descriptor_->extension_scope(), false) + "::";
|
||||
string name = scope + descriptor_->name();
|
||||
|
||||
std::map<string, string> vars;
|
||||
vars["extendee" ] = ExtendeeClassName(descriptor_);
|
||||
vars["type_traits" ] = type_traits_;
|
||||
vars["name" ] = name;
|
||||
vars["constant_name"] = FieldConstantName(descriptor_);
|
||||
vars["default" ] = DefaultValue(descriptor_);
|
||||
vars["field_type" ] = SimpleItoa(static_cast<int>(descriptor_->type()));
|
||||
vars["packed" ] = descriptor_->options().packed() ? "true" : "false";
|
||||
vars["scope" ] = scope;
|
||||
|
||||
if (descriptor_->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
|
||||
// We need to declare a global string which will contain the default value.
|
||||
// We cannot declare it at class scope because that would require exposing
|
||||
// it in the header which would be annoying for other reasons. So we
|
||||
// replace :: with _ in the name and declare it as a global.
|
||||
string global_name = StringReplace(name, "::", "_", true);
|
||||
vars["global_name"] = global_name;
|
||||
printer->Print(vars,
|
||||
"const ::std::string $global_name$_default($default$);\n");
|
||||
|
||||
// Update the default to refer to the string global.
|
||||
vars["default"] = global_name + "_default";
|
||||
}
|
||||
|
||||
// Likewise, class members need to declare the field constant variable.
|
||||
if (descriptor_->extension_scope() != NULL) {
|
||||
printer->Print(vars,
|
||||
"#if !defined(_MSC_VER) || _MSC_VER >= 1900\n"
|
||||
"const int $scope$$constant_name$;\n"
|
||||
"#endif\n");
|
||||
}
|
||||
|
||||
printer->Print(vars,
|
||||
"::google::protobuf::internal::ExtensionIdentifier< $extendee$,\n"
|
||||
" ::google::protobuf::internal::$type_traits$, $field_type$, $packed$ >\n"
|
||||
" $name$($constant_name$, $default$);\n");
|
||||
}
|
||||
|
||||
} // namespace cpp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
@ -0,0 +1,83 @@
|
||||
// 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.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_EXTENSION_H__
|
||||
#define GOOGLE_PROTOBUF_COMPILER_CPP_EXTENSION_H__
|
||||
|
||||
#include <string>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_options.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
class FieldDescriptor; // descriptor.h
|
||||
namespace io {
|
||||
class Printer; // printer.h
|
||||
}
|
||||
}
|
||||
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
|
||||
// Generates code for an extension, which may be within the scope of some
|
||||
// message or may be at file scope. This is much simpler than FieldGenerator
|
||||
// since extensions are just simple identifiers with interesting types.
|
||||
class ExtensionGenerator {
|
||||
public:
|
||||
// See generator.cc for the meaning of dllexport_decl.
|
||||
explicit ExtensionGenerator(const FieldDescriptor* descriptor,
|
||||
const Options& options);
|
||||
~ExtensionGenerator();
|
||||
|
||||
// Header stuff.
|
||||
void GenerateDeclaration(io::Printer* printer);
|
||||
|
||||
// Source file stuff.
|
||||
void GenerateDefinition(io::Printer* printer);
|
||||
|
||||
private:
|
||||
const FieldDescriptor* descriptor_;
|
||||
string type_traits_;
|
||||
Options options_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionGenerator);
|
||||
};
|
||||
|
||||
} // namespace cpp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__
|
195
Common/ProtocolBuffer/google/protobuf/compiler/cpp/cpp_field.cc
Normal file
195
Common/ProtocolBuffer/google/protobuf/compiler/cpp/cpp_field.cc
Normal file
@ -0,0 +1,195 @@
|
||||
// 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/compiler/cpp/cpp_field.h>
|
||||
#include <memory>
|
||||
|
||||
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_primitive_field.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_string_field.h>
|
||||
#include <google/protobuf/stubs/logging.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_enum_field.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_map_field.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_message_field.h>
|
||||
#include <google/protobuf/descriptor.pb.h>
|
||||
#include <google/protobuf/io/printer.h>
|
||||
#include <google/protobuf/wire_format.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
|
||||
using internal::WireFormat;
|
||||
|
||||
void SetCommonFieldVariables(const FieldDescriptor* descriptor,
|
||||
std::map<string, string>* variables,
|
||||
const Options& options) {
|
||||
(*variables)["ns"] = Namespace(descriptor);
|
||||
(*variables)["name"] = FieldName(descriptor);
|
||||
(*variables)["index"] = SimpleItoa(descriptor->index());
|
||||
(*variables)["number"] = SimpleItoa(descriptor->number());
|
||||
(*variables)["classname"] = ClassName(FieldScope(descriptor), false);
|
||||
(*variables)["declared_type"] = DeclaredTypeMethodName(descriptor->type());
|
||||
(*variables)["field_member"] = FieldName(descriptor) + "_";
|
||||
|
||||
(*variables)["tag_size"] = SimpleItoa(
|
||||
WireFormat::TagSize(descriptor->number(), descriptor->type()));
|
||||
(*variables)["deprecation"] = descriptor->options().deprecated()
|
||||
? " PROTOBUF_DEPRECATED" : "";
|
||||
(*variables)["deprecated_attr"] = descriptor->options().deprecated()
|
||||
? "GOOGLE_PROTOBUF_DEPRECATED_ATTR " : "";
|
||||
|
||||
if (HasFieldPresence(descriptor->file())) {
|
||||
(*variables)["set_hasbit"] =
|
||||
"set_has_" + FieldName(descriptor) + "();";
|
||||
(*variables)["clear_hasbit"] =
|
||||
"clear_has_" + FieldName(descriptor) + "();";
|
||||
} else {
|
||||
(*variables)["set_hasbit"] = "";
|
||||
(*variables)["clear_hasbit"] = "";
|
||||
}
|
||||
|
||||
// These variables are placeholders to pick out the beginning and ends of
|
||||
// identifiers for annotations (when doing so with existing variables would
|
||||
// be ambiguous or impossible). They should never be set to anything but the
|
||||
// empty string.
|
||||
(*variables)["{"] = "";
|
||||
(*variables)["}"] = "";
|
||||
}
|
||||
|
||||
void SetCommonOneofFieldVariables(const FieldDescriptor* descriptor,
|
||||
std::map<string, string>* variables) {
|
||||
const string prefix = descriptor->containing_oneof()->name() + "_.";
|
||||
(*variables)["oneof_name"] = descriptor->containing_oneof()->name();
|
||||
(*variables)["field_member"] = StrCat(prefix, (*variables)["name"], "_");
|
||||
}
|
||||
|
||||
FieldGenerator::~FieldGenerator() {}
|
||||
|
||||
void FieldGenerator::
|
||||
GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const {
|
||||
// Reaching here indicates a bug. Cases are:
|
||||
// - This FieldGenerator should support packing, but this method should be
|
||||
// overridden.
|
||||
// - This FieldGenerator doesn't support packing, and this method should
|
||||
// never have been called.
|
||||
GOOGLE_LOG(FATAL) << "GenerateMergeFromCodedStreamWithPacking() "
|
||||
<< "called on field generator that does not support packing.";
|
||||
|
||||
}
|
||||
|
||||
FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor,
|
||||
const Options& options,
|
||||
SCCAnalyzer* scc_analyzer)
|
||||
: descriptor_(descriptor),
|
||||
options_(options),
|
||||
field_generators_(descriptor->field_count()) {
|
||||
// Construct all the FieldGenerators.
|
||||
for (int i = 0; i < descriptor->field_count(); i++) {
|
||||
field_generators_[i].reset(
|
||||
MakeGenerator(descriptor->field(i), options, scc_analyzer));
|
||||
}
|
||||
}
|
||||
|
||||
FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field,
|
||||
const Options& options,
|
||||
SCCAnalyzer* scc_analyzer) {
|
||||
if (field->is_repeated()) {
|
||||
switch (field->cpp_type()) {
|
||||
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||
if (field->is_map()) {
|
||||
return new MapFieldGenerator(field, options);
|
||||
} else {
|
||||
return new RepeatedMessageFieldGenerator(field, options,
|
||||
scc_analyzer);
|
||||
}
|
||||
case FieldDescriptor::CPPTYPE_STRING:
|
||||
switch (field->options().ctype()) {
|
||||
default: // RepeatedStringFieldGenerator handles unknown ctypes.
|
||||
case FieldOptions::STRING:
|
||||
return new RepeatedStringFieldGenerator(field, options);
|
||||
}
|
||||
case FieldDescriptor::CPPTYPE_ENUM:
|
||||
return new RepeatedEnumFieldGenerator(field, options);
|
||||
default:
|
||||
return new RepeatedPrimitiveFieldGenerator(field, options);
|
||||
}
|
||||
} else if (field->containing_oneof()) {
|
||||
switch (field->cpp_type()) {
|
||||
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||
return new MessageOneofFieldGenerator(field, options, scc_analyzer);
|
||||
case FieldDescriptor::CPPTYPE_STRING:
|
||||
switch (field->options().ctype()) {
|
||||
default: // StringOneofFieldGenerator handles unknown ctypes.
|
||||
case FieldOptions::STRING:
|
||||
return new StringOneofFieldGenerator(field, options);
|
||||
}
|
||||
case FieldDescriptor::CPPTYPE_ENUM:
|
||||
return new EnumOneofFieldGenerator(field, options);
|
||||
default:
|
||||
return new PrimitiveOneofFieldGenerator(field, options);
|
||||
}
|
||||
} else {
|
||||
switch (field->cpp_type()) {
|
||||
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||
return new MessageFieldGenerator(field, options, scc_analyzer);
|
||||
case FieldDescriptor::CPPTYPE_STRING:
|
||||
switch (field->options().ctype()) {
|
||||
default: // StringFieldGenerator handles unknown ctypes.
|
||||
case FieldOptions::STRING:
|
||||
return new StringFieldGenerator(field, options);
|
||||
}
|
||||
case FieldDescriptor::CPPTYPE_ENUM:
|
||||
return new EnumFieldGenerator(field, options);
|
||||
default:
|
||||
return new PrimitiveFieldGenerator(field, options);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FieldGeneratorMap::~FieldGeneratorMap() {}
|
||||
|
||||
const FieldGenerator& FieldGeneratorMap::get(
|
||||
const FieldDescriptor* field) const {
|
||||
GOOGLE_CHECK_EQ(field->containing_type(), descriptor_);
|
||||
return *field_generators_[field->index()];
|
||||
}
|
||||
|
||||
} // namespace cpp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
220
Common/ProtocolBuffer/google/protobuf/compiler/cpp/cpp_field.h
Normal file
220
Common/ProtocolBuffer/google/protobuf/compiler/cpp/cpp_field.h
Normal file
@ -0,0 +1,220 @@
|
||||
// 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.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_FIELD_H__
|
||||
#define GOOGLE_PROTOBUF_COMPILER_CPP_FIELD_H__
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_options.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace io {
|
||||
class Printer; // printer.h
|
||||
}
|
||||
}
|
||||
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
|
||||
// Helper function: set variables in the map that are the same for all
|
||||
// field code generators.
|
||||
// ['name', 'index', 'number', 'classname', 'declared_type', 'tag_size',
|
||||
// 'deprecation'].
|
||||
void SetCommonFieldVariables(const FieldDescriptor* descriptor,
|
||||
std::map<string, string>* variables,
|
||||
const Options& options);
|
||||
|
||||
void SetCommonOneofFieldVariables(const FieldDescriptor* descriptor,
|
||||
std::map<string, string>* variables);
|
||||
|
||||
class FieldGenerator {
|
||||
public:
|
||||
explicit FieldGenerator(const Options& options) : options_(options) {}
|
||||
virtual ~FieldGenerator();
|
||||
|
||||
// Generate lines of code declaring members fields of the message class
|
||||
// needed to represent this field. These are placed inside the message
|
||||
// class.
|
||||
virtual void GeneratePrivateMembers(io::Printer* printer) const = 0;
|
||||
|
||||
// Generate static default variable for this field. These are placed inside
|
||||
// the message class. Most field types don't need this, so the default
|
||||
// implementation is empty.
|
||||
virtual void GenerateStaticMembers(io::Printer* /*printer*/) const {}
|
||||
|
||||
// Generate prototypes for all of the accessor functions related to this
|
||||
// field. These are placed inside the class definition.
|
||||
virtual void GenerateAccessorDeclarations(io::Printer* printer) const = 0;
|
||||
|
||||
// Generate inline definitions of accessor functions for this field.
|
||||
// These are placed inside the header after all class definitions.
|
||||
virtual void GenerateInlineAccessorDefinitions(
|
||||
io::Printer* printer) const = 0;
|
||||
|
||||
// Generate definitions of accessors that aren't inlined. These are
|
||||
// placed somewhere in the .cc file.
|
||||
// Most field types don't need this, so the default implementation is empty.
|
||||
virtual void GenerateNonInlineAccessorDefinitions(
|
||||
io::Printer* /*printer*/) const {}
|
||||
|
||||
// Generate lines of code (statements, not declarations) which clear the
|
||||
// field. This is used to define the clear_$name$() method
|
||||
virtual void GenerateClearingCode(io::Printer* printer) const = 0;
|
||||
|
||||
// Generate lines of code (statements, not declarations) which clear the field
|
||||
// as part of the Clear() method for the whole message. For message types
|
||||
// which have field presence bits, MessageGenerator::GenerateClear will have
|
||||
// already checked the presence bits.
|
||||
//
|
||||
// Since most field types can re-use GenerateClearingCode, this method is not
|
||||
// pure virtual.
|
||||
virtual void GenerateMessageClearingCode(io::Printer* printer) const {
|
||||
GenerateClearingCode(printer);
|
||||
}
|
||||
|
||||
// Generate lines of code (statements, not declarations) which merges the
|
||||
// contents of the field from the current message to the target message,
|
||||
// which is stored in the generated code variable "from".
|
||||
// This is used to fill in the MergeFrom method for the whole message.
|
||||
// Details of this usage can be found in message.cc under the
|
||||
// GenerateMergeFrom method.
|
||||
virtual void GenerateMergingCode(io::Printer* printer) const = 0;
|
||||
|
||||
// Generates a copy constructor
|
||||
virtual void GenerateCopyConstructorCode(io::Printer* printer) const = 0;
|
||||
|
||||
// Generate lines of code (statements, not declarations) which swaps
|
||||
// this field and the corresponding field of another message, which
|
||||
// is stored in the generated code variable "other". This is used to
|
||||
// define the Swap method. Details of usage can be found in
|
||||
// message.cc under the GenerateSwap method.
|
||||
virtual void GenerateSwappingCode(io::Printer* printer) const = 0;
|
||||
|
||||
// Generate initialization code for private members declared by
|
||||
// GeneratePrivateMembers(). These go into the message class's SharedCtor()
|
||||
// method, invoked by each of the generated constructors.
|
||||
virtual void GenerateConstructorCode(io::Printer* printer) const = 0;
|
||||
|
||||
// Generate any code that needs to go in the class's SharedDtor() method,
|
||||
// invoked by the destructor.
|
||||
// Most field types don't need this, so the default implementation is empty.
|
||||
virtual void GenerateDestructorCode(io::Printer* /*printer*/) const {}
|
||||
|
||||
// Generate a manual destructor invocation for use when the message is on an
|
||||
// arena. The code that this method generates will be executed inside a
|
||||
// shared-for-the-whole-message-class method registered with OwnDestructor().
|
||||
// The method should return |true| if it generated any code that requires a
|
||||
// call; this allows the message generator to eliminate the OwnDestructor()
|
||||
// registration if no fields require it.
|
||||
virtual bool GenerateArenaDestructorCode(io::Printer* printer) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Generate code that allocates the fields's default instance.
|
||||
virtual void GenerateDefaultInstanceAllocator(io::Printer* /*printer*/)
|
||||
const {}
|
||||
|
||||
// Generate lines to decode this field, which will be placed inside the
|
||||
// message's MergeFromCodedStream() method.
|
||||
virtual void GenerateMergeFromCodedStream(io::Printer* printer) const = 0;
|
||||
|
||||
// Returns true if this field's "MergeFromCodedStream" code needs the arena
|
||||
// to be defined as a variable.
|
||||
virtual bool MergeFromCodedStreamNeedsArena() const { return false; }
|
||||
|
||||
// Generate lines to decode this field from a packed value, which will be
|
||||
// placed inside the message's MergeFromCodedStream() method.
|
||||
virtual void GenerateMergeFromCodedStreamWithPacking(io::Printer* printer)
|
||||
const;
|
||||
|
||||
// Generate lines to serialize this field, which are placed within the
|
||||
// message's SerializeWithCachedSizes() method.
|
||||
virtual void GenerateSerializeWithCachedSizes(io::Printer* printer) const = 0;
|
||||
|
||||
// Generate lines to serialize this field directly to the array "target",
|
||||
// which are placed within the message's SerializeWithCachedSizesToArray()
|
||||
// method. This must also advance "target" past the written bytes.
|
||||
virtual void GenerateSerializeWithCachedSizesToArray(
|
||||
io::Printer* printer) const = 0;
|
||||
|
||||
// Generate lines to compute the serialized size of this field, which
|
||||
// are placed in the message's ByteSize() method.
|
||||
virtual void GenerateByteSize(io::Printer* printer) const = 0;
|
||||
|
||||
// Any tags about field layout decisions (such as inlining) to embed in the
|
||||
// offset.
|
||||
virtual uint32 CalculateFieldTag() const { return 0; }
|
||||
virtual bool IsInlined() const { return false; }
|
||||
|
||||
protected:
|
||||
const Options& options_;
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGenerator);
|
||||
};
|
||||
|
||||
// Convenience class which constructs FieldGenerators for a Descriptor.
|
||||
class FieldGeneratorMap {
|
||||
public:
|
||||
FieldGeneratorMap(const Descriptor* descriptor, const Options& options,
|
||||
SCCAnalyzer* scc_analyzer);
|
||||
~FieldGeneratorMap();
|
||||
|
||||
const FieldGenerator& get(const FieldDescriptor* field) const;
|
||||
|
||||
private:
|
||||
const Descriptor* descriptor_;
|
||||
const Options& options_;
|
||||
std::vector<std::unique_ptr<FieldGenerator>> field_generators_;
|
||||
|
||||
static FieldGenerator* MakeGenerator(const FieldDescriptor* field,
|
||||
const Options& options,
|
||||
SCCAnalyzer* scc_analyzer);
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap);
|
||||
};
|
||||
|
||||
} // namespace cpp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_FIELD_H__
|
1411
Common/ProtocolBuffer/google/protobuf/compiler/cpp/cpp_file.cc
Normal file
1411
Common/ProtocolBuffer/google/protobuf/compiler/cpp/cpp_file.cc
Normal file
File diff suppressed because it is too large
Load Diff
193
Common/ProtocolBuffer/google/protobuf/compiler/cpp/cpp_file.h
Normal file
193
Common/ProtocolBuffer/google/protobuf/compiler/cpp/cpp_file.h
Normal file
@ -0,0 +1,193 @@
|
||||
// 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.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_FILE_H__
|
||||
#define GOOGLE_PROTOBUF_COMPILER_CPP_FILE_H__
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_field.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_options.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
class FileDescriptor; // descriptor.h
|
||||
namespace io {
|
||||
class Printer; // printer.h
|
||||
}
|
||||
}
|
||||
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
|
||||
class EnumGenerator; // enum.h
|
||||
class MessageGenerator; // message.h
|
||||
class ServiceGenerator; // service.h
|
||||
class ExtensionGenerator; // extension.h
|
||||
|
||||
class FileGenerator {
|
||||
public:
|
||||
// See generator.cc for the meaning of dllexport_decl.
|
||||
FileGenerator(const FileDescriptor* file, const Options& options);
|
||||
~FileGenerator();
|
||||
|
||||
// Shared code between the two header generators below.
|
||||
void GenerateHeader(io::Printer* printer);
|
||||
|
||||
// info_path, if non-empty, should be the path (relative to printer's output)
|
||||
// to the metadata file describing this proto header.
|
||||
void GenerateProtoHeader(io::Printer* printer,
|
||||
const string& info_path);
|
||||
// info_path, if non-empty, should be the path (relative to printer's output)
|
||||
// to the metadata file describing this PB header.
|
||||
void GeneratePBHeader(io::Printer* printer,
|
||||
const string& info_path);
|
||||
void GenerateSource(io::Printer* printer);
|
||||
|
||||
int NumMessages() const { return message_generators_.size(); }
|
||||
// Similar to GenerateSource but generates only one message
|
||||
void GenerateSourceForMessage(int idx, io::Printer* printer);
|
||||
void GenerateGlobalSource(io::Printer* printer);
|
||||
|
||||
private:
|
||||
// Internal type used by GenerateForwardDeclarations (defined in file.cc).
|
||||
class ForwardDeclarations;
|
||||
|
||||
void GenerateSourceIncludes(io::Printer* printer);
|
||||
void GenerateSourceDefaultInstance(int idx, io::Printer* printer);
|
||||
|
||||
void GenerateInitForSCC(const SCC* scc, io::Printer* printer);
|
||||
void GenerateTables(io::Printer* printer);
|
||||
void GenerateReflectionInitializationCode(io::Printer* printer);
|
||||
|
||||
// For other imports, generates their forward-declarations.
|
||||
void GenerateForwardDeclarations(io::Printer* printer);
|
||||
|
||||
// Internal helper used by GenerateForwardDeclarations: fills 'decls'
|
||||
// with all necessary forward-declarations for this file and its
|
||||
// transient depednencies.
|
||||
void FillForwardDeclarations(ForwardDeclarations* decls);
|
||||
|
||||
// Generates top or bottom of a header file.
|
||||
void GenerateTopHeaderGuard(io::Printer* printer,
|
||||
const string& filename_identifier);
|
||||
void GenerateBottomHeaderGuard(io::Printer* printer,
|
||||
const string& filename_identifier);
|
||||
|
||||
// Generates #include directives.
|
||||
void GenerateLibraryIncludes(io::Printer* printer);
|
||||
void GenerateDependencyIncludes(io::Printer* printer);
|
||||
|
||||
// Generate a pragma to pull in metadata using the given info_path (if
|
||||
// non-empty). info_path should be relative to printer's output.
|
||||
void GenerateMetadataPragma(io::Printer* printer, const string& info_path);
|
||||
|
||||
// Generates a couple of different pieces before definitions:
|
||||
void GenerateGlobalStateFunctionDeclarations(io::Printer* printer);
|
||||
|
||||
// Generates types for classes.
|
||||
void GenerateMessageDefinitions(io::Printer* printer);
|
||||
|
||||
void GenerateEnumDefinitions(io::Printer* printer);
|
||||
|
||||
// Generates generic service definitions.
|
||||
void GenerateServiceDefinitions(io::Printer* printer);
|
||||
|
||||
// Generates extension identifiers.
|
||||
void GenerateExtensionIdentifiers(io::Printer* printer);
|
||||
|
||||
// Generates inline function defintions.
|
||||
void GenerateInlineFunctionDefinitions(io::Printer* printer);
|
||||
|
||||
void GenerateProto2NamespaceEnumSpecializations(io::Printer* printer);
|
||||
|
||||
// Sometimes the names we use in a .proto file happen to be defined as macros
|
||||
// on some platforms (e.g., macro/minor used in plugin.proto are defined as
|
||||
// macros in sys/types.h on FreeBSD and a few other platforms). To make the
|
||||
// generated code compile on these platforms, we either have to undef the
|
||||
// macro for these few platforms, or rename the field name for all platforms.
|
||||
// Since these names are part of protobuf public API, renaming is generally
|
||||
// a breaking change so we prefer the #undef approach.
|
||||
void GenerateMacroUndefs(io::Printer* printer);
|
||||
|
||||
bool IsSCCRepresentative(const Descriptor* d) {
|
||||
return GetSCCRepresentative(d) == d;
|
||||
}
|
||||
const Descriptor* GetSCCRepresentative(const Descriptor* d) {
|
||||
return GetSCC(d)->GetRepresentative();
|
||||
}
|
||||
const SCC* GetSCC(const Descriptor* d) {
|
||||
return scc_analyzer_.GetSCC(d);
|
||||
}
|
||||
|
||||
|
||||
const FileDescriptor* file_;
|
||||
const Options options_;
|
||||
|
||||
SCCAnalyzer scc_analyzer_;
|
||||
|
||||
|
||||
// Contains the post-order walk of all the messages (and child messages) in
|
||||
// this file. If you need a pre-order walk just reverse iterate.
|
||||
std::vector<MessageGenerator*> message_generators_;
|
||||
std::vector<EnumGenerator*> enum_generators_;
|
||||
std::vector<ServiceGenerator*> service_generators_;
|
||||
std::vector<ExtensionGenerator*> extension_generators_;
|
||||
|
||||
// These members are just for owning (and thus proper deleting).
|
||||
// Nested (enum/extension)_generators are owned by child messages.
|
||||
std::unique_ptr<std::unique_ptr<EnumGenerator> []> enum_generators_owner_;
|
||||
std::unique_ptr<std::unique_ptr<ServiceGenerator> []>
|
||||
service_generators_owner_;
|
||||
std::unique_ptr<std::unique_ptr<ExtensionGenerator> []>
|
||||
extension_generators_owner_;
|
||||
|
||||
// E.g. if the package is foo.bar, package_parts_ is {"foo", "bar"}.
|
||||
std::vector<string> package_parts_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator);
|
||||
};
|
||||
|
||||
} // namespace cpp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_FILE_H__
|
@ -0,0 +1,207 @@
|
||||
// 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/compiler/cpp/cpp_generator.h>
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_file.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
|
||||
#include <google/protobuf/descriptor.pb.h>
|
||||
#include <google/protobuf/io/printer.h>
|
||||
#include <google/protobuf/io/zero_copy_stream.h>
|
||||
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
|
||||
CppGenerator::CppGenerator() {}
|
||||
CppGenerator::~CppGenerator() {}
|
||||
|
||||
bool CppGenerator::Generate(const FileDescriptor* file,
|
||||
const string& parameter,
|
||||
GeneratorContext* generator_context,
|
||||
string* error) const {
|
||||
std::vector<std::pair<string, string> > options;
|
||||
ParseGeneratorParameter(parameter, &options);
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// parse generator options
|
||||
|
||||
// If the dllexport_decl option is passed to the compiler, we need to write
|
||||
// it in front of every symbol that should be exported if this .proto is
|
||||
// compiled into a Windows DLL. E.g., if the user invokes the protocol
|
||||
// compiler as:
|
||||
// protoc --cpp_out=dllexport_decl=FOO_EXPORT:outdir foo.proto
|
||||
// then we'll define classes like this:
|
||||
// class FOO_EXPORT Foo {
|
||||
// ...
|
||||
// }
|
||||
// FOO_EXPORT is a macro which should expand to __declspec(dllexport) or
|
||||
// __declspec(dllimport) depending on what is being compiled.
|
||||
//
|
||||
Options file_options;
|
||||
for (int i = 0; i < options.size(); i++) {
|
||||
if (options[i].first == "dllexport_decl") {
|
||||
file_options.dllexport_decl = options[i].second;
|
||||
} else if (options[i].first == "safe_boundary_check") {
|
||||
file_options.safe_boundary_check = true;
|
||||
} else if (options[i].first == "annotate_headers") {
|
||||
file_options.annotate_headers = true;
|
||||
} else if (options[i].first == "annotation_pragma_name") {
|
||||
file_options.annotation_pragma_name = options[i].second;
|
||||
} else if (options[i].first == "annotation_guard_name") {
|
||||
file_options.annotation_guard_name = options[i].second;
|
||||
} else if (options[i].first == "lite") {
|
||||
file_options.enforce_lite = true;
|
||||
} else if (options[i].first == "lite_implicit_weak_fields") {
|
||||
file_options.lite_implicit_weak_fields = true;
|
||||
if (!options[i].second.empty()) {
|
||||
file_options.num_cc_files = strto32(options[i].second.c_str(),
|
||||
NULL, 10);
|
||||
}
|
||||
} else if (options[i].first == "table_driven_parsing") {
|
||||
file_options.table_driven_parsing = true;
|
||||
} else if (options[i].first == "table_driven_serialization") {
|
||||
file_options.table_driven_serialization = true;
|
||||
} else {
|
||||
*error = "Unknown generator option: " + options[i].first;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// The safe_boundary_check option controls behavior for Google-internal
|
||||
// protobuf APIs.
|
||||
if (file_options.safe_boundary_check) {
|
||||
*error =
|
||||
"The safe_boundary_check option is not supported outside of Google.";
|
||||
return false;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
|
||||
|
||||
string basename = StripProto(file->name());
|
||||
|
||||
|
||||
FileGenerator file_generator(file, file_options);
|
||||
|
||||
// Generate header(s).
|
||||
if (file_options.proto_h) {
|
||||
std::unique_ptr<io::ZeroCopyOutputStream> output(
|
||||
generator_context->Open(basename + ".proto.h"));
|
||||
GeneratedCodeInfo annotations;
|
||||
io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector(
|
||||
&annotations);
|
||||
string info_path = basename + ".proto.h.meta";
|
||||
io::Printer printer(output.get(), '$', file_options.annotate_headers
|
||||
? &annotation_collector
|
||||
: NULL);
|
||||
file_generator.GenerateProtoHeader(
|
||||
&printer, file_options.annotate_headers ? info_path : "");
|
||||
if (file_options.annotate_headers) {
|
||||
std::unique_ptr<io::ZeroCopyOutputStream> info_output(
|
||||
generator_context->Open(info_path));
|
||||
annotations.SerializeToZeroCopyStream(info_output.get());
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
std::unique_ptr<io::ZeroCopyOutputStream> output(
|
||||
generator_context->Open(basename + ".pb.h"));
|
||||
GeneratedCodeInfo annotations;
|
||||
io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector(
|
||||
&annotations);
|
||||
string info_path = basename + ".pb.h.meta";
|
||||
io::Printer printer(output.get(), '$', file_options.annotate_headers
|
||||
? &annotation_collector
|
||||
: NULL);
|
||||
file_generator.GeneratePBHeader(
|
||||
&printer, file_options.annotate_headers ? info_path : "");
|
||||
if (file_options.annotate_headers) {
|
||||
std::unique_ptr<io::ZeroCopyOutputStream> info_output(
|
||||
generator_context->Open(info_path));
|
||||
annotations.SerializeToZeroCopyStream(info_output.get());
|
||||
}
|
||||
}
|
||||
|
||||
// Generate cc file(s).
|
||||
if (UsingImplicitWeakFields(file, file_options)) {
|
||||
{
|
||||
// This is the global .cc file, containing enum/services/tables/reflection
|
||||
std::unique_ptr<io::ZeroCopyOutputStream> output(
|
||||
generator_context->Open(basename + ".pb.cc"));
|
||||
io::Printer printer(output.get(), '$');
|
||||
file_generator.GenerateGlobalSource(&printer);
|
||||
}
|
||||
|
||||
int num_cc_files = file_generator.NumMessages();
|
||||
|
||||
// If we're using implicit weak fields then we allow the user to optionally
|
||||
// specify how many files to generate, not counting the global pb.cc file.
|
||||
// If we have more files than messages, then some files will be generated as
|
||||
// empty placeholders.
|
||||
if (file_options.num_cc_files > 0) {
|
||||
GOOGLE_CHECK_LE(file_generator.NumMessages(), file_options.num_cc_files)
|
||||
<< "There must be at least as many numbered .cc files as messages.";
|
||||
num_cc_files = file_options.num_cc_files;
|
||||
}
|
||||
for (int i = 0; i < num_cc_files; i++) {
|
||||
// TODO(gerbens) Agree on naming scheme.
|
||||
std::unique_ptr<io::ZeroCopyOutputStream> output(
|
||||
generator_context->Open(basename + "." + SimpleItoa(i) + ".cc"));
|
||||
io::Printer printer(output.get(), '$');
|
||||
if (i < file_generator.NumMessages()) {
|
||||
file_generator.GenerateSourceForMessage(i, &printer);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
std::unique_ptr<io::ZeroCopyOutputStream> output(
|
||||
generator_context->Open(basename + ".pb.cc"));
|
||||
io::Printer printer(output.get(), '$');
|
||||
file_generator.GenerateSource(&printer);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace cpp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
@ -0,0 +1,72 @@
|
||||
// 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.
|
||||
//
|
||||
// Generates C++ code for a given .proto file.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_GENERATOR_H__
|
||||
#define GOOGLE_PROTOBUF_COMPILER_CPP_GENERATOR_H__
|
||||
|
||||
#include <string>
|
||||
#include <google/protobuf/compiler/code_generator.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
|
||||
// CodeGenerator implementation which generates a C++ source file and
|
||||
// header. If you create your own protocol compiler binary and you want
|
||||
// it to support C++ output, you can do so by registering an instance of this
|
||||
// CodeGenerator with the CommandLineInterface in your main() function.
|
||||
class LIBPROTOC_EXPORT CppGenerator : public CodeGenerator {
|
||||
public:
|
||||
CppGenerator();
|
||||
~CppGenerator();
|
||||
|
||||
// implements CodeGenerator ----------------------------------------
|
||||
bool Generate(const FileDescriptor* file,
|
||||
const string& parameter,
|
||||
GeneratorContext* generator_context,
|
||||
string* error) const;
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CppGenerator);
|
||||
};
|
||||
|
||||
} // namespace cpp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_GENERATOR_H__
|
@ -0,0 +1,867 @@
|
||||
// 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/stubs/hash.h>
|
||||
#include <limits>
|
||||
#include <map>
|
||||
#include <queue>
|
||||
#include <vector>
|
||||
|
||||
#include <google/protobuf/stubs/logging.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
|
||||
#include <google/protobuf/io/printer.h>
|
||||
#include <google/protobuf/io/zero_copy_stream.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
#include <google/protobuf/stubs/substitute.h>
|
||||
|
||||
|
||||
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
|
||||
namespace {
|
||||
|
||||
static const char kAnyMessageName[] = "Any";
|
||||
static const char kAnyProtoFile[] = "google/protobuf/any.proto";
|
||||
static const char kGoogleProtobufPrefix[] = "google/protobuf/";
|
||||
|
||||
string DotsToUnderscores(const string& name) {
|
||||
return StringReplace(name, ".", "_", true);
|
||||
}
|
||||
|
||||
string DotsToColons(const string& name) {
|
||||
return StringReplace(name, ".", "::", true);
|
||||
}
|
||||
|
||||
const char* const kKeywordList[] = {
|
||||
"alignas", "alignof", "and", "and_eq", "asm", "auto", "bitand", "bitor",
|
||||
"bool", "break", "case", "catch", "char", "class", "compl", "const",
|
||||
"constexpr", "const_cast", "continue", "decltype", "default", "delete", "do",
|
||||
"double", "dynamic_cast", "else", "enum", "explicit", "export", "extern",
|
||||
"false", "float", "for", "friend", "goto", "if", "inline", "int", "long",
|
||||
"mutable", "namespace", "new", "noexcept", "not", "not_eq", "nullptr",
|
||||
"operator", "or", "or_eq", "private", "protected", "public", "register",
|
||||
"reinterpret_cast", "return", "short", "signed", "sizeof", "static",
|
||||
"static_assert", "static_cast", "struct", "switch", "template", "this",
|
||||
"thread_local", "throw", "true", "try", "typedef", "typeid", "typename",
|
||||
"union", "unsigned", "using", "virtual", "void", "volatile", "wchar_t",
|
||||
"while", "xor", "xor_eq"
|
||||
};
|
||||
|
||||
hash_set<string> MakeKeywordsMap() {
|
||||
hash_set<string> result;
|
||||
for (int i = 0; i < GOOGLE_ARRAYSIZE(kKeywordList); i++) {
|
||||
result.insert(kKeywordList[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
hash_set<string> kKeywords = MakeKeywordsMap();
|
||||
|
||||
// Returns whether the provided descriptor has an extension. This includes its
|
||||
// nested types.
|
||||
bool HasExtension(const Descriptor* descriptor) {
|
||||
if (descriptor->extension_count() > 0) {
|
||||
return true;
|
||||
}
|
||||
for (int i = 0; i < descriptor->nested_type_count(); ++i) {
|
||||
if (HasExtension(descriptor->nested_type(i))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Encode [0..63] as 'A'-'Z', 'a'-'z', '0'-'9', '_'
|
||||
char Base63Char(int value) {
|
||||
GOOGLE_CHECK_GE(value, 0);
|
||||
if (value < 26) return 'A' + value;
|
||||
value -= 26;
|
||||
if (value < 26) return 'a' + value;
|
||||
value -= 26;
|
||||
if (value < 10) return '0' + value;
|
||||
GOOGLE_CHECK_EQ(value, 10);
|
||||
return '_';
|
||||
}
|
||||
|
||||
// Given a c identifier has 63 legal characters we can't implement base64
|
||||
// encoding. So we return the k least significant "digits" in base 63.
|
||||
template <typename I>
|
||||
string Base63(I n, int k) {
|
||||
string res;
|
||||
while (k-- > 0) {
|
||||
res += Base63Char(static_cast<int>(n % 63));
|
||||
n /= 63;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
string UnderscoresToCamelCase(const string& input, bool cap_next_letter) {
|
||||
string result;
|
||||
// Note: I distrust ctype.h due to locales.
|
||||
for (int i = 0; i < input.size(); i++) {
|
||||
if ('a' <= input[i] && input[i] <= 'z') {
|
||||
if (cap_next_letter) {
|
||||
result += input[i] + ('A' - 'a');
|
||||
} else {
|
||||
result += input[i];
|
||||
}
|
||||
cap_next_letter = false;
|
||||
} else if ('A' <= input[i] && input[i] <= 'Z') {
|
||||
// Capital letters are left as-is.
|
||||
result += input[i];
|
||||
cap_next_letter = false;
|
||||
} else if ('0' <= input[i] && input[i] <= '9') {
|
||||
result += input[i];
|
||||
cap_next_letter = true;
|
||||
} else {
|
||||
cap_next_letter = true;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
const char kThickSeparator[] =
|
||||
"// ===================================================================\n";
|
||||
const char kThinSeparator[] =
|
||||
"// -------------------------------------------------------------------\n";
|
||||
|
||||
bool CanInitializeByZeroing(const FieldDescriptor* field) {
|
||||
if (field->is_repeated() || field->is_extension()) return false;
|
||||
switch (field->cpp_type()) {
|
||||
case FieldDescriptor::CPPTYPE_ENUM:
|
||||
return field->default_value_enum()->number() == 0;
|
||||
case FieldDescriptor::CPPTYPE_INT32:
|
||||
return field->default_value_int32() == 0;
|
||||
case FieldDescriptor::CPPTYPE_INT64:
|
||||
return field->default_value_int64() == 0;
|
||||
case FieldDescriptor::CPPTYPE_UINT32:
|
||||
return field->default_value_uint32() == 0;
|
||||
case FieldDescriptor::CPPTYPE_UINT64:
|
||||
return field->default_value_uint64() == 0;
|
||||
case FieldDescriptor::CPPTYPE_FLOAT:
|
||||
return field->default_value_float() == 0;
|
||||
case FieldDescriptor::CPPTYPE_DOUBLE:
|
||||
return field->default_value_double() == 0;
|
||||
case FieldDescriptor::CPPTYPE_BOOL:
|
||||
return field->default_value_bool() == false;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
string ClassName(const Descriptor* descriptor) {
|
||||
const Descriptor* parent = descriptor->containing_type();
|
||||
string res;
|
||||
if (parent) res += ClassName(parent) + "_";
|
||||
res += descriptor->name();
|
||||
if (IsMapEntryMessage(descriptor)) res += "_DoNotUse";
|
||||
return res;
|
||||
}
|
||||
|
||||
string ClassName(const EnumDescriptor* enum_descriptor) {
|
||||
if (enum_descriptor->containing_type() == NULL) {
|
||||
return enum_descriptor->name();
|
||||
} else {
|
||||
return ClassName(enum_descriptor->containing_type()) + "_" +
|
||||
enum_descriptor->name();
|
||||
}
|
||||
}
|
||||
|
||||
string Namespace(const string& package) {
|
||||
if (package.empty()) return "";
|
||||
return "::" + DotsToColons(package);
|
||||
}
|
||||
|
||||
string DefaultInstanceName(const Descriptor* descriptor) {
|
||||
string prefix = descriptor->file()->package().empty() ? "" : "::";
|
||||
return prefix + DotsToColons(descriptor->file()->package()) + "::_" +
|
||||
ClassName(descriptor, false) + "_default_instance_";
|
||||
}
|
||||
|
||||
string ReferenceFunctionName(const Descriptor* descriptor) {
|
||||
return QualifiedClassName(descriptor) + "_ReferenceStrong";
|
||||
}
|
||||
|
||||
string SuperClassName(const Descriptor* descriptor, const Options& options) {
|
||||
return HasDescriptorMethods(descriptor->file(), options)
|
||||
? "::google::protobuf::Message"
|
||||
: "::google::protobuf::MessageLite";
|
||||
}
|
||||
|
||||
string FieldName(const FieldDescriptor* field) {
|
||||
string result = field->name();
|
||||
LowerString(&result);
|
||||
if (kKeywords.count(result) > 0) {
|
||||
result.append("_");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
string EnumValueName(const EnumValueDescriptor* enum_value) {
|
||||
string result = enum_value->name();
|
||||
if (kKeywords.count(result) > 0) {
|
||||
result.append("_");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int EstimateAlignmentSize(const FieldDescriptor* field) {
|
||||
if (field == NULL) return 0;
|
||||
if (field->is_repeated()) return 8;
|
||||
switch (field->cpp_type()) {
|
||||
case FieldDescriptor::CPPTYPE_BOOL:
|
||||
return 1;
|
||||
|
||||
case FieldDescriptor::CPPTYPE_INT32:
|
||||
case FieldDescriptor::CPPTYPE_UINT32:
|
||||
case FieldDescriptor::CPPTYPE_ENUM:
|
||||
case FieldDescriptor::CPPTYPE_FLOAT:
|
||||
return 4;
|
||||
|
||||
case FieldDescriptor::CPPTYPE_INT64:
|
||||
case FieldDescriptor::CPPTYPE_UINT64:
|
||||
case FieldDescriptor::CPPTYPE_DOUBLE:
|
||||
case FieldDescriptor::CPPTYPE_STRING:
|
||||
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||
return 8;
|
||||
}
|
||||
GOOGLE_LOG(FATAL) << "Can't get here.";
|
||||
return -1; // Make compiler happy.
|
||||
}
|
||||
|
||||
string FieldConstantName(const FieldDescriptor *field) {
|
||||
string field_name = UnderscoresToCamelCase(field->name(), true);
|
||||
string result = "k" + field_name + "FieldNumber";
|
||||
|
||||
if (!field->is_extension() &&
|
||||
field->containing_type()->FindFieldByCamelcaseName(
|
||||
field->camelcase_name()) != field) {
|
||||
// This field's camelcase name is not unique. As a hack, add the field
|
||||
// number to the constant name. This makes the constant rather useless,
|
||||
// but what can we do?
|
||||
result += "_" + SimpleItoa(field->number());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
string FieldMessageTypeName(const FieldDescriptor* field) {
|
||||
// Note: The Google-internal version of Protocol Buffers uses this function
|
||||
// as a hook point for hacks to support legacy code.
|
||||
return ClassName(field->message_type(), true);
|
||||
}
|
||||
|
||||
string StripProto(const string& filename) {
|
||||
if (HasSuffixString(filename, ".protodevel")) {
|
||||
return StripSuffixString(filename, ".protodevel");
|
||||
} else {
|
||||
return StripSuffixString(filename, ".proto");
|
||||
}
|
||||
}
|
||||
|
||||
const char* PrimitiveTypeName(FieldDescriptor::CppType type) {
|
||||
switch (type) {
|
||||
case FieldDescriptor::CPPTYPE_INT32 : return "::google::protobuf::int32";
|
||||
case FieldDescriptor::CPPTYPE_INT64 : return "::google::protobuf::int64";
|
||||
case FieldDescriptor::CPPTYPE_UINT32 : return "::google::protobuf::uint32";
|
||||
case FieldDescriptor::CPPTYPE_UINT64 : return "::google::protobuf::uint64";
|
||||
case FieldDescriptor::CPPTYPE_DOUBLE : return "double";
|
||||
case FieldDescriptor::CPPTYPE_FLOAT : return "float";
|
||||
case FieldDescriptor::CPPTYPE_BOOL : return "bool";
|
||||
case FieldDescriptor::CPPTYPE_ENUM : return "int";
|
||||
case FieldDescriptor::CPPTYPE_STRING : return "::std::string";
|
||||
case FieldDescriptor::CPPTYPE_MESSAGE: return NULL;
|
||||
|
||||
// No default because we want the compiler to complain if any new
|
||||
// CppTypes are added.
|
||||
}
|
||||
|
||||
GOOGLE_LOG(FATAL) << "Can't get here.";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* DeclaredTypeMethodName(FieldDescriptor::Type type) {
|
||||
switch (type) {
|
||||
case FieldDescriptor::TYPE_INT32 : return "Int32";
|
||||
case FieldDescriptor::TYPE_INT64 : return "Int64";
|
||||
case FieldDescriptor::TYPE_UINT32 : return "UInt32";
|
||||
case FieldDescriptor::TYPE_UINT64 : return "UInt64";
|
||||
case FieldDescriptor::TYPE_SINT32 : return "SInt32";
|
||||
case FieldDescriptor::TYPE_SINT64 : return "SInt64";
|
||||
case FieldDescriptor::TYPE_FIXED32 : return "Fixed32";
|
||||
case FieldDescriptor::TYPE_FIXED64 : return "Fixed64";
|
||||
case FieldDescriptor::TYPE_SFIXED32: return "SFixed32";
|
||||
case FieldDescriptor::TYPE_SFIXED64: return "SFixed64";
|
||||
case FieldDescriptor::TYPE_FLOAT : return "Float";
|
||||
case FieldDescriptor::TYPE_DOUBLE : return "Double";
|
||||
|
||||
case FieldDescriptor::TYPE_BOOL : return "Bool";
|
||||
case FieldDescriptor::TYPE_ENUM : return "Enum";
|
||||
|
||||
case FieldDescriptor::TYPE_STRING : return "String";
|
||||
case FieldDescriptor::TYPE_BYTES : return "Bytes";
|
||||
case FieldDescriptor::TYPE_GROUP : return "Group";
|
||||
case FieldDescriptor::TYPE_MESSAGE : return "Message";
|
||||
|
||||
// No default because we want the compiler to complain if any new
|
||||
// types are added.
|
||||
}
|
||||
GOOGLE_LOG(FATAL) << "Can't get here.";
|
||||
return "";
|
||||
}
|
||||
|
||||
string Int32ToString(int number) {
|
||||
// gcc rejects the decimal form of kint32min.
|
||||
if (number == kint32min) {
|
||||
GOOGLE_COMPILE_ASSERT(kint32min == (~0x7fffffff), kint32min_value_error);
|
||||
return "(~0x7fffffff)";
|
||||
} else {
|
||||
return SimpleItoa(number);
|
||||
}
|
||||
}
|
||||
|
||||
string Int64ToString(int64 number) {
|
||||
// gcc rejects the decimal form of kint64min
|
||||
if (number == kint64min) {
|
||||
// Make sure we are in a 2's complement system.
|
||||
GOOGLE_COMPILE_ASSERT(kint64min == GOOGLE_LONGLONG(~0x7fffffffffffffff),
|
||||
kint64min_value_error);
|
||||
return "GOOGLE_LONGLONG(~0x7fffffffffffffff)";
|
||||
}
|
||||
return "GOOGLE_LONGLONG(" + SimpleItoa(number) + ")";
|
||||
}
|
||||
|
||||
string DefaultValue(const FieldDescriptor* field) {
|
||||
switch (field->cpp_type()) {
|
||||
case FieldDescriptor::CPPTYPE_INT32:
|
||||
return Int32ToString(field->default_value_int32());
|
||||
case FieldDescriptor::CPPTYPE_UINT32:
|
||||
return SimpleItoa(field->default_value_uint32()) + "u";
|
||||
case FieldDescriptor::CPPTYPE_INT64:
|
||||
return Int64ToString(field->default_value_int64());
|
||||
case FieldDescriptor::CPPTYPE_UINT64:
|
||||
return "GOOGLE_ULONGLONG(" + SimpleItoa(field->default_value_uint64())+ ")";
|
||||
case FieldDescriptor::CPPTYPE_DOUBLE: {
|
||||
double value = field->default_value_double();
|
||||
if (value == std::numeric_limits<double>::infinity()) {
|
||||
return "::google::protobuf::internal::Infinity()";
|
||||
} else if (value == -std::numeric_limits<double>::infinity()) {
|
||||
return "-::google::protobuf::internal::Infinity()";
|
||||
} else if (value != value) {
|
||||
return "::google::protobuf::internal::NaN()";
|
||||
} else {
|
||||
return SimpleDtoa(value);
|
||||
}
|
||||
}
|
||||
case FieldDescriptor::CPPTYPE_FLOAT:
|
||||
{
|
||||
float value = field->default_value_float();
|
||||
if (value == std::numeric_limits<float>::infinity()) {
|
||||
return "static_cast<float>(::google::protobuf::internal::Infinity())";
|
||||
} else if (value == -std::numeric_limits<float>::infinity()) {
|
||||
return "static_cast<float>(-::google::protobuf::internal::Infinity())";
|
||||
} else if (value != value) {
|
||||
return "static_cast<float>(::google::protobuf::internal::NaN())";
|
||||
} else {
|
||||
string float_value = SimpleFtoa(value);
|
||||
// If floating point value contains a period (.) or an exponent
|
||||
// (either E or e), then append suffix 'f' to make it a float
|
||||
// literal.
|
||||
if (float_value.find_first_of(".eE") != string::npos) {
|
||||
float_value.push_back('f');
|
||||
}
|
||||
return float_value;
|
||||
}
|
||||
}
|
||||
case FieldDescriptor::CPPTYPE_BOOL:
|
||||
return field->default_value_bool() ? "true" : "false";
|
||||
case FieldDescriptor::CPPTYPE_ENUM:
|
||||
// Lazy: Generate a static_cast because we don't have a helper function
|
||||
// that constructs the full name of an enum value.
|
||||
return strings::Substitute(
|
||||
"static_cast< $0 >($1)",
|
||||
ClassName(field->enum_type(), true),
|
||||
Int32ToString(field->default_value_enum()->number()));
|
||||
case FieldDescriptor::CPPTYPE_STRING:
|
||||
return "\"" + EscapeTrigraphs(
|
||||
CEscape(field->default_value_string())) +
|
||||
"\"";
|
||||
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||
return "*" + FieldMessageTypeName(field) +
|
||||
"::internal_default_instance()";
|
||||
}
|
||||
// Can't actually get here; make compiler happy. (We could add a default
|
||||
// case above but then we wouldn't get the nice compiler warning when a
|
||||
// new type is added.)
|
||||
GOOGLE_LOG(FATAL) << "Can't get here.";
|
||||
return "";
|
||||
}
|
||||
|
||||
// Convert a file name into a valid identifier.
|
||||
string FilenameIdentifier(const string& filename) {
|
||||
string result;
|
||||
for (int i = 0; i < filename.size(); i++) {
|
||||
if (ascii_isalnum(filename[i])) {
|
||||
result.push_back(filename[i]);
|
||||
} else {
|
||||
// Not alphanumeric. To avoid any possibility of name conflicts we
|
||||
// use the hex code for the character.
|
||||
StrAppend(&result, "_", strings::Hex(static_cast<uint8>(filename[i])));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
string FileLevelNamespace(const string& filename) {
|
||||
return "protobuf_" + FilenameIdentifier(filename);
|
||||
}
|
||||
|
||||
// Return the qualified C++ name for a file level symbol.
|
||||
string QualifiedFileLevelSymbol(const string& package, const string& name) {
|
||||
if (package.empty()) {
|
||||
return StrCat("::", name);
|
||||
}
|
||||
return StrCat("::", DotsToColons(package), "::", name);
|
||||
}
|
||||
|
||||
// Escape C++ trigraphs by escaping question marks to \?
|
||||
string EscapeTrigraphs(const string& to_escape) {
|
||||
return StringReplace(to_escape, "?", "\\?", true);
|
||||
}
|
||||
|
||||
// Escaped function name to eliminate naming conflict.
|
||||
string SafeFunctionName(const Descriptor* descriptor,
|
||||
const FieldDescriptor* field,
|
||||
const string& prefix) {
|
||||
// Do not use FieldName() since it will escape keywords.
|
||||
string name = field->name();
|
||||
LowerString(&name);
|
||||
string function_name = prefix + name;
|
||||
if (descriptor->FindFieldByName(function_name)) {
|
||||
// Single underscore will also make it conflicting with the private data
|
||||
// member. We use double underscore to escape function names.
|
||||
function_name.append("__");
|
||||
} else if (kKeywords.count(name) > 0) {
|
||||
// If the field name is a keyword, we append the underscore back to keep it
|
||||
// consistent with other function names.
|
||||
function_name.append("_");
|
||||
}
|
||||
return function_name;
|
||||
}
|
||||
|
||||
|
||||
static bool HasMapFields(const Descriptor* descriptor) {
|
||||
for (int i = 0; i < descriptor->field_count(); ++i) {
|
||||
if (descriptor->field(i)->is_map()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < descriptor->nested_type_count(); ++i) {
|
||||
if (HasMapFields(descriptor->nested_type(i))) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool HasMapFields(const FileDescriptor* file) {
|
||||
for (int i = 0; i < file->message_type_count(); ++i) {
|
||||
if (HasMapFields(file->message_type(i))) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool HasEnumDefinitions(const Descriptor* message_type) {
|
||||
if (message_type->enum_type_count() > 0) return true;
|
||||
for (int i = 0; i < message_type->nested_type_count(); ++i) {
|
||||
if (HasEnumDefinitions(message_type->nested_type(i))) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool HasEnumDefinitions(const FileDescriptor* file) {
|
||||
if (file->enum_type_count() > 0) return true;
|
||||
for (int i = 0; i < file->message_type_count(); ++i) {
|
||||
if (HasEnumDefinitions(file->message_type(i))) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsStringOrMessage(const FieldDescriptor* field) {
|
||||
switch (field->cpp_type()) {
|
||||
case FieldDescriptor::CPPTYPE_INT32:
|
||||
case FieldDescriptor::CPPTYPE_INT64:
|
||||
case FieldDescriptor::CPPTYPE_UINT32:
|
||||
case FieldDescriptor::CPPTYPE_UINT64:
|
||||
case FieldDescriptor::CPPTYPE_DOUBLE:
|
||||
case FieldDescriptor::CPPTYPE_FLOAT:
|
||||
case FieldDescriptor::CPPTYPE_BOOL:
|
||||
case FieldDescriptor::CPPTYPE_ENUM:
|
||||
return false;
|
||||
case FieldDescriptor::CPPTYPE_STRING:
|
||||
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||
return true;
|
||||
}
|
||||
|
||||
GOOGLE_LOG(FATAL) << "Can't get here.";
|
||||
return false;
|
||||
}
|
||||
|
||||
FieldOptions::CType EffectiveStringCType(const FieldDescriptor* field) {
|
||||
GOOGLE_DCHECK(field->cpp_type() == FieldDescriptor::CPPTYPE_STRING);
|
||||
// Open-source protobuf release only supports STRING ctype.
|
||||
return FieldOptions::STRING;
|
||||
|
||||
}
|
||||
|
||||
bool IsAnyMessage(const FileDescriptor* descriptor) {
|
||||
return descriptor->name() == kAnyProtoFile;
|
||||
}
|
||||
|
||||
bool IsAnyMessage(const Descriptor* descriptor) {
|
||||
return descriptor->name() == kAnyMessageName &&
|
||||
descriptor->file()->name() == kAnyProtoFile;
|
||||
}
|
||||
|
||||
bool IsWellKnownMessage(const FileDescriptor* descriptor) {
|
||||
return !descriptor->name().compare(0, 16, kGoogleProtobufPrefix);
|
||||
}
|
||||
|
||||
enum Utf8CheckMode {
|
||||
STRICT = 0, // Parsing will fail if non UTF-8 data is in string fields.
|
||||
VERIFY = 1, // Only log an error but parsing will succeed.
|
||||
NONE = 2, // No UTF-8 check.
|
||||
};
|
||||
|
||||
// Which level of UTF-8 enforcemant is placed on this file.
|
||||
static Utf8CheckMode GetUtf8CheckMode(const FieldDescriptor* field,
|
||||
const Options& options) {
|
||||
if (field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3) {
|
||||
return STRICT;
|
||||
} else if (GetOptimizeFor(field->file(), options) !=
|
||||
FileOptions::LITE_RUNTIME) {
|
||||
return VERIFY;
|
||||
} else {
|
||||
return NONE;
|
||||
}
|
||||
}
|
||||
|
||||
static void GenerateUtf8CheckCode(const FieldDescriptor* field,
|
||||
const Options& options, bool for_parse,
|
||||
const std::map<string, string>& variables,
|
||||
const char* parameters,
|
||||
const char* strict_function,
|
||||
const char* verify_function,
|
||||
io::Printer* printer) {
|
||||
switch (GetUtf8CheckMode(field, options)) {
|
||||
case STRICT: {
|
||||
if (for_parse) {
|
||||
printer->Print("DO_(");
|
||||
}
|
||||
printer->Print(
|
||||
"::google::protobuf::internal::WireFormatLite::$function$(\n",
|
||||
"function", strict_function);
|
||||
printer->Indent();
|
||||
printer->Print(variables, parameters);
|
||||
if (for_parse) {
|
||||
printer->Print("::google::protobuf::internal::WireFormatLite::PARSE,\n");
|
||||
} else {
|
||||
printer->Print("::google::protobuf::internal::WireFormatLite::SERIALIZE,\n");
|
||||
}
|
||||
printer->Print("\"$full_name$\")", "full_name", field->full_name());
|
||||
if (for_parse) {
|
||||
printer->Print(")");
|
||||
}
|
||||
printer->Print(";\n");
|
||||
printer->Outdent();
|
||||
break;
|
||||
}
|
||||
case VERIFY: {
|
||||
printer->Print(
|
||||
"::google::protobuf::internal::WireFormat::$function$(\n",
|
||||
"function", verify_function);
|
||||
printer->Indent();
|
||||
printer->Print(variables, parameters);
|
||||
if (for_parse) {
|
||||
printer->Print("::google::protobuf::internal::WireFormat::PARSE,\n");
|
||||
} else {
|
||||
printer->Print("::google::protobuf::internal::WireFormat::SERIALIZE,\n");
|
||||
}
|
||||
printer->Print("\"$full_name$\");\n", "full_name", field->full_name());
|
||||
printer->Outdent();
|
||||
break;
|
||||
}
|
||||
case NONE:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void GenerateUtf8CheckCodeForString(const FieldDescriptor* field,
|
||||
const Options& options, bool for_parse,
|
||||
const std::map<string, string>& variables,
|
||||
const char* parameters,
|
||||
io::Printer* printer) {
|
||||
GenerateUtf8CheckCode(field, options, for_parse, variables, parameters,
|
||||
"VerifyUtf8String", "VerifyUTF8StringNamedField",
|
||||
printer);
|
||||
}
|
||||
|
||||
void GenerateUtf8CheckCodeForCord(const FieldDescriptor* field,
|
||||
const Options& options, bool for_parse,
|
||||
const std::map<string, string>& variables,
|
||||
const char* parameters,
|
||||
io::Printer* printer) {
|
||||
GenerateUtf8CheckCode(field, options, for_parse, variables, parameters,
|
||||
"VerifyUtf8Cord", "VerifyUTF8CordNamedField", printer);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
void Flatten(const Descriptor* descriptor,
|
||||
std::vector<const Descriptor*>* flatten) {
|
||||
for (int i = 0; i < descriptor->nested_type_count(); i++)
|
||||
Flatten(descriptor->nested_type(i), flatten);
|
||||
flatten->push_back(descriptor);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void FlattenMessagesInFile(const FileDescriptor* file,
|
||||
std::vector<const Descriptor*>* result) {
|
||||
for (int i = 0; i < file->message_type_count(); i++) {
|
||||
Flatten(file->message_type(i), result);
|
||||
}
|
||||
}
|
||||
|
||||
bool HasWeakFields(const Descriptor* descriptor) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool HasWeakFields(const FileDescriptor* file) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UsingImplicitWeakFields(const FileDescriptor* file,
|
||||
const Options& options) {
|
||||
return options.lite_implicit_weak_fields &&
|
||||
GetOptimizeFor(file, options) == FileOptions::LITE_RUNTIME;
|
||||
}
|
||||
|
||||
bool IsImplicitWeakField(const FieldDescriptor* field, const Options& options,
|
||||
SCCAnalyzer* scc_analyzer) {
|
||||
return UsingImplicitWeakFields(field->file(), options) &&
|
||||
field->type() == FieldDescriptor::TYPE_MESSAGE &&
|
||||
!field->is_required() && !field->is_map() &&
|
||||
field->containing_oneof() == NULL &&
|
||||
!IsWellKnownMessage(field->message_type()->file()) &&
|
||||
// We do not support implicit weak fields between messages in the same
|
||||
// strongly-connected component.
|
||||
scc_analyzer->GetSCC(field->containing_type()) !=
|
||||
scc_analyzer->GetSCC(field->message_type());
|
||||
}
|
||||
|
||||
struct CompareDescriptors {
|
||||
bool operator()(const Descriptor* a, const Descriptor* b) {
|
||||
return a->full_name() < b->full_name();
|
||||
}
|
||||
};
|
||||
|
||||
SCCAnalyzer::NodeData SCCAnalyzer::DFS(const Descriptor* descriptor) {
|
||||
// Must not have visited already.
|
||||
GOOGLE_DCHECK_EQ(cache_.count(descriptor), 0);
|
||||
|
||||
// Mark visited by inserting in map.
|
||||
NodeData& result = cache_[descriptor];
|
||||
// Initialize data structures.
|
||||
result.index = result.lowlink = index_++;
|
||||
stack_.push_back(descriptor);
|
||||
|
||||
// Recurse the fields / nodes in graph
|
||||
for (int i = 0; i < descriptor->field_count(); i++) {
|
||||
const Descriptor* child = descriptor->field(i)->message_type();
|
||||
if (child) {
|
||||
if (cache_.count(child) == 0) {
|
||||
// unexplored node
|
||||
NodeData child_data = DFS(child);
|
||||
result.lowlink = std::min(result.lowlink, child_data.lowlink);
|
||||
} else {
|
||||
NodeData child_data = cache_[child];
|
||||
if (child_data.scc == NULL) {
|
||||
// Still in the stack_ so we found a back edge
|
||||
result.lowlink = std::min(result.lowlink, child_data.index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (result.index == result.lowlink) {
|
||||
// This is the root of a strongly connected component
|
||||
SCC* scc = CreateSCC();
|
||||
while (true) {
|
||||
const Descriptor* scc_desc = stack_.back();
|
||||
scc->descriptors.push_back(scc_desc);
|
||||
// Remove from stack
|
||||
stack_.pop_back();
|
||||
cache_[scc_desc].scc = scc;
|
||||
|
||||
if (scc_desc == descriptor) break;
|
||||
}
|
||||
|
||||
// The order of descriptors is random and depends how this SCC was
|
||||
// discovered. In-order to ensure maximum stability we sort it by name.
|
||||
std::sort(scc->descriptors.begin(), scc->descriptors.end(),
|
||||
CompareDescriptors());
|
||||
AddChildren(scc);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void SCCAnalyzer::AddChildren(SCC* scc) {
|
||||
std::set<const SCC*> seen;
|
||||
for (int i = 0; i < scc->descriptors.size(); i++) {
|
||||
const Descriptor* descriptor = scc->descriptors[i];
|
||||
for (int j = 0; j < descriptor->field_count(); j++) {
|
||||
const Descriptor* child_msg = descriptor->field(j)->message_type();
|
||||
if (child_msg) {
|
||||
const SCC* child = GetSCC(child_msg);
|
||||
if (child == scc) continue;
|
||||
if (seen.insert(child).second) {
|
||||
scc->children.push_back(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MessageAnalysis SCCAnalyzer::GetSCCAnalysis(const SCC* scc) {
|
||||
if (analysis_cache_.count(scc)) return analysis_cache_[scc];
|
||||
MessageAnalysis result = MessageAnalysis();
|
||||
for (int i = 0; i < scc->descriptors.size(); i++) {
|
||||
const Descriptor* descriptor = scc->descriptors[i];
|
||||
if (descriptor->extension_range_count() > 0) {
|
||||
result.contains_extension = true;
|
||||
}
|
||||
for (int i = 0; i < descriptor->field_count(); i++) {
|
||||
const FieldDescriptor* field = descriptor->field(i);
|
||||
if (field->is_required()) {
|
||||
result.contains_required = true;
|
||||
}
|
||||
switch (field->type()) {
|
||||
case FieldDescriptor::TYPE_STRING:
|
||||
case FieldDescriptor::TYPE_BYTES: {
|
||||
if (field->options().ctype() == FieldOptions::CORD) {
|
||||
result.contains_cord = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FieldDescriptor::TYPE_GROUP:
|
||||
case FieldDescriptor::TYPE_MESSAGE: {
|
||||
const SCC* child = GetSCC(field->message_type());
|
||||
if (child != scc) {
|
||||
MessageAnalysis analysis = GetSCCAnalysis(child);
|
||||
result.contains_cord |= analysis.contains_cord;
|
||||
result.contains_extension |= analysis.contains_extension;
|
||||
if (!ShouldIgnoreRequiredFieldCheck(field, options_)) {
|
||||
result.contains_required |= analysis.contains_required;
|
||||
}
|
||||
} else {
|
||||
// This field points back into the same SCC hence the messages
|
||||
// in the SCC are recursive. Note if SCC contains more than two
|
||||
// nodes it has to be recursive, however this test also works for
|
||||
// a single node that is recursive.
|
||||
result.is_recursive = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// We deliberately only insert the result here. After we contracted the SCC
|
||||
// in the graph, the graph should be a DAG. Hence we shouldn't need to mark
|
||||
// nodes visited as we can never return to them. By inserting them here
|
||||
// we will go in an infinite loop if the SCC is not correct.
|
||||
return analysis_cache_[scc] = result;
|
||||
}
|
||||
|
||||
void ListAllFields(const Descriptor* d,
|
||||
std::vector<const FieldDescriptor*>* fields) {
|
||||
// Collect sub messages
|
||||
for (int i = 0; i < d->nested_type_count(); i++) {
|
||||
ListAllFields(d->nested_type(i), fields);
|
||||
}
|
||||
// Collect message level extensions.
|
||||
for (int i = 0; i < d->extension_count(); i++) {
|
||||
fields->push_back(d->extension(i));
|
||||
}
|
||||
// Add types of fields necessary
|
||||
for (int i = 0; i < d->field_count(); i++) {
|
||||
fields->push_back(d->field(i));
|
||||
}
|
||||
}
|
||||
|
||||
void ListAllFields(const FileDescriptor* d,
|
||||
std::vector<const FieldDescriptor*>* fields) {
|
||||
// Collect file level message.
|
||||
for (int i = 0; i < d->message_type_count(); i++) {
|
||||
ListAllFields(d->message_type(i), fields);
|
||||
}
|
||||
// Collect message level extensions.
|
||||
for (int i = 0; i < d->extension_count(); i++) {
|
||||
fields->push_back(d->extension(i));
|
||||
}
|
||||
}
|
||||
|
||||
void ListAllTypesForServices(const FileDescriptor* fd,
|
||||
std::vector<const Descriptor*>* types) {
|
||||
for (int i = 0; i < fd->service_count(); i++) {
|
||||
const ServiceDescriptor* sd = fd->service(i);
|
||||
for (int j = 0; j < sd->method_count(); j++) {
|
||||
const MethodDescriptor* method = sd->method(j);
|
||||
types->push_back(method->input_type());
|
||||
types->push_back(method->output_type());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace cpp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
461
Common/ProtocolBuffer/google/protobuf/compiler/cpp/cpp_helpers.h
Normal file
461
Common/ProtocolBuffer/google/protobuf/compiler/cpp/cpp_helpers.h
Normal file
@ -0,0 +1,461 @@
|
||||
// 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.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__
|
||||
#define GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <google/protobuf/compiler/cpp/cpp_options.h>
|
||||
#include <google/protobuf/compiler/code_generator.h>
|
||||
#include <google/protobuf/descriptor.pb.h>
|
||||
#include <google/protobuf/io/printer.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
|
||||
// Commonly-used separator comments. Thick is a line of '=', thin is a line
|
||||
// of '-'.
|
||||
extern const char kThickSeparator[];
|
||||
extern const char kThinSeparator[];
|
||||
|
||||
|
||||
// Name space of the proto file. This namespace is such that the string
|
||||
// "<namespace>::some_name" is the correct fully qualified namespace.
|
||||
// This means if the package is empty the namespace is "", and otherwise
|
||||
// the namespace is "::foo::bar::...::baz" without trailing semi-colons.
|
||||
string Namespace(const string& package);
|
||||
inline string Namespace(const FileDescriptor* d) {
|
||||
return Namespace(d->package());
|
||||
}
|
||||
template <typename Desc>
|
||||
string Namespace(const Desc* d) {
|
||||
return Namespace(d->file());
|
||||
}
|
||||
|
||||
// Returns true if it's safe to reset "field" to zero.
|
||||
bool CanInitializeByZeroing(const FieldDescriptor* field);
|
||||
|
||||
string ClassName(const Descriptor* descriptor);
|
||||
string ClassName(const EnumDescriptor* enum_descriptor);
|
||||
template <typename Desc>
|
||||
string QualifiedClassName(const Desc* d) {
|
||||
return Namespace(d) + "::" + ClassName(d);
|
||||
}
|
||||
|
||||
// DEPRECATED just use ClassName or QualifiedClassName, a boolean is very
|
||||
// unreadable at the callsite.
|
||||
// Returns the non-nested type name for the given type. If "qualified" is
|
||||
// true, prefix the type with the full namespace. For example, if you had:
|
||||
// package foo.bar;
|
||||
// message Baz { message Qux {} }
|
||||
// Then the qualified ClassName for Qux would be:
|
||||
// ::foo::bar::Baz_Qux
|
||||
// While the non-qualified version would be:
|
||||
// Baz_Qux
|
||||
inline string ClassName(const Descriptor* descriptor, bool qualified) {
|
||||
return qualified ? QualifiedClassName(descriptor) : ClassName(descriptor);
|
||||
}
|
||||
|
||||
inline string ClassName(const EnumDescriptor* descriptor, bool qualified) {
|
||||
return qualified ? QualifiedClassName(descriptor) : ClassName(descriptor);
|
||||
}
|
||||
|
||||
// Fully qualified name of the default_instance of this message.
|
||||
string DefaultInstanceName(const Descriptor* descriptor);
|
||||
|
||||
// Returns the name of a no-op function that we can call to introduce a linker
|
||||
// dependency on the given message type. This is used to implement implicit weak
|
||||
// fields.
|
||||
string ReferenceFunctionName(const Descriptor* descriptor);
|
||||
|
||||
// Name of the base class: google::protobuf::Message or google::protobuf::MessageLite.
|
||||
string SuperClassName(const Descriptor* descriptor, const Options& options);
|
||||
|
||||
// Get the (unqualified) name that should be used for this field in C++ code.
|
||||
// The name is coerced to lower-case to emulate proto1 behavior. People
|
||||
// should be using lowercase-with-underscores style for proto field names
|
||||
// anyway, so normally this just returns field->name().
|
||||
string FieldName(const FieldDescriptor* field);
|
||||
|
||||
// Get the sanitized name that should be used for the given enum in C++ code.
|
||||
string EnumValueName(const EnumValueDescriptor* enum_value);
|
||||
|
||||
// Returns an estimate of the compiler's alignment for the field. This
|
||||
// can't guarantee to be correct because the generated code could be compiled on
|
||||
// different systems with different alignment rules. The estimates below assume
|
||||
// 64-bit pointers.
|
||||
int EstimateAlignmentSize(const FieldDescriptor* field);
|
||||
|
||||
// Get the unqualified name that should be used for a field's field
|
||||
// number constant.
|
||||
string FieldConstantName(const FieldDescriptor *field);
|
||||
|
||||
// Returns the scope where the field was defined (for extensions, this is
|
||||
// different from the message type to which the field applies).
|
||||
inline const Descriptor* FieldScope(const FieldDescriptor* field) {
|
||||
return field->is_extension() ?
|
||||
field->extension_scope() : field->containing_type();
|
||||
}
|
||||
|
||||
// Returns the fully-qualified type name field->message_type(). Usually this
|
||||
// is just ClassName(field->message_type(), true);
|
||||
string FieldMessageTypeName(const FieldDescriptor* field);
|
||||
|
||||
// Strips ".proto" or ".protodevel" from the end of a filename.
|
||||
LIBPROTOC_EXPORT string StripProto(const string& filename);
|
||||
|
||||
// Get the C++ type name for a primitive type (e.g. "double", "::google::protobuf::int32", etc.).
|
||||
// Note: non-built-in type names will be qualified, meaning they will start
|
||||
// with a ::. If you are using the type as a template parameter, you will
|
||||
// need to insure there is a space between the < and the ::, because the
|
||||
// ridiculous C++ standard defines "<:" to be a synonym for "[".
|
||||
const char* PrimitiveTypeName(FieldDescriptor::CppType type);
|
||||
|
||||
// Get the declared type name in CamelCase format, as is used e.g. for the
|
||||
// methods of WireFormat. For example, TYPE_INT32 becomes "Int32".
|
||||
const char* DeclaredTypeMethodName(FieldDescriptor::Type type);
|
||||
|
||||
// Return the code that evaluates to the number when compiled.
|
||||
string Int32ToString(int number);
|
||||
|
||||
// Return the code that evaluates to the number when compiled.
|
||||
string Int64ToString(int64 number);
|
||||
|
||||
// Get code that evaluates to the field's default value.
|
||||
string DefaultValue(const FieldDescriptor* field);
|
||||
|
||||
// Convert a file name into a valid identifier.
|
||||
string FilenameIdentifier(const string& filename);
|
||||
|
||||
// For each .proto file generates a unique namespace. In this namespace global
|
||||
// definitions are put to prevent collisions.
|
||||
string FileLevelNamespace(const string& filename);
|
||||
inline string FileLevelNamespace(const FileDescriptor* file) {
|
||||
return FileLevelNamespace(file->name());
|
||||
}
|
||||
inline string FileLevelNamespace(const Descriptor* d) {
|
||||
return FileLevelNamespace(d->file());
|
||||
}
|
||||
|
||||
// Return the qualified C++ name for a file level symbol.
|
||||
string QualifiedFileLevelSymbol(const string& package, const string& name);
|
||||
|
||||
// Escape C++ trigraphs by escaping question marks to \?
|
||||
string EscapeTrigraphs(const string& to_escape);
|
||||
|
||||
// Escaped function name to eliminate naming conflict.
|
||||
string SafeFunctionName(const Descriptor* descriptor,
|
||||
const FieldDescriptor* field,
|
||||
const string& prefix);
|
||||
|
||||
// Returns true if unknown fields are always preserved after parsing.
|
||||
inline bool AlwaysPreserveUnknownFields(const FileDescriptor* file) {
|
||||
return file->syntax() != FileDescriptor::SYNTAX_PROTO3;
|
||||
}
|
||||
|
||||
// Returns true if unknown fields are preserved after parsing.
|
||||
inline bool AlwaysPreserveUnknownFields(const Descriptor* message) {
|
||||
return AlwaysPreserveUnknownFields(message->file());
|
||||
}
|
||||
|
||||
// Returns true if generated messages have public unknown fields accessors
|
||||
inline bool PublicUnknownFieldsAccessors(const Descriptor* message) {
|
||||
return message->file()->syntax() != FileDescriptor::SYNTAX_PROTO3;
|
||||
}
|
||||
|
||||
// Returns the optimize mode for <file>, respecting <options.enforce_lite>.
|
||||
::google::protobuf::FileOptions_OptimizeMode GetOptimizeFor(
|
||||
const FileDescriptor* file, const Options& options);
|
||||
|
||||
// Determines whether unknown fields will be stored in an UnknownFieldSet or
|
||||
// a string.
|
||||
inline bool UseUnknownFieldSet(const FileDescriptor* file,
|
||||
const Options& options) {
|
||||
return GetOptimizeFor(file, options) != FileOptions::LITE_RUNTIME;
|
||||
}
|
||||
|
||||
|
||||
// Does the file have any map fields, necessitating the file to include
|
||||
// map_field_inl.h and map.h.
|
||||
bool HasMapFields(const FileDescriptor* file);
|
||||
|
||||
// Does this file have any enum type definitions?
|
||||
bool HasEnumDefinitions(const FileDescriptor* file);
|
||||
|
||||
// Does this file have generated parsing, serialization, and other
|
||||
// standard methods for which reflection-based fallback implementations exist?
|
||||
inline bool HasGeneratedMethods(const FileDescriptor* file,
|
||||
const Options& options) {
|
||||
return GetOptimizeFor(file, options) != FileOptions::CODE_SIZE;
|
||||
}
|
||||
|
||||
// Do message classes in this file have descriptor and reflection methods?
|
||||
inline bool HasDescriptorMethods(const FileDescriptor* file,
|
||||
const Options& options) {
|
||||
return GetOptimizeFor(file, options) != FileOptions::LITE_RUNTIME;
|
||||
}
|
||||
|
||||
// Should we generate generic services for this file?
|
||||
inline bool HasGenericServices(const FileDescriptor* file,
|
||||
const Options& options) {
|
||||
return file->service_count() > 0 &&
|
||||
GetOptimizeFor(file, options) != FileOptions::LITE_RUNTIME &&
|
||||
file->options().cc_generic_services();
|
||||
}
|
||||
|
||||
// Should we generate a separate, super-optimized code path for serializing to
|
||||
// flat arrays? We don't do this in Lite mode because we'd rather reduce code
|
||||
// size.
|
||||
inline bool HasFastArraySerialization(const FileDescriptor* file,
|
||||
const Options& options) {
|
||||
return GetOptimizeFor(file, options) == FileOptions::SPEED;
|
||||
}
|
||||
|
||||
|
||||
inline bool IsMapEntryMessage(const Descriptor* descriptor) {
|
||||
return descriptor->options().map_entry();
|
||||
}
|
||||
|
||||
// Returns true if the field's CPPTYPE is string or message.
|
||||
bool IsStringOrMessage(const FieldDescriptor* field);
|
||||
|
||||
// For a string field, returns the effective ctype. If the actual ctype is
|
||||
// not supported, returns the default of STRING.
|
||||
FieldOptions::CType EffectiveStringCType(const FieldDescriptor* field);
|
||||
|
||||
string UnderscoresToCamelCase(const string& input, bool cap_next_letter);
|
||||
|
||||
inline bool HasFieldPresence(const FileDescriptor* file) {
|
||||
return file->syntax() != FileDescriptor::SYNTAX_PROTO3;
|
||||
}
|
||||
|
||||
// Returns true if 'enum' semantics are such that unknown values are preserved
|
||||
// in the enum field itself, rather than going to the UnknownFieldSet.
|
||||
inline bool HasPreservingUnknownEnumSemantics(const FileDescriptor* file) {
|
||||
return file->syntax() == FileDescriptor::SYNTAX_PROTO3;
|
||||
}
|
||||
|
||||
inline bool SupportsArenas(const FileDescriptor* file) {
|
||||
return file->options().cc_enable_arenas();
|
||||
}
|
||||
|
||||
inline bool SupportsArenas(const Descriptor* desc) {
|
||||
return SupportsArenas(desc->file());
|
||||
}
|
||||
|
||||
inline bool SupportsArenas(const FieldDescriptor* field) {
|
||||
return SupportsArenas(field->file());
|
||||
}
|
||||
|
||||
inline bool IsCrossFileMessage(const FieldDescriptor* field) {
|
||||
return field->type() == FieldDescriptor::TYPE_MESSAGE &&
|
||||
field->message_type()->file() != field->file();
|
||||
}
|
||||
|
||||
inline string MessageCreateFunction(const Descriptor* d) {
|
||||
return SupportsArenas(d) ? "CreateMessage" : "Create";
|
||||
}
|
||||
|
||||
inline string MakeDefaultName(const FieldDescriptor* field) {
|
||||
return "_i_give_permission_to_break_this_code_default_" + FieldName(field) +
|
||||
"_";
|
||||
}
|
||||
|
||||
bool IsAnyMessage(const FileDescriptor* descriptor);
|
||||
bool IsAnyMessage(const Descriptor* descriptor);
|
||||
|
||||
bool IsWellKnownMessage(const FileDescriptor* descriptor);
|
||||
|
||||
void GenerateUtf8CheckCodeForString(const FieldDescriptor* field,
|
||||
const Options& options, bool for_parse,
|
||||
const std::map<string, string>& variables,
|
||||
const char* parameters,
|
||||
io::Printer* printer);
|
||||
|
||||
void GenerateUtf8CheckCodeForCord(const FieldDescriptor* field,
|
||||
const Options& options, bool for_parse,
|
||||
const std::map<string, string>& variables,
|
||||
const char* parameters, io::Printer* printer);
|
||||
|
||||
inline ::google::protobuf::FileOptions_OptimizeMode GetOptimizeFor(
|
||||
const FileDescriptor* file, const Options& options) {
|
||||
return options.enforce_lite
|
||||
? FileOptions::LITE_RUNTIME
|
||||
: file->options().optimize_for();
|
||||
}
|
||||
|
||||
// This orders the messages in a .pb.cc as it's outputted by file.cc
|
||||
void FlattenMessagesInFile(const FileDescriptor* file,
|
||||
std::vector<const Descriptor*>* result);
|
||||
inline std::vector<const Descriptor*> FlattenMessagesInFile(
|
||||
const FileDescriptor* file) {
|
||||
std::vector<const Descriptor*> result;
|
||||
FlattenMessagesInFile(file, &result);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool HasWeakFields(const Descriptor* desc);
|
||||
bool HasWeakFields(const FileDescriptor* desc);
|
||||
|
||||
// Returns true if the "required" restriction check should be ignored for the
|
||||
// given field.
|
||||
inline static bool ShouldIgnoreRequiredFieldCheck(const FieldDescriptor* field,
|
||||
const Options& options) {
|
||||
return false;
|
||||
}
|
||||
|
||||
class LIBPROTOC_EXPORT NamespaceOpener {
|
||||
public:
|
||||
explicit NamespaceOpener(io::Printer* printer) : printer_(printer) {}
|
||||
NamespaceOpener(const string& name, io::Printer* printer)
|
||||
: printer_(printer) {
|
||||
ChangeTo(name);
|
||||
}
|
||||
~NamespaceOpener() { ChangeTo(""); }
|
||||
|
||||
void ChangeTo(const string& name) {
|
||||
std::vector<string> new_stack_ =
|
||||
Split(name, "::", true);
|
||||
int len = std::min(name_stack_.size(), new_stack_.size());
|
||||
int common_idx = 0;
|
||||
while (common_idx < len) {
|
||||
if (name_stack_[common_idx] != new_stack_[common_idx]) break;
|
||||
common_idx++;
|
||||
}
|
||||
for (int i = name_stack_.size() - 1; i >= common_idx; i--) {
|
||||
printer_->Print("} // namespace $ns$\n", "ns", name_stack_[i]);
|
||||
}
|
||||
name_stack_.swap(new_stack_);
|
||||
for (int i = common_idx; i < name_stack_.size(); i++) {
|
||||
printer_->Print("namespace $ns$ {\n", "ns", name_stack_[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
io::Printer* printer_;
|
||||
std::vector<string> name_stack_;
|
||||
};
|
||||
|
||||
// Description of each strongly connected component. Note that the order
|
||||
// of both the descriptors in this SCC and the order of children is
|
||||
// deterministic.
|
||||
struct SCC {
|
||||
std::vector<const Descriptor*> descriptors;
|
||||
std::vector<const SCC*> children;
|
||||
|
||||
const Descriptor* GetRepresentative() const { return descriptors[0]; }
|
||||
};
|
||||
|
||||
struct MessageAnalysis {
|
||||
bool is_recursive;
|
||||
bool contains_cord;
|
||||
bool contains_extension;
|
||||
bool contains_required;
|
||||
};
|
||||
|
||||
// This class is used in FileGenerator, to ensure linear instead of
|
||||
// quadratic performance, if we do this per message we would get O(V*(V+E)).
|
||||
// Logically this is just only used in message.cc, but in the header for
|
||||
// FileGenerator to help share it.
|
||||
class LIBPROTOC_EXPORT SCCAnalyzer {
|
||||
public:
|
||||
explicit SCCAnalyzer(const Options& options) : options_(options), index_(0) {}
|
||||
~SCCAnalyzer() {
|
||||
for (int i = 0; i < garbage_bin_.size(); i++) delete garbage_bin_[i];
|
||||
}
|
||||
|
||||
const SCC* GetSCC(const Descriptor* descriptor) {
|
||||
if (cache_.count(descriptor)) return cache_[descriptor].scc;
|
||||
return DFS(descriptor).scc;
|
||||
}
|
||||
|
||||
MessageAnalysis GetSCCAnalysis(const SCC* scc);
|
||||
|
||||
bool HasRequiredFields(const Descriptor* descriptor) {
|
||||
MessageAnalysis result = GetSCCAnalysis(GetSCC(descriptor));
|
||||
return result.contains_required || result.contains_extension;
|
||||
}
|
||||
|
||||
private:
|
||||
struct NodeData {
|
||||
const SCC* scc; // if null it means its still on the stack
|
||||
int index;
|
||||
int lowlink;
|
||||
};
|
||||
|
||||
Options options_;
|
||||
std::map<const Descriptor*, NodeData> cache_;
|
||||
std::map<const SCC*, MessageAnalysis> analysis_cache_;
|
||||
std::vector<const Descriptor*> stack_;
|
||||
int index_;
|
||||
std::vector<SCC*> garbage_bin_;
|
||||
|
||||
SCC* CreateSCC() {
|
||||
garbage_bin_.push_back(new SCC());
|
||||
return garbage_bin_.back();
|
||||
}
|
||||
|
||||
// Tarjan's Strongly Connected Components algo
|
||||
NodeData DFS(const Descriptor* descriptor);
|
||||
|
||||
// Add the SCC's that are children of this SCC to its children.
|
||||
void AddChildren(SCC* scc);
|
||||
};
|
||||
|
||||
void ListAllFields(const Descriptor* d,
|
||||
std::vector<const FieldDescriptor*>* fields);
|
||||
void ListAllFields(const FileDescriptor* d,
|
||||
std::vector<const FieldDescriptor*>* fields);
|
||||
void ListAllTypesForServices(const FileDescriptor* fd,
|
||||
std::vector<const Descriptor*>* types);
|
||||
|
||||
// Indicates whether we should use implicit weak fields for this file.
|
||||
bool UsingImplicitWeakFields(const FileDescriptor* file,
|
||||
const Options& options);
|
||||
|
||||
// Indicates whether to treat this field as implicitly weak.
|
||||
bool IsImplicitWeakField(const FieldDescriptor* field, const Options& options,
|
||||
SCCAnalyzer* scc_analyzer);
|
||||
|
||||
} // namespace cpp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__
|
@ -0,0 +1,436 @@
|
||||
// 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/compiler/cpp/cpp_map_field.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
|
||||
#include <google/protobuf/io/printer.h>
|
||||
#include <google/protobuf/wire_format.h>
|
||||
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
|
||||
bool IsProto3Field(const FieldDescriptor* field_descriptor) {
|
||||
const FileDescriptor* file_descriptor = field_descriptor->file();
|
||||
return file_descriptor->syntax() == FileDescriptor::SYNTAX_PROTO3;
|
||||
}
|
||||
|
||||
void SetMessageVariables(const FieldDescriptor* descriptor,
|
||||
std::map<string, string>* variables,
|
||||
const Options& options) {
|
||||
SetCommonFieldVariables(descriptor, variables, options);
|
||||
(*variables)["type"] = ClassName(descriptor->message_type(), false);
|
||||
(*variables)["file_namespace"] =
|
||||
FileLevelNamespace(descriptor->file()->name());
|
||||
(*variables)["stream_writer"] =
|
||||
(*variables)["declared_type"] +
|
||||
(HasFastArraySerialization(descriptor->message_type()->file(), options)
|
||||
? "MaybeToArray"
|
||||
: "");
|
||||
(*variables)["full_name"] = descriptor->full_name();
|
||||
|
||||
const FieldDescriptor* key =
|
||||
descriptor->message_type()->FindFieldByName("key");
|
||||
const FieldDescriptor* val =
|
||||
descriptor->message_type()->FindFieldByName("value");
|
||||
(*variables)["key_cpp"] = PrimitiveTypeName(key->cpp_type());
|
||||
switch (val->cpp_type()) {
|
||||
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||
(*variables)["val_cpp"] = FieldMessageTypeName(val);
|
||||
(*variables)["wrapper"] = "EntryWrapper";
|
||||
break;
|
||||
case FieldDescriptor::CPPTYPE_ENUM:
|
||||
(*variables)["val_cpp"] = ClassName(val->enum_type(), true);
|
||||
(*variables)["wrapper"] = "EnumEntryWrapper";
|
||||
break;
|
||||
default:
|
||||
(*variables)["val_cpp"] = PrimitiveTypeName(val->cpp_type());
|
||||
(*variables)["wrapper"] = "EntryWrapper";
|
||||
}
|
||||
(*variables)["key_wire_type"] =
|
||||
"::google::protobuf::internal::WireFormatLite::TYPE_" +
|
||||
ToUpper(DeclaredTypeMethodName(key->type()));
|
||||
(*variables)["val_wire_type"] =
|
||||
"::google::protobuf::internal::WireFormatLite::TYPE_" +
|
||||
ToUpper(DeclaredTypeMethodName(val->type()));
|
||||
(*variables)["map_classname"] = ClassName(descriptor->message_type(), false);
|
||||
(*variables)["number"] = SimpleItoa(descriptor->number());
|
||||
(*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));
|
||||
|
||||
if (HasDescriptorMethods(descriptor->file(), options)) {
|
||||
(*variables)["lite"] = "";
|
||||
} else {
|
||||
(*variables)["lite"] = "Lite";
|
||||
}
|
||||
|
||||
if (!IsProto3Field(descriptor) &&
|
||||
val->type() == FieldDescriptor::TYPE_ENUM) {
|
||||
const EnumValueDescriptor* default_value = val->default_value_enum();
|
||||
(*variables)["default_enum_value"] = Int32ToString(default_value->number());
|
||||
} else {
|
||||
(*variables)["default_enum_value"] = "0";
|
||||
}
|
||||
}
|
||||
|
||||
MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor,
|
||||
const Options& options)
|
||||
: FieldGenerator(options), descriptor_(descriptor) {
|
||||
SetMessageVariables(descriptor, &variables_, options);
|
||||
}
|
||||
|
||||
MapFieldGenerator::~MapFieldGenerator() {}
|
||||
|
||||
void MapFieldGenerator::
|
||||
GeneratePrivateMembers(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"::google::protobuf::internal::MapField$lite$<\n"
|
||||
" $map_classname$,\n"
|
||||
" $key_cpp$, $val_cpp$,\n"
|
||||
" $key_wire_type$,\n"
|
||||
" $val_wire_type$,\n"
|
||||
" $default_enum_value$ > $name$_;\n");
|
||||
}
|
||||
|
||||
void MapFieldGenerator::
|
||||
GenerateAccessorDeclarations(io::Printer* printer) const {
|
||||
printer->Print(
|
||||
variables_,
|
||||
"$deprecated_attr$const ::google::protobuf::Map< $key_cpp$, $val_cpp$ >&\n"
|
||||
" $name$() const;\n");
|
||||
printer->Annotate("name", descriptor_);
|
||||
printer->Print(variables_,
|
||||
"$deprecated_attr$::google::protobuf::Map< $key_cpp$, $val_cpp$ >*\n"
|
||||
" ${$mutable_$name$$}$();\n");
|
||||
printer->Annotate("{", "}", descriptor_);
|
||||
}
|
||||
|
||||
void MapFieldGenerator::
|
||||
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"inline const ::google::protobuf::Map< $key_cpp$, $val_cpp$ >&\n"
|
||||
"$classname$::$name$() const {\n"
|
||||
" // @@protoc_insertion_point(field_map:$full_name$)\n"
|
||||
" return $name$_.GetMap();\n"
|
||||
"}\n"
|
||||
"inline ::google::protobuf::Map< $key_cpp$, $val_cpp$ >*\n"
|
||||
"$classname$::mutable_$name$() {\n"
|
||||
" // @@protoc_insertion_point(field_mutable_map:$full_name$)\n"
|
||||
" return $name$_.MutableMap();\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void MapFieldGenerator::
|
||||
GenerateClearingCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "$name$_.Clear();\n");
|
||||
}
|
||||
|
||||
void MapFieldGenerator::
|
||||
GenerateMergingCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n");
|
||||
}
|
||||
|
||||
void MapFieldGenerator::
|
||||
GenerateSwappingCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "$name$_.Swap(&other->$name$_);\n");
|
||||
}
|
||||
|
||||
void MapFieldGenerator::
|
||||
GenerateCopyConstructorCode(io::Printer* printer) const {
|
||||
GenerateConstructorCode(printer);
|
||||
GenerateMergingCode(printer);
|
||||
}
|
||||
|
||||
void MapFieldGenerator::
|
||||
GenerateMergeFromCodedStream(io::Printer* printer) const {
|
||||
const FieldDescriptor* key_field =
|
||||
descriptor_->message_type()->FindFieldByName("key");
|
||||
const FieldDescriptor* value_field =
|
||||
descriptor_->message_type()->FindFieldByName("value");
|
||||
bool using_entry = false;
|
||||
string key;
|
||||
string value;
|
||||
if (IsProto3Field(descriptor_) ||
|
||||
value_field->type() != FieldDescriptor::TYPE_ENUM) {
|
||||
printer->Print(
|
||||
variables_,
|
||||
"$map_classname$::Parser< ::google::protobuf::internal::MapField$lite$<\n"
|
||||
" $map_classname$,\n"
|
||||
" $key_cpp$, $val_cpp$,\n"
|
||||
" $key_wire_type$,\n"
|
||||
" $val_wire_type$,\n"
|
||||
" $default_enum_value$ >,\n"
|
||||
" ::google::protobuf::Map< $key_cpp$, $val_cpp$ > >"
|
||||
" parser(&$name$_);\n"
|
||||
"DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(\n"
|
||||
" input, &parser));\n");
|
||||
key = "parser.key()";
|
||||
value = "parser.value()";
|
||||
} else {
|
||||
using_entry = true;
|
||||
key = "entry->key()";
|
||||
value = "entry->value()";
|
||||
printer->Print(variables_,
|
||||
"::std::unique_ptr<$map_classname$> entry($name$_.NewEntry());\n");
|
||||
printer->Print(variables_,
|
||||
"{\n"
|
||||
" ::std::string data;\n"
|
||||
" DO_(::google::protobuf::internal::WireFormatLite::ReadString(input, &data));\n"
|
||||
" DO_(entry->ParseFromString(data));\n"
|
||||
" if ($val_cpp$_IsValid(*entry->mutable_value())) {\n"
|
||||
" (*mutable_$name$())[entry->key()] =\n"
|
||||
" static_cast< $val_cpp$ >(*entry->mutable_value());\n"
|
||||
" } else {\n");
|
||||
if (HasDescriptorMethods(descriptor_->file(), options_)) {
|
||||
printer->Print(variables_,
|
||||
" mutable_unknown_fields()"
|
||||
"->AddLengthDelimited($number$, data);\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
" unknown_fields_stream.WriteVarint32($tag$u);\n"
|
||||
" unknown_fields_stream.WriteVarint32(\n"
|
||||
" static_cast< ::google::protobuf::uint32>(data.size()));\n"
|
||||
" unknown_fields_stream.WriteString(data);\n");
|
||||
}
|
||||
|
||||
printer->Print(variables_,
|
||||
" }\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
if (key_field->type() == FieldDescriptor::TYPE_STRING) {
|
||||
GenerateUtf8CheckCodeForString(
|
||||
key_field, options_, true, variables_,
|
||||
StrCat(key, ".data(), static_cast<int>(", key, ".length()),\n").data(),
|
||||
printer);
|
||||
}
|
||||
if (value_field->type() == FieldDescriptor::TYPE_STRING) {
|
||||
GenerateUtf8CheckCodeForString(
|
||||
value_field, options_, true, variables_,
|
||||
StrCat(value, ".data(), static_cast<int>(", value, ".length()),\n")
|
||||
.data(),
|
||||
printer);
|
||||
}
|
||||
|
||||
// If entry is allocated by arena, its desctructor should be avoided.
|
||||
if (using_entry && SupportsArenas(descriptor_)) {
|
||||
printer->Print(variables_,
|
||||
"if (entry->GetArena() != NULL) entry.release();\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void GenerateSerializationLoop(io::Printer* printer,
|
||||
const std::map<string, string>& variables,
|
||||
bool supports_arenas,
|
||||
const string& utf8_check,
|
||||
const string& loop_header,
|
||||
const string& ptr,
|
||||
bool loop_via_iterators) {
|
||||
printer->Print(variables,
|
||||
StrCat("::std::unique_ptr<$map_classname$> entry;\n",
|
||||
loop_header, " {\n").c_str());
|
||||
printer->Indent();
|
||||
|
||||
printer->Print(variables, StrCat(
|
||||
"entry.reset($name$_.New$wrapper$(\n"
|
||||
" ", ptr, "->first, ", ptr, "->second));\n"
|
||||
"$write_entry$;\n").c_str());
|
||||
|
||||
// If entry is allocated by arena, its desctructor should be avoided.
|
||||
if (supports_arenas) {
|
||||
printer->Print(
|
||||
"if (entry->GetArena() != NULL) {\n"
|
||||
" entry.release();\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
if (!utf8_check.empty()) {
|
||||
// If loop_via_iterators is true then ptr is actually an iterator, and we
|
||||
// create a pointer by prefixing it with "&*".
|
||||
printer->Print(
|
||||
StrCat(utf8_check, "(", (loop_via_iterators ? "&*" : ""), ptr, ");\n")
|
||||
.c_str());
|
||||
}
|
||||
|
||||
printer->Outdent();
|
||||
printer->Print(
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void MapFieldGenerator::
|
||||
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
|
||||
std::map<string, string> variables(variables_);
|
||||
variables["write_entry"] = "::google::protobuf::internal::WireFormatLite::Write" +
|
||||
variables["stream_writer"] + "(\n " +
|
||||
variables["number"] + ", *entry, output)";
|
||||
variables["deterministic"] = "output->IsSerializationDeterministic()";
|
||||
GenerateSerializeWithCachedSizes(printer, variables);
|
||||
}
|
||||
|
||||
void MapFieldGenerator::
|
||||
GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
|
||||
std::map<string, string> variables(variables_);
|
||||
variables["write_entry"] =
|
||||
"target = ::google::protobuf::internal::WireFormatLite::\n"
|
||||
" InternalWrite" + variables["declared_type"] +
|
||||
"NoVirtualToArray(\n " + variables["number"] +
|
||||
", *entry, deterministic, target);\n";
|
||||
variables["deterministic"] = "deterministic";
|
||||
GenerateSerializeWithCachedSizes(printer, variables);
|
||||
}
|
||||
|
||||
void MapFieldGenerator::GenerateSerializeWithCachedSizes(
|
||||
io::Printer* printer, const std::map<string, string>& variables) const {
|
||||
printer->Print(variables,
|
||||
"if (!this->$name$().empty()) {\n");
|
||||
printer->Indent();
|
||||
const FieldDescriptor* key_field =
|
||||
descriptor_->message_type()->FindFieldByName("key");
|
||||
const FieldDescriptor* value_field =
|
||||
descriptor_->message_type()->FindFieldByName("value");
|
||||
const bool string_key = key_field->type() == FieldDescriptor::TYPE_STRING;
|
||||
const bool string_value = value_field->type() == FieldDescriptor::TYPE_STRING;
|
||||
|
||||
printer->Print(variables,
|
||||
"typedef ::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_pointer\n"
|
||||
" ConstPtr;\n");
|
||||
if (string_key) {
|
||||
printer->Print(variables,
|
||||
"typedef ConstPtr SortItem;\n"
|
||||
"typedef ::google::protobuf::internal::"
|
||||
"CompareByDerefFirst<SortItem> Less;\n");
|
||||
} else {
|
||||
printer->Print(variables,
|
||||
"typedef ::google::protobuf::internal::SortItem< $key_cpp$, ConstPtr > "
|
||||
"SortItem;\n"
|
||||
"typedef ::google::protobuf::internal::CompareByFirstField<SortItem> Less;\n");
|
||||
}
|
||||
string utf8_check;
|
||||
if (string_key || string_value) {
|
||||
printer->Print(
|
||||
"struct Utf8Check {\n"
|
||||
" static void Check(ConstPtr p) {\n");
|
||||
printer->Indent();
|
||||
printer->Indent();
|
||||
if (string_key) {
|
||||
GenerateUtf8CheckCodeForString(
|
||||
key_field, options_, false, variables,
|
||||
"p->first.data(), static_cast<int>(p->first.length()),\n", printer);
|
||||
}
|
||||
if (string_value) {
|
||||
GenerateUtf8CheckCodeForString(
|
||||
value_field, options_, false, variables,
|
||||
"p->second.data(), static_cast<int>(p->second.length()),\n", printer);
|
||||
}
|
||||
printer->Outdent();
|
||||
printer->Outdent();
|
||||
printer->Print(
|
||||
" }\n"
|
||||
"};\n");
|
||||
utf8_check = "Utf8Check::Check";
|
||||
}
|
||||
|
||||
printer->Print(variables,
|
||||
"\n"
|
||||
"if ($deterministic$ &&\n"
|
||||
" this->$name$().size() > 1) {\n"
|
||||
" ::std::unique_ptr<SortItem[]> items(\n"
|
||||
" new SortItem[this->$name$().size()]);\n"
|
||||
" typedef ::google::protobuf::Map< $key_cpp$, $val_cpp$ >::size_type size_type;\n"
|
||||
" size_type n = 0;\n"
|
||||
" for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n"
|
||||
" it = this->$name$().begin();\n"
|
||||
" it != this->$name$().end(); ++it, ++n) {\n"
|
||||
" items[static_cast<ptrdiff_t>(n)] = SortItem(&*it);\n"
|
||||
" }\n"
|
||||
" ::std::sort(&items[0], &items[static_cast<ptrdiff_t>(n)], Less());\n");
|
||||
printer->Indent();
|
||||
GenerateSerializationLoop(printer, variables, SupportsArenas(descriptor_),
|
||||
utf8_check, "for (size_type i = 0; i < n; i++)",
|
||||
string_key ? "items[static_cast<ptrdiff_t>(i)]" :
|
||||
"items[static_cast<ptrdiff_t>(i)].second", false);
|
||||
printer->Outdent();
|
||||
printer->Print(
|
||||
"} else {\n");
|
||||
printer->Indent();
|
||||
GenerateSerializationLoop(
|
||||
printer, variables, SupportsArenas(descriptor_), utf8_check,
|
||||
"for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n"
|
||||
" it = this->$name$().begin();\n"
|
||||
" it != this->$name$().end(); ++it)",
|
||||
"it", true);
|
||||
printer->Outdent();
|
||||
printer->Print("}\n");
|
||||
printer->Outdent();
|
||||
printer->Print("}\n");
|
||||
}
|
||||
|
||||
void MapFieldGenerator::
|
||||
GenerateByteSize(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"total_size += $tag_size$ *\n"
|
||||
" ::google::protobuf::internal::FromIntSize(this->$name$_size());\n"
|
||||
"{\n"
|
||||
" ::std::unique_ptr<$map_classname$> entry;\n"
|
||||
" for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n"
|
||||
" it = this->$name$().begin();\n"
|
||||
" it != this->$name$().end(); ++it) {\n");
|
||||
|
||||
// If entry is allocated by arena, its desctructor should be avoided.
|
||||
if (SupportsArenas(descriptor_)) {
|
||||
printer->Print(variables_,
|
||||
" if (entry.get() != NULL && entry->GetArena() != NULL) {\n"
|
||||
" entry.release();\n"
|
||||
" }\n");
|
||||
}
|
||||
|
||||
printer->Print(variables_,
|
||||
" entry.reset($name$_.New$wrapper$(it->first, it->second));\n"
|
||||
" total_size += ::google::protobuf::internal::WireFormatLite::\n"
|
||||
" $declared_type$SizeNoVirtual(*entry);\n"
|
||||
" }\n");
|
||||
|
||||
// If entry is allocated by arena, its desctructor should be avoided.
|
||||
if (SupportsArenas(descriptor_)) {
|
||||
printer->Print(variables_,
|
||||
" if (entry.get() != NULL && entry->GetArena() != NULL) {\n"
|
||||
" entry.release();\n"
|
||||
" }\n");
|
||||
}
|
||||
|
||||
printer->Print("}\n");
|
||||
}
|
||||
|
||||
} // namespace cpp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
@ -0,0 +1,79 @@
|
||||
// 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_COMPILER_CPP_MAP_FIELD_H__
|
||||
#define GOOGLE_PROTOBUF_COMPILER_CPP_MAP_FIELD_H__
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/compiler/cpp/cpp_message_field.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
|
||||
class MapFieldGenerator : public FieldGenerator {
|
||||
public:
|
||||
MapFieldGenerator(const FieldDescriptor* descriptor, const Options& options);
|
||||
~MapFieldGenerator();
|
||||
|
||||
// implements FieldGenerator ---------------------------------------
|
||||
void GeneratePrivateMembers(io::Printer* printer) const;
|
||||
void GenerateAccessorDeclarations(io::Printer* printer) const;
|
||||
void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
|
||||
void GenerateClearingCode(io::Printer* printer) const;
|
||||
void GenerateMergingCode(io::Printer* printer) const;
|
||||
void GenerateSwappingCode(io::Printer* printer) const;
|
||||
void GenerateConstructorCode(io::Printer* printer) const {}
|
||||
void GenerateCopyConstructorCode(io::Printer* printer) const;
|
||||
void GenerateMergeFromCodedStream(io::Printer* printer) const;
|
||||
void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
|
||||
void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
|
||||
void GenerateByteSize(io::Printer* printer) const;
|
||||
|
||||
private:
|
||||
// A helper for GenerateSerializeWithCachedSizes{,ToArray}.
|
||||
void GenerateSerializeWithCachedSizes(
|
||||
io::Printer* printer, const std::map<string, string>& variables) const;
|
||||
|
||||
const FieldDescriptor* descriptor_;
|
||||
std::map<string, string> variables_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapFieldGenerator);
|
||||
};
|
||||
|
||||
} // namespace cpp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_MAP_FIELD_H__
|
4385
Common/ProtocolBuffer/google/protobuf/compiler/cpp/cpp_message.cc
Normal file
4385
Common/ProtocolBuffer/google/protobuf/compiler/cpp/cpp_message.cc
Normal file
File diff suppressed because it is too large
Load Diff
237
Common/ProtocolBuffer/google/protobuf/compiler/cpp/cpp_message.h
Normal file
237
Common/ProtocolBuffer/google/protobuf/compiler/cpp/cpp_message.h
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.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__
|
||||
#define GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__
|
||||
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <google/protobuf/compiler/cpp/cpp_field.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_message_layout_helper.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_options.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace io {
|
||||
class Printer; // printer.h
|
||||
}
|
||||
}
|
||||
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
|
||||
class EnumGenerator; // enum.h
|
||||
class ExtensionGenerator; // extension.h
|
||||
|
||||
class MessageGenerator {
|
||||
public:
|
||||
// See generator.cc for the meaning of dllexport_decl.
|
||||
MessageGenerator(const Descriptor* descriptor, int index_in_file_messages,
|
||||
const Options& options, SCCAnalyzer* scc_analyzer);
|
||||
~MessageGenerator();
|
||||
|
||||
// Append the two types of nested generators to the corresponding vector.
|
||||
void AddGenerators(std::vector<EnumGenerator*>* enum_generators,
|
||||
std::vector<ExtensionGenerator*>* extension_generators);
|
||||
|
||||
// Header stuff.
|
||||
|
||||
// Return names for forward declarations of this class and all its nested
|
||||
// types. A given key in {class,enum}_names will map from a class name to the
|
||||
// descriptor that was responsible for its inclusion in the map. This can be
|
||||
// used to associate the descriptor with the code generated for it.
|
||||
void FillMessageForwardDeclarations(
|
||||
std::map<string, const Descriptor*>* class_names);
|
||||
|
||||
// Generate definitions for this class and all its nested types.
|
||||
void GenerateClassDefinition(io::Printer* printer);
|
||||
|
||||
// Generate definitions of inline methods (placed at the end of the header
|
||||
// file).
|
||||
void GenerateInlineMethods(io::Printer* printer);
|
||||
|
||||
// Source file stuff.
|
||||
|
||||
// Generate extra fields
|
||||
void GenerateExtraDefaultFields(io::Printer* printer);
|
||||
|
||||
// Generates code that creates default instances for fields.
|
||||
void GenerateFieldDefaultInstances(io::Printer* printer);
|
||||
|
||||
// Generates code that initializes the message's default instance. This
|
||||
// is separate from allocating because all default instances must be
|
||||
// allocated before any can be initialized.
|
||||
void GenerateDefaultInstanceInitializer(io::Printer* printer);
|
||||
|
||||
// Generate all non-inline methods for this class.
|
||||
void GenerateClassMethods(io::Printer* printer);
|
||||
|
||||
// Generate source file code that should go outside any namespace.
|
||||
void GenerateSourceInProto2Namespace(io::Printer* printer);
|
||||
|
||||
private:
|
||||
// Generate declarations and definitions of accessors for fields.
|
||||
void GenerateFieldAccessorDeclarations(io::Printer* printer);
|
||||
void GenerateFieldAccessorDefinitions(io::Printer* printer);
|
||||
|
||||
// Generate the table-driven parsing array. Returns the number of entries
|
||||
// generated.
|
||||
size_t GenerateParseOffsets(io::Printer* printer);
|
||||
size_t GenerateParseAuxTable(io::Printer* printer);
|
||||
// Generates a ParseTable entry. Returns whether the proto uses table-driven
|
||||
// parsing.
|
||||
bool GenerateParseTable(io::Printer* printer, size_t offset,
|
||||
size_t aux_offset);
|
||||
|
||||
// Generate the field offsets array. Returns the a pair of the total numer
|
||||
// of entries generated and the index of the first has_bit entry.
|
||||
std::pair<size_t, size_t> GenerateOffsets(io::Printer* printer);
|
||||
void GenerateSchema(io::Printer* printer, int offset, int has_offset);
|
||||
// For each field generates a table entry describing the field for the
|
||||
// table driven serializer.
|
||||
int GenerateFieldMetadata(io::Printer* printer);
|
||||
|
||||
// Generate constructors and destructor.
|
||||
void GenerateStructors(io::Printer* printer);
|
||||
|
||||
// The compiler typically generates multiple copies of each constructor and
|
||||
// destructor: http://gcc.gnu.org/bugs.html#nonbugs_cxx
|
||||
// Placing common code in a separate method reduces the generated code size.
|
||||
//
|
||||
// Generate the shared constructor code.
|
||||
void GenerateSharedConstructorCode(io::Printer* printer);
|
||||
// Generate the shared destructor code.
|
||||
void GenerateSharedDestructorCode(io::Printer* printer);
|
||||
// Generate the arena-specific destructor code.
|
||||
void GenerateArenaDestructorCode(io::Printer* printer);
|
||||
|
||||
// Helper for GenerateClear and others. Optionally emits a condition that
|
||||
// assumes the existence of the cached_has_bits variable, and returns true if
|
||||
// the condition was printed.
|
||||
bool MaybeGenerateOptionalFieldCondition(io::Printer* printer,
|
||||
const FieldDescriptor* field,
|
||||
int expected_has_bits_index);
|
||||
|
||||
// Generate standard Message methods.
|
||||
void GenerateClear(io::Printer* printer);
|
||||
void GenerateOneofClear(io::Printer* printer);
|
||||
void GenerateMergeFromCodedStream(io::Printer* printer);
|
||||
void GenerateSerializeWithCachedSizes(io::Printer* printer);
|
||||
void GenerateSerializeWithCachedSizesToArray(io::Printer* printer);
|
||||
void GenerateSerializeWithCachedSizesBody(io::Printer* printer,
|
||||
bool to_array);
|
||||
void GenerateByteSize(io::Printer* printer);
|
||||
void GenerateMergeFrom(io::Printer* printer);
|
||||
void GenerateCopyFrom(io::Printer* printer);
|
||||
void GenerateSwap(io::Printer* printer);
|
||||
void GenerateIsInitialized(io::Printer* printer);
|
||||
|
||||
// Helpers for GenerateSerializeWithCachedSizes().
|
||||
//
|
||||
// cached_has_bit_index maintains that:
|
||||
// cached_has_bits = _has_bits_[cached_has_bit_index]
|
||||
// for cached_has_bit_index >= 0
|
||||
void GenerateSerializeOneField(io::Printer* printer,
|
||||
const FieldDescriptor* field,
|
||||
bool unbounded,
|
||||
int cached_has_bits_index);
|
||||
// Generate a switch statement to serialize 2+ fields from the same oneof.
|
||||
// Or, if fields.size() == 1, just call GenerateSerializeOneField().
|
||||
void GenerateSerializeOneofFields(
|
||||
io::Printer* printer, const std::vector<const FieldDescriptor*>& fields,
|
||||
bool to_array);
|
||||
void GenerateSerializeOneExtensionRange(
|
||||
io::Printer* printer, const Descriptor::ExtensionRange* range,
|
||||
bool unbounded);
|
||||
|
||||
// Generates has_foo() functions and variables for singular field has-bits.
|
||||
void GenerateSingularFieldHasBits(const FieldDescriptor* field,
|
||||
std::map<string, string> vars,
|
||||
io::Printer* printer);
|
||||
// Generates has_foo() functions and variables for oneof field has-bits.
|
||||
void GenerateOneofHasBits(io::Printer* printer);
|
||||
// Generates has_foo_bar() functions for oneof members.
|
||||
void GenerateOneofMemberHasBits(const FieldDescriptor* field,
|
||||
const std::map<string, string>& vars,
|
||||
io::Printer* printer);
|
||||
// Generates the clear_foo() method for a field.
|
||||
void GenerateFieldClear(const FieldDescriptor* field,
|
||||
const std::map<string, string>& vars,
|
||||
bool is_inline,
|
||||
io::Printer* printer);
|
||||
|
||||
void GenerateConstructorBody(io::Printer* printer,
|
||||
std::vector<bool> already_processed,
|
||||
bool copy_constructor) const;
|
||||
|
||||
size_t HasBitsSize() const;
|
||||
std::vector<uint32> RequiredFieldsBitMask() const;
|
||||
|
||||
const Descriptor* descriptor_;
|
||||
int index_in_file_messages_;
|
||||
string classname_;
|
||||
Options options_;
|
||||
FieldGeneratorMap field_generators_;
|
||||
// optimized_order_ is the order we layout the message's fields in the class.
|
||||
// This is reused to initialize the fields in-order for cache efficiency.
|
||||
//
|
||||
// optimized_order_ excludes oneof fields and weak fields.
|
||||
std::vector<const FieldDescriptor *> optimized_order_;
|
||||
std::vector<int> has_bit_indices_;
|
||||
int max_has_bit_index_;
|
||||
std::unique_ptr<std::unique_ptr<EnumGenerator> []> enum_generators_;
|
||||
std::unique_ptr<std::unique_ptr<ExtensionGenerator> []> extension_generators_;
|
||||
int num_required_fields_;
|
||||
int num_weak_fields_;
|
||||
// table_driven_ indicates the generated message uses table-driven parsing.
|
||||
bool table_driven_;
|
||||
|
||||
std::unique_ptr<MessageLayoutHelper> message_layout_helper_;
|
||||
|
||||
SCCAnalyzer* scc_analyzer_;
|
||||
string scc_name_;
|
||||
|
||||
friend class FileGenerator;
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageGenerator);
|
||||
};
|
||||
|
||||
} // namespace cpp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__
|
@ -0,0 +1,836 @@
|
||||
// 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/compiler/cpp/cpp_message_field.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
|
||||
#include <google/protobuf/io/printer.h>
|
||||
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
|
||||
namespace {
|
||||
|
||||
// When we are generating code for implicit weak fields, we need to insert some
|
||||
// additional casts. These functions return the casted expression if
|
||||
// implicit_weak_field is true but otherwise return the original expression.
|
||||
// Ordinarily a static_cast is enough to cast google::protobuf::MessageLite* to a class
|
||||
// deriving from it, but we need a reinterpret_cast in cases where the generated
|
||||
// message is forward-declared but its full definition is not visible.
|
||||
string StaticCast(const string& type, const string& expression,
|
||||
bool implicit_weak_field) {
|
||||
if (implicit_weak_field) {
|
||||
return "static_cast< " + type + " >(" + expression + ")";
|
||||
} else {
|
||||
return expression;
|
||||
}
|
||||
}
|
||||
|
||||
string ReinterpretCast(const string& type, const string& expression,
|
||||
bool implicit_weak_field) {
|
||||
if (implicit_weak_field) {
|
||||
return "reinterpret_cast< " + type + " >(" + expression + ")";
|
||||
} else {
|
||||
return expression;
|
||||
}
|
||||
}
|
||||
|
||||
void SetMessageVariables(const FieldDescriptor* descriptor,
|
||||
const Options& options, bool implicit_weak,
|
||||
std::map<string, string>* variables) {
|
||||
SetCommonFieldVariables(descriptor, variables, options);
|
||||
(*variables)["type"] = FieldMessageTypeName(descriptor);
|
||||
(*variables)["casted_member"] = ReinterpretCast(
|
||||
(*variables)["type"] + "*", (*variables)["name"] + "_", implicit_weak);
|
||||
(*variables)["type_default_instance"] =
|
||||
DefaultInstanceName(descriptor->message_type());
|
||||
(*variables)["type_reference_function"] =
|
||||
implicit_weak
|
||||
? (" " + ReferenceFunctionName(descriptor->message_type()) + "();\n")
|
||||
: "";
|
||||
(*variables)["stream_writer"] =
|
||||
(*variables)["declared_type"] +
|
||||
(HasFastArraySerialization(descriptor->message_type()->file(), options)
|
||||
? "MaybeToArray"
|
||||
: "");
|
||||
// NOTE: Escaped here to unblock proto1->proto2 migration.
|
||||
// TODO(liujisi): Extend this to apply for other conflicting methods.
|
||||
(*variables)["release_name"] =
|
||||
SafeFunctionName(descriptor->containing_type(),
|
||||
descriptor, "release_");
|
||||
(*variables)["full_name"] = descriptor->full_name();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// ===================================================================
|
||||
|
||||
MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor,
|
||||
const Options& options,
|
||||
SCCAnalyzer* scc_analyzer)
|
||||
: FieldGenerator(options),
|
||||
descriptor_(descriptor),
|
||||
implicit_weak_field_(
|
||||
IsImplicitWeakField(descriptor, options, scc_analyzer)) {
|
||||
SetMessageVariables(descriptor, options, implicit_weak_field_, &variables_);
|
||||
}
|
||||
|
||||
MessageFieldGenerator::~MessageFieldGenerator() {}
|
||||
|
||||
void MessageFieldGenerator::
|
||||
GeneratePrivateMembers(io::Printer* printer) const {
|
||||
if (implicit_weak_field_) {
|
||||
printer->Print(variables_, "::google::protobuf::MessageLite* $name$_;\n");
|
||||
} else {
|
||||
printer->Print(variables_, "$type$* $name$_;\n");
|
||||
}
|
||||
}
|
||||
|
||||
void MessageFieldGenerator::
|
||||
GenerateAccessorDeclarations(io::Printer* printer) const {
|
||||
if (implicit_weak_field_) {
|
||||
// These private accessors are used by MergeFrom and
|
||||
// MergePartialFromCodedStream, and their purpose is to provide access to
|
||||
// the field without creating a strong dependency on the message type.
|
||||
printer->Print(variables_,
|
||||
"private:\n"
|
||||
"const ::google::protobuf::MessageLite& _internal_$name$() const;\n"
|
||||
"::google::protobuf::MessageLite* _internal_mutable_$name$();\n"
|
||||
"public:\n");
|
||||
} else {
|
||||
// This inline accessor directly returns member field and is used in
|
||||
// Serialize such that AFDO profile correctly captures access information to
|
||||
// message fields under serialize.
|
||||
printer->Print(variables_,
|
||||
"private:\n"
|
||||
"const $type$& _internal_$name$() const;\n"
|
||||
"public:\n");
|
||||
}
|
||||
printer->Print(variables_,
|
||||
"$deprecated_attr$const $type$& $name$() const;\n");
|
||||
printer->Annotate("name", descriptor_);
|
||||
printer->Print(variables_, "$deprecated_attr$$type$* $release_name$();\n");
|
||||
printer->Annotate("release_name", descriptor_);
|
||||
printer->Print(variables_,
|
||||
"$deprecated_attr$$type$* ${$mutable_$name$$}$();\n");
|
||||
printer->Annotate("{", "}", descriptor_);
|
||||
printer->Print(variables_,
|
||||
"$deprecated_attr$void ${$set_allocated_$name$$}$"
|
||||
"($type$* $name$);\n");
|
||||
printer->Annotate("{", "}", descriptor_);
|
||||
if (SupportsArenas(descriptor_)) {
|
||||
printer->Print(variables_,
|
||||
"$deprecated_attr$void "
|
||||
"${$unsafe_arena_set_allocated_$name$$}$(\n"
|
||||
" $type$* $name$);\n");
|
||||
printer->Annotate("{", "}", descriptor_);
|
||||
printer->Print(
|
||||
variables_,
|
||||
"$deprecated_attr$$type$* ${$unsafe_arena_release_$name$$}$();\n");
|
||||
printer->Annotate("{", "}", descriptor_);
|
||||
}
|
||||
}
|
||||
|
||||
void MessageFieldGenerator::GenerateNonInlineAccessorDefinitions(
|
||||
io::Printer* printer) const {
|
||||
if (implicit_weak_field_) {
|
||||
printer->Print(variables_,
|
||||
"const ::google::protobuf::MessageLite& $classname$::_internal_$name$() const {\n"
|
||||
" if ($name$_ != NULL) {\n"
|
||||
" return *$name$_;\n"
|
||||
" } else if (&$type_default_instance$ != NULL) {\n"
|
||||
" return *reinterpret_cast<const ::google::protobuf::MessageLite*>(\n"
|
||||
" &$type_default_instance$);\n"
|
||||
" } else {\n"
|
||||
" return "
|
||||
"*::google::protobuf::internal::ImplicitWeakMessage::default_instance();\n"
|
||||
" }\n"
|
||||
"}\n");
|
||||
}
|
||||
if (SupportsArenas(descriptor_)) {
|
||||
if (implicit_weak_field_) {
|
||||
printer->Print(variables_,
|
||||
"::google::protobuf::MessageLite* $classname$::_internal_mutable_$name$() {\n"
|
||||
" $set_hasbit$\n"
|
||||
" if ($name$_ == NULL) {\n"
|
||||
" if (&$type_default_instance$ == NULL) {\n"
|
||||
" $name$_ = ::google::protobuf::Arena::CreateMessage<\n"
|
||||
" ::google::protobuf::internal::ImplicitWeakMessage>(\n"
|
||||
" GetArenaNoVirtual());\n"
|
||||
" } else {\n"
|
||||
" $name$_ = reinterpret_cast<const ::google::protobuf::MessageLite*>(\n"
|
||||
" &$type_default_instance$)->New(GetArenaNoVirtual());\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" return $name$_;\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
printer->Print(variables_,
|
||||
"void $classname$::unsafe_arena_set_allocated_$name$(\n"
|
||||
" $type$* $name$) {\n"
|
||||
// If we're not on an arena, free whatever we were holding before.
|
||||
// (If we are on arena, we can just forget the earlier pointer.)
|
||||
" if (GetArenaNoVirtual() == NULL) {\n"
|
||||
" delete $name$_;\n"
|
||||
" }\n"
|
||||
" $name$_ = $name$;\n"
|
||||
" if ($name$) {\n"
|
||||
" $set_hasbit$\n"
|
||||
" } else {\n"
|
||||
" $clear_hasbit$\n"
|
||||
" }\n"
|
||||
" // @@protoc_insertion_point(field_unsafe_arena_set_allocated"
|
||||
":$full_name$)\n"
|
||||
"}\n");
|
||||
} else if (implicit_weak_field_) {
|
||||
printer->Print(variables_,
|
||||
"::google::protobuf::MessageLite* $classname$::_internal_mutable_$name$() {\n"
|
||||
" $set_hasbit$\n"
|
||||
" if ($name$_ == NULL) {\n"
|
||||
" if (&$type_default_instance$ == NULL) {\n"
|
||||
" $name$_ = new ::google::protobuf::internal::ImplicitWeakMessage;\n"
|
||||
" } else {\n"
|
||||
" $name$_ = reinterpret_cast<const ::google::protobuf::MessageLite*>(\n"
|
||||
" &$type_default_instance$)->New();\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" return $name$_;\n"
|
||||
"}\n");
|
||||
}
|
||||
}
|
||||
|
||||
void MessageFieldGenerator::
|
||||
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
|
||||
if (!implicit_weak_field_) {
|
||||
printer->Print(variables_,
|
||||
"inline const $type$& $classname$::_internal_$name$() const {\n"
|
||||
" return *$field_member$;\n"
|
||||
"}\n");
|
||||
}
|
||||
printer->Print(variables_,
|
||||
"inline const $type$& $classname$::$name$() const {\n"
|
||||
" const $type$* p = $casted_member$;\n"
|
||||
" // @@protoc_insertion_point(field_get:$full_name$)\n"
|
||||
" return p != NULL ? *p : *reinterpret_cast<const $type$*>(\n"
|
||||
" &$type_default_instance$);\n"
|
||||
"}\n");
|
||||
|
||||
printer->Print(variables_,
|
||||
"inline $type$* $classname$::$release_name$() {\n"
|
||||
" // @@protoc_insertion_point(field_release:$full_name$)\n"
|
||||
"$type_reference_function$"
|
||||
" $clear_hasbit$\n"
|
||||
" $type$* temp = $casted_member$;\n");
|
||||
if (SupportsArenas(descriptor_)) {
|
||||
printer->Print(variables_,
|
||||
" if (GetArenaNoVirtual() != NULL) {\n"
|
||||
" temp = ::google::protobuf::internal::DuplicateIfNonNull(temp);\n"
|
||||
" }\n");
|
||||
}
|
||||
printer->Print(variables_,
|
||||
" $name$_ = NULL;\n"
|
||||
" return temp;\n"
|
||||
"}\n");
|
||||
|
||||
if (SupportsArenas(descriptor_)) {
|
||||
printer->Print(variables_,
|
||||
"inline $type$* $classname$::unsafe_arena_release_$name$() {\n"
|
||||
" // @@protoc_insertion_point(field_unsafe_arena_release:$full_name$)\n"
|
||||
"$type_reference_function$"
|
||||
" $clear_hasbit$\n"
|
||||
" $type$* temp = $casted_member$;\n"
|
||||
" $name$_ = NULL;\n"
|
||||
" return temp;\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
printer->Print(variables_,
|
||||
"inline $type$* $classname$::mutable_$name$() {\n"
|
||||
" $set_hasbit$\n"
|
||||
" if ($name$_ == NULL) {\n"
|
||||
" auto* p = CreateMaybeMessage<$type$>(GetArenaNoVirtual());\n");
|
||||
if (implicit_weak_field_) {
|
||||
printer->Print(variables_,
|
||||
" $name$_ = reinterpret_cast<::google::protobuf::MessageLite*>(p);\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
" $name$_ = p;\n");
|
||||
}
|
||||
printer->Print(variables_,
|
||||
" }\n"
|
||||
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
|
||||
" return $casted_member$;\n"
|
||||
"}\n");
|
||||
|
||||
// We handle the most common case inline, and delegate less common cases to
|
||||
// the slow fallback function.
|
||||
printer->Print(variables_,
|
||||
"inline void $classname$::set_allocated_$name$($type$* $name$) {\n"
|
||||
" ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();\n");
|
||||
printer->Print(variables_,
|
||||
" if (message_arena == NULL) {\n");
|
||||
if (IsCrossFileMessage(descriptor_)) {
|
||||
printer->Print(variables_,
|
||||
" delete reinterpret_cast< ::google::protobuf::MessageLite*>($name$_);\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
" delete $name$_;\n");
|
||||
}
|
||||
printer->Print(variables_,
|
||||
" }\n"
|
||||
" if ($name$) {\n");
|
||||
if (SupportsArenas(descriptor_->message_type()) &&
|
||||
IsCrossFileMessage(descriptor_)) {
|
||||
// We have to read the arena through the virtual method, because the type
|
||||
// isn't defined in this file.
|
||||
printer->Print(variables_,
|
||||
" ::google::protobuf::Arena* submessage_arena =\n"
|
||||
" reinterpret_cast<::google::protobuf::MessageLite*>($name$)->GetArena();\n");
|
||||
} else if (!SupportsArenas(descriptor_->message_type())) {
|
||||
printer->Print(variables_,
|
||||
" ::google::protobuf::Arena* submessage_arena = NULL;\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
" ::google::protobuf::Arena* submessage_arena =\n"
|
||||
" ::google::protobuf::Arena::GetArena($name$);\n");
|
||||
}
|
||||
printer->Print(variables_,
|
||||
" if (message_arena != submessage_arena) {\n"
|
||||
" $name$ = ::google::protobuf::internal::GetOwnedMessage(\n"
|
||||
" message_arena, $name$, submessage_arena);\n"
|
||||
" }\n"
|
||||
" $set_hasbit$\n"
|
||||
" } else {\n"
|
||||
" $clear_hasbit$\n"
|
||||
" }\n");
|
||||
if (implicit_weak_field_) {
|
||||
printer->Print(variables_,
|
||||
" $name$_ = reinterpret_cast<MessageLite*>($name$);\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
" $name$_ = $name$;\n");
|
||||
}
|
||||
printer->Print(variables_,
|
||||
" // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void MessageFieldGenerator::
|
||||
GenerateClearingCode(io::Printer* printer) const {
|
||||
if (!HasFieldPresence(descriptor_->file())) {
|
||||
// If we don't have has-bits, message presence is indicated only by ptr !=
|
||||
// NULL. Thus on clear, we need to delete the object.
|
||||
printer->Print(variables_,
|
||||
"if (GetArenaNoVirtual() == NULL && $name$_ != NULL) {\n"
|
||||
" delete $name$_;\n"
|
||||
"}\n"
|
||||
"$name$_ = NULL;\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
"if ($name$_ != NULL) $name$_->Clear();\n");
|
||||
}
|
||||
}
|
||||
|
||||
void MessageFieldGenerator::
|
||||
GenerateMessageClearingCode(io::Printer* printer) const {
|
||||
if (!HasFieldPresence(descriptor_->file())) {
|
||||
// If we don't have has-bits, message presence is indicated only by ptr !=
|
||||
// NULL. Thus on clear, we need to delete the object.
|
||||
printer->Print(variables_,
|
||||
"if (GetArenaNoVirtual() == NULL && $name$_ != NULL) {\n"
|
||||
" delete $name$_;\n"
|
||||
"}\n"
|
||||
"$name$_ = NULL;\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
"GOOGLE_DCHECK($name$_ != NULL);\n"
|
||||
"$name$_->Clear();\n");
|
||||
}
|
||||
}
|
||||
|
||||
void MessageFieldGenerator::
|
||||
GenerateMergingCode(io::Printer* printer) const {
|
||||
if (implicit_weak_field_) {
|
||||
printer->Print(variables_,
|
||||
"_internal_mutable_$name$()->CheckTypeAndMergeFrom(\n"
|
||||
" from._internal_$name$());\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
"mutable_$name$()->$type$::MergeFrom(from.$name$());\n");
|
||||
}
|
||||
}
|
||||
|
||||
void MessageFieldGenerator::
|
||||
GenerateSwappingCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "swap($name$_, other->$name$_);\n");
|
||||
}
|
||||
|
||||
void MessageFieldGenerator::
|
||||
GenerateDestructorCode(io::Printer* printer) const {
|
||||
// TODO(gerbens) Remove this when we don't need to destruct default instances.
|
||||
// In google3 a default instance will never get deleted so we don't need to
|
||||
// worry about that but in opensource protobuf default instances are deleted
|
||||
// in shutdown process and we need to take special care when handling them.
|
||||
printer->Print(variables_,
|
||||
"if (this != internal_default_instance()) ");
|
||||
printer->Print(variables_, "delete $name$_;\n");
|
||||
}
|
||||
|
||||
void MessageFieldGenerator::
|
||||
GenerateConstructorCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "$name$_ = NULL;\n");
|
||||
}
|
||||
|
||||
void MessageFieldGenerator::
|
||||
GenerateCopyConstructorCode(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"if (from.has_$name$()) {\n"
|
||||
" $name$_ = new $type$(*from.$name$_);\n"
|
||||
"} else {\n"
|
||||
" $name$_ = NULL;\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void MessageFieldGenerator::
|
||||
GenerateMergeFromCodedStream(io::Printer* printer) const {
|
||||
if (implicit_weak_field_) {
|
||||
printer->Print(variables_,
|
||||
"DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(\n"
|
||||
" input, _internal_mutable_$name$()));\n");
|
||||
} else if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) {
|
||||
printer->Print(variables_,
|
||||
"DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(\n"
|
||||
" input, mutable_$name$()));\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
"DO_(::google::protobuf::internal::WireFormatLite::ReadGroup(\n"
|
||||
" $number$, input, mutable_$name$()));\n");
|
||||
}
|
||||
}
|
||||
|
||||
void MessageFieldGenerator::
|
||||
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n"
|
||||
" $number$, this->_internal_$name$(), output);\n");
|
||||
}
|
||||
|
||||
void MessageFieldGenerator::
|
||||
GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"target = ::google::protobuf::internal::WireFormatLite::\n"
|
||||
" InternalWrite$declared_type$ToArray(\n"
|
||||
" $number$, this->_internal_$name$(), deterministic, target);\n");
|
||||
}
|
||||
|
||||
void MessageFieldGenerator::
|
||||
GenerateByteSize(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"total_size += $tag_size$ +\n"
|
||||
" ::google::protobuf::internal::WireFormatLite::$declared_type$Size(\n"
|
||||
" *$field_member$);\n");
|
||||
}
|
||||
|
||||
// ===================================================================
|
||||
|
||||
MessageOneofFieldGenerator::MessageOneofFieldGenerator(
|
||||
const FieldDescriptor* descriptor, const Options& options,
|
||||
SCCAnalyzer* scc_analyzer)
|
||||
: MessageFieldGenerator(descriptor, options, scc_analyzer) {
|
||||
SetCommonOneofFieldVariables(descriptor, &variables_);
|
||||
}
|
||||
|
||||
MessageOneofFieldGenerator::~MessageOneofFieldGenerator() {}
|
||||
|
||||
void MessageOneofFieldGenerator::GenerateNonInlineAccessorDefinitions(
|
||||
io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"void $classname$::set_allocated_$name$($type$* $name$) {\n"
|
||||
" ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();\n"
|
||||
" clear_$oneof_name$();\n"
|
||||
" if ($name$) {\n");
|
||||
if (SupportsArenas(descriptor_->message_type()) &&
|
||||
descriptor_->file() != descriptor_->message_type()->file()) {
|
||||
// We have to read the arena through the virtual method, because the type
|
||||
// isn't defined in this file.
|
||||
printer->Print(variables_,
|
||||
" ::google::protobuf::Arena* submessage_arena =\n"
|
||||
" reinterpret_cast<::google::protobuf::MessageLite*>($name$)->GetArena();\n");
|
||||
} else if (!SupportsArenas(descriptor_->message_type())) {
|
||||
printer->Print(variables_,
|
||||
" ::google::protobuf::Arena* submessage_arena = NULL;\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
" ::google::protobuf::Arena* submessage_arena =\n"
|
||||
" ::google::protobuf::Arena::GetArena($name$);\n");
|
||||
}
|
||||
printer->Print(variables_,
|
||||
" if (message_arena != submessage_arena) {\n"
|
||||
" $name$ = ::google::protobuf::internal::GetOwnedMessage(\n"
|
||||
" message_arena, $name$, submessage_arena);\n"
|
||||
" }\n"
|
||||
" set_has_$name$();\n"
|
||||
" $field_member$ = $name$;\n"
|
||||
" }\n"
|
||||
" // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void MessageOneofFieldGenerator::
|
||||
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
|
||||
if (!implicit_weak_field_) {
|
||||
printer->Print(variables_,
|
||||
"inline const $type$& $classname$::_internal_$name$() const {\n"
|
||||
" return *$field_member$;\n"
|
||||
"}\n");
|
||||
}
|
||||
printer->Print(variables_,
|
||||
"inline $type$* $classname$::$release_name$() {\n"
|
||||
" // @@protoc_insertion_point(field_release:$full_name$)\n"
|
||||
" if (has_$name$()) {\n"
|
||||
" clear_has_$oneof_name$();\n"
|
||||
" $type$* temp = $field_member$;\n");
|
||||
if (SupportsArenas(descriptor_)) {
|
||||
printer->Print(variables_,
|
||||
" if (GetArenaNoVirtual() != NULL) {\n"
|
||||
" temp = ::google::protobuf::internal::DuplicateIfNonNull(temp);\n"
|
||||
" }\n");
|
||||
}
|
||||
printer->Print(variables_,
|
||||
" $field_member$ = NULL;\n"
|
||||
" return temp;\n"
|
||||
" } else {\n"
|
||||
" return NULL;\n"
|
||||
" }\n"
|
||||
"}\n");
|
||||
|
||||
printer->Print(variables_,
|
||||
"inline const $type$& $classname$::$name$() const {\n"
|
||||
" // @@protoc_insertion_point(field_get:$full_name$)\n"
|
||||
" return has_$name$()\n"
|
||||
" ? *$field_member$\n"
|
||||
" : *reinterpret_cast< $type$*>(&$type_default_instance$);\n"
|
||||
"}\n");
|
||||
|
||||
if (SupportsArenas(descriptor_)) {
|
||||
printer->Print(variables_,
|
||||
"inline $type$* $classname$::unsafe_arena_release_$name$() {\n"
|
||||
" // @@protoc_insertion_point(field_unsafe_arena_release"
|
||||
":$full_name$)\n"
|
||||
" if (has_$name$()) {\n"
|
||||
" clear_has_$oneof_name$();\n"
|
||||
" $type$* temp = $field_member$;\n"
|
||||
" $field_member$ = NULL;\n"
|
||||
" return temp;\n"
|
||||
" } else {\n"
|
||||
" return NULL;\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"inline void $classname$::unsafe_arena_set_allocated_$name$"
|
||||
"($type$* $name$) {\n"
|
||||
// We rely on the oneof clear method to free the earlier contents of this
|
||||
// oneof. We can directly use the pointer we're given to set the new
|
||||
// value.
|
||||
" clear_$oneof_name$();\n"
|
||||
" if ($name$) {\n"
|
||||
" set_has_$name$();\n"
|
||||
" $field_member$ = $name$;\n"
|
||||
" }\n"
|
||||
" // @@protoc_insertion_point(field_unsafe_arena_set_allocated:"
|
||||
"$full_name$)\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
printer->Print(variables_,
|
||||
"inline $type$* $classname$::mutable_$name$() {\n"
|
||||
" if (!has_$name$()) {\n"
|
||||
" clear_$oneof_name$();\n"
|
||||
" set_has_$name$();\n"
|
||||
" $field_member$ = CreateMaybeMessage< $type$ >(\n"
|
||||
" GetArenaNoVirtual());\n"
|
||||
" }\n"
|
||||
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
|
||||
" return $field_member$;\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void MessageOneofFieldGenerator::
|
||||
GenerateClearingCode(io::Printer* printer) const {
|
||||
if (SupportsArenas(descriptor_)) {
|
||||
printer->Print(variables_,
|
||||
"if (GetArenaNoVirtual() == NULL) {\n"
|
||||
" delete $field_member$;\n"
|
||||
"}\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
"delete $field_member$;\n");
|
||||
}
|
||||
}
|
||||
|
||||
void MessageOneofFieldGenerator::
|
||||
GenerateMessageClearingCode(io::Printer* printer) const {
|
||||
GenerateClearingCode(printer);
|
||||
}
|
||||
|
||||
void MessageOneofFieldGenerator::
|
||||
GenerateSwappingCode(io::Printer* printer) const {
|
||||
// Don't print any swapping code. Swapping the union will swap this field.
|
||||
}
|
||||
|
||||
void MessageOneofFieldGenerator::
|
||||
GenerateDestructorCode(io::Printer* printer) const {
|
||||
// We inherit from MessageFieldGenerator, so we need to override the default
|
||||
// behavior.
|
||||
}
|
||||
|
||||
void MessageOneofFieldGenerator::
|
||||
GenerateConstructorCode(io::Printer* printer) const {
|
||||
// Don't print any constructor code. The field is in a union. We allocate
|
||||
// space only when this field is used.
|
||||
}
|
||||
|
||||
// ===================================================================
|
||||
|
||||
RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator(
|
||||
const FieldDescriptor* descriptor, const Options& options,
|
||||
SCCAnalyzer* scc_analyzer)
|
||||
: FieldGenerator(options),
|
||||
descriptor_(descriptor),
|
||||
implicit_weak_field_(
|
||||
IsImplicitWeakField(descriptor, options, scc_analyzer)) {
|
||||
SetMessageVariables(descriptor, options, implicit_weak_field_, &variables_);
|
||||
}
|
||||
|
||||
RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
|
||||
|
||||
void RepeatedMessageFieldGenerator::
|
||||
GeneratePrivateMembers(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"::google::protobuf::RepeatedPtrField< $type$ > $name$_;\n");
|
||||
}
|
||||
|
||||
void RepeatedMessageFieldGenerator::
|
||||
GenerateAccessorDeclarations(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"$deprecated_attr$$type$* ${$mutable_$name$$}$(int index);\n");
|
||||
printer->Annotate("{", "}", descriptor_);
|
||||
printer->Print(variables_,
|
||||
"$deprecated_attr$::google::protobuf::RepeatedPtrField< $type$ >*\n"
|
||||
" ${$mutable_$name$$}$();\n");
|
||||
printer->Annotate("{", "}", descriptor_);
|
||||
|
||||
printer->Print(variables_,
|
||||
"$deprecated_attr$const $type$& $name$(int index) const;\n");
|
||||
printer->Annotate("name", descriptor_);
|
||||
printer->Print(variables_, "$deprecated_attr$$type$* ${$add_$name$$}$();\n");
|
||||
printer->Annotate("{", "}", descriptor_);
|
||||
printer->Print(variables_,
|
||||
"$deprecated_attr$const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
|
||||
" $name$() const;\n");
|
||||
printer->Annotate("name", descriptor_);
|
||||
}
|
||||
|
||||
void RepeatedMessageFieldGenerator::
|
||||
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"inline $type$* $classname$::mutable_$name$(int index) {\n"
|
||||
// TODO(dlj): move insertion points
|
||||
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
|
||||
"$type_reference_function$"
|
||||
" return $name$_.Mutable(index);\n"
|
||||
"}\n"
|
||||
"inline ::google::protobuf::RepeatedPtrField< $type$ >*\n"
|
||||
"$classname$::mutable_$name$() {\n"
|
||||
" // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
|
||||
"$type_reference_function$"
|
||||
" return &$name$_;\n"
|
||||
"}\n");
|
||||
|
||||
if (options_.safe_boundary_check) {
|
||||
printer->Print(variables_,
|
||||
"inline const $type$& $classname$::$name$(int index) const {\n"
|
||||
" // @@protoc_insertion_point(field_get:$full_name$)\n"
|
||||
" return $name$_.InternalCheckedGet(index,\n"
|
||||
" *reinterpret_cast<const $type$*>(&$type_default_instance$));\n"
|
||||
"}\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
"inline const $type$& $classname$::$name$(int index) const {\n"
|
||||
" // @@protoc_insertion_point(field_get:$full_name$)\n"
|
||||
"$type_reference_function$"
|
||||
" return $name$_.Get(index);\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
printer->Print(variables_,
|
||||
"inline $type$* $classname$::add_$name$() {\n"
|
||||
" // @@protoc_insertion_point(field_add:$full_name$)\n"
|
||||
" return $name$_.Add();\n"
|
||||
"}\n");
|
||||
|
||||
printer->Print(variables_,
|
||||
"inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
|
||||
"$classname$::$name$() const {\n"
|
||||
" // @@protoc_insertion_point(field_list:$full_name$)\n"
|
||||
"$type_reference_function$"
|
||||
" return $name$_;\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void RepeatedMessageFieldGenerator::
|
||||
GenerateClearingCode(io::Printer* printer) const {
|
||||
if (implicit_weak_field_) {
|
||||
printer->Print(
|
||||
variables_,
|
||||
"CastToBase(&$name$_)->Clear<"
|
||||
"::google::protobuf::internal::ImplicitWeakTypeHandler<$type$>>();\n");
|
||||
} else {
|
||||
printer->Print(variables_, "$name$_.Clear();\n");
|
||||
}
|
||||
}
|
||||
|
||||
void RepeatedMessageFieldGenerator::
|
||||
GenerateMergingCode(io::Printer* printer) const {
|
||||
if (implicit_weak_field_) {
|
||||
printer->Print(
|
||||
variables_,
|
||||
"CastToBase(&$name$_)->MergeFrom<"
|
||||
"::google::protobuf::internal::ImplicitWeakTypeHandler<$type$>>(CastToBase("
|
||||
"from.$name$_));\n");
|
||||
} else {
|
||||
printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n");
|
||||
}
|
||||
}
|
||||
|
||||
void RepeatedMessageFieldGenerator::
|
||||
GenerateSwappingCode(io::Printer* printer) const {
|
||||
printer->Print(
|
||||
variables_,
|
||||
"CastToBase(&$name$_)->InternalSwap(CastToBase(&other->$name$_));\n");
|
||||
}
|
||||
|
||||
void RepeatedMessageFieldGenerator::
|
||||
GenerateConstructorCode(io::Printer* printer) const {
|
||||
// Not needed for repeated fields.
|
||||
}
|
||||
|
||||
void RepeatedMessageFieldGenerator::
|
||||
GenerateMergeFromCodedStream(io::Printer* printer) const {
|
||||
if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) {
|
||||
if (implicit_weak_field_) {
|
||||
printer->Print(variables_,
|
||||
"DO_(::google::protobuf::internal::WireFormatLite::"
|
||||
"ReadMessage(input, CastToBase(&$name$_)->AddWeak(\n"
|
||||
" reinterpret_cast<const ::google::protobuf::MessageLite*>(\n"
|
||||
" &$type_default_instance$))));\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
"DO_(::google::protobuf::internal::WireFormatLite::"
|
||||
"ReadMessage(\n"
|
||||
" input, add_$name$()));\n");
|
||||
}
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
"DO_(::google::protobuf::internal::WireFormatLite::"
|
||||
"ReadGroup($number$, input, add_$name$()));\n");
|
||||
}
|
||||
}
|
||||
|
||||
void RepeatedMessageFieldGenerator::
|
||||
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"for (unsigned int i = 0,\n"
|
||||
" n = static_cast<unsigned int>(this->$name$_size()); i < n; i++) {\n"
|
||||
" ::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n"
|
||||
" $number$,\n");
|
||||
if (implicit_weak_field_) {
|
||||
printer->Print(
|
||||
variables_,
|
||||
" CastToBase($name$_).Get<"
|
||||
"::google::protobuf::internal::ImplicitWeakTypeHandler<$type$>>("
|
||||
"static_cast<int>(i)),\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
" this->$name$(static_cast<int>(i)),\n");
|
||||
}
|
||||
printer->Print(variables_,
|
||||
" output);\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void RepeatedMessageFieldGenerator::
|
||||
GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"for (unsigned int i = 0,\n"
|
||||
" n = static_cast<unsigned int>(this->$name$_size()); i < n; i++) {\n"
|
||||
" target = ::google::protobuf::internal::WireFormatLite::\n"
|
||||
" InternalWrite$declared_type$ToArray(\n"
|
||||
" $number$, this->$name$(static_cast<int>(i)), deterministic, target);\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void RepeatedMessageFieldGenerator::
|
||||
GenerateByteSize(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"{\n"
|
||||
" unsigned int count = static_cast<unsigned int>(this->$name$_size());\n");
|
||||
printer->Indent();
|
||||
printer->Print(variables_,
|
||||
"total_size += $tag_size$UL * count;\n"
|
||||
"for (unsigned int i = 0; i < count; i++) {\n"
|
||||
" total_size +=\n"
|
||||
" ::google::protobuf::internal::WireFormatLite::$declared_type$Size(\n");
|
||||
if (implicit_weak_field_) {
|
||||
printer->Print(
|
||||
variables_,
|
||||
" CastToBase($name$_).Get<"
|
||||
"::google::protobuf::internal::ImplicitWeakTypeHandler<$type$>>("
|
||||
"static_cast<int>(i)));\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
" this->$name$(static_cast<int>(i)));\n");
|
||||
}
|
||||
printer->Print(variables_, "}\n");
|
||||
printer->Outdent();
|
||||
printer->Print("}\n");
|
||||
}
|
||||
|
||||
} // namespace cpp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
@ -0,0 +1,136 @@
|
||||
// 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.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_FIELD_H__
|
||||
#define GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_FIELD_H__
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <google/protobuf/compiler/cpp/cpp_field.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
|
||||
class MessageFieldGenerator : public FieldGenerator {
|
||||
public:
|
||||
MessageFieldGenerator(const FieldDescriptor* descriptor,
|
||||
const Options& options, SCCAnalyzer* scc_analyzer);
|
||||
~MessageFieldGenerator();
|
||||
|
||||
// implements FieldGenerator ---------------------------------------
|
||||
void GeneratePrivateMembers(io::Printer* printer) const;
|
||||
void GenerateAccessorDeclarations(io::Printer* printer) const;
|
||||
void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
|
||||
void GenerateNonInlineAccessorDefinitions(io::Printer* printer) const;
|
||||
void GenerateClearingCode(io::Printer* printer) const;
|
||||
void GenerateMessageClearingCode(io::Printer* printer) const;
|
||||
void GenerateMergingCode(io::Printer* printer) const;
|
||||
void GenerateSwappingCode(io::Printer* printer) const;
|
||||
void GenerateDestructorCode(io::Printer* printer) const;
|
||||
void GenerateConstructorCode(io::Printer* printer) const;
|
||||
void GenerateCopyConstructorCode(io::Printer* printer) const;
|
||||
void GenerateMergeFromCodedStream(io::Printer* printer) const;
|
||||
void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
|
||||
void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
|
||||
void GenerateByteSize(io::Printer* printer) const;
|
||||
|
||||
protected:
|
||||
const FieldDescriptor* descriptor_;
|
||||
const bool implicit_weak_field_;
|
||||
std::map<string, string> variables_;
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFieldGenerator);
|
||||
};
|
||||
|
||||
class MessageOneofFieldGenerator : public MessageFieldGenerator {
|
||||
public:
|
||||
MessageOneofFieldGenerator(const FieldDescriptor* descriptor,
|
||||
const Options& options, SCCAnalyzer* scc_analyzer);
|
||||
~MessageOneofFieldGenerator();
|
||||
|
||||
// implements FieldGenerator ---------------------------------------
|
||||
void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
|
||||
void GenerateNonInlineAccessorDefinitions(io::Printer* printer) const;
|
||||
void GenerateClearingCode(io::Printer* printer) const;
|
||||
|
||||
// MessageFieldGenerator, from which we inherit, overrides this so we need to
|
||||
// override it as well.
|
||||
void GenerateMessageClearingCode(io::Printer* printer) const;
|
||||
void GenerateSwappingCode(io::Printer* printer) const;
|
||||
void GenerateDestructorCode(io::Printer* printer) const;
|
||||
void GenerateConstructorCode(io::Printer* printer) const;
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageOneofFieldGenerator);
|
||||
};
|
||||
|
||||
class RepeatedMessageFieldGenerator : public FieldGenerator {
|
||||
public:
|
||||
RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
|
||||
const Options& options,
|
||||
SCCAnalyzer* scc_analyzer);
|
||||
~RepeatedMessageFieldGenerator();
|
||||
|
||||
// implements FieldGenerator ---------------------------------------
|
||||
void GeneratePrivateMembers(io::Printer* printer) const;
|
||||
void GenerateAccessorDeclarations(io::Printer* printer) const;
|
||||
void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
|
||||
void GenerateClearingCode(io::Printer* printer) const;
|
||||
void GenerateMergingCode(io::Printer* printer) const;
|
||||
void GenerateSwappingCode(io::Printer* printer) const;
|
||||
void GenerateConstructorCode(io::Printer* printer) const;
|
||||
void GenerateCopyConstructorCode(io::Printer* printer) const {}
|
||||
void GenerateMergeFromCodedStream(io::Printer* printer) const;
|
||||
void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
|
||||
void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
|
||||
void GenerateByteSize(io::Printer* printer) const;
|
||||
|
||||
private:
|
||||
const FieldDescriptor* descriptor_;
|
||||
const bool implicit_weak_field_;
|
||||
std::map<string, string> variables_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedMessageFieldGenerator);
|
||||
};
|
||||
|
||||
} // namespace cpp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_FIELD_H__
|
@ -0,0 +1,61 @@
|
||||
// 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: seongkim@google.com (Seong Beom Kim)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_LAYOUT_HELPER_H__
|
||||
#define GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_LAYOUT_HELPER_H__
|
||||
|
||||
#include <google/protobuf/compiler/cpp/cpp_options.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
|
||||
// Provides an abstract interface to optimize message layout
|
||||
// by rearranging the fields of a message.
|
||||
class MessageLayoutHelper {
|
||||
public:
|
||||
virtual ~MessageLayoutHelper() {}
|
||||
|
||||
virtual void OptimizeLayout(std::vector<const FieldDescriptor*>* fields,
|
||||
const Options& options) = 0;
|
||||
};
|
||||
|
||||
} // namespace cpp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_LAYOUT_HELPER_H__
|
@ -0,0 +1,169 @@
|
||||
// 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/common.h>
|
||||
#include <google/protobuf/test_util.h>
|
||||
#include <google/protobuf/unittest.pb.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#if LANG_CXX11
|
||||
#include <type_traits>
|
||||
#endif
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
|
||||
// Can't use an anonymous namespace here due to brokenness of Tru64 compiler.
|
||||
namespace cpp_unittest {
|
||||
|
||||
// Moves are enabled only when compiling with a C++11 compiler or newer.
|
||||
#if LANG_CXX11
|
||||
|
||||
TEST(MovableMessageTest, MoveConstructor) {
|
||||
protobuf_unittest::TestAllTypes message1;
|
||||
TestUtil::SetAllFields(&message1);
|
||||
const auto* nested = &message1.optional_nested_message();
|
||||
|
||||
protobuf_unittest::TestAllTypes message2(std::move(message1));
|
||||
TestUtil::ExpectAllFieldsSet(message2);
|
||||
|
||||
// Check if the optional_nested_message was actually moved (and not just
|
||||
// copied).
|
||||
EXPECT_EQ(nested, &message2.optional_nested_message());
|
||||
EXPECT_NE(nested, &message1.optional_nested_message());
|
||||
}
|
||||
|
||||
TEST(MovableMessageTest, MoveAssignmentOperator) {
|
||||
protobuf_unittest::TestAllTypes message1;
|
||||
TestUtil::SetAllFields(&message1);
|
||||
const auto* nested = &message1.optional_nested_message();
|
||||
|
||||
protobuf_unittest::TestAllTypes message2;
|
||||
message2 = std::move(message1);
|
||||
TestUtil::ExpectAllFieldsSet(message2);
|
||||
|
||||
// Check if the optional_nested_message was actually moved (and not just
|
||||
// copied).
|
||||
EXPECT_EQ(nested, &message2.optional_nested_message());
|
||||
EXPECT_NE(nested, &message1.optional_nested_message());
|
||||
}
|
||||
|
||||
TEST(MovableMessageTest, SelfMoveAssignment) {
|
||||
// The `self` reference is necessary to defeat -Wself-move.
|
||||
protobuf_unittest::TestAllTypes message, &self = message;
|
||||
TestUtil::SetAllFields(&message);
|
||||
message = std::move(self);
|
||||
TestUtil::ExpectAllFieldsSet(message);
|
||||
}
|
||||
|
||||
TEST(MovableMessageTest, MoveSameArena) {
|
||||
Arena arena;
|
||||
|
||||
auto* message1_on_arena =
|
||||
Arena::CreateMessage<protobuf_unittest::TestAllTypes>(&arena);
|
||||
TestUtil::SetAllFields(message1_on_arena);
|
||||
const auto* nested = &message1_on_arena->optional_nested_message();
|
||||
|
||||
auto* message2_on_arena =
|
||||
Arena::CreateMessage<protobuf_unittest::TestAllTypes>(&arena);
|
||||
|
||||
// Moving messages on the same arena should lead to swapped pointers.
|
||||
*message2_on_arena = std::move(*message1_on_arena);
|
||||
EXPECT_EQ(nested, &message2_on_arena->optional_nested_message());
|
||||
}
|
||||
|
||||
TEST(MovableMessageTest, MoveDifferentArenas) {
|
||||
Arena arena1, arena2;
|
||||
|
||||
auto* message1_on_arena =
|
||||
Arena::CreateMessage<protobuf_unittest::TestAllTypes>(&arena1);
|
||||
TestUtil::SetAllFields(message1_on_arena);
|
||||
const auto* nested = &message1_on_arena->optional_nested_message();
|
||||
|
||||
auto* message2_on_arena =
|
||||
Arena::CreateMessage<protobuf_unittest::TestAllTypes>(&arena2);
|
||||
|
||||
// Moving messages on two different arenas should lead to a copy.
|
||||
*message2_on_arena = std::move(*message1_on_arena);
|
||||
EXPECT_NE(nested, &message2_on_arena->optional_nested_message());
|
||||
TestUtil::ExpectAllFieldsSet(*message1_on_arena);
|
||||
TestUtil::ExpectAllFieldsSet(*message2_on_arena);
|
||||
}
|
||||
|
||||
TEST(MovableMessageTest, MoveFromArena) {
|
||||
Arena arena;
|
||||
|
||||
auto* message1_on_arena =
|
||||
Arena::CreateMessage<protobuf_unittest::TestAllTypes>(&arena);
|
||||
TestUtil::SetAllFields(message1_on_arena);
|
||||
const auto* nested = &message1_on_arena->optional_nested_message();
|
||||
|
||||
protobuf_unittest::TestAllTypes message2;
|
||||
|
||||
// Moving from a message on the arena should lead to a copy.
|
||||
message2 = std::move(*message1_on_arena);
|
||||
EXPECT_NE(nested, &message2.optional_nested_message());
|
||||
TestUtil::ExpectAllFieldsSet(*message1_on_arena);
|
||||
TestUtil::ExpectAllFieldsSet(message2);
|
||||
}
|
||||
|
||||
TEST(MovableMessageTest, MoveToArena) {
|
||||
Arena arena;
|
||||
|
||||
protobuf_unittest::TestAllTypes message1;
|
||||
TestUtil::SetAllFields(&message1);
|
||||
const auto* nested = &message1.optional_nested_message();
|
||||
|
||||
auto* message2_on_arena =
|
||||
Arena::CreateMessage<protobuf_unittest::TestAllTypes>(&arena);
|
||||
|
||||
// Moving to a message on the arena should lead to a copy.
|
||||
*message2_on_arena = std::move(message1);
|
||||
EXPECT_NE(nested, &message2_on_arena->optional_nested_message());
|
||||
TestUtil::ExpectAllFieldsSet(message1);
|
||||
TestUtil::ExpectAllFieldsSet(*message2_on_arena);
|
||||
}
|
||||
|
||||
TEST(MovableMessageTest, Noexcept) {
|
||||
EXPECT_TRUE(
|
||||
std::is_nothrow_move_constructible<protobuf_unittest::TestAllTypes>());
|
||||
EXPECT_TRUE(std::is_nothrow_move_assignable<protobuf_unittest::TestAllTypes>());
|
||||
}
|
||||
|
||||
#endif // LANG_CXX11
|
||||
|
||||
} // namespace cpp_unittest
|
||||
|
||||
} // namespace cpp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
@ -0,0 +1,83 @@
|
||||
// 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: rennie@google.com (Jeffrey Rennie)
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_OPTIONS_H__
|
||||
#define GOOGLE_PROTOBUF_COMPILER_CPP_OPTIONS_H__
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
class AccessInfoMap;
|
||||
|
||||
namespace cpp {
|
||||
|
||||
// Generator options (see generator.cc for a description of each):
|
||||
struct Options {
|
||||
Options()
|
||||
: safe_boundary_check(false),
|
||||
proto_h(false),
|
||||
transitive_pb_h(true),
|
||||
annotate_headers(false),
|
||||
enforce_lite(false),
|
||||
table_driven_parsing(false),
|
||||
table_driven_serialization(false),
|
||||
lite_implicit_weak_fields(false),
|
||||
bootstrap(false),
|
||||
num_cc_files(0),
|
||||
access_info_map(NULL) {}
|
||||
|
||||
string dllexport_decl;
|
||||
bool safe_boundary_check;
|
||||
bool proto_h;
|
||||
bool transitive_pb_h;
|
||||
bool annotate_headers;
|
||||
bool enforce_lite;
|
||||
bool table_driven_parsing;
|
||||
bool table_driven_serialization;
|
||||
bool lite_implicit_weak_fields;
|
||||
bool bootstrap;
|
||||
int num_cc_files;
|
||||
string annotation_pragma_name;
|
||||
string annotation_guard_name;
|
||||
const AccessInfoMap* access_info_map;
|
||||
};
|
||||
|
||||
} // namespace cpp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_OPTIONS_H__
|
@ -0,0 +1,220 @@
|
||||
// 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/compiler/cpp/cpp_padding_optimizer.h>
|
||||
|
||||
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
|
||||
namespace {
|
||||
|
||||
// FieldGroup is just a helper for PaddingOptimizer below. It holds a vector of
|
||||
// fields that are grouped together because they have compatible alignment, and
|
||||
// a preferred location in the final field ordering.
|
||||
class FieldGroup {
|
||||
public:
|
||||
FieldGroup() : preferred_location_(0) {}
|
||||
|
||||
// A group with a single field.
|
||||
FieldGroup(float preferred_location, const FieldDescriptor* field)
|
||||
: preferred_location_(preferred_location), fields_(1, field) {}
|
||||
|
||||
// Append the fields in 'other' to this group.
|
||||
void Append(const FieldGroup& other) {
|
||||
if (other.fields_.empty()) {
|
||||
return;
|
||||
}
|
||||
// Preferred location is the average among all the fields, so we weight by
|
||||
// the number of fields on each FieldGroup object.
|
||||
preferred_location_ = (preferred_location_ * fields_.size() +
|
||||
(other.preferred_location_ * other.fields_.size())) /
|
||||
(fields_.size() + other.fields_.size());
|
||||
fields_.insert(fields_.end(), other.fields_.begin(), other.fields_.end());
|
||||
}
|
||||
|
||||
void SetPreferredLocation(float location) { preferred_location_ = location; }
|
||||
const std::vector<const FieldDescriptor*>& fields() const { return fields_; }
|
||||
|
||||
// FieldGroup objects sort by their preferred location.
|
||||
bool operator<(const FieldGroup& other) const {
|
||||
return preferred_location_ < other.preferred_location_;
|
||||
}
|
||||
|
||||
private:
|
||||
// "preferred_location_" is an estimate of where this group should go in the
|
||||
// final list of fields. We compute this by taking the average index of each
|
||||
// field in this group in the original ordering of fields. This is very
|
||||
// approximate, but should put this group close to where its member fields
|
||||
// originally went.
|
||||
float preferred_location_;
|
||||
std::vector<const FieldDescriptor*> fields_;
|
||||
// We rely on the default copy constructor and operator= so this type can be
|
||||
// used in a vector.
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
// Reorder 'fields' so that if the fields are output into a c++ class in the new
|
||||
// order, fields of similar family (see below) are together and within each
|
||||
// family, alignment padding is minimized.
|
||||
//
|
||||
// We try to do this while keeping each field as close as possible to its field
|
||||
// number order so that we don't reduce cache locality much for function that
|
||||
// access each field in order. Originally, OptimizePadding used declaration
|
||||
// order for its decisions, but generated code minus the serializer/parsers uses
|
||||
// the output of OptimizePadding as well (stored in
|
||||
// MessageGenerator::optimized_order_). Since the serializers use field number
|
||||
// order, we use that as a tie-breaker.
|
||||
//
|
||||
// We classify each field into a particular "family" of fields, that we perform
|
||||
// the same operation on in our generated functions.
|
||||
//
|
||||
// REPEATED is placed first, as the C++ compiler automatically initializes
|
||||
// these fields in layout order.
|
||||
//
|
||||
// STRING is grouped next, as our Clear/SharedCtor/SharedDtor walks it and
|
||||
// calls ArenaStringPtr::Destroy on each.
|
||||
//
|
||||
//
|
||||
// MESSAGE is grouped next, as our Clear/SharedDtor code walks it and calls
|
||||
// delete on each. We initialize these fields with a NULL pointer (see
|
||||
// MessageFieldGenerator::GenerateConstructorCode), which allows them to be
|
||||
// memset.
|
||||
//
|
||||
// ZERO_INITIALIZABLE is memset in Clear/SharedCtor
|
||||
//
|
||||
// OTHER these fields are initialized one-by-one.
|
||||
void PaddingOptimizer::OptimizeLayout(
|
||||
std::vector<const FieldDescriptor*>* fields, const Options& options) {
|
||||
// The sorted numeric order of Family determines the declaration order in the
|
||||
// memory layout.
|
||||
enum Family {
|
||||
REPEATED = 0,
|
||||
STRING = 1,
|
||||
MESSAGE = 3,
|
||||
ZERO_INITIALIZABLE = 4,
|
||||
OTHER = 5,
|
||||
kMaxFamily
|
||||
};
|
||||
|
||||
// First divide fields into those that align to 1 byte, 4 bytes or 8 bytes.
|
||||
std::vector<FieldGroup> aligned_to_1[kMaxFamily];
|
||||
std::vector<FieldGroup> aligned_to_4[kMaxFamily];
|
||||
std::vector<FieldGroup> aligned_to_8[kMaxFamily];
|
||||
for (int i = 0; i < fields->size(); ++i) {
|
||||
const FieldDescriptor* field = (*fields)[i];
|
||||
|
||||
Family f = OTHER;
|
||||
if (field->is_repeated()) {
|
||||
f = REPEATED;
|
||||
} else if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
|
||||
f = STRING;
|
||||
} else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
|
||||
f = MESSAGE;
|
||||
|
||||
} else if (CanInitializeByZeroing(field)) {
|
||||
f = ZERO_INITIALIZABLE;
|
||||
}
|
||||
|
||||
const int j = field->number();
|
||||
switch (EstimateAlignmentSize(field)) {
|
||||
case 1:
|
||||
aligned_to_1[f].push_back(FieldGroup(j, field));
|
||||
break;
|
||||
case 4:
|
||||
aligned_to_4[f].push_back(FieldGroup(j, field));
|
||||
break;
|
||||
case 8:
|
||||
aligned_to_8[f].push_back(FieldGroup(j, field));
|
||||
break;
|
||||
default:
|
||||
GOOGLE_LOG(FATAL) << "Unknown alignment size " << EstimateAlignmentSize(field)
|
||||
<< "for a field " << field->full_name() << ".";
|
||||
}
|
||||
}
|
||||
|
||||
// For each family, group fields to optimize padding.
|
||||
for (int f = 0; f < kMaxFamily; f++) {
|
||||
// Now group fields aligned to 1 byte into sets of 4, and treat those like a
|
||||
// single field aligned to 4 bytes.
|
||||
for (int i = 0; i < aligned_to_1[f].size(); i += 4) {
|
||||
FieldGroup field_group;
|
||||
for (int j = i; j < aligned_to_1[f].size() && j < i + 4; ++j) {
|
||||
field_group.Append(aligned_to_1[f][j]);
|
||||
}
|
||||
aligned_to_4[f].push_back(field_group);
|
||||
}
|
||||
// Sort by preferred location to keep fields as close to their field number
|
||||
// order as possible. Using stable_sort ensures that the output is
|
||||
// consistent across runs.
|
||||
std::stable_sort(aligned_to_4[f].begin(), aligned_to_4[f].end());
|
||||
|
||||
// Now group fields aligned to 4 bytes (or the 4-field groups created above)
|
||||
// into pairs, and treat those like a single field aligned to 8 bytes.
|
||||
for (int i = 0; i < aligned_to_4[f].size(); i += 2) {
|
||||
FieldGroup field_group;
|
||||
for (int j = i; j < aligned_to_4[f].size() && j < i + 2; ++j) {
|
||||
field_group.Append(aligned_to_4[f][j]);
|
||||
}
|
||||
if (i == aligned_to_4[f].size() - 1) {
|
||||
if (f == OTHER) {
|
||||
// Move incomplete 4-byte block to the beginning. This is done to
|
||||
// pair with the (possible) leftover blocks from the
|
||||
// ZERO_INITIALIZABLE family.
|
||||
field_group.SetPreferredLocation(-1);
|
||||
} else {
|
||||
// Move incomplete 4-byte block to the end.
|
||||
field_group.SetPreferredLocation(fields->size() + 1);
|
||||
}
|
||||
}
|
||||
aligned_to_8[f].push_back(field_group);
|
||||
}
|
||||
// Sort by preferred location.
|
||||
std::stable_sort(aligned_to_8[f].begin(), aligned_to_8[f].end());
|
||||
}
|
||||
|
||||
// Now pull out all the FieldDescriptors in order.
|
||||
fields->clear();
|
||||
for (int f = 0; f < kMaxFamily; ++f) {
|
||||
for (int i = 0; i < aligned_to_8[f].size(); ++i) {
|
||||
fields->insert(fields->end(), aligned_to_8[f][i].fields().begin(),
|
||||
aligned_to_8[f][i].fields().end());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace cpp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
@ -0,0 +1,64 @@
|
||||
// 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: seongkim@google.com (Seong Beom Kim)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_PADDING_OPTIMIZER_H__
|
||||
#define GOOGLE_PROTOBUF_COMPILER_CPP_PADDING_OPTIMIZER_H__
|
||||
|
||||
#include <google/protobuf/compiler/cpp/cpp_message_layout_helper.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
|
||||
// Rearranges the fields of a message to minimize padding.
|
||||
// Fields are grouped by the type and the size.
|
||||
// For example, grouping four boolean fields and one int32
|
||||
// field results in zero padding overhead. See OptimizeLayout's
|
||||
// comment for details.
|
||||
class PaddingOptimizer : public MessageLayoutHelper {
|
||||
public:
|
||||
PaddingOptimizer() {}
|
||||
~PaddingOptimizer() override {}
|
||||
|
||||
void OptimizeLayout(std::vector<const FieldDescriptor*>* fields,
|
||||
const Options& options) override;
|
||||
};
|
||||
|
||||
} // namespace cpp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_PADDING_OPTIMIZER_H__
|
@ -0,0 +1,249 @@
|
||||
// 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)
|
||||
//
|
||||
// TODO(kenton): Share code with the versions of this test in other languages?
|
||||
// It seemed like parameterizing it would add more complexity than it is
|
||||
// worth.
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <google/protobuf/compiler/cpp/cpp_generator.h>
|
||||
#include <google/protobuf/compiler/command_line_interface.h>
|
||||
#include <google/protobuf/io/zero_copy_stream.h>
|
||||
#include <google/protobuf/io/printer.h>
|
||||
|
||||
#include <google/protobuf/testing/file.h>
|
||||
#include <google/protobuf/testing/file.h>
|
||||
#include <google/protobuf/testing/googletest.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
namespace {
|
||||
|
||||
class TestGenerator : public CodeGenerator {
|
||||
public:
|
||||
TestGenerator() {}
|
||||
~TestGenerator() {}
|
||||
|
||||
virtual bool Generate(const FileDescriptor* file,
|
||||
const string& parameter,
|
||||
GeneratorContext* context,
|
||||
string* error) const {
|
||||
TryInsert("test.pb.h", "includes", context);
|
||||
TryInsert("test.pb.h", "namespace_scope", context);
|
||||
TryInsert("test.pb.h", "global_scope", context);
|
||||
TryInsert("test.pb.h", "class_scope:foo.Bar", context);
|
||||
TryInsert("test.pb.h", "class_scope:foo.Bar.Baz", context);
|
||||
|
||||
TryInsert("test.pb.cc", "includes", context);
|
||||
TryInsert("test.pb.cc", "namespace_scope", context);
|
||||
TryInsert("test.pb.cc", "global_scope", context);
|
||||
|
||||
// Check field accessors for an optional int32:
|
||||
TryInsert("test.pb.h", "field_get:foo.Bar.optInt", context);
|
||||
TryInsert("test.pb.h", "field_set:foo.Bar.optInt", context);
|
||||
|
||||
// Check field accessors for a repeated int32:
|
||||
TryInsert("test.pb.h", "field_get:foo.Bar.repeatedInt", context);
|
||||
TryInsert("test.pb.h", "field_set:foo.Bar.repeatedInt", context);
|
||||
|
||||
// Check field accessors for a required string:
|
||||
TryInsert("test.pb.h", "field_get:foo.Bar.requiredString", context);
|
||||
TryInsert("test.pb.h", "field_set:foo.Bar.requiredString", context);
|
||||
TryInsert("test.pb.h", "field_set_char:foo.Bar.requiredString", context);
|
||||
TryInsert("test.pb.h", "field_set_pointer:foo.Bar.requiredString", context);
|
||||
TryInsert("test.pb.h", "field_mutable:foo.Bar.requiredString", context);
|
||||
TryInsert("test.pb.h", "field_set_allocated:foo.Bar.requiredString",
|
||||
context);
|
||||
TryInsert("test.pb.h", "field_set_char:foo.Bar.requiredString", context);
|
||||
TryInsert("test.pb.h", "field_set_pointer:foo.Bar.requiredString", context);
|
||||
|
||||
// Check field accessors for a repeated string:
|
||||
TryInsert("test.pb.h", "field_get:foo.Bar.repeatedString", context);
|
||||
TryInsert("test.pb.h", "field_set:foo.Bar.repeatedString", context);
|
||||
TryInsert("test.pb.h", "field_set_char:foo.Bar.repeatedString", context);
|
||||
TryInsert("test.pb.h", "field_set_pointer:foo.Bar.repeatedString", context);
|
||||
TryInsert("test.pb.h", "field_mutable:foo.Bar.repeatedString", context);
|
||||
TryInsert("test.pb.h", "field_set_char:foo.Bar.repeatedString", context);
|
||||
TryInsert("test.pb.h", "field_set_pointer:foo.Bar.repeatedString", context);
|
||||
|
||||
// Check field accessors for an int inside oneof{}:
|
||||
TryInsert("test.pb.h", "field_get:foo.Bar.oneOfInt", context);
|
||||
TryInsert("test.pb.h", "field_set:foo.Bar.oneOfInt", context);
|
||||
|
||||
// Check field accessors for a string inside oneof{}:
|
||||
TryInsert("test.pb.h", "field_get:foo.Bar.oneOfString", context);
|
||||
TryInsert("test.pb.h", "field_set:foo.Bar.oneOfString", context);
|
||||
TryInsert("test.pb.h", "field_set_char:foo.Bar.oneOfString", context);
|
||||
TryInsert("test.pb.h", "field_set_pointer:foo.Bar.oneOfString", context);
|
||||
TryInsert("test.pb.h", "field_mutable:foo.Bar.oneOfString", context);
|
||||
TryInsert("test.pb.h", "field_set_allocated:foo.Bar.oneOfString", context);
|
||||
TryInsert("test.pb.h", "field_set_char:foo.Bar.oneOfString", context);
|
||||
TryInsert("test.pb.h", "field_set_pointer:foo.Bar.oneOfString", context);
|
||||
|
||||
// Check field accessors for an optional message:
|
||||
TryInsert("test.pb.h", "field_get:foo.Bar.optMessage", context);
|
||||
TryInsert("test.pb.h", "field_mutable:foo.Bar.optMessage", context);
|
||||
TryInsert("test.pb.h", "field_set_allocated:foo.Bar.optMessage", context);
|
||||
|
||||
// Check field accessors for a repeated message:
|
||||
TryInsert("test.pb.h", "field_add:foo.Bar.repeatedMessage", context);
|
||||
TryInsert("test.pb.h", "field_get:foo.Bar.repeatedMessage", context);
|
||||
TryInsert("test.pb.h", "field_list:foo.Bar.repeatedMessage", context);
|
||||
TryInsert("test.pb.h", "field_mutable:foo.Bar.repeatedMessage", context);
|
||||
TryInsert("test.pb.h", "field_mutable_list:foo.Bar.repeatedMessage",
|
||||
context);
|
||||
|
||||
// Check field accessors for a message inside oneof{}:
|
||||
TryInsert("test.pb.h", "field_get:foo.Bar.oneOfMessage", context);
|
||||
TryInsert("test.pb.h", "field_mutable:foo.Bar.oneOfMessage", context);
|
||||
TryInsert("test.pb.cc", "field_set_allocated:foo.Bar.oneOfMessage", context);
|
||||
|
||||
// Check field accessors for an optional enum:
|
||||
TryInsert("test.pb.h", "field_get:foo.Bar.optEnum", context);
|
||||
TryInsert("test.pb.h", "field_set:foo.Bar.optEnum", context);
|
||||
|
||||
// Check field accessors for a repeated enum:
|
||||
TryInsert("test.pb.h", "field_get:foo.Bar.repeatedEnum", context);
|
||||
TryInsert("test.pb.h", "field_set:foo.Bar.repeatedEnum", context);
|
||||
TryInsert("test.pb.h", "field_add:foo.Bar.repeatedEnum", context);
|
||||
TryInsert("test.pb.h", "field_list:foo.Bar.repeatedEnum", context);
|
||||
TryInsert("test.pb.h", "field_mutable_list:foo.Bar.repeatedEnum", context);
|
||||
|
||||
// Check field accessors for an enum inside oneof{}:
|
||||
TryInsert("test.pb.h", "field_get:foo.Bar.oneOfEnum", context);
|
||||
TryInsert("test.pb.h", "field_set:foo.Bar.oneOfEnum", context);
|
||||
|
||||
// Check field accessors for a required cord:
|
||||
TryInsert("test.pb.h", "field_get:foo.Bar.requiredCord", context);
|
||||
TryInsert("test.pb.h", "field_set:foo.Bar.requiredCord", context);
|
||||
TryInsert("test.pb.h", "field_mutable:foo.Bar.requiredCord", context);
|
||||
|
||||
// Check field accessors for a repeated cord:
|
||||
TryInsert("test.pb.h", "field_get:foo.Bar.repeatedCord", context);
|
||||
TryInsert("test.pb.h", "field_set:foo.Bar.repeatedCord", context);
|
||||
TryInsert("test.pb.h", "field_add:foo.Bar.repeatedCord", context);
|
||||
TryInsert("test.pb.h", "field_list:foo.Bar.repeatedCord", context);
|
||||
TryInsert("test.pb.h", "field_mutable:foo.Bar.repeatedCord", context);
|
||||
TryInsert("test.pb.h", "field_mutable_list:foo.Bar.repeatedCord", context);
|
||||
|
||||
// Check field accessors for a cord inside oneof{}:
|
||||
TryInsert("test.pb.h", "field_get:foo.Bar.oneOfCord", context);
|
||||
TryInsert("test.pb.h", "field_set:foo.Bar.oneOfCord", context);
|
||||
TryInsert("test.pb.h", "field_mutable:foo.Bar.oneOfCord", context);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void TryInsert(const string& filename, const string& insertion_point,
|
||||
GeneratorContext* context) const {
|
||||
std::unique_ptr<io::ZeroCopyOutputStream> output(
|
||||
context->OpenForInsert(filename, insertion_point));
|
||||
io::Printer printer(output.get(), '$');
|
||||
printer.Print("// inserted $name$\n", "name", insertion_point);
|
||||
}
|
||||
};
|
||||
|
||||
// This test verifies that all the expected insertion points exist. It does
|
||||
// not verify that they are correctly-placed; that would require actually
|
||||
// compiling the output which is a bit more than I care to do for this test.
|
||||
TEST(CppPluginTest, PluginTest) {
|
||||
GOOGLE_CHECK_OK(File::SetContents(TestTempDir() + "/test.proto",
|
||||
"syntax = \"proto2\";\n"
|
||||
"package foo;\n"
|
||||
"\n"
|
||||
"enum Thud { VALUE = 0; }\n"
|
||||
"\n"
|
||||
"message Bar {\n"
|
||||
" message Baz {}\n"
|
||||
" optional int32 optInt = 1;\n"
|
||||
" repeated int32 repeatedInt = 2;\n"
|
||||
"\n"
|
||||
" required string requiredString = 3;\n"
|
||||
" repeated string repeatedString = 4;\n"
|
||||
"\n"
|
||||
" optional Baz optMessage = 6;\n"
|
||||
" repeated Baz repeatedMessage = 7;\n"
|
||||
"\n"
|
||||
" optional Thud optEnum = 8;\n"
|
||||
" repeated Thud repeatedEnum = 9;\n"
|
||||
"\n"
|
||||
" required string requiredCord = 10 [\n"
|
||||
" ctype = CORD\n"
|
||||
" ];\n"
|
||||
" repeated string repeatedCord = 11 [\n"
|
||||
" ctype = CORD\n"
|
||||
" ];\n"
|
||||
"\n"
|
||||
" oneof Qux {\n"
|
||||
" int64 oneOfInt = 20;\n"
|
||||
" string oneOfString = 21;\n"
|
||||
" Baz oneOfMessage = 22;\n"
|
||||
" Thud oneOfEnum = 23;"
|
||||
" string oneOfCord = 24 [\n"
|
||||
" ctype = CORD\n"
|
||||
" ];\n"
|
||||
" }\n"
|
||||
"}\n",
|
||||
true));
|
||||
|
||||
google::protobuf::compiler::CommandLineInterface cli;
|
||||
cli.SetInputsAreProtoPathRelative(true);
|
||||
|
||||
CppGenerator cpp_generator;
|
||||
TestGenerator test_generator;
|
||||
cli.RegisterGenerator("--cpp_out", &cpp_generator, "");
|
||||
cli.RegisterGenerator("--test_out", &test_generator, "");
|
||||
|
||||
string proto_path = "-I" + TestTempDir();
|
||||
string cpp_out = "--cpp_out=" + TestTempDir();
|
||||
string test_out = "--test_out=" + TestTempDir();
|
||||
|
||||
const char* argv[] = {
|
||||
"protoc",
|
||||
proto_path.c_str(),
|
||||
cpp_out.c_str(),
|
||||
test_out.c_str(),
|
||||
"test.proto"
|
||||
};
|
||||
|
||||
EXPECT_EQ(0, cli.Run(5, argv));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace cpp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
@ -0,0 +1,481 @@
|
||||
// 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/compiler/cpp/cpp_primitive_field.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
|
||||
#include <google/protobuf/io/printer.h>
|
||||
#include <google/protobuf/wire_format.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
|
||||
using internal::WireFormatLite;
|
||||
|
||||
namespace {
|
||||
|
||||
// For encodings with fixed sizes, returns that size in bytes. Otherwise
|
||||
// returns -1.
|
||||
int FixedSize(FieldDescriptor::Type type) {
|
||||
switch (type) {
|
||||
case FieldDescriptor::TYPE_INT32 : return -1;
|
||||
case FieldDescriptor::TYPE_INT64 : return -1;
|
||||
case FieldDescriptor::TYPE_UINT32 : return -1;
|
||||
case FieldDescriptor::TYPE_UINT64 : return -1;
|
||||
case FieldDescriptor::TYPE_SINT32 : return -1;
|
||||
case FieldDescriptor::TYPE_SINT64 : return -1;
|
||||
case FieldDescriptor::TYPE_FIXED32 : return WireFormatLite::kFixed32Size;
|
||||
case FieldDescriptor::TYPE_FIXED64 : return WireFormatLite::kFixed64Size;
|
||||
case FieldDescriptor::TYPE_SFIXED32: return WireFormatLite::kSFixed32Size;
|
||||
case FieldDescriptor::TYPE_SFIXED64: return WireFormatLite::kSFixed64Size;
|
||||
case FieldDescriptor::TYPE_FLOAT : return WireFormatLite::kFloatSize;
|
||||
case FieldDescriptor::TYPE_DOUBLE : return WireFormatLite::kDoubleSize;
|
||||
|
||||
case FieldDescriptor::TYPE_BOOL : return WireFormatLite::kBoolSize;
|
||||
case FieldDescriptor::TYPE_ENUM : return -1;
|
||||
|
||||
case FieldDescriptor::TYPE_STRING : return -1;
|
||||
case FieldDescriptor::TYPE_BYTES : return -1;
|
||||
case FieldDescriptor::TYPE_GROUP : return -1;
|
||||
case FieldDescriptor::TYPE_MESSAGE : return -1;
|
||||
|
||||
// No default because we want the compiler to complain if any new
|
||||
// types are added.
|
||||
}
|
||||
GOOGLE_LOG(FATAL) << "Can't get here.";
|
||||
return -1;
|
||||
}
|
||||
|
||||
void SetPrimitiveVariables(const FieldDescriptor* descriptor,
|
||||
std::map<string, string>* variables,
|
||||
const Options& options) {
|
||||
SetCommonFieldVariables(descriptor, variables, options);
|
||||
(*variables)["type"] = PrimitiveTypeName(descriptor->cpp_type());
|
||||
(*variables)["default"] = DefaultValue(descriptor);
|
||||
(*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));
|
||||
int fixed_size = FixedSize(descriptor->type());
|
||||
if (fixed_size != -1) {
|
||||
(*variables)["fixed_size"] = SimpleItoa(fixed_size);
|
||||
}
|
||||
(*variables)["wire_format_field_type"] =
|
||||
"::google::protobuf::internal::WireFormatLite::" + FieldDescriptorProto_Type_Name(
|
||||
static_cast<FieldDescriptorProto_Type>(descriptor->type()));
|
||||
(*variables)["full_name"] = descriptor->full_name();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// ===================================================================
|
||||
|
||||
PrimitiveFieldGenerator::PrimitiveFieldGenerator(
|
||||
const FieldDescriptor* descriptor, const Options& options)
|
||||
: FieldGenerator(options), descriptor_(descriptor) {
|
||||
SetPrimitiveVariables(descriptor, &variables_, options);
|
||||
}
|
||||
|
||||
PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {}
|
||||
|
||||
void PrimitiveFieldGenerator::
|
||||
GeneratePrivateMembers(io::Printer* printer) const {
|
||||
printer->Print(variables_, "$type$ $name$_;\n");
|
||||
}
|
||||
|
||||
void PrimitiveFieldGenerator::
|
||||
GenerateAccessorDeclarations(io::Printer* printer) const {
|
||||
printer->Print(variables_, "$deprecated_attr$$type$ $name$() const;\n");
|
||||
printer->Annotate("name", descriptor_);
|
||||
printer->Print(variables_,
|
||||
"$deprecated_attr$void ${$set_$name$$}$($type$ value);\n");
|
||||
printer->Annotate("{", "}", descriptor_);
|
||||
}
|
||||
|
||||
void PrimitiveFieldGenerator::
|
||||
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"inline $type$ $classname$::$name$() const {\n"
|
||||
" // @@protoc_insertion_point(field_get:$full_name$)\n"
|
||||
" return $name$_;\n"
|
||||
"}\n"
|
||||
"inline void $classname$::set_$name$($type$ value) {\n"
|
||||
" $set_hasbit$\n"
|
||||
" $name$_ = value;\n"
|
||||
" // @@protoc_insertion_point(field_set:$full_name$)\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void PrimitiveFieldGenerator::
|
||||
GenerateClearingCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "$name$_ = $default$;\n");
|
||||
}
|
||||
|
||||
void PrimitiveFieldGenerator::
|
||||
GenerateMergingCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "set_$name$(from.$name$());\n");
|
||||
}
|
||||
|
||||
void PrimitiveFieldGenerator::
|
||||
GenerateSwappingCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "swap($name$_, other->$name$_);\n");
|
||||
}
|
||||
|
||||
void PrimitiveFieldGenerator::
|
||||
GenerateConstructorCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "$name$_ = $default$;\n");
|
||||
}
|
||||
|
||||
void PrimitiveFieldGenerator::
|
||||
GenerateCopyConstructorCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "$name$_ = from.$name$_;\n");
|
||||
}
|
||||
|
||||
void PrimitiveFieldGenerator::
|
||||
GenerateMergeFromCodedStream(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"$set_hasbit$\n"
|
||||
"DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
|
||||
" $type$, $wire_format_field_type$>(\n"
|
||||
" input, &$name$_)));\n");
|
||||
}
|
||||
|
||||
void PrimitiveFieldGenerator::
|
||||
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"::google::protobuf::internal::WireFormatLite::Write$declared_type$("
|
||||
"$number$, this->$name$(), output);\n");
|
||||
}
|
||||
|
||||
void PrimitiveFieldGenerator::
|
||||
GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"target = ::google::protobuf::internal::WireFormatLite::Write$declared_type$ToArray("
|
||||
"$number$, this->$name$(), target);\n");
|
||||
}
|
||||
|
||||
void PrimitiveFieldGenerator::
|
||||
GenerateByteSize(io::Printer* printer) const {
|
||||
int fixed_size = FixedSize(descriptor_->type());
|
||||
if (fixed_size == -1) {
|
||||
printer->Print(variables_,
|
||||
"total_size += $tag_size$ +\n"
|
||||
" ::google::protobuf::internal::WireFormatLite::$declared_type$Size(\n"
|
||||
" this->$name$());\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
"total_size += $tag_size$ + $fixed_size$;\n");
|
||||
}
|
||||
}
|
||||
|
||||
// ===================================================================
|
||||
|
||||
PrimitiveOneofFieldGenerator::
|
||||
PrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor,
|
||||
const Options& options)
|
||||
: PrimitiveFieldGenerator(descriptor, options) {
|
||||
SetCommonOneofFieldVariables(descriptor, &variables_);
|
||||
}
|
||||
|
||||
PrimitiveOneofFieldGenerator::~PrimitiveOneofFieldGenerator() {}
|
||||
|
||||
void PrimitiveOneofFieldGenerator::
|
||||
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"inline $type$ $classname$::$name$() const {\n"
|
||||
" // @@protoc_insertion_point(field_get:$full_name$)\n"
|
||||
" if (has_$name$()) {\n"
|
||||
" return $field_member$;\n"
|
||||
" }\n"
|
||||
" return $default$;\n"
|
||||
"}\n"
|
||||
"inline void $classname$::set_$name$($type$ value) {\n"
|
||||
" if (!has_$name$()) {\n"
|
||||
" clear_$oneof_name$();\n"
|
||||
" set_has_$name$();\n"
|
||||
" }\n"
|
||||
" $field_member$ = value;\n"
|
||||
" // @@protoc_insertion_point(field_set:$full_name$)\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void PrimitiveOneofFieldGenerator::
|
||||
GenerateClearingCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "$field_member$ = $default$;\n");
|
||||
}
|
||||
|
||||
void PrimitiveOneofFieldGenerator::
|
||||
GenerateSwappingCode(io::Printer* printer) const {
|
||||
// Don't print any swapping code. Swapping the union will swap this field.
|
||||
}
|
||||
|
||||
void PrimitiveOneofFieldGenerator::
|
||||
GenerateConstructorCode(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"$ns$::_$classname$_default_instance_.$name$_ = $default$;\n");
|
||||
}
|
||||
|
||||
void PrimitiveOneofFieldGenerator::
|
||||
GenerateMergeFromCodedStream(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"clear_$oneof_name$();\n"
|
||||
"DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
|
||||
" $type$, $wire_format_field_type$>(\n"
|
||||
" input, &$field_member$)));\n"
|
||||
"set_has_$name$();\n");
|
||||
}
|
||||
|
||||
// ===================================================================
|
||||
|
||||
RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator(
|
||||
const FieldDescriptor* descriptor, const Options& options)
|
||||
: FieldGenerator(options), descriptor_(descriptor) {
|
||||
SetPrimitiveVariables(descriptor, &variables_, options);
|
||||
|
||||
if (descriptor->is_packed()) {
|
||||
variables_["packed_reader"] = "ReadPackedPrimitive";
|
||||
variables_["repeated_reader"] = "ReadRepeatedPrimitiveNoInline";
|
||||
} else {
|
||||
variables_["packed_reader"] = "ReadPackedPrimitiveNoInline";
|
||||
variables_["repeated_reader"] = "ReadRepeatedPrimitive";
|
||||
}
|
||||
}
|
||||
|
||||
RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {}
|
||||
|
||||
void RepeatedPrimitiveFieldGenerator::
|
||||
GeneratePrivateMembers(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"::google::protobuf::RepeatedField< $type$ > $name$_;\n");
|
||||
if (descriptor_->is_packed() &&
|
||||
HasGeneratedMethods(descriptor_->file(), options_)) {
|
||||
printer->Print(variables_,
|
||||
"mutable int _$name$_cached_byte_size_;\n");
|
||||
}
|
||||
}
|
||||
|
||||
void RepeatedPrimitiveFieldGenerator::
|
||||
GenerateAccessorDeclarations(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"$deprecated_attr$$type$ $name$(int index) const;\n");
|
||||
printer->Annotate("name", descriptor_);
|
||||
printer->Print(
|
||||
variables_,
|
||||
"$deprecated_attr$void ${$set_$name$$}$(int index, $type$ value);\n");
|
||||
printer->Annotate("{", "}", descriptor_);
|
||||
printer->Print(variables_,
|
||||
"$deprecated_attr$void ${$add_$name$$}$($type$ value);\n");
|
||||
printer->Annotate("{", "}", descriptor_);
|
||||
printer->Print(variables_,
|
||||
"$deprecated_attr$const ::google::protobuf::RepeatedField< $type$ >&\n"
|
||||
" $name$() const;\n");
|
||||
printer->Annotate("name", descriptor_);
|
||||
printer->Print(variables_,
|
||||
"$deprecated_attr$::google::protobuf::RepeatedField< $type$ >*\n"
|
||||
" ${$mutable_$name$$}$();\n");
|
||||
printer->Annotate("{", "}", descriptor_);
|
||||
}
|
||||
|
||||
void RepeatedPrimitiveFieldGenerator::
|
||||
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"inline $type$ $classname$::$name$(int index) const {\n"
|
||||
" // @@protoc_insertion_point(field_get:$full_name$)\n"
|
||||
" return $name$_.Get(index);\n"
|
||||
"}\n"
|
||||
"inline void $classname$::set_$name$(int index, $type$ value) {\n"
|
||||
" $name$_.Set(index, value);\n"
|
||||
" // @@protoc_insertion_point(field_set:$full_name$)\n"
|
||||
"}\n"
|
||||
"inline void $classname$::add_$name$($type$ value) {\n"
|
||||
" $name$_.Add(value);\n"
|
||||
" // @@protoc_insertion_point(field_add:$full_name$)\n"
|
||||
"}\n"
|
||||
"inline const ::google::protobuf::RepeatedField< $type$ >&\n"
|
||||
"$classname$::$name$() const {\n"
|
||||
" // @@protoc_insertion_point(field_list:$full_name$)\n"
|
||||
" return $name$_;\n"
|
||||
"}\n"
|
||||
"inline ::google::protobuf::RepeatedField< $type$ >*\n"
|
||||
"$classname$::mutable_$name$() {\n"
|
||||
" // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
|
||||
" return &$name$_;\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void RepeatedPrimitiveFieldGenerator::
|
||||
GenerateClearingCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "$name$_.Clear();\n");
|
||||
}
|
||||
|
||||
void RepeatedPrimitiveFieldGenerator::
|
||||
GenerateMergingCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n");
|
||||
}
|
||||
|
||||
void RepeatedPrimitiveFieldGenerator::
|
||||
GenerateSwappingCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "$name$_.InternalSwap(&other->$name$_);\n");
|
||||
}
|
||||
|
||||
void RepeatedPrimitiveFieldGenerator::
|
||||
GenerateConstructorCode(io::Printer* printer) const {
|
||||
// Not needed for repeated fields.
|
||||
}
|
||||
|
||||
void RepeatedPrimitiveFieldGenerator::
|
||||
GenerateCopyConstructorCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "$name$_.CopyFrom(from.$name$_);\n");
|
||||
}
|
||||
|
||||
void RepeatedPrimitiveFieldGenerator::
|
||||
GenerateMergeFromCodedStream(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"DO_((::google::protobuf::internal::WireFormatLite::$repeated_reader$<\n"
|
||||
" $type$, $wire_format_field_type$>(\n"
|
||||
" $tag_size$, $tag$u, input, this->mutable_$name$())));\n");
|
||||
}
|
||||
|
||||
void RepeatedPrimitiveFieldGenerator::
|
||||
GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"DO_((::google::protobuf::internal::WireFormatLite::$packed_reader$<\n"
|
||||
" $type$, $wire_format_field_type$>(\n"
|
||||
" input, this->mutable_$name$())));\n");
|
||||
}
|
||||
|
||||
void RepeatedPrimitiveFieldGenerator::
|
||||
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
|
||||
bool array_written = false;
|
||||
if (descriptor_->is_packed()) {
|
||||
// Write the tag and the size.
|
||||
printer->Print(variables_,
|
||||
"if (this->$name$_size() > 0) {\n"
|
||||
" ::google::protobuf::internal::WireFormatLite::WriteTag("
|
||||
"$number$, "
|
||||
"::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, "
|
||||
"output);\n"
|
||||
" output->WriteVarint32(static_cast< ::google::protobuf::uint32>(\n"
|
||||
" _$name$_cached_byte_size_));\n");
|
||||
|
||||
if (FixedSize(descriptor_->type()) > 0) {
|
||||
// TODO(ckennelly): Use RepeatedField<T>::unsafe_data() via
|
||||
// WireFormatLite to access the contents of this->$name$_ to save a branch
|
||||
// here.
|
||||
printer->Print(variables_,
|
||||
" ::google::protobuf::internal::WireFormatLite::Write$declared_type$Array(\n"
|
||||
" this->$name$().data(), this->$name$_size(), output);\n");
|
||||
array_written = true; // Wrote array all at once
|
||||
}
|
||||
printer->Print(variables_, "}\n");
|
||||
}
|
||||
if (!array_written) {
|
||||
printer->Print(variables_,
|
||||
"for (int i = 0, n = this->$name$_size(); i < n; i++) {\n");
|
||||
if (descriptor_->is_packed()) {
|
||||
printer->Print(variables_,
|
||||
" ::google::protobuf::internal::WireFormatLite::Write$declared_type$NoTag(\n"
|
||||
" this->$name$(i), output);\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
" ::google::protobuf::internal::WireFormatLite::Write$declared_type$(\n"
|
||||
" $number$, this->$name$(i), output);\n");
|
||||
}
|
||||
printer->Print("}\n");
|
||||
}
|
||||
}
|
||||
|
||||
void RepeatedPrimitiveFieldGenerator::
|
||||
GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
|
||||
if (descriptor_->is_packed()) {
|
||||
// Write the tag and the size.
|
||||
printer->Print(variables_,
|
||||
"if (this->$name$_size() > 0) {\n"
|
||||
" target = ::google::protobuf::internal::WireFormatLite::WriteTagToArray(\n"
|
||||
" $number$,\n"
|
||||
" ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,\n"
|
||||
" target);\n"
|
||||
" target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray(\n"
|
||||
" static_cast< ::google::protobuf::int32>(\n"
|
||||
" _$name$_cached_byte_size_), target);\n"
|
||||
" target = ::google::protobuf::internal::WireFormatLite::\n"
|
||||
" Write$declared_type$NoTagToArray(this->$name$_, target);\n"
|
||||
"}\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
"target = ::google::protobuf::internal::WireFormatLite::\n"
|
||||
" Write$declared_type$ToArray($number$, this->$name$_, target);\n");
|
||||
}
|
||||
}
|
||||
|
||||
void RepeatedPrimitiveFieldGenerator::
|
||||
GenerateByteSize(io::Printer* printer) const {
|
||||
printer->Print(variables_, "{\n");
|
||||
printer->Indent();
|
||||
int fixed_size = FixedSize(descriptor_->type());
|
||||
if (fixed_size == -1) {
|
||||
printer->Print(variables_,
|
||||
"size_t data_size = ::google::protobuf::internal::WireFormatLite::\n"
|
||||
" $declared_type$Size(this->$name$_);\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
"unsigned int count = static_cast<unsigned int>(this->$name$_size());\n"
|
||||
"size_t data_size = $fixed_size$UL * count;\n");
|
||||
}
|
||||
|
||||
if (descriptor_->is_packed()) {
|
||||
printer->Print(variables_,
|
||||
"if (data_size > 0) {\n"
|
||||
" total_size += $tag_size$ +\n"
|
||||
" ::google::protobuf::internal::WireFormatLite::Int32Size(\n"
|
||||
" static_cast< ::google::protobuf::int32>(data_size));\n"
|
||||
"}\n"
|
||||
"int cached_size = ::google::protobuf::internal::ToCachedSize(data_size);\n"
|
||||
"GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n"
|
||||
"_$name$_cached_byte_size_ = cached_size;\n"
|
||||
"GOOGLE_SAFE_CONCURRENT_WRITES_END();\n"
|
||||
"total_size += data_size;\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
"total_size += $tag_size$ *\n"
|
||||
" ::google::protobuf::internal::FromIntSize(this->$name$_size());\n"
|
||||
"total_size += data_size;\n");
|
||||
}
|
||||
printer->Outdent();
|
||||
printer->Print("}\n");
|
||||
}
|
||||
|
||||
} // namespace cpp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
@ -0,0 +1,125 @@
|
||||
// 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.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_PRIMITIVE_FIELD_H__
|
||||
#define GOOGLE_PROTOBUF_COMPILER_CPP_PRIMITIVE_FIELD_H__
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <google/protobuf/compiler/cpp/cpp_field.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
|
||||
class PrimitiveFieldGenerator : public FieldGenerator {
|
||||
public:
|
||||
PrimitiveFieldGenerator(const FieldDescriptor* descriptor,
|
||||
const Options& options);
|
||||
~PrimitiveFieldGenerator();
|
||||
|
||||
// implements FieldGenerator ---------------------------------------
|
||||
void GeneratePrivateMembers(io::Printer* printer) const;
|
||||
void GenerateAccessorDeclarations(io::Printer* printer) const;
|
||||
void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
|
||||
void GenerateClearingCode(io::Printer* printer) const;
|
||||
void GenerateMergingCode(io::Printer* printer) const;
|
||||
void GenerateSwappingCode(io::Printer* printer) const;
|
||||
void GenerateConstructorCode(io::Printer* printer) const;
|
||||
void GenerateCopyConstructorCode(io::Printer* printer) const;
|
||||
void GenerateMergeFromCodedStream(io::Printer* printer) const;
|
||||
void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
|
||||
void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
|
||||
void GenerateByteSize(io::Printer* printer) const;
|
||||
|
||||
protected:
|
||||
const FieldDescriptor* descriptor_;
|
||||
std::map<string, string> variables_;
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveFieldGenerator);
|
||||
};
|
||||
|
||||
class PrimitiveOneofFieldGenerator : public PrimitiveFieldGenerator {
|
||||
public:
|
||||
PrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor,
|
||||
const Options& options);
|
||||
~PrimitiveOneofFieldGenerator();
|
||||
|
||||
// implements FieldGenerator ---------------------------------------
|
||||
void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
|
||||
void GenerateClearingCode(io::Printer* printer) const;
|
||||
void GenerateSwappingCode(io::Printer* printer) const;
|
||||
void GenerateConstructorCode(io::Printer* printer) const;
|
||||
void GenerateMergeFromCodedStream(io::Printer* printer) const;
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveOneofFieldGenerator);
|
||||
};
|
||||
|
||||
class RepeatedPrimitiveFieldGenerator : public FieldGenerator {
|
||||
public:
|
||||
RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
|
||||
const Options& options);
|
||||
~RepeatedPrimitiveFieldGenerator();
|
||||
|
||||
// implements FieldGenerator ---------------------------------------
|
||||
void GeneratePrivateMembers(io::Printer* printer) const;
|
||||
void GenerateAccessorDeclarations(io::Printer* printer) const;
|
||||
void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
|
||||
void GenerateClearingCode(io::Printer* printer) const;
|
||||
void GenerateMergingCode(io::Printer* printer) const;
|
||||
void GenerateSwappingCode(io::Printer* printer) const;
|
||||
void GenerateConstructorCode(io::Printer* printer) const;
|
||||
void GenerateCopyConstructorCode(io::Printer* printer) const;
|
||||
void GenerateMergeFromCodedStream(io::Printer* printer) const;
|
||||
void GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const;
|
||||
void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
|
||||
void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
|
||||
void GenerateByteSize(io::Printer* printer) const;
|
||||
|
||||
private:
|
||||
const FieldDescriptor* descriptor_;
|
||||
std::map<string, string> variables_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPrimitiveFieldGenerator);
|
||||
};
|
||||
|
||||
} // namespace cpp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_PRIMITIVE_FIELD_H__
|
@ -0,0 +1,340 @@
|
||||
// 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/compiler/cpp/cpp_service.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
|
||||
#include <google/protobuf/io/printer.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
|
||||
ServiceGenerator::ServiceGenerator(const ServiceDescriptor* descriptor,
|
||||
const Options& options)
|
||||
: descriptor_(descriptor) {
|
||||
vars_["classname"] = descriptor_->name();
|
||||
vars_["file_namespace"] = FileLevelNamespace(descriptor_->file()->name());
|
||||
vars_["full_name"] = descriptor_->full_name();
|
||||
if (options.dllexport_decl.empty()) {
|
||||
vars_["dllexport"] = "";
|
||||
} else {
|
||||
vars_["dllexport"] = options.dllexport_decl + " ";
|
||||
}
|
||||
}
|
||||
|
||||
ServiceGenerator::~ServiceGenerator() {}
|
||||
|
||||
void ServiceGenerator::GenerateDeclarations(io::Printer* printer) {
|
||||
// Forward-declare the stub type.
|
||||
printer->Print(vars_,
|
||||
"class $classname$_Stub;\n"
|
||||
"\n");
|
||||
|
||||
GenerateInterface(printer);
|
||||
GenerateStubDefinition(printer);
|
||||
}
|
||||
|
||||
void ServiceGenerator::GenerateInterface(io::Printer* printer) {
|
||||
printer->Print(vars_,
|
||||
"class $dllexport$$classname$ : public ::google::protobuf::Service {\n"
|
||||
" protected:\n"
|
||||
" // This class should be treated as an abstract interface.\n"
|
||||
" inline $classname$() {};\n"
|
||||
" public:\n"
|
||||
" virtual ~$classname$();\n");
|
||||
printer->Indent();
|
||||
|
||||
printer->Print(vars_,
|
||||
"\n"
|
||||
"typedef $classname$_Stub Stub;\n"
|
||||
"\n"
|
||||
"static const ::google::protobuf::ServiceDescriptor* descriptor();\n"
|
||||
"\n");
|
||||
|
||||
GenerateMethodSignatures(VIRTUAL, printer);
|
||||
|
||||
printer->Print(
|
||||
"\n"
|
||||
"// implements Service ----------------------------------------------\n"
|
||||
"\n"
|
||||
"const ::google::protobuf::ServiceDescriptor* GetDescriptor();\n"
|
||||
"void CallMethod(const ::google::protobuf::MethodDescriptor* method,\n"
|
||||
" ::google::protobuf::RpcController* controller,\n"
|
||||
" const ::google::protobuf::Message* request,\n"
|
||||
" ::google::protobuf::Message* response,\n"
|
||||
" ::google::protobuf::Closure* done);\n"
|
||||
"const ::google::protobuf::Message& GetRequestPrototype(\n"
|
||||
" const ::google::protobuf::MethodDescriptor* method) const;\n"
|
||||
"const ::google::protobuf::Message& GetResponsePrototype(\n"
|
||||
" const ::google::protobuf::MethodDescriptor* method) const;\n");
|
||||
|
||||
printer->Outdent();
|
||||
printer->Print(vars_,
|
||||
"\n"
|
||||
" private:\n"
|
||||
" GOOGLE_DISALLOW_EVIL_CONSTRUCTORS($classname$);\n"
|
||||
"};\n"
|
||||
"\n");
|
||||
}
|
||||
|
||||
void ServiceGenerator::GenerateStubDefinition(io::Printer* printer) {
|
||||
printer->Print(vars_,
|
||||
"class $dllexport$$classname$_Stub : public $classname$ {\n"
|
||||
" public:\n");
|
||||
|
||||
printer->Indent();
|
||||
|
||||
printer->Print(vars_,
|
||||
"$classname$_Stub(::google::protobuf::RpcChannel* channel);\n"
|
||||
"$classname$_Stub(::google::protobuf::RpcChannel* channel,\n"
|
||||
" ::google::protobuf::Service::ChannelOwnership ownership);\n"
|
||||
"~$classname$_Stub();\n"
|
||||
"\n"
|
||||
"inline ::google::protobuf::RpcChannel* channel() { return channel_; }\n"
|
||||
"\n"
|
||||
"// implements $classname$ ------------------------------------------\n"
|
||||
"\n");
|
||||
|
||||
GenerateMethodSignatures(NON_VIRTUAL, printer);
|
||||
|
||||
printer->Outdent();
|
||||
printer->Print(vars_,
|
||||
" private:\n"
|
||||
" ::google::protobuf::RpcChannel* channel_;\n"
|
||||
" bool owns_channel_;\n"
|
||||
" GOOGLE_DISALLOW_EVIL_CONSTRUCTORS($classname$_Stub);\n"
|
||||
"};\n"
|
||||
"\n");
|
||||
}
|
||||
|
||||
void ServiceGenerator::GenerateMethodSignatures(
|
||||
VirtualOrNon virtual_or_non, io::Printer* printer) {
|
||||
for (int i = 0; i < descriptor_->method_count(); i++) {
|
||||
const MethodDescriptor* method = descriptor_->method(i);
|
||||
std::map<string, string> sub_vars;
|
||||
sub_vars["name"] = method->name();
|
||||
sub_vars["input_type"] = ClassName(method->input_type(), true);
|
||||
sub_vars["output_type"] = ClassName(method->output_type(), true);
|
||||
sub_vars["virtual"] = virtual_or_non == VIRTUAL ? "virtual " : "";
|
||||
|
||||
printer->Print(sub_vars,
|
||||
"$virtual$void $name$(::google::protobuf::RpcController* controller,\n"
|
||||
" const $input_type$* request,\n"
|
||||
" $output_type$* response,\n"
|
||||
" ::google::protobuf::Closure* done);\n");
|
||||
}
|
||||
}
|
||||
|
||||
// ===================================================================
|
||||
|
||||
void ServiceGenerator::GenerateDescriptorInitializer(
|
||||
io::Printer* printer, int index) {
|
||||
std::map<string, string> vars;
|
||||
vars["classname"] = descriptor_->name();
|
||||
vars["index"] = SimpleItoa(index);
|
||||
|
||||
printer->Print(vars,
|
||||
"$classname$_descriptor_ = file->service($index$);\n");
|
||||
}
|
||||
|
||||
// ===================================================================
|
||||
|
||||
void ServiceGenerator::GenerateImplementation(io::Printer* printer) {
|
||||
vars_["index"] = SimpleItoa(index_in_metadata_);
|
||||
printer->Print(
|
||||
vars_,
|
||||
"$classname$::~$classname$() {}\n"
|
||||
"\n"
|
||||
"const ::google::protobuf::ServiceDescriptor* $classname$::descriptor() {\n"
|
||||
" $file_namespace$::protobuf_AssignDescriptorsOnce();\n"
|
||||
" return $file_namespace$::file_level_service_descriptors[$index$];\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"const ::google::protobuf::ServiceDescriptor* $classname$::GetDescriptor() {\n"
|
||||
" return descriptor();\n"
|
||||
"}\n"
|
||||
"\n");
|
||||
|
||||
// Generate methods of the interface.
|
||||
GenerateNotImplementedMethods(printer);
|
||||
GenerateCallMethod(printer);
|
||||
GenerateGetPrototype(REQUEST, printer);
|
||||
GenerateGetPrototype(RESPONSE, printer);
|
||||
|
||||
// Generate stub implementation.
|
||||
printer->Print(vars_,
|
||||
"$classname$_Stub::$classname$_Stub(::google::protobuf::RpcChannel* channel)\n"
|
||||
" : channel_(channel), owns_channel_(false) {}\n"
|
||||
"$classname$_Stub::$classname$_Stub(\n"
|
||||
" ::google::protobuf::RpcChannel* channel,\n"
|
||||
" ::google::protobuf::Service::ChannelOwnership ownership)\n"
|
||||
" : channel_(channel),\n"
|
||||
" owns_channel_(ownership == ::google::protobuf::Service::STUB_OWNS_CHANNEL) {}\n"
|
||||
"$classname$_Stub::~$classname$_Stub() {\n"
|
||||
" if (owns_channel_) delete channel_;\n"
|
||||
"}\n"
|
||||
"\n");
|
||||
|
||||
GenerateStubMethods(printer);
|
||||
}
|
||||
|
||||
void ServiceGenerator::GenerateNotImplementedMethods(io::Printer* printer) {
|
||||
for (int i = 0; i < descriptor_->method_count(); i++) {
|
||||
const MethodDescriptor* method = descriptor_->method(i);
|
||||
std::map<string, string> sub_vars;
|
||||
sub_vars["classname"] = descriptor_->name();
|
||||
sub_vars["name"] = method->name();
|
||||
sub_vars["index"] = SimpleItoa(i);
|
||||
sub_vars["input_type"] = ClassName(method->input_type(), true);
|
||||
sub_vars["output_type"] = ClassName(method->output_type(), true);
|
||||
|
||||
printer->Print(sub_vars,
|
||||
"void $classname$::$name$(::google::protobuf::RpcController* controller,\n"
|
||||
" const $input_type$*,\n"
|
||||
" $output_type$*,\n"
|
||||
" ::google::protobuf::Closure* done) {\n"
|
||||
" controller->SetFailed(\"Method $name$() not implemented.\");\n"
|
||||
" done->Run();\n"
|
||||
"}\n"
|
||||
"\n");
|
||||
}
|
||||
}
|
||||
|
||||
void ServiceGenerator::GenerateCallMethod(io::Printer* printer) {
|
||||
printer->Print(
|
||||
vars_,
|
||||
"void $classname$::CallMethod(const ::google::protobuf::MethodDescriptor* method,\n"
|
||||
" ::google::protobuf::RpcController* controller,\n"
|
||||
" const ::google::protobuf::Message* request,\n"
|
||||
" ::google::protobuf::Message* response,\n"
|
||||
" ::google::protobuf::Closure* done) {\n"
|
||||
" GOOGLE_DCHECK_EQ(method->service(), "
|
||||
"$file_namespace$::file_level_service_descriptors[$index$]);\n"
|
||||
" switch(method->index()) {\n");
|
||||
|
||||
for (int i = 0; i < descriptor_->method_count(); i++) {
|
||||
const MethodDescriptor* method = descriptor_->method(i);
|
||||
std::map<string, string> sub_vars;
|
||||
sub_vars["name"] = method->name();
|
||||
sub_vars["index"] = SimpleItoa(i);
|
||||
sub_vars["input_type"] = ClassName(method->input_type(), true);
|
||||
sub_vars["output_type"] = ClassName(method->output_type(), true);
|
||||
|
||||
// Note: down_cast does not work here because it only works on pointers,
|
||||
// not references.
|
||||
printer->Print(sub_vars,
|
||||
" case $index$:\n"
|
||||
" $name$(controller,\n"
|
||||
" ::google::protobuf::down_cast<const $input_type$*>(request),\n"
|
||||
" ::google::protobuf::down_cast< $output_type$*>(response),\n"
|
||||
" done);\n"
|
||||
" break;\n");
|
||||
}
|
||||
|
||||
printer->Print(vars_,
|
||||
" default:\n"
|
||||
" GOOGLE_LOG(FATAL) << \"Bad method index; this should never happen.\";\n"
|
||||
" break;\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"\n");
|
||||
}
|
||||
|
||||
void ServiceGenerator::GenerateGetPrototype(RequestOrResponse which,
|
||||
io::Printer* printer) {
|
||||
if (which == REQUEST) {
|
||||
printer->Print(vars_,
|
||||
"const ::google::protobuf::Message& $classname$::GetRequestPrototype(\n");
|
||||
} else {
|
||||
printer->Print(vars_,
|
||||
"const ::google::protobuf::Message& $classname$::GetResponsePrototype(\n");
|
||||
}
|
||||
|
||||
printer->Print(vars_,
|
||||
" const ::google::protobuf::MethodDescriptor* method) const {\n"
|
||||
" GOOGLE_DCHECK_EQ(method->service(), descriptor());\n"
|
||||
" switch(method->index()) {\n");
|
||||
|
||||
for (int i = 0; i < descriptor_->method_count(); i++) {
|
||||
const MethodDescriptor* method = descriptor_->method(i);
|
||||
const Descriptor* type =
|
||||
(which == REQUEST) ? method->input_type() : method->output_type();
|
||||
|
||||
std::map<string, string> sub_vars;
|
||||
sub_vars["index"] = SimpleItoa(i);
|
||||
sub_vars["type"] = ClassName(type, true);
|
||||
|
||||
printer->Print(sub_vars,
|
||||
" case $index$:\n"
|
||||
" return $type$::default_instance();\n");
|
||||
}
|
||||
|
||||
printer->Print(
|
||||
" default:\n"
|
||||
" GOOGLE_LOG(FATAL) << \"Bad method index; this should never happen.\";\n"
|
||||
" return *::google::protobuf::MessageFactory::generated_factory()\n"
|
||||
" ->GetPrototype(method->$input_or_output$_type());\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"\n",
|
||||
"input_or_output", which == REQUEST ? "input" : "output");
|
||||
}
|
||||
|
||||
void ServiceGenerator::GenerateStubMethods(io::Printer* printer) {
|
||||
for (int i = 0; i < descriptor_->method_count(); i++) {
|
||||
const MethodDescriptor* method = descriptor_->method(i);
|
||||
std::map<string, string> sub_vars;
|
||||
sub_vars["classname"] = descriptor_->name();
|
||||
sub_vars["name"] = method->name();
|
||||
sub_vars["index"] = SimpleItoa(i);
|
||||
sub_vars["input_type"] = ClassName(method->input_type(), true);
|
||||
sub_vars["output_type"] = ClassName(method->output_type(), true);
|
||||
|
||||
printer->Print(sub_vars,
|
||||
"void $classname$_Stub::$name$(::google::protobuf::RpcController* controller,\n"
|
||||
" const $input_type$* request,\n"
|
||||
" $output_type$* response,\n"
|
||||
" ::google::protobuf::Closure* done) {\n"
|
||||
" channel_->CallMethod(descriptor()->method($index$),\n"
|
||||
" controller, request, response, done);\n"
|
||||
"}\n");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace cpp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
121
Common/ProtocolBuffer/google/protobuf/compiler/cpp/cpp_service.h
Normal file
121
Common/ProtocolBuffer/google/protobuf/compiler/cpp/cpp_service.h
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.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_SERVICE_H__
|
||||
#define GOOGLE_PROTOBUF_COMPILER_CPP_SERVICE_H__
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <google/protobuf/compiler/cpp/cpp_options.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace io {
|
||||
class Printer; // printer.h
|
||||
}
|
||||
}
|
||||
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
|
||||
class ServiceGenerator {
|
||||
public:
|
||||
// See generator.cc for the meaning of dllexport_decl.
|
||||
explicit ServiceGenerator(const ServiceDescriptor* descriptor,
|
||||
const Options& options);
|
||||
~ServiceGenerator();
|
||||
|
||||
// Header stuff.
|
||||
|
||||
// Generate the class definitions for the service's interface and the
|
||||
// stub implementation.
|
||||
void GenerateDeclarations(io::Printer* printer);
|
||||
|
||||
// Source file stuff.
|
||||
|
||||
// Generate code that initializes the global variable storing the service's
|
||||
// descriptor.
|
||||
void GenerateDescriptorInitializer(io::Printer* printer, int index);
|
||||
|
||||
// Generate implementations of everything declared by GenerateDeclarations().
|
||||
void GenerateImplementation(io::Printer* printer);
|
||||
|
||||
private:
|
||||
enum RequestOrResponse { REQUEST, RESPONSE };
|
||||
enum VirtualOrNon { VIRTUAL, NON_VIRTUAL };
|
||||
|
||||
// Header stuff.
|
||||
|
||||
// Generate the service abstract interface.
|
||||
void GenerateInterface(io::Printer* printer);
|
||||
|
||||
// Generate the stub class definition.
|
||||
void GenerateStubDefinition(io::Printer* printer);
|
||||
|
||||
// Prints signatures for all methods in the
|
||||
void GenerateMethodSignatures(VirtualOrNon virtual_or_non,
|
||||
io::Printer* printer);
|
||||
|
||||
// Source file stuff.
|
||||
|
||||
// Generate the default implementations of the service methods, which
|
||||
// produce a "not implemented" error.
|
||||
void GenerateNotImplementedMethods(io::Printer* printer);
|
||||
|
||||
// Generate the CallMethod() method of the service.
|
||||
void GenerateCallMethod(io::Printer* printer);
|
||||
|
||||
// Generate the Get{Request,Response}Prototype() methods.
|
||||
void GenerateGetPrototype(RequestOrResponse which, io::Printer* printer);
|
||||
|
||||
// Generate the stub's implementations of the service methods.
|
||||
void GenerateStubMethods(io::Printer* printer);
|
||||
|
||||
const ServiceDescriptor* descriptor_;
|
||||
std::map<string, string> vars_;
|
||||
|
||||
int index_in_metadata_;
|
||||
|
||||
friend class FileGenerator;
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ServiceGenerator);
|
||||
};
|
||||
|
||||
} // namespace cpp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_SERVICE_H__
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,141 @@
|
||||
// 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.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_STRING_FIELD_H__
|
||||
#define GOOGLE_PROTOBUF_COMPILER_CPP_STRING_FIELD_H__
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <google/protobuf/compiler/cpp/cpp_field.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
|
||||
class StringFieldGenerator : public FieldGenerator {
|
||||
public:
|
||||
StringFieldGenerator(const FieldDescriptor* descriptor,
|
||||
const Options& options);
|
||||
~StringFieldGenerator();
|
||||
|
||||
// implements FieldGenerator ---------------------------------------
|
||||
void GeneratePrivateMembers(io::Printer* printer) const;
|
||||
void GenerateStaticMembers(io::Printer* printer) const;
|
||||
void GenerateAccessorDeclarations(io::Printer* printer) const;
|
||||
void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
|
||||
void GenerateNonInlineAccessorDefinitions(io::Printer* printer) const;
|
||||
void GenerateClearingCode(io::Printer* printer) const;
|
||||
void GenerateMessageClearingCode(io::Printer* printer) const;
|
||||
void GenerateMergingCode(io::Printer* printer) const;
|
||||
void GenerateSwappingCode(io::Printer* printer) const;
|
||||
void GenerateConstructorCode(io::Printer* printer) const;
|
||||
void GenerateCopyConstructorCode(io::Printer* printer) const;
|
||||
void GenerateDestructorCode(io::Printer* printer) const;
|
||||
bool GenerateArenaDestructorCode(io::Printer* printer) const;
|
||||
void GenerateDefaultInstanceAllocator(io::Printer* printer) const;
|
||||
void GenerateMergeFromCodedStream(io::Printer* printer) const;
|
||||
void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
|
||||
void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
|
||||
void GenerateByteSize(io::Printer* printer) const;
|
||||
uint32 CalculateFieldTag() const;
|
||||
bool IsInlined() const { return inlined_; }
|
||||
|
||||
bool MergeFromCodedStreamNeedsArena() const;
|
||||
|
||||
protected:
|
||||
const FieldDescriptor* descriptor_;
|
||||
std::map<string, string> variables_;
|
||||
const bool lite_;
|
||||
bool inlined_;
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringFieldGenerator);
|
||||
};
|
||||
|
||||
class StringOneofFieldGenerator : public StringFieldGenerator {
|
||||
public:
|
||||
StringOneofFieldGenerator(const FieldDescriptor* descriptor,
|
||||
const Options& options);
|
||||
~StringOneofFieldGenerator();
|
||||
|
||||
// implements FieldGenerator ---------------------------------------
|
||||
void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
|
||||
void GenerateClearingCode(io::Printer* printer) const;
|
||||
|
||||
// StringFieldGenerator, from which we inherit, overrides this so we need to
|
||||
// override it as well.
|
||||
void GenerateMessageClearingCode(io::Printer* printer) const;
|
||||
void GenerateSwappingCode(io::Printer* printer) const;
|
||||
void GenerateConstructorCode(io::Printer* printer) const;
|
||||
void GenerateDestructorCode(io::Printer* printer) const;
|
||||
void GenerateMergeFromCodedStream(io::Printer* printer) const;
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringOneofFieldGenerator);
|
||||
};
|
||||
|
||||
class RepeatedStringFieldGenerator : public FieldGenerator {
|
||||
public:
|
||||
RepeatedStringFieldGenerator(const FieldDescriptor* descriptor,
|
||||
const Options& options);
|
||||
~RepeatedStringFieldGenerator();
|
||||
|
||||
// implements FieldGenerator ---------------------------------------
|
||||
void GeneratePrivateMembers(io::Printer* printer) const;
|
||||
void GenerateAccessorDeclarations(io::Printer* printer) const;
|
||||
void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
|
||||
void GenerateClearingCode(io::Printer* printer) const;
|
||||
void GenerateMergingCode(io::Printer* printer) const;
|
||||
void GenerateSwappingCode(io::Printer* printer) const;
|
||||
void GenerateConstructorCode(io::Printer* printer) const;
|
||||
void GenerateCopyConstructorCode(io::Printer* printer) const;
|
||||
void GenerateMergeFromCodedStream(io::Printer* printer) const;
|
||||
void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
|
||||
void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
|
||||
void GenerateByteSize(io::Printer* printer) const;
|
||||
|
||||
private:
|
||||
const FieldDescriptor* descriptor_;
|
||||
std::map<string, string> variables_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedStringFieldGenerator);
|
||||
};
|
||||
|
||||
} // namespace cpp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_STRING_FIELD_H__
|
@ -0,0 +1,160 @@
|
||||
// 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 tests that various identifiers work as field and type names even
|
||||
// though the same identifiers are used internally by the C++ code generator.
|
||||
|
||||
syntax = "proto2";
|
||||
|
||||
// Some generic_services option(s) added automatically.
|
||||
// See: http://go/proto2-generic-services-default
|
||||
option cc_generic_services = true; // auto-added
|
||||
|
||||
// We don't put this in a package within proto2 because we need to make sure
|
||||
// that the generated code doesn't depend on being in the proto2 namespace.
|
||||
package protobuf_unittest;
|
||||
|
||||
// Test that fields can have names like "input" and "i" which are also used
|
||||
// internally by the code generator for local variables.
|
||||
message TestConflictingSymbolNames {
|
||||
message BuildDescriptors {}
|
||||
message TypeTraits {}
|
||||
|
||||
optional int32 input = 1;
|
||||
optional int32 output = 2;
|
||||
optional string length = 3;
|
||||
repeated int32 i = 4;
|
||||
repeated string new_element = 5 [ctype=STRING_PIECE];
|
||||
optional int32 total_size = 6;
|
||||
optional int32 tag = 7;
|
||||
|
||||
enum TestEnum { FOO = 0; }
|
||||
message Data1 { repeated int32 data = 1; }
|
||||
message Data2 { repeated TestEnum data = 1; }
|
||||
message Data3 { repeated string data = 1; }
|
||||
message Data4 { repeated Data4 data = 1; }
|
||||
message Data5 { repeated string data = 1 [ctype=STRING_PIECE]; }
|
||||
message Data6 { repeated string data = 1 [ctype=CORD]; }
|
||||
|
||||
optional int32 source = 8;
|
||||
optional int32 value = 9;
|
||||
optional int32 file = 10;
|
||||
optional int32 from = 11;
|
||||
optional int32 handle_uninterpreted = 12;
|
||||
repeated int32 index = 13;
|
||||
optional int32 controller = 14;
|
||||
optional int32 already_here = 15;
|
||||
|
||||
optional uint32 uint32 = 16;
|
||||
optional uint64 uint64 = 17;
|
||||
optional string string = 18;
|
||||
optional int32 memset = 19;
|
||||
optional int32 int32 = 20;
|
||||
optional int64 int64 = 21;
|
||||
|
||||
optional uint32 cached_size = 22;
|
||||
optional uint32 extensions = 23;
|
||||
optional uint32 bit = 24;
|
||||
optional uint32 bits = 25;
|
||||
optional uint32 offsets = 26;
|
||||
optional uint32 reflection = 27;
|
||||
|
||||
message Cord {}
|
||||
optional string some_cord = 28 [ctype=CORD];
|
||||
|
||||
message StringPiece {}
|
||||
optional string some_string_piece = 29 [ctype=STRING_PIECE];
|
||||
|
||||
// Some keywords.
|
||||
optional uint32 int = 30;
|
||||
optional uint32 friend = 31;
|
||||
optional uint32 class = 37;
|
||||
optional uint32 typedecl = 39;
|
||||
optional uint32 auto = 40;
|
||||
|
||||
// The generator used to #define a macro called "DO" inside the .cc file.
|
||||
message DO {}
|
||||
optional DO do = 32;
|
||||
|
||||
// Some template parameter names for extensions.
|
||||
optional int32 field_type = 33;
|
||||
optional bool is_packed = 34;
|
||||
|
||||
// test conflicting release_$name$. "length" and "do" field in this message
|
||||
// must remain string or message fields to make the test valid.
|
||||
optional string release_length = 35;
|
||||
// A more extreme case, the field name "do" here is a keyword, which will be
|
||||
// escaped to "do_" already. Test there is no conflict even with escaped field
|
||||
// names.
|
||||
optional DO release_do = 36;
|
||||
|
||||
// For clashing local variables in Serialize and ByteSize calculation.
|
||||
optional string target = 38;
|
||||
|
||||
extensions 1000 to max; // NO_PROTO3
|
||||
}
|
||||
|
||||
message TestConflictingSymbolNamesExtension { // NO_PROTO3
|
||||
extend TestConflictingSymbolNames { // NO_PROTO3
|
||||
repeated int32 repeated_int32_ext = 20423638 [packed=true]; // NO_PROTO3
|
||||
} // NO_PROTO3
|
||||
} // NO_PROTO3
|
||||
|
||||
message TestConflictingEnumNames { // NO_PROTO3
|
||||
enum NestedConflictingEnum { // NO_PROTO3
|
||||
and = 1; // NO_PROTO3
|
||||
class = 2; // NO_PROTO3
|
||||
int = 3; // NO_PROTO3
|
||||
typedef = 4; // NO_PROTO3
|
||||
XOR = 5; // NO_PROTO3
|
||||
} // NO_PROTO3
|
||||
|
||||
optional NestedConflictingEnum conflicting_enum = 1; // NO_PROTO3
|
||||
} // NO_PROTO3
|
||||
|
||||
enum ConflictingEnum { // NO_PROTO3
|
||||
NOT_EQ = 1; // NO_PROTO3
|
||||
volatile = 2; // NO_PROTO3
|
||||
return = 3; // NO_PROTO3
|
||||
} // NO_PROTO3
|
||||
|
||||
message DummyMessage {}
|
||||
|
||||
// Message names that could conflict.
|
||||
message Shutdown {}
|
||||
message TableStruct {}
|
||||
|
||||
service TestConflictingMethodNames {
|
||||
rpc Closure(DummyMessage) returns (DummyMessage);
|
||||
}
|
@ -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.
|
||||
|
||||
// Test that proto2 compiler can generate valid code when the enum value
|
||||
// is INT_MAX. Note that this is a compile-only test and this proto is not
|
||||
// referenced in any C++ code.
|
||||
syntax = "proto2";
|
||||
|
||||
package protobuf_unittest;
|
||||
|
||||
message TestLargeEnumValue {
|
||||
enum EnumWithLargeValue {
|
||||
VALUE_1 = 1;
|
||||
VALUE_MAX = 0x7fffffff;
|
||||
}
|
||||
}
|
@ -0,0 +1,122 @@
|
||||
// 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.
|
||||
//
|
||||
// To test the code generator, we actually use it to generate code for
|
||||
// google/protobuf/unittest.proto, then test that. This means that we
|
||||
// are actually testing the parser and other parts of the system at the same
|
||||
// time, and that problems in the generator may show up as compile-time errors
|
||||
// rather than unittest failures, which may be surprising. However, testing
|
||||
// the output of the C++ generator directly would be very hard. We can't very
|
||||
// well just check it against golden files since those files would have to be
|
||||
// updated for any small change; such a test would be very brittle and probably
|
||||
// not very helpful. What we really want to test is that the code compiles
|
||||
// correctly and produces the interfaces we expect, which is why this test
|
||||
// is written this way.
|
||||
|
||||
#include <google/protobuf/compiler/cpp/cpp_unittest.h>
|
||||
|
||||
#include <google/protobuf/unittest.pb.h>
|
||||
#include <google/protobuf/unittest_optimize_for.pb.h>
|
||||
#include <google/protobuf/unittest_embed_optimize_for.pb.h>
|
||||
|
||||
#include <google/protobuf/test_util.h>
|
||||
|
||||
#define MESSAGE_TEST_NAME MessageTest
|
||||
#define GENERATED_DESCRIPTOR_TEST_NAME GeneratedDescriptorTest
|
||||
#define GENERATED_MESSAGE_TEST_NAME GeneratedMessageTest
|
||||
#define GENERATED_ENUM_TEST_NAME GeneratedEnumTest
|
||||
#define GENERATED_SERVICE_TEST_NAME GeneratedServiceTest
|
||||
#define HELPERS_TEST_NAME HelpersTest
|
||||
#define DESCRIPTOR_INIT_TEST_NAME DescriptorInitializationTest
|
||||
|
||||
#define UNITTEST_PROTO_PATH "google/protobuf/unittest.proto"
|
||||
#define UNITTEST ::protobuf_unittest
|
||||
#define UNITTEST_IMPORT ::protobuf_unittest_import
|
||||
|
||||
// Must include after the above macros.
|
||||
#include <google/protobuf/compiler/cpp/cpp_unittest.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
|
||||
// Can't use an anonymous namespace here due to brokenness of Tru64 compiler.
|
||||
namespace cpp_unittest {
|
||||
|
||||
namespace protobuf_unittest = ::protobuf_unittest;
|
||||
|
||||
TEST(GENERATED_MESSAGE_TEST_NAME, TestConflictingSymbolNames) {
|
||||
// test_bad_identifiers.proto successfully compiled, then it works. The
|
||||
// following is just a token usage to insure that the code is, in fact,
|
||||
// being compiled and linked.
|
||||
|
||||
protobuf_unittest::TestConflictingSymbolNames message;
|
||||
message.set_uint32(1);
|
||||
EXPECT_EQ(3, message.ByteSizeLong());
|
||||
|
||||
message.set_friend_(5);
|
||||
EXPECT_EQ(5, message.friend_());
|
||||
|
||||
message.set_class_(6);
|
||||
EXPECT_EQ(6, message.class_());
|
||||
|
||||
// Instantiate extension template functions to test conflicting template
|
||||
// parameter names.
|
||||
typedef protobuf_unittest::TestConflictingSymbolNamesExtension ExtensionMessage;
|
||||
message.AddExtension(ExtensionMessage::repeated_int32_ext, 123);
|
||||
EXPECT_EQ(123,
|
||||
message.GetExtension(ExtensionMessage::repeated_int32_ext, 0));
|
||||
}
|
||||
|
||||
TEST(GENERATED_MESSAGE_TEST_NAME, TestConflictingEnumNames) {
|
||||
protobuf_unittest::TestConflictingEnumNames message;
|
||||
message.set_conflicting_enum(protobuf_unittest::TestConflictingEnumNames_NestedConflictingEnum_and_);
|
||||
EXPECT_EQ(1, message.conflicting_enum());
|
||||
message.set_conflicting_enum(protobuf_unittest::TestConflictingEnumNames_NestedConflictingEnum_XOR);
|
||||
EXPECT_EQ(5, message.conflicting_enum());
|
||||
|
||||
|
||||
protobuf_unittest::ConflictingEnum conflicting_enum;
|
||||
conflicting_enum = protobuf_unittest::NOT_EQ;
|
||||
EXPECT_EQ(1, conflicting_enum);
|
||||
conflicting_enum = protobuf_unittest::return_;
|
||||
EXPECT_EQ(3, conflicting_enum);
|
||||
}
|
||||
|
||||
} // namespace cpp_unittest
|
||||
} // namespace cpp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
@ -0,0 +1,51 @@
|
||||
// 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 header declares the namespace google::protobuf::protobuf_unittest in order to expose
|
||||
// any problems with the generated class names. We use this header to ensure
|
||||
// unittest.cc will declare the namespace prior to other includes, while obeying
|
||||
// normal include ordering.
|
||||
//
|
||||
// When generating a class name of "foo.Bar" we must ensure we prefix the class
|
||||
// name with "::", in case the namespace google::protobuf::foo exists. We intentionally
|
||||
// trigger that case here by declaring google::protobuf::protobuf_unittest.
|
||||
//
|
||||
// See ClassName in helpers.h for more details.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_UNITTEST_H__
|
||||
#define GOOGLE_PROTOBUF_COMPILER_CPP_UNITTEST_H__
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace protobuf_unittest {}
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_UNITTEST_H__
|
2281
Common/ProtocolBuffer/google/protobuf/compiler/cpp/cpp_unittest.inc
Normal file
2281
Common/ProtocolBuffer/google/protobuf/compiler/cpp/cpp_unittest.inc
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,162 @@
|
||||
// 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 <memory>
|
||||
|
||||
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_generator.h>
|
||||
#include <google/protobuf/compiler/annotation_test_util.h>
|
||||
#include <google/protobuf/compiler/command_line_interface.h>
|
||||
#include <google/protobuf/descriptor.pb.h>
|
||||
|
||||
#include <google/protobuf/testing/file.h>
|
||||
#include <google/protobuf/testing/file.h>
|
||||
#include <google/protobuf/testing/googletest.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
namespace google {
|
||||
namespace atu = ::google::protobuf::compiler::annotation_test_util;
|
||||
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
namespace {
|
||||
|
||||
class CppMetadataTest : public ::testing::Test {
|
||||
public:
|
||||
// Tries to capture a FileDescriptorProto, GeneratedCodeInfo, and output
|
||||
// code from the previously added file with name `filename`. Returns true on
|
||||
// success. If pb_h is non-null, expects a .pb.h and a .pb.h.meta (copied to
|
||||
// pb_h and pb_h_info respecfively); similarly for proto_h and proto_h_info.
|
||||
bool CaptureMetadata(const string& filename, FileDescriptorProto* file,
|
||||
string* pb_h, GeneratedCodeInfo* pb_h_info,
|
||||
string* proto_h, GeneratedCodeInfo* proto_h_info,
|
||||
string* pb_cc) {
|
||||
google::protobuf::compiler::CommandLineInterface cli;
|
||||
CppGenerator cpp_generator;
|
||||
cli.RegisterGenerator("--cpp_out", &cpp_generator, "");
|
||||
string cpp_out =
|
||||
"--cpp_out=annotate_headers=true,"
|
||||
"annotation_pragma_name=pragma_name,"
|
||||
"annotation_guard_name=guard_name:" +
|
||||
TestTempDir();
|
||||
|
||||
const bool result =
|
||||
atu::RunProtoCompiler(filename, cpp_out, &cli, file);
|
||||
|
||||
if (!result) {
|
||||
return result;
|
||||
}
|
||||
|
||||
string output_base = TestTempDir() + "/" + StripProto(filename);
|
||||
|
||||
if (pb_cc != NULL) {
|
||||
GOOGLE_CHECK_OK(
|
||||
File::GetContents(output_base + ".pb.cc", pb_cc, true));
|
||||
}
|
||||
|
||||
if (pb_h != NULL && pb_h_info != NULL) {
|
||||
GOOGLE_CHECK_OK(
|
||||
File::GetContents(output_base + ".pb.h", pb_h, true));
|
||||
if (!atu::DecodeMetadata(output_base + ".pb.h.meta", pb_h_info)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (proto_h != NULL && proto_h_info != NULL) {
|
||||
GOOGLE_CHECK_OK(File::GetContents(output_base + ".proto.h", proto_h,
|
||||
true));
|
||||
if (!atu::DecodeMetadata(output_base + ".proto.h.meta", proto_h_info)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
const char kSmallTestFile[] =
|
||||
"syntax = \"proto2\";\n"
|
||||
"package foo;\n"
|
||||
"enum Enum { VALUE = 0; }\n"
|
||||
"message Message { }\n";
|
||||
|
||||
TEST_F(CppMetadataTest, CapturesEnumNames) {
|
||||
FileDescriptorProto file;
|
||||
GeneratedCodeInfo info;
|
||||
string pb_h;
|
||||
atu::AddFile("test.proto", kSmallTestFile);
|
||||
EXPECT_TRUE(
|
||||
CaptureMetadata("test.proto", &file, &pb_h, &info, NULL, NULL, NULL));
|
||||
EXPECT_EQ("Enum", file.enum_type(0).name());
|
||||
std::vector<int> enum_path;
|
||||
enum_path.push_back(FileDescriptorProto::kEnumTypeFieldNumber);
|
||||
enum_path.push_back(0);
|
||||
const GeneratedCodeInfo::Annotation* enum_annotation =
|
||||
atu::FindAnnotationOnPath(info, "test.proto", enum_path);
|
||||
EXPECT_TRUE(NULL != enum_annotation);
|
||||
EXPECT_TRUE(atu::AnnotationMatchesSubstring(pb_h, enum_annotation, "Enum"));
|
||||
}
|
||||
|
||||
TEST_F(CppMetadataTest, AddsPragma) {
|
||||
FileDescriptorProto file;
|
||||
GeneratedCodeInfo info;
|
||||
string pb_h;
|
||||
atu::AddFile("test.proto", kSmallTestFile);
|
||||
EXPECT_TRUE(
|
||||
CaptureMetadata("test.proto", &file, &pb_h, &info, NULL, NULL, NULL));
|
||||
EXPECT_TRUE(pb_h.find("#ifdef guard_name") != string::npos);
|
||||
EXPECT_TRUE(pb_h.find("#pragma pragma_name \"test.pb.h.meta\"") !=
|
||||
string::npos);
|
||||
}
|
||||
|
||||
TEST_F(CppMetadataTest, CapturesMessageNames) {
|
||||
FileDescriptorProto file;
|
||||
GeneratedCodeInfo info;
|
||||
string pb_h;
|
||||
atu::AddFile("test.proto", kSmallTestFile);
|
||||
EXPECT_TRUE(
|
||||
CaptureMetadata("test.proto", &file, &pb_h, &info, NULL, NULL, NULL));
|
||||
EXPECT_EQ("Message", file.message_type(0).name());
|
||||
std::vector<int> message_path;
|
||||
message_path.push_back(FileDescriptorProto::kMessageTypeFieldNumber);
|
||||
message_path.push_back(0);
|
||||
const GeneratedCodeInfo::Annotation* message_annotation =
|
||||
atu::FindAnnotationOnPath(info, "test.proto", message_path);
|
||||
EXPECT_TRUE(NULL != message_annotation);
|
||||
EXPECT_TRUE(
|
||||
atu::AnnotationMatchesSubstring(pb_h, message_annotation, "Message"));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace cpp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
@ -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.
|
||||
|
||||
// This test insures that
|
||||
// csharp/src/Google.Protobuf/Reflection/Descriptor.cs match exactly
|
||||
// what would be generated by the protocol compiler. The file is not
|
||||
// generated automatically at build time.
|
||||
//
|
||||
// If this test fails, run the script
|
||||
// "generate_descriptor_proto.sh" and add the changed files under
|
||||
// csharp/src/ to your changelist.
|
||||
|
||||
#include <map>
|
||||
|
||||
#include <google/protobuf/compiler/csharp/csharp_generator.h>
|
||||
#include <google/protobuf/compiler/importer.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/io/zero_copy_stream_impl.h>
|
||||
#include <google/protobuf/stubs/map_util.h>
|
||||
#include <google/protobuf/stubs/stl_util.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
#include <google/protobuf/stubs/substitute.h>
|
||||
|
||||
#include <google/protobuf/testing/file.h>
|
||||
#include <google/protobuf/testing/file.h>
|
||||
#include <google/protobuf/testing/googletest.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace csharp {
|
||||
|
||||
namespace {
|
||||
|
||||
class MockErrorCollector : public MultiFileErrorCollector {
|
||||
public:
|
||||
MockErrorCollector() {}
|
||||
~MockErrorCollector() {}
|
||||
|
||||
string text_;
|
||||
|
||||
// implements ErrorCollector ---------------------------------------
|
||||
void AddError(const string& filename, int line, int column,
|
||||
const string& message) {
|
||||
strings::SubstituteAndAppend(&text_, "$0:$1:$2: $3\n",
|
||||
filename, line, column, message);
|
||||
}
|
||||
};
|
||||
|
||||
class MockGeneratorContext : public GeneratorContext {
|
||||
public:
|
||||
MockGeneratorContext() {}
|
||||
~MockGeneratorContext() {
|
||||
STLDeleteValues(&files_);
|
||||
}
|
||||
|
||||
void ExpectFileMatches(const string& virtual_filename,
|
||||
const string& physical_filename) {
|
||||
string* expected_contents = FindPtrOrNull(files_, virtual_filename);
|
||||
ASSERT_TRUE(expected_contents != NULL)
|
||||
<< "Generator failed to generate file: " << virtual_filename;
|
||||
|
||||
string actual_contents;
|
||||
GOOGLE_CHECK_OK(
|
||||
File::GetContents(TestSourceDir() + "/" + physical_filename,
|
||||
&actual_contents, true))
|
||||
<< "Unable to get " << physical_filename;
|
||||
EXPECT_TRUE(actual_contents == *expected_contents)
|
||||
<< physical_filename << " needs to be regenerated. Please run "
|
||||
"generate_descriptor_proto.sh. Then add this file "
|
||||
"to your CL.";
|
||||
}
|
||||
|
||||
// implements GeneratorContext --------------------------------------
|
||||
|
||||
virtual io::ZeroCopyOutputStream* Open(const string& filename) {
|
||||
string** map_slot = &files_[filename];
|
||||
delete *map_slot;
|
||||
*map_slot = new string;
|
||||
|
||||
return new io::StringOutputStream(*map_slot);
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<string, string*> files_;
|
||||
};
|
||||
|
||||
class GenerateAndTest {
|
||||
public:
|
||||
GenerateAndTest() {}
|
||||
void Run(const FileDescriptor* proto_file, string file1, string file2) {
|
||||
ASSERT_TRUE(proto_file != NULL) << TestSourceDir();
|
||||
ASSERT_TRUE(generator_.Generate(proto_file, parameter_,
|
||||
&context_, &error_));
|
||||
context_.ExpectFileMatches(file1, file2);
|
||||
}
|
||||
void SetParameter(string parameter) {
|
||||
parameter_ = parameter;
|
||||
}
|
||||
|
||||
private:
|
||||
Generator generator_;
|
||||
MockGeneratorContext context_;
|
||||
string error_;
|
||||
string parameter_;
|
||||
};
|
||||
|
||||
TEST(CsharpBootstrapTest, GeneratedCsharpDescriptorMatches) {
|
||||
// Skip this whole test if the csharp directory doesn't exist (i.e., a C++11
|
||||
// only distribution).
|
||||
string descriptor_file_name =
|
||||
"../csharp/src/Google.Protobuf/Reflection/Descriptor.cs";
|
||||
if (!File::Exists(TestSourceDir() + "/" + descriptor_file_name)) {
|
||||
return;
|
||||
}
|
||||
|
||||
MockErrorCollector error_collector;
|
||||
DiskSourceTree source_tree;
|
||||
Importer importer(&source_tree, &error_collector);
|
||||
GenerateAndTest generate_test;
|
||||
|
||||
generate_test.SetParameter("base_namespace=Google.Protobuf");
|
||||
source_tree.MapPath("", TestSourceDir());
|
||||
generate_test.Run(importer.Import("google/protobuf/descriptor.proto"),
|
||||
"Reflection/Descriptor.cs",
|
||||
"../csharp/src/Google.Protobuf/Reflection/Descriptor.cs");
|
||||
generate_test.Run(importer.Import("google/protobuf/any.proto"),
|
||||
"WellKnownTypes/Any.cs",
|
||||
"../csharp/src/Google.Protobuf/WellKnownTypes/Any.cs");
|
||||
generate_test.Run(importer.Import("google/protobuf/api.proto"),
|
||||
"WellKnownTypes/Api.cs",
|
||||
"../csharp/src/Google.Protobuf/WellKnownTypes/Api.cs");
|
||||
generate_test.Run(importer.Import("google/protobuf/duration.proto"),
|
||||
"WellKnownTypes/Duration.cs",
|
||||
"../csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs");
|
||||
generate_test.Run(importer.Import("google/protobuf/empty.proto"),
|
||||
"WellKnownTypes/Empty.cs",
|
||||
"../csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs");
|
||||
generate_test.Run(importer.Import("google/protobuf/field_mask.proto"),
|
||||
"WellKnownTypes/FieldMask.cs",
|
||||
"../csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs");
|
||||
generate_test.Run(importer.Import("google/protobuf/source_context.proto"),
|
||||
"WellKnownTypes/SourceContext.cs",
|
||||
"../csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.cs");
|
||||
generate_test.Run(importer.Import("google/protobuf/struct.proto"),
|
||||
"WellKnownTypes/Struct.cs",
|
||||
"../csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs");
|
||||
generate_test.Run(importer.Import("google/protobuf/timestamp.proto"),
|
||||
"WellKnownTypes/Timestamp.cs",
|
||||
"../csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs");
|
||||
generate_test.Run(importer.Import("google/protobuf/type.proto"),
|
||||
"WellKnownTypes/Type.cs",
|
||||
"../csharp/src/Google.Protobuf/WellKnownTypes/Type.cs");
|
||||
generate_test.Run(importer.Import("google/protobuf/wrappers.proto"),
|
||||
"WellKnownTypes/Wrappers.cs",
|
||||
"../csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs");
|
||||
|
||||
generate_test.SetParameter("");
|
||||
source_tree.MapPath("", TestSourceDir() + "/../conformance");
|
||||
generate_test.Run(importer.Import("conformance.proto"),
|
||||
"Conformance.cs",
|
||||
"../csharp/src/Google.Protobuf.Conformance/Conformance.cs");
|
||||
|
||||
EXPECT_EQ("", error_collector.text_);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
} // namespace csharp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
@ -0,0 +1,114 @@
|
||||
// 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/compiler/csharp/csharp_doc_comment.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/io/printer.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace csharp {
|
||||
|
||||
// Functions to create C# XML documentation comments.
|
||||
// Currently this only includes documentation comments containing text specified as comments
|
||||
// in the .proto file; documentation comments generated just from field/message/enum/proto names
|
||||
// is inlined in the relevant code. If more control is required, that code can be moved here.
|
||||
|
||||
void WriteDocCommentBodyImpl(io::Printer* printer, SourceLocation location) {
|
||||
string comments = location.leading_comments.empty() ?
|
||||
location.trailing_comments : location.leading_comments;
|
||||
if (comments.empty()) {
|
||||
return;
|
||||
}
|
||||
// XML escaping... no need for apostrophes etc as the whole text is going to be a child
|
||||
// node of a summary element, not part of an attribute.
|
||||
comments = StringReplace(comments, "&", "&", true);
|
||||
comments = StringReplace(comments, "<", "<", true);
|
||||
std::vector<string> lines = Split(comments, "\n", false /* skip_empty */);
|
||||
// TODO: We really should work out which part to put in the summary and which to put in the remarks...
|
||||
// but that needs to be part of a bigger effort to understand the markdown better anyway.
|
||||
printer->Print("/// <summary>\n");
|
||||
bool last_was_empty = false;
|
||||
// We squash multiple blank lines down to one, and remove any trailing blank lines. We need
|
||||
// to preserve the blank lines themselves, as this is relevant in the markdown.
|
||||
// Note that we can't remove leading or trailing whitespace as *that's* relevant in markdown too.
|
||||
// (We don't skip "just whitespace" lines, either.)
|
||||
for (std::vector<string>::iterator it = lines.begin(); it != lines.end(); ++it) {
|
||||
string line = *it;
|
||||
if (line.empty()) {
|
||||
last_was_empty = true;
|
||||
} else {
|
||||
if (last_was_empty) {
|
||||
printer->Print("///\n");
|
||||
}
|
||||
last_was_empty = false;
|
||||
printer->Print("///$line$\n", "line", *it);
|
||||
}
|
||||
}
|
||||
printer->Print("/// </summary>\n");
|
||||
}
|
||||
|
||||
template <typename DescriptorType>
|
||||
static void WriteDocCommentBody(
|
||||
io::Printer* printer, const DescriptorType* descriptor) {
|
||||
SourceLocation location;
|
||||
if (descriptor->GetSourceLocation(&location)) {
|
||||
WriteDocCommentBodyImpl(printer, location);
|
||||
}
|
||||
}
|
||||
|
||||
void WriteMessageDocComment(io::Printer* printer, const Descriptor* message) {
|
||||
WriteDocCommentBody(printer, message);
|
||||
}
|
||||
|
||||
void WritePropertyDocComment(io::Printer* printer, const FieldDescriptor* field) {
|
||||
WriteDocCommentBody(printer, field);
|
||||
}
|
||||
|
||||
void WriteEnumDocComment(io::Printer* printer, const EnumDescriptor* enumDescriptor) {
|
||||
WriteDocCommentBody(printer, enumDescriptor);
|
||||
}
|
||||
void WriteEnumValueDocComment(io::Printer* printer, const EnumValueDescriptor* value) {
|
||||
WriteDocCommentBody(printer, value);
|
||||
}
|
||||
|
||||
void WriteMethodDocComment(io::Printer* printer, const MethodDescriptor* method) {
|
||||
WriteDocCommentBody(printer, method);
|
||||
}
|
||||
|
||||
} // namespace csharp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
@ -0,0 +1,51 @@
|
||||
// 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_COMPILER_CSHARP_DOC_COMMENT_H__
|
||||
#define GOOGLE_PROTOBUF_COMPILER_CSHARP_DOC_COMMENT_H__
|
||||
|
||||
#include <google/protobuf/io/printer.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace csharp {
|
||||
void WriteMessageDocComment(io::Printer* printer, const Descriptor* message);
|
||||
void WritePropertyDocComment(io::Printer* printer, const FieldDescriptor* field);
|
||||
void WriteEnumDocComment(io::Printer* printer, const EnumDescriptor* enumDescriptor);
|
||||
void WriteEnumValueDocComment(io::Printer* printer, const EnumValueDescriptor* value);
|
||||
void WriteMethodDocComment(io::Printer* printer, const MethodDescriptor* method);
|
||||
} // namespace csharp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_DOC_COMMENT_H__
|
@ -0,0 +1,99 @@
|
||||
// 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 <sstream>
|
||||
|
||||
#include <google/protobuf/compiler/code_generator.h>
|
||||
#include <google/protobuf/compiler/plugin.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/descriptor.pb.h>
|
||||
#include <google/protobuf/io/printer.h>
|
||||
#include <google/protobuf/io/zero_copy_stream.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
|
||||
#include <google/protobuf/compiler/csharp/csharp_doc_comment.h>
|
||||
#include <google/protobuf/compiler/csharp/csharp_enum.h>
|
||||
#include <google/protobuf/compiler/csharp/csharp_helpers.h>
|
||||
#include <google/protobuf/compiler/csharp/csharp_options.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace csharp {
|
||||
|
||||
EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor, const Options* options) :
|
||||
SourceGeneratorBase(descriptor->file(), options),
|
||||
descriptor_(descriptor) {
|
||||
}
|
||||
|
||||
EnumGenerator::~EnumGenerator() {
|
||||
}
|
||||
|
||||
void EnumGenerator::Generate(io::Printer* printer) {
|
||||
WriteEnumDocComment(printer, descriptor_);
|
||||
printer->Print("$access_level$ enum $name$ {\n",
|
||||
"access_level", class_access_level(),
|
||||
"name", descriptor_->name());
|
||||
printer->Indent();
|
||||
std::set<string> used_names;
|
||||
std::set<int> used_number;
|
||||
for (int i = 0; i < descriptor_->value_count(); i++) {
|
||||
WriteEnumValueDocComment(printer, descriptor_->value(i));
|
||||
string original_name = descriptor_->value(i)->name();
|
||||
string name = GetEnumValueName(descriptor_->name(), descriptor_->value(i)->name());
|
||||
// Make sure we don't get any duplicate names due to prefix removal.
|
||||
while (!used_names.insert(name).second) {
|
||||
// It's possible we'll end up giving this warning multiple times, but that's better than not at all.
|
||||
GOOGLE_LOG(WARNING) << "Duplicate enum value " << name << " (originally " << original_name
|
||||
<< ") in " << descriptor_->name() << "; adding underscore to distinguish";
|
||||
name += "_";
|
||||
}
|
||||
int number = descriptor_->value(i)->number();
|
||||
if (!used_number.insert(number).second) {
|
||||
printer->Print("[pbr::OriginalName(\"$original_name$\", PreferredAlias = false)] $name$ = $number$,\n",
|
||||
"original_name", original_name,
|
||||
"name", name,
|
||||
"number", SimpleItoa(number));
|
||||
} else {
|
||||
printer->Print("[pbr::OriginalName(\"$original_name$\")] $name$ = $number$,\n",
|
||||
"original_name", original_name,
|
||||
"name", name,
|
||||
"number", SimpleItoa(number));
|
||||
}
|
||||
}
|
||||
printer->Outdent();
|
||||
printer->Print("}\n");
|
||||
printer->Print("\n");
|
||||
}
|
||||
|
||||
} // namespace csharp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
@ -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.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_ENUM_H__
|
||||
#define GOOGLE_PROTOBUF_COMPILER_CSHARP_ENUM_H__
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/compiler/code_generator.h>
|
||||
#include <google/protobuf/compiler/csharp/csharp_source_generator_base.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace csharp {
|
||||
|
||||
class EnumGenerator : public SourceGeneratorBase {
|
||||
public:
|
||||
EnumGenerator(const EnumDescriptor* descriptor, const Options* options);
|
||||
~EnumGenerator();
|
||||
|
||||
void Generate(io::Printer* printer);
|
||||
|
||||
private:
|
||||
const EnumDescriptor* descriptor_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumGenerator);
|
||||
};
|
||||
|
||||
} // namespace csharp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_ENUM_H__
|
||||
|
@ -0,0 +1,124 @@
|
||||
// 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 <sstream>
|
||||
|
||||
#include <google/protobuf/compiler/code_generator.h>
|
||||
#include <google/protobuf/compiler/plugin.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/descriptor.pb.h>
|
||||
#include <google/protobuf/io/printer.h>
|
||||
#include <google/protobuf/io/zero_copy_stream.h>
|
||||
|
||||
#include <google/protobuf/compiler/csharp/csharp_helpers.h>
|
||||
#include <google/protobuf/compiler/csharp/csharp_options.h>
|
||||
#include <google/protobuf/compiler/csharp/csharp_enum_field.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace csharp {
|
||||
|
||||
EnumFieldGenerator::EnumFieldGenerator(const FieldDescriptor* descriptor,
|
||||
int fieldOrdinal, const Options *options)
|
||||
: PrimitiveFieldGenerator(descriptor, fieldOrdinal, options) {
|
||||
}
|
||||
|
||||
EnumFieldGenerator::~EnumFieldGenerator() {
|
||||
}
|
||||
|
||||
void EnumFieldGenerator::GenerateParsingCode(io::Printer* printer) {
|
||||
printer->Print(variables_,
|
||||
"$name$_ = ($type_name$) input.ReadEnum();\n");
|
||||
}
|
||||
|
||||
void EnumFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
|
||||
printer->Print(variables_,
|
||||
"if ($has_property_check$) {\n"
|
||||
" output.WriteRawTag($tag_bytes$);\n"
|
||||
" output.WriteEnum((int) $property_name$);\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void EnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
|
||||
printer->Print(
|
||||
variables_,
|
||||
"if ($has_property_check$) {\n"
|
||||
" size += $tag_size$ + pb::CodedOutputStream.ComputeEnumSize((int) $property_name$);\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void EnumFieldGenerator::GenerateCodecCode(io::Printer* printer) {
|
||||
printer->Print(
|
||||
variables_,
|
||||
"pb::FieldCodec.ForEnum($tag$, x => (int) x, x => ($type_name$) x)");
|
||||
}
|
||||
|
||||
EnumOneofFieldGenerator::EnumOneofFieldGenerator(
|
||||
const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options)
|
||||
: PrimitiveOneofFieldGenerator(descriptor, fieldOrdinal, options) {
|
||||
}
|
||||
|
||||
EnumOneofFieldGenerator::~EnumOneofFieldGenerator() {
|
||||
}
|
||||
|
||||
void EnumOneofFieldGenerator::GenerateMergingCode(io::Printer* printer) {
|
||||
printer->Print(variables_, "$property_name$ = other.$property_name$;\n");
|
||||
}
|
||||
|
||||
void EnumOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) {
|
||||
// TODO(jonskeet): What about if we read the default value?
|
||||
printer->Print(
|
||||
variables_,
|
||||
"$oneof_name$_ = input.ReadEnum();\n"
|
||||
"$oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n");
|
||||
}
|
||||
|
||||
void EnumOneofFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
|
||||
printer->Print(
|
||||
variables_,
|
||||
"if ($has_property_check$) {\n"
|
||||
" output.WriteRawTag($tag_bytes$);\n"
|
||||
" output.WriteEnum((int) $property_name$);\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void EnumOneofFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
|
||||
printer->Print(
|
||||
variables_,
|
||||
"if ($has_property_check$) {\n"
|
||||
" size += $tag_size$ + pb::CodedOutputStream.ComputeEnumSize((int) $property_name$);\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
} // namespace csharp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
@ -0,0 +1,82 @@
|
||||
// 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_COMPILER_CSHARP_ENUM_FIELD_H__
|
||||
#define GOOGLE_PROTOBUF_COMPILER_CSHARP_ENUM_FIELD_H__
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/compiler/code_generator.h>
|
||||
#include <google/protobuf/compiler/csharp/csharp_primitive_field.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace csharp {
|
||||
|
||||
class EnumFieldGenerator : public PrimitiveFieldGenerator {
|
||||
public:
|
||||
EnumFieldGenerator(const FieldDescriptor* descriptor,
|
||||
int fieldOrdinal,
|
||||
const Options *options);
|
||||
~EnumFieldGenerator();
|
||||
|
||||
virtual void GenerateCodecCode(io::Printer* printer);
|
||||
virtual void GenerateParsingCode(io::Printer* printer);
|
||||
virtual void GenerateSerializationCode(io::Printer* printer);
|
||||
virtual void GenerateSerializedSizeCode(io::Printer* printer);
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumFieldGenerator);
|
||||
};
|
||||
|
||||
class EnumOneofFieldGenerator : public PrimitiveOneofFieldGenerator {
|
||||
public:
|
||||
EnumOneofFieldGenerator(const FieldDescriptor* descriptor,
|
||||
int fieldOrdinal,
|
||||
const Options *options);
|
||||
~EnumOneofFieldGenerator();
|
||||
|
||||
virtual void GenerateMergingCode(io::Printer* printer);
|
||||
virtual void GenerateParsingCode(io::Printer* printer);
|
||||
virtual void GenerateSerializationCode(io::Printer* printer);
|
||||
virtual void GenerateSerializedSizeCode(io::Printer* printer);
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumOneofFieldGenerator);
|
||||
};
|
||||
|
||||
} // namespace csharp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_ENUM_FIELD_H__
|
||||
|
@ -0,0 +1,430 @@
|
||||
// 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 <limits>
|
||||
#include <sstream>
|
||||
|
||||
#include <google/protobuf/compiler/code_generator.h>
|
||||
#include <google/protobuf/compiler/plugin.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/descriptor.pb.h>
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/io/printer.h>
|
||||
#include <google/protobuf/io/zero_copy_stream.h>
|
||||
#include <google/protobuf/stubs/mathlimits.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
#include <google/protobuf/wire_format.h>
|
||||
|
||||
#include <google/protobuf/compiler/csharp/csharp_field_base.h>
|
||||
#include <google/protobuf/compiler/csharp/csharp_helpers.h>
|
||||
#include <google/protobuf/compiler/csharp/csharp_names.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace csharp {
|
||||
|
||||
void FieldGeneratorBase::SetCommonFieldVariables(
|
||||
std::map<string, string>* variables) {
|
||||
// Note: this will be valid even though the tag emitted for packed and unpacked versions of
|
||||
// repeated fields varies by wire format. The wire format is encoded in the bottom 3 bits, which
|
||||
// never effects the tag size.
|
||||
int tag_size = internal::WireFormat::TagSize(descriptor_->number(), descriptor_->type());
|
||||
uint tag = internal::WireFormat::MakeTag(descriptor_);
|
||||
uint8 tag_array[5];
|
||||
io::CodedOutputStream::WriteTagToArray(tag, tag_array);
|
||||
string tag_bytes = SimpleItoa(tag_array[0]);
|
||||
for (int i = 1; i < tag_size; i++) {
|
||||
tag_bytes += ", " + SimpleItoa(tag_array[i]);
|
||||
}
|
||||
|
||||
(*variables)["access_level"] = "public";
|
||||
(*variables)["tag"] = SimpleItoa(tag);
|
||||
(*variables)["tag_size"] = SimpleItoa(tag_size);
|
||||
(*variables)["tag_bytes"] = tag_bytes;
|
||||
|
||||
(*variables)["property_name"] = property_name();
|
||||
(*variables)["type_name"] = type_name();
|
||||
(*variables)["name"] = name();
|
||||
(*variables)["descriptor_name"] = descriptor_->name();
|
||||
(*variables)["default_value"] = default_value();
|
||||
if (has_default_value()) {
|
||||
(*variables)["name_def_message"] =
|
||||
(*variables)["name"] + "_ = " + (*variables)["default_value"];
|
||||
} else {
|
||||
(*variables)["name_def_message"] = (*variables)["name"] + "_";
|
||||
}
|
||||
(*variables)["capitalized_type_name"] = capitalized_type_name();
|
||||
(*variables)["number"] = number();
|
||||
(*variables)["has_property_check"] =
|
||||
(*variables)["property_name"] + " != " + (*variables)["default_value"];
|
||||
(*variables)["other_has_property_check"] = "other." +
|
||||
(*variables)["property_name"] + " != " + (*variables)["default_value"];
|
||||
}
|
||||
|
||||
void FieldGeneratorBase::SetCommonOneofFieldVariables(
|
||||
std::map<string, string>* variables) {
|
||||
(*variables)["oneof_name"] = oneof_name();
|
||||
(*variables)["has_property_check"] =
|
||||
oneof_name() + "Case_ == " + oneof_property_name() +
|
||||
"OneofCase." + property_name();
|
||||
(*variables)["oneof_property_name"] = oneof_property_name();
|
||||
}
|
||||
|
||||
FieldGeneratorBase::FieldGeneratorBase(const FieldDescriptor* descriptor,
|
||||
int fieldOrdinal, const Options* options)
|
||||
: SourceGeneratorBase(descriptor->file(), options),
|
||||
descriptor_(descriptor),
|
||||
fieldOrdinal_(fieldOrdinal) {
|
||||
SetCommonFieldVariables(&variables_);
|
||||
}
|
||||
|
||||
FieldGeneratorBase::~FieldGeneratorBase() {
|
||||
}
|
||||
|
||||
void FieldGeneratorBase::GenerateFreezingCode(io::Printer* printer) {
|
||||
// No-op: only message fields and repeated fields need
|
||||
// special handling for freezing, so default to not generating any code.
|
||||
}
|
||||
|
||||
void FieldGeneratorBase::GenerateCodecCode(io::Printer* printer) {
|
||||
// No-op: expect this to be overridden by appropriate types.
|
||||
// Could fail if we get called here though...
|
||||
}
|
||||
|
||||
void FieldGeneratorBase::AddDeprecatedFlag(io::Printer* printer) {
|
||||
if (descriptor_->options().deprecated()) {
|
||||
printer->Print("[global::System.ObsoleteAttribute]\n");
|
||||
} else if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE &&
|
||||
descriptor_->message_type()->options().deprecated()) {
|
||||
printer->Print("[global::System.ObsoleteAttribute]\n");
|
||||
}
|
||||
}
|
||||
|
||||
void FieldGeneratorBase::AddPublicMemberAttributes(io::Printer* printer) {
|
||||
AddDeprecatedFlag(printer);
|
||||
WriteGeneratedCodeAttributes(printer);
|
||||
}
|
||||
|
||||
std::string FieldGeneratorBase::oneof_property_name() {
|
||||
return UnderscoresToCamelCase(descriptor_->containing_oneof()->name(), true);
|
||||
}
|
||||
|
||||
std::string FieldGeneratorBase::oneof_name() {
|
||||
return UnderscoresToCamelCase(descriptor_->containing_oneof()->name(), false);
|
||||
}
|
||||
|
||||
std::string FieldGeneratorBase::property_name() {
|
||||
return GetPropertyName(descriptor_);
|
||||
}
|
||||
|
||||
std::string FieldGeneratorBase::name() {
|
||||
return UnderscoresToCamelCase(GetFieldName(descriptor_), false);
|
||||
}
|
||||
|
||||
std::string FieldGeneratorBase::type_name() {
|
||||
return type_name(descriptor_);
|
||||
}
|
||||
|
||||
std::string FieldGeneratorBase::type_name(const FieldDescriptor* descriptor) {
|
||||
switch (descriptor->type()) {
|
||||
case FieldDescriptor::TYPE_ENUM:
|
||||
return GetClassName(descriptor->enum_type());
|
||||
case FieldDescriptor::TYPE_MESSAGE:
|
||||
case FieldDescriptor::TYPE_GROUP:
|
||||
if (IsWrapperType(descriptor)) {
|
||||
const FieldDescriptor* wrapped_field =
|
||||
descriptor->message_type()->field(0);
|
||||
string wrapped_field_type_name = type_name(wrapped_field);
|
||||
// String and ByteString go to the same type; other wrapped types
|
||||
// go to the nullable equivalent.
|
||||
if (wrapped_field->type() == FieldDescriptor::TYPE_STRING ||
|
||||
wrapped_field->type() == FieldDescriptor::TYPE_BYTES) {
|
||||
return wrapped_field_type_name;
|
||||
} else {
|
||||
return wrapped_field_type_name + "?";
|
||||
}
|
||||
}
|
||||
return GetClassName(descriptor->message_type());
|
||||
case FieldDescriptor::TYPE_DOUBLE:
|
||||
return "double";
|
||||
case FieldDescriptor::TYPE_FLOAT:
|
||||
return "float";
|
||||
case FieldDescriptor::TYPE_INT64:
|
||||
return "long";
|
||||
case FieldDescriptor::TYPE_UINT64:
|
||||
return "ulong";
|
||||
case FieldDescriptor::TYPE_INT32:
|
||||
return "int";
|
||||
case FieldDescriptor::TYPE_FIXED64:
|
||||
return "ulong";
|
||||
case FieldDescriptor::TYPE_FIXED32:
|
||||
return "uint";
|
||||
case FieldDescriptor::TYPE_BOOL:
|
||||
return "bool";
|
||||
case FieldDescriptor::TYPE_STRING:
|
||||
return "string";
|
||||
case FieldDescriptor::TYPE_BYTES:
|
||||
return "pb::ByteString";
|
||||
case FieldDescriptor::TYPE_UINT32:
|
||||
return "uint";
|
||||
case FieldDescriptor::TYPE_SFIXED32:
|
||||
return "int";
|
||||
case FieldDescriptor::TYPE_SFIXED64:
|
||||
return "long";
|
||||
case FieldDescriptor::TYPE_SINT32:
|
||||
return "int";
|
||||
case FieldDescriptor::TYPE_SINT64:
|
||||
return "long";
|
||||
default:
|
||||
GOOGLE_LOG(FATAL)<< "Unknown field type.";
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
bool FieldGeneratorBase::has_default_value() {
|
||||
switch (descriptor_->type()) {
|
||||
case FieldDescriptor::TYPE_ENUM:
|
||||
case FieldDescriptor::TYPE_MESSAGE:
|
||||
case FieldDescriptor::TYPE_GROUP:
|
||||
return true;
|
||||
case FieldDescriptor::TYPE_DOUBLE:
|
||||
return descriptor_->default_value_double() != 0.0;
|
||||
case FieldDescriptor::TYPE_FLOAT:
|
||||
return descriptor_->default_value_float() != 0.0;
|
||||
case FieldDescriptor::TYPE_INT64:
|
||||
return descriptor_->default_value_int64() != 0L;
|
||||
case FieldDescriptor::TYPE_UINT64:
|
||||
return descriptor_->default_value_uint64() != 0L;
|
||||
case FieldDescriptor::TYPE_INT32:
|
||||
return descriptor_->default_value_int32() != 0;
|
||||
case FieldDescriptor::TYPE_FIXED64:
|
||||
return descriptor_->default_value_uint64() != 0L;
|
||||
case FieldDescriptor::TYPE_FIXED32:
|
||||
return descriptor_->default_value_uint32() != 0;
|
||||
case FieldDescriptor::TYPE_BOOL:
|
||||
return descriptor_->default_value_bool();
|
||||
case FieldDescriptor::TYPE_STRING:
|
||||
return true;
|
||||
case FieldDescriptor::TYPE_BYTES:
|
||||
return true;
|
||||
case FieldDescriptor::TYPE_UINT32:
|
||||
return descriptor_->default_value_uint32() != 0;
|
||||
case FieldDescriptor::TYPE_SFIXED32:
|
||||
return descriptor_->default_value_int32() != 0;
|
||||
case FieldDescriptor::TYPE_SFIXED64:
|
||||
return descriptor_->default_value_int64() != 0L;
|
||||
case FieldDescriptor::TYPE_SINT32:
|
||||
return descriptor_->default_value_int32() != 0;
|
||||
case FieldDescriptor::TYPE_SINT64:
|
||||
return descriptor_->default_value_int64() != 0L;
|
||||
default:
|
||||
GOOGLE_LOG(FATAL)<< "Unknown field type.";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool FieldGeneratorBase::is_nullable_type() {
|
||||
switch (descriptor_->type()) {
|
||||
case FieldDescriptor::TYPE_ENUM:
|
||||
case FieldDescriptor::TYPE_DOUBLE:
|
||||
case FieldDescriptor::TYPE_FLOAT:
|
||||
case FieldDescriptor::TYPE_INT64:
|
||||
case FieldDescriptor::TYPE_UINT64:
|
||||
case FieldDescriptor::TYPE_INT32:
|
||||
case FieldDescriptor::TYPE_FIXED64:
|
||||
case FieldDescriptor::TYPE_FIXED32:
|
||||
case FieldDescriptor::TYPE_BOOL:
|
||||
case FieldDescriptor::TYPE_UINT32:
|
||||
case FieldDescriptor::TYPE_SFIXED32:
|
||||
case FieldDescriptor::TYPE_SFIXED64:
|
||||
case FieldDescriptor::TYPE_SINT32:
|
||||
case FieldDescriptor::TYPE_SINT64:
|
||||
return false;
|
||||
|
||||
case FieldDescriptor::TYPE_MESSAGE:
|
||||
case FieldDescriptor::TYPE_GROUP:
|
||||
case FieldDescriptor::TYPE_STRING:
|
||||
case FieldDescriptor::TYPE_BYTES:
|
||||
return true;
|
||||
|
||||
default:
|
||||
GOOGLE_LOG(FATAL)<< "Unknown field type.";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool AllPrintableAscii(const std::string& text) {
|
||||
for(int i = 0; i < text.size(); i++) {
|
||||
if (text[i] < 0x20 || text[i] > 0x7e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string FieldGeneratorBase::GetStringDefaultValueInternal() {
|
||||
// No other default values needed for proto3...
|
||||
return "\"\"";
|
||||
}
|
||||
|
||||
std::string FieldGeneratorBase::GetBytesDefaultValueInternal() {
|
||||
// No other default values needed for proto3...
|
||||
return "pb::ByteString.Empty";
|
||||
}
|
||||
|
||||
std::string FieldGeneratorBase::default_value() {
|
||||
return default_value(descriptor_);
|
||||
}
|
||||
|
||||
std::string FieldGeneratorBase::default_value(const FieldDescriptor* descriptor) {
|
||||
switch (descriptor->type()) {
|
||||
case FieldDescriptor::TYPE_ENUM:
|
||||
// All proto3 enums have a default value of 0, and there's an implicit conversion from the constant 0 to
|
||||
// any C# enum. This means we don't need to work out what we actually mapped the enum value name to.
|
||||
return "0";
|
||||
case FieldDescriptor::TYPE_MESSAGE:
|
||||
case FieldDescriptor::TYPE_GROUP:
|
||||
if (IsWrapperType(descriptor)) {
|
||||
const FieldDescriptor* wrapped_field = descriptor->message_type()->field(0);
|
||||
return default_value(wrapped_field);
|
||||
} else {
|
||||
return "null";
|
||||
}
|
||||
case FieldDescriptor::TYPE_DOUBLE: {
|
||||
double value = descriptor->default_value_double();
|
||||
if (value == std::numeric_limits<double>::infinity()) {
|
||||
return "double.PositiveInfinity";
|
||||
} else if (value == -std::numeric_limits<double>::infinity()) {
|
||||
return "double.NegativeInfinity";
|
||||
} else if (MathLimits<double>::IsNaN(value)) {
|
||||
return "double.NaN";
|
||||
}
|
||||
return SimpleDtoa(value) + "D";
|
||||
}
|
||||
case FieldDescriptor::TYPE_FLOAT: {
|
||||
float value = descriptor->default_value_float();
|
||||
if (value == std::numeric_limits<float>::infinity()) {
|
||||
return "float.PositiveInfinity";
|
||||
} else if (value == -std::numeric_limits<float>::infinity()) {
|
||||
return "float.NegativeInfinity";
|
||||
} else if (MathLimits<float>::IsNaN(value)) {
|
||||
return "float.NaN";
|
||||
}
|
||||
return SimpleFtoa(value) + "F";
|
||||
}
|
||||
case FieldDescriptor::TYPE_INT64:
|
||||
return SimpleItoa(descriptor->default_value_int64()) + "L";
|
||||
case FieldDescriptor::TYPE_UINT64:
|
||||
return SimpleItoa(descriptor->default_value_uint64()) + "UL";
|
||||
case FieldDescriptor::TYPE_INT32:
|
||||
return SimpleItoa(descriptor->default_value_int32());
|
||||
case FieldDescriptor::TYPE_FIXED64:
|
||||
return SimpleItoa(descriptor->default_value_uint64()) + "UL";
|
||||
case FieldDescriptor::TYPE_FIXED32:
|
||||
return SimpleItoa(descriptor->default_value_uint32());
|
||||
case FieldDescriptor::TYPE_BOOL:
|
||||
if (descriptor->default_value_bool()) {
|
||||
return "true";
|
||||
} else {
|
||||
return "false";
|
||||
}
|
||||
case FieldDescriptor::TYPE_STRING:
|
||||
return GetStringDefaultValueInternal();
|
||||
case FieldDescriptor::TYPE_BYTES:
|
||||
return GetBytesDefaultValueInternal();
|
||||
case FieldDescriptor::TYPE_UINT32:
|
||||
return SimpleItoa(descriptor->default_value_uint32());
|
||||
case FieldDescriptor::TYPE_SFIXED32:
|
||||
return SimpleItoa(descriptor->default_value_int32());
|
||||
case FieldDescriptor::TYPE_SFIXED64:
|
||||
return SimpleItoa(descriptor->default_value_int64()) + "L";
|
||||
case FieldDescriptor::TYPE_SINT32:
|
||||
return SimpleItoa(descriptor->default_value_int32());
|
||||
case FieldDescriptor::TYPE_SINT64:
|
||||
return SimpleItoa(descriptor->default_value_int64()) + "L";
|
||||
default:
|
||||
GOOGLE_LOG(FATAL)<< "Unknown field type.";
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
std::string FieldGeneratorBase::number() {
|
||||
return SimpleItoa(descriptor_->number());
|
||||
}
|
||||
|
||||
std::string FieldGeneratorBase::capitalized_type_name() {
|
||||
switch (descriptor_->type()) {
|
||||
case FieldDescriptor::TYPE_ENUM:
|
||||
return "Enum";
|
||||
case FieldDescriptor::TYPE_MESSAGE:
|
||||
return "Message";
|
||||
case FieldDescriptor::TYPE_GROUP:
|
||||
return "Group";
|
||||
case FieldDescriptor::TYPE_DOUBLE:
|
||||
return "Double";
|
||||
case FieldDescriptor::TYPE_FLOAT:
|
||||
return "Float";
|
||||
case FieldDescriptor::TYPE_INT64:
|
||||
return "Int64";
|
||||
case FieldDescriptor::TYPE_UINT64:
|
||||
return "UInt64";
|
||||
case FieldDescriptor::TYPE_INT32:
|
||||
return "Int32";
|
||||
case FieldDescriptor::TYPE_FIXED64:
|
||||
return "Fixed64";
|
||||
case FieldDescriptor::TYPE_FIXED32:
|
||||
return "Fixed32";
|
||||
case FieldDescriptor::TYPE_BOOL:
|
||||
return "Bool";
|
||||
case FieldDescriptor::TYPE_STRING:
|
||||
return "String";
|
||||
case FieldDescriptor::TYPE_BYTES:
|
||||
return "Bytes";
|
||||
case FieldDescriptor::TYPE_UINT32:
|
||||
return "UInt32";
|
||||
case FieldDescriptor::TYPE_SFIXED32:
|
||||
return "SFixed32";
|
||||
case FieldDescriptor::TYPE_SFIXED64:
|
||||
return "SFixed64";
|
||||
case FieldDescriptor::TYPE_SINT32:
|
||||
return "SInt32";
|
||||
case FieldDescriptor::TYPE_SINT64:
|
||||
return "SInt64";
|
||||
default:
|
||||
GOOGLE_LOG(FATAL)<< "Unknown field type.";
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace csharp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
@ -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_COMPILER_CSHARP_FIELD_BASE_H__
|
||||
#define GOOGLE_PROTOBUF_COMPILER_CSHARP_FIELD_BASE_H__
|
||||
|
||||
#include <string>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
|
||||
#include <google/protobuf/compiler/code_generator.h>
|
||||
#include <google/protobuf/compiler/csharp/csharp_source_generator_base.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace csharp {
|
||||
|
||||
class FieldGeneratorBase : public SourceGeneratorBase {
|
||||
public:
|
||||
FieldGeneratorBase(const FieldDescriptor* descriptor,
|
||||
int fieldOrdinal,
|
||||
const Options* options);
|
||||
~FieldGeneratorBase();
|
||||
|
||||
virtual void GenerateCloningCode(io::Printer* printer) = 0;
|
||||
virtual void GenerateFreezingCode(io::Printer* printer);
|
||||
virtual void GenerateCodecCode(io::Printer* printer);
|
||||
virtual void GenerateMembers(io::Printer* printer) = 0;
|
||||
virtual void GenerateMergingCode(io::Printer* printer) = 0;
|
||||
virtual void GenerateParsingCode(io::Printer* printer) = 0;
|
||||
virtual void GenerateSerializationCode(io::Printer* printer) = 0;
|
||||
virtual void GenerateSerializedSizeCode(io::Printer* printer) = 0;
|
||||
|
||||
virtual void WriteHash(io::Printer* printer) = 0;
|
||||
virtual void WriteEquals(io::Printer* printer) = 0;
|
||||
// Currently unused, as we use reflection to generate JSON
|
||||
virtual void WriteToString(io::Printer* printer) = 0;
|
||||
|
||||
protected:
|
||||
const FieldDescriptor* descriptor_;
|
||||
const int fieldOrdinal_;
|
||||
std::map<string, string> variables_;
|
||||
|
||||
void AddDeprecatedFlag(io::Printer* printer);
|
||||
void AddNullCheck(io::Printer* printer);
|
||||
void AddNullCheck(io::Printer* printer, const std::string& name);
|
||||
|
||||
void AddPublicMemberAttributes(io::Printer* printer);
|
||||
void SetCommonOneofFieldVariables(std::map<string, string>* variables);
|
||||
|
||||
std::string oneof_property_name();
|
||||
std::string oneof_name();
|
||||
std::string property_name();
|
||||
std::string name();
|
||||
std::string type_name();
|
||||
std::string type_name(const FieldDescriptor* descriptor);
|
||||
bool has_default_value();
|
||||
bool is_nullable_type();
|
||||
std::string default_value();
|
||||
std::string default_value(const FieldDescriptor* descriptor);
|
||||
std::string number();
|
||||
std::string capitalized_type_name();
|
||||
|
||||
private:
|
||||
void SetCommonFieldVariables(std::map<string, string>* variables);
|
||||
std::string GetStringDefaultValueInternal();
|
||||
std::string GetBytesDefaultValueInternal();
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorBase);
|
||||
};
|
||||
|
||||
} // namespace csharp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_FIELD_BASE_H__
|
||||
|
@ -0,0 +1,113 @@
|
||||
// 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 <sstream>
|
||||
|
||||
#include <google/protobuf/compiler/code_generator.h>
|
||||
#include <google/protobuf/compiler/plugin.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/descriptor.pb.h>
|
||||
#include <google/protobuf/io/printer.h>
|
||||
#include <google/protobuf/io/zero_copy_stream.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
|
||||
#include <google/protobuf/compiler/csharp/csharp_generator.h>
|
||||
#include <google/protobuf/compiler/csharp/csharp_helpers.h>
|
||||
#include <google/protobuf/compiler/csharp/csharp_names.h>
|
||||
#include <google/protobuf/compiler/csharp/csharp_options.h>
|
||||
#include <google/protobuf/compiler/csharp/csharp_reflection_class.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace csharp {
|
||||
|
||||
void GenerateFile(const google::protobuf::FileDescriptor* file,
|
||||
io::Printer* printer,
|
||||
const Options* options) {
|
||||
ReflectionClassGenerator reflectionClassGenerator(file, options);
|
||||
reflectionClassGenerator.Generate(printer);
|
||||
}
|
||||
|
||||
bool Generator::Generate(
|
||||
const FileDescriptor* file,
|
||||
const string& parameter,
|
||||
GeneratorContext* generator_context,
|
||||
string* error) const {
|
||||
|
||||
std::vector<std::pair<string, string> > options;
|
||||
ParseGeneratorParameter(parameter, &options);
|
||||
|
||||
// We only support proto3 - but we make an exception for descriptor.proto.
|
||||
if (file->syntax() != FileDescriptor::SYNTAX_PROTO3 && !IsDescriptorProto(file)) {
|
||||
*error = "C# code generation only supports proto3 syntax";
|
||||
return false;
|
||||
}
|
||||
|
||||
struct Options cli_options;
|
||||
|
||||
for (int i = 0; i < options.size(); i++) {
|
||||
if (options[i].first == "file_extension") {
|
||||
cli_options.file_extension = options[i].second;
|
||||
} else if (options[i].first == "base_namespace") {
|
||||
cli_options.base_namespace = options[i].second;
|
||||
cli_options.base_namespace_specified = true;
|
||||
} else if (options[i].first == "internal_access") {
|
||||
cli_options.internal_access = true;
|
||||
} else {
|
||||
*error = "Unknown generator option: " + options[i].first;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
string filename_error = "";
|
||||
std::string filename = GetOutputFile(file,
|
||||
cli_options.file_extension,
|
||||
cli_options.base_namespace_specified,
|
||||
cli_options.base_namespace,
|
||||
&filename_error);
|
||||
|
||||
if (filename.empty()) {
|
||||
*error = filename_error;
|
||||
return false;
|
||||
}
|
||||
std::unique_ptr<io::ZeroCopyOutputStream> output(
|
||||
generator_context->Open(filename));
|
||||
io::Printer printer(output.get(), '$');
|
||||
|
||||
GenerateFile(file, &printer, &cli_options);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace csharp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
@ -0,0 +1,64 @@
|
||||
// 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.
|
||||
|
||||
// Generates C# code for a given .proto file.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_GENERATOR_H__
|
||||
#define GOOGLE_PROTOBUF_COMPILER_CSHARP_GENERATOR_H__
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/compiler/code_generator.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace csharp {
|
||||
|
||||
// CodeGenerator implementation which generates a C# source file and
|
||||
// header. If you create your own protocol compiler binary and you want
|
||||
// it to support C# output, you can do so by registering an instance of this
|
||||
// CodeGenerator with the CommandLineInterface in your main() function.
|
||||
class LIBPROTOC_EXPORT Generator
|
||||
: public google::protobuf::compiler::CodeGenerator {
|
||||
public:
|
||||
virtual bool Generate(
|
||||
const FileDescriptor* file,
|
||||
const string& parameter,
|
||||
GeneratorContext* generator_context,
|
||||
string* error) const;
|
||||
};
|
||||
|
||||
} // namespace csharp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_GENERATOR_H__
|
@ -0,0 +1,70 @@
|
||||
// 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.
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <google/protobuf/compiler/command_line_interface.h>
|
||||
#include <google/protobuf/compiler/csharp/csharp_helpers.h>
|
||||
#include <google/protobuf/io/zero_copy_stream.h>
|
||||
#include <google/protobuf/io/printer.h>
|
||||
|
||||
#include <google/protobuf/testing/googletest.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <google/protobuf/testing/file.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace csharp {
|
||||
namespace {
|
||||
|
||||
TEST(CSharpEnumValue, PascalCasedPrefixStripping) {
|
||||
EXPECT_EQ("Bar", GetEnumValueName("Foo", "BAR"));
|
||||
EXPECT_EQ("BarBaz", GetEnumValueName("Foo", "BAR_BAZ"));
|
||||
EXPECT_EQ("Bar", GetEnumValueName("Foo", "FOO_BAR"));
|
||||
EXPECT_EQ("Bar", GetEnumValueName("Foo", "FOO__BAR"));
|
||||
EXPECT_EQ("BarBaz", GetEnumValueName("Foo", "FOO_BAR_BAZ"));
|
||||
EXPECT_EQ("BarBaz", GetEnumValueName("Foo", "Foo_BarBaz"));
|
||||
EXPECT_EQ("Bar", GetEnumValueName("FO_O", "FOO_BAR"));
|
||||
EXPECT_EQ("Bar", GetEnumValueName("FOO", "F_O_O_BAR"));
|
||||
EXPECT_EQ("Bar", GetEnumValueName("Foo", "BAR"));
|
||||
EXPECT_EQ("BarBaz", GetEnumValueName("Foo", "BAR_BAZ"));
|
||||
EXPECT_EQ("Foo", GetEnumValueName("Foo", "FOO"));
|
||||
EXPECT_EQ("Foo", GetEnumValueName("Foo", "FOO___"));
|
||||
// Identifiers can't start with digits
|
||||
EXPECT_EQ("_2Bar", GetEnumValueName("Foo", "FOO_2_BAR"));
|
||||
EXPECT_EQ("_2", GetEnumValueName("Foo", "FOO___2"));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace csharp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
@ -0,0 +1,507 @@
|
||||
// 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 <algorithm>
|
||||
#include <google/protobuf/stubs/hash.h>
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
|
||||
#include <google/protobuf/compiler/csharp/csharp_helpers.h>
|
||||
#include <google/protobuf/compiler/csharp/csharp_names.h>
|
||||
#include <google/protobuf/descriptor.pb.h>
|
||||
#include <google/protobuf/io/printer.h>
|
||||
#include <google/protobuf/wire_format.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
#include <google/protobuf/stubs/substitute.h>
|
||||
|
||||
#include <google/protobuf/compiler/csharp/csharp_field_base.h>
|
||||
#include <google/protobuf/compiler/csharp/csharp_enum_field.h>
|
||||
#include <google/protobuf/compiler/csharp/csharp_map_field.h>
|
||||
#include <google/protobuf/compiler/csharp/csharp_message_field.h>
|
||||
#include <google/protobuf/compiler/csharp/csharp_options.h>
|
||||
#include <google/protobuf/compiler/csharp/csharp_primitive_field.h>
|
||||
#include <google/protobuf/compiler/csharp/csharp_repeated_enum_field.h>
|
||||
#include <google/protobuf/compiler/csharp/csharp_repeated_message_field.h>
|
||||
#include <google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h>
|
||||
#include <google/protobuf/compiler/csharp/csharp_wrapper_field.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace csharp {
|
||||
|
||||
CSharpType GetCSharpType(FieldDescriptor::Type type) {
|
||||
switch (type) {
|
||||
case FieldDescriptor::TYPE_INT32:
|
||||
return CSHARPTYPE_INT32;
|
||||
case FieldDescriptor::TYPE_INT64:
|
||||
return CSHARPTYPE_INT64;
|
||||
case FieldDescriptor::TYPE_UINT32:
|
||||
return CSHARPTYPE_UINT32;
|
||||
case FieldDescriptor::TYPE_UINT64:
|
||||
return CSHARPTYPE_UINT32;
|
||||
case FieldDescriptor::TYPE_SINT32:
|
||||
return CSHARPTYPE_INT32;
|
||||
case FieldDescriptor::TYPE_SINT64:
|
||||
return CSHARPTYPE_INT64;
|
||||
case FieldDescriptor::TYPE_FIXED32:
|
||||
return CSHARPTYPE_UINT32;
|
||||
case FieldDescriptor::TYPE_FIXED64:
|
||||
return CSHARPTYPE_UINT64;
|
||||
case FieldDescriptor::TYPE_SFIXED32:
|
||||
return CSHARPTYPE_INT32;
|
||||
case FieldDescriptor::TYPE_SFIXED64:
|
||||
return CSHARPTYPE_INT64;
|
||||
case FieldDescriptor::TYPE_FLOAT:
|
||||
return CSHARPTYPE_FLOAT;
|
||||
case FieldDescriptor::TYPE_DOUBLE:
|
||||
return CSHARPTYPE_DOUBLE;
|
||||
case FieldDescriptor::TYPE_BOOL:
|
||||
return CSHARPTYPE_BOOL;
|
||||
case FieldDescriptor::TYPE_ENUM:
|
||||
return CSHARPTYPE_ENUM;
|
||||
case FieldDescriptor::TYPE_STRING:
|
||||
return CSHARPTYPE_STRING;
|
||||
case FieldDescriptor::TYPE_BYTES:
|
||||
return CSHARPTYPE_BYTESTRING;
|
||||
case FieldDescriptor::TYPE_GROUP:
|
||||
return CSHARPTYPE_MESSAGE;
|
||||
case FieldDescriptor::TYPE_MESSAGE:
|
||||
return CSHARPTYPE_MESSAGE;
|
||||
|
||||
// No default because we want the compiler to complain if any new
|
||||
// types are added.
|
||||
}
|
||||
GOOGLE_LOG(FATAL)<< "Can't get here.";
|
||||
return (CSharpType) -1;
|
||||
}
|
||||
|
||||
std::string StripDotProto(const std::string& proto_file) {
|
||||
int lastindex = proto_file.find_last_of(".");
|
||||
return proto_file.substr(0, lastindex);
|
||||
}
|
||||
|
||||
std::string GetFileNamespace(const FileDescriptor* descriptor) {
|
||||
if (descriptor->options().has_csharp_namespace()) {
|
||||
return descriptor->options().csharp_namespace();
|
||||
}
|
||||
return UnderscoresToCamelCase(descriptor->package(), true, true);
|
||||
}
|
||||
|
||||
// Returns the Pascal-cased last part of the proto file. For example,
|
||||
// input of "google/protobuf/foo_bar.proto" would result in "FooBar".
|
||||
std::string GetFileNameBase(const FileDescriptor* descriptor) {
|
||||
std::string proto_file = descriptor->name();
|
||||
int lastslash = proto_file.find_last_of("/");
|
||||
std::string base = proto_file.substr(lastslash + 1);
|
||||
return UnderscoresToPascalCase(StripDotProto(base));
|
||||
}
|
||||
|
||||
std::string GetReflectionClassUnqualifiedName(const FileDescriptor* descriptor) {
|
||||
// TODO: Detect collisions with existing messages,
|
||||
// and append an underscore if necessary.
|
||||
return GetFileNameBase(descriptor) + "Reflection";
|
||||
}
|
||||
|
||||
// TODO(jtattermusch): can we reuse a utility function?
|
||||
std::string UnderscoresToCamelCase(const std::string& input,
|
||||
bool cap_next_letter,
|
||||
bool preserve_period) {
|
||||
string result;
|
||||
// Note: I distrust ctype.h due to locales.
|
||||
for (int i = 0; i < input.size(); i++) {
|
||||
if ('a' <= input[i] && input[i] <= 'z') {
|
||||
if (cap_next_letter) {
|
||||
result += input[i] + ('A' - 'a');
|
||||
} else {
|
||||
result += input[i];
|
||||
}
|
||||
cap_next_letter = false;
|
||||
} else if ('A' <= input[i] && input[i] <= 'Z') {
|
||||
if (i == 0 && !cap_next_letter) {
|
||||
// Force first letter to lower-case unless explicitly told to
|
||||
// capitalize it.
|
||||
result += input[i] + ('a' - 'A');
|
||||
} else {
|
||||
// Capital letters after the first are left as-is.
|
||||
result += input[i];
|
||||
}
|
||||
cap_next_letter = false;
|
||||
} else if ('0' <= input[i] && input[i] <= '9') {
|
||||
result += input[i];
|
||||
cap_next_letter = true;
|
||||
} else {
|
||||
cap_next_letter = true;
|
||||
if (input[i] == '.' && preserve_period) {
|
||||
result += '.';
|
||||
}
|
||||
}
|
||||
}
|
||||
// Add a trailing "_" if the name should be altered.
|
||||
if (input[input.size() - 1] == '#') {
|
||||
result += '_';
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string UnderscoresToPascalCase(const std::string& input) {
|
||||
return UnderscoresToCamelCase(input, true);
|
||||
}
|
||||
|
||||
// Convert a string which is expected to be SHOUTY_CASE (but may not be *precisely* shouty)
|
||||
// into a PascalCase string. Precise rules implemented:
|
||||
|
||||
// Previous input character Current character Case
|
||||
// Any Non-alphanumeric Skipped
|
||||
// None - first char of input Alphanumeric Upper
|
||||
// Non-letter (e.g. _ or 1) Alphanumeric Upper
|
||||
// Numeric Alphanumeric Upper
|
||||
// Lower letter Alphanumeric Same as current
|
||||
// Upper letter Alphanumeric Lower
|
||||
std::string ShoutyToPascalCase(const std::string& input) {
|
||||
string result;
|
||||
// Simple way of implementing "always start with upper"
|
||||
char previous = '_';
|
||||
for (int i = 0; i < input.size(); i++) {
|
||||
char current = input[i];
|
||||
if (!ascii_isalnum(current)) {
|
||||
previous = current;
|
||||
continue;
|
||||
}
|
||||
if (!ascii_isalnum(previous)) {
|
||||
result += ascii_toupper(current);
|
||||
} else if (ascii_isdigit(previous)) {
|
||||
result += ascii_toupper(current);
|
||||
} else if (ascii_islower(previous)) {
|
||||
result += current;
|
||||
} else {
|
||||
result += ascii_tolower(current);
|
||||
}
|
||||
previous = current;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Attempt to remove a prefix from a value, ignoring casing and skipping underscores.
|
||||
// (foo, foo_bar) => bar - underscore after prefix is skipped
|
||||
// (FOO, foo_bar) => bar - casing is ignored
|
||||
// (foo_bar, foobarbaz) => baz - underscore in prefix is ignored
|
||||
// (foobar, foo_barbaz) => baz - underscore in value is ignored
|
||||
// (foo, bar) => bar - prefix isn't matched; return original value
|
||||
std::string TryRemovePrefix(const std::string& prefix, const std::string& value) {
|
||||
// First normalize to a lower-case no-underscores prefix to match against
|
||||
std::string prefix_to_match = "";
|
||||
for (size_t i = 0; i < prefix.size(); i++) {
|
||||
if (prefix[i] != '_') {
|
||||
prefix_to_match += ascii_tolower(prefix[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// This keeps track of how much of value we've consumed
|
||||
size_t prefix_index, value_index;
|
||||
for (prefix_index = 0, value_index = 0;
|
||||
prefix_index < prefix_to_match.size() && value_index < value.size();
|
||||
value_index++) {
|
||||
// Skip over underscores in the value
|
||||
if (value[value_index] == '_') {
|
||||
continue;
|
||||
}
|
||||
if (ascii_tolower(value[value_index]) != prefix_to_match[prefix_index++]) {
|
||||
// Failed to match the prefix - bail out early.
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
// If we didn't finish looking through the prefix, we can't strip it.
|
||||
if (prefix_index < prefix_to_match.size()) {
|
||||
return value;
|
||||
}
|
||||
|
||||
// Step over any underscores after the prefix
|
||||
while (value_index < value.size() && value[value_index] == '_') {
|
||||
value_index++;
|
||||
}
|
||||
|
||||
// If there's nothing left (e.g. it was a prefix with only underscores afterwards), don't strip.
|
||||
if (value_index == value.size()) {
|
||||
return value;
|
||||
}
|
||||
|
||||
return value.substr(value_index);
|
||||
}
|
||||
|
||||
// Format the enum value name in a pleasant way for C#:
|
||||
// - Strip the enum name as a prefix if possible
|
||||
// - Convert to PascalCase.
|
||||
// For example, an enum called Color with a value of COLOR_BLUE should
|
||||
// result in an enum value in C# called just Blue
|
||||
std::string GetEnumValueName(const std::string& enum_name, const std::string& enum_value_name) {
|
||||
std::string stripped = TryRemovePrefix(enum_name, enum_value_name);
|
||||
std::string result = ShoutyToPascalCase(stripped);
|
||||
// Just in case we have an enum name of FOO and a value of FOO_2... make sure the returned
|
||||
// string is a valid identifier.
|
||||
if (ascii_isdigit(result[0])) {
|
||||
result = "_" + result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string ToCSharpName(const std::string& name, const FileDescriptor* file) {
|
||||
std::string result = GetFileNamespace(file);
|
||||
if (result != "") {
|
||||
result += '.';
|
||||
}
|
||||
string classname;
|
||||
if (file->package().empty()) {
|
||||
classname = name;
|
||||
} else {
|
||||
// Strip the proto package from full_name since we've replaced it with
|
||||
// the C# namespace.
|
||||
classname = name.substr(file->package().size() + 1);
|
||||
}
|
||||
result += StringReplace(classname, ".", ".Types.", true);
|
||||
return "global::" + result;
|
||||
}
|
||||
|
||||
std::string GetReflectionClassName(const FileDescriptor* descriptor) {
|
||||
std::string result = GetFileNamespace(descriptor);
|
||||
if (!result.empty()) {
|
||||
result += '.';
|
||||
}
|
||||
result += GetReflectionClassUnqualifiedName(descriptor);
|
||||
return "global::" + result;
|
||||
}
|
||||
|
||||
std::string GetClassName(const Descriptor* descriptor) {
|
||||
return ToCSharpName(descriptor->full_name(), descriptor->file());
|
||||
}
|
||||
|
||||
std::string GetClassName(const EnumDescriptor* descriptor) {
|
||||
return ToCSharpName(descriptor->full_name(), descriptor->file());
|
||||
}
|
||||
|
||||
// Groups are hacky: The name of the field is just the lower-cased name
|
||||
// of the group type. In C#, though, we would like to retain the original
|
||||
// capitalization of the type name.
|
||||
std::string GetFieldName(const FieldDescriptor* descriptor) {
|
||||
if (descriptor->type() == FieldDescriptor::TYPE_GROUP) {
|
||||
return descriptor->message_type()->name();
|
||||
} else {
|
||||
return descriptor->name();
|
||||
}
|
||||
}
|
||||
|
||||
std::string GetFieldConstantName(const FieldDescriptor* field) {
|
||||
return GetPropertyName(field) + "FieldNumber";
|
||||
}
|
||||
|
||||
std::string GetPropertyName(const FieldDescriptor* descriptor) {
|
||||
// TODO(jtattermusch): consider introducing csharp_property_name field option
|
||||
std::string property_name = UnderscoresToPascalCase(GetFieldName(descriptor));
|
||||
// Avoid either our own type name or reserved names. Note that not all names
|
||||
// are reserved - a field called to_string, write_to etc would still cause a problem.
|
||||
// There are various ways of ending up with naming collisions, but we try to avoid obvious
|
||||
// ones.
|
||||
if (property_name == descriptor->containing_type()->name()
|
||||
|| property_name == "Types"
|
||||
|| property_name == "Descriptor") {
|
||||
property_name += "_";
|
||||
}
|
||||
return property_name;
|
||||
}
|
||||
|
||||
std::string GetOutputFile(
|
||||
const google::protobuf::FileDescriptor* descriptor,
|
||||
const std::string file_extension,
|
||||
const bool generate_directories,
|
||||
const std::string base_namespace,
|
||||
string* error) {
|
||||
string relative_filename = GetFileNameBase(descriptor) + file_extension;
|
||||
if (!generate_directories) {
|
||||
return relative_filename;
|
||||
}
|
||||
string ns = GetFileNamespace(descriptor);
|
||||
string namespace_suffix = ns;
|
||||
if (!base_namespace.empty()) {
|
||||
// Check that the base_namespace is either equal to or a leading part of
|
||||
// the file namespace. This isn't just a simple prefix; "Foo.B" shouldn't
|
||||
// be regarded as a prefix of "Foo.Bar". The simplest option is to add "."
|
||||
// to both.
|
||||
string extended_ns = ns + ".";
|
||||
if (extended_ns.find(base_namespace + ".") != 0) {
|
||||
*error = "Namespace " + ns + " is not a prefix namespace of base namespace " + base_namespace;
|
||||
return ""; // This will be ignored, because we've set an error.
|
||||
}
|
||||
namespace_suffix = ns.substr(base_namespace.length());
|
||||
if (namespace_suffix.find(".") == 0) {
|
||||
namespace_suffix = namespace_suffix.substr(1);
|
||||
}
|
||||
}
|
||||
|
||||
string namespace_dir = StringReplace(namespace_suffix, ".", "/", true);
|
||||
if (!namespace_dir.empty()) {
|
||||
namespace_dir += "/";
|
||||
}
|
||||
return namespace_dir + relative_filename;
|
||||
}
|
||||
|
||||
// TODO: c&p from Java protoc plugin
|
||||
// For encodings with fixed sizes, returns that size in bytes. Otherwise
|
||||
// returns -1.
|
||||
int GetFixedSize(FieldDescriptor::Type type) {
|
||||
switch (type) {
|
||||
case FieldDescriptor::TYPE_INT32 : return -1;
|
||||
case FieldDescriptor::TYPE_INT64 : return -1;
|
||||
case FieldDescriptor::TYPE_UINT32 : return -1;
|
||||
case FieldDescriptor::TYPE_UINT64 : return -1;
|
||||
case FieldDescriptor::TYPE_SINT32 : return -1;
|
||||
case FieldDescriptor::TYPE_SINT64 : return -1;
|
||||
case FieldDescriptor::TYPE_FIXED32 : return internal::WireFormatLite::kFixed32Size;
|
||||
case FieldDescriptor::TYPE_FIXED64 : return internal::WireFormatLite::kFixed64Size;
|
||||
case FieldDescriptor::TYPE_SFIXED32: return internal::WireFormatLite::kSFixed32Size;
|
||||
case FieldDescriptor::TYPE_SFIXED64: return internal::WireFormatLite::kSFixed64Size;
|
||||
case FieldDescriptor::TYPE_FLOAT : return internal::WireFormatLite::kFloatSize;
|
||||
case FieldDescriptor::TYPE_DOUBLE : return internal::WireFormatLite::kDoubleSize;
|
||||
|
||||
case FieldDescriptor::TYPE_BOOL : return internal::WireFormatLite::kBoolSize;
|
||||
case FieldDescriptor::TYPE_ENUM : return -1;
|
||||
|
||||
case FieldDescriptor::TYPE_STRING : return -1;
|
||||
case FieldDescriptor::TYPE_BYTES : return -1;
|
||||
case FieldDescriptor::TYPE_GROUP : return -1;
|
||||
case FieldDescriptor::TYPE_MESSAGE : return -1;
|
||||
|
||||
// No default because we want the compiler to complain if any new
|
||||
// types are added.
|
||||
}
|
||||
GOOGLE_LOG(FATAL) << "Can't get here.";
|
||||
return -1;
|
||||
}
|
||||
|
||||
static const char base64_chars[] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
std::string StringToBase64(const std::string& input) {
|
||||
std::string result;
|
||||
size_t remaining = input.size();
|
||||
const unsigned char *src = (const unsigned char*) input.c_str();
|
||||
while (remaining > 2) {
|
||||
result += base64_chars[src[0] >> 2];
|
||||
result += base64_chars[((src[0] & 0x3) << 4) | (src[1] >> 4)];
|
||||
result += base64_chars[((src[1] & 0xf) << 2) | (src[2] >> 6)];
|
||||
result += base64_chars[src[2] & 0x3f];
|
||||
remaining -= 3;
|
||||
src += 3;
|
||||
}
|
||||
switch (remaining) {
|
||||
case 2:
|
||||
result += base64_chars[src[0] >> 2];
|
||||
result += base64_chars[((src[0] & 0x3) << 4) | (src[1] >> 4)];
|
||||
result += base64_chars[(src[1] & 0xf) << 2];
|
||||
result += '=';
|
||||
src += 2;
|
||||
break;
|
||||
case 1:
|
||||
result += base64_chars[src[0] >> 2];
|
||||
result += base64_chars[((src[0] & 0x3) << 4)];
|
||||
result += '=';
|
||||
result += '=';
|
||||
src += 1;
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string FileDescriptorToBase64(const FileDescriptor* descriptor) {
|
||||
std::string fdp_bytes;
|
||||
FileDescriptorProto fdp;
|
||||
descriptor->CopyTo(&fdp);
|
||||
fdp.SerializeToString(&fdp_bytes);
|
||||
return StringToBase64(fdp_bytes);
|
||||
}
|
||||
|
||||
FieldGeneratorBase* CreateFieldGenerator(const FieldDescriptor* descriptor,
|
||||
int fieldOrdinal,
|
||||
const Options* options) {
|
||||
switch (descriptor->type()) {
|
||||
case FieldDescriptor::TYPE_GROUP:
|
||||
case FieldDescriptor::TYPE_MESSAGE:
|
||||
if (descriptor->is_repeated()) {
|
||||
if (descriptor->is_map()) {
|
||||
return new MapFieldGenerator(descriptor, fieldOrdinal, options);
|
||||
} else {
|
||||
return new RepeatedMessageFieldGenerator(descriptor, fieldOrdinal, options);
|
||||
}
|
||||
} else {
|
||||
if (IsWrapperType(descriptor)) {
|
||||
if (descriptor->containing_oneof()) {
|
||||
return new WrapperOneofFieldGenerator(descriptor, fieldOrdinal, options);
|
||||
} else {
|
||||
return new WrapperFieldGenerator(descriptor, fieldOrdinal, options);
|
||||
}
|
||||
} else {
|
||||
if (descriptor->containing_oneof()) {
|
||||
return new MessageOneofFieldGenerator(descriptor, fieldOrdinal, options);
|
||||
} else {
|
||||
return new MessageFieldGenerator(descriptor, fieldOrdinal, options);
|
||||
}
|
||||
}
|
||||
}
|
||||
case FieldDescriptor::TYPE_ENUM:
|
||||
if (descriptor->is_repeated()) {
|
||||
return new RepeatedEnumFieldGenerator(descriptor, fieldOrdinal, options);
|
||||
} else {
|
||||
if (descriptor->containing_oneof()) {
|
||||
return new EnumOneofFieldGenerator(descriptor, fieldOrdinal, options);
|
||||
} else {
|
||||
return new EnumFieldGenerator(descriptor, fieldOrdinal, options);
|
||||
}
|
||||
}
|
||||
default:
|
||||
if (descriptor->is_repeated()) {
|
||||
return new RepeatedPrimitiveFieldGenerator(descriptor, fieldOrdinal, options);
|
||||
} else {
|
||||
if (descriptor->containing_oneof()) {
|
||||
return new PrimitiveOneofFieldGenerator(descriptor, fieldOrdinal, options);
|
||||
} else {
|
||||
return new PrimitiveFieldGenerator(descriptor, fieldOrdinal, options);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace csharp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
@ -0,0 +1,148 @@
|
||||
// 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.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_HELPERS_H__
|
||||
#define GOOGLE_PROTOBUF_COMPILER_CSHARP_HELPERS_H__
|
||||
|
||||
#include <string>
|
||||
#include <google/protobuf/stubs/port.h>
|
||||
#include <google/protobuf/descriptor.pb.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/compiler/code_generator.h>
|
||||
#include <google/protobuf/io/printer.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace csharp {
|
||||
|
||||
struct Options;
|
||||
class FieldGeneratorBase;
|
||||
|
||||
// TODO: start using this enum.
|
||||
enum CSharpType {
|
||||
CSHARPTYPE_INT32 = 1,
|
||||
CSHARPTYPE_INT64 = 2,
|
||||
CSHARPTYPE_UINT32 = 3,
|
||||
CSHARPTYPE_UINT64 = 4,
|
||||
CSHARPTYPE_FLOAT = 5,
|
||||
CSHARPTYPE_DOUBLE = 6,
|
||||
CSHARPTYPE_BOOL = 7,
|
||||
CSHARPTYPE_STRING = 8,
|
||||
CSHARPTYPE_BYTESTRING = 9,
|
||||
CSHARPTYPE_MESSAGE = 10,
|
||||
CSHARPTYPE_ENUM = 11,
|
||||
MAX_CSHARPTYPE = 11
|
||||
};
|
||||
|
||||
// Converts field type to corresponding C# type.
|
||||
CSharpType GetCSharpType(FieldDescriptor::Type type);
|
||||
|
||||
std::string StripDotProto(const std::string& proto_file);
|
||||
|
||||
// Gets unqualified name of the reflection class
|
||||
std::string GetReflectionClassUnqualifiedName(const FileDescriptor* descriptor);
|
||||
|
||||
std::string GetClassName(const EnumDescriptor* descriptor);
|
||||
|
||||
std::string GetFieldName(const FieldDescriptor* descriptor);
|
||||
|
||||
std::string GetFieldConstantName(const FieldDescriptor* field);
|
||||
|
||||
std::string GetPropertyName(const FieldDescriptor* descriptor);
|
||||
|
||||
int GetFixedSize(FieldDescriptor::Type type);
|
||||
|
||||
std::string UnderscoresToCamelCase(const std::string& input,
|
||||
bool cap_next_letter,
|
||||
bool preserve_period);
|
||||
|
||||
inline std::string UnderscoresToCamelCase(const std::string& input, bool cap_next_letter) {
|
||||
return UnderscoresToCamelCase(input, cap_next_letter, false);
|
||||
}
|
||||
|
||||
std::string UnderscoresToPascalCase(const std::string& input);
|
||||
|
||||
// Note that we wouldn't normally want to export this (we're not expecting
|
||||
// it to be used outside libprotoc itself) but this exposes it for testing.
|
||||
std::string LIBPROTOBUF_EXPORT GetEnumValueName(const std::string& enum_name, const std::string& enum_value_name);
|
||||
|
||||
// TODO(jtattermusch): perhaps we could move this to strutil
|
||||
std::string StringToBase64(const std::string& input);
|
||||
|
||||
std::string FileDescriptorToBase64(const FileDescriptor* descriptor);
|
||||
|
||||
FieldGeneratorBase* CreateFieldGenerator(const FieldDescriptor* descriptor,
|
||||
int fieldOrdinal,
|
||||
const Options* options);
|
||||
|
||||
// Determines whether the given message is a map entry message,
|
||||
// i.e. one implicitly created by protoc due to a map<key, value> field.
|
||||
inline bool IsMapEntryMessage(const Descriptor* descriptor) {
|
||||
return descriptor->options().map_entry();
|
||||
}
|
||||
|
||||
// Determines whether we're generating code for the proto representation of
|
||||
// descriptors etc, for use in the runtime. This is the only type which is
|
||||
// allowed to use proto2 syntax, and it generates internal classes.
|
||||
inline bool IsDescriptorProto(const FileDescriptor* descriptor) {
|
||||
return descriptor->name() == "google/protobuf/descriptor.proto";
|
||||
}
|
||||
|
||||
// Determines whether the given message is an options message within descriptor.proto.
|
||||
inline bool IsDescriptorOptionMessage(const Descriptor* descriptor) {
|
||||
if (!IsDescriptorProto(descriptor->file())) {
|
||||
return false;
|
||||
}
|
||||
const string name = descriptor->full_name();
|
||||
return name == "google.protobuf.FileOptions" ||
|
||||
name == "google.protobuf.MessageOptions" ||
|
||||
name == "google.protobuf.FieldOptions" ||
|
||||
name == "google.protobuf.OneofOptions" ||
|
||||
name == "google.protobuf.EnumOptions" ||
|
||||
name == "google.protobuf.EnumValueOptions" ||
|
||||
name == "google.protobuf.ServiceOptions" ||
|
||||
name == "google.protobuf.MethodOptions";
|
||||
}
|
||||
|
||||
inline bool IsWrapperType(const FieldDescriptor* descriptor) {
|
||||
return descriptor->type() == FieldDescriptor::TYPE_MESSAGE &&
|
||||
descriptor->message_type()->file()->name() == "google/protobuf/wrappers.proto";
|
||||
}
|
||||
|
||||
} // namespace csharp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_HELPERS_H__
|
@ -0,0 +1,141 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2015 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 <sstream>
|
||||
|
||||
#include <google/protobuf/compiler/code_generator.h>
|
||||
#include <google/protobuf/compiler/plugin.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/descriptor.pb.h>
|
||||
#include <google/protobuf/io/printer.h>
|
||||
#include <google/protobuf/io/zero_copy_stream.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
|
||||
#include <google/protobuf/compiler/csharp/csharp_doc_comment.h>
|
||||
#include <google/protobuf/compiler/csharp/csharp_helpers.h>
|
||||
#include <google/protobuf/compiler/csharp/csharp_map_field.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace csharp {
|
||||
|
||||
MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor,
|
||||
int fieldOrdinal,
|
||||
const Options* options)
|
||||
: FieldGeneratorBase(descriptor, fieldOrdinal, options) {
|
||||
}
|
||||
|
||||
MapFieldGenerator::~MapFieldGenerator() {
|
||||
}
|
||||
|
||||
void MapFieldGenerator::GenerateMembers(io::Printer* printer) {
|
||||
const FieldDescriptor* key_descriptor =
|
||||
descriptor_->message_type()->FindFieldByName("key");
|
||||
const FieldDescriptor* value_descriptor =
|
||||
descriptor_->message_type()->FindFieldByName("value");
|
||||
variables_["key_type_name"] = type_name(key_descriptor);
|
||||
variables_["value_type_name"] = type_name(value_descriptor);
|
||||
std::unique_ptr<FieldGeneratorBase> key_generator(
|
||||
CreateFieldGenerator(key_descriptor, 1, this->options()));
|
||||
std::unique_ptr<FieldGeneratorBase> value_generator(
|
||||
CreateFieldGenerator(value_descriptor, 2, this->options()));
|
||||
|
||||
printer->Print(
|
||||
variables_,
|
||||
"private static readonly pbc::MapField<$key_type_name$, $value_type_name$>.Codec _map_$name$_codec\n"
|
||||
" = new pbc::MapField<$key_type_name$, $value_type_name$>.Codec(");
|
||||
key_generator->GenerateCodecCode(printer);
|
||||
printer->Print(", ");
|
||||
value_generator->GenerateCodecCode(printer);
|
||||
printer->Print(
|
||||
variables_,
|
||||
", $tag$);\n"
|
||||
"private readonly pbc::MapField<$key_type_name$, $value_type_name$> $name$_ = new pbc::MapField<$key_type_name$, $value_type_name$>();\n");
|
||||
WritePropertyDocComment(printer, descriptor_);
|
||||
AddPublicMemberAttributes(printer);
|
||||
printer->Print(
|
||||
variables_,
|
||||
"$access_level$ pbc::MapField<$key_type_name$, $value_type_name$> $property_name$ {\n"
|
||||
" get { return $name$_; }\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void MapFieldGenerator::GenerateMergingCode(io::Printer* printer) {
|
||||
printer->Print(
|
||||
variables_,
|
||||
"$name$_.Add(other.$name$_);\n");
|
||||
}
|
||||
|
||||
void MapFieldGenerator::GenerateParsingCode(io::Printer* printer) {
|
||||
printer->Print(
|
||||
variables_,
|
||||
"$name$_.AddEntriesFrom(input, _map_$name$_codec);\n");
|
||||
}
|
||||
|
||||
void MapFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
|
||||
printer->Print(
|
||||
variables_,
|
||||
"$name$_.WriteTo(output, _map_$name$_codec);\n");
|
||||
}
|
||||
|
||||
void MapFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
|
||||
printer->Print(
|
||||
variables_,
|
||||
"size += $name$_.CalculateSize(_map_$name$_codec);\n");
|
||||
}
|
||||
|
||||
void MapFieldGenerator::WriteHash(io::Printer* printer) {
|
||||
printer->Print(
|
||||
variables_,
|
||||
"hash ^= $property_name$.GetHashCode();\n");
|
||||
}
|
||||
void MapFieldGenerator::WriteEquals(io::Printer* printer) {
|
||||
printer->Print(
|
||||
variables_,
|
||||
"if (!$property_name$.Equals(other.$property_name$)) return false;\n");
|
||||
}
|
||||
|
||||
void MapFieldGenerator::WriteToString(io::Printer* printer) {
|
||||
// TODO: If we ever actually use ToString, we'll need to impleme this...
|
||||
}
|
||||
|
||||
void MapFieldGenerator::GenerateCloningCode(io::Printer* printer) {
|
||||
printer->Print(variables_,
|
||||
"$name$_ = other.$name$_.Clone();\n");
|
||||
}
|
||||
|
||||
void MapFieldGenerator::GenerateFreezingCode(io::Printer* printer) {
|
||||
}
|
||||
|
||||
} // namespace csharp
|
||||
} // namespace compiler
|
||||
} // 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