mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-07-02 02:51:42 +00:00
[wpiutil,glass,dlt] Replace libprotobuf with upb for dynamic decode (#7988)
libprotobuf is a very annoying dependency to deal with, and with the switch to nanopb for generated C++ code, libprotobuf is only used for dynamic decode in the GUI apps. libprotobuf has been swapped out with upb, a much smaller C-based library that supports reflection and can therefore do dynamic decode. This means we can remove the libprotobuf dependency and stop dealing with build issues because of it.
This commit is contained in:
@@ -1,136 +0,0 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
#include "wpi/protobuf/ProtobufMessageDatabase.h"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/descriptor.h>
|
||||
|
||||
#include "wpi/ProtoHelper.h"
|
||||
|
||||
using namespace wpi;
|
||||
|
||||
using google::protobuf::Arena;
|
||||
using google::protobuf::FileDescriptorProto;
|
||||
using google::protobuf::Message;
|
||||
|
||||
bool ProtobufMessageDatabase::Add(std::string_view filename,
|
||||
std::span<const uint8_t> data) {
|
||||
auto& file = m_files[filename];
|
||||
bool needsRebuild = false;
|
||||
if (file.complete) {
|
||||
file.complete = false;
|
||||
|
||||
m_msgs.clear();
|
||||
m_factory.reset();
|
||||
|
||||
// rebuild the pool EXCEPT for this descriptor
|
||||
m_pool = std::make_unique<google::protobuf::DescriptorPool>();
|
||||
|
||||
for (auto&& p : m_files) {
|
||||
p.second.inPool = false;
|
||||
}
|
||||
|
||||
needsRebuild = true;
|
||||
}
|
||||
|
||||
if (!file.proto) {
|
||||
file.proto = std::unique_ptr<FileDescriptorProto>{
|
||||
wpi::CreateMessage<FileDescriptorProto>(nullptr)};
|
||||
} else {
|
||||
// replacing an existing one; remove any previously existing refs
|
||||
for (auto&& dep : file.proto->dependency()) {
|
||||
auto& depFile = m_files[dep];
|
||||
std::erase(depFile.uses, filename);
|
||||
}
|
||||
file.proto->Clear();
|
||||
}
|
||||
|
||||
// parse data
|
||||
if (!file.proto->ParseFromArray(data.data(), data.size())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// rebuild if necessary; we do this after the parse due to dependencies
|
||||
if (needsRebuild) {
|
||||
for (auto&& p : m_files) {
|
||||
if (p.second.complete && !p.second.inPool) {
|
||||
Rebuild(p.second);
|
||||
}
|
||||
}
|
||||
|
||||
// clear messages and reset factory; Find() will recreate as needed
|
||||
m_factory = std::make_unique<google::protobuf::DynamicMessageFactory>();
|
||||
}
|
||||
|
||||
// build this one
|
||||
Build(filename, file);
|
||||
return true;
|
||||
}
|
||||
|
||||
Message* ProtobufMessageDatabase::Find(std::string_view name) const {
|
||||
// cached
|
||||
auto& msg = m_msgs[name];
|
||||
if (msg) {
|
||||
return msg.get();
|
||||
}
|
||||
|
||||
// need to create it
|
||||
auto desc = m_pool->FindMessageTypeByName(std::string{name});
|
||||
if (!desc) {
|
||||
return nullptr;
|
||||
}
|
||||
msg = std::unique_ptr<Message>{m_factory->GetPrototype(desc)->New(nullptr)};
|
||||
return msg.get();
|
||||
}
|
||||
|
||||
void ProtobufMessageDatabase::Build(std::string_view filename,
|
||||
ProtoFile& file) {
|
||||
if (file.complete) {
|
||||
return;
|
||||
}
|
||||
// are all of the dependencies complete?
|
||||
bool complete = true;
|
||||
for (auto&& dep : file.proto->dependency()) {
|
||||
auto& depFile = m_files[dep];
|
||||
if (!depFile.complete) {
|
||||
complete = false;
|
||||
}
|
||||
depFile.uses.emplace_back(filename);
|
||||
}
|
||||
if (!complete) {
|
||||
return;
|
||||
}
|
||||
|
||||
// add to pool
|
||||
if (!m_pool->BuildFile(*file.proto)) {
|
||||
return;
|
||||
}
|
||||
file.inPool = true;
|
||||
file.complete = true;
|
||||
|
||||
// recursively validate all uses
|
||||
for (auto&& use : file.uses) {
|
||||
Build(use, m_files[use]);
|
||||
}
|
||||
}
|
||||
|
||||
bool ProtobufMessageDatabase::Rebuild(ProtoFile& file) {
|
||||
for (auto&& dep : file.proto->dependency()) {
|
||||
auto& depFile = m_files[dep];
|
||||
if (!depFile.inPool) {
|
||||
if (!Rebuild(depFile)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!m_pool->BuildFile(*file.proto)) {
|
||||
return false;
|
||||
}
|
||||
file.inPool = true;
|
||||
file.complete = true;
|
||||
return true;
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <google/protobuf/message.h>
|
||||
|
||||
namespace wpi {
|
||||
template <typename T>
|
||||
inline T* CreateMessage(google::protobuf::Arena* arena) {
|
||||
#if GOOGLE_PROTOBUF_VERSION < 4000000
|
||||
return google::protobuf::Arena::CreateMessage<T>(arena);
|
||||
#else
|
||||
return google::protobuf::Arena::Create<T>(arena);
|
||||
#endif
|
||||
}
|
||||
} // namespace wpi
|
||||
@@ -1,77 +0,0 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <span>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include <google/protobuf/descriptor.pb.h>
|
||||
#include <google/protobuf/descriptor_database.h>
|
||||
#include <google/protobuf/dynamic_message.h>
|
||||
|
||||
#include "wpi/StringMap.h"
|
||||
|
||||
namespace wpi {
|
||||
|
||||
/**
|
||||
* Database of protobuf dynamic messages. Unlike the protobuf descriptor pools
|
||||
* and databases, this gracefully handles adding descriptors out of order and
|
||||
* descriptors being replaced.
|
||||
*/
|
||||
class ProtobufMessageDatabase {
|
||||
public:
|
||||
/**
|
||||
* Adds a file descriptor to the database. If the file references other
|
||||
* files that have not yet been added, no messages in that file will be
|
||||
* available until those files are added. Replaces any existing file with
|
||||
* the same name.
|
||||
*
|
||||
* @param filename filename
|
||||
* @param data FileDescriptorProto serialized data
|
||||
* @return False if could not parse data
|
||||
*/
|
||||
bool Add(std::string_view filename, std::span<const uint8_t> data);
|
||||
|
||||
/**
|
||||
* Finds a message in the database by name.
|
||||
*
|
||||
* @param name type name
|
||||
* @return protobuf message, or nullptr if not found
|
||||
*/
|
||||
google::protobuf::Message* Find(std::string_view name) const;
|
||||
|
||||
/**
|
||||
* Gets message factory.
|
||||
*
|
||||
* @return message factory
|
||||
*/
|
||||
google::protobuf::MessageFactory* GetMessageFactory() {
|
||||
return m_factory.get();
|
||||
}
|
||||
|
||||
private:
|
||||
struct ProtoFile {
|
||||
std::unique_ptr<google::protobuf::FileDescriptorProto> proto;
|
||||
std::vector<std::string> uses;
|
||||
bool complete = false;
|
||||
bool inPool = false;
|
||||
};
|
||||
|
||||
void Build(std::string_view filename, ProtoFile& file);
|
||||
bool Rebuild(ProtoFile& file);
|
||||
|
||||
std::unique_ptr<google::protobuf::DescriptorPool> m_pool =
|
||||
std::make_unique<google::protobuf::DescriptorPool>();
|
||||
std::unique_ptr<google::protobuf::DynamicMessageFactory> m_factory =
|
||||
std::make_unique<google::protobuf::DynamicMessageFactory>();
|
||||
wpi::StringMap<ProtoFile> m_files; // indexed by filename
|
||||
// indexed by type string
|
||||
mutable wpi::StringMap<std::unique_ptr<google::protobuf::Message>> m_msgs;
|
||||
};
|
||||
|
||||
} // namespace wpi
|
||||
@@ -1,157 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_ANY_H__
|
||||
#define GOOGLE_PROTOBUF_ANY_H__
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/arenastring.h>
|
||||
#include <google/protobuf/message_lite.h>
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
class FieldDescriptor;
|
||||
class Message;
|
||||
|
||||
namespace internal {
|
||||
|
||||
extern const char kAnyFullTypeName[]; // "google.protobuf.Any".
|
||||
extern const char kTypeGoogleApisComPrefix[]; // "type.googleapis.com/".
|
||||
extern const char kTypeGoogleProdComPrefix[]; // "type.googleprod.com/".
|
||||
|
||||
std::string GetTypeUrl(StringPiece message_name,
|
||||
StringPiece type_url_prefix);
|
||||
|
||||
// Helper class used to implement google::protobuf::Any.
|
||||
class PROTOBUF_EXPORT AnyMetadata {
|
||||
typedef ArenaStringPtr UrlType;
|
||||
typedef ArenaStringPtr ValueType;
|
||||
public:
|
||||
// AnyMetadata does not take ownership of "type_url" and "value".
|
||||
constexpr AnyMetadata(UrlType* type_url, ValueType* value)
|
||||
: type_url_(type_url), value_(value) {}
|
||||
|
||||
// Packs a message using the default type URL prefix: "type.googleapis.com".
|
||||
// The resulted type URL will be "type.googleapis.com/<message_full_name>".
|
||||
// Returns false if serializing the message failed.
|
||||
template <typename T>
|
||||
bool PackFrom(Arena* arena, const T& message) {
|
||||
return InternalPackFrom(arena, message, kTypeGoogleApisComPrefix,
|
||||
T::FullMessageName());
|
||||
}
|
||||
|
||||
bool PackFrom(Arena* arena, const Message& message);
|
||||
|
||||
// Packs a message using the given type URL prefix. The type URL will be
|
||||
// constructed by concatenating the message type's full name to the prefix
|
||||
// with an optional "/" separator if the prefix doesn't already end with "/".
|
||||
// For example, both PackFrom(message, "type.googleapis.com") and
|
||||
// PackFrom(message, "type.googleapis.com/") yield the same result type
|
||||
// URL: "type.googleapis.com/<message_full_name>".
|
||||
// Returns false if serializing the message failed.
|
||||
template <typename T>
|
||||
bool PackFrom(Arena* arena, const T& message,
|
||||
StringPiece type_url_prefix) {
|
||||
return InternalPackFrom(arena, message, type_url_prefix,
|
||||
T::FullMessageName());
|
||||
}
|
||||
|
||||
bool PackFrom(Arena* arena, const Message& message,
|
||||
StringPiece type_url_prefix);
|
||||
|
||||
// Unpacks the payload into the given message. Returns false if the message's
|
||||
// type doesn't match the type specified in the type URL (i.e., the full
|
||||
// name after the last "/" of the type URL doesn't match the message's actual
|
||||
// full name) or parsing the payload has failed.
|
||||
template <typename T>
|
||||
bool UnpackTo(T* message) const {
|
||||
return InternalUnpackTo(T::FullMessageName(), message);
|
||||
}
|
||||
|
||||
bool UnpackTo(Message* message) const;
|
||||
|
||||
// Checks whether the type specified in the type URL matches the given type.
|
||||
// A type is considered matching if its full name matches the full name after
|
||||
// the last "/" in the type URL.
|
||||
template <typename T>
|
||||
bool Is() const {
|
||||
return InternalIs(T::FullMessageName());
|
||||
}
|
||||
|
||||
private:
|
||||
bool InternalPackFrom(Arena* arena, const MessageLite& message,
|
||||
StringPiece type_url_prefix,
|
||||
StringPiece type_name);
|
||||
bool InternalUnpackTo(StringPiece type_name,
|
||||
MessageLite* message) const;
|
||||
bool InternalIs(StringPiece type_name) const;
|
||||
|
||||
UrlType* type_url_;
|
||||
ValueType* value_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(AnyMetadata);
|
||||
};
|
||||
|
||||
// Get the proto type name from Any::type_url value. For example, passing
|
||||
// "type.googleapis.com/rpc.QueryOrigin" will return "rpc.QueryOrigin" in
|
||||
// *full_type_name. Returns false if the type_url does not have a "/"
|
||||
// in the type url separating the full type name.
|
||||
//
|
||||
// NOTE: this function is available publicly as a static method on the
|
||||
// generated message type: google::protobuf::Any::ParseAnyTypeUrl()
|
||||
bool ParseAnyTypeUrl(StringPiece type_url, std::string* full_type_name);
|
||||
|
||||
// Get the proto type name and prefix from Any::type_url value. For example,
|
||||
// passing "type.googleapis.com/rpc.QueryOrigin" will return
|
||||
// "type.googleapis.com/" in *url_prefix and "rpc.QueryOrigin" in
|
||||
// *full_type_name. Returns false if the type_url does not have a "/" in the
|
||||
// type url separating the full type name.
|
||||
bool ParseAnyTypeUrl(StringPiece type_url, std::string* url_prefix,
|
||||
std::string* full_type_name);
|
||||
|
||||
// See if message is of type google.protobuf.Any, if so, return the descriptors
|
||||
// for "type_url" and "value" fields.
|
||||
bool GetAnyFieldDescriptors(const Message& message,
|
||||
const FieldDescriptor** type_url_field,
|
||||
const FieldDescriptor** value_field);
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_ANY_H__
|
||||
@@ -1,384 +0,0 @@
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: google/protobuf/any.proto
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fany_2eproto
|
||||
#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fany_2eproto
|
||||
|
||||
#include <limits>
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/port_def.inc>
|
||||
#if PROTOBUF_VERSION < 3021000
|
||||
#error This file was generated by a newer version of protoc which is
|
||||
#error incompatible with your Protocol Buffer headers. Please update
|
||||
#error your headers.
|
||||
#endif
|
||||
#if 3021012 < PROTOBUF_MIN_PROTOC_VERSION
|
||||
#error This file was generated by an older version of protoc which is
|
||||
#error incompatible with your Protocol Buffer headers. Please
|
||||
#error regenerate this file with a newer version of protoc.
|
||||
#endif
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/arena.h>
|
||||
#include <google/protobuf/arenastring.h>
|
||||
#include <google/protobuf/generated_message_util.h>
|
||||
#include <google/protobuf/metadata_lite.h>
|
||||
#include <google/protobuf/generated_message_reflection.h>
|
||||
#include <google/protobuf/message.h>
|
||||
#include <google/protobuf/repeated_field.h> // IWYU pragma: export
|
||||
#include <google/protobuf/extension_set.h> // IWYU pragma: export
|
||||
#include <google/protobuf/unknown_field_set.h>
|
||||
// @@protoc_insertion_point(includes)
|
||||
#include <google/protobuf/port_def.inc>
|
||||
#define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fany_2eproto PROTOBUF_EXPORT
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
namespace internal {
|
||||
class AnyMetadata;
|
||||
} // namespace internal
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
|
||||
// Internal implementation detail -- do not use these members.
|
||||
struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2fany_2eproto {
|
||||
static const uint32_t offsets[];
|
||||
};
|
||||
PROTOBUF_EXPORT extern const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fany_2eproto;
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
class Any;
|
||||
struct AnyDefaultTypeInternal;
|
||||
PROTOBUF_EXPORT extern AnyDefaultTypeInternal _Any_default_instance_;
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Any* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Any>(Arena*);
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
|
||||
// ===================================================================
|
||||
|
||||
class PROTOBUF_EXPORT Any final :
|
||||
public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Any) */ {
|
||||
public:
|
||||
inline Any() : Any(nullptr) {}
|
||||
~Any() override;
|
||||
explicit PROTOBUF_CONSTEXPR Any(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
|
||||
|
||||
Any(const Any& from);
|
||||
Any(Any&& from) noexcept
|
||||
: Any() {
|
||||
*this = ::std::move(from);
|
||||
}
|
||||
|
||||
inline Any& operator=(const Any& from) {
|
||||
CopyFrom(from);
|
||||
return *this;
|
||||
}
|
||||
inline Any& operator=(Any&& from) noexcept {
|
||||
if (this == &from) return *this;
|
||||
if (GetOwningArena() == from.GetOwningArena()
|
||||
#ifdef PROTOBUF_FORCE_COPY_IN_MOVE
|
||||
&& GetOwningArena() != nullptr
|
||||
#endif // !PROTOBUF_FORCE_COPY_IN_MOVE
|
||||
) {
|
||||
InternalSwap(&from);
|
||||
} else {
|
||||
CopyFrom(from);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() {
|
||||
return GetDescriptor();
|
||||
}
|
||||
static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
|
||||
return default_instance().GetMetadata().descriptor;
|
||||
}
|
||||
static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
|
||||
return default_instance().GetMetadata().reflection;
|
||||
}
|
||||
static const Any& default_instance() {
|
||||
return *internal_default_instance();
|
||||
}
|
||||
static inline const Any* internal_default_instance() {
|
||||
return reinterpret_cast<const Any*>(
|
||||
&_Any_default_instance_);
|
||||
}
|
||||
static constexpr int kIndexInFileMessages =
|
||||
0;
|
||||
|
||||
// implements Any -----------------------------------------------
|
||||
|
||||
bool PackFrom(const ::PROTOBUF_NAMESPACE_ID::Message& message) {
|
||||
GOOGLE_DCHECK_NE(&message, this);
|
||||
return _impl_._any_metadata_.PackFrom(GetArena(), message);
|
||||
}
|
||||
bool PackFrom(const ::PROTOBUF_NAMESPACE_ID::Message& message,
|
||||
::PROTOBUF_NAMESPACE_ID::ConstStringParam type_url_prefix) {
|
||||
GOOGLE_DCHECK_NE(&message, this);
|
||||
return _impl_._any_metadata_.PackFrom(GetArena(), message, type_url_prefix);
|
||||
}
|
||||
bool UnpackTo(::PROTOBUF_NAMESPACE_ID::Message* message) const {
|
||||
return _impl_._any_metadata_.UnpackTo(message);
|
||||
}
|
||||
static bool GetAnyFieldDescriptors(
|
||||
const ::PROTOBUF_NAMESPACE_ID::Message& message,
|
||||
const ::PROTOBUF_NAMESPACE_ID::FieldDescriptor** type_url_field,
|
||||
const ::PROTOBUF_NAMESPACE_ID::FieldDescriptor** value_field);
|
||||
template <typename T, class = typename std::enable_if<!std::is_convertible<T, const ::PROTOBUF_NAMESPACE_ID::Message&>::value>::type>
|
||||
bool PackFrom(const T& message) {
|
||||
return _impl_._any_metadata_.PackFrom<T>(GetArena(), message);
|
||||
}
|
||||
template <typename T, class = typename std::enable_if<!std::is_convertible<T, const ::PROTOBUF_NAMESPACE_ID::Message&>::value>::type>
|
||||
bool PackFrom(const T& message,
|
||||
::PROTOBUF_NAMESPACE_ID::ConstStringParam type_url_prefix) {
|
||||
return _impl_._any_metadata_.PackFrom<T>(GetArena(), message, type_url_prefix);}
|
||||
template <typename T, class = typename std::enable_if<!std::is_convertible<T, const ::PROTOBUF_NAMESPACE_ID::Message&>::value>::type>
|
||||
bool UnpackTo(T* message) const {
|
||||
return _impl_._any_metadata_.UnpackTo<T>(message);
|
||||
}
|
||||
template<typename T> bool Is() const {
|
||||
return _impl_._any_metadata_.Is<T>();
|
||||
}
|
||||
static bool ParseAnyTypeUrl(::PROTOBUF_NAMESPACE_ID::ConstStringParam type_url,
|
||||
std::string* full_type_name);
|
||||
friend void swap(Any& a, Any& b) {
|
||||
a.Swap(&b);
|
||||
}
|
||||
inline void Swap(Any* other) {
|
||||
if (other == this) return;
|
||||
#ifdef PROTOBUF_FORCE_COPY_IN_SWAP
|
||||
if (GetOwningArena() != nullptr &&
|
||||
GetOwningArena() == other->GetOwningArena()) {
|
||||
#else // PROTOBUF_FORCE_COPY_IN_SWAP
|
||||
if (GetOwningArena() == other->GetOwningArena()) {
|
||||
#endif // !PROTOBUF_FORCE_COPY_IN_SWAP
|
||||
InternalSwap(other);
|
||||
} else {
|
||||
::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
|
||||
}
|
||||
}
|
||||
void UnsafeArenaSwap(Any* other) {
|
||||
if (other == this) return;
|
||||
GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
|
||||
InternalSwap(other);
|
||||
}
|
||||
|
||||
// implements Message ----------------------------------------------
|
||||
|
||||
Any* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final {
|
||||
return CreateMaybeMessage<Any>(arena);
|
||||
}
|
||||
using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
|
||||
void CopyFrom(const Any& from);
|
||||
using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
|
||||
void MergeFrom( const Any& from) {
|
||||
Any::MergeImpl(*this, from);
|
||||
}
|
||||
private:
|
||||
static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg);
|
||||
public:
|
||||
PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
|
||||
bool IsInitialized() const final;
|
||||
|
||||
size_t ByteSizeLong() const final;
|
||||
const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
|
||||
uint8_t* _InternalSerialize(
|
||||
uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
|
||||
int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
|
||||
|
||||
private:
|
||||
void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned);
|
||||
void SharedDtor();
|
||||
void SetCachedSize(int size) const final;
|
||||
void InternalSwap(Any* other);
|
||||
|
||||
private:
|
||||
friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
|
||||
static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
|
||||
return "google.protobuf.Any";
|
||||
}
|
||||
protected:
|
||||
explicit Any(::PROTOBUF_NAMESPACE_ID::Arena* arena,
|
||||
bool is_message_owned = false);
|
||||
public:
|
||||
|
||||
static const ClassData _class_data_;
|
||||
const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
|
||||
|
||||
::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
|
||||
|
||||
// nested types ----------------------------------------------------
|
||||
|
||||
// accessors -------------------------------------------------------
|
||||
|
||||
enum : int {
|
||||
kTypeUrlFieldNumber = 1,
|
||||
kValueFieldNumber = 2,
|
||||
};
|
||||
// string type_url = 1;
|
||||
void clear_type_url();
|
||||
const std::string& type_url() const;
|
||||
template <typename ArgT0 = const std::string&, typename... ArgT>
|
||||
void set_type_url(ArgT0&& arg0, ArgT... args);
|
||||
std::string* mutable_type_url();
|
||||
PROTOBUF_NODISCARD std::string* release_type_url();
|
||||
void set_allocated_type_url(std::string* type_url);
|
||||
private:
|
||||
const std::string& _internal_type_url() const;
|
||||
inline PROTOBUF_ALWAYS_INLINE void _internal_set_type_url(const std::string& value);
|
||||
std::string* _internal_mutable_type_url();
|
||||
public:
|
||||
|
||||
// bytes value = 2;
|
||||
void clear_value();
|
||||
const std::string& value() const;
|
||||
template <typename ArgT0 = const std::string&, typename... ArgT>
|
||||
void set_value(ArgT0&& arg0, ArgT... args);
|
||||
std::string* mutable_value();
|
||||
PROTOBUF_NODISCARD std::string* release_value();
|
||||
void set_allocated_value(std::string* value);
|
||||
private:
|
||||
const std::string& _internal_value() const;
|
||||
inline PROTOBUF_ALWAYS_INLINE void _internal_set_value(const std::string& value);
|
||||
std::string* _internal_mutable_value();
|
||||
public:
|
||||
|
||||
// @@protoc_insertion_point(class_scope:google.protobuf.Any)
|
||||
private:
|
||||
class _Internal;
|
||||
|
||||
template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper;
|
||||
typedef void InternalArenaConstructable_;
|
||||
typedef void DestructorSkippable_;
|
||||
struct Impl_ {
|
||||
::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr type_url_;
|
||||
::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr value_;
|
||||
mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
|
||||
::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata _any_metadata_;
|
||||
};
|
||||
union { Impl_ _impl_; };
|
||||
friend struct ::TableStruct_google_2fprotobuf_2fany_2eproto;
|
||||
};
|
||||
// ===================================================================
|
||||
|
||||
|
||||
// ===================================================================
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
|
||||
#endif // __GNUC__
|
||||
// Any
|
||||
|
||||
// string type_url = 1;
|
||||
inline void Any::clear_type_url() {
|
||||
_impl_.type_url_.ClearToEmpty();
|
||||
}
|
||||
inline const std::string& Any::type_url() const {
|
||||
// @@protoc_insertion_point(field_get:google.protobuf.Any.type_url)
|
||||
return _internal_type_url();
|
||||
}
|
||||
template <typename ArgT0, typename... ArgT>
|
||||
inline PROTOBUF_ALWAYS_INLINE
|
||||
void Any::set_type_url(ArgT0&& arg0, ArgT... args) {
|
||||
|
||||
_impl_.type_url_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
|
||||
// @@protoc_insertion_point(field_set:google.protobuf.Any.type_url)
|
||||
}
|
||||
inline std::string* Any::mutable_type_url() {
|
||||
std::string* _s = _internal_mutable_type_url();
|
||||
// @@protoc_insertion_point(field_mutable:google.protobuf.Any.type_url)
|
||||
return _s;
|
||||
}
|
||||
inline const std::string& Any::_internal_type_url() const {
|
||||
return _impl_.type_url_.Get();
|
||||
}
|
||||
inline void Any::_internal_set_type_url(const std::string& value) {
|
||||
|
||||
_impl_.type_url_.Set(value, GetArenaForAllocation());
|
||||
}
|
||||
inline std::string* Any::_internal_mutable_type_url() {
|
||||
|
||||
return _impl_.type_url_.Mutable(GetArenaForAllocation());
|
||||
}
|
||||
inline std::string* Any::release_type_url() {
|
||||
// @@protoc_insertion_point(field_release:google.protobuf.Any.type_url)
|
||||
return _impl_.type_url_.Release();
|
||||
}
|
||||
inline void Any::set_allocated_type_url(std::string* type_url) {
|
||||
if (type_url != nullptr) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
_impl_.type_url_.SetAllocated(type_url, GetArenaForAllocation());
|
||||
#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
|
||||
if (_impl_.type_url_.IsDefault()) {
|
||||
_impl_.type_url_.Set("", GetArenaForAllocation());
|
||||
}
|
||||
#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
|
||||
// @@protoc_insertion_point(field_set_allocated:google.protobuf.Any.type_url)
|
||||
}
|
||||
|
||||
// bytes value = 2;
|
||||
inline void Any::clear_value() {
|
||||
_impl_.value_.ClearToEmpty();
|
||||
}
|
||||
inline const std::string& Any::value() const {
|
||||
// @@protoc_insertion_point(field_get:google.protobuf.Any.value)
|
||||
return _internal_value();
|
||||
}
|
||||
template <typename ArgT0, typename... ArgT>
|
||||
inline PROTOBUF_ALWAYS_INLINE
|
||||
void Any::set_value(ArgT0&& arg0, ArgT... args) {
|
||||
|
||||
_impl_.value_.SetBytes(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
|
||||
// @@protoc_insertion_point(field_set:google.protobuf.Any.value)
|
||||
}
|
||||
inline std::string* Any::mutable_value() {
|
||||
std::string* _s = _internal_mutable_value();
|
||||
// @@protoc_insertion_point(field_mutable:google.protobuf.Any.value)
|
||||
return _s;
|
||||
}
|
||||
inline const std::string& Any::_internal_value() const {
|
||||
return _impl_.value_.Get();
|
||||
}
|
||||
inline void Any::_internal_set_value(const std::string& value) {
|
||||
|
||||
_impl_.value_.Set(value, GetArenaForAllocation());
|
||||
}
|
||||
inline std::string* Any::_internal_mutable_value() {
|
||||
|
||||
return _impl_.value_.Mutable(GetArenaForAllocation());
|
||||
}
|
||||
inline std::string* Any::release_value() {
|
||||
// @@protoc_insertion_point(field_release:google.protobuf.Any.value)
|
||||
return _impl_.value_.Release();
|
||||
}
|
||||
inline void Any::set_allocated_value(std::string* value) {
|
||||
if (value != nullptr) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
_impl_.value_.SetAllocated(value, GetArenaForAllocation());
|
||||
#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
|
||||
if (_impl_.value_.IsDefault()) {
|
||||
_impl_.value_.Set("", GetArenaForAllocation());
|
||||
}
|
||||
#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
|
||||
// @@protoc_insertion_point(field_set_allocated:google.protobuf.Any.value)
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif // __GNUC__
|
||||
|
||||
// @@protoc_insertion_point(namespace_scope)
|
||||
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
|
||||
// @@protoc_insertion_point(global_scope)
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
#endif // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fany_2eproto
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,851 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// This file defines an Arena allocator for better allocation performance.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_ARENA_H__
|
||||
#define GOOGLE_PROTOBUF_ARENA_H__
|
||||
|
||||
|
||||
#include <limits>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#if defined(_MSC_VER) && !defined(_LIBCPP_STD_VER) && !_HAS_EXCEPTIONS
|
||||
// Work around bugs in MSVC <typeinfo> header when _HAS_EXCEPTIONS=0.
|
||||
#include <exception>
|
||||
#include <typeinfo>
|
||||
namespace std {
|
||||
using type_info = ::type_info;
|
||||
}
|
||||
#else
|
||||
#include <typeinfo>
|
||||
#endif
|
||||
|
||||
#include <type_traits>
|
||||
#include <google/protobuf/arena_impl.h>
|
||||
#include <google/protobuf/port.h>
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
#ifdef SWIG
|
||||
#error "You cannot SWIG proto headers"
|
||||
#endif
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
struct ArenaOptions; // defined below
|
||||
class Arena; // defined below
|
||||
class Message; // defined in message.h
|
||||
class MessageLite;
|
||||
template <typename Key, typename T>
|
||||
class Map;
|
||||
|
||||
namespace arena_metrics {
|
||||
|
||||
void EnableArenaMetrics(ArenaOptions* options);
|
||||
|
||||
} // namespace arena_metrics
|
||||
|
||||
namespace TestUtil {
|
||||
class ReflectionTester; // defined in test_util.h
|
||||
} // namespace TestUtil
|
||||
|
||||
namespace internal {
|
||||
|
||||
struct ArenaTestPeer; // defined in arena_test_util.h
|
||||
class InternalMetadata; // defined in metadata_lite.h
|
||||
class LazyField; // defined in lazy_field.h
|
||||
class EpsCopyInputStream; // defined in parse_context.h
|
||||
class RepeatedPtrFieldBase; // defined in repeated_ptr_field.h
|
||||
|
||||
template <typename Type>
|
||||
class GenericTypeHandler; // defined in repeated_field.h
|
||||
|
||||
inline PROTOBUF_ALWAYS_INLINE
|
||||
void* AlignTo(void* ptr, size_t align) {
|
||||
return reinterpret_cast<void*>(
|
||||
(reinterpret_cast<uintptr_t>(ptr) + align - 1) & (~align + 1));
|
||||
}
|
||||
|
||||
// Templated cleanup methods.
|
||||
template <typename T>
|
||||
void arena_destruct_object(void* object) {
|
||||
reinterpret_cast<T*>(object)->~T();
|
||||
}
|
||||
|
||||
template <bool destructor_skippable, typename T>
|
||||
struct ObjectDestructor {
|
||||
constexpr static void (*destructor)(void*) = &arena_destruct_object<T>;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct ObjectDestructor<true, T> {
|
||||
constexpr static void (*destructor)(void*) = nullptr;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
void arena_delete_object(void* object) {
|
||||
delete reinterpret_cast<T*>(object);
|
||||
}
|
||||
} // namespace internal
|
||||
|
||||
// ArenaOptions provides optional additional parameters to arena construction
|
||||
// that control its block-allocation behavior.
|
||||
struct ArenaOptions {
|
||||
// This defines the size of the first block requested from the system malloc.
|
||||
// Subsequent block sizes will increase in a geometric series up to a maximum.
|
||||
size_t start_block_size;
|
||||
|
||||
// This defines the maximum block size requested from system malloc (unless an
|
||||
// individual arena allocation request occurs with a size larger than this
|
||||
// maximum). Requested block sizes increase up to this value, then remain
|
||||
// here.
|
||||
size_t max_block_size;
|
||||
|
||||
// An initial block of memory for the arena to use, or NULL for none. If
|
||||
// provided, the block must live at least as long as the arena itself. The
|
||||
// creator of the Arena retains ownership of the block after the Arena is
|
||||
// destroyed.
|
||||
char* initial_block;
|
||||
|
||||
// The size of the initial block, if provided.
|
||||
size_t initial_block_size;
|
||||
|
||||
// A function pointer to an alloc method that returns memory blocks of size
|
||||
// requested. By default, it contains a ptr to the malloc function.
|
||||
//
|
||||
// NOTE: block_alloc and dealloc functions are expected to behave like
|
||||
// malloc and free, including Asan poisoning.
|
||||
void* (*block_alloc)(size_t);
|
||||
// A function pointer to a dealloc method that takes ownership of the blocks
|
||||
// from the arena. By default, it contains a ptr to a wrapper function that
|
||||
// calls free.
|
||||
void (*block_dealloc)(void*, size_t);
|
||||
|
||||
ArenaOptions()
|
||||
: start_block_size(internal::AllocationPolicy::kDefaultStartBlockSize),
|
||||
max_block_size(internal::AllocationPolicy::kDefaultMaxBlockSize),
|
||||
initial_block(NULL),
|
||||
initial_block_size(0),
|
||||
block_alloc(nullptr),
|
||||
block_dealloc(nullptr),
|
||||
make_metrics_collector(nullptr) {}
|
||||
|
||||
private:
|
||||
// If make_metrics_collector is not nullptr, it will be called at Arena init
|
||||
// time. It may return a pointer to a collector instance that will be notified
|
||||
// of interesting events related to the arena.
|
||||
internal::ArenaMetricsCollector* (*make_metrics_collector)();
|
||||
|
||||
internal::ArenaMetricsCollector* MetricsCollector() const {
|
||||
return make_metrics_collector ? (*make_metrics_collector)() : nullptr;
|
||||
}
|
||||
|
||||
internal::AllocationPolicy AllocationPolicy() const {
|
||||
internal::AllocationPolicy res;
|
||||
res.start_block_size = start_block_size;
|
||||
res.max_block_size = max_block_size;
|
||||
res.block_alloc = block_alloc;
|
||||
res.block_dealloc = block_dealloc;
|
||||
res.metrics_collector = MetricsCollector();
|
||||
return res;
|
||||
}
|
||||
|
||||
friend void arena_metrics::EnableArenaMetrics(ArenaOptions*);
|
||||
|
||||
friend class Arena;
|
||||
friend class ArenaOptionsTestFriend;
|
||||
};
|
||||
|
||||
// Support for non-RTTI environments. (The metrics hooks API uses type
|
||||
// information.)
|
||||
#if PROTOBUF_RTTI
|
||||
#define RTTI_TYPE_ID(type) (&typeid(type))
|
||||
#else
|
||||
#define RTTI_TYPE_ID(type) (NULL)
|
||||
#endif
|
||||
|
||||
// Arena allocator. Arena allocation replaces ordinary (heap-based) allocation
|
||||
// with new/delete, and improves performance by aggregating allocations into
|
||||
// larger blocks and freeing allocations all at once. Protocol messages are
|
||||
// allocated on an arena by using Arena::CreateMessage<T>(Arena*), below, and
|
||||
// are automatically freed when the arena is destroyed.
|
||||
//
|
||||
// This is a thread-safe implementation: multiple threads may allocate from the
|
||||
// arena concurrently. Destruction is not thread-safe and the destructing
|
||||
// thread must synchronize with users of the arena first.
|
||||
//
|
||||
// An arena provides two allocation interfaces: CreateMessage<T>, which works
|
||||
// for arena-enabled proto2 message types as well as other types that satisfy
|
||||
// the appropriate protocol (described below), and Create<T>, which works for
|
||||
// any arbitrary type T. CreateMessage<T> is better when the type T supports it,
|
||||
// because this interface (i) passes the arena pointer to the created object so
|
||||
// that its sub-objects and internal allocations can use the arena too, and (ii)
|
||||
// elides the object's destructor call when possible. Create<T> does not place
|
||||
// any special requirements on the type T, and will invoke the object's
|
||||
// destructor when the arena is destroyed.
|
||||
//
|
||||
// The arena message allocation protocol, required by
|
||||
// CreateMessage<T>(Arena* arena, Args&&... args), is as follows:
|
||||
//
|
||||
// - The type T must have (at least) two constructors: a constructor callable
|
||||
// with `args` (without `arena`), called when a T is allocated on the heap;
|
||||
// and a constructor callable with `Arena* arena, Args&&... args`, called when
|
||||
// a T is allocated on an arena. If the second constructor is called with a
|
||||
// NULL arena pointer, it must be equivalent to invoking the first
|
||||
// (`args`-only) constructor.
|
||||
//
|
||||
// - The type T must have a particular type trait: a nested type
|
||||
// |InternalArenaConstructable_|. This is usually a typedef to |void|. If no
|
||||
// such type trait exists, then the instantiation CreateMessage<T> will fail
|
||||
// to compile.
|
||||
//
|
||||
// - The type T *may* have the type trait |DestructorSkippable_|. If this type
|
||||
// trait is present in the type, then its destructor will not be called if and
|
||||
// only if it was passed a non-NULL arena pointer. If this type trait is not
|
||||
// present on the type, then its destructor is always called when the
|
||||
// containing arena is destroyed.
|
||||
//
|
||||
// This protocol is implemented by all arena-enabled proto2 message classes as
|
||||
// well as protobuf container types like RepeatedPtrField and Map. The protocol
|
||||
// is internal to protobuf and is not guaranteed to be stable. Non-proto types
|
||||
// should not rely on this protocol.
|
||||
class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8) Arena final {
|
||||
public:
|
||||
// Default constructor with sensible default options, tuned for average
|
||||
// use-cases.
|
||||
inline Arena() : impl_() {}
|
||||
|
||||
// Construct an arena with default options, except for the supplied
|
||||
// initial block. It is more efficient to use this constructor
|
||||
// instead of passing ArenaOptions if the only configuration needed
|
||||
// by the caller is supplying an initial block.
|
||||
inline Arena(char* initial_block, size_t initial_block_size)
|
||||
: impl_(initial_block, initial_block_size) {}
|
||||
|
||||
// Arena constructor taking custom options. See ArenaOptions above for
|
||||
// descriptions of the options available.
|
||||
explicit Arena(const ArenaOptions& options)
|
||||
: impl_(options.initial_block, options.initial_block_size,
|
||||
options.AllocationPolicy()) {}
|
||||
|
||||
// Block overhead. Use this as a guide for how much to over-allocate the
|
||||
// initial block if you want an allocation of size N to fit inside it.
|
||||
//
|
||||
// WARNING: if you allocate multiple objects, it is difficult to guarantee
|
||||
// that a series of allocations will fit in the initial block, especially if
|
||||
// Arena changes its alignment guarantees in the future!
|
||||
static const size_t kBlockOverhead =
|
||||
internal::ThreadSafeArena::kBlockHeaderSize +
|
||||
internal::ThreadSafeArena::kSerialArenaSize;
|
||||
|
||||
inline ~Arena() {}
|
||||
|
||||
// TODO(protobuf-team): Fix callers to use constructor and delete this method.
|
||||
void Init(const ArenaOptions&) {}
|
||||
|
||||
// API to create proto2 message objects on the arena. If the arena passed in
|
||||
// is NULL, then a heap allocated object is returned. Type T must be a message
|
||||
// defined in a .proto file with cc_enable_arenas set to true, otherwise a
|
||||
// compilation error will occur.
|
||||
//
|
||||
// RepeatedField and RepeatedPtrField may also be instantiated directly on an
|
||||
// arena with this method.
|
||||
//
|
||||
// This function also accepts any type T that satisfies the arena message
|
||||
// allocation protocol, documented above.
|
||||
template <typename T, typename... Args>
|
||||
PROTOBUF_ALWAYS_INLINE static T* CreateMessage(Arena* arena, Args&&... args) {
|
||||
static_assert(
|
||||
InternalHelper<T>::is_arena_constructable::value,
|
||||
"CreateMessage can only construct types that are ArenaConstructable");
|
||||
// We must delegate to CreateMaybeMessage() and NOT CreateMessageInternal()
|
||||
// because protobuf generated classes specialize CreateMaybeMessage() and we
|
||||
// need to use that specialization for code size reasons.
|
||||
return Arena::CreateMaybeMessage<T>(arena, static_cast<Args&&>(args)...);
|
||||
}
|
||||
|
||||
// API to create any objects on the arena. Note that only the object will
|
||||
// be created on the arena; the underlying ptrs (in case of a proto2 message)
|
||||
// will be still heap allocated. Proto messages should usually be allocated
|
||||
// with CreateMessage<T>() instead.
|
||||
//
|
||||
// Note that even if T satisfies the arena message construction protocol
|
||||
// (InternalArenaConstructable_ trait and optional DestructorSkippable_
|
||||
// trait), as described above, this function does not follow the protocol;
|
||||
// instead, it treats T as a black-box type, just as if it did not have these
|
||||
// traits. Specifically, T's constructor arguments will always be only those
|
||||
// passed to Create<T>() -- no additional arena pointer is implicitly added.
|
||||
// Furthermore, the destructor will always be called at arena destruction time
|
||||
// (unless the destructor is trivial). Hence, from T's point of view, it is as
|
||||
// if the object were allocated on the heap (except that the underlying memory
|
||||
// is obtained from the arena).
|
||||
template <typename T, typename... Args>
|
||||
PROTOBUF_NDEBUG_INLINE static T* Create(Arena* arena, Args&&... args) {
|
||||
return CreateInternal<T>(arena, std::is_convertible<T*, MessageLite*>(),
|
||||
static_cast<Args&&>(args)...);
|
||||
}
|
||||
|
||||
// Allocates memory with the specific size and alignment.
|
||||
void* AllocateAligned(size_t size, size_t align = 8) {
|
||||
if (align <= 8) {
|
||||
return AllocateAlignedNoHook(internal::AlignUpTo8(size));
|
||||
} else {
|
||||
// We are wasting space by over allocating align - 8 bytes. Compared
|
||||
// to a dedicated function that takes current alignment in consideration.
|
||||
// Such a scheme would only waste (align - 8)/2 bytes on average, but
|
||||
// requires a dedicated function in the outline arena allocation
|
||||
// functions. Possibly re-evaluate tradeoffs later.
|
||||
return internal::AlignTo(AllocateAlignedNoHook(size + align - 8), align);
|
||||
}
|
||||
}
|
||||
|
||||
// Create an array of object type T on the arena *without* invoking the
|
||||
// constructor of T. If `arena` is null, then the return value should be freed
|
||||
// with `delete[] x;` (or `::operator delete[](x);`).
|
||||
// To ensure safe uses, this function checks at compile time
|
||||
// (when compiled as C++11) that T is trivially default-constructible and
|
||||
// trivially destructible.
|
||||
template <typename T>
|
||||
PROTOBUF_NDEBUG_INLINE static T* CreateArray(Arena* arena,
|
||||
size_t num_elements) {
|
||||
static_assert(std::is_trivial<T>::value,
|
||||
"CreateArray requires a trivially constructible type");
|
||||
static_assert(std::is_trivially_destructible<T>::value,
|
||||
"CreateArray requires a trivially destructible type");
|
||||
GOOGLE_CHECK_LE(num_elements, std::numeric_limits<size_t>::max() / sizeof(T))
|
||||
<< "Requested size is too large to fit into size_t.";
|
||||
if (arena == NULL) {
|
||||
return static_cast<T*>(::operator new[](num_elements * sizeof(T)));
|
||||
} else {
|
||||
return arena->CreateInternalRawArray<T>(num_elements);
|
||||
}
|
||||
}
|
||||
|
||||
// The following are routines are for monitoring. They will approximate the
|
||||
// total sum allocated and used memory, but the exact value is an
|
||||
// implementation deal. For instance allocated space depends on growth
|
||||
// policies. Do not use these in unit tests.
|
||||
// Returns the total space allocated by the arena, which is the sum of the
|
||||
// sizes of the underlying blocks.
|
||||
uint64_t SpaceAllocated() const { return impl_.SpaceAllocated(); }
|
||||
// Returns the total space used by the arena. Similar to SpaceAllocated but
|
||||
// does not include free space and block overhead. The total space returned
|
||||
// may not include space used by other threads executing concurrently with
|
||||
// the call to this method.
|
||||
uint64_t SpaceUsed() const { return impl_.SpaceUsed(); }
|
||||
|
||||
// Frees all storage allocated by this arena after calling destructors
|
||||
// registered with OwnDestructor() and freeing objects registered with Own().
|
||||
// Any objects allocated on this arena are unusable after this call. It also
|
||||
// returns the total space used by the arena which is the sums of the sizes
|
||||
// of the allocated blocks. This method is not thread-safe.
|
||||
uint64_t Reset() { return impl_.Reset(); }
|
||||
|
||||
// Adds |object| to a list of heap-allocated objects to be freed with |delete|
|
||||
// when the arena is destroyed or reset.
|
||||
template <typename T>
|
||||
PROTOBUF_ALWAYS_INLINE void Own(T* object) {
|
||||
OwnInternal(object, std::is_convertible<T*, MessageLite*>());
|
||||
}
|
||||
|
||||
// Adds |object| to a list of objects whose destructors will be manually
|
||||
// called when the arena is destroyed or reset. This differs from Own() in
|
||||
// that it does not free the underlying memory with |delete|; hence, it is
|
||||
// normally only used for objects that are placement-newed into
|
||||
// arena-allocated memory.
|
||||
template <typename T>
|
||||
PROTOBUF_ALWAYS_INLINE void OwnDestructor(T* object) {
|
||||
if (object != NULL) {
|
||||
impl_.AddCleanup(object, &internal::arena_destruct_object<T>);
|
||||
}
|
||||
}
|
||||
|
||||
// Adds a custom member function on an object to the list of destructors that
|
||||
// will be manually called when the arena is destroyed or reset. This differs
|
||||
// from OwnDestructor() in that any member function may be specified, not only
|
||||
// the class destructor.
|
||||
PROTOBUF_ALWAYS_INLINE void OwnCustomDestructor(void* object,
|
||||
void (*destruct)(void*)) {
|
||||
impl_.AddCleanup(object, destruct);
|
||||
}
|
||||
|
||||
// Retrieves the arena associated with |value| if |value| is an arena-capable
|
||||
// message, or NULL otherwise. If possible, the call resolves at compile time.
|
||||
// Note that we can often devirtualize calls to `value->GetArena()` so usually
|
||||
// calling this method is unnecessary.
|
||||
template <typename T>
|
||||
PROTOBUF_ALWAYS_INLINE static Arena* GetArena(const T* value) {
|
||||
return GetArenaInternal(value);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
class InternalHelper {
|
||||
private:
|
||||
// Provides access to protected GetOwningArena to generated messages.
|
||||
static Arena* GetOwningArena(const T* p) { return p->GetOwningArena(); }
|
||||
|
||||
static void InternalSwap(T* a, T* b) { a->InternalSwap(b); }
|
||||
|
||||
static Arena* GetArenaForAllocationInternal(
|
||||
const T* p, std::true_type /*is_derived_from<MessageLite>*/) {
|
||||
return p->GetArenaForAllocation();
|
||||
}
|
||||
|
||||
static Arena* GetArenaForAllocationInternal(
|
||||
const T* p, std::false_type /*is_derived_from<MessageLite>*/) {
|
||||
return GetArenaForAllocationForNonMessage(
|
||||
p, typename is_arena_constructable::type());
|
||||
}
|
||||
|
||||
static Arena* GetArenaForAllocationForNonMessage(
|
||||
const T* p, std::true_type /*is_arena_constructible*/) {
|
||||
return p->GetArena();
|
||||
}
|
||||
|
||||
static Arena* GetArenaForAllocationForNonMessage(
|
||||
const T* p, std::false_type /*is_arena_constructible*/) {
|
||||
return GetArenaForAllocationForNonMessageNonArenaConstructible(
|
||||
p, typename has_get_arena::type());
|
||||
}
|
||||
|
||||
static Arena* GetArenaForAllocationForNonMessageNonArenaConstructible(
|
||||
const T* p, std::true_type /*has_get_arena*/) {
|
||||
return p->GetArena();
|
||||
}
|
||||
|
||||
static Arena* GetArenaForAllocationForNonMessageNonArenaConstructible(
|
||||
const T* /* p */, std::false_type /*has_get_arena*/) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
static char DestructorSkippable(const typename U::DestructorSkippable_*);
|
||||
template <typename U>
|
||||
static double DestructorSkippable(...);
|
||||
|
||||
typedef std::integral_constant<
|
||||
bool, sizeof(DestructorSkippable<T>(static_cast<const T*>(0))) ==
|
||||
sizeof(char) ||
|
||||
std::is_trivially_destructible<T>::value>
|
||||
is_destructor_skippable;
|
||||
|
||||
template <typename U>
|
||||
static char ArenaConstructable(
|
||||
const typename U::InternalArenaConstructable_*);
|
||||
template <typename U>
|
||||
static double ArenaConstructable(...);
|
||||
|
||||
typedef std::integral_constant<bool, sizeof(ArenaConstructable<T>(
|
||||
static_cast<const T*>(0))) ==
|
||||
sizeof(char)>
|
||||
is_arena_constructable;
|
||||
|
||||
template <typename U,
|
||||
typename std::enable_if<
|
||||
std::is_same<Arena*, decltype(std::declval<const U>()
|
||||
.GetArena())>::value,
|
||||
int>::type = 0>
|
||||
static char HasGetArena(decltype(&U::GetArena));
|
||||
template <typename U>
|
||||
static double HasGetArena(...);
|
||||
|
||||
typedef std::integral_constant<bool, sizeof(HasGetArena<T>(nullptr)) ==
|
||||
sizeof(char)>
|
||||
has_get_arena;
|
||||
|
||||
template <typename... Args>
|
||||
static T* Construct(void* ptr, Args&&... args) {
|
||||
return new (ptr) T(static_cast<Args&&>(args)...);
|
||||
}
|
||||
|
||||
static inline PROTOBUF_ALWAYS_INLINE T* New() {
|
||||
return new T(nullptr);
|
||||
}
|
||||
|
||||
static Arena* GetArena(const T* p) { return p->GetArena(); }
|
||||
|
||||
friend class Arena;
|
||||
friend class TestUtil::ReflectionTester;
|
||||
};
|
||||
|
||||
// Provides access to protected GetOwningArena to generated messages. For
|
||||
// internal use only.
|
||||
template <typename T>
|
||||
static Arena* InternalGetOwningArena(const T* p) {
|
||||
return InternalHelper<T>::GetOwningArena(p);
|
||||
}
|
||||
|
||||
// Provides access to protected GetArenaForAllocation to generated messages.
|
||||
// For internal use only.
|
||||
template <typename T>
|
||||
static Arena* InternalGetArenaForAllocation(const T* p) {
|
||||
return InternalHelper<T>::GetArenaForAllocationInternal(
|
||||
p, std::is_convertible<T*, MessageLite*>());
|
||||
}
|
||||
|
||||
// Creates message-owned arena. For internal use only.
|
||||
static Arena* InternalCreateMessageOwnedArena() {
|
||||
return new Arena(internal::MessageOwned{});
|
||||
}
|
||||
|
||||
// Checks whether this arena is message-owned. For internal use only.
|
||||
bool InternalIsMessageOwnedArena() { return IsMessageOwned(); }
|
||||
|
||||
// Helper typetraits that indicates support for arenas in a type T at compile
|
||||
// time. This is public only to allow construction of higher-level templated
|
||||
// utilities.
|
||||
//
|
||||
// is_arena_constructable<T>::value is true if the message type T has arena
|
||||
// support enabled, and false otherwise.
|
||||
//
|
||||
// is_destructor_skippable<T>::value is true if the message type T has told
|
||||
// the arena that it is safe to skip the destructor, and false otherwise.
|
||||
//
|
||||
// This is inside Arena because only Arena has the friend relationships
|
||||
// necessary to see the underlying generated code traits.
|
||||
template <typename T>
|
||||
struct is_arena_constructable : InternalHelper<T>::is_arena_constructable {};
|
||||
template <typename T>
|
||||
struct is_destructor_skippable : InternalHelper<T>::is_destructor_skippable {
|
||||
};
|
||||
|
||||
private:
|
||||
internal::ThreadSafeArena impl_;
|
||||
|
||||
template <typename T>
|
||||
struct has_get_arena : InternalHelper<T>::has_get_arena {};
|
||||
|
||||
// Constructor solely used by message-owned arena.
|
||||
inline Arena(internal::MessageOwned) : impl_(internal::MessageOwned{}) {}
|
||||
|
||||
// Checks whether this arena is message-owned.
|
||||
PROTOBUF_ALWAYS_INLINE bool IsMessageOwned() const {
|
||||
return impl_.IsMessageOwned();
|
||||
}
|
||||
|
||||
void ReturnArrayMemory(void* p, size_t size) {
|
||||
impl_.ReturnArrayMemory(p, size);
|
||||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
PROTOBUF_NDEBUG_INLINE static T* CreateMessageInternal(Arena* arena,
|
||||
Args&&... args) {
|
||||
static_assert(
|
||||
InternalHelper<T>::is_arena_constructable::value,
|
||||
"CreateMessage can only construct types that are ArenaConstructable");
|
||||
if (arena == NULL) {
|
||||
return new T(nullptr, static_cast<Args&&>(args)...);
|
||||
} else {
|
||||
return arena->DoCreateMessage<T>(static_cast<Args&&>(args)...);
|
||||
}
|
||||
}
|
||||
|
||||
// This specialization for no arguments is necessary, because its behavior is
|
||||
// slightly different. When the arena pointer is nullptr, it calls T()
|
||||
// instead of T(nullptr).
|
||||
template <typename T>
|
||||
PROTOBUF_NDEBUG_INLINE static T* CreateMessageInternal(Arena* arena) {
|
||||
static_assert(
|
||||
InternalHelper<T>::is_arena_constructable::value,
|
||||
"CreateMessage can only construct types that are ArenaConstructable");
|
||||
if (arena == NULL) {
|
||||
// Generated arena constructor T(Arena*) is protected. Call via
|
||||
// InternalHelper.
|
||||
return InternalHelper<T>::New();
|
||||
} else {
|
||||
return arena->DoCreateMessage<T>();
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate and also optionally call collector with the allocated type info
|
||||
// when allocation recording is enabled.
|
||||
PROTOBUF_NDEBUG_INLINE void* AllocateInternal(size_t size, size_t align,
|
||||
void (*destructor)(void*),
|
||||
const std::type_info* type) {
|
||||
// Monitor allocation if needed.
|
||||
if (destructor == nullptr) {
|
||||
return AllocateAlignedWithHook(size, align, type);
|
||||
} else {
|
||||
if (align <= 8) {
|
||||
auto res = AllocateAlignedWithCleanup(internal::AlignUpTo8(size), type);
|
||||
res.second->elem = res.first;
|
||||
res.second->cleanup = destructor;
|
||||
return res.first;
|
||||
} else {
|
||||
auto res = AllocateAlignedWithCleanup(size + align - 8, type);
|
||||
auto ptr = internal::AlignTo(res.first, align);
|
||||
res.second->elem = ptr;
|
||||
res.second->cleanup = destructor;
|
||||
return ptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// CreateMessage<T> requires that T supports arenas, but this private method
|
||||
// works whether or not T supports arenas. These are not exposed to user code
|
||||
// as it can cause confusing API usages, and end up having double free in
|
||||
// user code. These are used only internally from LazyField and Repeated
|
||||
// fields, since they are designed to work in all mode combinations.
|
||||
template <typename Msg, typename... Args>
|
||||
PROTOBUF_ALWAYS_INLINE static Msg* DoCreateMaybeMessage(Arena* arena,
|
||||
std::true_type,
|
||||
Args&&... args) {
|
||||
return CreateMessageInternal<Msg>(arena, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
PROTOBUF_ALWAYS_INLINE static T* DoCreateMaybeMessage(Arena* arena,
|
||||
std::false_type,
|
||||
Args&&... args) {
|
||||
return Create<T>(arena, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
PROTOBUF_ALWAYS_INLINE static T* CreateMaybeMessage(Arena* arena,
|
||||
Args&&... args) {
|
||||
return DoCreateMaybeMessage<T>(arena, is_arena_constructable<T>(),
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
// Just allocate the required size for the given type assuming the
|
||||
// type has a trivial constructor.
|
||||
template <typename T>
|
||||
PROTOBUF_NDEBUG_INLINE T* CreateInternalRawArray(size_t num_elements) {
|
||||
GOOGLE_CHECK_LE(num_elements, std::numeric_limits<size_t>::max() / sizeof(T))
|
||||
<< "Requested size is too large to fit into size_t.";
|
||||
// We count on compiler to realize that if sizeof(T) is a multiple of
|
||||
// 8 AlignUpTo can be elided.
|
||||
const size_t n = sizeof(T) * num_elements;
|
||||
return static_cast<T*>(
|
||||
AllocateAlignedWithHookForArray(n, alignof(T), RTTI_TYPE_ID(T)));
|
||||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
PROTOBUF_NDEBUG_INLINE T* DoCreateMessage(Args&&... args) {
|
||||
return InternalHelper<T>::Construct(
|
||||
AllocateInternal(sizeof(T), alignof(T),
|
||||
internal::ObjectDestructor<
|
||||
InternalHelper<T>::is_destructor_skippable::value,
|
||||
T>::destructor,
|
||||
RTTI_TYPE_ID(T)),
|
||||
this, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
// CreateInArenaStorage is used to implement map field. Without it,
|
||||
// Map need to call generated message's protected arena constructor,
|
||||
// which needs to declare Map as friend of generated message.
|
||||
template <typename T, typename... Args>
|
||||
static void CreateInArenaStorage(T* ptr, Arena* arena, Args&&... args) {
|
||||
CreateInArenaStorageInternal(ptr, arena,
|
||||
typename is_arena_constructable<T>::type(),
|
||||
std::forward<Args>(args)...);
|
||||
if (arena != nullptr) {
|
||||
RegisterDestructorInternal(
|
||||
ptr, arena,
|
||||
typename InternalHelper<T>::is_destructor_skippable::type());
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
static void CreateInArenaStorageInternal(T* ptr, Arena* arena,
|
||||
std::true_type, Args&&... args) {
|
||||
InternalHelper<T>::Construct(ptr, arena, std::forward<Args>(args)...);
|
||||
}
|
||||
template <typename T, typename... Args>
|
||||
static void CreateInArenaStorageInternal(T* ptr, Arena* /* arena */,
|
||||
std::false_type, Args&&... args) {
|
||||
new (ptr) T(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static void RegisterDestructorInternal(T* /* ptr */, Arena* /* arena */,
|
||||
std::true_type) {}
|
||||
template <typename T>
|
||||
static void RegisterDestructorInternal(T* ptr, Arena* arena,
|
||||
std::false_type) {
|
||||
arena->OwnDestructor(ptr);
|
||||
}
|
||||
|
||||
// These implement Create(). The second parameter has type 'true_type' if T is
|
||||
// a subtype of Message and 'false_type' otherwise.
|
||||
template <typename T, typename... Args>
|
||||
PROTOBUF_ALWAYS_INLINE static T* CreateInternal(Arena* arena, std::true_type,
|
||||
Args&&... args) {
|
||||
if (arena == nullptr) {
|
||||
return new T(std::forward<Args>(args)...);
|
||||
} else {
|
||||
auto destructor =
|
||||
internal::ObjectDestructor<std::is_trivially_destructible<T>::value,
|
||||
T>::destructor;
|
||||
T* result =
|
||||
new (arena->AllocateInternal(sizeof(T), alignof(T), destructor,
|
||||
RTTI_TYPE_ID(T)))
|
||||
T(std::forward<Args>(args)...);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
template <typename T, typename... Args>
|
||||
PROTOBUF_ALWAYS_INLINE static T* CreateInternal(Arena* arena, std::false_type,
|
||||
Args&&... args) {
|
||||
if (arena == nullptr) {
|
||||
return new T(std::forward<Args>(args)...);
|
||||
} else {
|
||||
auto destructor =
|
||||
internal::ObjectDestructor<std::is_trivially_destructible<T>::value,
|
||||
T>::destructor;
|
||||
return new (arena->AllocateInternal(sizeof(T), alignof(T), destructor,
|
||||
RTTI_TYPE_ID(T)))
|
||||
T(std::forward<Args>(args)...);
|
||||
}
|
||||
}
|
||||
|
||||
// These implement Own(), which registers an object for deletion (destructor
|
||||
// call and operator delete()). The second parameter has type 'true_type' if T
|
||||
// is a subtype of Message and 'false_type' otherwise. Collapsing
|
||||
// all template instantiations to one for generic Message reduces code size,
|
||||
// using the virtual destructor instead.
|
||||
template <typename T>
|
||||
PROTOBUF_ALWAYS_INLINE void OwnInternal(T* object, std::true_type) {
|
||||
if (object != NULL) {
|
||||
impl_.AddCleanup(object, &internal::arena_delete_object<MessageLite>);
|
||||
}
|
||||
}
|
||||
template <typename T>
|
||||
PROTOBUF_ALWAYS_INLINE void OwnInternal(T* object, std::false_type) {
|
||||
if (object != NULL) {
|
||||
impl_.AddCleanup(object, &internal::arena_delete_object<T>);
|
||||
}
|
||||
}
|
||||
|
||||
// Implementation for GetArena(). Only message objects with
|
||||
// InternalArenaConstructable_ tags can be associated with an arena, and such
|
||||
// objects must implement a GetArena() method.
|
||||
template <typename T, typename std::enable_if<
|
||||
is_arena_constructable<T>::value, int>::type = 0>
|
||||
PROTOBUF_ALWAYS_INLINE static Arena* GetArenaInternal(const T* value) {
|
||||
return InternalHelper<T>::GetArena(value);
|
||||
}
|
||||
template <typename T,
|
||||
typename std::enable_if<!is_arena_constructable<T>::value &&
|
||||
has_get_arena<T>::value,
|
||||
int>::type = 0>
|
||||
PROTOBUF_ALWAYS_INLINE static Arena* GetArenaInternal(const T* value) {
|
||||
return value->GetArena();
|
||||
}
|
||||
template <typename T,
|
||||
typename std::enable_if<!is_arena_constructable<T>::value &&
|
||||
!has_get_arena<T>::value,
|
||||
int>::type = 0>
|
||||
PROTOBUF_ALWAYS_INLINE static Arena* GetArenaInternal(const T* value) {
|
||||
(void)value;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
PROTOBUF_ALWAYS_INLINE static Arena* GetOwningArena(const T* value) {
|
||||
return GetOwningArenaInternal(
|
||||
value, std::is_convertible<T*, MessageLite*>());
|
||||
}
|
||||
|
||||
// Implementation for GetOwningArena(). All and only message objects have
|
||||
// GetOwningArena() method.
|
||||
template <typename T>
|
||||
PROTOBUF_ALWAYS_INLINE static Arena* GetOwningArenaInternal(
|
||||
const T* value, std::true_type) {
|
||||
return InternalHelper<T>::GetOwningArena(value);
|
||||
}
|
||||
template <typename T>
|
||||
PROTOBUF_ALWAYS_INLINE static Arena* GetOwningArenaInternal(
|
||||
const T* /* value */, std::false_type) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void* AllocateAlignedWithHookForArray(size_t n, size_t align,
|
||||
const std::type_info* type) {
|
||||
if (align <= 8) {
|
||||
return AllocateAlignedWithHookForArray(internal::AlignUpTo8(n), type);
|
||||
} else {
|
||||
// We are wasting space by over allocating align - 8 bytes. Compared
|
||||
// to a dedicated function that takes current alignment in consideration.
|
||||
// Such a scheme would only waste (align - 8)/2 bytes on average, but
|
||||
// requires a dedicated function in the outline arena allocation
|
||||
// functions. Possibly re-evaluate tradeoffs later.
|
||||
return internal::AlignTo(
|
||||
AllocateAlignedWithHookForArray(n + align - 8, type), align);
|
||||
}
|
||||
}
|
||||
|
||||
void* AllocateAlignedWithHook(size_t n, size_t align,
|
||||
const std::type_info* type) {
|
||||
if (align <= 8) {
|
||||
return AllocateAlignedWithHook(internal::AlignUpTo8(n), type);
|
||||
} else {
|
||||
// We are wasting space by over allocating align - 8 bytes. Compared
|
||||
// to a dedicated function that takes current alignment in consideration.
|
||||
// Such a scheme would only waste (align - 8)/2 bytes on average, but
|
||||
// requires a dedicated function in the outline arena allocation
|
||||
// functions. Possibly re-evaluate tradeoffs later.
|
||||
return internal::AlignTo(AllocateAlignedWithHook(n + align - 8, type),
|
||||
align);
|
||||
}
|
||||
}
|
||||
|
||||
void* AllocateAlignedNoHook(size_t n);
|
||||
void* AllocateAlignedWithHook(size_t n, const std::type_info* type);
|
||||
void* AllocateAlignedWithHookForArray(size_t n, const std::type_info* type);
|
||||
std::pair<void*, internal::SerialArena::CleanupNode*>
|
||||
AllocateAlignedWithCleanup(size_t n, const std::type_info* type);
|
||||
|
||||
template <typename Type>
|
||||
friend class internal::GenericTypeHandler;
|
||||
friend class internal::InternalMetadata; // For user_arena().
|
||||
friend class internal::LazyField; // For CreateMaybeMessage.
|
||||
friend class internal::EpsCopyInputStream; // For parser performance
|
||||
friend class MessageLite;
|
||||
template <typename Key, typename T>
|
||||
friend class Map;
|
||||
template <typename>
|
||||
friend class RepeatedField; // For ReturnArrayMemory
|
||||
friend class internal::RepeatedPtrFieldBase; // For ReturnArrayMemory
|
||||
friend struct internal::ArenaTestPeer;
|
||||
};
|
||||
|
||||
// Defined above for supporting environments without RTTI.
|
||||
#undef RTTI_TYPE_ID
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_ARENA_H__
|
||||
@@ -1,686 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// This file defines an Arena allocator for better allocation performance.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_ARENA_IMPL_H__
|
||||
#define GOOGLE_PROTOBUF_ARENA_IMPL_H__
|
||||
|
||||
#include <atomic>
|
||||
#include <limits>
|
||||
#include <typeinfo>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/logging.h>
|
||||
#include <google/protobuf/stubs/port.h>
|
||||
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
#include <sanitizer/asan_interface.h>
|
||||
#endif // ADDRESS_SANITIZER
|
||||
|
||||
#include <google/protobuf/arenaz_sampler.h>
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
// To prevent sharing cache lines between threads
|
||||
#ifdef __cpp_aligned_new
|
||||
enum { kCacheAlignment = 64 };
|
||||
#else
|
||||
enum { kCacheAlignment = alignof(max_align_t) }; // do the best we can
|
||||
#endif
|
||||
|
||||
inline constexpr size_t AlignUpTo8(size_t n) {
|
||||
// Align n to next multiple of 8 (from Hacker's Delight, Chapter 3.)
|
||||
return (n + 7) & static_cast<size_t>(-8);
|
||||
}
|
||||
|
||||
using LifecycleIdAtomic = uint64_t;
|
||||
|
||||
// MetricsCollector collects stats for a particular arena.
|
||||
class PROTOBUF_EXPORT ArenaMetricsCollector {
|
||||
public:
|
||||
ArenaMetricsCollector(bool record_allocs) : record_allocs_(record_allocs) {}
|
||||
|
||||
// Invoked when the arena is about to be destroyed. This method will
|
||||
// typically finalize any metric collection and delete the collector.
|
||||
// space_allocated is the space used by the arena.
|
||||
virtual void OnDestroy(uint64_t space_allocated) = 0;
|
||||
|
||||
// OnReset() is called when the associated arena is reset.
|
||||
// space_allocated is the space used by the arena just before the reset.
|
||||
virtual void OnReset(uint64_t space_allocated) = 0;
|
||||
|
||||
// OnAlloc is called when an allocation happens.
|
||||
// type_info is promised to be static - its lifetime extends to
|
||||
// match program's lifetime (It is given by typeid operator).
|
||||
// Note: typeid(void) will be passed as allocated_type every time we
|
||||
// intentionally want to avoid monitoring an allocation. (i.e. internal
|
||||
// allocations for managing the arena)
|
||||
virtual void OnAlloc(const std::type_info* allocated_type,
|
||||
uint64_t alloc_size) = 0;
|
||||
|
||||
// Does OnAlloc() need to be called? If false, metric collection overhead
|
||||
// will be reduced since we will not do extra work per allocation.
|
||||
bool RecordAllocs() { return record_allocs_; }
|
||||
|
||||
protected:
|
||||
// This class is destructed by the call to OnDestroy().
|
||||
~ArenaMetricsCollector() = default;
|
||||
const bool record_allocs_;
|
||||
};
|
||||
|
||||
struct AllocationPolicy {
|
||||
static constexpr size_t kDefaultStartBlockSize = 256;
|
||||
static constexpr size_t kDefaultMaxBlockSize = 8192;
|
||||
|
||||
size_t start_block_size = kDefaultStartBlockSize;
|
||||
size_t max_block_size = kDefaultMaxBlockSize;
|
||||
void* (*block_alloc)(size_t) = nullptr;
|
||||
void (*block_dealloc)(void*, size_t) = nullptr;
|
||||
ArenaMetricsCollector* metrics_collector = nullptr;
|
||||
|
||||
bool IsDefault() const {
|
||||
return start_block_size == kDefaultMaxBlockSize &&
|
||||
max_block_size == kDefaultMaxBlockSize && block_alloc == nullptr &&
|
||||
block_dealloc == nullptr && metrics_collector == nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
// Tagged pointer to an AllocationPolicy.
|
||||
class TaggedAllocationPolicyPtr {
|
||||
public:
|
||||
constexpr TaggedAllocationPolicyPtr() : policy_(0) {}
|
||||
|
||||
explicit TaggedAllocationPolicyPtr(AllocationPolicy* policy)
|
||||
: policy_(reinterpret_cast<uintptr_t>(policy)) {}
|
||||
|
||||
void set_policy(AllocationPolicy* policy) {
|
||||
auto bits = policy_ & kTagsMask;
|
||||
policy_ = reinterpret_cast<uintptr_t>(policy) | bits;
|
||||
}
|
||||
|
||||
AllocationPolicy* get() {
|
||||
return reinterpret_cast<AllocationPolicy*>(policy_ & kPtrMask);
|
||||
}
|
||||
const AllocationPolicy* get() const {
|
||||
return reinterpret_cast<const AllocationPolicy*>(policy_ & kPtrMask);
|
||||
}
|
||||
|
||||
AllocationPolicy& operator*() { return *get(); }
|
||||
const AllocationPolicy& operator*() const { return *get(); }
|
||||
|
||||
AllocationPolicy* operator->() { return get(); }
|
||||
const AllocationPolicy* operator->() const { return get(); }
|
||||
|
||||
bool is_user_owned_initial_block() const {
|
||||
return static_cast<bool>(get_mask<kUserOwnedInitialBlock>());
|
||||
}
|
||||
void set_is_user_owned_initial_block(bool v) {
|
||||
set_mask<kUserOwnedInitialBlock>(v);
|
||||
}
|
||||
|
||||
bool should_record_allocs() const {
|
||||
return static_cast<bool>(get_mask<kRecordAllocs>());
|
||||
}
|
||||
void set_should_record_allocs(bool v) { set_mask<kRecordAllocs>(v); }
|
||||
|
||||
uintptr_t get_raw() const { return policy_; }
|
||||
|
||||
inline void RecordAlloc(const std::type_info* allocated_type,
|
||||
size_t n) const {
|
||||
get()->metrics_collector->OnAlloc(allocated_type, n);
|
||||
}
|
||||
|
||||
private:
|
||||
enum : uintptr_t {
|
||||
kUserOwnedInitialBlock = 1,
|
||||
kRecordAllocs = 2,
|
||||
};
|
||||
|
||||
static constexpr uintptr_t kTagsMask = 7;
|
||||
static constexpr uintptr_t kPtrMask = ~kTagsMask;
|
||||
|
||||
template <uintptr_t kMask>
|
||||
uintptr_t get_mask() const {
|
||||
return policy_ & kMask;
|
||||
}
|
||||
template <uintptr_t kMask>
|
||||
void set_mask(bool v) {
|
||||
if (v) {
|
||||
policy_ |= kMask;
|
||||
} else {
|
||||
policy_ &= ~kMask;
|
||||
}
|
||||
}
|
||||
uintptr_t policy_;
|
||||
};
|
||||
|
||||
enum class AllocationClient { kDefault, kArray };
|
||||
|
||||
// A simple arena allocator. Calls to allocate functions must be properly
|
||||
// serialized by the caller, hence this class cannot be used as a general
|
||||
// purpose allocator in a multi-threaded program. It serves as a building block
|
||||
// for ThreadSafeArena, which provides a thread-safe arena allocator.
|
||||
//
|
||||
// This class manages
|
||||
// 1) Arena bump allocation + owning memory blocks.
|
||||
// 2) Maintaining a cleanup list.
|
||||
// It delagetes the actual memory allocation back to ThreadSafeArena, which
|
||||
// contains the information on block growth policy and backing memory allocation
|
||||
// used.
|
||||
class PROTOBUF_EXPORT SerialArena {
|
||||
public:
|
||||
struct Memory {
|
||||
void* ptr;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
// Node contains the ptr of the object to be cleaned up and the associated
|
||||
// cleanup function ptr.
|
||||
struct CleanupNode {
|
||||
void* elem; // Pointer to the object to be cleaned up.
|
||||
void (*cleanup)(void*); // Function pointer to the destructor or deleter.
|
||||
};
|
||||
|
||||
void CleanupList();
|
||||
uint64_t SpaceAllocated() const {
|
||||
return space_allocated_.load(std::memory_order_relaxed);
|
||||
}
|
||||
uint64_t SpaceUsed() const;
|
||||
|
||||
bool HasSpace(size_t n) const {
|
||||
return n <= static_cast<size_t>(limit_ - ptr_);
|
||||
}
|
||||
|
||||
// See comments on `cached_blocks_` member for details.
|
||||
PROTOBUF_ALWAYS_INLINE void* TryAllocateFromCachedBlock(size_t size) {
|
||||
if (PROTOBUF_PREDICT_FALSE(size < 16)) return nullptr;
|
||||
// We round up to the next larger block in case the memory doesn't match
|
||||
// the pattern we are looking for.
|
||||
const size_t index = Bits::Log2FloorNonZero64(size - 1) - 3;
|
||||
|
||||
if (index >= cached_block_length_) return nullptr;
|
||||
auto& cached_head = cached_blocks_[index];
|
||||
if (cached_head == nullptr) return nullptr;
|
||||
|
||||
void* ret = cached_head;
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
ASAN_UNPOISON_MEMORY_REGION(ret, size);
|
||||
#endif // ADDRESS_SANITIZER
|
||||
cached_head = cached_head->next;
|
||||
return ret;
|
||||
}
|
||||
|
||||
// In kArray mode we look through cached blocks.
|
||||
// We do not do this by default because most non-array allocations will not
|
||||
// have the right size and will fail to find an appropriate cached block.
|
||||
//
|
||||
// TODO(sbenza): Evaluate if we should use cached blocks for message types of
|
||||
// the right size. We can statically know if the allocation size can benefit
|
||||
// from it.
|
||||
template <AllocationClient alloc_client = AllocationClient::kDefault>
|
||||
void* AllocateAligned(size_t n, const AllocationPolicy* policy) {
|
||||
GOOGLE_DCHECK_EQ(internal::AlignUpTo8(n), n); // Must be already aligned.
|
||||
GOOGLE_DCHECK_GE(limit_, ptr_);
|
||||
|
||||
if (alloc_client == AllocationClient::kArray) {
|
||||
if (void* res = TryAllocateFromCachedBlock(n)) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
if (PROTOBUF_PREDICT_FALSE(!HasSpace(n))) {
|
||||
return AllocateAlignedFallback(n, policy);
|
||||
}
|
||||
return AllocateFromExisting(n);
|
||||
}
|
||||
|
||||
private:
|
||||
void* AllocateFromExisting(size_t n) {
|
||||
void* ret = ptr_;
|
||||
ptr_ += n;
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
ASAN_UNPOISON_MEMORY_REGION(ret, n);
|
||||
#endif // ADDRESS_SANITIZER
|
||||
return ret;
|
||||
}
|
||||
|
||||
// See comments on `cached_blocks_` member for details.
|
||||
void ReturnArrayMemory(void* p, size_t size) {
|
||||
// We only need to check for 32-bit platforms.
|
||||
// In 64-bit platforms the minimum allocation size from Repeated*Field will
|
||||
// be 16 guaranteed.
|
||||
if (sizeof(void*) < 8) {
|
||||
if (PROTOBUF_PREDICT_FALSE(size < 16)) return;
|
||||
} else {
|
||||
GOOGLE_DCHECK(size >= 16);
|
||||
}
|
||||
|
||||
// We round down to the next smaller block in case the memory doesn't match
|
||||
// the pattern we are looking for. eg, someone might have called Reserve()
|
||||
// on the repeated field.
|
||||
const size_t index = Bits::Log2FloorNonZero64(size) - 4;
|
||||
|
||||
if (PROTOBUF_PREDICT_FALSE(index >= cached_block_length_)) {
|
||||
// We can't put this object on the freelist so make this object the
|
||||
// freelist. It is guaranteed it is larger than the one we have, and
|
||||
// large enough to hold another allocation of `size`.
|
||||
CachedBlock** new_list = static_cast<CachedBlock**>(p);
|
||||
size_t new_size = size / sizeof(CachedBlock*);
|
||||
|
||||
std::copy(cached_blocks_, cached_blocks_ + cached_block_length_,
|
||||
new_list);
|
||||
std::fill(new_list + cached_block_length_, new_list + new_size, nullptr);
|
||||
cached_blocks_ = new_list;
|
||||
// Make the size fit in uint8_t. This is the power of two, so we don't
|
||||
// need anything larger.
|
||||
cached_block_length_ =
|
||||
static_cast<uint8_t>(std::min(size_t{64}, new_size));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
auto& cached_head = cached_blocks_[index];
|
||||
auto* new_node = static_cast<CachedBlock*>(p);
|
||||
new_node->next = cached_head;
|
||||
cached_head = new_node;
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
ASAN_POISON_MEMORY_REGION(p, size);
|
||||
#endif // ADDRESS_SANITIZER
|
||||
}
|
||||
|
||||
public:
|
||||
// Allocate space if the current region provides enough space.
|
||||
bool MaybeAllocateAligned(size_t n, void** out) {
|
||||
GOOGLE_DCHECK_EQ(internal::AlignUpTo8(n), n); // Must be already aligned.
|
||||
GOOGLE_DCHECK_GE(limit_, ptr_);
|
||||
if (PROTOBUF_PREDICT_FALSE(!HasSpace(n))) return false;
|
||||
*out = AllocateFromExisting(n);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::pair<void*, CleanupNode*> AllocateAlignedWithCleanup(
|
||||
size_t n, const AllocationPolicy* policy) {
|
||||
GOOGLE_DCHECK_EQ(internal::AlignUpTo8(n), n); // Must be already aligned.
|
||||
if (PROTOBUF_PREDICT_FALSE(!HasSpace(n + kCleanupSize))) {
|
||||
return AllocateAlignedWithCleanupFallback(n, policy);
|
||||
}
|
||||
return AllocateFromExistingWithCleanupFallback(n);
|
||||
}
|
||||
|
||||
private:
|
||||
std::pair<void*, CleanupNode*> AllocateFromExistingWithCleanupFallback(
|
||||
size_t n) {
|
||||
void* ret = ptr_;
|
||||
ptr_ += n;
|
||||
limit_ -= kCleanupSize;
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
ASAN_UNPOISON_MEMORY_REGION(ret, n);
|
||||
ASAN_UNPOISON_MEMORY_REGION(limit_, kCleanupSize);
|
||||
#endif // ADDRESS_SANITIZER
|
||||
return CreatePair(ret, reinterpret_cast<CleanupNode*>(limit_));
|
||||
}
|
||||
|
||||
public:
|
||||
void AddCleanup(void* elem, void (*cleanup)(void*),
|
||||
const AllocationPolicy* policy) {
|
||||
auto res = AllocateAlignedWithCleanup(0, policy);
|
||||
res.second->elem = elem;
|
||||
res.second->cleanup = cleanup;
|
||||
}
|
||||
|
||||
void* owner() const { return owner_; }
|
||||
SerialArena* next() const { return next_; }
|
||||
void set_next(SerialArena* next) { next_ = next; }
|
||||
|
||||
private:
|
||||
friend class ThreadSafeArena;
|
||||
friend class ArenaBenchmark;
|
||||
|
||||
// Creates a new SerialArena inside mem using the remaining memory as for
|
||||
// future allocations.
|
||||
static SerialArena* New(SerialArena::Memory mem, void* owner,
|
||||
ThreadSafeArenaStats* stats);
|
||||
// Free SerialArena returning the memory passed in to New
|
||||
template <typename Deallocator>
|
||||
Memory Free(Deallocator deallocator);
|
||||
|
||||
// Blocks are variable length malloc-ed objects. The following structure
|
||||
// describes the common header for all blocks.
|
||||
struct Block {
|
||||
Block(Block* next, size_t size) : next(next), size(size), start(nullptr) {}
|
||||
|
||||
char* Pointer(size_t n) {
|
||||
GOOGLE_DCHECK(n <= size);
|
||||
return reinterpret_cast<char*>(this) + n;
|
||||
}
|
||||
|
||||
Block* const next;
|
||||
const size_t size;
|
||||
CleanupNode* start;
|
||||
// data follows
|
||||
};
|
||||
|
||||
void* owner_; // &ThreadCache of this thread;
|
||||
Block* head_; // Head of linked list of blocks.
|
||||
SerialArena* next_; // Next SerialArena in this linked list.
|
||||
size_t space_used_ = 0; // Necessary for metrics.
|
||||
std::atomic<size_t> space_allocated_;
|
||||
|
||||
// Next pointer to allocate from. Always 8-byte aligned. Points inside
|
||||
// head_ (and head_->pos will always be non-canonical). We keep these
|
||||
// here to reduce indirection.
|
||||
char* ptr_;
|
||||
// Limiting address up to which memory can be allocated from the head block.
|
||||
char* limit_;
|
||||
// For holding sampling information. The pointer is owned by the
|
||||
// ThreadSafeArena that holds this serial arena.
|
||||
ThreadSafeArenaStats* arena_stats_;
|
||||
|
||||
// Repeated*Field and Arena play together to reduce memory consumption by
|
||||
// reusing blocks. Currently, natural growth of the repeated field types makes
|
||||
// them allocate blocks of size `8 + 2^N, N>=3`.
|
||||
// When the repeated field grows returns the previous block and we put it in
|
||||
// this free list.
|
||||
// `cached_blocks_[i]` points to the free list for blocks of size `8+2^(i+3)`.
|
||||
// The array of freelists is grown when needed in `ReturnArrayMemory()`.
|
||||
struct CachedBlock {
|
||||
// Simple linked list.
|
||||
CachedBlock* next;
|
||||
};
|
||||
uint8_t cached_block_length_ = 0;
|
||||
CachedBlock** cached_blocks_ = nullptr;
|
||||
|
||||
// Constructor is private as only New() should be used.
|
||||
inline SerialArena(Block* b, void* owner, ThreadSafeArenaStats* stats);
|
||||
void* AllocateAlignedFallback(size_t n, const AllocationPolicy* policy);
|
||||
std::pair<void*, CleanupNode*> AllocateAlignedWithCleanupFallback(
|
||||
size_t n, const AllocationPolicy* policy);
|
||||
void AllocateNewBlock(size_t n, const AllocationPolicy* policy);
|
||||
|
||||
std::pair<void*, CleanupNode*> CreatePair(void* ptr, CleanupNode* node) {
|
||||
return {ptr, node};
|
||||
}
|
||||
|
||||
public:
|
||||
static constexpr size_t kBlockHeaderSize = AlignUpTo8(sizeof(Block));
|
||||
static constexpr size_t kCleanupSize = AlignUpTo8(sizeof(CleanupNode));
|
||||
};
|
||||
|
||||
// Tag type used to invoke the constructor of message-owned arena.
|
||||
// Only message-owned arenas use this constructor for creation.
|
||||
// Such constructors are internal implementation details of the library.
|
||||
struct MessageOwned {
|
||||
explicit MessageOwned() = default;
|
||||
};
|
||||
|
||||
// This class provides the core Arena memory allocation library. Different
|
||||
// implementations only need to implement the public interface below.
|
||||
// Arena is not a template type as that would only be useful if all protos
|
||||
// in turn would be templates, which will/cannot happen. However separating
|
||||
// the memory allocation part from the cruft of the API users expect we can
|
||||
// use #ifdef the select the best implementation based on hardware / OS.
|
||||
class PROTOBUF_EXPORT ThreadSafeArena {
|
||||
public:
|
||||
ThreadSafeArena() { Init(); }
|
||||
|
||||
// Constructor solely used by message-owned arena.
|
||||
ThreadSafeArena(internal::MessageOwned) : tag_and_id_(kMessageOwnedArena) {
|
||||
Init();
|
||||
}
|
||||
|
||||
ThreadSafeArena(char* mem, size_t size) { InitializeFrom(mem, size); }
|
||||
|
||||
explicit ThreadSafeArena(void* mem, size_t size,
|
||||
const AllocationPolicy& policy) {
|
||||
InitializeWithPolicy(mem, size, policy);
|
||||
}
|
||||
|
||||
// Destructor deletes all owned heap allocated objects, and destructs objects
|
||||
// that have non-trivial destructors, except for proto2 message objects whose
|
||||
// destructors can be skipped. Also, frees all blocks except the initial block
|
||||
// if it was passed in.
|
||||
~ThreadSafeArena();
|
||||
|
||||
uint64_t Reset();
|
||||
|
||||
uint64_t SpaceAllocated() const;
|
||||
uint64_t SpaceUsed() const;
|
||||
|
||||
template <AllocationClient alloc_client = AllocationClient::kDefault>
|
||||
void* AllocateAligned(size_t n, const std::type_info* type) {
|
||||
SerialArena* arena = nullptr;
|
||||
if (PROTOBUF_PREDICT_TRUE(!alloc_policy_.should_record_allocs() &&
|
||||
GetSerialArenaFast(&arena))) {
|
||||
return arena->AllocateAligned<alloc_client>(n, AllocPolicy());
|
||||
} else {
|
||||
return AllocateAlignedFallback(n, type);
|
||||
}
|
||||
}
|
||||
|
||||
void ReturnArrayMemory(void* p, size_t size) {
|
||||
SerialArena* arena = nullptr;
|
||||
if (PROTOBUF_PREDICT_TRUE(GetSerialArenaFast(&arena))) {
|
||||
arena->ReturnArrayMemory(p, size);
|
||||
}
|
||||
}
|
||||
|
||||
// This function allocates n bytes if the common happy case is true and
|
||||
// returns true. Otherwise does nothing and returns false. This strange
|
||||
// semantics is necessary to allow callers to program functions that only
|
||||
// have fallback function calls in tail position. This substantially improves
|
||||
// code for the happy path.
|
||||
PROTOBUF_NDEBUG_INLINE bool MaybeAllocateAligned(size_t n, void** out) {
|
||||
SerialArena* arena;
|
||||
if (PROTOBUF_PREDICT_TRUE(!alloc_policy_.should_record_allocs() &&
|
||||
GetSerialArenaFromThreadCache(&arena))) {
|
||||
return arena->MaybeAllocateAligned(n, out);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::pair<void*, SerialArena::CleanupNode*> AllocateAlignedWithCleanup(
|
||||
size_t n, const std::type_info* type);
|
||||
|
||||
// Add object pointer and cleanup function pointer to the list.
|
||||
void AddCleanup(void* elem, void (*cleanup)(void*));
|
||||
|
||||
// Checks whether this arena is message-owned.
|
||||
PROTOBUF_ALWAYS_INLINE bool IsMessageOwned() const {
|
||||
return tag_and_id_ & kMessageOwnedArena;
|
||||
}
|
||||
|
||||
private:
|
||||
// Unique for each arena. Changes on Reset().
|
||||
uint64_t tag_and_id_ = 0;
|
||||
// The LSB of tag_and_id_ indicates if the arena is message-owned.
|
||||
enum : uint64_t { kMessageOwnedArena = 1 };
|
||||
|
||||
TaggedAllocationPolicyPtr alloc_policy_; // Tagged pointer to AllocPolicy.
|
||||
|
||||
static_assert(std::is_trivially_destructible<SerialArena>{},
|
||||
"SerialArena needs to be trivially destructible.");
|
||||
// Pointer to a linked list of SerialArena.
|
||||
std::atomic<SerialArena*> threads_;
|
||||
std::atomic<SerialArena*> hint_; // Fast thread-local block access
|
||||
|
||||
const AllocationPolicy* AllocPolicy() const { return alloc_policy_.get(); }
|
||||
void InitializeFrom(void* mem, size_t size);
|
||||
void InitializeWithPolicy(void* mem, size_t size, AllocationPolicy policy);
|
||||
void* AllocateAlignedFallback(size_t n, const std::type_info* type);
|
||||
std::pair<void*, SerialArena::CleanupNode*>
|
||||
AllocateAlignedWithCleanupFallback(size_t n, const std::type_info* type);
|
||||
|
||||
void Init();
|
||||
void SetInitialBlock(void* mem, size_t size);
|
||||
|
||||
// Delete or Destruct all objects owned by the arena.
|
||||
void CleanupList();
|
||||
|
||||
inline uint64_t LifeCycleId() const {
|
||||
return tag_and_id_ & ~kMessageOwnedArena;
|
||||
}
|
||||
|
||||
inline void CacheSerialArena(SerialArena* serial) {
|
||||
thread_cache().last_serial_arena = serial;
|
||||
thread_cache().last_lifecycle_id_seen = tag_and_id_;
|
||||
// TODO(haberman): evaluate whether we would gain efficiency by getting rid
|
||||
// of hint_. It's the only write we do to ThreadSafeArena in the allocation
|
||||
// path, which will dirty the cache line.
|
||||
|
||||
hint_.store(serial, std::memory_order_release);
|
||||
}
|
||||
|
||||
PROTOBUF_NDEBUG_INLINE bool GetSerialArenaFast(SerialArena** arena) {
|
||||
if (GetSerialArenaFromThreadCache(arena)) return true;
|
||||
|
||||
// Check whether we own the last accessed SerialArena on this arena. This
|
||||
// fast path optimizes the case where a single thread uses multiple arenas.
|
||||
ThreadCache* tc = &thread_cache();
|
||||
SerialArena* serial = hint_.load(std::memory_order_acquire);
|
||||
if (PROTOBUF_PREDICT_TRUE(serial != nullptr && serial->owner() == tc)) {
|
||||
*arena = serial;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
PROTOBUF_NDEBUG_INLINE bool GetSerialArenaFromThreadCache(
|
||||
SerialArena** arena) {
|
||||
// If this thread already owns a block in this arena then try to use that.
|
||||
// This fast path optimizes the case where multiple threads allocate from
|
||||
// the same arena.
|
||||
ThreadCache* tc = &thread_cache();
|
||||
if (PROTOBUF_PREDICT_TRUE(tc->last_lifecycle_id_seen == tag_and_id_)) {
|
||||
*arena = tc->last_serial_arena;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
SerialArena* GetSerialArenaFallback(void* me);
|
||||
|
||||
template <typename Functor>
|
||||
void PerSerialArena(Functor fn) {
|
||||
// By omitting an Acquire barrier we ensure that any user code that doesn't
|
||||
// properly synchronize Reset() or the destructor will throw a TSAN warning.
|
||||
SerialArena* serial = threads_.load(std::memory_order_relaxed);
|
||||
|
||||
for (; serial; serial = serial->next()) fn(serial);
|
||||
}
|
||||
|
||||
// Releases all memory except the first block which it returns. The first
|
||||
// block might be owned by the user and thus need some extra checks before
|
||||
// deleting.
|
||||
SerialArena::Memory Free(size_t* space_allocated);
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4324)
|
||||
#endif
|
||||
struct alignas(kCacheAlignment) ThreadCache {
|
||||
#if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL)
|
||||
// If we are using the ThreadLocalStorage class to store the ThreadCache,
|
||||
// then the ThreadCache's default constructor has to be responsible for
|
||||
// initializing it.
|
||||
ThreadCache()
|
||||
: next_lifecycle_id(0),
|
||||
last_lifecycle_id_seen(-1),
|
||||
last_serial_arena(nullptr) {}
|
||||
#endif
|
||||
|
||||
// Number of per-thread lifecycle IDs to reserve. Must be power of two.
|
||||
// To reduce contention on a global atomic, each thread reserves a batch of
|
||||
// IDs. The following number is calculated based on a stress test with
|
||||
// ~6500 threads all frequently allocating a new arena.
|
||||
static constexpr size_t kPerThreadIds = 256;
|
||||
// Next lifecycle ID available to this thread. We need to reserve a new
|
||||
// batch, if `next_lifecycle_id & (kPerThreadIds - 1) == 0`.
|
||||
uint64_t next_lifecycle_id;
|
||||
// The ThreadCache is considered valid as long as this matches the
|
||||
// lifecycle_id of the arena being used.
|
||||
uint64_t last_lifecycle_id_seen;
|
||||
SerialArena* last_serial_arena;
|
||||
};
|
||||
|
||||
// Lifecycle_id can be highly contended variable in a situation of lots of
|
||||
// arena creation. Make sure that other global variables are not sharing the
|
||||
// cacheline.
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4324)
|
||||
#endif
|
||||
struct alignas(kCacheAlignment) CacheAlignedLifecycleIdGenerator {
|
||||
std::atomic<LifecycleIdAtomic> id;
|
||||
};
|
||||
static CacheAlignedLifecycleIdGenerator lifecycle_id_generator_;
|
||||
#if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL)
|
||||
// iOS does not support __thread keyword so we use a custom thread local
|
||||
// storage class we implemented.
|
||||
static ThreadCache& thread_cache();
|
||||
#elif defined(PROTOBUF_USE_DLLS)
|
||||
// Thread local variables cannot be exposed through DLL interface but we can
|
||||
// wrap them in static functions.
|
||||
static ThreadCache& thread_cache();
|
||||
#else
|
||||
static PROTOBUF_THREAD_LOCAL ThreadCache thread_cache_;
|
||||
static ThreadCache& thread_cache() { return thread_cache_; }
|
||||
#endif
|
||||
|
||||
ThreadSafeArenaStatsHandle arena_stats_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ThreadSafeArena);
|
||||
// All protos have pointers back to the arena hence Arena must have
|
||||
// pointer stability.
|
||||
ThreadSafeArena(ThreadSafeArena&&) = delete;
|
||||
ThreadSafeArena& operator=(ThreadSafeArena&&) = delete;
|
||||
|
||||
public:
|
||||
// kBlockHeaderSize is sizeof(Block), aligned up to the nearest multiple of 8
|
||||
// to protect the invariant that pos is always at a multiple of 8.
|
||||
static constexpr size_t kBlockHeaderSize = SerialArena::kBlockHeaderSize;
|
||||
static constexpr size_t kSerialArenaSize =
|
||||
(sizeof(SerialArena) + 7) & static_cast<size_t>(-8);
|
||||
static_assert(kBlockHeaderSize % 8 == 0,
|
||||
"kBlockHeaderSize must be a multiple of 8.");
|
||||
static_assert(kSerialArenaSize % 8 == 0,
|
||||
"kSerialArenaSize must be a multiple of 8.");
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_ARENA_IMPL_H__
|
||||
@@ -1,480 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_ARENASTRING_H__
|
||||
#define GOOGLE_PROTOBUF_ARENASTRING_H__
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include <google/protobuf/stubs/logging.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/arena.h>
|
||||
#include <google/protobuf/port.h>
|
||||
#include <google/protobuf/explicitly_constructed.h>
|
||||
|
||||
// must be last:
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
#ifdef SWIG
|
||||
#error "You cannot SWIG proto headers"
|
||||
#endif
|
||||
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
class EpsCopyInputStream;
|
||||
|
||||
class SwapFieldHelper;
|
||||
|
||||
// Declared in message_lite.h
|
||||
PROTOBUF_EXPORT extern ExplicitlyConstructedArenaString
|
||||
fixed_address_empty_string;
|
||||
|
||||
// Lazy string instance to support string fields with non-empty default.
|
||||
// These are initialized on the first call to .get().
|
||||
class PROTOBUF_EXPORT LazyString {
|
||||
public:
|
||||
// We explicitly make LazyString an aggregate so that MSVC can do constant
|
||||
// initialization on it without marking it `constexpr`.
|
||||
// We do not want to use `constexpr` because it makes it harder to have extern
|
||||
// storage for it and causes library bloat.
|
||||
struct InitValue {
|
||||
const char* ptr;
|
||||
size_t size;
|
||||
};
|
||||
// We keep a union of the initialization value and the std::string to save on
|
||||
// space. We don't need the string array after Init() is done.
|
||||
union {
|
||||
mutable InitValue init_value_;
|
||||
alignas(std::string) mutable char string_buf_[sizeof(std::string)];
|
||||
};
|
||||
mutable std::atomic<const std::string*> inited_;
|
||||
|
||||
const std::string& get() const {
|
||||
// This check generates less code than a call-once invocation.
|
||||
auto* res = inited_.load(std::memory_order_acquire);
|
||||
if (PROTOBUF_PREDICT_FALSE(res == nullptr)) return Init();
|
||||
return *res;
|
||||
}
|
||||
|
||||
private:
|
||||
// Initialize the string in `string_buf_`, update `inited_` and return it.
|
||||
// We return it here to avoid having to read it again in the inlined code.
|
||||
const std::string& Init() const;
|
||||
};
|
||||
|
||||
class TaggedStringPtr {
|
||||
public:
|
||||
// Bit flags qualifying string properties. We can use 2 bits as
|
||||
// ptr_ is guaranteed and enforced to be aligned on 4 byte boundaries.
|
||||
enum Flags {
|
||||
kArenaBit = 0x1, // ptr is arena allocated
|
||||
kMutableBit = 0x2, // ptr contents are fully mutable
|
||||
kMask = 0x3 // Bit mask
|
||||
};
|
||||
|
||||
// Composed logical types
|
||||
enum Type {
|
||||
// Default strings are immutable and never owned.
|
||||
kDefault = 0,
|
||||
|
||||
// Allocated strings are mutable and (as the name implies) owned.
|
||||
// A heap allocated string must be deleted.
|
||||
kAllocated = kMutableBit,
|
||||
|
||||
// Mutable arena strings are strings where the string instance is owned
|
||||
// by the arena, but the string contents itself are owned by the string
|
||||
// instance. Mutable arena string instances need to be destroyed which is
|
||||
// typically done through a cleanup action added to the arena owning it.
|
||||
kMutableArena = kArenaBit | kMutableBit,
|
||||
|
||||
// Fixed size arena strings are strings where both the string instance and
|
||||
// the string contents are fully owned by the arena. Fixed size arena
|
||||
// strings are a platform and c++ library specific customization. Fixed
|
||||
// size arena strings are immutable, with the exception of custom internal
|
||||
// updates to the content that fit inside the existing capacity.
|
||||
// Fixed size arena strings must never be deleted or destroyed.
|
||||
kFixedSizeArena = kArenaBit,
|
||||
};
|
||||
|
||||
TaggedStringPtr() = default;
|
||||
explicit constexpr TaggedStringPtr(ExplicitlyConstructedArenaString* ptr)
|
||||
: ptr_(ptr) {}
|
||||
|
||||
// Sets the value to `p`, tagging the value as being a 'default' value.
|
||||
// See documentation for kDefault for more info.
|
||||
inline const std::string* SetDefault(const std::string* p) {
|
||||
return TagAs(kDefault, const_cast<std::string*>(p));
|
||||
}
|
||||
|
||||
// Sets the value to `p`, tagging the value as a heap allocated value.
|
||||
// Allocated strings are mutable and (as the name implies) owned.
|
||||
// `p` must not be null
|
||||
inline std::string* SetAllocated(std::string* p) {
|
||||
return TagAs(kAllocated, p);
|
||||
}
|
||||
|
||||
// Sets the value to `p`, tagging the value as a fixed size arena string.
|
||||
// See documentation for kFixedSizeArena for more info.
|
||||
// `p` must not be null
|
||||
inline std::string* SetFixedSizeArena(std::string* p) {
|
||||
return TagAs(kFixedSizeArena, p);
|
||||
}
|
||||
|
||||
// Sets the value to `p`, tagging the value as a mutable arena string.
|
||||
// See documentation for kMutableArena for more info.
|
||||
// `p` must not be null
|
||||
inline std::string* SetMutableArena(std::string* p) {
|
||||
return TagAs(kMutableArena, p);
|
||||
}
|
||||
|
||||
// Returns true if the contents of the current string are fully mutable.
|
||||
inline bool IsMutable() const { return as_int() & kMutableBit; }
|
||||
|
||||
// Returns true if the current string is an immutable default value.
|
||||
inline bool IsDefault() const { return (as_int() & kMask) == kDefault; }
|
||||
|
||||
// If the current string is a heap-allocated mutable value, returns a pointer
|
||||
// to it. Returns nullptr otherwise.
|
||||
inline std::string *GetIfAllocated() const {
|
||||
auto allocated = as_int() ^ kAllocated;
|
||||
if (allocated & kMask) return nullptr;
|
||||
|
||||
auto ptr = reinterpret_cast<std::string*>(allocated);
|
||||
PROTOBUF_ASSUME(ptr != nullptr);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// Returns true if the current string is an arena allocated value.
|
||||
// This means it's either a mutable or fixed size arena string.
|
||||
inline bool IsArena() const { return as_int() & kArenaBit; }
|
||||
|
||||
// Returns true if the current string is a fixed size arena allocated value.
|
||||
inline bool IsFixedSizeArena() const {
|
||||
return (as_int() & kMask) == kFixedSizeArena;
|
||||
}
|
||||
|
||||
// Returns the contained string pointer.
|
||||
inline std::string* Get() const {
|
||||
return reinterpret_cast<std::string*>(as_int() & ~kMask);
|
||||
}
|
||||
|
||||
// Returns true if the contained pointer is null, indicating some error.
|
||||
// The Null value is only used during parsing for temporary values.
|
||||
// A persisted ArenaStringPtr value is never null.
|
||||
inline bool IsNull() { return ptr_ == nullptr; }
|
||||
|
||||
private:
|
||||
static inline void assert_aligned(const void* p) {
|
||||
GOOGLE_DCHECK_EQ(reinterpret_cast<uintptr_t>(p) & kMask, 0UL);
|
||||
}
|
||||
|
||||
inline std::string* TagAs(Type type, std::string* p) {
|
||||
GOOGLE_DCHECK(p != nullptr);
|
||||
assert_aligned(p);
|
||||
ptr_ = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(p) | type);
|
||||
return p;
|
||||
}
|
||||
|
||||
uintptr_t as_int() const { return reinterpret_cast<uintptr_t>(ptr_); }
|
||||
void* ptr_;
|
||||
};
|
||||
|
||||
static_assert(std::is_trivial<TaggedStringPtr>::value,
|
||||
"TaggedStringPtr must be trivial");
|
||||
|
||||
// This class encapsulates a pointer to a std::string with or without arena
|
||||
// owned contents, tagged by the bottom bits of the string pointer. It is a
|
||||
// high-level wrapper that almost directly corresponds to the interface required
|
||||
// by string fields in generated code. It replaces the old std::string* pointer
|
||||
// in such cases.
|
||||
//
|
||||
// The string pointer is tagged to be either a default, externally owned value,
|
||||
// a mutable heap allocated value, or an arena allocated value. The object uses
|
||||
// a single global instance of an empty string that is used as the initial
|
||||
// default value. Fields that have empty default values directly use this global
|
||||
// default. Fields that have non empty default values are supported through
|
||||
// lazily initialized default values managed by the LazyString class.
|
||||
//
|
||||
// Generated code and reflection code both ensure that ptr_ is never null.
|
||||
// Because ArenaStringPtr is used in oneof unions, its constructor is a NOP and
|
||||
// the field is always manually initialized via method calls.
|
||||
//
|
||||
// See TaggedStringPtr for more information about the types of string values
|
||||
// being held, and the mutable and ownership invariants for each type.
|
||||
struct PROTOBUF_EXPORT ArenaStringPtr {
|
||||
ArenaStringPtr() = default;
|
||||
constexpr ArenaStringPtr(ExplicitlyConstructedArenaString* default_value,
|
||||
ConstantInitialized)
|
||||
: tagged_ptr_(default_value) {}
|
||||
|
||||
// Called from generated code / reflection runtime only. Resets value to point
|
||||
// to a default string pointer, with the semantics that this ArenaStringPtr
|
||||
// does not own the pointed-to memory. Disregards initial value of ptr_ (so
|
||||
// this is the *ONLY* safe method to call after construction or when
|
||||
// reinitializing after becoming the active field in a oneof union).
|
||||
inline void InitDefault();
|
||||
|
||||
// Similar to `InitDefault` except that it allows the default value to be
|
||||
// initialized to an externally owned string. This method is called from
|
||||
// parsing code. `str` must not be null and outlive this instance.
|
||||
inline void InitExternal(const std::string* str);
|
||||
|
||||
// Called from generated code / reflection runtime only. Resets the value of
|
||||
// this instances to the heap allocated value in `str`. `str` must not be
|
||||
// null. Invokes `arena->Own(str)` to transfer ownership into the arena if
|
||||
// `arena` is not null, else, `str` will be owned by ArenaStringPtr. This
|
||||
// function should only be used to initialize a ArenaStringPtr or on an
|
||||
// instance known to not carry any heap allocated value.
|
||||
inline void InitAllocated(std::string* str, Arena* arena);
|
||||
|
||||
void Set(ConstStringParam value, Arena* arena);
|
||||
void Set(std::string&& value, Arena* arena);
|
||||
void Set(const char* s, Arena* arena);
|
||||
void Set(const char* s, size_t n, Arena* arena);
|
||||
|
||||
void SetBytes(ConstStringParam value, Arena* arena);
|
||||
void SetBytes(std::string&& value, Arena* arena);
|
||||
void SetBytes(const char* s, Arena* arena);
|
||||
void SetBytes(const void* p, size_t n, Arena* arena);
|
||||
|
||||
template <typename RefWrappedType>
|
||||
void Set(std::reference_wrapper<RefWrappedType> const_string_ref,
|
||||
::google::protobuf::Arena* arena) {
|
||||
Set(const_string_ref.get(), arena);
|
||||
}
|
||||
|
||||
// Returns a mutable std::string reference.
|
||||
// The version accepting a `LazyString` value is used in the generated code to
|
||||
// initialize mutable copies for fields with a non-empty default where the
|
||||
// default value is lazily initialized.
|
||||
std::string* Mutable(Arena* arena);
|
||||
std::string* Mutable(const LazyString& default_value, Arena* arena);
|
||||
|
||||
// Gets a mutable pointer with unspecified contents.
|
||||
// This function is identical to Mutable(), except it is optimized for the
|
||||
// case where the caller is not interested in the current contents. For
|
||||
// example, if the current field is not mutable, it will re-initialize the
|
||||
// value with an empty string rather than a (non-empty) default value.
|
||||
// Likewise, if the current value is a fixed size arena string with contents,
|
||||
// it will be initialized into an empty mutable arena string.
|
||||
std::string* MutableNoCopy(Arena* arena);
|
||||
|
||||
// Basic accessors.
|
||||
PROTOBUF_NDEBUG_INLINE const std::string& Get() const {
|
||||
// Unconditionally mask away the tag.
|
||||
return *tagged_ptr_.Get();
|
||||
}
|
||||
|
||||
// Returns a pointer to the stored contents for this instance.
|
||||
// This method is for internal debugging and tracking purposes only.
|
||||
PROTOBUF_NDEBUG_INLINE const std::string* UnsafeGetPointer() const
|
||||
PROTOBUF_RETURNS_NONNULL {
|
||||
return tagged_ptr_.Get();
|
||||
}
|
||||
|
||||
// Release returns a std::string* instance that is heap-allocated and is not
|
||||
// Own()'d by any arena. If the field is not set, this returns nullptr. The
|
||||
// caller retains ownership. Clears this field back to the default state.
|
||||
// Used to implement release_<field>() methods on generated classes.
|
||||
PROTOBUF_NODISCARD std::string* Release();
|
||||
|
||||
// Takes a std::string that is heap-allocated, and takes ownership. The
|
||||
// std::string's destructor is registered with the arena. Used to implement
|
||||
// set_allocated_<field> in generated classes.
|
||||
void SetAllocated(std::string* value, Arena* arena);
|
||||
|
||||
// Frees storage (if not on an arena).
|
||||
void Destroy();
|
||||
|
||||
// Clears content, but keeps allocated std::string, to avoid the overhead of
|
||||
// heap operations. After this returns, the content (as seen by the user) will
|
||||
// always be the empty std::string. Assumes that |default_value| is an empty
|
||||
// std::string.
|
||||
void ClearToEmpty();
|
||||
|
||||
// Clears content, assuming that the current value is not the empty
|
||||
// string default.
|
||||
void ClearNonDefaultToEmpty();
|
||||
|
||||
// Clears content, but keeps allocated std::string if arena != nullptr, to
|
||||
// avoid the overhead of heap operations. After this returns, the content
|
||||
// (as seen by the user) will always be equal to |default_value|.
|
||||
void ClearToDefault(const LazyString& default_value, ::google::protobuf::Arena* arena);
|
||||
|
||||
// Swaps internal pointers. Arena-safety semantics: this is guarded by the
|
||||
// logic in Swap()/UnsafeArenaSwap() at the message level, so this method is
|
||||
// 'unsafe' if called directly.
|
||||
inline PROTOBUF_NDEBUG_INLINE static void InternalSwap(ArenaStringPtr* rhs,
|
||||
Arena* rhs_arena,
|
||||
ArenaStringPtr* lhs,
|
||||
Arena* lhs_arena);
|
||||
|
||||
// Internal setter used only at parse time to directly set a donated string
|
||||
// value.
|
||||
void UnsafeSetTaggedPointer(TaggedStringPtr value) { tagged_ptr_ = value; }
|
||||
// Generated code only! An optimization, in certain cases the generated
|
||||
// code is certain we can obtain a std::string with no default checks and
|
||||
// tag tests.
|
||||
std::string* UnsafeMutablePointer() PROTOBUF_RETURNS_NONNULL;
|
||||
|
||||
// Returns true if this instances holds an immutable default value.
|
||||
inline bool IsDefault() const { return tagged_ptr_.IsDefault(); }
|
||||
|
||||
private:
|
||||
template <typename... Args>
|
||||
inline std::string* NewString(Arena* arena, Args&&... args) {
|
||||
if (arena == nullptr) {
|
||||
auto* s = new std::string(std::forward<Args>(args)...);
|
||||
return tagged_ptr_.SetAllocated(s);
|
||||
} else {
|
||||
auto* s = Arena::Create<std::string>(arena, std::forward<Args>(args)...);
|
||||
return tagged_ptr_.SetMutableArena(s);
|
||||
}
|
||||
}
|
||||
|
||||
TaggedStringPtr tagged_ptr_;
|
||||
|
||||
bool IsFixedSizeArena() const { return false; }
|
||||
|
||||
// Swaps tagged pointer without debug hardening. This is to allow python
|
||||
// protobuf to maintain pointer stability even in DEBUG builds.
|
||||
inline PROTOBUF_NDEBUG_INLINE static void UnsafeShallowSwap(
|
||||
ArenaStringPtr* rhs, ArenaStringPtr* lhs) {
|
||||
std::swap(lhs->tagged_ptr_, rhs->tagged_ptr_);
|
||||
}
|
||||
|
||||
friend class ::google::protobuf::internal::SwapFieldHelper;
|
||||
friend class TcParser;
|
||||
|
||||
// Slow paths.
|
||||
|
||||
// MutableSlow requires that !IsString() || IsDefault
|
||||
// Variadic to support 0 args for empty default and 1 arg for LazyString.
|
||||
template <typename... Lazy>
|
||||
std::string* MutableSlow(::google::protobuf::Arena* arena, const Lazy&... lazy_default);
|
||||
|
||||
friend class EpsCopyInputStream;
|
||||
};
|
||||
|
||||
inline void ArenaStringPtr::InitDefault() {
|
||||
tagged_ptr_ = TaggedStringPtr(&fixed_address_empty_string);
|
||||
}
|
||||
|
||||
inline void ArenaStringPtr::InitExternal(const std::string* str) {
|
||||
tagged_ptr_.SetDefault(str);
|
||||
}
|
||||
|
||||
inline void ArenaStringPtr::InitAllocated(std::string* str, Arena* arena) {
|
||||
if (arena != nullptr) {
|
||||
tagged_ptr_.SetMutableArena(str);
|
||||
arena->Own(str);
|
||||
} else {
|
||||
tagged_ptr_.SetAllocated(str);
|
||||
}
|
||||
}
|
||||
|
||||
inline void ArenaStringPtr::Set(const char* s, Arena* arena) {
|
||||
Set(ConstStringParam{s}, arena);
|
||||
}
|
||||
|
||||
inline void ArenaStringPtr::Set(const char* s, size_t n, Arena* arena) {
|
||||
Set(ConstStringParam{s, n}, arena);
|
||||
}
|
||||
|
||||
inline void ArenaStringPtr::SetBytes(ConstStringParam value, Arena* arena) {
|
||||
Set(value, arena);
|
||||
}
|
||||
|
||||
inline void ArenaStringPtr::SetBytes(std::string&& value, Arena* arena) {
|
||||
Set(std::move(value), arena);
|
||||
}
|
||||
|
||||
inline void ArenaStringPtr::SetBytes(const char* s, Arena* arena) {
|
||||
Set(s, arena);
|
||||
}
|
||||
|
||||
inline void ArenaStringPtr::SetBytes(const void* p, size_t n, Arena* arena) {
|
||||
Set(ConstStringParam{static_cast<const char*>(p), n}, arena);
|
||||
}
|
||||
|
||||
// Make sure rhs_arena allocated rhs, and lhs_arena allocated lhs.
|
||||
inline PROTOBUF_NDEBUG_INLINE void ArenaStringPtr::InternalSwap( //
|
||||
ArenaStringPtr* rhs, Arena* rhs_arena, //
|
||||
ArenaStringPtr* lhs, Arena* lhs_arena) {
|
||||
// Silence unused variable warnings in release buildls.
|
||||
(void)rhs_arena;
|
||||
(void)lhs_arena;
|
||||
std::swap(lhs->tagged_ptr_, rhs->tagged_ptr_);
|
||||
#ifdef PROTOBUF_FORCE_COPY_IN_SWAP
|
||||
auto force_realloc = [](ArenaStringPtr* p, Arena* arena) {
|
||||
if (p->IsDefault()) return;
|
||||
std::string* old_value = p->tagged_ptr_.Get();
|
||||
std::string* new_value =
|
||||
p->IsFixedSizeArena()
|
||||
? Arena::Create<std::string>(arena, *old_value)
|
||||
: Arena::Create<std::string>(arena, std::move(*old_value));
|
||||
if (arena == nullptr) {
|
||||
delete old_value;
|
||||
p->tagged_ptr_.SetAllocated(new_value);
|
||||
} else {
|
||||
p->tagged_ptr_.SetMutableArena(new_value);
|
||||
}
|
||||
};
|
||||
// Because, at this point, tagged_ptr_ has been swapped, arena should also be
|
||||
// swapped.
|
||||
force_realloc(lhs, rhs_arena);
|
||||
force_realloc(rhs, lhs_arena);
|
||||
#endif // PROTOBUF_FORCE_COPY_IN_SWAP
|
||||
}
|
||||
|
||||
inline void ArenaStringPtr::ClearNonDefaultToEmpty() {
|
||||
// Unconditionally mask away the tag.
|
||||
tagged_ptr_.Get()->clear();
|
||||
}
|
||||
|
||||
inline std::string* ArenaStringPtr::UnsafeMutablePointer() {
|
||||
GOOGLE_DCHECK(tagged_ptr_.IsMutable());
|
||||
GOOGLE_DCHECK(tagged_ptr_.Get() != nullptr);
|
||||
return tagged_ptr_.Get();
|
||||
}
|
||||
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_ARENASTRING_H__
|
||||
@@ -1,207 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_SRC_GOOGLE_PROTOBUF_ARENAZ_SAMPLER_H__
|
||||
#define GOOGLE_PROTOBUF_SRC_GOOGLE_PROTOBUF_ARENAZ_SAMPLER_H__
|
||||
|
||||
#include <atomic>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
#if defined(PROTOBUF_ARENAZ_SAMPLE)
|
||||
struct ThreadSafeArenaStats;
|
||||
void RecordResetSlow(ThreadSafeArenaStats* info);
|
||||
void RecordAllocateSlow(ThreadSafeArenaStats* info, size_t requested,
|
||||
size_t allocated, size_t wasted);
|
||||
// Stores information about a sampled thread safe arena. All mutations to this
|
||||
// *must* be made through `Record*` functions below. All reads from this *must*
|
||||
// only occur in the callback to `ThreadSafeArenazSampler::Iterate`.
|
||||
struct ThreadSafeArenaStats
|
||||
: public absl::profiling_internal::Sample<ThreadSafeArenaStats> {
|
||||
// Constructs the object but does not fill in any fields.
|
||||
ThreadSafeArenaStats();
|
||||
~ThreadSafeArenaStats();
|
||||
|
||||
// Puts the object into a clean state, fills in the logically `const` members,
|
||||
// blocking for any readers that are currently sampling the object.
|
||||
void PrepareForSampling() ABSL_EXCLUSIVE_LOCKS_REQUIRED(init_mu);
|
||||
|
||||
// These fields are mutated by the various Record* APIs and need to be
|
||||
// thread-safe.
|
||||
std::atomic<int> num_allocations;
|
||||
std::atomic<int> num_resets;
|
||||
std::atomic<size_t> bytes_requested;
|
||||
std::atomic<size_t> bytes_allocated;
|
||||
std::atomic<size_t> bytes_wasted;
|
||||
// Records the largest size an arena ever had. Maintained across resets.
|
||||
std::atomic<size_t> max_bytes_allocated;
|
||||
// Bit i when set to 1 indicates that a thread with tid % 63 = i accessed the
|
||||
// underlying arena. The field is maintained across resets.
|
||||
std::atomic<uint64_t> thread_ids;
|
||||
|
||||
// All of the fields below are set by `PrepareForSampling`, they must not
|
||||
// be mutated in `Record*` functions. They are logically `const` in that
|
||||
// sense. These are guarded by init_mu, but that is not externalized to
|
||||
// clients, who can only read them during
|
||||
// `ThreadSafeArenazSampler::Iterate` which will hold the lock.
|
||||
static constexpr int kMaxStackDepth = 64;
|
||||
int32_t depth;
|
||||
void* stack[kMaxStackDepth];
|
||||
static void RecordAllocateStats(ThreadSafeArenaStats* info, size_t requested,
|
||||
size_t allocated, size_t wasted) {
|
||||
if (PROTOBUF_PREDICT_TRUE(info == nullptr)) return;
|
||||
RecordAllocateSlow(info, requested, allocated, wasted);
|
||||
}
|
||||
};
|
||||
|
||||
ThreadSafeArenaStats* SampleSlow(int64_t* next_sample);
|
||||
void UnsampleSlow(ThreadSafeArenaStats* info);
|
||||
|
||||
class ThreadSafeArenaStatsHandle {
|
||||
public:
|
||||
explicit ThreadSafeArenaStatsHandle() = default;
|
||||
explicit ThreadSafeArenaStatsHandle(ThreadSafeArenaStats* info)
|
||||
: info_(info) {}
|
||||
|
||||
~ThreadSafeArenaStatsHandle() {
|
||||
if (PROTOBUF_PREDICT_TRUE(info_ == nullptr)) return;
|
||||
UnsampleSlow(info_);
|
||||
}
|
||||
|
||||
ThreadSafeArenaStatsHandle(ThreadSafeArenaStatsHandle&& other) noexcept
|
||||
: info_(absl::exchange(other.info_, nullptr)) {}
|
||||
|
||||
ThreadSafeArenaStatsHandle& operator=(
|
||||
ThreadSafeArenaStatsHandle&& other) noexcept {
|
||||
if (PROTOBUF_PREDICT_FALSE(info_ != nullptr)) {
|
||||
UnsampleSlow(info_);
|
||||
}
|
||||
info_ = absl::exchange(other.info_, nullptr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void RecordReset() {
|
||||
if (PROTOBUF_PREDICT_TRUE(info_ == nullptr)) return;
|
||||
RecordResetSlow(info_);
|
||||
}
|
||||
|
||||
ThreadSafeArenaStats* MutableStats() { return info_; }
|
||||
|
||||
friend void swap(ThreadSafeArenaStatsHandle& lhs,
|
||||
ThreadSafeArenaStatsHandle& rhs) {
|
||||
std::swap(lhs.info_, rhs.info_);
|
||||
}
|
||||
|
||||
friend class ThreadSafeArenaStatsHandlePeer;
|
||||
|
||||
private:
|
||||
ThreadSafeArenaStats* info_ = nullptr;
|
||||
};
|
||||
|
||||
using ThreadSafeArenazSampler =
|
||||
::absl::profiling_internal::SampleRecorder<ThreadSafeArenaStats>;
|
||||
|
||||
extern PROTOBUF_THREAD_LOCAL int64_t global_next_sample;
|
||||
|
||||
// Returns an RAII sampling handle that manages registration and unregistation
|
||||
// with the global sampler.
|
||||
inline ThreadSafeArenaStatsHandle Sample() {
|
||||
if (PROTOBUF_PREDICT_TRUE(--global_next_sample > 0)) {
|
||||
return ThreadSafeArenaStatsHandle(nullptr);
|
||||
}
|
||||
return ThreadSafeArenaStatsHandle(SampleSlow(&global_next_sample));
|
||||
}
|
||||
|
||||
#else
|
||||
struct ThreadSafeArenaStats {
|
||||
static void RecordAllocateStats(ThreadSafeArenaStats*, size_t /*requested*/,
|
||||
size_t /*allocated*/, size_t /*wasted*/) {}
|
||||
};
|
||||
|
||||
ThreadSafeArenaStats* SampleSlow(int64_t* next_sample);
|
||||
void UnsampleSlow(ThreadSafeArenaStats* info);
|
||||
|
||||
class ThreadSafeArenaStatsHandle {
|
||||
public:
|
||||
explicit ThreadSafeArenaStatsHandle() = default;
|
||||
explicit ThreadSafeArenaStatsHandle(ThreadSafeArenaStats*) {}
|
||||
|
||||
void RecordReset() {}
|
||||
|
||||
ThreadSafeArenaStats* MutableStats() { return nullptr; }
|
||||
|
||||
friend void swap(ThreadSafeArenaStatsHandle&, ThreadSafeArenaStatsHandle&) {}
|
||||
|
||||
private:
|
||||
friend class ThreadSafeArenaStatsHandlePeer;
|
||||
};
|
||||
|
||||
class ThreadSafeArenazSampler {
|
||||
public:
|
||||
void Unregister(ThreadSafeArenaStats*) {}
|
||||
void SetMaxSamples(int32_t) {}
|
||||
};
|
||||
|
||||
// Returns an RAII sampling handle that manages registration and unregistation
|
||||
// with the global sampler.
|
||||
inline ThreadSafeArenaStatsHandle Sample() {
|
||||
return ThreadSafeArenaStatsHandle(nullptr);
|
||||
}
|
||||
#endif // defined(PROTOBUF_ARENAZ_SAMPLE)
|
||||
|
||||
// Returns a global Sampler.
|
||||
ThreadSafeArenazSampler& GlobalThreadSafeArenazSampler();
|
||||
|
||||
// Enables or disables sampling for thread safe arenas.
|
||||
void SetThreadSafeArenazEnabled(bool enabled);
|
||||
|
||||
// Sets the rate at which thread safe arena will be sampled.
|
||||
void SetThreadSafeArenazSampleParameter(int32_t rate);
|
||||
|
||||
// Sets a soft max for the number of samples that will be kept.
|
||||
void SetThreadSafeArenazMaxSamples(int32_t max);
|
||||
|
||||
// Sets the current value for when arenas should be next sampled.
|
||||
void SetThreadSafeArenazGlobalNextSample(int64_t next_sample);
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
#endif // GOOGLE_PROTOBUF_SRC_PROTOBUF_ARENAZ_SAMPLER_H__
|
||||
@@ -1,338 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
//
|
||||
// This file is the public interface to the .proto file parser.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_IMPORTER_H__
|
||||
#define GOOGLE_PROTOBUF_COMPILER_IMPORTER_H__
|
||||
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <google/protobuf/compiler/parser.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/descriptor_database.h>
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
namespace io {
|
||||
class ZeroCopyInputStream;
|
||||
}
|
||||
|
||||
namespace compiler {
|
||||
|
||||
// Defined in this file.
|
||||
class Importer;
|
||||
class MultiFileErrorCollector;
|
||||
class SourceTree;
|
||||
class DiskSourceTree;
|
||||
|
||||
// TODO(kenton): Move all SourceTree stuff to a separate file?
|
||||
|
||||
// An implementation of DescriptorDatabase which loads files from a SourceTree
|
||||
// and parses them.
|
||||
//
|
||||
// Note: This class is not thread-safe since it maintains a table of source
|
||||
// code locations for error reporting. However, when a DescriptorPool wraps
|
||||
// a DescriptorDatabase, it uses mutex locking to make sure only one method
|
||||
// of the database is called at a time, even if the DescriptorPool is used
|
||||
// from multiple threads. Therefore, there is only a problem if you create
|
||||
// multiple DescriptorPools wrapping the same SourceTreeDescriptorDatabase
|
||||
// and use them from multiple threads.
|
||||
//
|
||||
// Note: This class does not implement FindFileContainingSymbol() or
|
||||
// FindFileContainingExtension(); these will always return false.
|
||||
class PROTOBUF_EXPORT SourceTreeDescriptorDatabase : public DescriptorDatabase {
|
||||
public:
|
||||
SourceTreeDescriptorDatabase(SourceTree* source_tree);
|
||||
|
||||
// If non-NULL, fallback_database will be checked if a file doesn't exist in
|
||||
// the specified source_tree.
|
||||
SourceTreeDescriptorDatabase(SourceTree* source_tree,
|
||||
DescriptorDatabase* fallback_database);
|
||||
~SourceTreeDescriptorDatabase() override;
|
||||
|
||||
// Instructs the SourceTreeDescriptorDatabase to report any parse errors
|
||||
// to the given MultiFileErrorCollector. This should be called before
|
||||
// parsing. error_collector must remain valid until either this method
|
||||
// is called again or the SourceTreeDescriptorDatabase is destroyed.
|
||||
void RecordErrorsTo(MultiFileErrorCollector* error_collector) {
|
||||
error_collector_ = error_collector;
|
||||
}
|
||||
|
||||
// Gets a DescriptorPool::ErrorCollector which records errors to the
|
||||
// MultiFileErrorCollector specified with RecordErrorsTo(). This collector
|
||||
// has the ability to determine exact line and column numbers of errors
|
||||
// from the information given to it by the DescriptorPool.
|
||||
DescriptorPool::ErrorCollector* GetValidationErrorCollector() {
|
||||
using_validation_error_collector_ = true;
|
||||
return &validation_error_collector_;
|
||||
}
|
||||
|
||||
// implements DescriptorDatabase -----------------------------------
|
||||
bool FindFileByName(const std::string& filename,
|
||||
FileDescriptorProto* output) override;
|
||||
bool FindFileContainingSymbol(const std::string& symbol_name,
|
||||
FileDescriptorProto* output) override;
|
||||
bool FindFileContainingExtension(const std::string& containing_type,
|
||||
int field_number,
|
||||
FileDescriptorProto* output) override;
|
||||
|
||||
private:
|
||||
class SingleFileErrorCollector;
|
||||
|
||||
SourceTree* source_tree_;
|
||||
DescriptorDatabase* fallback_database_;
|
||||
MultiFileErrorCollector* error_collector_;
|
||||
|
||||
class PROTOBUF_EXPORT ValidationErrorCollector
|
||||
: public DescriptorPool::ErrorCollector {
|
||||
public:
|
||||
ValidationErrorCollector(SourceTreeDescriptorDatabase* owner);
|
||||
~ValidationErrorCollector() override;
|
||||
|
||||
// implements ErrorCollector ---------------------------------------
|
||||
void AddError(const std::string& filename, const std::string& element_name,
|
||||
const Message* descriptor, ErrorLocation location,
|
||||
const std::string& message) override;
|
||||
|
||||
void AddWarning(const std::string& filename,
|
||||
const std::string& element_name, const Message* descriptor,
|
||||
ErrorLocation location,
|
||||
const std::string& message) override;
|
||||
|
||||
private:
|
||||
SourceTreeDescriptorDatabase* owner_;
|
||||
};
|
||||
friend class ValidationErrorCollector;
|
||||
|
||||
bool using_validation_error_collector_;
|
||||
SourceLocationTable source_locations_;
|
||||
ValidationErrorCollector validation_error_collector_;
|
||||
};
|
||||
|
||||
// Simple interface for parsing .proto files. This wraps the process
|
||||
// of opening the file, parsing it with a Parser, recursively parsing all its
|
||||
// imports, and then cross-linking the results to produce a FileDescriptor.
|
||||
//
|
||||
// This is really just a thin wrapper around SourceTreeDescriptorDatabase.
|
||||
// You may find that SourceTreeDescriptorDatabase is more flexible.
|
||||
//
|
||||
// TODO(kenton): I feel like this class is not well-named.
|
||||
class PROTOBUF_EXPORT Importer {
|
||||
public:
|
||||
Importer(SourceTree* source_tree, MultiFileErrorCollector* error_collector);
|
||||
~Importer();
|
||||
|
||||
// Import the given file and build a FileDescriptor representing it. If
|
||||
// the file is already in the DescriptorPool, the existing FileDescriptor
|
||||
// will be returned. The FileDescriptor is property of the DescriptorPool,
|
||||
// and will remain valid until it is destroyed. If any errors occur, they
|
||||
// will be reported using the error collector and Import() will return NULL.
|
||||
//
|
||||
// A particular Importer object will only report errors for a particular
|
||||
// file once. All future attempts to import the same file will return NULL
|
||||
// without reporting any errors. The idea is that you might want to import
|
||||
// a lot of files without seeing the same errors over and over again. If
|
||||
// you want to see errors for the same files repeatedly, you can use a
|
||||
// separate Importer object to import each one (but use the same
|
||||
// DescriptorPool so that they can be cross-linked).
|
||||
const FileDescriptor* Import(const std::string& filename);
|
||||
|
||||
// The DescriptorPool in which all imported FileDescriptors and their
|
||||
// contents are stored.
|
||||
inline const DescriptorPool* pool() const { return &pool_; }
|
||||
|
||||
void AddUnusedImportTrackFile(const std::string& file_name,
|
||||
bool is_error = false);
|
||||
void ClearUnusedImportTrackFiles();
|
||||
|
||||
|
||||
private:
|
||||
SourceTreeDescriptorDatabase database_;
|
||||
DescriptorPool pool_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Importer);
|
||||
};
|
||||
|
||||
// If the importer encounters problems while trying to import the proto files,
|
||||
// it reports them to a MultiFileErrorCollector.
|
||||
class PROTOBUF_EXPORT MultiFileErrorCollector {
|
||||
public:
|
||||
inline MultiFileErrorCollector() {}
|
||||
virtual ~MultiFileErrorCollector();
|
||||
|
||||
// Line and column numbers are zero-based. A line number of -1 indicates
|
||||
// an error with the entire file (e.g. "not found").
|
||||
virtual void AddError(const std::string& filename, int line, int column,
|
||||
const std::string& message) = 0;
|
||||
|
||||
virtual void AddWarning(const std::string& /* filename */, int /* line */,
|
||||
int /* column */, const std::string& /* message */) {}
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MultiFileErrorCollector);
|
||||
};
|
||||
|
||||
// Abstract interface which represents a directory tree containing proto files.
|
||||
// Used by the default implementation of Importer to resolve import statements
|
||||
// Most users will probably want to use the DiskSourceTree implementation,
|
||||
// below.
|
||||
class PROTOBUF_EXPORT SourceTree {
|
||||
public:
|
||||
inline SourceTree() {}
|
||||
virtual ~SourceTree();
|
||||
|
||||
// Open the given file and return a stream that reads it, or NULL if not
|
||||
// found. The caller takes ownership of the returned object. The filename
|
||||
// must be a path relative to the root of the source tree and must not
|
||||
// contain "." or ".." components.
|
||||
virtual io::ZeroCopyInputStream* Open(const std::string& filename) = 0;
|
||||
|
||||
// If Open() returns NULL, calling this method immediately will return an
|
||||
// description of the error.
|
||||
// Subclasses should implement this method and return a meaningful value for
|
||||
// better error reporting.
|
||||
// TODO(xiaofeng): change this to a pure virtual function.
|
||||
virtual std::string GetLastErrorMessage();
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SourceTree);
|
||||
};
|
||||
|
||||
// An implementation of SourceTree which loads files from locations on disk.
|
||||
// Multiple mappings can be set up to map locations in the DiskSourceTree to
|
||||
// locations in the physical filesystem.
|
||||
class PROTOBUF_EXPORT DiskSourceTree : public SourceTree {
|
||||
public:
|
||||
DiskSourceTree();
|
||||
~DiskSourceTree() override;
|
||||
|
||||
// Map a path on disk to a location in the SourceTree. The path may be
|
||||
// either a file or a directory. If it is a directory, the entire tree
|
||||
// under it will be mapped to the given virtual location. To map a directory
|
||||
// to the root of the source tree, pass an empty string for virtual_path.
|
||||
//
|
||||
// If multiple mapped paths apply when opening a file, they will be searched
|
||||
// in order. For example, if you do:
|
||||
// MapPath("bar", "foo/bar");
|
||||
// MapPath("", "baz");
|
||||
// and then you do:
|
||||
// Open("bar/qux");
|
||||
// the DiskSourceTree will first try to open foo/bar/qux, then baz/bar/qux,
|
||||
// returning the first one that opens successfully.
|
||||
//
|
||||
// disk_path may be an absolute path or relative to the current directory,
|
||||
// just like a path you'd pass to open().
|
||||
void MapPath(const std::string& virtual_path, const std::string& disk_path);
|
||||
|
||||
// Return type for DiskFileToVirtualFile().
|
||||
enum DiskFileToVirtualFileResult {
|
||||
SUCCESS,
|
||||
SHADOWED,
|
||||
CANNOT_OPEN,
|
||||
NO_MAPPING
|
||||
};
|
||||
|
||||
// Given a path to a file on disk, find a virtual path mapping to that
|
||||
// file. The first mapping created with MapPath() whose disk_path contains
|
||||
// the filename is used. However, that virtual path may not actually be
|
||||
// usable to open the given file. Possible return values are:
|
||||
// * SUCCESS: The mapping was found. *virtual_file is filled in so that
|
||||
// calling Open(*virtual_file) will open the file named by disk_file.
|
||||
// * SHADOWED: A mapping was found, but using Open() to open this virtual
|
||||
// path will end up returning some different file. This is because some
|
||||
// other mapping with a higher precedence also matches this virtual path
|
||||
// and maps it to a different file that exists on disk. *virtual_file
|
||||
// is filled in as it would be in the SUCCESS case. *shadowing_disk_file
|
||||
// is filled in with the disk path of the file which would be opened if
|
||||
// you were to call Open(*virtual_file).
|
||||
// * CANNOT_OPEN: The mapping was found and was not shadowed, but the
|
||||
// file specified cannot be opened. When this value is returned,
|
||||
// errno will indicate the reason the file cannot be opened. *virtual_file
|
||||
// will be set to the virtual path as in the SUCCESS case, even though
|
||||
// it is not useful.
|
||||
// * NO_MAPPING: Indicates that no mapping was found which contains this
|
||||
// file.
|
||||
DiskFileToVirtualFileResult DiskFileToVirtualFile(
|
||||
const std::string& disk_file, std::string* virtual_file,
|
||||
std::string* shadowing_disk_file);
|
||||
|
||||
// Given a virtual path, find the path to the file on disk.
|
||||
// Return true and update disk_file with the on-disk path if the file exists.
|
||||
// Return false and leave disk_file untouched if the file doesn't exist.
|
||||
bool VirtualFileToDiskFile(const std::string& virtual_file,
|
||||
std::string* disk_file);
|
||||
|
||||
// implements SourceTree -------------------------------------------
|
||||
io::ZeroCopyInputStream* Open(const std::string& filename) override;
|
||||
|
||||
std::string GetLastErrorMessage() override;
|
||||
|
||||
private:
|
||||
struct Mapping {
|
||||
std::string virtual_path;
|
||||
std::string disk_path;
|
||||
|
||||
inline Mapping(const std::string& virtual_path_param,
|
||||
const std::string& disk_path_param)
|
||||
: virtual_path(virtual_path_param), disk_path(disk_path_param) {}
|
||||
};
|
||||
std::vector<Mapping> mappings_;
|
||||
std::string last_error_message_;
|
||||
|
||||
// Like Open(), but returns the on-disk path in disk_file if disk_file is
|
||||
// non-NULL and the file could be successfully opened.
|
||||
io::ZeroCopyInputStream* OpenVirtualFile(const std::string& virtual_file,
|
||||
std::string* disk_file);
|
||||
|
||||
// Like Open() but given the actual on-disk path.
|
||||
io::ZeroCopyInputStream* OpenDiskFile(const std::string& filename);
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DiskSourceTree);
|
||||
};
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_IMPORTER_H__
|
||||
@@ -1,602 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
//
|
||||
// Implements parsing of .proto files to FileDescriptorProtos.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_PARSER_H__
|
||||
#define GOOGLE_PROTOBUF_COMPILER_PARSER_H__
|
||||
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/descriptor.pb.h>
|
||||
#include <google/protobuf/io/tokenizer.h>
|
||||
#include <google/protobuf/repeated_field.h>
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
class Message;
|
||||
|
||||
namespace compiler {
|
||||
|
||||
// Defined in this file.
|
||||
class Parser;
|
||||
class SourceLocationTable;
|
||||
|
||||
// Implements parsing of protocol definitions (such as .proto files).
|
||||
//
|
||||
// Note that most users will be more interested in the Importer class.
|
||||
// Parser is a lower-level class which simply converts a single .proto file
|
||||
// to a FileDescriptorProto. It does not resolve import directives or perform
|
||||
// many other kinds of validation needed to construct a complete
|
||||
// FileDescriptor.
|
||||
class PROTOBUF_EXPORT Parser {
|
||||
public:
|
||||
Parser();
|
||||
~Parser();
|
||||
|
||||
// Parse the entire input and construct a FileDescriptorProto representing
|
||||
// it. Returns true if no errors occurred, false otherwise.
|
||||
bool Parse(io::Tokenizer* input, FileDescriptorProto* file);
|
||||
|
||||
// Optional features:
|
||||
|
||||
// DEPRECATED: New code should use the SourceCodeInfo embedded in the
|
||||
// FileDescriptorProto.
|
||||
//
|
||||
// Requests that locations of certain definitions be recorded to the given
|
||||
// SourceLocationTable while parsing. This can be used to look up exact line
|
||||
// and column numbers for errors reported by DescriptorPool during validation.
|
||||
// Set to NULL (the default) to discard source location information.
|
||||
void RecordSourceLocationsTo(SourceLocationTable* location_table) {
|
||||
source_location_table_ = location_table;
|
||||
}
|
||||
|
||||
// Requests that errors be recorded to the given ErrorCollector while
|
||||
// parsing. Set to NULL (the default) to discard error messages.
|
||||
void RecordErrorsTo(io::ErrorCollector* error_collector) {
|
||||
error_collector_ = error_collector;
|
||||
}
|
||||
|
||||
// Returns the identifier used in the "syntax = " declaration, if one was
|
||||
// seen during the last call to Parse(), or the empty string otherwise.
|
||||
const std::string& GetSyntaxIdentifier() { return syntax_identifier_; }
|
||||
|
||||
// If set true, input files will be required to begin with a syntax
|
||||
// identifier. Otherwise, files may omit this. If a syntax identifier
|
||||
// is provided, it must be 'syntax = "proto2";' and must appear at the
|
||||
// top of this file regardless of whether or not it was required.
|
||||
void SetRequireSyntaxIdentifier(bool value) {
|
||||
require_syntax_identifier_ = value;
|
||||
}
|
||||
|
||||
// Call SetStopAfterSyntaxIdentifier(true) to tell the parser to stop
|
||||
// parsing as soon as it has seen the syntax identifier, or lack thereof.
|
||||
// This is useful for quickly identifying the syntax of the file without
|
||||
// parsing the whole thing. If this is enabled, no error will be recorded
|
||||
// if the syntax identifier is something other than "proto2" (since
|
||||
// presumably the caller intends to deal with that), but other kinds of
|
||||
// errors (e.g. parse errors) will still be reported. When this is enabled,
|
||||
// you may pass a NULL FileDescriptorProto to Parse().
|
||||
void SetStopAfterSyntaxIdentifier(bool value) {
|
||||
stop_after_syntax_identifier_ = value;
|
||||
}
|
||||
|
||||
private:
|
||||
class LocationRecorder;
|
||||
struct MapField;
|
||||
|
||||
// =================================================================
|
||||
// Error recovery helpers
|
||||
|
||||
// Consume the rest of the current statement. This consumes tokens
|
||||
// until it sees one of:
|
||||
// ';' Consumes the token and returns.
|
||||
// '{' Consumes the brace then calls SkipRestOfBlock().
|
||||
// '}' Returns without consuming.
|
||||
// EOF Returns (can't consume).
|
||||
// The Parser often calls SkipStatement() after encountering a syntax
|
||||
// error. This allows it to go on parsing the following lines, allowing
|
||||
// it to report more than just one error in the file.
|
||||
void SkipStatement();
|
||||
|
||||
// Consume the rest of the current block, including nested blocks,
|
||||
// ending after the closing '}' is encountered and consumed, or at EOF.
|
||||
void SkipRestOfBlock();
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// Single-token consuming helpers
|
||||
//
|
||||
// These make parsing code more readable.
|
||||
|
||||
// True if the current token is TYPE_END.
|
||||
inline bool AtEnd();
|
||||
|
||||
// True if the next token matches the given text.
|
||||
inline bool LookingAt(const char* text);
|
||||
// True if the next token is of the given type.
|
||||
inline bool LookingAtType(io::Tokenizer::TokenType token_type);
|
||||
|
||||
// If the next token exactly matches the text given, consume it and return
|
||||
// true. Otherwise, return false without logging an error.
|
||||
bool TryConsume(const char* text);
|
||||
|
||||
// These attempt to read some kind of token from the input. If successful,
|
||||
// they return true. Otherwise they return false and add the given error
|
||||
// to the error list.
|
||||
|
||||
// Consume a token with the exact text given.
|
||||
bool Consume(const char* text, const char* error);
|
||||
// Same as above, but automatically generates the error "Expected \"text\".",
|
||||
// where "text" is the expected token text.
|
||||
bool Consume(const char* text);
|
||||
// Consume a token of type IDENTIFIER and store its text in "output".
|
||||
bool ConsumeIdentifier(std::string* output, const char* error);
|
||||
// Consume an integer and store its value in "output".
|
||||
bool ConsumeInteger(int* output, const char* error);
|
||||
// Consume a signed integer and store its value in "output".
|
||||
bool ConsumeSignedInteger(int* output, const char* error);
|
||||
// Consume a 64-bit integer and store its value in "output". If the value
|
||||
// is greater than max_value, an error will be reported.
|
||||
bool ConsumeInteger64(uint64_t max_value, uint64_t* output,
|
||||
const char* error);
|
||||
// Consume a number and store its value in "output". This will accept
|
||||
// tokens of either INTEGER or FLOAT type.
|
||||
bool ConsumeNumber(double* output, const char* error);
|
||||
// Consume a string literal and store its (unescaped) value in "output".
|
||||
bool ConsumeString(std::string* output, const char* error);
|
||||
|
||||
// Consume a token representing the end of the statement. Comments between
|
||||
// this token and the next will be harvested for documentation. The given
|
||||
// LocationRecorder should refer to the declaration that was just parsed;
|
||||
// it will be populated with these comments.
|
||||
//
|
||||
// TODO(kenton): The LocationRecorder is const because historically locations
|
||||
// have been passed around by const reference, for no particularly good
|
||||
// reason. We should probably go through and change them all to mutable
|
||||
// pointer to make this more intuitive.
|
||||
bool TryConsumeEndOfDeclaration(const char* text,
|
||||
const LocationRecorder* location);
|
||||
bool TryConsumeEndOfDeclarationFinishScope(const char* text,
|
||||
const LocationRecorder* location);
|
||||
|
||||
bool ConsumeEndOfDeclaration(const char* text,
|
||||
const LocationRecorder* location);
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// Error logging helpers
|
||||
|
||||
// Invokes error_collector_->AddError(), if error_collector_ is not NULL.
|
||||
void AddError(int line, int column, const std::string& error);
|
||||
|
||||
// Invokes error_collector_->AddError() with the line and column number
|
||||
// of the current token.
|
||||
void AddError(const std::string& error);
|
||||
|
||||
// Invokes error_collector_->AddWarning() with the line and column number
|
||||
// of the current token.
|
||||
void AddWarning(const std::string& warning);
|
||||
|
||||
// Records a location in the SourceCodeInfo.location table (see
|
||||
// descriptor.proto). We use RAII to ensure that the start and end locations
|
||||
// are recorded -- the constructor records the start location and the
|
||||
// destructor records the end location. Since the parser is
|
||||
// recursive-descent, this works out beautifully.
|
||||
class PROTOBUF_EXPORT LocationRecorder {
|
||||
public:
|
||||
// Construct the file's "root" location.
|
||||
LocationRecorder(Parser* parser);
|
||||
|
||||
// Construct a location that represents a declaration nested within the
|
||||
// given parent. E.g. a field's location is nested within the location
|
||||
// for a message type. The parent's path will be copied, so you should
|
||||
// call AddPath() only to add the path components leading from the parent
|
||||
// to the child (as opposed to leading from the root to the child).
|
||||
LocationRecorder(const LocationRecorder& parent);
|
||||
|
||||
// Convenience constructors that call AddPath() one or two times.
|
||||
LocationRecorder(const LocationRecorder& parent, int path1);
|
||||
LocationRecorder(const LocationRecorder& parent, int path1, int path2);
|
||||
|
||||
// Creates a recorder that generates locations into given source code info.
|
||||
LocationRecorder(const LocationRecorder& parent, int path1,
|
||||
SourceCodeInfo* source_code_info);
|
||||
|
||||
~LocationRecorder();
|
||||
|
||||
// Add a path component. See SourceCodeInfo.Location.path in
|
||||
// descriptor.proto.
|
||||
void AddPath(int path_component);
|
||||
|
||||
// By default the location is considered to start at the current token at
|
||||
// the time the LocationRecorder is created. StartAt() sets the start
|
||||
// location to the given token instead.
|
||||
void StartAt(const io::Tokenizer::Token& token);
|
||||
|
||||
// Start at the same location as some other LocationRecorder.
|
||||
void StartAt(const LocationRecorder& other);
|
||||
|
||||
// By default the location is considered to end at the previous token at
|
||||
// the time the LocationRecorder is destroyed. EndAt() sets the end
|
||||
// location to the given token instead.
|
||||
void EndAt(const io::Tokenizer::Token& token);
|
||||
|
||||
// Records the start point of this location to the SourceLocationTable that
|
||||
// was passed to RecordSourceLocationsTo(), if any. SourceLocationTable
|
||||
// is an older way of keeping track of source locations which is still
|
||||
// used in some places.
|
||||
void RecordLegacyLocation(
|
||||
const Message* descriptor,
|
||||
DescriptorPool::ErrorCollector::ErrorLocation location);
|
||||
void RecordLegacyImportLocation(const Message* descriptor,
|
||||
const std::string& name);
|
||||
|
||||
// Returns the number of path components in the recorder's current location.
|
||||
int CurrentPathSize() const;
|
||||
|
||||
// Attaches leading and trailing comments to the location. The two strings
|
||||
// will be swapped into place, so after this is called *leading and
|
||||
// *trailing will be empty.
|
||||
//
|
||||
// TODO(kenton): See comment on TryConsumeEndOfDeclaration(), above, for
|
||||
// why this is const.
|
||||
void AttachComments(std::string* leading, std::string* trailing,
|
||||
std::vector<std::string>* detached_comments) const;
|
||||
|
||||
private:
|
||||
Parser* parser_;
|
||||
SourceCodeInfo* source_code_info_;
|
||||
SourceCodeInfo::Location* location_;
|
||||
|
||||
void Init(const LocationRecorder& parent, SourceCodeInfo* source_code_info);
|
||||
};
|
||||
|
||||
// =================================================================
|
||||
// Parsers for various language constructs
|
||||
|
||||
// Parses the "syntax = \"proto2\";" line at the top of the file. Returns
|
||||
// false if it failed to parse or if the syntax identifier was not
|
||||
// recognized.
|
||||
bool ParseSyntaxIdentifier(const LocationRecorder& parent);
|
||||
|
||||
// These methods parse various individual bits of code. They return
|
||||
// false if they completely fail to parse the construct. In this case,
|
||||
// it is probably necessary to skip the rest of the statement to recover.
|
||||
// However, if these methods return true, it does NOT mean that there
|
||||
// were no errors; only that there were no *syntax* errors. For instance,
|
||||
// if a service method is defined using proper syntax but uses a primitive
|
||||
// type as its input or output, ParseMethodField() still returns true
|
||||
// and only reports the error by calling AddError(). In practice, this
|
||||
// makes logic much simpler for the caller.
|
||||
|
||||
// Parse a top-level message, enum, service, etc.
|
||||
bool ParseTopLevelStatement(FileDescriptorProto* file,
|
||||
const LocationRecorder& root_location);
|
||||
|
||||
// Parse various language high-level language construrcts.
|
||||
bool ParseMessageDefinition(DescriptorProto* message,
|
||||
const LocationRecorder& message_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
bool ParseEnumDefinition(EnumDescriptorProto* enum_type,
|
||||
const LocationRecorder& enum_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
bool ParseServiceDefinition(ServiceDescriptorProto* service,
|
||||
const LocationRecorder& service_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
bool ParsePackage(FileDescriptorProto* file,
|
||||
const LocationRecorder& root_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
bool ParseImport(RepeatedPtrField<std::string>* dependency,
|
||||
RepeatedField<int32_t>* public_dependency,
|
||||
RepeatedField<int32_t>* weak_dependency,
|
||||
const LocationRecorder& root_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
|
||||
// These methods parse the contents of a message, enum, or service type and
|
||||
// add them to the given object. They consume the entire block including
|
||||
// the beginning and ending brace.
|
||||
bool ParseMessageBlock(DescriptorProto* message,
|
||||
const LocationRecorder& message_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
bool ParseEnumBlock(EnumDescriptorProto* enum_type,
|
||||
const LocationRecorder& enum_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
bool ParseServiceBlock(ServiceDescriptorProto* service,
|
||||
const LocationRecorder& service_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
|
||||
// Parse one statement within a message, enum, or service block, including
|
||||
// final semicolon.
|
||||
bool ParseMessageStatement(DescriptorProto* message,
|
||||
const LocationRecorder& message_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
bool ParseEnumStatement(EnumDescriptorProto* message,
|
||||
const LocationRecorder& enum_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
bool ParseServiceStatement(ServiceDescriptorProto* message,
|
||||
const LocationRecorder& service_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
|
||||
// Parse a field of a message. If the field is a group, its type will be
|
||||
// added to "messages".
|
||||
//
|
||||
// parent_location and location_field_number_for_nested_type are needed when
|
||||
// parsing groups -- we need to generate a nested message type within the
|
||||
// parent and record its location accordingly. Since the parent could be
|
||||
// either a FileDescriptorProto or a DescriptorProto, we must pass in the
|
||||
// correct field number to use.
|
||||
bool ParseMessageField(FieldDescriptorProto* field,
|
||||
RepeatedPtrField<DescriptorProto>* messages,
|
||||
const LocationRecorder& parent_location,
|
||||
int location_field_number_for_nested_type,
|
||||
const LocationRecorder& field_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
|
||||
// Like ParseMessageField() but expects the label has already been filled in
|
||||
// by the caller.
|
||||
bool ParseMessageFieldNoLabel(FieldDescriptorProto* field,
|
||||
RepeatedPtrField<DescriptorProto>* messages,
|
||||
const LocationRecorder& parent_location,
|
||||
int location_field_number_for_nested_type,
|
||||
const LocationRecorder& field_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
|
||||
bool ParseMapType(MapField* map_field, FieldDescriptorProto* field,
|
||||
LocationRecorder& type_name_location);
|
||||
|
||||
// Parse an "extensions" declaration.
|
||||
bool ParseExtensions(DescriptorProto* message,
|
||||
const LocationRecorder& extensions_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
|
||||
// Parse a "reserved" declaration.
|
||||
bool ParseReserved(DescriptorProto* message,
|
||||
const LocationRecorder& message_location);
|
||||
bool ParseReservedNames(DescriptorProto* message,
|
||||
const LocationRecorder& parent_location);
|
||||
bool ParseReservedNumbers(DescriptorProto* message,
|
||||
const LocationRecorder& parent_location);
|
||||
bool ParseReserved(EnumDescriptorProto* message,
|
||||
const LocationRecorder& message_location);
|
||||
bool ParseReservedNames(EnumDescriptorProto* message,
|
||||
const LocationRecorder& parent_location);
|
||||
bool ParseReservedNumbers(EnumDescriptorProto* message,
|
||||
const LocationRecorder& parent_location);
|
||||
|
||||
// Parse an "extend" declaration. (See also comments for
|
||||
// ParseMessageField().)
|
||||
bool ParseExtend(RepeatedPtrField<FieldDescriptorProto>* extensions,
|
||||
RepeatedPtrField<DescriptorProto>* messages,
|
||||
const LocationRecorder& parent_location,
|
||||
int location_field_number_for_nested_type,
|
||||
const LocationRecorder& extend_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
|
||||
// Parse a "oneof" declaration. The caller is responsible for setting
|
||||
// oneof_decl->label() since it will have had to parse the label before it
|
||||
// knew it was parsing a oneof.
|
||||
bool ParseOneof(OneofDescriptorProto* oneof_decl,
|
||||
DescriptorProto* containing_type, int oneof_index,
|
||||
const LocationRecorder& oneof_location,
|
||||
const LocationRecorder& containing_type_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
|
||||
// Parse a single enum value within an enum block.
|
||||
bool ParseEnumConstant(EnumValueDescriptorProto* enum_value,
|
||||
const LocationRecorder& enum_value_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
|
||||
// Parse enum constant options, i.e. the list in square brackets at the end
|
||||
// of the enum constant value definition.
|
||||
bool ParseEnumConstantOptions(EnumValueDescriptorProto* value,
|
||||
const LocationRecorder& enum_value_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
|
||||
// Parse a single method within a service definition.
|
||||
bool ParseServiceMethod(MethodDescriptorProto* method,
|
||||
const LocationRecorder& method_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
|
||||
// Parse options of a single method or stream.
|
||||
bool ParseMethodOptions(const LocationRecorder& parent_location,
|
||||
const FileDescriptorProto* containing_file,
|
||||
const int optionsFieldNumber,
|
||||
Message* mutable_options);
|
||||
|
||||
// Parse "required", "optional", or "repeated" and fill in "label"
|
||||
// with the value. Returns true if such a label is consumed.
|
||||
bool ParseLabel(FieldDescriptorProto::Label* label,
|
||||
const LocationRecorder& field_location);
|
||||
|
||||
// Parse a type name and fill in "type" (if it is a primitive) or
|
||||
// "type_name" (if it is not) with the type parsed.
|
||||
bool ParseType(FieldDescriptorProto::Type* type, std::string* type_name);
|
||||
// Parse a user-defined type and fill in "type_name" with the name.
|
||||
// If a primitive type is named, it is treated as an error.
|
||||
bool ParseUserDefinedType(std::string* type_name);
|
||||
|
||||
// Parses field options, i.e. the stuff in square brackets at the end
|
||||
// of a field definition. Also parses default value.
|
||||
bool ParseFieldOptions(FieldDescriptorProto* field,
|
||||
const LocationRecorder& field_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
|
||||
// Parse the "default" option. This needs special handling because its
|
||||
// type is the field's type.
|
||||
bool ParseDefaultAssignment(FieldDescriptorProto* field,
|
||||
const LocationRecorder& field_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
|
||||
bool ParseJsonName(FieldDescriptorProto* field,
|
||||
const LocationRecorder& field_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
|
||||
enum OptionStyle {
|
||||
OPTION_ASSIGNMENT, // just "name = value"
|
||||
OPTION_STATEMENT // "option name = value;"
|
||||
};
|
||||
|
||||
// Parse a single option name/value pair, e.g. "ctype = CORD". The name
|
||||
// identifies a field of the given Message, and the value of that field
|
||||
// is set to the parsed value.
|
||||
bool ParseOption(Message* options, const LocationRecorder& options_location,
|
||||
const FileDescriptorProto* containing_file,
|
||||
OptionStyle style);
|
||||
|
||||
// Parses a single part of a multipart option name. A multipart name consists
|
||||
// of names separated by dots. Each name is either an identifier or a series
|
||||
// of identifiers separated by dots and enclosed in parentheses. E.g.,
|
||||
// "foo.(bar.baz).moo".
|
||||
bool ParseOptionNamePart(UninterpretedOption* uninterpreted_option,
|
||||
const LocationRecorder& part_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
|
||||
// Parses a string surrounded by balanced braces. Strips off the outer
|
||||
// braces and stores the enclosed string in *value.
|
||||
// E.g.,
|
||||
// { foo } *value gets 'foo'
|
||||
// { foo { bar: box } } *value gets 'foo { bar: box }'
|
||||
// {} *value gets ''
|
||||
//
|
||||
// REQUIRES: LookingAt("{")
|
||||
// When finished successfully, we are looking at the first token past
|
||||
// the ending brace.
|
||||
bool ParseUninterpretedBlock(std::string* value);
|
||||
|
||||
struct MapField {
|
||||
// Whether the field is a map field.
|
||||
bool is_map_field;
|
||||
// The types of the key and value if they are primitive types.
|
||||
FieldDescriptorProto::Type key_type;
|
||||
FieldDescriptorProto::Type value_type;
|
||||
// Or the type names string if the types are customized types.
|
||||
std::string key_type_name;
|
||||
std::string value_type_name;
|
||||
|
||||
MapField() : is_map_field(false) {}
|
||||
};
|
||||
// Desugar the map syntax to generate a nested map entry message.
|
||||
void GenerateMapEntry(const MapField& map_field, FieldDescriptorProto* field,
|
||||
RepeatedPtrField<DescriptorProto>* messages);
|
||||
|
||||
// Whether fields without label default to optional fields.
|
||||
bool DefaultToOptionalFields() const {
|
||||
return syntax_identifier_ == "proto3";
|
||||
}
|
||||
|
||||
bool ValidateEnum(const EnumDescriptorProto* proto);
|
||||
|
||||
// =================================================================
|
||||
|
||||
io::Tokenizer* input_;
|
||||
io::ErrorCollector* error_collector_;
|
||||
SourceCodeInfo* source_code_info_;
|
||||
SourceLocationTable* source_location_table_; // legacy
|
||||
bool had_errors_;
|
||||
bool require_syntax_identifier_;
|
||||
bool stop_after_syntax_identifier_;
|
||||
std::string syntax_identifier_;
|
||||
|
||||
// Leading doc comments for the next declaration. These are not complete
|
||||
// yet; use ConsumeEndOfDeclaration() to get the complete comments.
|
||||
std::string upcoming_doc_comments_;
|
||||
|
||||
// Detached comments are not connected to any syntax entities. Elements in
|
||||
// this vector are paragraphs of comments separated by empty lines. The
|
||||
// detached comments will be put into the leading_detached_comments field for
|
||||
// the next element (See SourceCodeInfo.Location in descriptor.proto), when
|
||||
// ConsumeEndOfDeclaration() is called.
|
||||
std::vector<std::string> upcoming_detached_comments_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Parser);
|
||||
};
|
||||
|
||||
// A table mapping (descriptor, ErrorLocation) pairs -- as reported by
|
||||
// DescriptorPool when validating descriptors -- to line and column numbers
|
||||
// within the original source code.
|
||||
//
|
||||
// This is semi-obsolete: FileDescriptorProto.source_code_info now contains
|
||||
// far more complete information about source locations. However, as of this
|
||||
// writing you still need to use SourceLocationTable when integrating with
|
||||
// DescriptorPool.
|
||||
class PROTOBUF_EXPORT SourceLocationTable {
|
||||
public:
|
||||
SourceLocationTable();
|
||||
~SourceLocationTable();
|
||||
|
||||
// Finds the precise location of the given error and fills in *line and
|
||||
// *column with the line and column numbers. If not found, sets *line to
|
||||
// -1 and *column to 0 (since line = -1 is used to mean "error has no exact
|
||||
// location" in the ErrorCollector interface). Returns true if found, false
|
||||
// otherwise.
|
||||
bool Find(const Message* descriptor,
|
||||
DescriptorPool::ErrorCollector::ErrorLocation location, int* line,
|
||||
int* column) const;
|
||||
bool FindImport(const Message* descriptor, const std::string& name, int* line,
|
||||
int* column) const;
|
||||
|
||||
// Adds a location to the table.
|
||||
void Add(const Message* descriptor,
|
||||
DescriptorPool::ErrorCollector::ErrorLocation location, int line,
|
||||
int column);
|
||||
void AddImport(const Message* descriptor, const std::string& name, int line,
|
||||
int column);
|
||||
|
||||
// Clears the contents of the table.
|
||||
void Clear();
|
||||
|
||||
private:
|
||||
typedef std::map<
|
||||
std::pair<const Message*, DescriptorPool::ErrorCollector::ErrorLocation>,
|
||||
std::pair<int, int> >
|
||||
LocationMap;
|
||||
LocationMap location_map_;
|
||||
std::map<std::pair<const Message*, std::string>, std::pair<int, int> >
|
||||
import_location_map_;
|
||||
};
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_PARSER_H__
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,398 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
//
|
||||
// Interface for manipulating databases of descriptors.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_DESCRIPTOR_DATABASE_H__
|
||||
#define GOOGLE_PROTOBUF_DESCRIPTOR_DATABASE_H__
|
||||
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
#ifdef SWIG
|
||||
#error "You cannot SWIG proto headers"
|
||||
#endif
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
// Defined in this file.
|
||||
class DescriptorDatabase;
|
||||
class SimpleDescriptorDatabase;
|
||||
class EncodedDescriptorDatabase;
|
||||
class DescriptorPoolDatabase;
|
||||
class MergedDescriptorDatabase;
|
||||
|
||||
// Abstract interface for a database of descriptors.
|
||||
//
|
||||
// This is useful if you want to create a DescriptorPool which loads
|
||||
// descriptors on-demand from some sort of large database. If the database
|
||||
// is large, it may be inefficient to enumerate every .proto file inside it
|
||||
// calling DescriptorPool::BuildFile() for each one. Instead, a DescriptorPool
|
||||
// can be created which wraps a DescriptorDatabase and only builds particular
|
||||
// descriptors when they are needed.
|
||||
class PROTOBUF_EXPORT DescriptorDatabase {
|
||||
public:
|
||||
inline DescriptorDatabase() {}
|
||||
virtual ~DescriptorDatabase();
|
||||
|
||||
// Find a file by file name. Fills in in *output and returns true if found.
|
||||
// Otherwise, returns false, leaving the contents of *output undefined.
|
||||
virtual bool FindFileByName(const std::string& filename,
|
||||
FileDescriptorProto* output) = 0;
|
||||
|
||||
// Find the file that declares the given fully-qualified symbol name.
|
||||
// If found, fills in *output and returns true, otherwise returns false
|
||||
// and leaves *output undefined.
|
||||
virtual bool FindFileContainingSymbol(const std::string& symbol_name,
|
||||
FileDescriptorProto* output) = 0;
|
||||
|
||||
// Find the file which defines an extension extending the given message type
|
||||
// with the given field number. If found, fills in *output and returns true,
|
||||
// otherwise returns false and leaves *output undefined. containing_type
|
||||
// must be a fully-qualified type name.
|
||||
virtual bool FindFileContainingExtension(const std::string& containing_type,
|
||||
int field_number,
|
||||
FileDescriptorProto* output) = 0;
|
||||
|
||||
// Finds the tag numbers used by all known extensions of
|
||||
// extendee_type, and appends them to output in an undefined
|
||||
// order. This method is best-effort: it's not guaranteed that the
|
||||
// database will find all extensions, and it's not guaranteed that
|
||||
// FindFileContainingExtension will return true on all of the found
|
||||
// numbers. Returns true if the search was successful, otherwise
|
||||
// returns false and leaves output unchanged.
|
||||
//
|
||||
// This method has a default implementation that always returns
|
||||
// false.
|
||||
virtual bool FindAllExtensionNumbers(const std::string& /* extendee_type */,
|
||||
std::vector<int>* /* output */) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Finds the file names and appends them to the output in an
|
||||
// undefined order. This method is best-effort: it's not guaranteed that the
|
||||
// database will find all files. Returns true if the database supports
|
||||
// searching all file names, otherwise returns false and leaves output
|
||||
// unchanged.
|
||||
//
|
||||
// This method has a default implementation that always returns
|
||||
// false.
|
||||
virtual bool FindAllFileNames(std::vector<std::string>* /*output*/) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Finds the package names and appends them to the output in an
|
||||
// undefined order. This method is best-effort: it's not guaranteed that the
|
||||
// database will find all packages. Returns true if the database supports
|
||||
// searching all package names, otherwise returns false and leaves output
|
||||
// unchanged.
|
||||
bool FindAllPackageNames(std::vector<std::string>* output);
|
||||
|
||||
// Finds the message names and appends them to the output in an
|
||||
// undefined order. This method is best-effort: it's not guaranteed that the
|
||||
// database will find all messages. Returns true if the database supports
|
||||
// searching all message names, otherwise returns false and leaves output
|
||||
// unchanged.
|
||||
bool FindAllMessageNames(std::vector<std::string>* output);
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DescriptorDatabase);
|
||||
};
|
||||
|
||||
// A DescriptorDatabase into which you can insert files manually.
|
||||
//
|
||||
// FindFileContainingSymbol() is fully-implemented. When you add a file, its
|
||||
// symbols will be indexed for this purpose. Note that the implementation
|
||||
// may return false positives, but only if it isn't possible for the symbol
|
||||
// to be defined in any other file. In particular, if a file defines a symbol
|
||||
// "Foo", then searching for "Foo.[anything]" will match that file. This way,
|
||||
// the database does not need to aggressively index all children of a symbol.
|
||||
//
|
||||
// FindFileContainingExtension() is mostly-implemented. It works if and only
|
||||
// if the original FieldDescriptorProto defining the extension has a
|
||||
// fully-qualified type name in its "extendee" field (i.e. starts with a '.').
|
||||
// If the extendee is a relative name, SimpleDescriptorDatabase will not
|
||||
// attempt to resolve the type, so it will not know what type the extension is
|
||||
// extending. Therefore, calling FindFileContainingExtension() with the
|
||||
// extension's containing type will never actually find that extension. Note
|
||||
// that this is an unlikely problem, as all FileDescriptorProtos created by the
|
||||
// protocol compiler (as well as ones created by calling
|
||||
// FileDescriptor::CopyTo()) will always use fully-qualified names for all
|
||||
// types. You only need to worry if you are constructing FileDescriptorProtos
|
||||
// yourself, or are calling compiler::Parser directly.
|
||||
class PROTOBUF_EXPORT SimpleDescriptorDatabase : public DescriptorDatabase {
|
||||
public:
|
||||
SimpleDescriptorDatabase();
|
||||
~SimpleDescriptorDatabase() override;
|
||||
|
||||
// Adds the FileDescriptorProto to the database, making a copy. The object
|
||||
// can be deleted after Add() returns. Returns false if the file conflicted
|
||||
// with a file already in the database, in which case an error will have
|
||||
// been written to GOOGLE_LOG(ERROR).
|
||||
bool Add(const FileDescriptorProto& file);
|
||||
|
||||
// Adds the FileDescriptorProto to the database and takes ownership of it.
|
||||
bool AddAndOwn(const FileDescriptorProto* file);
|
||||
|
||||
// implements DescriptorDatabase -----------------------------------
|
||||
bool FindFileByName(const std::string& filename,
|
||||
FileDescriptorProto* output) override;
|
||||
bool FindFileContainingSymbol(const std::string& symbol_name,
|
||||
FileDescriptorProto* output) override;
|
||||
bool FindFileContainingExtension(const std::string& containing_type,
|
||||
int field_number,
|
||||
FileDescriptorProto* output) override;
|
||||
bool FindAllExtensionNumbers(const std::string& extendee_type,
|
||||
std::vector<int>* output) override;
|
||||
|
||||
bool FindAllFileNames(std::vector<std::string>* output) override;
|
||||
|
||||
private:
|
||||
// An index mapping file names, symbol names, and extension numbers to
|
||||
// some sort of values.
|
||||
template <typename Value>
|
||||
class DescriptorIndex {
|
||||
public:
|
||||
// Helpers to recursively add particular descriptors and all their contents
|
||||
// to the index.
|
||||
bool AddFile(const FileDescriptorProto& file, Value value);
|
||||
bool AddSymbol(const std::string& name, Value value);
|
||||
bool AddNestedExtensions(const std::string& filename,
|
||||
const DescriptorProto& message_type, Value value);
|
||||
bool AddExtension(const std::string& filename,
|
||||
const FieldDescriptorProto& field, Value value);
|
||||
|
||||
Value FindFile(const std::string& filename);
|
||||
Value FindSymbol(const std::string& name);
|
||||
Value FindExtension(const std::string& containing_type, int field_number);
|
||||
bool FindAllExtensionNumbers(const std::string& containing_type,
|
||||
std::vector<int>* output);
|
||||
void FindAllFileNames(std::vector<std::string>* output);
|
||||
|
||||
private:
|
||||
std::map<std::string, Value> by_name_;
|
||||
std::map<std::string, Value> by_symbol_;
|
||||
std::map<std::pair<std::string, int>, Value> by_extension_;
|
||||
|
||||
// Invariant: The by_symbol_ map does not contain any symbols which are
|
||||
// prefixes of other symbols in the map. For example, "foo.bar" is a
|
||||
// prefix of "foo.bar.baz" (but is not a prefix of "foo.barbaz").
|
||||
//
|
||||
// This invariant is important because it means that given a symbol name,
|
||||
// we can find a key in the map which is a prefix of the symbol in O(lg n)
|
||||
// time, and we know that there is at most one such key.
|
||||
//
|
||||
// The prefix lookup algorithm works like so:
|
||||
// 1) Find the last key in the map which is less than or equal to the
|
||||
// search key.
|
||||
// 2) If the found key is a prefix of the search key, then return it.
|
||||
// Otherwise, there is no match.
|
||||
//
|
||||
// I am sure this algorithm has been described elsewhere, but since I
|
||||
// wasn't able to find it quickly I will instead prove that it works
|
||||
// myself. The key to the algorithm is that if a match exists, step (1)
|
||||
// will find it. Proof:
|
||||
// 1) Define the "search key" to be the key we are looking for, the "found
|
||||
// key" to be the key found in step (1), and the "match key" to be the
|
||||
// key which actually matches the search key (i.e. the key we're trying
|
||||
// to find).
|
||||
// 2) The found key must be less than or equal to the search key by
|
||||
// definition.
|
||||
// 3) The match key must also be less than or equal to the search key
|
||||
// (because it is a prefix).
|
||||
// 4) The match key cannot be greater than the found key, because if it
|
||||
// were, then step (1) of the algorithm would have returned the match
|
||||
// key instead (since it finds the *greatest* key which is less than or
|
||||
// equal to the search key).
|
||||
// 5) Therefore, the found key must be between the match key and the search
|
||||
// key, inclusive.
|
||||
// 6) Since the search key must be a sub-symbol of the match key, if it is
|
||||
// not equal to the match key, then search_key[match_key.size()] must
|
||||
// be '.'.
|
||||
// 7) Since '.' sorts before any other character that is valid in a symbol
|
||||
// name, then if the found key is not equal to the match key, then
|
||||
// found_key[match_key.size()] must also be '.', because any other value
|
||||
// would make it sort after the search key.
|
||||
// 8) Therefore, if the found key is not equal to the match key, then the
|
||||
// found key must be a sub-symbol of the match key. However, this would
|
||||
// contradict our map invariant which says that no symbol in the map is
|
||||
// a sub-symbol of any other.
|
||||
// 9) Therefore, the found key must match the match key.
|
||||
//
|
||||
// The above proof assumes the match key exists. In the case that the
|
||||
// match key does not exist, then step (1) will return some other symbol.
|
||||
// That symbol cannot be a super-symbol of the search key since if it were,
|
||||
// then it would be a match, and we're assuming the match key doesn't exist.
|
||||
// Therefore, step 2 will correctly return no match.
|
||||
};
|
||||
|
||||
DescriptorIndex<const FileDescriptorProto*> index_;
|
||||
std::vector<std::unique_ptr<const FileDescriptorProto>> files_to_delete_;
|
||||
|
||||
// If file is non-nullptr, copy it into *output and return true, otherwise
|
||||
// return false.
|
||||
bool MaybeCopy(const FileDescriptorProto* file, FileDescriptorProto* output);
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SimpleDescriptorDatabase);
|
||||
};
|
||||
|
||||
// Very similar to SimpleDescriptorDatabase, but stores all the descriptors
|
||||
// as raw bytes and generally tries to use as little memory as possible.
|
||||
//
|
||||
// The same caveats regarding FindFileContainingExtension() apply as with
|
||||
// SimpleDescriptorDatabase.
|
||||
class PROTOBUF_EXPORT EncodedDescriptorDatabase : public DescriptorDatabase {
|
||||
public:
|
||||
EncodedDescriptorDatabase();
|
||||
~EncodedDescriptorDatabase() override;
|
||||
|
||||
// Adds the FileDescriptorProto to the database. The descriptor is provided
|
||||
// in encoded form. The database does not make a copy of the bytes, nor
|
||||
// does it take ownership; it's up to the caller to make sure the bytes
|
||||
// remain valid for the life of the database. Returns false and logs an error
|
||||
// if the bytes are not a valid FileDescriptorProto or if the file conflicted
|
||||
// with a file already in the database.
|
||||
bool Add(const void* encoded_file_descriptor, int size);
|
||||
|
||||
// Like Add(), but makes a copy of the data, so that the caller does not
|
||||
// need to keep it around.
|
||||
bool AddCopy(const void* encoded_file_descriptor, int size);
|
||||
|
||||
// Like FindFileContainingSymbol but returns only the name of the file.
|
||||
bool FindNameOfFileContainingSymbol(const std::string& symbol_name,
|
||||
std::string* output);
|
||||
|
||||
// implements DescriptorDatabase -----------------------------------
|
||||
bool FindFileByName(const std::string& filename,
|
||||
FileDescriptorProto* output) override;
|
||||
bool FindFileContainingSymbol(const std::string& symbol_name,
|
||||
FileDescriptorProto* output) override;
|
||||
bool FindFileContainingExtension(const std::string& containing_type,
|
||||
int field_number,
|
||||
FileDescriptorProto* output) override;
|
||||
bool FindAllExtensionNumbers(const std::string& extendee_type,
|
||||
std::vector<int>* output) override;
|
||||
bool FindAllFileNames(std::vector<std::string>* output) override;
|
||||
|
||||
private:
|
||||
class DescriptorIndex;
|
||||
// Keep DescriptorIndex by pointer to hide the implementation to keep a
|
||||
// cleaner header.
|
||||
std::unique_ptr<DescriptorIndex> index_;
|
||||
std::vector<void*> files_to_delete_;
|
||||
|
||||
// If encoded_file.first is non-nullptr, parse the data into *output and
|
||||
// return true, otherwise return false.
|
||||
bool MaybeParse(std::pair<const void*, int> encoded_file,
|
||||
FileDescriptorProto* output);
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EncodedDescriptorDatabase);
|
||||
};
|
||||
|
||||
// A DescriptorDatabase that fetches files from a given pool.
|
||||
class PROTOBUF_EXPORT DescriptorPoolDatabase : public DescriptorDatabase {
|
||||
public:
|
||||
explicit DescriptorPoolDatabase(const DescriptorPool& pool);
|
||||
~DescriptorPoolDatabase() override;
|
||||
|
||||
// implements DescriptorDatabase -----------------------------------
|
||||
bool FindFileByName(const std::string& filename,
|
||||
FileDescriptorProto* output) override;
|
||||
bool FindFileContainingSymbol(const std::string& symbol_name,
|
||||
FileDescriptorProto* output) override;
|
||||
bool FindFileContainingExtension(const std::string& containing_type,
|
||||
int field_number,
|
||||
FileDescriptorProto* output) override;
|
||||
bool FindAllExtensionNumbers(const std::string& extendee_type,
|
||||
std::vector<int>* output) override;
|
||||
|
||||
private:
|
||||
const DescriptorPool& pool_;
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DescriptorPoolDatabase);
|
||||
};
|
||||
|
||||
// A DescriptorDatabase that wraps two or more others. It first searches the
|
||||
// first database and, if that fails, tries the second, and so on.
|
||||
class PROTOBUF_EXPORT MergedDescriptorDatabase : public DescriptorDatabase {
|
||||
public:
|
||||
// Merge just two databases. The sources remain property of the caller.
|
||||
MergedDescriptorDatabase(DescriptorDatabase* source1,
|
||||
DescriptorDatabase* source2);
|
||||
// Merge more than two databases. The sources remain property of the caller.
|
||||
// The vector may be deleted after the constructor returns but the
|
||||
// DescriptorDatabases need to stick around.
|
||||
explicit MergedDescriptorDatabase(
|
||||
const std::vector<DescriptorDatabase*>& sources);
|
||||
~MergedDescriptorDatabase() override;
|
||||
|
||||
// implements DescriptorDatabase -----------------------------------
|
||||
bool FindFileByName(const std::string& filename,
|
||||
FileDescriptorProto* output) override;
|
||||
bool FindFileContainingSymbol(const std::string& symbol_name,
|
||||
FileDescriptorProto* output) override;
|
||||
bool FindFileContainingExtension(const std::string& containing_type,
|
||||
int field_number,
|
||||
FileDescriptorProto* output) override;
|
||||
// Merges the results of calling all databases. Returns true iff any
|
||||
// of the databases returned true.
|
||||
bool FindAllExtensionNumbers(const std::string& extendee_type,
|
||||
std::vector<int>* output) override;
|
||||
|
||||
|
||||
// This function is best-effort. Returns true if at least one underlying
|
||||
// DescriptorDatabase returns true.
|
||||
bool FindAllFileNames(std::vector<std::string>* output) override;
|
||||
|
||||
private:
|
||||
std::vector<DescriptorDatabase*> sources_;
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MergedDescriptorDatabase);
|
||||
};
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_DESCRIPTOR_DATABASE_H__
|
||||
@@ -1,278 +0,0 @@
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: google/protobuf/duration.proto
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fduration_2eproto
|
||||
#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fduration_2eproto
|
||||
|
||||
#include <limits>
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/port_def.inc>
|
||||
#if PROTOBUF_VERSION < 3021000
|
||||
#error This file was generated by a newer version of protoc which is
|
||||
#error incompatible with your Protocol Buffer headers. Please update
|
||||
#error your headers.
|
||||
#endif
|
||||
#if 3021012 < PROTOBUF_MIN_PROTOC_VERSION
|
||||
#error This file was generated by an older version of protoc which is
|
||||
#error incompatible with your Protocol Buffer headers. Please
|
||||
#error regenerate this file with a newer version of protoc.
|
||||
#endif
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/arena.h>
|
||||
#include <google/protobuf/arenastring.h>
|
||||
#include <google/protobuf/generated_message_util.h>
|
||||
#include <google/protobuf/metadata_lite.h>
|
||||
#include <google/protobuf/generated_message_reflection.h>
|
||||
#include <google/protobuf/message.h>
|
||||
#include <google/protobuf/repeated_field.h> // IWYU pragma: export
|
||||
#include <google/protobuf/extension_set.h> // IWYU pragma: export
|
||||
#include <google/protobuf/unknown_field_set.h>
|
||||
// @@protoc_insertion_point(includes)
|
||||
#include <google/protobuf/port_def.inc>
|
||||
#define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fduration_2eproto PROTOBUF_EXPORT
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
namespace internal {
|
||||
class AnyMetadata;
|
||||
} // namespace internal
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
|
||||
// Internal implementation detail -- do not use these members.
|
||||
struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2fduration_2eproto {
|
||||
static const uint32_t offsets[];
|
||||
};
|
||||
PROTOBUF_EXPORT extern const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fduration_2eproto;
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
class Duration;
|
||||
struct DurationDefaultTypeInternal;
|
||||
PROTOBUF_EXPORT extern DurationDefaultTypeInternal _Duration_default_instance_;
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Duration* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Duration>(Arena*);
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
|
||||
// ===================================================================
|
||||
|
||||
class PROTOBUF_EXPORT Duration final :
|
||||
public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Duration) */ {
|
||||
public:
|
||||
inline Duration() : Duration(nullptr) {}
|
||||
~Duration() override;
|
||||
explicit PROTOBUF_CONSTEXPR Duration(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
|
||||
|
||||
Duration(const Duration& from);
|
||||
Duration(Duration&& from) noexcept
|
||||
: Duration() {
|
||||
*this = ::std::move(from);
|
||||
}
|
||||
|
||||
inline Duration& operator=(const Duration& from) {
|
||||
CopyFrom(from);
|
||||
return *this;
|
||||
}
|
||||
inline Duration& operator=(Duration&& from) noexcept {
|
||||
if (this == &from) return *this;
|
||||
if (GetOwningArena() == from.GetOwningArena()
|
||||
#ifdef PROTOBUF_FORCE_COPY_IN_MOVE
|
||||
&& GetOwningArena() != nullptr
|
||||
#endif // !PROTOBUF_FORCE_COPY_IN_MOVE
|
||||
) {
|
||||
InternalSwap(&from);
|
||||
} else {
|
||||
CopyFrom(from);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() {
|
||||
return GetDescriptor();
|
||||
}
|
||||
static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
|
||||
return default_instance().GetMetadata().descriptor;
|
||||
}
|
||||
static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
|
||||
return default_instance().GetMetadata().reflection;
|
||||
}
|
||||
static const Duration& default_instance() {
|
||||
return *internal_default_instance();
|
||||
}
|
||||
static inline const Duration* internal_default_instance() {
|
||||
return reinterpret_cast<const Duration*>(
|
||||
&_Duration_default_instance_);
|
||||
}
|
||||
static constexpr int kIndexInFileMessages =
|
||||
0;
|
||||
|
||||
friend void swap(Duration& a, Duration& b) {
|
||||
a.Swap(&b);
|
||||
}
|
||||
inline void Swap(Duration* other) {
|
||||
if (other == this) return;
|
||||
#ifdef PROTOBUF_FORCE_COPY_IN_SWAP
|
||||
if (GetOwningArena() != nullptr &&
|
||||
GetOwningArena() == other->GetOwningArena()) {
|
||||
#else // PROTOBUF_FORCE_COPY_IN_SWAP
|
||||
if (GetOwningArena() == other->GetOwningArena()) {
|
||||
#endif // !PROTOBUF_FORCE_COPY_IN_SWAP
|
||||
InternalSwap(other);
|
||||
} else {
|
||||
::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
|
||||
}
|
||||
}
|
||||
void UnsafeArenaSwap(Duration* other) {
|
||||
if (other == this) return;
|
||||
GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
|
||||
InternalSwap(other);
|
||||
}
|
||||
|
||||
// implements Message ----------------------------------------------
|
||||
|
||||
Duration* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final {
|
||||
return CreateMaybeMessage<Duration>(arena);
|
||||
}
|
||||
using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
|
||||
void CopyFrom(const Duration& from);
|
||||
using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
|
||||
void MergeFrom( const Duration& from) {
|
||||
Duration::MergeImpl(*this, from);
|
||||
}
|
||||
private:
|
||||
static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg);
|
||||
public:
|
||||
PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
|
||||
bool IsInitialized() const final;
|
||||
|
||||
size_t ByteSizeLong() const final;
|
||||
const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
|
||||
uint8_t* _InternalSerialize(
|
||||
uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
|
||||
int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
|
||||
|
||||
private:
|
||||
void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned);
|
||||
void SharedDtor();
|
||||
void SetCachedSize(int size) const final;
|
||||
void InternalSwap(Duration* other);
|
||||
|
||||
private:
|
||||
friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
|
||||
static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
|
||||
return "google.protobuf.Duration";
|
||||
}
|
||||
protected:
|
||||
explicit Duration(::PROTOBUF_NAMESPACE_ID::Arena* arena,
|
||||
bool is_message_owned = false);
|
||||
public:
|
||||
|
||||
static const ClassData _class_data_;
|
||||
const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
|
||||
|
||||
::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
|
||||
|
||||
// nested types ----------------------------------------------------
|
||||
|
||||
// accessors -------------------------------------------------------
|
||||
|
||||
enum : int {
|
||||
kSecondsFieldNumber = 1,
|
||||
kNanosFieldNumber = 2,
|
||||
};
|
||||
// int64 seconds = 1;
|
||||
void clear_seconds();
|
||||
int64_t seconds() const;
|
||||
void set_seconds(int64_t value);
|
||||
private:
|
||||
int64_t _internal_seconds() const;
|
||||
void _internal_set_seconds(int64_t value);
|
||||
public:
|
||||
|
||||
// int32 nanos = 2;
|
||||
void clear_nanos();
|
||||
int32_t nanos() const;
|
||||
void set_nanos(int32_t value);
|
||||
private:
|
||||
int32_t _internal_nanos() const;
|
||||
void _internal_set_nanos(int32_t value);
|
||||
public:
|
||||
|
||||
// @@protoc_insertion_point(class_scope:google.protobuf.Duration)
|
||||
private:
|
||||
class _Internal;
|
||||
|
||||
template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper;
|
||||
typedef void InternalArenaConstructable_;
|
||||
typedef void DestructorSkippable_;
|
||||
struct Impl_ {
|
||||
int64_t seconds_;
|
||||
int32_t nanos_;
|
||||
mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
|
||||
};
|
||||
union { Impl_ _impl_; };
|
||||
friend struct ::TableStruct_google_2fprotobuf_2fduration_2eproto;
|
||||
};
|
||||
// ===================================================================
|
||||
|
||||
|
||||
// ===================================================================
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
|
||||
#endif // __GNUC__
|
||||
// Duration
|
||||
|
||||
// int64 seconds = 1;
|
||||
inline void Duration::clear_seconds() {
|
||||
_impl_.seconds_ = int64_t{0};
|
||||
}
|
||||
inline int64_t Duration::_internal_seconds() const {
|
||||
return _impl_.seconds_;
|
||||
}
|
||||
inline int64_t Duration::seconds() const {
|
||||
// @@protoc_insertion_point(field_get:google.protobuf.Duration.seconds)
|
||||
return _internal_seconds();
|
||||
}
|
||||
inline void Duration::_internal_set_seconds(int64_t value) {
|
||||
|
||||
_impl_.seconds_ = value;
|
||||
}
|
||||
inline void Duration::set_seconds(int64_t value) {
|
||||
_internal_set_seconds(value);
|
||||
// @@protoc_insertion_point(field_set:google.protobuf.Duration.seconds)
|
||||
}
|
||||
|
||||
// int32 nanos = 2;
|
||||
inline void Duration::clear_nanos() {
|
||||
_impl_.nanos_ = 0;
|
||||
}
|
||||
inline int32_t Duration::_internal_nanos() const {
|
||||
return _impl_.nanos_;
|
||||
}
|
||||
inline int32_t Duration::nanos() const {
|
||||
// @@protoc_insertion_point(field_get:google.protobuf.Duration.nanos)
|
||||
return _internal_nanos();
|
||||
}
|
||||
inline void Duration::_internal_set_nanos(int32_t value) {
|
||||
|
||||
_impl_.nanos_ = value;
|
||||
}
|
||||
inline void Duration::set_nanos(int32_t value) {
|
||||
_internal_set_nanos(value);
|
||||
// @@protoc_insertion_point(field_set:google.protobuf.Duration.nanos)
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif // __GNUC__
|
||||
|
||||
// @@protoc_insertion_point(namespace_scope)
|
||||
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
|
||||
// @@protoc_insertion_point(global_scope)
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
#endif // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fduration_2eproto
|
||||
@@ -1,227 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
//
|
||||
// Defines an implementation of Message which can emulate types which are not
|
||||
// known at compile-time.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_DYNAMIC_MESSAGE_H__
|
||||
#define GOOGLE_PROTOBUF_DYNAMIC_MESSAGE_H__
|
||||
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/mutex.h>
|
||||
#include <google/protobuf/message.h>
|
||||
#include <google/protobuf/reflection.h>
|
||||
#include <google/protobuf/repeated_field.h>
|
||||
|
||||
#ifdef SWIG
|
||||
#error "You cannot SWIG proto headers"
|
||||
#endif
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
// Defined in other files.
|
||||
class Descriptor; // descriptor.h
|
||||
class DescriptorPool; // descriptor.h
|
||||
|
||||
// Constructs implementations of Message which can emulate types which are not
|
||||
// known at compile-time.
|
||||
//
|
||||
// Sometimes you want to be able to manipulate protocol types that you don't
|
||||
// know about at compile time. It would be nice to be able to construct
|
||||
// a Message object which implements the message type given by any arbitrary
|
||||
// Descriptor. DynamicMessage provides this.
|
||||
//
|
||||
// As it turns out, a DynamicMessage needs to construct extra
|
||||
// information about its type in order to operate. Most of this information
|
||||
// can be shared between all DynamicMessages of the same type. But, caching
|
||||
// this information in some sort of global map would be a bad idea, since
|
||||
// the cached information for a particular descriptor could outlive the
|
||||
// descriptor itself. To avoid this problem, DynamicMessageFactory
|
||||
// encapsulates this "cache". All DynamicMessages of the same type created
|
||||
// from the same factory will share the same support data. Any Descriptors
|
||||
// used with a particular factory must outlive the factory.
|
||||
class PROTOBUF_EXPORT DynamicMessageFactory : public MessageFactory {
|
||||
public:
|
||||
// Construct a DynamicMessageFactory that will search for extensions in
|
||||
// the DescriptorPool in which the extendee is defined.
|
||||
DynamicMessageFactory();
|
||||
|
||||
// Construct a DynamicMessageFactory that will search for extensions in
|
||||
// the given DescriptorPool.
|
||||
//
|
||||
// DEPRECATED: Use CodedInputStream::SetExtensionRegistry() to tell the
|
||||
// parser to look for extensions in an alternate pool. However, note that
|
||||
// this is almost never what you want to do. Almost all users should use
|
||||
// the zero-arg constructor.
|
||||
DynamicMessageFactory(const DescriptorPool* pool);
|
||||
|
||||
~DynamicMessageFactory() override;
|
||||
|
||||
// Call this to tell the DynamicMessageFactory that if it is given a
|
||||
// Descriptor d for which:
|
||||
// d->file()->pool() == DescriptorPool::generated_pool(),
|
||||
// then it should delegate to MessageFactory::generated_factory() instead
|
||||
// of constructing a dynamic implementation of the message. In theory there
|
||||
// is no down side to doing this, so it may become the default in the future.
|
||||
void SetDelegateToGeneratedFactory(bool enable) {
|
||||
delegate_to_generated_factory_ = enable;
|
||||
}
|
||||
|
||||
// implements MessageFactory ---------------------------------------
|
||||
|
||||
// Given a Descriptor, constructs the default (prototype) Message of that
|
||||
// type. You can then call that message's New() method to construct a
|
||||
// mutable message of that type.
|
||||
//
|
||||
// Calling this method twice with the same Descriptor returns the same
|
||||
// object. The returned object remains property of the factory and will
|
||||
// be destroyed when the factory is destroyed. Also, any objects created
|
||||
// by calling the prototype's New() method share some data with the
|
||||
// prototype, so these must be destroyed before the DynamicMessageFactory
|
||||
// is destroyed.
|
||||
//
|
||||
// The given descriptor must outlive the returned message, and hence must
|
||||
// outlive the DynamicMessageFactory.
|
||||
//
|
||||
// The method is thread-safe.
|
||||
const Message* GetPrototype(const Descriptor* type) override;
|
||||
|
||||
private:
|
||||
const DescriptorPool* pool_;
|
||||
bool delegate_to_generated_factory_;
|
||||
|
||||
struct TypeInfo;
|
||||
std::unordered_map<const Descriptor*, const TypeInfo*> prototypes_;
|
||||
mutable internal::WrappedMutex prototypes_mutex_;
|
||||
|
||||
friend class DynamicMessage;
|
||||
const Message* GetPrototypeNoLock(const Descriptor* type);
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMessageFactory);
|
||||
};
|
||||
|
||||
// Helper for computing a sorted list of map entries via reflection.
|
||||
class PROTOBUF_EXPORT DynamicMapSorter {
|
||||
public:
|
||||
static std::vector<const Message*> Sort(const Message& message, int map_size,
|
||||
const Reflection* reflection,
|
||||
const FieldDescriptor* field) {
|
||||
std::vector<const Message*> result;
|
||||
result.reserve(map_size);
|
||||
RepeatedFieldRef<Message> map_field =
|
||||
reflection->GetRepeatedFieldRef<Message>(message, field);
|
||||
for (auto it = map_field.begin(); it != map_field.end(); ++it) {
|
||||
result.push_back(&*it);
|
||||
}
|
||||
MapEntryMessageComparator comparator(field->message_type());
|
||||
std::stable_sort(result.begin(), result.end(), comparator);
|
||||
// Complain if the keys aren't in ascending order.
|
||||
#ifndef NDEBUG
|
||||
for (size_t j = 1; j < static_cast<size_t>(map_size); j++) {
|
||||
if (!comparator(result[j - 1], result[j])) {
|
||||
GOOGLE_LOG(ERROR) << (comparator(result[j], result[j - 1])
|
||||
? "internal error in map key sorting"
|
||||
: "map keys are not unique");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
class PROTOBUF_EXPORT MapEntryMessageComparator {
|
||||
public:
|
||||
explicit MapEntryMessageComparator(const Descriptor* descriptor)
|
||||
: field_(descriptor->field(0)) {}
|
||||
|
||||
bool operator()(const Message* a, const Message* b) {
|
||||
const Reflection* reflection = a->GetReflection();
|
||||
switch (field_->cpp_type()) {
|
||||
case FieldDescriptor::CPPTYPE_BOOL: {
|
||||
bool first = reflection->GetBool(*a, field_);
|
||||
bool second = reflection->GetBool(*b, field_);
|
||||
return first < second;
|
||||
}
|
||||
case FieldDescriptor::CPPTYPE_INT32: {
|
||||
int32_t first = reflection->GetInt32(*a, field_);
|
||||
int32_t second = reflection->GetInt32(*b, field_);
|
||||
return first < second;
|
||||
}
|
||||
case FieldDescriptor::CPPTYPE_INT64: {
|
||||
int64_t first = reflection->GetInt64(*a, field_);
|
||||
int64_t second = reflection->GetInt64(*b, field_);
|
||||
return first < second;
|
||||
}
|
||||
case FieldDescriptor::CPPTYPE_UINT32: {
|
||||
uint32_t first = reflection->GetUInt32(*a, field_);
|
||||
uint32_t second = reflection->GetUInt32(*b, field_);
|
||||
return first < second;
|
||||
}
|
||||
case FieldDescriptor::CPPTYPE_UINT64: {
|
||||
uint64_t first = reflection->GetUInt64(*a, field_);
|
||||
uint64_t second = reflection->GetUInt64(*b, field_);
|
||||
return first < second;
|
||||
}
|
||||
case FieldDescriptor::CPPTYPE_STRING: {
|
||||
std::string first = reflection->GetString(*a, field_);
|
||||
std::string second = reflection->GetString(*b, field_);
|
||||
return first < second;
|
||||
}
|
||||
default:
|
||||
GOOGLE_LOG(DFATAL) << "Invalid key for map field.";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
const FieldDescriptor* field_;
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_DYNAMIC_MESSAGE_H__
|
||||
@@ -1,198 +0,0 @@
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: google/protobuf/empty.proto
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fempty_2eproto
|
||||
#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fempty_2eproto
|
||||
|
||||
#include <limits>
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/port_def.inc>
|
||||
#if PROTOBUF_VERSION < 3021000
|
||||
#error This file was generated by a newer version of protoc which is
|
||||
#error incompatible with your Protocol Buffer headers. Please update
|
||||
#error your headers.
|
||||
#endif
|
||||
#if 3021012 < PROTOBUF_MIN_PROTOC_VERSION
|
||||
#error This file was generated by an older version of protoc which is
|
||||
#error incompatible with your Protocol Buffer headers. Please
|
||||
#error regenerate this file with a newer version of protoc.
|
||||
#endif
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/arena.h>
|
||||
#include <google/protobuf/arenastring.h>
|
||||
#include <google/protobuf/generated_message_bases.h>
|
||||
#include <google/protobuf/generated_message_util.h>
|
||||
#include <google/protobuf/metadata_lite.h>
|
||||
#include <google/protobuf/generated_message_reflection.h>
|
||||
#include <google/protobuf/message.h>
|
||||
#include <google/protobuf/repeated_field.h> // IWYU pragma: export
|
||||
#include <google/protobuf/extension_set.h> // IWYU pragma: export
|
||||
#include <google/protobuf/unknown_field_set.h>
|
||||
// @@protoc_insertion_point(includes)
|
||||
#include <google/protobuf/port_def.inc>
|
||||
#define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fempty_2eproto PROTOBUF_EXPORT
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
namespace internal {
|
||||
class AnyMetadata;
|
||||
} // namespace internal
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
|
||||
// Internal implementation detail -- do not use these members.
|
||||
struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2fempty_2eproto {
|
||||
static const uint32_t offsets[];
|
||||
};
|
||||
PROTOBUF_EXPORT extern const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fempty_2eproto;
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
class Empty;
|
||||
struct EmptyDefaultTypeInternal;
|
||||
PROTOBUF_EXPORT extern EmptyDefaultTypeInternal _Empty_default_instance_;
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Empty* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Empty>(Arena*);
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
|
||||
// ===================================================================
|
||||
|
||||
class PROTOBUF_EXPORT Empty final :
|
||||
public ::PROTOBUF_NAMESPACE_ID::internal::ZeroFieldsBase /* @@protoc_insertion_point(class_definition:google.protobuf.Empty) */ {
|
||||
public:
|
||||
inline Empty() : Empty(nullptr) {}
|
||||
explicit PROTOBUF_CONSTEXPR Empty(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
|
||||
|
||||
Empty(const Empty& from);
|
||||
Empty(Empty&& from) noexcept
|
||||
: Empty() {
|
||||
*this = ::std::move(from);
|
||||
}
|
||||
|
||||
inline Empty& operator=(const Empty& from) {
|
||||
CopyFrom(from);
|
||||
return *this;
|
||||
}
|
||||
inline Empty& operator=(Empty&& from) noexcept {
|
||||
if (this == &from) return *this;
|
||||
if (GetOwningArena() == from.GetOwningArena()
|
||||
#ifdef PROTOBUF_FORCE_COPY_IN_MOVE
|
||||
&& GetOwningArena() != nullptr
|
||||
#endif // !PROTOBUF_FORCE_COPY_IN_MOVE
|
||||
) {
|
||||
InternalSwap(&from);
|
||||
} else {
|
||||
CopyFrom(from);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() {
|
||||
return GetDescriptor();
|
||||
}
|
||||
static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
|
||||
return default_instance().GetMetadata().descriptor;
|
||||
}
|
||||
static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
|
||||
return default_instance().GetMetadata().reflection;
|
||||
}
|
||||
static const Empty& default_instance() {
|
||||
return *internal_default_instance();
|
||||
}
|
||||
static inline const Empty* internal_default_instance() {
|
||||
return reinterpret_cast<const Empty*>(
|
||||
&_Empty_default_instance_);
|
||||
}
|
||||
static constexpr int kIndexInFileMessages =
|
||||
0;
|
||||
|
||||
friend void swap(Empty& a, Empty& b) {
|
||||
a.Swap(&b);
|
||||
}
|
||||
inline void Swap(Empty* other) {
|
||||
if (other == this) return;
|
||||
#ifdef PROTOBUF_FORCE_COPY_IN_SWAP
|
||||
if (GetOwningArena() != nullptr &&
|
||||
GetOwningArena() == other->GetOwningArena()) {
|
||||
#else // PROTOBUF_FORCE_COPY_IN_SWAP
|
||||
if (GetOwningArena() == other->GetOwningArena()) {
|
||||
#endif // !PROTOBUF_FORCE_COPY_IN_SWAP
|
||||
InternalSwap(other);
|
||||
} else {
|
||||
::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
|
||||
}
|
||||
}
|
||||
void UnsafeArenaSwap(Empty* other) {
|
||||
if (other == this) return;
|
||||
GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
|
||||
InternalSwap(other);
|
||||
}
|
||||
|
||||
// implements Message ----------------------------------------------
|
||||
|
||||
Empty* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final {
|
||||
return CreateMaybeMessage<Empty>(arena);
|
||||
}
|
||||
using ::PROTOBUF_NAMESPACE_ID::internal::ZeroFieldsBase::CopyFrom;
|
||||
inline void CopyFrom(const Empty& from) {
|
||||
::PROTOBUF_NAMESPACE_ID::internal::ZeroFieldsBase::CopyImpl(*this, from);
|
||||
}
|
||||
using ::PROTOBUF_NAMESPACE_ID::internal::ZeroFieldsBase::MergeFrom;
|
||||
void MergeFrom(const Empty& from) {
|
||||
::PROTOBUF_NAMESPACE_ID::internal::ZeroFieldsBase::MergeImpl(*this, from);
|
||||
}
|
||||
public:
|
||||
|
||||
private:
|
||||
friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
|
||||
static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
|
||||
return "google.protobuf.Empty";
|
||||
}
|
||||
protected:
|
||||
explicit Empty(::PROTOBUF_NAMESPACE_ID::Arena* arena,
|
||||
bool is_message_owned = false);
|
||||
public:
|
||||
|
||||
static const ClassData _class_data_;
|
||||
const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
|
||||
|
||||
::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
|
||||
|
||||
// nested types ----------------------------------------------------
|
||||
|
||||
// accessors -------------------------------------------------------
|
||||
|
||||
// @@protoc_insertion_point(class_scope:google.protobuf.Empty)
|
||||
private:
|
||||
class _Internal;
|
||||
|
||||
template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper;
|
||||
typedef void InternalArenaConstructable_;
|
||||
typedef void DestructorSkippable_;
|
||||
struct Impl_ {
|
||||
};
|
||||
friend struct ::TableStruct_google_2fprotobuf_2fempty_2eproto;
|
||||
};
|
||||
// ===================================================================
|
||||
|
||||
|
||||
// ===================================================================
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
|
||||
#endif // __GNUC__
|
||||
// Empty
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif // __GNUC__
|
||||
|
||||
// @@protoc_insertion_point(namespace_scope)
|
||||
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
|
||||
// @@protoc_insertion_point(global_scope)
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
#endif // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fempty_2eproto
|
||||
@@ -1,198 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_ENDIAN_H__
|
||||
#define GOOGLE_PROTOBUF_ENDIAN_H__
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
inline uint64_t BSwap64(uint64_t host_int) {
|
||||
#if defined(PROTOBUF_BUILTIN_BSWAP64)
|
||||
return PROTOBUF_BUILTIN_BSWAP64(host_int);
|
||||
#elif defined(_MSC_VER)
|
||||
return _byteswap_uint64(host_int);
|
||||
#else
|
||||
return (((host_int & uint64_t{0xFF}) << 56) |
|
||||
((host_int & uint64_t{0xFF00}) << 40) |
|
||||
((host_int & uint64_t{0xFF0000}) << 24) |
|
||||
((host_int & uint64_t{0xFF000000}) << 8) |
|
||||
((host_int & uint64_t{0xFF00000000}) >> 8) |
|
||||
((host_int & uint64_t{0xFF0000000000}) >> 24) |
|
||||
((host_int & uint64_t{0xFF000000000000}) >> 40) |
|
||||
((host_int & uint64_t{0xFF00000000000000}) >> 56));
|
||||
#endif
|
||||
}
|
||||
|
||||
inline uint32_t BSwap32(uint32_t host_int) {
|
||||
#if defined(PROTOBUF_BUILTIN_BSWAP32)
|
||||
return PROTOBUF_BUILTIN_BSWAP32(host_int);
|
||||
#elif defined(_MSC_VER)
|
||||
return _byteswap_ulong(host_int);
|
||||
#else
|
||||
return (((host_int & uint32_t{0xFF}) << 24) |
|
||||
((host_int & uint32_t{0xFF00}) << 8) |
|
||||
((host_int & uint32_t{0xFF0000}) >> 8) |
|
||||
((host_int & uint32_t{0xFF000000}) >> 24));
|
||||
#endif
|
||||
}
|
||||
|
||||
inline uint16_t BSwap16(uint16_t host_int) {
|
||||
#if defined(PROTOBUF_BUILTIN_BSWAP16)
|
||||
return PROTOBUF_BUILTIN_BSWAP16(host_int);
|
||||
#elif defined(_MSC_VER)
|
||||
return _byteswap_ushort(host_int);
|
||||
#else
|
||||
return (((host_int & uint16_t{0xFF}) << 8) |
|
||||
((host_int & uint16_t{0xFF00}) >> 8));
|
||||
#endif
|
||||
}
|
||||
|
||||
namespace little_endian {
|
||||
|
||||
inline uint16_t FromHost(uint16_t value) {
|
||||
#if defined(PROTOBUF_BIG_ENDIAN)
|
||||
return BSwap16(value);
|
||||
#else
|
||||
return value;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline uint32_t FromHost(uint32_t value) {
|
||||
#if defined(PROTOBUF_BIG_ENDIAN)
|
||||
return BSwap32(value);
|
||||
#else
|
||||
return value;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline uint64_t FromHost(uint64_t value) {
|
||||
#if defined(PROTOBUF_BIG_ENDIAN)
|
||||
return BSwap64(value);
|
||||
#else
|
||||
return value;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline uint16_t ToHost(uint16_t value) {
|
||||
#if defined(PROTOBUF_BIG_ENDIAN)
|
||||
return BSwap16(value);
|
||||
#else
|
||||
return value;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline uint32_t ToHost(uint32_t value) {
|
||||
#if defined(PROTOBUF_BIG_ENDIAN)
|
||||
return BSwap32(value);
|
||||
#else
|
||||
return value;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline uint64_t ToHost(uint64_t value) {
|
||||
#if defined(PROTOBUF_BIG_ENDIAN)
|
||||
return BSwap64(value);
|
||||
#else
|
||||
return value;
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace little_endian
|
||||
|
||||
namespace big_endian {
|
||||
|
||||
inline uint16_t FromHost(uint16_t value) {
|
||||
#if defined(PROTOBUF_BIG_ENDIAN)
|
||||
return value;
|
||||
#else
|
||||
return BSwap16(value);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline uint32_t FromHost(uint32_t value) {
|
||||
#if defined(PROTOBUF_BIG_ENDIAN)
|
||||
return value;
|
||||
#else
|
||||
return BSwap32(value);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline uint64_t FromHost(uint64_t value) {
|
||||
#if defined(PROTOBUF_BIG_ENDIAN)
|
||||
return value;
|
||||
#else
|
||||
return BSwap64(value);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline uint16_t ToHost(uint16_t value) {
|
||||
#if defined(PROTOBUF_BIG_ENDIAN)
|
||||
return value;
|
||||
#else
|
||||
return BSwap16(value);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline uint32_t ToHost(uint32_t value) {
|
||||
#if defined(PROTOBUF_BIG_ENDIAN)
|
||||
return value;
|
||||
#else
|
||||
return BSwap32(value);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline uint64_t ToHost(uint64_t value) {
|
||||
#if defined(PROTOBUF_BIG_ENDIAN)
|
||||
return value;
|
||||
#else
|
||||
return BSwap64(value);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace big_endian
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_ENDIAN_H__
|
||||
@@ -1,97 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_EXPLICITLY_CONSTRUCTED_H__
|
||||
#define GOOGLE_PROTOBUF_EXPLICITLY_CONSTRUCTED_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include <google/protobuf/stubs/logging.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
// clang-format off
|
||||
#include <google/protobuf/port_def.inc>
|
||||
// clang-format on
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
// Wraps a variable whose constructor and destructor are explicitly
|
||||
// called. It is particularly useful for a global variable, without its
|
||||
// constructor and destructor run on start and end of the program lifetime.
|
||||
// This circumvents the initial construction order fiasco, while keeping
|
||||
// the address of the empty string a compile time constant.
|
||||
//
|
||||
// Pay special attention to the initialization state of the object.
|
||||
// 1. The object is "uninitialized" to begin with.
|
||||
// 2. Call Construct() or DefaultConstruct() only if the object is
|
||||
// uninitialized. After the call, the object becomes "initialized".
|
||||
// 3. Call get() and get_mutable() only if the object is initialized.
|
||||
// 4. Call Destruct() only if the object is initialized.
|
||||
// After the call, the object becomes uninitialized.
|
||||
template <typename T, size_t min_align = 1>
|
||||
class ExplicitlyConstructed {
|
||||
public:
|
||||
void DefaultConstruct() { new (&union_) T(); }
|
||||
|
||||
template <typename... Args>
|
||||
void Construct(Args&&... args) {
|
||||
new (&union_) T(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
void Destruct() { get_mutable()->~T(); }
|
||||
|
||||
constexpr const T& get() const { return reinterpret_cast<const T&>(union_); }
|
||||
T* get_mutable() { return reinterpret_cast<T*>(&union_); }
|
||||
|
||||
private:
|
||||
union AlignedUnion {
|
||||
alignas(min_align > alignof(T) ? min_align
|
||||
: alignof(T)) char space[sizeof(T)];
|
||||
int64_t align_to_int64;
|
||||
void* align_to_ptr;
|
||||
} union_;
|
||||
};
|
||||
|
||||
// ArenaStringPtr compatible explicitly constructed string type.
|
||||
// This empty string type is aligned with a minimum alignment of 8 bytes
|
||||
// which is the minimum requirement of ArenaStringPtr
|
||||
using ExplicitlyConstructedArenaString = ExplicitlyConstructed<std::string, 8>;
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_EXPLICITLY_CONSTRUCTED_H__
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,285 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_EXTENSION_SET_INL_H__
|
||||
#define GOOGLE_PROTOBUF_EXTENSION_SET_INL_H__
|
||||
|
||||
#include <google/protobuf/extension_set.h>
|
||||
#include <google/protobuf/metadata_lite.h>
|
||||
#include <google/protobuf/parse_context.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
template <typename T>
|
||||
const char* ExtensionSet::ParseFieldWithExtensionInfo(
|
||||
int number, bool was_packed_on_wire, const ExtensionInfo& extension,
|
||||
InternalMetadata* metadata, const char* ptr, internal::ParseContext* ctx) {
|
||||
if (was_packed_on_wire) {
|
||||
switch (extension.type) {
|
||||
#define HANDLE_TYPE(UPPERCASE, CPP_CAMELCASE) \
|
||||
case WireFormatLite::TYPE_##UPPERCASE: \
|
||||
return internal::Packed##CPP_CAMELCASE##Parser( \
|
||||
MutableRawRepeatedField(number, extension.type, extension.is_packed, \
|
||||
extension.descriptor), \
|
||||
ptr, ctx);
|
||||
HANDLE_TYPE(INT32, Int32);
|
||||
HANDLE_TYPE(INT64, Int64);
|
||||
HANDLE_TYPE(UINT32, UInt32);
|
||||
HANDLE_TYPE(UINT64, UInt64);
|
||||
HANDLE_TYPE(SINT32, SInt32);
|
||||
HANDLE_TYPE(SINT64, SInt64);
|
||||
HANDLE_TYPE(FIXED32, Fixed32);
|
||||
HANDLE_TYPE(FIXED64, Fixed64);
|
||||
HANDLE_TYPE(SFIXED32, SFixed32);
|
||||
HANDLE_TYPE(SFIXED64, SFixed64);
|
||||
HANDLE_TYPE(FLOAT, Float);
|
||||
HANDLE_TYPE(DOUBLE, Double);
|
||||
HANDLE_TYPE(BOOL, Bool);
|
||||
#undef HANDLE_TYPE
|
||||
|
||||
case WireFormatLite::TYPE_ENUM:
|
||||
return internal::PackedEnumParserArg<T>(
|
||||
MutableRawRepeatedField(number, extension.type, extension.is_packed,
|
||||
extension.descriptor),
|
||||
ptr, ctx, extension.enum_validity_check.func,
|
||||
extension.enum_validity_check.arg, metadata, number);
|
||||
case WireFormatLite::TYPE_STRING:
|
||||
case WireFormatLite::TYPE_BYTES:
|
||||
case WireFormatLite::TYPE_GROUP:
|
||||
case WireFormatLite::TYPE_MESSAGE:
|
||||
GOOGLE_LOG(FATAL) << "Non-primitive types can't be packed.";
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (extension.type) {
|
||||
#define HANDLE_VARINT_TYPE(UPPERCASE, CPP_CAMELCASE) \
|
||||
case WireFormatLite::TYPE_##UPPERCASE: { \
|
||||
uint64_t value; \
|
||||
ptr = VarintParse(ptr, &value); \
|
||||
GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); \
|
||||
if (extension.is_repeated) { \
|
||||
Add##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, \
|
||||
extension.is_packed, value, extension.descriptor); \
|
||||
} else { \
|
||||
Set##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, value, \
|
||||
extension.descriptor); \
|
||||
} \
|
||||
} break
|
||||
|
||||
HANDLE_VARINT_TYPE(INT32, Int32);
|
||||
HANDLE_VARINT_TYPE(INT64, Int64);
|
||||
HANDLE_VARINT_TYPE(UINT32, UInt32);
|
||||
HANDLE_VARINT_TYPE(UINT64, UInt64);
|
||||
HANDLE_VARINT_TYPE(BOOL, Bool);
|
||||
#undef HANDLE_VARINT_TYPE
|
||||
#define HANDLE_SVARINT_TYPE(UPPERCASE, CPP_CAMELCASE, SIZE) \
|
||||
case WireFormatLite::TYPE_##UPPERCASE: { \
|
||||
uint64_t val; \
|
||||
ptr = VarintParse(ptr, &val); \
|
||||
GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); \
|
||||
auto value = WireFormatLite::ZigZagDecode##SIZE(val); \
|
||||
if (extension.is_repeated) { \
|
||||
Add##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, \
|
||||
extension.is_packed, value, extension.descriptor); \
|
||||
} else { \
|
||||
Set##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, value, \
|
||||
extension.descriptor); \
|
||||
} \
|
||||
} break
|
||||
|
||||
HANDLE_SVARINT_TYPE(SINT32, Int32, 32);
|
||||
HANDLE_SVARINT_TYPE(SINT64, Int64, 64);
|
||||
#undef HANDLE_SVARINT_TYPE
|
||||
#define HANDLE_FIXED_TYPE(UPPERCASE, CPP_CAMELCASE, CPPTYPE) \
|
||||
case WireFormatLite::TYPE_##UPPERCASE: { \
|
||||
auto value = UnalignedLoad<CPPTYPE>(ptr); \
|
||||
ptr += sizeof(CPPTYPE); \
|
||||
if (extension.is_repeated) { \
|
||||
Add##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, \
|
||||
extension.is_packed, value, extension.descriptor); \
|
||||
} else { \
|
||||
Set##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, value, \
|
||||
extension.descriptor); \
|
||||
} \
|
||||
} break
|
||||
|
||||
HANDLE_FIXED_TYPE(FIXED32, UInt32, uint32_t);
|
||||
HANDLE_FIXED_TYPE(FIXED64, UInt64, uint64_t);
|
||||
HANDLE_FIXED_TYPE(SFIXED32, Int32, int32_t);
|
||||
HANDLE_FIXED_TYPE(SFIXED64, Int64, int64_t);
|
||||
HANDLE_FIXED_TYPE(FLOAT, Float, float);
|
||||
HANDLE_FIXED_TYPE(DOUBLE, Double, double);
|
||||
#undef HANDLE_FIXED_TYPE
|
||||
|
||||
case WireFormatLite::TYPE_ENUM: {
|
||||
uint64_t val;
|
||||
ptr = VarintParse(ptr, &val);
|
||||
GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
|
||||
int value = val;
|
||||
|
||||
if (!extension.enum_validity_check.func(
|
||||
extension.enum_validity_check.arg, value)) {
|
||||
WriteVarint(number, val, metadata->mutable_unknown_fields<T>());
|
||||
} else if (extension.is_repeated) {
|
||||
AddEnum(number, WireFormatLite::TYPE_ENUM, extension.is_packed, value,
|
||||
extension.descriptor);
|
||||
} else {
|
||||
SetEnum(number, WireFormatLite::TYPE_ENUM, value,
|
||||
extension.descriptor);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case WireFormatLite::TYPE_BYTES:
|
||||
case WireFormatLite::TYPE_STRING: {
|
||||
std::string* value =
|
||||
extension.is_repeated
|
||||
? AddString(number, WireFormatLite::TYPE_STRING,
|
||||
extension.descriptor)
|
||||
: MutableString(number, WireFormatLite::TYPE_STRING,
|
||||
extension.descriptor);
|
||||
int size = ReadSize(&ptr);
|
||||
GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
|
||||
return ctx->ReadString(ptr, size, value);
|
||||
}
|
||||
|
||||
case WireFormatLite::TYPE_GROUP: {
|
||||
MessageLite* value =
|
||||
extension.is_repeated
|
||||
? AddMessage(number, WireFormatLite::TYPE_GROUP,
|
||||
*extension.message_info.prototype,
|
||||
extension.descriptor)
|
||||
: MutableMessage(number, WireFormatLite::TYPE_GROUP,
|
||||
*extension.message_info.prototype,
|
||||
extension.descriptor);
|
||||
uint32_t tag = (number << 3) + WireFormatLite::WIRETYPE_START_GROUP;
|
||||
return ctx->ParseGroup(value, ptr, tag);
|
||||
}
|
||||
|
||||
case WireFormatLite::TYPE_MESSAGE: {
|
||||
MessageLite* value =
|
||||
extension.is_repeated
|
||||
? AddMessage(number, WireFormatLite::TYPE_MESSAGE,
|
||||
*extension.message_info.prototype,
|
||||
extension.descriptor)
|
||||
: MutableMessage(number, WireFormatLite::TYPE_MESSAGE,
|
||||
*extension.message_info.prototype,
|
||||
extension.descriptor);
|
||||
return ctx->ParseMessage(value, ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
template <typename Msg, typename T>
|
||||
const char* ExtensionSet::ParseMessageSetItemTmpl(
|
||||
const char* ptr, const Msg* extendee, internal::InternalMetadata* metadata,
|
||||
internal::ParseContext* ctx) {
|
||||
std::string payload;
|
||||
uint32_t type_id = 0;
|
||||
enum class State { kNoTag, kHasType, kHasPayload, kDone };
|
||||
State state = State::kNoTag;
|
||||
|
||||
while (!ctx->Done(&ptr)) {
|
||||
uint32_t tag = static_cast<uint8_t>(*ptr++);
|
||||
if (tag == WireFormatLite::kMessageSetTypeIdTag) {
|
||||
uint64_t tmp;
|
||||
ptr = ParseBigVarint(ptr, &tmp);
|
||||
GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
|
||||
if (state == State::kNoTag) {
|
||||
type_id = tmp;
|
||||
state = State::kHasType;
|
||||
} else if (state == State::kHasPayload) {
|
||||
type_id = tmp;
|
||||
ExtensionInfo extension;
|
||||
bool was_packed_on_wire;
|
||||
if (!FindExtension(2, type_id, extendee, ctx, &extension,
|
||||
&was_packed_on_wire)) {
|
||||
WriteLengthDelimited(type_id, payload,
|
||||
metadata->mutable_unknown_fields<T>());
|
||||
} else {
|
||||
MessageLite* value =
|
||||
extension.is_repeated
|
||||
? AddMessage(type_id, WireFormatLite::TYPE_MESSAGE,
|
||||
*extension.message_info.prototype,
|
||||
extension.descriptor)
|
||||
: MutableMessage(type_id, WireFormatLite::TYPE_MESSAGE,
|
||||
*extension.message_info.prototype,
|
||||
extension.descriptor);
|
||||
|
||||
const char* p;
|
||||
// We can't use regular parse from string as we have to track
|
||||
// proper recursion depth and descriptor pools.
|
||||
ParseContext tmp_ctx(ctx->depth(), false, &p, payload);
|
||||
tmp_ctx.data().pool = ctx->data().pool;
|
||||
tmp_ctx.data().factory = ctx->data().factory;
|
||||
GOOGLE_PROTOBUF_PARSER_ASSERT(value->_InternalParse(p, &tmp_ctx) &&
|
||||
tmp_ctx.EndedAtLimit());
|
||||
}
|
||||
state = State::kDone;
|
||||
}
|
||||
} else if (tag == WireFormatLite::kMessageSetMessageTag) {
|
||||
if (state == State::kHasType) {
|
||||
ptr = ParseFieldMaybeLazily(static_cast<uint64_t>(type_id) * 8 + 2, ptr,
|
||||
extendee, metadata, ctx);
|
||||
GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
|
||||
state = State::kDone;
|
||||
} else {
|
||||
std::string tmp;
|
||||
int32_t size = ReadSize(&ptr);
|
||||
GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
|
||||
ptr = ctx->ReadString(ptr, size, &tmp);
|
||||
GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
|
||||
if (state == State::kNoTag) {
|
||||
payload = std::move(tmp);
|
||||
state = State::kHasPayload;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ptr = ReadTag(ptr - 1, &tag);
|
||||
if (tag == 0 || (tag & 7) == 4) {
|
||||
ctx->SetLastTag(tag);
|
||||
return ptr;
|
||||
}
|
||||
ptr = ParseField(tag, ptr, extendee, metadata, ctx);
|
||||
GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
|
||||
}
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_EXTENSION_SET_INL_H__
|
||||
@@ -1,172 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_FIELD_ACCESS_LISTENER_H__
|
||||
#define GOOGLE_PROTOBUF_FIELD_ACCESS_LISTENER_H__
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/message_lite.h>
|
||||
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
// A default/no-op implementation of message hooks.
|
||||
//
|
||||
// See go/statically-dispatched-message-hooks for details.
|
||||
template <typename Proto>
|
||||
struct NoOpAccessListener {
|
||||
// Number of fields are provided at compile time for the trackers to be able
|
||||
// to have stack allocated bitmaps for the fields. This is useful for
|
||||
// performance critical trackers. This is also to avoid cyclic dependencies
|
||||
// if the number of fields is needed.
|
||||
static constexpr int kFields = Proto::_kInternalFieldNumber;
|
||||
// Default constructor is called during the static global initialization of
|
||||
// the program.
|
||||
// We provide a pointer to extract the name of the proto not to get cyclic
|
||||
// dependencies on GetDescriptor() and OnGetMetadata() calls. If you want
|
||||
// to differentiate the protos during the runtime before the start of the
|
||||
// program, use this functor to get its name. We either way need it for
|
||||
// LITE_RUNTIME protos as they don't have descriptors at all.
|
||||
explicit NoOpAccessListener(StringPiece (*name_extractor)()) {}
|
||||
// called repeatedly during serialization/deserialization/ByteSize of
|
||||
// Reflection as:
|
||||
// AccessListener<MessageT>::OnSerialize(this);
|
||||
static void OnSerialize(const MessageLite* msg) {}
|
||||
static void OnDeserialize(const MessageLite* msg) {}
|
||||
static void OnByteSize(const MessageLite* msg) {}
|
||||
static void OnMergeFrom(const MessageLite* to, const MessageLite* from) {}
|
||||
|
||||
// NOTE: This function can be called pre-main. Make sure it does not make
|
||||
// the state of the listener invalid.
|
||||
static void OnGetMetadata() {}
|
||||
|
||||
// called from accessors as:
|
||||
// AccessListener<MessageT>::On$operation(this, &field_storage_);
|
||||
// If you need to override this with type, in your hook implementation
|
||||
// introduce
|
||||
// template <int kFieldNum, typename T>
|
||||
// static void On$operation(const MessageLite* msg,
|
||||
// const T* field) {}
|
||||
// And overloads for std::nullptr_t for incomplete types such as Messages,
|
||||
// Maps. Extract them using reflection if you need. Consequently, second
|
||||
// argument can be null pointer.
|
||||
// For an example, see proto_hooks/testing/memory_test_field_listener.h
|
||||
// And argument template deduction will deduce the type itself without
|
||||
// changing the generated code.
|
||||
|
||||
// add_<field>(f)
|
||||
template <int kFieldNum>
|
||||
static void OnAdd(const MessageLite* msg, const void* field) {}
|
||||
|
||||
// add_<field>()
|
||||
template <int kFieldNum>
|
||||
static void OnAddMutable(const MessageLite* msg, const void* field) {}
|
||||
|
||||
// <field>() and <repeated_field>(i)
|
||||
template <int kFieldNum>
|
||||
static void OnGet(const MessageLite* msg, const void* field) {}
|
||||
|
||||
// clear_<field>()
|
||||
template <int kFieldNum>
|
||||
static void OnClear(const MessageLite* msg, const void* field) {}
|
||||
|
||||
// has_<field>()
|
||||
template <int kFieldNum>
|
||||
static void OnHas(const MessageLite* msg, const void* field) {}
|
||||
|
||||
// <repeated_field>()
|
||||
template <int kFieldNum>
|
||||
static void OnList(const MessageLite* msg, const void* field) {}
|
||||
|
||||
// mutable_<field>()
|
||||
template <int kFieldNum>
|
||||
static void OnMutable(const MessageLite* msg, const void* field) {}
|
||||
|
||||
// mutable_<repeated_field>()
|
||||
template <int kFieldNum>
|
||||
static void OnMutableList(const MessageLite* msg, const void* field) {}
|
||||
|
||||
// release_<field>()
|
||||
template <int kFieldNum>
|
||||
static void OnRelease(const MessageLite* msg, const void* field) {}
|
||||
|
||||
// set_<field>() and set_<repeated_field>(i)
|
||||
template <int kFieldNum>
|
||||
static void OnSet(const MessageLite* msg, const void* field) {}
|
||||
|
||||
// <repeated_field>_size()
|
||||
template <int kFieldNum>
|
||||
static void OnSize(const MessageLite* msg, const void* field) {}
|
||||
|
||||
static void OnHasExtension(const MessageLite* msg, int extension_tag,
|
||||
const void* field) {}
|
||||
// TODO(b/190614678): Support clear in the proto compiler.
|
||||
static void OnClearExtension(const MessageLite* msg, int extension_tag,
|
||||
const void* field) {}
|
||||
static void OnExtensionSize(const MessageLite* msg, int extension_tag,
|
||||
const void* field) {}
|
||||
static void OnGetExtension(const MessageLite* msg, int extension_tag,
|
||||
const void* field) {}
|
||||
static void OnMutableExtension(const MessageLite* msg, int extension_tag,
|
||||
const void* field) {}
|
||||
static void OnSetExtension(const MessageLite* msg, int extension_tag,
|
||||
const void* field) {}
|
||||
static void OnReleaseExtension(const MessageLite* msg, int extension_tag,
|
||||
const void* field) {}
|
||||
static void OnAddExtension(const MessageLite* msg, int extension_tag,
|
||||
const void* field) {}
|
||||
static void OnAddMutableExtension(const MessageLite* msg, int extension_tag,
|
||||
const void* field) {}
|
||||
static void OnListExtension(const MessageLite* msg, int extension_tag,
|
||||
const void* field) {}
|
||||
static void OnMutableListExtension(const MessageLite* msg, int extension_tag,
|
||||
const void* field) {}
|
||||
};
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#ifndef REPLACE_PROTO_LISTENER_IMPL
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
template <class T>
|
||||
using AccessListener = NoOpAccessListener<T>;
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
#else
|
||||
// You can put your implementations of hooks/listeners here.
|
||||
// All hooks are subject to approval by protobuf-team@.
|
||||
|
||||
#endif // !REPLACE_PROTO_LISTENER_IMPL
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_FIELD_ACCESS_LISTENER_H__
|
||||
@@ -1,317 +0,0 @@
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: google/protobuf/field_mask.proto
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2ffield_5fmask_2eproto
|
||||
#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2ffield_5fmask_2eproto
|
||||
|
||||
#include <limits>
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/port_def.inc>
|
||||
#if PROTOBUF_VERSION < 3021000
|
||||
#error This file was generated by a newer version of protoc which is
|
||||
#error incompatible with your Protocol Buffer headers. Please update
|
||||
#error your headers.
|
||||
#endif
|
||||
#if 3021012 < PROTOBUF_MIN_PROTOC_VERSION
|
||||
#error This file was generated by an older version of protoc which is
|
||||
#error incompatible with your Protocol Buffer headers. Please
|
||||
#error regenerate this file with a newer version of protoc.
|
||||
#endif
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/arena.h>
|
||||
#include <google/protobuf/arenastring.h>
|
||||
#include <google/protobuf/generated_message_util.h>
|
||||
#include <google/protobuf/metadata_lite.h>
|
||||
#include <google/protobuf/generated_message_reflection.h>
|
||||
#include <google/protobuf/message.h>
|
||||
#include <google/protobuf/repeated_field.h> // IWYU pragma: export
|
||||
#include <google/protobuf/extension_set.h> // IWYU pragma: export
|
||||
#include <google/protobuf/unknown_field_set.h>
|
||||
// @@protoc_insertion_point(includes)
|
||||
#include <google/protobuf/port_def.inc>
|
||||
#define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2ffield_5fmask_2eproto PROTOBUF_EXPORT
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
namespace internal {
|
||||
class AnyMetadata;
|
||||
} // namespace internal
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
|
||||
// Internal implementation detail -- do not use these members.
|
||||
struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2ffield_5fmask_2eproto {
|
||||
static const uint32_t offsets[];
|
||||
};
|
||||
PROTOBUF_EXPORT extern const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto;
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
class FieldMask;
|
||||
struct FieldMaskDefaultTypeInternal;
|
||||
PROTOBUF_EXPORT extern FieldMaskDefaultTypeInternal _FieldMask_default_instance_;
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::FieldMask* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::FieldMask>(Arena*);
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
|
||||
// ===================================================================
|
||||
|
||||
class PROTOBUF_EXPORT FieldMask final :
|
||||
public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.FieldMask) */ {
|
||||
public:
|
||||
inline FieldMask() : FieldMask(nullptr) {}
|
||||
~FieldMask() override;
|
||||
explicit PROTOBUF_CONSTEXPR FieldMask(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
|
||||
|
||||
FieldMask(const FieldMask& from);
|
||||
FieldMask(FieldMask&& from) noexcept
|
||||
: FieldMask() {
|
||||
*this = ::std::move(from);
|
||||
}
|
||||
|
||||
inline FieldMask& operator=(const FieldMask& from) {
|
||||
CopyFrom(from);
|
||||
return *this;
|
||||
}
|
||||
inline FieldMask& operator=(FieldMask&& from) noexcept {
|
||||
if (this == &from) return *this;
|
||||
if (GetOwningArena() == from.GetOwningArena()
|
||||
#ifdef PROTOBUF_FORCE_COPY_IN_MOVE
|
||||
&& GetOwningArena() != nullptr
|
||||
#endif // !PROTOBUF_FORCE_COPY_IN_MOVE
|
||||
) {
|
||||
InternalSwap(&from);
|
||||
} else {
|
||||
CopyFrom(from);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() {
|
||||
return GetDescriptor();
|
||||
}
|
||||
static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
|
||||
return default_instance().GetMetadata().descriptor;
|
||||
}
|
||||
static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
|
||||
return default_instance().GetMetadata().reflection;
|
||||
}
|
||||
static const FieldMask& default_instance() {
|
||||
return *internal_default_instance();
|
||||
}
|
||||
static inline const FieldMask* internal_default_instance() {
|
||||
return reinterpret_cast<const FieldMask*>(
|
||||
&_FieldMask_default_instance_);
|
||||
}
|
||||
static constexpr int kIndexInFileMessages =
|
||||
0;
|
||||
|
||||
friend void swap(FieldMask& a, FieldMask& b) {
|
||||
a.Swap(&b);
|
||||
}
|
||||
inline void Swap(FieldMask* other) {
|
||||
if (other == this) return;
|
||||
#ifdef PROTOBUF_FORCE_COPY_IN_SWAP
|
||||
if (GetOwningArena() != nullptr &&
|
||||
GetOwningArena() == other->GetOwningArena()) {
|
||||
#else // PROTOBUF_FORCE_COPY_IN_SWAP
|
||||
if (GetOwningArena() == other->GetOwningArena()) {
|
||||
#endif // !PROTOBUF_FORCE_COPY_IN_SWAP
|
||||
InternalSwap(other);
|
||||
} else {
|
||||
::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
|
||||
}
|
||||
}
|
||||
void UnsafeArenaSwap(FieldMask* other) {
|
||||
if (other == this) return;
|
||||
GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
|
||||
InternalSwap(other);
|
||||
}
|
||||
|
||||
// implements Message ----------------------------------------------
|
||||
|
||||
FieldMask* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final {
|
||||
return CreateMaybeMessage<FieldMask>(arena);
|
||||
}
|
||||
using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
|
||||
void CopyFrom(const FieldMask& from);
|
||||
using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
|
||||
void MergeFrom( const FieldMask& from) {
|
||||
FieldMask::MergeImpl(*this, from);
|
||||
}
|
||||
private:
|
||||
static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg);
|
||||
public:
|
||||
PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
|
||||
bool IsInitialized() const final;
|
||||
|
||||
size_t ByteSizeLong() const final;
|
||||
const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
|
||||
uint8_t* _InternalSerialize(
|
||||
uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
|
||||
int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
|
||||
|
||||
private:
|
||||
void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned);
|
||||
void SharedDtor();
|
||||
void SetCachedSize(int size) const final;
|
||||
void InternalSwap(FieldMask* other);
|
||||
|
||||
private:
|
||||
friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
|
||||
static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
|
||||
return "google.protobuf.FieldMask";
|
||||
}
|
||||
protected:
|
||||
explicit FieldMask(::PROTOBUF_NAMESPACE_ID::Arena* arena,
|
||||
bool is_message_owned = false);
|
||||
public:
|
||||
|
||||
static const ClassData _class_data_;
|
||||
const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
|
||||
|
||||
::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
|
||||
|
||||
// nested types ----------------------------------------------------
|
||||
|
||||
// accessors -------------------------------------------------------
|
||||
|
||||
enum : int {
|
||||
kPathsFieldNumber = 1,
|
||||
};
|
||||
// repeated string paths = 1;
|
||||
int paths_size() const;
|
||||
private:
|
||||
int _internal_paths_size() const;
|
||||
public:
|
||||
void clear_paths();
|
||||
const std::string& paths(int index) const;
|
||||
std::string* mutable_paths(int index);
|
||||
void set_paths(int index, const std::string& value);
|
||||
void set_paths(int index, std::string&& value);
|
||||
void set_paths(int index, const char* value);
|
||||
void set_paths(int index, const char* value, size_t size);
|
||||
std::string* add_paths();
|
||||
void add_paths(const std::string& value);
|
||||
void add_paths(std::string&& value);
|
||||
void add_paths(const char* value);
|
||||
void add_paths(const char* value, size_t size);
|
||||
const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string>& paths() const;
|
||||
::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string>* mutable_paths();
|
||||
private:
|
||||
const std::string& _internal_paths(int index) const;
|
||||
std::string* _internal_add_paths();
|
||||
public:
|
||||
|
||||
// @@protoc_insertion_point(class_scope:google.protobuf.FieldMask)
|
||||
private:
|
||||
class _Internal;
|
||||
|
||||
template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper;
|
||||
typedef void InternalArenaConstructable_;
|
||||
typedef void DestructorSkippable_;
|
||||
struct Impl_ {
|
||||
::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string> paths_;
|
||||
mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
|
||||
};
|
||||
union { Impl_ _impl_; };
|
||||
friend struct ::TableStruct_google_2fprotobuf_2ffield_5fmask_2eproto;
|
||||
};
|
||||
// ===================================================================
|
||||
|
||||
|
||||
// ===================================================================
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
|
||||
#endif // __GNUC__
|
||||
// FieldMask
|
||||
|
||||
// repeated string paths = 1;
|
||||
inline int FieldMask::_internal_paths_size() const {
|
||||
return _impl_.paths_.size();
|
||||
}
|
||||
inline int FieldMask::paths_size() const {
|
||||
return _internal_paths_size();
|
||||
}
|
||||
inline void FieldMask::clear_paths() {
|
||||
_impl_.paths_.Clear();
|
||||
}
|
||||
inline std::string* FieldMask::add_paths() {
|
||||
std::string* _s = _internal_add_paths();
|
||||
// @@protoc_insertion_point(field_add_mutable:google.protobuf.FieldMask.paths)
|
||||
return _s;
|
||||
}
|
||||
inline const std::string& FieldMask::_internal_paths(int index) const {
|
||||
return _impl_.paths_.Get(index);
|
||||
}
|
||||
inline const std::string& FieldMask::paths(int index) const {
|
||||
// @@protoc_insertion_point(field_get:google.protobuf.FieldMask.paths)
|
||||
return _internal_paths(index);
|
||||
}
|
||||
inline std::string* FieldMask::mutable_paths(int index) {
|
||||
// @@protoc_insertion_point(field_mutable:google.protobuf.FieldMask.paths)
|
||||
return _impl_.paths_.Mutable(index);
|
||||
}
|
||||
inline void FieldMask::set_paths(int index, const std::string& value) {
|
||||
_impl_.paths_.Mutable(index)->assign(value);
|
||||
// @@protoc_insertion_point(field_set:google.protobuf.FieldMask.paths)
|
||||
}
|
||||
inline void FieldMask::set_paths(int index, std::string&& value) {
|
||||
_impl_.paths_.Mutable(index)->assign(std::move(value));
|
||||
// @@protoc_insertion_point(field_set:google.protobuf.FieldMask.paths)
|
||||
}
|
||||
inline void FieldMask::set_paths(int index, const char* value) {
|
||||
GOOGLE_DCHECK(value != nullptr);
|
||||
_impl_.paths_.Mutable(index)->assign(value);
|
||||
// @@protoc_insertion_point(field_set_char:google.protobuf.FieldMask.paths)
|
||||
}
|
||||
inline void FieldMask::set_paths(int index, const char* value, size_t size) {
|
||||
_impl_.paths_.Mutable(index)->assign(
|
||||
reinterpret_cast<const char*>(value), size);
|
||||
// @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldMask.paths)
|
||||
}
|
||||
inline std::string* FieldMask::_internal_add_paths() {
|
||||
return _impl_.paths_.Add();
|
||||
}
|
||||
inline void FieldMask::add_paths(const std::string& value) {
|
||||
_impl_.paths_.Add()->assign(value);
|
||||
// @@protoc_insertion_point(field_add:google.protobuf.FieldMask.paths)
|
||||
}
|
||||
inline void FieldMask::add_paths(std::string&& value) {
|
||||
_impl_.paths_.Add(std::move(value));
|
||||
// @@protoc_insertion_point(field_add:google.protobuf.FieldMask.paths)
|
||||
}
|
||||
inline void FieldMask::add_paths(const char* value) {
|
||||
GOOGLE_DCHECK(value != nullptr);
|
||||
_impl_.paths_.Add()->assign(value);
|
||||
// @@protoc_insertion_point(field_add_char:google.protobuf.FieldMask.paths)
|
||||
}
|
||||
inline void FieldMask::add_paths(const char* value, size_t size) {
|
||||
_impl_.paths_.Add()->assign(reinterpret_cast<const char*>(value), size);
|
||||
// @@protoc_insertion_point(field_add_pointer:google.protobuf.FieldMask.paths)
|
||||
}
|
||||
inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string>&
|
||||
FieldMask::paths() const {
|
||||
// @@protoc_insertion_point(field_list:google.protobuf.FieldMask.paths)
|
||||
return _impl_.paths_;
|
||||
}
|
||||
inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string>*
|
||||
FieldMask::mutable_paths() {
|
||||
// @@protoc_insertion_point(field_mutable_list:google.protobuf.FieldMask.paths)
|
||||
return &_impl_.paths_;
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif // __GNUC__
|
||||
|
||||
// @@protoc_insertion_point(namespace_scope)
|
||||
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
|
||||
// @@protoc_insertion_point(global_scope)
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
#endif // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2ffield_5fmask_2eproto
|
||||
@@ -1,100 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: jasonh@google.com (Jason Hsueh)
|
||||
//
|
||||
// This header is logically internal, but is made public because it is used
|
||||
// from protocol-compiler-generated code, which may reside in other components.
|
||||
// It provides reflection support for generated enums, and is included in
|
||||
// generated .pb.h files and should have minimal dependencies. The methods are
|
||||
// implemented in generated_message_reflection.cc.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_GENERATED_ENUM_REFLECTION_H__
|
||||
#define GOOGLE_PROTOBUF_GENERATED_ENUM_REFLECTION_H__
|
||||
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/port.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
#include <google/protobuf/generated_enum_util.h>
|
||||
|
||||
#ifdef SWIG
|
||||
#error "You cannot SWIG proto headers"
|
||||
#endif
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
class EnumDescriptor;
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
// Returns the EnumDescriptor for enum type E, which must be a
|
||||
// proto-declared enum type. Code generated by the protocol compiler
|
||||
// will include specializations of this template for each enum type declared.
|
||||
template <typename E>
|
||||
const EnumDescriptor* GetEnumDescriptor();
|
||||
|
||||
namespace internal {
|
||||
|
||||
// Helper for EnumType_Parse functions: try to parse the string 'name' as
|
||||
// an enum name of the given type, returning true and filling in value on
|
||||
// success, or returning false and leaving value unchanged on failure.
|
||||
PROTOBUF_EXPORT bool ParseNamedEnum(const EnumDescriptor* descriptor,
|
||||
ConstStringParam name, int* value);
|
||||
|
||||
template <typename EnumType>
|
||||
bool ParseNamedEnum(const EnumDescriptor* descriptor, ConstStringParam name,
|
||||
EnumType* value) {
|
||||
int tmp;
|
||||
if (!ParseNamedEnum(descriptor, name, &tmp)) return false;
|
||||
*value = static_cast<EnumType>(tmp);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Just a wrapper around printing the name of a value. The main point of this
|
||||
// function is not to be inlined, so that you can do this without including
|
||||
// descriptor.h.
|
||||
PROTOBUF_EXPORT const std::string& NameOfEnum(const EnumDescriptor* descriptor,
|
||||
int value);
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_GENERATED_ENUM_REFLECTION_H__
|
||||
@@ -1,85 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_GENERATED_ENUM_UTIL_H__
|
||||
#define GOOGLE_PROTOBUF_GENERATED_ENUM_UTIL_H__
|
||||
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
#include <google/protobuf/message_lite.h>
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
#ifdef SWIG
|
||||
#error "You cannot SWIG proto headers"
|
||||
#endif
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
// This type trait can be used to cause templates to only match proto2 enum
|
||||
// types.
|
||||
template <typename T>
|
||||
struct is_proto_enum : ::std::false_type {};
|
||||
|
||||
namespace internal {
|
||||
|
||||
// The table entry format for storing enum name-to-value mapping used with lite
|
||||
// protos. This struct and the following related functions should only be used
|
||||
// by protobuf generated code.
|
||||
struct EnumEntry {
|
||||
StringPiece name;
|
||||
int value;
|
||||
};
|
||||
|
||||
// Looks up a numeric enum value given the string name.
|
||||
PROTOBUF_EXPORT bool LookUpEnumValue(const EnumEntry* enums, size_t size,
|
||||
StringPiece name, int* value);
|
||||
|
||||
// Looks up an enum name given the numeric value.
|
||||
PROTOBUF_EXPORT int LookUpEnumName(const EnumEntry* enums,
|
||||
const int* sorted_indices, size_t size,
|
||||
int value);
|
||||
|
||||
// Initializes the list of enum names in std::string form.
|
||||
PROTOBUF_EXPORT bool InitializeEnumStrings(
|
||||
const EnumEntry* enums, const int* sorted_indices, size_t size,
|
||||
internal::ExplicitlyConstructed<std::string>* enum_strings);
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_GENERATED_ENUM_UTIL_H__
|
||||
@@ -1,87 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// This file contains helpers for generated code.
|
||||
//
|
||||
// Nothing in this file should be directly referenced by users of protobufs.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_GENERATED_MESSAGE_BASES_H__
|
||||
#define GOOGLE_PROTOBUF_GENERATED_MESSAGE_BASES_H__
|
||||
|
||||
#include <google/protobuf/io/zero_copy_stream_impl.h>
|
||||
#include <google/protobuf/arena.h>
|
||||
#include <google/protobuf/generated_message_util.h>
|
||||
#include <google/protobuf/message.h>
|
||||
#include <google/protobuf/parse_context.h>
|
||||
|
||||
// Must come last:
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
// To save code size, protos without any fields are derived from ZeroFieldsBase
|
||||
// rather than Message.
|
||||
class PROTOBUF_EXPORT ZeroFieldsBase : public Message {
|
||||
public:
|
||||
PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
|
||||
bool IsInitialized() const final { return true; }
|
||||
size_t ByteSizeLong() const final;
|
||||
int GetCachedSize() const final { return _cached_size_.Get(); }
|
||||
const char* _InternalParse(const char* ptr,
|
||||
internal::ParseContext* ctx) final;
|
||||
::uint8_t* _InternalSerialize(::uint8_t* target,
|
||||
io::EpsCopyOutputStream* stream) const final;
|
||||
|
||||
protected:
|
||||
constexpr ZeroFieldsBase() {}
|
||||
explicit ZeroFieldsBase(Arena* arena, bool is_message_owned)
|
||||
: Message(arena, is_message_owned) {}
|
||||
ZeroFieldsBase(const ZeroFieldsBase&) = delete;
|
||||
ZeroFieldsBase& operator=(const ZeroFieldsBase&) = delete;
|
||||
~ZeroFieldsBase() override;
|
||||
|
||||
void SetCachedSize(int size) const final { _cached_size_.Set(size); }
|
||||
|
||||
static void MergeImpl(Message& to, const Message& from);
|
||||
static void CopyImpl(Message& to, const Message& from);
|
||||
void InternalSwap(ZeroFieldsBase* other);
|
||||
|
||||
mutable internal::CachedSize _cached_size_;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_GENERATED_MESSAGE_BASES_H__
|
||||
@@ -1,354 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
//
|
||||
// This header is logically internal, but is made public because it is used
|
||||
// from protocol-compiler-generated code, which may reside in other components.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_GENERATED_MESSAGE_REFLECTION_H__
|
||||
#define GOOGLE_PROTOBUF_GENERATED_MESSAGE_REFLECTION_H__
|
||||
|
||||
#include <google/protobuf/stubs/casts.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/once.h>
|
||||
#include <google/protobuf/port.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/generated_enum_reflection.h>
|
||||
#include <google/protobuf/unknown_field_set.h>
|
||||
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
#ifdef SWIG
|
||||
#error "You cannot SWIG proto headers"
|
||||
#endif
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
class MapKey;
|
||||
class MapValueRef;
|
||||
class MessageLayoutInspector;
|
||||
class Message;
|
||||
struct Metadata;
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
class DefaultEmptyOneof;
|
||||
// Defined in other files.
|
||||
class ExtensionSet; // extension_set.h
|
||||
class WeakFieldMap; // weak_field_map.h
|
||||
|
||||
// This struct describes the internal layout of the message, hence this is
|
||||
// used to act on the message reflectively.
|
||||
// default_instance: The default instance of the message. This is only
|
||||
// used to obtain pointers to default instances of embedded
|
||||
// messages, which GetMessage() will return if the particular
|
||||
// sub-message has not been initialized yet. (Thus, all
|
||||
// embedded message fields *must* have non-null pointers
|
||||
// in the default instance.)
|
||||
// offsets: An array of ints giving the byte offsets.
|
||||
// For each oneof or weak field, the offset is relative to the
|
||||
// default_instance. These can be computed at compile time
|
||||
// using the
|
||||
// PROTO2_GENERATED_DEFAULT_ONEOF_FIELD_OFFSET()
|
||||
// macro. For each none oneof field, the offset is related to
|
||||
// the start of the message object. These can be computed at
|
||||
// compile time using the
|
||||
// PROTO2_GENERATED_MESSAGE_FIELD_OFFSET() macro.
|
||||
// Besides offsets for all fields, this array also contains
|
||||
// offsets for oneof unions. The offset of the i-th oneof union
|
||||
// is offsets[descriptor->field_count() + i].
|
||||
// has_bit_indices: Mapping from field indexes to their index in the has
|
||||
// bit array.
|
||||
// has_bits_offset: Offset in the message of an array of uint32s of size
|
||||
// descriptor->field_count()/32, rounded up. This is a
|
||||
// bitfield where each bit indicates whether or not the
|
||||
// corresponding field of the message has been initialized.
|
||||
// The bit for field index i is obtained by the expression:
|
||||
// has_bits[i / 32] & (1 << (i % 32))
|
||||
// unknown_fields_offset: Offset in the message of the UnknownFieldSet for
|
||||
// the message.
|
||||
// extensions_offset: Offset in the message of the ExtensionSet for the
|
||||
// message, or -1 if the message type has no extension
|
||||
// ranges.
|
||||
// oneof_case_offset: Offset in the message of an array of uint32s of
|
||||
// size descriptor->oneof_decl_count(). Each uint32_t
|
||||
// indicates what field is set for each oneof.
|
||||
// object_size: The size of a message object of this type, as measured
|
||||
// by sizeof().
|
||||
// arena_offset: If a message doesn't have a unknown_field_set that stores
|
||||
// the arena, it must have a direct pointer to the arena.
|
||||
// weak_field_map_offset: If the message proto has weak fields, this is the
|
||||
// offset of _weak_field_map_ in the generated proto. Otherwise
|
||||
// -1.
|
||||
struct ReflectionSchema {
|
||||
public:
|
||||
// Size of a google::protobuf::Message object of this type.
|
||||
uint32_t GetObjectSize() const { return static_cast<uint32_t>(object_size_); }
|
||||
|
||||
bool InRealOneof(const FieldDescriptor* field) const {
|
||||
return field->containing_oneof() &&
|
||||
!field->containing_oneof()->is_synthetic();
|
||||
}
|
||||
|
||||
// Offset of a non-oneof field. Getting a field offset is slightly more
|
||||
// efficient when we know statically that it is not a oneof field.
|
||||
uint32_t GetFieldOffsetNonOneof(const FieldDescriptor* field) const {
|
||||
GOOGLE_DCHECK(!InRealOneof(field));
|
||||
return OffsetValue(offsets_[field->index()], field->type());
|
||||
}
|
||||
|
||||
// Offset of any field.
|
||||
uint32_t GetFieldOffset(const FieldDescriptor* field) const {
|
||||
if (InRealOneof(field)) {
|
||||
size_t offset =
|
||||
static_cast<size_t>(field->containing_type()->field_count()) +
|
||||
field->containing_oneof()->index();
|
||||
return OffsetValue(offsets_[offset], field->type());
|
||||
} else {
|
||||
return GetFieldOffsetNonOneof(field);
|
||||
}
|
||||
}
|
||||
|
||||
bool IsFieldInlined(const FieldDescriptor* field) const {
|
||||
return Inlined(offsets_[field->index()], field->type());
|
||||
}
|
||||
|
||||
uint32_t GetOneofCaseOffset(const OneofDescriptor* oneof_descriptor) const {
|
||||
return static_cast<uint32_t>(oneof_case_offset_) +
|
||||
static_cast<uint32_t>(
|
||||
static_cast<size_t>(oneof_descriptor->index()) *
|
||||
sizeof(uint32_t));
|
||||
}
|
||||
|
||||
bool HasHasbits() const { return has_bits_offset_ != -1; }
|
||||
|
||||
// Bit index within the bit array of hasbits. Bit order is low-to-high.
|
||||
uint32_t HasBitIndex(const FieldDescriptor* field) const {
|
||||
if (has_bits_offset_ == -1) return static_cast<uint32_t>(-1);
|
||||
GOOGLE_DCHECK(HasHasbits());
|
||||
return has_bit_indices_[field->index()];
|
||||
}
|
||||
|
||||
// Byte offset of the hasbits array.
|
||||
uint32_t HasBitsOffset() const {
|
||||
GOOGLE_DCHECK(HasHasbits());
|
||||
return static_cast<uint32_t>(has_bits_offset_);
|
||||
}
|
||||
|
||||
bool HasInlinedString() const { return inlined_string_donated_offset_ != -1; }
|
||||
|
||||
// Bit index within the bit array of _inlined_string_donated_. Bit order is
|
||||
// low-to-high.
|
||||
uint32_t InlinedStringIndex(const FieldDescriptor* field) const {
|
||||
GOOGLE_DCHECK(HasInlinedString());
|
||||
return inlined_string_indices_[field->index()];
|
||||
}
|
||||
|
||||
// Byte offset of the _inlined_string_donated_ array.
|
||||
uint32_t InlinedStringDonatedOffset() const {
|
||||
GOOGLE_DCHECK(HasInlinedString());
|
||||
return static_cast<uint32_t>(inlined_string_donated_offset_);
|
||||
}
|
||||
|
||||
// The offset of the InternalMetadataWithArena member.
|
||||
// For Lite this will actually be an InternalMetadataWithArenaLite.
|
||||
// The schema doesn't contain enough information to distinguish between
|
||||
// these two cases.
|
||||
uint32_t GetMetadataOffset() const {
|
||||
return static_cast<uint32_t>(metadata_offset_);
|
||||
}
|
||||
|
||||
// Whether this message has an ExtensionSet.
|
||||
bool HasExtensionSet() const { return extensions_offset_ != -1; }
|
||||
|
||||
// The offset of the ExtensionSet in this message.
|
||||
uint32_t GetExtensionSetOffset() const {
|
||||
GOOGLE_DCHECK(HasExtensionSet());
|
||||
return static_cast<uint32_t>(extensions_offset_);
|
||||
}
|
||||
|
||||
// The off set of WeakFieldMap when the message contains weak fields.
|
||||
// The default is 0 for now.
|
||||
int GetWeakFieldMapOffset() const { return weak_field_map_offset_; }
|
||||
|
||||
bool IsDefaultInstance(const Message& message) const {
|
||||
return &message == default_instance_;
|
||||
}
|
||||
|
||||
// Returns a pointer to the default value for this field. The size and type
|
||||
// of the underlying data depends on the field's type.
|
||||
const void* GetFieldDefault(const FieldDescriptor* field) const {
|
||||
return reinterpret_cast<const uint8_t*>(default_instance_) +
|
||||
OffsetValue(offsets_[field->index()], field->type());
|
||||
}
|
||||
|
||||
// Returns true if the field is implicitly backed by LazyField.
|
||||
bool IsEagerlyVerifiedLazyField(const FieldDescriptor* field) const {
|
||||
GOOGLE_DCHECK_EQ(field->type(), FieldDescriptor::TYPE_MESSAGE);
|
||||
(void)field;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsFieldStripped(const FieldDescriptor* field) const {
|
||||
(void)field;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsMessageStripped(const Descriptor* descriptor) const {
|
||||
(void)descriptor;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool HasWeakFields() const { return weak_field_map_offset_ > 0; }
|
||||
|
||||
// These members are intended to be private, but we cannot actually make them
|
||||
// private because this prevents us from using aggregate initialization of
|
||||
// them, ie.
|
||||
//
|
||||
// ReflectionSchema schema = {a, b, c, d, e, ...};
|
||||
// private:
|
||||
const Message* default_instance_;
|
||||
const uint32_t* offsets_;
|
||||
const uint32_t* has_bit_indices_;
|
||||
int has_bits_offset_;
|
||||
int metadata_offset_;
|
||||
int extensions_offset_;
|
||||
int oneof_case_offset_;
|
||||
int object_size_;
|
||||
int weak_field_map_offset_;
|
||||
const uint32_t* inlined_string_indices_;
|
||||
int inlined_string_donated_offset_;
|
||||
|
||||
// We tag offset values to provide additional data about fields (such as
|
||||
// "unused" or "lazy" or "inlined").
|
||||
static uint32_t OffsetValue(uint32_t v, FieldDescriptor::Type type) {
|
||||
if (type == FieldDescriptor::TYPE_MESSAGE ||
|
||||
type == FieldDescriptor::TYPE_STRING ||
|
||||
type == FieldDescriptor::TYPE_BYTES) {
|
||||
return v & 0xFFFFFFFEu;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
static bool Inlined(uint32_t v, FieldDescriptor::Type type) {
|
||||
if (type == FieldDescriptor::TYPE_STRING ||
|
||||
type == FieldDescriptor::TYPE_BYTES) {
|
||||
return (v & 1u) != 0u;
|
||||
} else {
|
||||
// Non string/byte fields are not inlined.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Structs that the code generator emits directly to describe a message.
|
||||
// These should never used directly except to build a ReflectionSchema
|
||||
// object.
|
||||
//
|
||||
// EXPERIMENTAL: these are changing rapidly, and may completely disappear
|
||||
// or merge with ReflectionSchema.
|
||||
struct MigrationSchema {
|
||||
int32_t offsets_index;
|
||||
int32_t has_bit_indices_index;
|
||||
int32_t inlined_string_indices_index;
|
||||
int object_size;
|
||||
};
|
||||
|
||||
// This struct tries to reduce unnecessary padding.
|
||||
// The num_xxx might not be close to their respective pointer, but this saves
|
||||
// padding.
|
||||
struct PROTOBUF_EXPORT DescriptorTable {
|
||||
mutable bool is_initialized;
|
||||
bool is_eager;
|
||||
int size; // of serialized descriptor
|
||||
const char* descriptor;
|
||||
const char* filename;
|
||||
once_flag* once;
|
||||
const DescriptorTable* const* deps;
|
||||
int num_deps;
|
||||
int num_messages;
|
||||
const MigrationSchema* schemas;
|
||||
const Message* const* default_instances;
|
||||
const uint32_t* offsets;
|
||||
// update the following descriptor arrays.
|
||||
Metadata* file_level_metadata;
|
||||
const EnumDescriptor** file_level_enum_descriptors;
|
||||
const ServiceDescriptor** file_level_service_descriptors;
|
||||
};
|
||||
|
||||
enum {
|
||||
// Tag used on offsets for fields that don't have a real offset.
|
||||
// For example, weak message fields go into the WeakFieldMap and not in an
|
||||
// actual field.
|
||||
kInvalidFieldOffsetTag = 0x40000000u,
|
||||
};
|
||||
|
||||
// AssignDescriptors() pulls the compiled FileDescriptor from the DescriptorPool
|
||||
// and uses it to populate all of the global variables which store pointers to
|
||||
// the descriptor objects. It also constructs the reflection objects. It is
|
||||
// called the first time anyone calls descriptor() or GetReflection() on one of
|
||||
// the types defined in the file. AssignDescriptors() is thread-safe.
|
||||
void PROTOBUF_EXPORT AssignDescriptors(const DescriptorTable* table,
|
||||
bool eager = false);
|
||||
|
||||
// Overload used to implement GetMetadataStatic in the generated code.
|
||||
// See comments in compiler/cpp/internal/file.cc as to why.
|
||||
// It takes a `Metadata` and returns it to allow for tail calls and reduce
|
||||
// binary size.
|
||||
Metadata PROTOBUF_EXPORT AssignDescriptors(const DescriptorTable* (*table)(),
|
||||
internal::once_flag* once,
|
||||
const Metadata& metadata);
|
||||
|
||||
// These cannot be in lite so we put them in the reflection.
|
||||
PROTOBUF_EXPORT void UnknownFieldSetSerializer(const uint8_t* base,
|
||||
uint32_t offset, uint32_t tag,
|
||||
uint32_t has_offset,
|
||||
io::CodedOutputStream* output);
|
||||
|
||||
struct PROTOBUF_EXPORT AddDescriptorsRunner {
|
||||
explicit AddDescriptorsRunner(const DescriptorTable* table);
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_GENERATED_MESSAGE_REFLECTION_H__
|
||||
@@ -1,312 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// This file contains declarations needed in generated headers for messages
|
||||
// that use tail-call table parsing. Everything in this file is for internal
|
||||
// use only.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_GENERATED_MESSAGE_TCTABLE_DECL_H__
|
||||
#define GOOGLE_PROTOBUF_GENERATED_MESSAGE_TCTABLE_DECL_H__
|
||||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <type_traits>
|
||||
|
||||
#include <google/protobuf/message_lite.h>
|
||||
#include <google/protobuf/parse_context.h>
|
||||
|
||||
// Must come last:
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
// Additional information about this field:
|
||||
struct TcFieldData {
|
||||
constexpr TcFieldData() : data(0) {}
|
||||
|
||||
// Fast table entry constructor:
|
||||
constexpr TcFieldData(uint16_t coded_tag, uint8_t hasbit_idx, uint8_t aux_idx,
|
||||
uint16_t offset)
|
||||
: data(uint64_t{offset} << 48 | //
|
||||
uint64_t{aux_idx} << 24 | //
|
||||
uint64_t{hasbit_idx} << 16 | //
|
||||
uint64_t{coded_tag}) {}
|
||||
|
||||
// Fields used in fast table parsing:
|
||||
//
|
||||
// Bit:
|
||||
// +-----------+-------------------+
|
||||
// |63 .. 32|31 .. 0|
|
||||
// +---------------+---------------+
|
||||
// : . : . : . 16|=======| [16] coded_tag()
|
||||
// : . : . : 24|===| . : [ 8] hasbit_idx()
|
||||
// : . : . 32|===| : . : [ 8] aux_idx()
|
||||
// : . 48:---.---: . : . : [16] (unused)
|
||||
// |=======| . : . : . : [16] offset()
|
||||
// +-----------+-------------------+
|
||||
// |63 .. 32|31 .. 0|
|
||||
// +---------------+---------------+
|
||||
|
||||
template <typename TagType = uint16_t>
|
||||
TagType coded_tag() const {
|
||||
return static_cast<TagType>(data);
|
||||
}
|
||||
uint8_t hasbit_idx() const { return static_cast<uint8_t>(data >> 16); }
|
||||
uint8_t aux_idx() const { return static_cast<uint8_t>(data >> 24); }
|
||||
uint16_t offset() const { return static_cast<uint16_t>(data >> 48); }
|
||||
|
||||
// Fields used in mini table parsing:
|
||||
//
|
||||
// Bit:
|
||||
// +-----------+-------------------+
|
||||
// |63 .. 32|31 .. 0|
|
||||
// +---------------+---------------+
|
||||
// : . : . |===============| [32] tag() (decoded)
|
||||
// |===============| . : . : [32] entry_offset()
|
||||
// +-----------+-------------------+
|
||||
// |63 .. 32|31 .. 0|
|
||||
// +---------------+---------------+
|
||||
|
||||
uint32_t tag() const { return static_cast<uint32_t>(data); }
|
||||
uint32_t entry_offset() const { return static_cast<uint32_t>(data >> 32); }
|
||||
|
||||
uint64_t data;
|
||||
};
|
||||
|
||||
struct TcParseTableBase;
|
||||
|
||||
// TailCallParseFunc is the function pointer type used in the tailcall table.
|
||||
typedef const char* (*TailCallParseFunc)(PROTOBUF_TC_PARAM_DECL);
|
||||
|
||||
namespace field_layout {
|
||||
struct Offset {
|
||||
uint32_t off;
|
||||
};
|
||||
} // namespace field_layout
|
||||
|
||||
#if defined(_MSC_VER) && !defined(_WIN64)
|
||||
#pragma warning(push)
|
||||
// TcParseTableBase is intentionally overaligned on 32 bit targets.
|
||||
#pragma warning(disable : 4324)
|
||||
#endif
|
||||
|
||||
// Base class for message-level table with info for the tail-call parser.
|
||||
struct alignas(uint64_t) TcParseTableBase {
|
||||
// Common attributes for message layout:
|
||||
uint16_t has_bits_offset;
|
||||
uint16_t extension_offset;
|
||||
uint32_t extension_range_low;
|
||||
uint32_t extension_range_high;
|
||||
uint32_t max_field_number;
|
||||
uint8_t fast_idx_mask;
|
||||
uint16_t lookup_table_offset;
|
||||
uint32_t skipmap32;
|
||||
uint32_t field_entries_offset;
|
||||
uint16_t num_field_entries;
|
||||
|
||||
uint16_t num_aux_entries;
|
||||
uint32_t aux_offset;
|
||||
|
||||
const MessageLite* default_instance;
|
||||
|
||||
// Handler for fields which are not handled by table dispatch.
|
||||
TailCallParseFunc fallback;
|
||||
|
||||
// This constructor exactly follows the field layout, so it's technically
|
||||
// not necessary. However, it makes it much much easier to add or re-arrange
|
||||
// fields, because it can be overloaded with an additional constructor,
|
||||
// temporarily allowing both old and new protocol buffer headers to be
|
||||
// compiled.
|
||||
constexpr TcParseTableBase(
|
||||
uint16_t has_bits_offset, uint16_t extension_offset,
|
||||
uint32_t extension_range_low, uint32_t extension_range_high,
|
||||
uint32_t max_field_number, uint8_t fast_idx_mask,
|
||||
uint16_t lookup_table_offset, uint32_t skipmap32,
|
||||
uint32_t field_entries_offset, uint16_t num_field_entries,
|
||||
uint16_t num_aux_entries, uint32_t aux_offset,
|
||||
const MessageLite* default_instance, TailCallParseFunc fallback)
|
||||
: has_bits_offset(has_bits_offset),
|
||||
extension_offset(extension_offset),
|
||||
extension_range_low(extension_range_low),
|
||||
extension_range_high(extension_range_high),
|
||||
max_field_number(max_field_number),
|
||||
fast_idx_mask(fast_idx_mask),
|
||||
lookup_table_offset(lookup_table_offset),
|
||||
skipmap32(skipmap32),
|
||||
field_entries_offset(field_entries_offset),
|
||||
num_field_entries(num_field_entries),
|
||||
num_aux_entries(num_aux_entries),
|
||||
aux_offset(aux_offset),
|
||||
default_instance(default_instance),
|
||||
fallback(fallback) {}
|
||||
|
||||
// Table entry for fast-path tailcall dispatch handling.
|
||||
struct FastFieldEntry {
|
||||
// Target function for dispatch:
|
||||
TailCallParseFunc target;
|
||||
// Field data used during parse:
|
||||
TcFieldData bits;
|
||||
};
|
||||
// There is always at least one table entry.
|
||||
const FastFieldEntry* fast_entry(size_t idx) const {
|
||||
return reinterpret_cast<const FastFieldEntry*>(this + 1) + idx;
|
||||
}
|
||||
|
||||
// Returns a begin iterator (pointer) to the start of the field lookup table.
|
||||
const uint16_t* field_lookup_begin() const {
|
||||
return reinterpret_cast<const uint16_t*>(reinterpret_cast<uintptr_t>(this) +
|
||||
lookup_table_offset);
|
||||
}
|
||||
|
||||
// Field entry for all fields.
|
||||
struct FieldEntry {
|
||||
uint32_t offset; // offset in the message object
|
||||
int32_t has_idx; // has-bit index
|
||||
uint16_t aux_idx; // index for `field_aux`.
|
||||
uint16_t type_card; // `FieldType` and `Cardinality` (see _impl.h)
|
||||
};
|
||||
|
||||
// Returns a begin iterator (pointer) to the start of the field entries array.
|
||||
const FieldEntry* field_entries_begin() const {
|
||||
return reinterpret_cast<const FieldEntry*>(
|
||||
reinterpret_cast<uintptr_t>(this) + field_entries_offset);
|
||||
}
|
||||
|
||||
// Auxiliary entries for field types that need extra information.
|
||||
union FieldAux {
|
||||
constexpr FieldAux() : message_default(nullptr) {}
|
||||
constexpr FieldAux(bool (*enum_validator)(int))
|
||||
: enum_validator(enum_validator) {}
|
||||
constexpr FieldAux(field_layout::Offset off) : offset(off.off) {}
|
||||
constexpr FieldAux(int16_t range_start, uint16_t range_length)
|
||||
: enum_range{range_start, range_length} {}
|
||||
constexpr FieldAux(const MessageLite* msg) : message_default(msg) {}
|
||||
bool (*enum_validator)(int);
|
||||
struct {
|
||||
int16_t start; // minimum enum number (if it fits)
|
||||
uint16_t length; // length of range (i.e., max = start + length - 1)
|
||||
} enum_range;
|
||||
uint32_t offset;
|
||||
const MessageLite* message_default;
|
||||
};
|
||||
const FieldAux* field_aux(uint32_t idx) const {
|
||||
return reinterpret_cast<const FieldAux*>(reinterpret_cast<uintptr_t>(this) +
|
||||
aux_offset) +
|
||||
idx;
|
||||
}
|
||||
const FieldAux* field_aux(const FieldEntry* entry) const {
|
||||
return field_aux(entry->aux_idx);
|
||||
}
|
||||
|
||||
// Field name data
|
||||
const char* name_data() const {
|
||||
return reinterpret_cast<const char*>(reinterpret_cast<uintptr_t>(this) +
|
||||
aux_offset +
|
||||
num_aux_entries * sizeof(FieldAux));
|
||||
}
|
||||
};
|
||||
|
||||
#if defined(_MSC_VER) && !defined(_WIN64)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
static_assert(sizeof(TcParseTableBase::FastFieldEntry) <= 16,
|
||||
"Fast field entry is too big.");
|
||||
static_assert(sizeof(TcParseTableBase::FieldEntry) <= 16,
|
||||
"Field entry is too big.");
|
||||
|
||||
template <size_t kFastTableSizeLog2, size_t kNumFieldEntries = 0,
|
||||
size_t kNumFieldAux = 0, size_t kNameTableSize = 0,
|
||||
size_t kFieldLookupSize = 2>
|
||||
struct TcParseTable {
|
||||
TcParseTableBase header;
|
||||
|
||||
// Entries for each field.
|
||||
//
|
||||
// Fields are indexed by the lowest bits of their field number. The field
|
||||
// number is masked to fit inside the table. Note that the parsing logic
|
||||
// generally calls `TailCallParseTableBase::fast_entry()` instead of accessing
|
||||
// this field directly.
|
||||
std::array<TcParseTableBase::FastFieldEntry, (1 << kFastTableSizeLog2)>
|
||||
fast_entries;
|
||||
|
||||
// Just big enough to find all the field entries.
|
||||
std::array<uint16_t, kFieldLookupSize> field_lookup_table;
|
||||
// Entries for all fields:
|
||||
std::array<TcParseTableBase::FieldEntry, kNumFieldEntries> field_entries;
|
||||
std::array<TcParseTableBase::FieldAux, kNumFieldAux> aux_entries;
|
||||
std::array<char, kNameTableSize> field_names;
|
||||
};
|
||||
|
||||
// Partial specialization: if there are no aux entries, there will be no array.
|
||||
// In C++, arrays cannot have length 0, but (C++11) std::array<T, 0> is valid.
|
||||
// However, different implementations have different sizeof(std::array<T, 0>).
|
||||
// Skipping the member makes offset computations portable.
|
||||
template <size_t kFastTableSizeLog2, size_t kNumFieldEntries,
|
||||
size_t kNameTableSize, size_t kFieldLookupSize>
|
||||
struct TcParseTable<kFastTableSizeLog2, kNumFieldEntries, 0, kNameTableSize,
|
||||
kFieldLookupSize> {
|
||||
TcParseTableBase header;
|
||||
std::array<TcParseTableBase::FastFieldEntry, (1 << kFastTableSizeLog2)>
|
||||
fast_entries;
|
||||
std::array<uint16_t, kFieldLookupSize> field_lookup_table;
|
||||
std::array<TcParseTableBase::FieldEntry, kNumFieldEntries> field_entries;
|
||||
std::array<char, kNameTableSize> field_names;
|
||||
};
|
||||
|
||||
// Partial specialization: if there are no fields at all, then we can save space
|
||||
// by skipping the field numbers and entries.
|
||||
template <size_t kNameTableSize, size_t kFieldLookupSize>
|
||||
struct TcParseTable<0, 0, 0, kNameTableSize, kFieldLookupSize> {
|
||||
TcParseTableBase header;
|
||||
// N.B.: the fast entries are sized by log2, so 2**0 fields = 1 entry.
|
||||
// The fast parsing loop will always use this entry, so it must be present.
|
||||
std::array<TcParseTableBase::FastFieldEntry, 1> fast_entries;
|
||||
std::array<uint16_t, kFieldLookupSize> field_lookup_table;
|
||||
std::array<char, kNameTableSize> field_names;
|
||||
};
|
||||
|
||||
static_assert(std::is_standard_layout<TcParseTable<1>>::value,
|
||||
"TcParseTable must be standard layout.");
|
||||
|
||||
static_assert(offsetof(TcParseTable<1>, fast_entries) ==
|
||||
sizeof(TcParseTableBase),
|
||||
"Table entries must be laid out after TcParseTableBase.");
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_GENERATED_MESSAGE_TCTABLE_DECL_H__
|
||||
@@ -1,565 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_GENERATED_MESSAGE_TCTABLE_IMPL_H__
|
||||
#define GOOGLE_PROTOBUF_GENERATED_MESSAGE_TCTABLE_IMPL_H__
|
||||
|
||||
#include <cstdint>
|
||||
#include <type_traits>
|
||||
|
||||
#include <google/protobuf/port.h>
|
||||
#include <google/protobuf/extension_set.h>
|
||||
#include <google/protobuf/generated_message_tctable_decl.h>
|
||||
#include <google/protobuf/message_lite.h>
|
||||
#include <google/protobuf/metadata_lite.h>
|
||||
#include <google/protobuf/parse_context.h>
|
||||
#include <google/protobuf/wire_format_lite.h>
|
||||
|
||||
// Must come last:
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
class Message;
|
||||
class UnknownFieldSet;
|
||||
|
||||
namespace internal {
|
||||
|
||||
// Field layout enums.
|
||||
//
|
||||
// Structural information about fields is packed into a 16-bit value. The enum
|
||||
// types below represent bitwise fields, along with their respective widths,
|
||||
// shifts, and masks.
|
||||
//
|
||||
// Bit:
|
||||
// +-----------------------+-----------------------+
|
||||
// |15 .. 8|7 .. 0|
|
||||
// +-----------------------+-----------------------+
|
||||
// : . : . : . : . : . : . : 3|========| [3] FieldType
|
||||
// : : : : : : 5|=====| : : [2] FieldCardinality
|
||||
// : . : . : . : . 8|========| : . : . : [3] FieldRep
|
||||
// : : : 10|=====| : : : : [2] TransformValidation
|
||||
// : . : .12|=====| . : . : . : . : . : [2] FormatDiscriminator
|
||||
// +-----------------------+-----------------------+
|
||||
// |15 .. 8|7 .. 0|
|
||||
// +-----------------------+-----------------------+
|
||||
//
|
||||
namespace field_layout {
|
||||
// clang-format off
|
||||
|
||||
// Field kind (3 bits):
|
||||
// These values broadly represent a wire type and an in-memory storage class.
|
||||
enum FieldKind : uint16_t {
|
||||
kFkShift = 0,
|
||||
kFkBits = 3,
|
||||
kFkMask = ((1 << kFkBits) - 1) << kFkShift,
|
||||
|
||||
kFkNone = 0,
|
||||
kFkVarint, // WT=0 rep=8,32,64 bits
|
||||
kFkPackedVarint, // WT=2 rep=8,32,64 bits
|
||||
kFkFixed, // WT=1,5 rep=32,64 bits
|
||||
kFkPackedFixed, // WT=2 rep=32,64 bits
|
||||
kFkString, // WT=2 rep=various
|
||||
kFkMessage, // WT=2,3,4 rep=MessageLite*
|
||||
// Maps are a special case of Message, but use different parsing logic.
|
||||
kFkMap, // WT=2 rep=Map(Lite)<various, various>
|
||||
};
|
||||
|
||||
static_assert(kFkMap < (1 << kFkBits), "too many types");
|
||||
|
||||
// Cardinality (2 bits):
|
||||
// These values determine how many values a field can have and its presence.
|
||||
// Packed fields are represented in FieldType.
|
||||
enum Cardinality : uint16_t {
|
||||
kFcShift = kFkShift + kFkBits,
|
||||
kFcBits = 2,
|
||||
kFcMask = ((1 << kFcBits) - 1) << kFcShift,
|
||||
|
||||
kFcSingular = 0,
|
||||
kFcOptional = 1 << kFcShift,
|
||||
kFcRepeated = 2 << kFcShift,
|
||||
kFcOneof = 3 << kFcShift,
|
||||
};
|
||||
|
||||
// Field representation (3 bits):
|
||||
// These values are the specific refinements of storage classes in FieldType.
|
||||
enum FieldRep : uint16_t {
|
||||
kRepShift = kFcShift + kFcBits,
|
||||
kRepBits = 3,
|
||||
kRepMask = ((1 << kRepBits) - 1) << kRepShift,
|
||||
|
||||
// Numeric types (used for optional and repeated fields):
|
||||
kRep8Bits = 0,
|
||||
kRep32Bits = 2 << kRepShift,
|
||||
kRep64Bits = 3 << kRepShift,
|
||||
// String types:
|
||||
kRepAString = 0, // ArenaStringPtr
|
||||
kRepIString = 1 << kRepShift, // InlinedString
|
||||
kRepCord = 2 << kRepShift, // absl::Cord
|
||||
kRepSPiece = 3 << kRepShift, // StringPieceField
|
||||
kRepSString = 4 << kRepShift, // std::string*
|
||||
// Message types (WT=2 unless otherwise noted):
|
||||
kRepMessage = 0, // MessageLite*
|
||||
kRepGroup = 1 << kRepShift, // MessageLite* (WT=3,4)
|
||||
kRepLazy = 2 << kRepShift, // LazyField*
|
||||
kRepIWeak = 3 << kRepShift, // ImplicitWeak
|
||||
};
|
||||
|
||||
// Transform/validation (2 bits):
|
||||
// These values determine transforms or validation to/from wire format.
|
||||
enum TransformValidation : uint16_t {
|
||||
kTvShift = kRepShift + kRepBits,
|
||||
kTvBits = 2,
|
||||
kTvMask = ((1 << kTvBits) - 1) << kTvShift,
|
||||
|
||||
// Varint fields:
|
||||
kTvZigZag = 1 << kTvShift,
|
||||
kTvEnum = 2 << kTvShift, // validate using generated _IsValid()
|
||||
kTvRange = 3 << kTvShift, // validate using FieldAux::enum_range
|
||||
// String fields:
|
||||
kTvUtf8Debug = 1 << kTvShift, // proto2
|
||||
kTvUtf8 = 2 << kTvShift, // proto3
|
||||
};
|
||||
|
||||
static_assert((kTvEnum & kTvRange) != 0,
|
||||
"enum validation types must share a bit");
|
||||
static_assert((kTvEnum & kTvRange & kTvZigZag) == 0,
|
||||
"zigzag encoding is not enum validation");
|
||||
|
||||
// Format discriminators (2 bits):
|
||||
enum FormatDiscriminator : uint16_t {
|
||||
kFmtShift = kTvShift + kTvBits,
|
||||
kFmtBits = 2,
|
||||
kFmtMask = ((1 << kFmtBits) - 1) << kFmtShift,
|
||||
|
||||
// Numeric:
|
||||
kFmtUnsigned = 1 << kFmtShift, // fixed, varint
|
||||
kFmtSigned = 2 << kFmtShift, // fixed, varint
|
||||
kFmtFloating = 3 << kFmtShift, // fixed
|
||||
kFmtEnum = 3 << kFmtShift, // varint
|
||||
// Strings:
|
||||
kFmtUtf8 = 1 << kFmtShift, // string (proto3, enforce_utf8=true)
|
||||
kFmtUtf8Escape = 2 << kFmtShift, // string (proto2, enforce_utf8=false)
|
||||
// Bytes:
|
||||
kFmtArray = 1 << kFmtShift, // bytes
|
||||
// Messages:
|
||||
kFmtShow = 1 << kFmtShift, // message, map
|
||||
};
|
||||
|
||||
// Update this assertion (and comments above) when adding or removing bits:
|
||||
static_assert(kFmtShift + kFmtBits == 12, "number of bits changed");
|
||||
|
||||
// This assertion should not change unless the storage width changes:
|
||||
static_assert(kFmtShift + kFmtBits <= 16, "too many bits");
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#if __GNUC__ >= 12 || (__GNUC__ == 11 && __GNUC_MINOR__ >= 1)
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-enum-enum-conversion"
|
||||
#endif
|
||||
#endif
|
||||
// Convenience aliases (16 bits, with format):
|
||||
enum FieldType : uint16_t {
|
||||
// Numeric types:
|
||||
kBool = kFkVarint | kRep8Bits,
|
||||
|
||||
kFixed32 = kFkFixed | kRep32Bits | kFmtUnsigned,
|
||||
kUInt32 = kFkVarint | kRep32Bits | kFmtUnsigned,
|
||||
kSFixed32 = kFkFixed | kRep32Bits | kFmtSigned,
|
||||
kInt32 = kFkVarint | kRep32Bits | kFmtSigned,
|
||||
kSInt32 = kFkVarint | kRep32Bits | kFmtSigned | kTvZigZag,
|
||||
kFloat = kFkFixed | kRep32Bits | kFmtFloating,
|
||||
kEnum = kFkVarint | kRep32Bits | kFmtEnum | kTvEnum,
|
||||
kEnumRange = kFkVarint | kRep32Bits | kFmtEnum | kTvRange,
|
||||
kOpenEnum = kFkVarint | kRep32Bits | kFmtEnum,
|
||||
|
||||
kFixed64 = kFkFixed | kRep64Bits | kFmtUnsigned,
|
||||
kUInt64 = kFkVarint | kRep64Bits | kFmtUnsigned,
|
||||
kSFixed64 = kFkFixed | kRep64Bits | kFmtSigned,
|
||||
kInt64 = kFkVarint | kRep64Bits | kFmtSigned,
|
||||
kSInt64 = kFkVarint | kRep64Bits | kFmtSigned | kTvZigZag,
|
||||
kDouble = kFkFixed | kRep64Bits | kFmtFloating,
|
||||
|
||||
kPackedBool = kFkPackedVarint | kRep8Bits,
|
||||
|
||||
kPackedFixed32 = kFkPackedFixed | kRep32Bits | kFmtUnsigned,
|
||||
kPackedUInt32 = kFkPackedVarint | kRep32Bits | kFmtUnsigned,
|
||||
kPackedSFixed32 = kFkPackedFixed | kRep32Bits | kFmtSigned,
|
||||
kPackedInt32 = kFkPackedVarint | kRep32Bits | kFmtSigned,
|
||||
kPackedSInt32 = kFkPackedVarint | kRep32Bits | kFmtSigned | kTvZigZag,
|
||||
kPackedFloat = kFkPackedFixed | kRep32Bits | kFmtFloating,
|
||||
kPackedEnum = kFkPackedVarint | kRep32Bits | kFmtEnum | kTvEnum,
|
||||
kPackedEnumRange = kFkPackedVarint | kRep32Bits | kFmtEnum | kTvRange,
|
||||
kPackedOpenEnum = kFkPackedVarint | kRep32Bits | kFmtEnum,
|
||||
|
||||
kPackedFixed64 = kFkPackedFixed | kRep64Bits | kFmtUnsigned,
|
||||
kPackedUInt64 = kFkPackedVarint | kRep64Bits | kFmtUnsigned,
|
||||
kPackedSFixed64 = kFkPackedFixed | kRep64Bits | kFmtSigned,
|
||||
kPackedInt64 = kFkPackedVarint | kRep64Bits | kFmtSigned,
|
||||
kPackedSInt64 = kFkPackedVarint | kRep64Bits | kFmtSigned | kTvZigZag,
|
||||
kPackedDouble = kFkPackedFixed | kRep64Bits | kFmtFloating,
|
||||
|
||||
// String types:
|
||||
kBytes = kFkString | kFmtArray,
|
||||
kRawString = kFkString | kFmtUtf8 | kTvUtf8Debug,
|
||||
kUtf8String = kFkString | kFmtUtf8 | kTvUtf8,
|
||||
|
||||
// Message types:
|
||||
kMessage = kFkMessage,
|
||||
|
||||
// Map types:
|
||||
kMap = kFkMap,
|
||||
};
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
// clang-format on
|
||||
} // namespace field_layout
|
||||
|
||||
// PROTOBUF_TC_PARAM_DECL are the parameters for tailcall functions, it is
|
||||
// defined in port_def.inc.
|
||||
//
|
||||
// Note that this is performance sensitive: changing the parameters will change
|
||||
// the registers used by the ABI calling convention, which subsequently affects
|
||||
// register selection logic inside the function.
|
||||
|
||||
// PROTOBUF_TC_PARAM_PASS passes values to match PROTOBUF_TC_PARAM_DECL.
|
||||
#define PROTOBUF_TC_PARAM_PASS msg, ptr, ctx, table, hasbits, data
|
||||
|
||||
#ifndef NDEBUG
|
||||
template <size_t align>
|
||||
#ifndef _MSC_VER
|
||||
[[noreturn]]
|
||||
#endif
|
||||
void AlignFail(uintptr_t address) {
|
||||
GOOGLE_LOG(FATAL) << "Unaligned (" << align << ") access at " << address;
|
||||
#ifdef __GNUC__
|
||||
__builtin_unreachable();
|
||||
#endif
|
||||
}
|
||||
|
||||
extern template void AlignFail<4>(uintptr_t);
|
||||
extern template void AlignFail<8>(uintptr_t);
|
||||
#endif
|
||||
|
||||
// TcParser implements most of the parsing logic for tailcall tables.
|
||||
class PROTOBUF_EXPORT TcParser final {
|
||||
public:
|
||||
static const char* GenericFallback(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* GenericFallbackLite(PROTOBUF_TC_PARAM_DECL);
|
||||
|
||||
static const char* ParseLoop(MessageLite* msg, const char* ptr,
|
||||
ParseContext* ctx,
|
||||
const TcParseTableBase* table);
|
||||
|
||||
// Functions referenced by generated fast tables (numeric types):
|
||||
// F: fixed V: varint Z: zigzag
|
||||
// 8/32/64: storage type width (bits)
|
||||
// S: singular R: repeated P: packed
|
||||
// 1/2: tag length (bytes)
|
||||
|
||||
// Fixed:
|
||||
static const char* FastF32S1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastF32S2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastF32R1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastF32R2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastF32P1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastF32P2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastF64S1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastF64S2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastF64R1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastF64R2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastF64P1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastF64P2(PROTOBUF_TC_PARAM_DECL);
|
||||
|
||||
// Varint:
|
||||
static const char* FastV8S1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastV8S2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastV8R1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastV8R2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastV8P1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastV8P2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastV32S1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastV32S2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastV32R1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastV32R2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastV32P1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastV32P2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastV64S1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastV64S2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastV64R1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastV64R2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastV64P1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastV64P2(PROTOBUF_TC_PARAM_DECL);
|
||||
|
||||
// Varint (with zigzag):
|
||||
static const char* FastZ32S1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastZ32S2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastZ32R1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastZ32R2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastZ32P1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastZ32P2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastZ64S1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastZ64S2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastZ64R1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastZ64R2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastZ64P1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastZ64P2(PROTOBUF_TC_PARAM_DECL);
|
||||
|
||||
// Functions referenced by generated fast tables (closed enum):
|
||||
// E: closed enum (N.B.: open enums use V32, above)
|
||||
// r: enum range v: enum validator (_IsValid function)
|
||||
// S: singular R: repeated
|
||||
// 1/2: tag length (bytes)
|
||||
static const char* FastErS1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastErS2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastErR1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastErR2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastEvS1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastEvS2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastEvR1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastEvR2(PROTOBUF_TC_PARAM_DECL);
|
||||
|
||||
// Functions referenced by generated fast tables (string types):
|
||||
// B: bytes S: string U: UTF-8 string
|
||||
// (empty): ArenaStringPtr i: InlinedString
|
||||
// S: singular R: repeated
|
||||
// 1/2: tag length (bytes)
|
||||
static const char* FastBS1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastBS2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastBR1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastBR2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastSS1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastSS2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastSR1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastSR2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastUS1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastUS2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastUR1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastUR2(PROTOBUF_TC_PARAM_DECL);
|
||||
|
||||
static const char* FastBiS1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastBiS2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastSiS1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastSiS2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastUiS1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastUiS2(PROTOBUF_TC_PARAM_DECL);
|
||||
|
||||
// Functions referenced by generated fast tables (message types):
|
||||
// M: message G: group
|
||||
// S: singular R: repeated
|
||||
// 1/2: tag length (bytes)
|
||||
static const char* FastMS1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastMS2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastMR1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastMR2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastGS1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastGS2(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastGR1(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* FastGR2(PROTOBUF_TC_PARAM_DECL);
|
||||
|
||||
template <typename T>
|
||||
static inline T& RefAt(void* x, size_t offset) {
|
||||
T* target = reinterpret_cast<T*>(static_cast<char*>(x) + offset);
|
||||
#ifndef NDEBUG
|
||||
if (PROTOBUF_PREDICT_FALSE(
|
||||
reinterpret_cast<uintptr_t>(target) % alignof(T) != 0)) {
|
||||
AlignFail<alignof(T)>(reinterpret_cast<uintptr_t>(target));
|
||||
}
|
||||
#endif
|
||||
return *target;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static inline const T& RefAt(const void* x, size_t offset) {
|
||||
const T* target =
|
||||
reinterpret_cast<const T*>(static_cast<const char*>(x) + offset);
|
||||
#ifndef NDEBUG
|
||||
if (PROTOBUF_PREDICT_FALSE(
|
||||
reinterpret_cast<uintptr_t>(target) % alignof(T) != 0)) {
|
||||
AlignFail<alignof(T)>(reinterpret_cast<uintptr_t>(target));
|
||||
}
|
||||
#endif
|
||||
return *target;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static inline T ReadAt(const void* x, size_t offset) {
|
||||
T out;
|
||||
memcpy(&out, static_cast<const char*>(x) + offset, sizeof(T));
|
||||
return out;
|
||||
}
|
||||
|
||||
// Mini parsing:
|
||||
//
|
||||
// This function parses a field from incoming data based on metadata stored in
|
||||
// the message definition. If the field is not defined in the message, it is
|
||||
// stored in either the ExtensionSet (if applicable) or the UnknownFieldSet.
|
||||
//
|
||||
// NOTE: Currently, this function only calls the table-level fallback
|
||||
// function, so it should only be called as the fallback from fast table
|
||||
// parsing.
|
||||
static const char* MiniParse(PROTOBUF_TC_PARAM_DECL);
|
||||
|
||||
private:
|
||||
friend class GeneratedTcTableLiteTest;
|
||||
|
||||
template <typename TagType, bool group_coding>
|
||||
static inline const char* SingularParseMessageAuxImpl(PROTOBUF_TC_PARAM_DECL);
|
||||
template <typename TagType, bool group_coding>
|
||||
static inline const char* RepeatedParseMessageAuxImpl(PROTOBUF_TC_PARAM_DECL);
|
||||
|
||||
static inline PROTOBUF_ALWAYS_INLINE void SyncHasbits(
|
||||
MessageLite* msg, uint64_t hasbits, const TcParseTableBase* table) {
|
||||
const uint32_t has_bits_offset = table->has_bits_offset;
|
||||
if (has_bits_offset) {
|
||||
// Only the first 32 has-bits are updated. Nothing above those is stored,
|
||||
// but e.g. messages without has-bits update the upper bits.
|
||||
RefAt<uint32_t>(msg, has_bits_offset) = static_cast<uint32_t>(hasbits);
|
||||
}
|
||||
}
|
||||
|
||||
static const char* TagDispatch(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* ToTagDispatch(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* ToParseLoop(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* Error(PROTOBUF_TC_PARAM_DECL);
|
||||
|
||||
static const char* FastUnknownEnumFallback(PROTOBUF_TC_PARAM_DECL);
|
||||
|
||||
class ScopedArenaSwap;
|
||||
|
||||
template <class MessageBaseT, class UnknownFieldsT>
|
||||
static const char* GenericFallbackImpl(PROTOBUF_TC_PARAM_DECL) {
|
||||
#define CHK_(x) \
|
||||
if (PROTOBUF_PREDICT_FALSE(!(x))) return nullptr /* NOLINT */
|
||||
|
||||
SyncHasbits(msg, hasbits, table);
|
||||
CHK_(ptr);
|
||||
uint32_t tag = data.tag();
|
||||
if ((tag & 7) == WireFormatLite::WIRETYPE_END_GROUP || tag == 0) {
|
||||
ctx->SetLastTag(tag);
|
||||
return ptr;
|
||||
}
|
||||
uint32_t num = tag >> 3;
|
||||
if (table->extension_range_low <= num &&
|
||||
num <= table->extension_range_high) {
|
||||
return RefAt<ExtensionSet>(msg, table->extension_offset)
|
||||
.ParseField(tag, ptr,
|
||||
static_cast<const MessageBaseT*>(table->default_instance),
|
||||
&msg->_internal_metadata_, ctx);
|
||||
}
|
||||
return UnknownFieldParse(
|
||||
tag, msg->_internal_metadata_.mutable_unknown_fields<UnknownFieldsT>(),
|
||||
ptr, ctx);
|
||||
#undef CHK_
|
||||
}
|
||||
|
||||
// Note: `inline` is needed on template function declarations below to avoid
|
||||
// -Wattributes diagnostic in GCC.
|
||||
|
||||
// Implementations for fast fixed field parsing functions:
|
||||
template <typename LayoutType, typename TagType>
|
||||
static inline const char* SingularFixed(PROTOBUF_TC_PARAM_DECL);
|
||||
template <typename LayoutType, typename TagType>
|
||||
static inline const char* RepeatedFixed(PROTOBUF_TC_PARAM_DECL);
|
||||
template <typename LayoutType, typename TagType>
|
||||
static inline const char* PackedFixed(PROTOBUF_TC_PARAM_DECL);
|
||||
|
||||
// Implementations for fast varint field parsing functions:
|
||||
template <typename FieldType, typename TagType, bool zigzag = false>
|
||||
static inline const char* SingularVarint(PROTOBUF_TC_PARAM_DECL);
|
||||
template <typename FieldType, typename TagType, bool zigzag = false>
|
||||
static inline const char* RepeatedVarint(PROTOBUF_TC_PARAM_DECL);
|
||||
template <typename FieldType, typename TagType, bool zigzag = false>
|
||||
static inline const char* PackedVarint(PROTOBUF_TC_PARAM_DECL);
|
||||
|
||||
// Helper for ints > 127:
|
||||
template <typename FieldType, typename TagType, bool zigzag = false>
|
||||
static const char* SingularVarBigint(PROTOBUF_TC_PARAM_DECL);
|
||||
|
||||
// Implementations for fast enum field parsing functions:
|
||||
template <typename TagType, uint16_t xform_val>
|
||||
static inline const char* SingularEnum(PROTOBUF_TC_PARAM_DECL);
|
||||
template <typename TagType, uint16_t xform_val>
|
||||
static inline const char* RepeatedEnum(PROTOBUF_TC_PARAM_DECL);
|
||||
|
||||
// Implementations for fast string field parsing functions:
|
||||
enum Utf8Type { kNoUtf8 = 0, kUtf8 = 1, kUtf8ValidateOnly = 2 };
|
||||
template <typename TagType, Utf8Type utf8>
|
||||
static inline const char* SingularString(PROTOBUF_TC_PARAM_DECL);
|
||||
template <typename TagType, Utf8Type utf8>
|
||||
static inline const char* RepeatedString(PROTOBUF_TC_PARAM_DECL);
|
||||
|
||||
// Mini field lookup:
|
||||
static const TcParseTableBase::FieldEntry* FindFieldEntry(
|
||||
const TcParseTableBase* table, uint32_t field_num);
|
||||
static StringPiece MessageName(const TcParseTableBase* table);
|
||||
static StringPiece FieldName(const TcParseTableBase* table,
|
||||
const TcParseTableBase::FieldEntry*);
|
||||
static bool ChangeOneof(const TcParseTableBase* table,
|
||||
const TcParseTableBase::FieldEntry& entry,
|
||||
uint32_t field_num, ParseContext* ctx,
|
||||
MessageLite* msg);
|
||||
|
||||
// UTF-8 validation:
|
||||
static void ReportFastUtf8Error(uint32_t decoded_tag,
|
||||
const TcParseTableBase* table);
|
||||
static bool MpVerifyUtf8(StringPiece wire_bytes,
|
||||
const TcParseTableBase* table,
|
||||
const TcParseTableBase::FieldEntry& entry,
|
||||
uint16_t xform_val);
|
||||
|
||||
// For FindFieldEntry tests:
|
||||
friend class FindFieldEntryTest;
|
||||
static constexpr const uint32_t kMtSmallScanSize = 4;
|
||||
|
||||
// Mini parsing:
|
||||
static const char* MpVarint(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* MpRepeatedVarint(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* MpPackedVarint(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* MpFixed(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* MpRepeatedFixed(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* MpPackedFixed(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* MpString(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* MpRepeatedString(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* MpMessage(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* MpRepeatedMessage(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* MpMap(PROTOBUF_TC_PARAM_DECL);
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_GENERATED_MESSAGE_TCTABLE_IMPL_H__
|
||||
@@ -1,214 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
//
|
||||
// This file contains miscellaneous helper code used by generated code --
|
||||
// including lite types -- but which should not be used directly by users.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__
|
||||
#define GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <climits>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/once.h> // Add direct dep on port for pb.cc
|
||||
#include <google/protobuf/port.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
#include <google/protobuf/any.h>
|
||||
#include <google/protobuf/has_bits.h>
|
||||
#include <google/protobuf/implicit_weak_message.h>
|
||||
#include <google/protobuf/message_lite.h>
|
||||
#include <google/protobuf/repeated_field.h>
|
||||
#include <google/protobuf/wire_format_lite.h>
|
||||
#include <google/protobuf/stubs/casts.h>
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
#ifdef SWIG
|
||||
#error "You cannot SWIG proto headers"
|
||||
#endif
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
class Arena;
|
||||
class Message;
|
||||
|
||||
namespace io {
|
||||
class CodedInputStream;
|
||||
}
|
||||
|
||||
namespace internal {
|
||||
|
||||
template <typename To, typename From>
|
||||
inline To DownCast(From* f) {
|
||||
return PROTOBUF_NAMESPACE_ID::internal::down_cast<To>(f);
|
||||
}
|
||||
template <typename To, typename From>
|
||||
inline To DownCast(From& f) {
|
||||
return PROTOBUF_NAMESPACE_ID::internal::down_cast<To>(f);
|
||||
}
|
||||
|
||||
|
||||
// This fastpath inlines a single branch instead of having to make the
|
||||
// InitProtobufDefaults function call.
|
||||
// It also generates less inlined code than a function-scope static initializer.
|
||||
PROTOBUF_EXPORT extern std::atomic<bool> init_protobuf_defaults_state;
|
||||
PROTOBUF_EXPORT void InitProtobufDefaultsSlow();
|
||||
PROTOBUF_EXPORT inline void InitProtobufDefaults() {
|
||||
if (PROTOBUF_PREDICT_FALSE(
|
||||
!init_protobuf_defaults_state.load(std::memory_order_acquire))) {
|
||||
InitProtobufDefaultsSlow();
|
||||
}
|
||||
}
|
||||
|
||||
// This used by proto1
|
||||
PROTOBUF_EXPORT inline const std::string& GetEmptyString() {
|
||||
InitProtobufDefaults();
|
||||
return GetEmptyStringAlreadyInited();
|
||||
}
|
||||
|
||||
|
||||
// True if IsInitialized() is true for all elements of t. Type is expected
|
||||
// to be a RepeatedPtrField<some message type>. It's useful to have this
|
||||
// helper here to keep the protobuf compiler from ever having to emit loops in
|
||||
// IsInitialized() methods. We want the C++ compiler to inline this or not
|
||||
// as it sees fit.
|
||||
template <typename Msg>
|
||||
bool AllAreInitialized(const RepeatedPtrField<Msg>& t) {
|
||||
for (int i = t.size(); --i >= 0;) {
|
||||
if (!t.Get(i).IsInitialized()) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// "Weak" variant of AllAreInitialized, used to implement implicit weak fields.
|
||||
// This version operates on MessageLite to avoid introducing a dependency on the
|
||||
// concrete message type.
|
||||
template <class T>
|
||||
bool AllAreInitializedWeak(const RepeatedPtrField<T>& t) {
|
||||
for (int i = t.size(); --i >= 0;) {
|
||||
if (!reinterpret_cast<const RepeatedPtrFieldBase&>(t)
|
||||
.Get<ImplicitWeakTypeHandler<T> >(i)
|
||||
.IsInitialized()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool IsPresent(const void* base, uint32_t hasbit) {
|
||||
const uint32_t* has_bits_array = static_cast<const uint32_t*>(base);
|
||||
return (has_bits_array[hasbit / 32] & (1u << (hasbit & 31))) != 0;
|
||||
}
|
||||
|
||||
inline bool IsOneofPresent(const void* base, uint32_t offset, uint32_t tag) {
|
||||
const uint32_t* oneof = reinterpret_cast<const uint32_t*>(
|
||||
static_cast<const uint8_t*>(base) + offset);
|
||||
return *oneof == tag >> 3;
|
||||
}
|
||||
|
||||
typedef void (*SpecialSerializer)(const uint8_t* base, uint32_t offset,
|
||||
uint32_t tag, uint32_t has_offset,
|
||||
io::CodedOutputStream* output);
|
||||
|
||||
PROTOBUF_EXPORT void ExtensionSerializer(const MessageLite* extendee,
|
||||
const uint8_t* ptr, uint32_t offset,
|
||||
uint32_t tag, uint32_t has_offset,
|
||||
io::CodedOutputStream* output);
|
||||
PROTOBUF_EXPORT void UnknownFieldSerializerLite(const uint8_t* base,
|
||||
uint32_t offset, uint32_t tag,
|
||||
uint32_t has_offset,
|
||||
io::CodedOutputStream* output);
|
||||
|
||||
PROTOBUF_EXPORT MessageLite* DuplicateIfNonNullInternal(MessageLite* message);
|
||||
PROTOBUF_EXPORT MessageLite* GetOwnedMessageInternal(Arena* message_arena,
|
||||
MessageLite* submessage,
|
||||
Arena* submessage_arena);
|
||||
PROTOBUF_EXPORT void GenericSwap(MessageLite* m1, MessageLite* m2);
|
||||
// We specialize GenericSwap for non-lite messages to benefit from reflection.
|
||||
PROTOBUF_EXPORT void GenericSwap(Message* m1, Message* m2);
|
||||
|
||||
template <typename T>
|
||||
T* DuplicateIfNonNull(T* message) {
|
||||
// The casts must be reinterpret_cast<> because T might be a forward-declared
|
||||
// type that the compiler doesn't know is related to MessageLite.
|
||||
return reinterpret_cast<T*>(
|
||||
DuplicateIfNonNullInternal(reinterpret_cast<MessageLite*>(message)));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T* GetOwnedMessage(Arena* message_arena, T* submessage,
|
||||
Arena* submessage_arena) {
|
||||
// The casts must be reinterpret_cast<> because T might be a forward-declared
|
||||
// type that the compiler doesn't know is related to MessageLite.
|
||||
return reinterpret_cast<T*>(GetOwnedMessageInternal(
|
||||
message_arena, reinterpret_cast<MessageLite*>(submessage),
|
||||
submessage_arena));
|
||||
}
|
||||
|
||||
// Hide atomic from the public header and allow easy change to regular int
|
||||
// on platforms where the atomic might have a perf impact.
|
||||
class PROTOBUF_EXPORT CachedSize {
|
||||
public:
|
||||
int Get() const { return size_.load(std::memory_order_relaxed); }
|
||||
void Set(int size) { size_.store(size, std::memory_order_relaxed); }
|
||||
|
||||
private:
|
||||
std::atomic<int> size_{0};
|
||||
};
|
||||
|
||||
PROTOBUF_EXPORT void DestroyMessage(const void* message);
|
||||
PROTOBUF_EXPORT void DestroyString(const void* s);
|
||||
// Destroy (not delete) the message
|
||||
inline void OnShutdownDestroyMessage(const void* ptr) {
|
||||
OnShutdownRun(DestroyMessage, ptr);
|
||||
}
|
||||
// Destroy the string (call std::string destructor)
|
||||
inline void OnShutdownDestroyString(const std::string* ptr) {
|
||||
OnShutdownRun(DestroyString, ptr);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__
|
||||
@@ -1,117 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_HAS_BITS_H__
|
||||
#define GOOGLE_PROTOBUF_HAS_BITS_H__
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/port.h>
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
#ifdef SWIG
|
||||
#error "You cannot SWIG proto headers"
|
||||
#endif
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
template <size_t doublewords>
|
||||
class HasBits {
|
||||
public:
|
||||
PROTOBUF_NDEBUG_INLINE constexpr HasBits() : has_bits_{} {}
|
||||
|
||||
PROTOBUF_NDEBUG_INLINE void Clear() {
|
||||
memset(has_bits_, 0, sizeof(has_bits_));
|
||||
}
|
||||
|
||||
PROTOBUF_NDEBUG_INLINE uint32_t& operator[](int index) {
|
||||
return has_bits_[index];
|
||||
}
|
||||
|
||||
PROTOBUF_NDEBUG_INLINE const uint32_t& operator[](int index) const {
|
||||
return has_bits_[index];
|
||||
}
|
||||
|
||||
bool operator==(const HasBits<doublewords>& rhs) const {
|
||||
return memcmp(has_bits_, rhs.has_bits_, sizeof(has_bits_)) == 0;
|
||||
}
|
||||
|
||||
bool operator!=(const HasBits<doublewords>& rhs) const {
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
void Or(const HasBits<doublewords>& rhs) {
|
||||
for (size_t i = 0; i < doublewords; i++) has_bits_[i] |= rhs[i];
|
||||
}
|
||||
|
||||
bool empty() const;
|
||||
|
||||
private:
|
||||
uint32_t has_bits_[doublewords];
|
||||
};
|
||||
|
||||
template <>
|
||||
inline bool HasBits<1>::empty() const {
|
||||
return !has_bits_[0];
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool HasBits<2>::empty() const {
|
||||
return !(has_bits_[0] | has_bits_[1]);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool HasBits<3>::empty() const {
|
||||
return !(has_bits_[0] | has_bits_[1] | has_bits_[2]);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool HasBits<4>::empty() const {
|
||||
return !(has_bits_[0] | has_bits_[1] | has_bits_[2] | has_bits_[3]);
|
||||
}
|
||||
|
||||
template <size_t doublewords>
|
||||
inline bool HasBits<doublewords>::empty() const {
|
||||
for (size_t i = 0; i < doublewords; ++i) {
|
||||
if (has_bits_[i]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_HAS_BITS_H__
|
||||
@@ -1,213 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_IMPLICIT_WEAK_MESSAGE_H__
|
||||
#define GOOGLE_PROTOBUF_IMPLICIT_WEAK_MESSAGE_H__
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/arena.h>
|
||||
#include <google/protobuf/message_lite.h>
|
||||
#include <google/protobuf/repeated_field.h>
|
||||
|
||||
#ifdef SWIG
|
||||
#error "You cannot SWIG proto headers"
|
||||
#endif
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
// This file is logically internal-only and should only be used by protobuf
|
||||
// generated code.
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
// An implementation of MessageLite that treats all data as unknown. This type
|
||||
// acts as a placeholder for an implicit weak field in the case where the true
|
||||
// message type does not get linked into the binary.
|
||||
class PROTOBUF_EXPORT ImplicitWeakMessage : public MessageLite {
|
||||
public:
|
||||
ImplicitWeakMessage() : data_(new std::string) {}
|
||||
explicit constexpr ImplicitWeakMessage(ConstantInitialized)
|
||||
: data_(nullptr) {}
|
||||
explicit ImplicitWeakMessage(Arena* arena)
|
||||
: MessageLite(arena), data_(new std::string) {}
|
||||
|
||||
~ImplicitWeakMessage() override {
|
||||
// data_ will be null in the default instance, but we can safely call delete
|
||||
// here because the default instance will never be destroyed.
|
||||
delete data_;
|
||||
}
|
||||
|
||||
static const ImplicitWeakMessage* default_instance();
|
||||
|
||||
std::string GetTypeName() const override { return ""; }
|
||||
|
||||
MessageLite* New(Arena* arena) const override {
|
||||
return Arena::CreateMessage<ImplicitWeakMessage>(arena);
|
||||
}
|
||||
|
||||
void Clear() override { data_->clear(); }
|
||||
|
||||
bool IsInitialized() const override { return true; }
|
||||
|
||||
void CheckTypeAndMergeFrom(const MessageLite& other) override {
|
||||
const std::string* other_data =
|
||||
static_cast<const ImplicitWeakMessage&>(other).data_;
|
||||
if (other_data != nullptr) {
|
||||
data_->append(*other_data);
|
||||
}
|
||||
}
|
||||
|
||||
const char* _InternalParse(const char* ptr, ParseContext* ctx) final;
|
||||
|
||||
size_t ByteSizeLong() const override {
|
||||
return data_ == nullptr ? 0 : data_->size();
|
||||
}
|
||||
|
||||
uint8_t* _InternalSerialize(uint8_t* target,
|
||||
io::EpsCopyOutputStream* stream) const final {
|
||||
if (data_ == nullptr) {
|
||||
return target;
|
||||
}
|
||||
return stream->WriteRaw(data_->data(), data_->size(),
|
||||
target);
|
||||
}
|
||||
|
||||
int GetCachedSize() const override {
|
||||
return data_ == nullptr ? 0 : static_cast<int>(data_->size());
|
||||
}
|
||||
|
||||
typedef void InternalArenaConstructable_;
|
||||
|
||||
private:
|
||||
// This std::string is allocated on the heap, but we use a raw pointer so that
|
||||
// the default instance can be constant-initialized. In the const methods, we
|
||||
// have to handle the possibility of data_ being null.
|
||||
std::string* data_;
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImplicitWeakMessage);
|
||||
};
|
||||
|
||||
struct ImplicitWeakMessageDefaultType;
|
||||
extern ImplicitWeakMessageDefaultType implicit_weak_message_default_instance;
|
||||
|
||||
// A type handler for use with implicit weak repeated message fields.
|
||||
template <typename ImplicitWeakType>
|
||||
class ImplicitWeakTypeHandler {
|
||||
public:
|
||||
typedef MessageLite Type;
|
||||
static constexpr bool Moveable = false;
|
||||
|
||||
static inline MessageLite* NewFromPrototype(const MessageLite* prototype,
|
||||
Arena* arena = nullptr) {
|
||||
return prototype->New(arena);
|
||||
}
|
||||
|
||||
static inline void Delete(MessageLite* value, Arena* arena) {
|
||||
if (arena == nullptr) {
|
||||
delete value;
|
||||
}
|
||||
}
|
||||
static inline Arena* GetArena(MessageLite* value) {
|
||||
return value->GetArena();
|
||||
}
|
||||
static inline void Clear(MessageLite* value) { value->Clear(); }
|
||||
static void Merge(const MessageLite& from, MessageLite* to) {
|
||||
to->CheckTypeAndMergeFrom(from);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
template <typename T>
|
||||
struct WeakRepeatedPtrField {
|
||||
using TypeHandler = internal::ImplicitWeakTypeHandler<T>;
|
||||
constexpr WeakRepeatedPtrField() : weak() {}
|
||||
explicit WeakRepeatedPtrField(Arena* arena) : weak(arena) {}
|
||||
~WeakRepeatedPtrField() { weak.template Destroy<TypeHandler>(); }
|
||||
|
||||
typedef internal::RepeatedPtrIterator<MessageLite> iterator;
|
||||
typedef internal::RepeatedPtrIterator<const MessageLite> const_iterator;
|
||||
typedef internal::RepeatedPtrOverPtrsIterator<MessageLite*, void*>
|
||||
pointer_iterator;
|
||||
typedef internal::RepeatedPtrOverPtrsIterator<const MessageLite* const,
|
||||
const void* const>
|
||||
const_pointer_iterator;
|
||||
|
||||
iterator begin() { return iterator(base().raw_data()); }
|
||||
const_iterator begin() const { return iterator(base().raw_data()); }
|
||||
const_iterator cbegin() const { return begin(); }
|
||||
iterator end() { return begin() + base().size(); }
|
||||
const_iterator end() const { return begin() + base().size(); }
|
||||
const_iterator cend() const { return end(); }
|
||||
pointer_iterator pointer_begin() {
|
||||
return pointer_iterator(base().raw_mutable_data());
|
||||
}
|
||||
const_pointer_iterator pointer_begin() const {
|
||||
return const_pointer_iterator(base().raw_mutable_data());
|
||||
}
|
||||
pointer_iterator pointer_end() {
|
||||
return pointer_iterator(base().raw_mutable_data() + base().size());
|
||||
}
|
||||
const_pointer_iterator pointer_end() const {
|
||||
return const_pointer_iterator(base().raw_mutable_data() + base().size());
|
||||
}
|
||||
|
||||
MessageLite* AddWeak(const MessageLite* prototype) {
|
||||
return base().AddWeak(prototype);
|
||||
}
|
||||
T* Add() { return weak.Add(); }
|
||||
void Clear() { base().template Clear<TypeHandler>(); }
|
||||
void MergeFrom(const WeakRepeatedPtrField& other) {
|
||||
base().template MergeFrom<TypeHandler>(other.base());
|
||||
}
|
||||
void InternalSwap(WeakRepeatedPtrField* other) {
|
||||
base().InternalSwap(&other->base());
|
||||
}
|
||||
|
||||
const internal::RepeatedPtrFieldBase& base() const { return weak; }
|
||||
internal::RepeatedPtrFieldBase& base() { return weak; }
|
||||
// Union disables running the destructor. Which would create a strong link.
|
||||
// Instead we explicitly destroy the underlying base through the virtual
|
||||
// destructor.
|
||||
union {
|
||||
RepeatedPtrField<T> weak;
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_IMPLICIT_WEAK_MESSAGE_H__
|
||||
@@ -1,532 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_INLINED_STRING_FIELD_H__
|
||||
#define GOOGLE_PROTOBUF_INLINED_STRING_FIELD_H__
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include <google/protobuf/stubs/logging.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/port.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
#include <google/protobuf/arenastring.h>
|
||||
#include <google/protobuf/message_lite.h>
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
#ifdef SWIG
|
||||
#error "You cannot SWIG proto headers"
|
||||
#endif
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
class Arena;
|
||||
|
||||
namespace internal {
|
||||
|
||||
// InlinedStringField wraps a std::string instance and exposes an API similar to
|
||||
// ArenaStringPtr's wrapping of a std::string* instance.
|
||||
//
|
||||
// default_value parameters are taken for consistency with ArenaStringPtr, but
|
||||
// are not used for most methods. With inlining, these should be removed from
|
||||
// the generated binary.
|
||||
//
|
||||
// InlinedStringField has a donating mechanism that allows string buffer
|
||||
// allocated on arena. A string is donated means both the string container and
|
||||
// the data buffer are on arena. The donating mechanism here is similar to the
|
||||
// one in ArenaStringPtr with some differences:
|
||||
//
|
||||
// When an InlinedStringField is constructed, the donating state is true. This
|
||||
// is because the string container is directly stored in the message on the
|
||||
// arena:
|
||||
//
|
||||
// Construction: donated=true
|
||||
// Arena:
|
||||
// +-----------------------+
|
||||
// |Message foo: |
|
||||
// | +-------------------+ |
|
||||
// | |InlinedStringField:| |
|
||||
// | | +-----+ | |
|
||||
// | | | | | | | |
|
||||
// | | +-----+ | |
|
||||
// | +-------------------+ |
|
||||
// +-----------------------+
|
||||
//
|
||||
// When lvalue Set is called, the donating state is still true. String data will
|
||||
// be allocated on the arena:
|
||||
//
|
||||
// Lvalue Set: donated=true
|
||||
// Arena:
|
||||
// +-----------------------+
|
||||
// |Message foo: |
|
||||
// | +-------------------+ |
|
||||
// | |InlinedStringField:| |
|
||||
// | | +-----+ | |
|
||||
// | | | | | | | |
|
||||
// | | +|----+ | |
|
||||
// | +--|----------------+ |
|
||||
// | V |
|
||||
// | +----------------+ |
|
||||
// | |'f','o','o',... | |
|
||||
// | +----------------+ |
|
||||
// +-----------------------+
|
||||
//
|
||||
// Some operations will undonate a donated string, including: Mutable,
|
||||
// SetAllocated, Rvalue Set, and Swap with a non-donated string.
|
||||
//
|
||||
// For more details of the donating states transitions, go/pd-inlined-string.
|
||||
class PROTOBUF_EXPORT InlinedStringField {
|
||||
public:
|
||||
InlinedStringField() { Init(); }
|
||||
inline void Init() { new (get_mutable()) std::string(); }
|
||||
// Add the dummy parameter just to make InlinedStringField(nullptr)
|
||||
// unambiguous.
|
||||
constexpr InlinedStringField(
|
||||
const ExplicitlyConstructed<std::string>* /*default_value*/,
|
||||
bool /*dummy*/)
|
||||
: value_{} {}
|
||||
explicit InlinedStringField(const std::string& default_value);
|
||||
explicit InlinedStringField(Arena* arena);
|
||||
~InlinedStringField() { Destruct(); }
|
||||
|
||||
// Lvalue Set. To save space, we pack the donating states of multiple
|
||||
// InlinedStringFields into an uint32_t `donating_states`. The `mask`
|
||||
// indicates the position of the bit for this InlinedStringField. `donated` is
|
||||
// whether this field is donated.
|
||||
//
|
||||
// The caller should guarantee that:
|
||||
//
|
||||
// `donated == ((donating_states & ~mask) != 0)`
|
||||
//
|
||||
// This method never changes the `donating_states`.
|
||||
void Set(ConstStringParam value, Arena* arena, bool donated,
|
||||
uint32_t* donating_states, uint32_t mask, MessageLite* msg);
|
||||
|
||||
// Rvalue Set. If this field is donated, this method will undonate this field
|
||||
// by mutating the `donating_states` according to `mask`.
|
||||
void Set(std::string&& value, Arena* arena, bool donated,
|
||||
uint32_t* donating_states, uint32_t mask, MessageLite* msg);
|
||||
|
||||
void Set(const char* str, ::google::protobuf::Arena* arena, bool donated,
|
||||
uint32_t* donating_states, uint32_t mask, MessageLite* msg);
|
||||
|
||||
void Set(const char* str, size_t size, ::google::protobuf::Arena* arena, bool donated,
|
||||
uint32_t* donating_states, uint32_t mask, MessageLite* msg);
|
||||
|
||||
template <typename RefWrappedType>
|
||||
void Set(std::reference_wrapper<RefWrappedType> const_string_ref,
|
||||
::google::protobuf::Arena* arena, bool donated, uint32_t* donating_states,
|
||||
uint32_t mask, MessageLite* msg);
|
||||
|
||||
void SetBytes(ConstStringParam value, Arena* arena, bool donated,
|
||||
uint32_t* donating_states, uint32_t mask, MessageLite* msg);
|
||||
|
||||
void SetBytes(std::string&& value, Arena* arena, bool donated,
|
||||
uint32_t* donating_states, uint32_t mask, MessageLite* msg);
|
||||
|
||||
void SetBytes(const char* str, ::google::protobuf::Arena* arena, bool donated,
|
||||
uint32_t* donating_states, uint32_t mask, MessageLite* msg);
|
||||
|
||||
void SetBytes(const void* p, size_t size, ::google::protobuf::Arena* arena,
|
||||
bool donated, uint32_t* donating_states, uint32_t mask,
|
||||
MessageLite* msg);
|
||||
|
||||
template <typename RefWrappedType>
|
||||
void SetBytes(std::reference_wrapper<RefWrappedType> const_string_ref,
|
||||
::google::protobuf::Arena* arena, bool donated, uint32_t* donating_states,
|
||||
uint32_t mask, MessageLite* msg);
|
||||
|
||||
PROTOBUF_NDEBUG_INLINE void SetNoArena(StringPiece value);
|
||||
PROTOBUF_NDEBUG_INLINE void SetNoArena(std::string&& value);
|
||||
|
||||
// Basic accessors.
|
||||
PROTOBUF_NDEBUG_INLINE const std::string& Get() const { return GetNoArena(); }
|
||||
PROTOBUF_NDEBUG_INLINE const std::string& GetNoArena() const;
|
||||
|
||||
// Mutable returns a std::string* instance that is heap-allocated. If this
|
||||
// field is donated, this method undonates this field by mutating the
|
||||
// `donating_states` according to `mask`, and copies the content of the
|
||||
// original string to the returning string.
|
||||
std::string* Mutable(Arena* arena, bool donated, uint32_t* donating_states,
|
||||
uint32_t mask, MessageLite* msg);
|
||||
std::string* Mutable(const LazyString& default_value, Arena* arena,
|
||||
bool donated, uint32_t* donating_states, uint32_t mask,
|
||||
MessageLite* msg);
|
||||
|
||||
// Mutable(nullptr_t) is an overload to explicitly support Mutable(nullptr)
|
||||
// calls used by the internal parser logic. This provides API equivalence with
|
||||
// ArenaStringPtr, while still protecting against calls with arena pointers.
|
||||
std::string* Mutable(std::nullptr_t);
|
||||
std::string* MutableNoCopy(std::nullptr_t);
|
||||
|
||||
// Takes a std::string that is heap-allocated, and takes ownership. The
|
||||
// std::string's destructor is registered with the arena. Used to implement
|
||||
// set_allocated_<field> in generated classes.
|
||||
//
|
||||
// If this field is donated, this method undonates this field by mutating the
|
||||
// `donating_states` according to `mask`.
|
||||
void SetAllocated(const std::string* default_value, std::string* value,
|
||||
Arena* arena, bool donated, uint32_t* donating_states,
|
||||
uint32_t mask, MessageLite* msg);
|
||||
|
||||
void SetAllocatedNoArena(const std::string* default_value,
|
||||
std::string* value);
|
||||
|
||||
// Release returns a std::string* instance that is heap-allocated and is not
|
||||
// Own()'d by any arena. If the field is not set, this returns nullptr. The
|
||||
// caller retains ownership. Clears this field back to nullptr state. Used to
|
||||
// implement release_<field>() methods on generated classes.
|
||||
PROTOBUF_NODISCARD std::string* Release(Arena* arena, bool donated);
|
||||
PROTOBUF_NODISCARD std::string* Release();
|
||||
|
||||
// --------------------------------------------------------
|
||||
// Below functions will be removed in subsequent code change
|
||||
// --------------------------------------------------------
|
||||
#ifdef DEPRECATED_METHODS_TO_BE_DELETED
|
||||
PROTOBUF_NODISCARD std::string* Release(const std::string*, Arena* arena,
|
||||
bool donated) {
|
||||
return Release(arena, donated);
|
||||
}
|
||||
|
||||
PROTOBUF_NODISCARD std::string* ReleaseNonDefault(const std::string*,
|
||||
Arena* arena) {
|
||||
return Release();
|
||||
}
|
||||
|
||||
std::string* ReleaseNonDefaultNoArena(const std::string* default_value) {
|
||||
return Release();
|
||||
}
|
||||
|
||||
void Set(const std::string*, ConstStringParam value, Arena* arena,
|
||||
bool donated, uint32_t* donating_states, uint32_t mask,
|
||||
MessageLite* msg) {
|
||||
Set(value, arena, donated, donating_states, mask, msg);
|
||||
}
|
||||
|
||||
void Set(const std::string*, std::string&& value, Arena* arena, bool donated,
|
||||
uint32_t* donating_states, uint32_t mask, MessageLite* msg) {
|
||||
Set(std::move(value), arena, donated, donating_states, mask, msg);
|
||||
}
|
||||
|
||||
|
||||
template <typename FirstParam>
|
||||
void Set(FirstParam, const char* str, ::google::protobuf::Arena* arena, bool donated,
|
||||
uint32_t* donating_states, uint32_t mask, MessageLite* msg) {
|
||||
Set(str, arena, donated, donating_states, mask, msg);
|
||||
}
|
||||
|
||||
template <typename FirstParam>
|
||||
void Set(FirstParam p1, const char* str, size_t size, ::google::protobuf::Arena* arena,
|
||||
bool donated, uint32_t* donating_states, uint32_t mask,
|
||||
MessageLite* msg) {
|
||||
Set(str, size, arena, donated, donating_states, mask, msg);
|
||||
}
|
||||
|
||||
template <typename FirstParam, typename RefWrappedType>
|
||||
void Set(FirstParam p1,
|
||||
std::reference_wrapper<RefWrappedType> const_string_ref,
|
||||
::google::protobuf::Arena* arena, bool donated, uint32_t* donating_states,
|
||||
uint32_t mask, MessageLite* msg) {
|
||||
Set(const_string_ref, arena, donated, donating_states, mask, msg);
|
||||
}
|
||||
|
||||
void SetBytes(const std::string*, ConstStringParam value, Arena* arena,
|
||||
bool donated, uint32_t* donating_states, uint32_t mask,
|
||||
MessageLite* msg) {
|
||||
Set(value, arena, donated, donating_states, mask, msg);
|
||||
}
|
||||
|
||||
|
||||
void SetBytes(const std::string*, std::string&& value, Arena* arena,
|
||||
bool donated, uint32_t* donating_states, uint32_t mask,
|
||||
MessageLite* msg) {
|
||||
Set(std::move(value), arena, donated, donating_states, mask, msg);
|
||||
}
|
||||
|
||||
template <typename FirstParam>
|
||||
void SetBytes(FirstParam p1, const char* str, ::google::protobuf::Arena* arena,
|
||||
bool donated, uint32_t* donating_states, uint32_t mask,
|
||||
MessageLite* msg) {
|
||||
SetBytes(str, arena, donated, donating_states, mask, msg);
|
||||
}
|
||||
|
||||
template <typename FirstParam>
|
||||
void SetBytes(FirstParam p1, const void* p, size_t size,
|
||||
::google::protobuf::Arena* arena, bool donated, uint32_t* donating_states,
|
||||
uint32_t mask, MessageLite* msg) {
|
||||
SetBytes(p, size, arena, donated, donating_states, mask, msg);
|
||||
}
|
||||
|
||||
template <typename FirstParam, typename RefWrappedType>
|
||||
void SetBytes(FirstParam p1,
|
||||
std::reference_wrapper<RefWrappedType> const_string_ref,
|
||||
::google::protobuf::Arena* arena, bool donated, uint32_t* donating_states,
|
||||
uint32_t mask, MessageLite* msg) {
|
||||
SetBytes(const_string_ref.get(), arena, donated, donating_states, mask,
|
||||
msg);
|
||||
}
|
||||
|
||||
void SetNoArena(const std::string*, StringPiece value) {
|
||||
SetNoArena(value);
|
||||
}
|
||||
void SetNoArena(const std::string*, std::string&& value) {
|
||||
SetNoArena(std::move(value));
|
||||
}
|
||||
|
||||
std::string* Mutable(ArenaStringPtr::EmptyDefault, Arena* arena, bool donated,
|
||||
uint32_t* donating_states, uint32_t mask,
|
||||
MessageLite* msg) {
|
||||
return Mutable(arena, donated, donating_states, mask, msg);
|
||||
}
|
||||
|
||||
PROTOBUF_NDEBUG_INLINE std::string* MutableNoArenaNoDefault(
|
||||
const std::string* /*default_value*/) {
|
||||
return MutableNoCopy(nullptr);
|
||||
}
|
||||
|
||||
#endif // DEPRECATED_METHODS_TO_BE_DELETED
|
||||
|
||||
// Arena-safety semantics: this is guarded by the logic in
|
||||
// Swap()/UnsafeArenaSwap() at the message level, so this method is
|
||||
// 'unsafe' if called directly.
|
||||
inline PROTOBUF_NDEBUG_INLINE static void InternalSwap(
|
||||
InlinedStringField* lhs, Arena* lhs_arena, bool lhs_arena_dtor_registered,
|
||||
MessageLite* lhs_msg, //
|
||||
InlinedStringField* rhs, Arena* rhs_arena, bool rhs_arena_dtor_registered,
|
||||
MessageLite* rhs_msg);
|
||||
|
||||
// Frees storage (if not on an arena).
|
||||
PROTOBUF_NDEBUG_INLINE void Destroy(const std::string* default_value,
|
||||
Arena* arena) {
|
||||
if (arena == nullptr) {
|
||||
DestroyNoArena(default_value);
|
||||
}
|
||||
}
|
||||
PROTOBUF_NDEBUG_INLINE void DestroyNoArena(const std::string* default_value);
|
||||
|
||||
// Clears content, but keeps allocated std::string, to avoid the overhead of
|
||||
// heap operations. After this returns, the content (as seen by the user) will
|
||||
// always be the empty std::string.
|
||||
PROTOBUF_NDEBUG_INLINE void ClearToEmpty() { ClearNonDefaultToEmpty(); }
|
||||
PROTOBUF_NDEBUG_INLINE void ClearNonDefaultToEmpty() {
|
||||
get_mutable()->clear();
|
||||
}
|
||||
|
||||
// Clears content, but keeps allocated std::string if arena != nullptr, to
|
||||
// avoid the overhead of heap operations. After this returns, the content (as
|
||||
// seen by the user) will always be equal to |default_value|.
|
||||
void ClearToDefault(const LazyString& default_value, Arena* arena,
|
||||
bool donated);
|
||||
|
||||
// Generated code / reflection only! Returns a mutable pointer to the string.
|
||||
PROTOBUF_NDEBUG_INLINE std::string* UnsafeMutablePointer();
|
||||
|
||||
// InlinedStringField doesn't have things like the `default_value` pointer in
|
||||
// ArenaStringPtr.
|
||||
static constexpr bool IsDefault() { return false; }
|
||||
static constexpr bool IsDefault(const std::string*) { return false; }
|
||||
|
||||
private:
|
||||
void Destruct() { get_mutable()->~basic_string(); }
|
||||
|
||||
PROTOBUF_NDEBUG_INLINE std::string* get_mutable();
|
||||
PROTOBUF_NDEBUG_INLINE const std::string* get_const() const;
|
||||
|
||||
alignas(std::string) char value_[sizeof(std::string)];
|
||||
|
||||
std::string* MutableSlow(::google::protobuf::Arena* arena, bool donated,
|
||||
uint32_t* donating_states, uint32_t mask,
|
||||
MessageLite* msg);
|
||||
|
||||
|
||||
// When constructed in an Arena, we want our destructor to be skipped.
|
||||
friend class ::google::protobuf::Arena;
|
||||
typedef void InternalArenaConstructable_;
|
||||
typedef void DestructorSkippable_;
|
||||
};
|
||||
|
||||
inline std::string* InlinedStringField::get_mutable() {
|
||||
return reinterpret_cast<std::string*>(&value_);
|
||||
}
|
||||
|
||||
inline const std::string* InlinedStringField::get_const() const {
|
||||
return reinterpret_cast<const std::string*>(&value_);
|
||||
}
|
||||
|
||||
inline InlinedStringField::InlinedStringField(
|
||||
const std::string& default_value) {
|
||||
new (get_mutable()) std::string(default_value);
|
||||
}
|
||||
|
||||
|
||||
inline InlinedStringField::InlinedStringField(Arena* /*arena*/) { Init(); }
|
||||
|
||||
inline const std::string& InlinedStringField::GetNoArena() const {
|
||||
return *get_const();
|
||||
}
|
||||
|
||||
inline void InlinedStringField::SetAllocatedNoArena(
|
||||
const std::string* /*default_value*/, std::string* value) {
|
||||
if (value == nullptr) {
|
||||
// Currently, inlined string field can't have non empty default.
|
||||
get_mutable()->clear();
|
||||
} else {
|
||||
get_mutable()->assign(std::move(*value));
|
||||
delete value;
|
||||
}
|
||||
}
|
||||
|
||||
inline void InlinedStringField::DestroyNoArena(const std::string*) {
|
||||
// This is invoked from the generated message's ArenaDtor, which is used to
|
||||
// clean up objects not allocated on the Arena.
|
||||
this->~InlinedStringField();
|
||||
}
|
||||
|
||||
inline void InlinedStringField::SetNoArena(StringPiece value) {
|
||||
get_mutable()->assign(value.data(), value.length());
|
||||
}
|
||||
|
||||
inline void InlinedStringField::SetNoArena(std::string&& value) {
|
||||
get_mutable()->assign(std::move(value));
|
||||
}
|
||||
|
||||
// Caller should make sure rhs_arena allocated rhs, and lhs_arena allocated lhs.
|
||||
inline PROTOBUF_NDEBUG_INLINE void InlinedStringField::InternalSwap(
|
||||
InlinedStringField* lhs, Arena* lhs_arena, bool lhs_arena_dtor_registered,
|
||||
MessageLite* lhs_msg, //
|
||||
InlinedStringField* rhs, Arena* rhs_arena, bool rhs_arena_dtor_registered,
|
||||
MessageLite* rhs_msg) {
|
||||
#if GOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE
|
||||
lhs->get_mutable()->swap(*rhs->get_mutable());
|
||||
if (!lhs_arena_dtor_registered && rhs_arena_dtor_registered) {
|
||||
lhs_msg->OnDemandRegisterArenaDtor(lhs_arena);
|
||||
} else if (lhs_arena_dtor_registered && !rhs_arena_dtor_registered) {
|
||||
rhs_msg->OnDemandRegisterArenaDtor(rhs_arena);
|
||||
}
|
||||
#else
|
||||
(void)lhs_arena;
|
||||
(void)rhs_arena;
|
||||
(void)lhs_arena_dtor_registered;
|
||||
(void)rhs_arena_dtor_registered;
|
||||
(void)lhs_msg;
|
||||
(void)rhs_msg;
|
||||
lhs->get_mutable()->swap(*rhs->get_mutable());
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void InlinedStringField::Set(ConstStringParam value, Arena* arena,
|
||||
bool donated, uint32_t* /*donating_states*/,
|
||||
uint32_t /*mask*/, MessageLite* /*msg*/) {
|
||||
(void)arena;
|
||||
(void)donated;
|
||||
SetNoArena(value);
|
||||
}
|
||||
|
||||
inline void InlinedStringField::Set(const char* str, ::google::protobuf::Arena* arena,
|
||||
bool donated, uint32_t* donating_states,
|
||||
uint32_t mask, MessageLite* msg) {
|
||||
Set(ConstStringParam(str), arena, donated, donating_states, mask, msg);
|
||||
}
|
||||
|
||||
inline void InlinedStringField::Set(const char* str, size_t size,
|
||||
::google::protobuf::Arena* arena, bool donated,
|
||||
uint32_t* donating_states, uint32_t mask,
|
||||
MessageLite* msg) {
|
||||
Set(ConstStringParam{str, size}, arena, donated, donating_states, mask, msg);
|
||||
}
|
||||
|
||||
inline void InlinedStringField::SetBytes(ConstStringParam value, Arena* arena,
|
||||
bool donated,
|
||||
uint32_t* donating_states,
|
||||
uint32_t mask, MessageLite* msg) {
|
||||
Set(value, arena, donated, donating_states, mask, msg);
|
||||
}
|
||||
|
||||
inline void InlinedStringField::SetBytes(std::string&& value, Arena* arena,
|
||||
bool donated,
|
||||
uint32_t* donating_states,
|
||||
uint32_t mask, MessageLite* msg) {
|
||||
Set(std::move(value), arena, donated, donating_states, mask, msg);
|
||||
}
|
||||
|
||||
inline void InlinedStringField::SetBytes(const char* str,
|
||||
::google::protobuf::Arena* arena, bool donated,
|
||||
uint32_t* donating_states,
|
||||
uint32_t mask, MessageLite* msg) {
|
||||
Set(str, arena, donated, donating_states, mask, msg);
|
||||
}
|
||||
|
||||
inline void InlinedStringField::SetBytes(const void* p, size_t size,
|
||||
::google::protobuf::Arena* arena, bool donated,
|
||||
uint32_t* donating_states,
|
||||
uint32_t mask, MessageLite* msg) {
|
||||
Set(static_cast<const char*>(p), size, arena, donated, donating_states, mask,
|
||||
msg);
|
||||
}
|
||||
|
||||
template <typename RefWrappedType>
|
||||
inline void InlinedStringField::Set(
|
||||
std::reference_wrapper<RefWrappedType> const_string_ref,
|
||||
::google::protobuf::Arena* arena, bool donated, uint32_t* donating_states,
|
||||
uint32_t mask, MessageLite* msg) {
|
||||
Set(const_string_ref.get(), arena, donated, donating_states, mask, msg);
|
||||
}
|
||||
|
||||
template <typename RefWrappedType>
|
||||
inline void InlinedStringField::SetBytes(
|
||||
std::reference_wrapper<RefWrappedType> const_string_ref,
|
||||
::google::protobuf::Arena* arena, bool donated, uint32_t* donating_states,
|
||||
uint32_t mask, MessageLite* msg) {
|
||||
Set(const_string_ref.get(), arena, donated, donating_states, mask, msg);
|
||||
}
|
||||
|
||||
inline std::string* InlinedStringField::UnsafeMutablePointer() {
|
||||
return get_mutable();
|
||||
}
|
||||
|
||||
inline std::string* InlinedStringField::Mutable(std::nullptr_t) {
|
||||
return get_mutable();
|
||||
}
|
||||
|
||||
inline std::string* InlinedStringField::MutableNoCopy(std::nullptr_t) {
|
||||
return get_mutable();
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_INLINED_STRING_FIELD_H__
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,205 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: brianolson@google.com (Brian Olson)
|
||||
//
|
||||
// This file contains the definition for classes GzipInputStream and
|
||||
// GzipOutputStream.
|
||||
//
|
||||
// GzipInputStream decompresses data from an underlying
|
||||
// ZeroCopyInputStream and provides the decompressed data as a
|
||||
// ZeroCopyInputStream.
|
||||
//
|
||||
// GzipOutputStream is an ZeroCopyOutputStream that compresses data to
|
||||
// an underlying ZeroCopyOutputStream.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_IO_GZIP_STREAM_H__
|
||||
#define GOOGLE_PROTOBUF_IO_GZIP_STREAM_H__
|
||||
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/io/zero_copy_stream.h>
|
||||
#include <google/protobuf/port.h>
|
||||
#include "zlib.h"
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace io {
|
||||
|
||||
// A ZeroCopyInputStream that reads compressed data through zlib
|
||||
class PROTOBUF_EXPORT GzipInputStream PROTOBUF_FUTURE_FINAL
|
||||
: public ZeroCopyInputStream {
|
||||
public:
|
||||
// Format key for constructor
|
||||
enum Format {
|
||||
// zlib will autodetect gzip header or deflate stream
|
||||
AUTO = 0,
|
||||
|
||||
// GZIP streams have some extra header data for file attributes.
|
||||
GZIP = 1,
|
||||
|
||||
// Simpler zlib stream format.
|
||||
ZLIB = 2,
|
||||
};
|
||||
|
||||
// buffer_size and format may be -1 for default of 64kB and GZIP format
|
||||
explicit GzipInputStream(ZeroCopyInputStream* sub_stream,
|
||||
Format format = AUTO, int buffer_size = -1);
|
||||
virtual ~GzipInputStream();
|
||||
|
||||
// Return last error message or NULL if no error.
|
||||
inline const char* ZlibErrorMessage() const { return zcontext_.msg; }
|
||||
inline int ZlibErrorCode() const { return zerror_; }
|
||||
|
||||
// implements ZeroCopyInputStream ----------------------------------
|
||||
bool Next(const void** data, int* size) override;
|
||||
void BackUp(int count) override;
|
||||
bool Skip(int count) override;
|
||||
int64_t ByteCount() const override;
|
||||
|
||||
private:
|
||||
Format format_;
|
||||
|
||||
ZeroCopyInputStream* sub_stream_;
|
||||
|
||||
z_stream zcontext_;
|
||||
int zerror_;
|
||||
|
||||
void* output_buffer_;
|
||||
void* output_position_;
|
||||
size_t output_buffer_length_;
|
||||
int64_t byte_count_;
|
||||
|
||||
int Inflate(int flush);
|
||||
void DoNextOutput(const void** data, int* size);
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GzipInputStream);
|
||||
};
|
||||
|
||||
class PROTOBUF_EXPORT GzipOutputStream PROTOBUF_FUTURE_FINAL
|
||||
: public ZeroCopyOutputStream {
|
||||
public:
|
||||
// Format key for constructor
|
||||
enum Format {
|
||||
// GZIP streams have some extra header data for file attributes.
|
||||
GZIP = 1,
|
||||
|
||||
// Simpler zlib stream format.
|
||||
ZLIB = 2,
|
||||
};
|
||||
|
||||
struct PROTOBUF_EXPORT Options {
|
||||
// Defaults to GZIP.
|
||||
Format format;
|
||||
|
||||
// What size buffer to use internally. Defaults to 64kB.
|
||||
int buffer_size;
|
||||
|
||||
// A number between 0 and 9, where 0 is no compression and 9 is best
|
||||
// compression. Defaults to Z_DEFAULT_COMPRESSION (see zlib.h).
|
||||
int compression_level;
|
||||
|
||||
// Defaults to Z_DEFAULT_STRATEGY. Can also be set to Z_FILTERED,
|
||||
// Z_HUFFMAN_ONLY, or Z_RLE. See the documentation for deflateInit2 in
|
||||
// zlib.h for definitions of these constants.
|
||||
int compression_strategy;
|
||||
|
||||
Options(); // Initializes with default values.
|
||||
};
|
||||
|
||||
// Create a GzipOutputStream with default options.
|
||||
explicit GzipOutputStream(ZeroCopyOutputStream* sub_stream);
|
||||
|
||||
// Create a GzipOutputStream with the given options.
|
||||
GzipOutputStream(ZeroCopyOutputStream* sub_stream, const Options& options);
|
||||
|
||||
virtual ~GzipOutputStream();
|
||||
|
||||
// Return last error message or NULL if no error.
|
||||
inline const char* ZlibErrorMessage() const { return zcontext_.msg; }
|
||||
inline int ZlibErrorCode() const { return zerror_; }
|
||||
|
||||
// Flushes data written so far to zipped data in the underlying stream.
|
||||
// It is the caller's responsibility to flush the underlying stream if
|
||||
// necessary.
|
||||
// Compression may be less efficient stopping and starting around flushes.
|
||||
// Returns true if no error.
|
||||
//
|
||||
// Please ensure that block size is > 6. Here is an excerpt from the zlib
|
||||
// doc that explains why:
|
||||
//
|
||||
// In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that avail_out
|
||||
// is greater than six to avoid repeated flush markers due to
|
||||
// avail_out == 0 on return.
|
||||
bool Flush();
|
||||
|
||||
// Writes out all data and closes the gzip stream.
|
||||
// It is the caller's responsibility to close the underlying stream if
|
||||
// necessary.
|
||||
// Returns true if no error.
|
||||
bool Close();
|
||||
|
||||
// implements ZeroCopyOutputStream ---------------------------------
|
||||
bool Next(void** data, int* size) override;
|
||||
void BackUp(int count) override;
|
||||
int64_t ByteCount() const override;
|
||||
|
||||
private:
|
||||
ZeroCopyOutputStream* sub_stream_;
|
||||
// Result from calling Next() on sub_stream_
|
||||
void* sub_data_;
|
||||
int sub_data_size_;
|
||||
|
||||
z_stream zcontext_;
|
||||
int zerror_;
|
||||
void* input_buffer_;
|
||||
size_t input_buffer_length_;
|
||||
|
||||
// Shared constructor code.
|
||||
void Init(ZeroCopyOutputStream* sub_stream, const Options& options);
|
||||
|
||||
// Do some compression.
|
||||
// Takes zlib flush mode.
|
||||
// Returns zlib error code.
|
||||
int Deflate(int flush);
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GzipOutputStream);
|
||||
};
|
||||
|
||||
} // namespace io
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_IO_GZIP_STREAM_H__
|
||||
@@ -1,141 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: laszlocsomor@google.com (Laszlo Csomor)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
|
||||
// This file contains the declarations for Windows implementations of
|
||||
// commonly used POSIX functions such as open(2) and access(2), as well
|
||||
// as macro definitions for flags of these functions.
|
||||
//
|
||||
// By including this file you'll redefine open/access/etc. to
|
||||
// ::google::protobuf::io::win32::{open/access/etc.}.
|
||||
// Make sure you don't include a header that attempts to redeclare or
|
||||
// redefine these functions, that'll lead to confusing compilation
|
||||
// errors. It's best to #include this file as the last one to ensure that.
|
||||
//
|
||||
// This file is only used on Windows, it's empty on other platforms.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_IO_IO_WIN32_H__
|
||||
#define GOOGLE_PROTOBUF_IO_IO_WIN32_H__
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/port.h>
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
// Compilers on Windows other than MSVC (e.g. Cygwin, MinGW32) define the
|
||||
// following functions already, except for mkdir.
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace io {
|
||||
namespace win32 {
|
||||
|
||||
PROTOBUF_EXPORT FILE* fopen(const char* path, const char* mode);
|
||||
PROTOBUF_EXPORT int access(const char* path, int mode);
|
||||
PROTOBUF_EXPORT int chdir(const char* path);
|
||||
PROTOBUF_EXPORT int close(int fd);
|
||||
PROTOBUF_EXPORT int dup(int fd);
|
||||
PROTOBUF_EXPORT int dup2(int fd1, int fd2);
|
||||
PROTOBUF_EXPORT int mkdir(const char* path, int _mode);
|
||||
PROTOBUF_EXPORT int open(const char* path, int flags, int mode = 0);
|
||||
PROTOBUF_EXPORT int read(int fd, void* buffer, size_t size);
|
||||
PROTOBUF_EXPORT int setmode(int fd, int mode);
|
||||
PROTOBUF_EXPORT int stat(const char* path, struct _stat* buffer);
|
||||
PROTOBUF_EXPORT int write(int fd, const void* buffer, size_t size);
|
||||
PROTOBUF_EXPORT std::wstring testonly_utf8_to_winpath(const char* path);
|
||||
|
||||
enum class ExpandWildcardsResult {
|
||||
kSuccess = 0,
|
||||
kErrorNoMatchingFile = 1,
|
||||
kErrorInputPathConversion = 2,
|
||||
kErrorOutputPathConversion = 3,
|
||||
};
|
||||
|
||||
// Expand wildcards in a path pattern, feed the result to a consumer function.
|
||||
//
|
||||
// `path` must be a valid, Windows-style path. It may be absolute, or relative
|
||||
// to the current working directory, and it may contain wildcards ("*" and "?")
|
||||
// in the last path segment. This function passes all matching file names to
|
||||
// `consume`. The resulting paths may not be absolute nor normalized.
|
||||
//
|
||||
// The function returns a value from `ExpandWildcardsResult`.
|
||||
PROTOBUF_EXPORT ExpandWildcardsResult ExpandWildcards(
|
||||
const std::string& path, std::function<void(const std::string&)> consume);
|
||||
|
||||
namespace strings {
|
||||
|
||||
// Convert from UTF-16 to Active-Code-Page-encoded or to UTF-8-encoded text.
|
||||
PROTOBUF_EXPORT bool wcs_to_mbs(const wchar_t* s, std::string* out,
|
||||
bool outUtf8);
|
||||
|
||||
// Convert from Active-Code-Page-encoded or UTF-8-encoded text to UTF-16.
|
||||
PROTOBUF_EXPORT bool mbs_to_wcs(const char* s, std::wstring* out, bool inUtf8);
|
||||
|
||||
// Convert from UTF-8-encoded text to UTF-16.
|
||||
PROTOBUF_EXPORT bool utf8_to_wcs(const char* input, std::wstring* out);
|
||||
|
||||
// Convert from UTF-16-encoded text to UTF-8.
|
||||
PROTOBUF_EXPORT bool wcs_to_utf8(const wchar_t* input, std::string* out);
|
||||
|
||||
} // namespace strings
|
||||
|
||||
} // namespace win32
|
||||
} // namespace io
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#ifndef W_OK
|
||||
#define W_OK 02 // not defined by MSVC for whatever reason
|
||||
#endif
|
||||
|
||||
#ifndef F_OK
|
||||
#define F_OK 00 // not defined by MSVC for whatever reason
|
||||
#endif
|
||||
|
||||
#ifndef STDIN_FILENO
|
||||
#define STDIN_FILENO 0
|
||||
#endif
|
||||
|
||||
#ifndef STDOUT_FILENO
|
||||
#define STDOUT_FILENO 1
|
||||
#endif
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // defined(_WIN32)
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_IO_IO_WIN32_H__
|
||||
@@ -1,387 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
//
|
||||
// Utility class for writing text to a ZeroCopyOutputStream.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_IO_PRINTER_H__
|
||||
#define GOOGLE_PROTOBUF_IO_PRINTER_H__
|
||||
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace io {
|
||||
|
||||
class ZeroCopyOutputStream; // zero_copy_stream.h
|
||||
|
||||
// Records annotations about a Printer's output.
|
||||
class PROTOBUF_EXPORT AnnotationCollector {
|
||||
public:
|
||||
// Annotation is a offset range and a payload pair.
|
||||
typedef std::pair<std::pair<size_t, size_t>, std::string> Annotation;
|
||||
|
||||
// Records that the bytes in file_path beginning with begin_offset and ending
|
||||
// before end_offset are associated with the SourceCodeInfo-style path.
|
||||
virtual void AddAnnotation(size_t begin_offset, size_t end_offset,
|
||||
const std::string& file_path,
|
||||
const std::vector<int>& path) = 0;
|
||||
|
||||
// TODO(gerbens) I don't see why we need virtuals here. Just a vector of
|
||||
// range, payload pairs stored in a context should suffice.
|
||||
virtual void AddAnnotationNew(Annotation& /* a */) {}
|
||||
|
||||
virtual ~AnnotationCollector() {}
|
||||
};
|
||||
|
||||
// Records annotations about a Printer's output to the given protocol buffer,
|
||||
// assuming that the buffer has an ::Annotation message exposing path,
|
||||
// source_file, begin and end fields.
|
||||
template <typename AnnotationProto>
|
||||
class AnnotationProtoCollector : public AnnotationCollector {
|
||||
public:
|
||||
// annotation_proto is the protocol buffer to which new Annotations should be
|
||||
// added. It is not owned by the AnnotationProtoCollector.
|
||||
explicit AnnotationProtoCollector(AnnotationProto* annotation_proto)
|
||||
: annotation_proto_(annotation_proto) {}
|
||||
|
||||
// Override for AnnotationCollector::AddAnnotation.
|
||||
void AddAnnotation(size_t begin_offset, size_t end_offset,
|
||||
const std::string& file_path,
|
||||
const std::vector<int>& path) override {
|
||||
typename AnnotationProto::Annotation* annotation =
|
||||
annotation_proto_->add_annotation();
|
||||
for (int i = 0; i < path.size(); ++i) {
|
||||
annotation->add_path(path[i]);
|
||||
}
|
||||
annotation->set_source_file(file_path);
|
||||
annotation->set_begin(begin_offset);
|
||||
annotation->set_end(end_offset);
|
||||
}
|
||||
// Override for AnnotationCollector::AddAnnotation.
|
||||
void AddAnnotationNew(Annotation& a) override {
|
||||
auto* annotation = annotation_proto_->add_annotation();
|
||||
annotation->ParseFromString(a.second);
|
||||
annotation->set_begin(a.first.first);
|
||||
annotation->set_end(a.first.second);
|
||||
}
|
||||
|
||||
private:
|
||||
// The protocol buffer to which new annotations should be added.
|
||||
AnnotationProto* const annotation_proto_;
|
||||
};
|
||||
|
||||
// This simple utility class assists in code generation. It basically
|
||||
// allows the caller to define a set of variables and then output some
|
||||
// text with variable substitutions. Example usage:
|
||||
//
|
||||
// Printer printer(output, '$');
|
||||
// map<string, string> vars;
|
||||
// vars["name"] = "Bob";
|
||||
// printer.Print(vars, "My name is $name$.");
|
||||
//
|
||||
// The above writes "My name is Bob." to the output stream.
|
||||
//
|
||||
// Printer aggressively enforces correct usage, crashing (with assert failures)
|
||||
// in the case of undefined variables in debug builds. This helps greatly in
|
||||
// debugging code which uses it.
|
||||
//
|
||||
// If a Printer is constructed with an AnnotationCollector, it will provide it
|
||||
// with annotations that connect the Printer's output to paths that can identify
|
||||
// various descriptors. In the above example, if person_ is a descriptor that
|
||||
// identifies Bob, we can associate the output string "My name is Bob." with
|
||||
// a source path pointing to that descriptor with:
|
||||
//
|
||||
// printer.Annotate("name", person_);
|
||||
//
|
||||
// The AnnotationCollector will be sent an annotation linking the output range
|
||||
// covering "Bob" to the logical path provided by person_. Tools may use
|
||||
// this association to (for example) link "Bob" in the output back to the
|
||||
// source file that defined the person_ descriptor identifying Bob.
|
||||
//
|
||||
// Annotate can only examine variables substituted during the last call to
|
||||
// Print. It is invalid to refer to a variable that was used multiple times
|
||||
// in a single Print call.
|
||||
//
|
||||
// In full generality, one may specify a range of output text using a beginning
|
||||
// substitution variable and an ending variable. The resulting annotation will
|
||||
// span from the first character of the substituted value for the beginning
|
||||
// variable to the last character of the substituted value for the ending
|
||||
// variable. For example, the Annotate call above is equivalent to this one:
|
||||
//
|
||||
// printer.Annotate("name", "name", person_);
|
||||
//
|
||||
// This is useful if multiple variables combine to form a single span of output
|
||||
// that should be annotated with the same source path. For example:
|
||||
//
|
||||
// Printer printer(output, '$');
|
||||
// map<string, string> vars;
|
||||
// vars["first"] = "Alice";
|
||||
// vars["last"] = "Smith";
|
||||
// printer.Print(vars, "My name is $first$ $last$.");
|
||||
// printer.Annotate("first", "last", person_);
|
||||
//
|
||||
// This code would associate the span covering "Alice Smith" in the output with
|
||||
// the person_ descriptor.
|
||||
//
|
||||
// Note that the beginning variable must come before (or overlap with, in the
|
||||
// case of zero-sized substitution values) the ending variable.
|
||||
//
|
||||
// It is also sometimes useful to use variables with zero-sized values as
|
||||
// markers. This avoids issues with multiple references to the same variable
|
||||
// and also allows annotation ranges to span literal text from the Print
|
||||
// templates:
|
||||
//
|
||||
// Printer printer(output, '$');
|
||||
// map<string, string> vars;
|
||||
// vars["foo"] = "bar";
|
||||
// vars["function"] = "call";
|
||||
// vars["mark"] = "";
|
||||
// printer.Print(vars, "$function$($foo$,$foo$)$mark$");
|
||||
// printer.Annotate("function", "mark", call_);
|
||||
//
|
||||
// This code associates the span covering "call(bar,bar)" in the output with the
|
||||
// call_ descriptor.
|
||||
|
||||
class PROTOBUF_EXPORT Printer {
|
||||
public:
|
||||
// Create a printer that writes text to the given output stream. Use the
|
||||
// given character as the delimiter for variables.
|
||||
Printer(ZeroCopyOutputStream* output, char variable_delimiter);
|
||||
|
||||
// Create a printer that writes text to the given output stream. Use the
|
||||
// given character as the delimiter for variables. If annotation_collector
|
||||
// is not null, Printer will provide it with annotations about code written
|
||||
// to the stream. annotation_collector is not owned by Printer.
|
||||
Printer(ZeroCopyOutputStream* output, char variable_delimiter,
|
||||
AnnotationCollector* annotation_collector);
|
||||
|
||||
~Printer();
|
||||
|
||||
// Link a substitution variable emitted by the last call to Print to the
|
||||
// object described by descriptor.
|
||||
template <typename SomeDescriptor>
|
||||
void Annotate(const char* varname, const SomeDescriptor* descriptor) {
|
||||
Annotate(varname, varname, descriptor);
|
||||
}
|
||||
|
||||
// Link the output range defined by the substitution variables as emitted by
|
||||
// the last call to Print to the object described by descriptor. The range
|
||||
// begins at begin_varname's value and ends after the last character of the
|
||||
// value substituted for end_varname.
|
||||
template <typename SomeDescriptor>
|
||||
void Annotate(const char* begin_varname, const char* end_varname,
|
||||
const SomeDescriptor* descriptor) {
|
||||
if (annotation_collector_ == NULL) {
|
||||
// Annotations aren't turned on for this Printer, so don't pay the cost
|
||||
// of building the location path.
|
||||
return;
|
||||
}
|
||||
std::vector<int> path;
|
||||
descriptor->GetLocationPath(&path);
|
||||
Annotate(begin_varname, end_varname, descriptor->file()->name(), path);
|
||||
}
|
||||
|
||||
// Link a substitution variable emitted by the last call to Print to the file
|
||||
// with path file_name.
|
||||
void Annotate(const char* varname, const std::string& file_name) {
|
||||
Annotate(varname, varname, file_name);
|
||||
}
|
||||
|
||||
// Link the output range defined by the substitution variables as emitted by
|
||||
// the last call to Print to the file with path file_name. The range begins
|
||||
// at begin_varname's value and ends after the last character of the value
|
||||
// substituted for end_varname.
|
||||
void Annotate(const char* begin_varname, const char* end_varname,
|
||||
const std::string& file_name) {
|
||||
if (annotation_collector_ == NULL) {
|
||||
// Annotations aren't turned on for this Printer.
|
||||
return;
|
||||
}
|
||||
std::vector<int> empty_path;
|
||||
Annotate(begin_varname, end_varname, file_name, empty_path);
|
||||
}
|
||||
|
||||
// Print some text after applying variable substitutions. If a particular
|
||||
// variable in the text is not defined, this will crash. Variables to be
|
||||
// substituted are identified by their names surrounded by delimiter
|
||||
// characters (as given to the constructor). The variable bindings are
|
||||
// defined by the given map.
|
||||
void Print(const std::map<std::string, std::string>& variables,
|
||||
const char* text);
|
||||
|
||||
// Like the first Print(), except the substitutions are given as parameters.
|
||||
template <typename... Args>
|
||||
void Print(const char* text, const Args&... args) {
|
||||
std::map<std::string, std::string> vars;
|
||||
PrintInternal(&vars, text, args...);
|
||||
}
|
||||
|
||||
// Indent text by two spaces. After calling Indent(), two spaces will be
|
||||
// inserted at the beginning of each line of text. Indent() may be called
|
||||
// multiple times to produce deeper indents.
|
||||
void Indent();
|
||||
|
||||
// Reduces the current indent level by two spaces, or crashes if the indent
|
||||
// level is zero.
|
||||
void Outdent();
|
||||
|
||||
// Write a string to the output buffer.
|
||||
// This method does not look for newlines to add indentation.
|
||||
void PrintRaw(const std::string& data);
|
||||
|
||||
// Write a zero-delimited string to output buffer.
|
||||
// This method does not look for newlines to add indentation.
|
||||
void PrintRaw(const char* data);
|
||||
|
||||
// Write some bytes to the output buffer.
|
||||
// This method does not look for newlines to add indentation.
|
||||
void WriteRaw(const char* data, int size);
|
||||
|
||||
// FormatInternal is a helper function not meant to use directly, use
|
||||
// compiler::cpp::Formatter instead. This function is meant to support
|
||||
// formatting text using named variables (eq. "$foo$) from a lookup map (vars)
|
||||
// and variables directly supplied by arguments (eq "$1$" meaning first
|
||||
// argument which is the zero index element of args).
|
||||
void FormatInternal(const std::vector<std::string>& args,
|
||||
const std::map<std::string, std::string>& vars,
|
||||
const char* format);
|
||||
|
||||
// True if any write to the underlying stream failed. (We don't just
|
||||
// crash in this case because this is an I/O failure, not a programming
|
||||
// error.)
|
||||
bool failed() const { return failed_; }
|
||||
|
||||
private:
|
||||
// Link the output range defined by the substitution variables as emitted by
|
||||
// the last call to Print to the object found at the SourceCodeInfo-style path
|
||||
// in a file with path file_path. The range begins at the start of
|
||||
// begin_varname's value and ends after the last character of the value
|
||||
// substituted for end_varname. Note that begin_varname and end_varname
|
||||
// may refer to the same variable.
|
||||
void Annotate(const char* begin_varname, const char* end_varname,
|
||||
const std::string& file_path, const std::vector<int>& path);
|
||||
|
||||
// Base case
|
||||
void PrintInternal(std::map<std::string, std::string>* vars,
|
||||
const char* text) {
|
||||
Print(*vars, text);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
void PrintInternal(std::map<std::string, std::string>* vars, const char* text,
|
||||
const char* key, const std::string& value,
|
||||
const Args&... args) {
|
||||
(*vars)[key] = value;
|
||||
PrintInternal(vars, text, args...);
|
||||
}
|
||||
|
||||
// Copy size worth of bytes from data to buffer_.
|
||||
void CopyToBuffer(const char* data, int size);
|
||||
|
||||
void push_back(char c) {
|
||||
if (failed_) return;
|
||||
if (buffer_size_ == 0) {
|
||||
if (!Next()) return;
|
||||
}
|
||||
*buffer_++ = c;
|
||||
buffer_size_--;
|
||||
offset_++;
|
||||
}
|
||||
|
||||
bool Next();
|
||||
|
||||
inline void IndentIfAtStart();
|
||||
const char* WriteVariable(
|
||||
const std::vector<std::string>& args,
|
||||
const std::map<std::string, std::string>& vars, const char* format,
|
||||
int* arg_index,
|
||||
std::vector<AnnotationCollector::Annotation>* annotations);
|
||||
|
||||
const char variable_delimiter_;
|
||||
|
||||
ZeroCopyOutputStream* const output_;
|
||||
char* buffer_;
|
||||
int buffer_size_;
|
||||
// The current position, in bytes, in the output stream. This is equivalent
|
||||
// to the total number of bytes that have been written so far. This value is
|
||||
// used to calculate annotation ranges in the substitutions_ map below.
|
||||
size_t offset_;
|
||||
|
||||
std::string indent_;
|
||||
bool at_start_of_line_;
|
||||
bool failed_;
|
||||
|
||||
// A map from variable name to [start, end) offsets in the output buffer.
|
||||
// These refer to the offsets used for a variable after the last call to
|
||||
// Print. If a variable was used more than once, the entry used in
|
||||
// this map is set to a negative-length span. For singly-used variables, the
|
||||
// start offset is the beginning of the substitution; the end offset is the
|
||||
// last byte of the substitution plus one (such that (end - start) is the
|
||||
// length of the substituted string).
|
||||
std::map<std::string, std::pair<size_t, size_t> > substitutions_;
|
||||
|
||||
// Keeps track of the keys in substitutions_ that need to be updated when
|
||||
// indents are inserted. These are keys that refer to the beginning of the
|
||||
// current line.
|
||||
std::vector<std::string> line_start_variables_;
|
||||
|
||||
// Returns true and sets range to the substitution range in the output for
|
||||
// varname if varname was used once in the last call to Print. If varname
|
||||
// was not used, or if it was used multiple times, returns false (and
|
||||
// fails a debug assertion).
|
||||
bool GetSubstitutionRange(const char* varname,
|
||||
std::pair<size_t, size_t>* range);
|
||||
|
||||
// If non-null, annotation_collector_ is used to store annotations about
|
||||
// generated code.
|
||||
AnnotationCollector* const annotation_collector_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Printer);
|
||||
};
|
||||
|
||||
} // namespace io
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_IO_PRINTER_H__
|
||||
@@ -1,55 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// A locale-independent version of strtod(), used to parse floating
|
||||
// point default values in .proto files, where the decimal separator
|
||||
// is always a dot.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_IO_STRTOD_H__
|
||||
#define GOOGLE_PROTOBUF_IO_STRTOD_H__
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace io {
|
||||
|
||||
// A locale-independent version of the standard strtod(), which always
|
||||
// uses a dot as the decimal separator.
|
||||
double NoLocaleStrtod(const char* str, char** endptr);
|
||||
|
||||
// Casts a double value to a float value. If the value is outside of the
|
||||
// representable range of float, it will be converted to positive or negative
|
||||
// infinity.
|
||||
float SafeDoubleToFloat(double value);
|
||||
|
||||
} // namespace io
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_IO_STRTOD_H__
|
||||
@@ -1,442 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
//
|
||||
// Class for parsing tokenized text from a ZeroCopyInputStream.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_IO_TOKENIZER_H__
|
||||
#define GOOGLE_PROTOBUF_IO_TOKENIZER_H__
|
||||
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/logging.h>
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace io {
|
||||
|
||||
class ZeroCopyInputStream; // zero_copy_stream.h
|
||||
|
||||
// Defined in this file.
|
||||
class ErrorCollector;
|
||||
class Tokenizer;
|
||||
|
||||
// By "column number", the proto compiler refers to a count of the number
|
||||
// of bytes before a given byte, except that a tab character advances to
|
||||
// the next multiple of 8 bytes. Note in particular that column numbers
|
||||
// are zero-based, while many user interfaces use one-based column numbers.
|
||||
typedef int ColumnNumber;
|
||||
|
||||
// Abstract interface for an object which collects the errors that occur
|
||||
// during parsing. A typical implementation might simply print the errors
|
||||
// to stdout.
|
||||
class PROTOBUF_EXPORT ErrorCollector {
|
||||
public:
|
||||
inline ErrorCollector() {}
|
||||
virtual ~ErrorCollector();
|
||||
|
||||
// Indicates that there was an error in the input at the given line and
|
||||
// column numbers. The numbers are zero-based, so you may want to add
|
||||
// 1 to each before printing them.
|
||||
virtual void AddError(int line, ColumnNumber column,
|
||||
const std::string& message) = 0;
|
||||
|
||||
// Indicates that there was a warning in the input at the given line and
|
||||
// column numbers. The numbers are zero-based, so you may want to add
|
||||
// 1 to each before printing them.
|
||||
virtual void AddWarning(int /* line */, ColumnNumber /* column */,
|
||||
const std::string& /* message */) {}
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ErrorCollector);
|
||||
};
|
||||
|
||||
// This class converts a stream of raw text into a stream of tokens for
|
||||
// the protocol definition parser to parse. The tokens recognized are
|
||||
// similar to those that make up the C language; see the TokenType enum for
|
||||
// precise descriptions. Whitespace and comments are skipped. By default,
|
||||
// C- and C++-style comments are recognized, but other styles can be used by
|
||||
// calling set_comment_style().
|
||||
class PROTOBUF_EXPORT Tokenizer {
|
||||
public:
|
||||
// Construct a Tokenizer that reads and tokenizes text from the given
|
||||
// input stream and writes errors to the given error_collector.
|
||||
// The caller keeps ownership of input and error_collector.
|
||||
Tokenizer(ZeroCopyInputStream* input, ErrorCollector* error_collector);
|
||||
~Tokenizer();
|
||||
|
||||
enum TokenType {
|
||||
TYPE_START, // Next() has not yet been called.
|
||||
TYPE_END, // End of input reached. "text" is empty.
|
||||
|
||||
TYPE_IDENTIFIER, // A sequence of letters, digits, and underscores, not
|
||||
// starting with a digit. It is an error for a number
|
||||
// to be followed by an identifier with no space in
|
||||
// between.
|
||||
TYPE_INTEGER, // A sequence of digits representing an integer. Normally
|
||||
// the digits are decimal, but a prefix of "0x" indicates
|
||||
// a hex number and a leading zero indicates octal, just
|
||||
// like with C numeric literals. A leading negative sign
|
||||
// is NOT included in the token; it's up to the parser to
|
||||
// interpret the unary minus operator on its own.
|
||||
TYPE_FLOAT, // A floating point literal, with a fractional part and/or
|
||||
// an exponent. Always in decimal. Again, never
|
||||
// negative.
|
||||
TYPE_STRING, // A quoted sequence of escaped characters. Either single
|
||||
// or double quotes can be used, but they must match.
|
||||
// A string literal cannot cross a line break.
|
||||
TYPE_SYMBOL, // Any other printable character, like '!' or '+'.
|
||||
// Symbols are always a single character, so "!+$%" is
|
||||
// four tokens.
|
||||
TYPE_WHITESPACE, // A sequence of whitespace. This token type is only
|
||||
// produced if report_whitespace() is true. It is not
|
||||
// reported for whitespace within comments or strings.
|
||||
TYPE_NEWLINE, // A newline (\n). This token type is only
|
||||
// produced if report_whitespace() is true and
|
||||
// report_newlines() is true. It is not reported for
|
||||
// newlines in comments or strings.
|
||||
};
|
||||
|
||||
// Structure representing a token read from the token stream.
|
||||
struct Token {
|
||||
TokenType type;
|
||||
std::string text; // The exact text of the token as it appeared in
|
||||
// the input. e.g. tokens of TYPE_STRING will still
|
||||
// be escaped and in quotes.
|
||||
|
||||
// "line" and "column" specify the position of the first character of
|
||||
// the token within the input stream. They are zero-based.
|
||||
int line;
|
||||
ColumnNumber column;
|
||||
ColumnNumber end_column;
|
||||
};
|
||||
|
||||
// Get the current token. This is updated when Next() is called. Before
|
||||
// the first call to Next(), current() has type TYPE_START and no contents.
|
||||
const Token& current();
|
||||
|
||||
// Return the previous token -- i.e. what current() returned before the
|
||||
// previous call to Next().
|
||||
const Token& previous();
|
||||
|
||||
// Advance to the next token. Returns false if the end of the input is
|
||||
// reached.
|
||||
bool Next();
|
||||
|
||||
// Like Next(), but also collects comments which appear between the previous
|
||||
// and next tokens.
|
||||
//
|
||||
// Comments which appear to be attached to the previous token are stored
|
||||
// in *prev_tailing_comments. Comments which appear to be attached to the
|
||||
// next token are stored in *next_leading_comments. Comments appearing in
|
||||
// between which do not appear to be attached to either will be added to
|
||||
// detached_comments. Any of these parameters can be NULL to simply discard
|
||||
// the comments.
|
||||
//
|
||||
// A series of line comments appearing on consecutive lines, with no other
|
||||
// tokens appearing on those lines, will be treated as a single comment.
|
||||
//
|
||||
// Only the comment content is returned; comment markers (e.g. //) are
|
||||
// stripped out. For block comments, leading whitespace and an asterisk will
|
||||
// be stripped from the beginning of each line other than the first. Newlines
|
||||
// are included in the output.
|
||||
//
|
||||
// Examples:
|
||||
//
|
||||
// optional int32 foo = 1; // Comment attached to foo.
|
||||
// // Comment attached to bar.
|
||||
// optional int32 bar = 2;
|
||||
//
|
||||
// optional string baz = 3;
|
||||
// // Comment attached to baz.
|
||||
// // Another line attached to baz.
|
||||
//
|
||||
// // Comment attached to qux.
|
||||
// //
|
||||
// // Another line attached to qux.
|
||||
// optional double qux = 4;
|
||||
//
|
||||
// // Detached comment. This is not attached to qux or corge
|
||||
// // because there are blank lines separating it from both.
|
||||
//
|
||||
// optional string corge = 5;
|
||||
// /* Block comment attached
|
||||
// * to corge. Leading asterisks
|
||||
// * will be removed. */
|
||||
// /* Block comment attached to
|
||||
// * grault. */
|
||||
// optional int32 grault = 6;
|
||||
bool NextWithComments(std::string* prev_trailing_comments,
|
||||
std::vector<std::string>* detached_comments,
|
||||
std::string* next_leading_comments);
|
||||
|
||||
// Parse helpers ---------------------------------------------------
|
||||
|
||||
// Parses a TYPE_FLOAT token. This never fails, so long as the text actually
|
||||
// comes from a TYPE_FLOAT token parsed by Tokenizer. If it doesn't, the
|
||||
// result is undefined (possibly an assert failure).
|
||||
static double ParseFloat(const std::string& text);
|
||||
|
||||
// Parses a TYPE_STRING token. This never fails, so long as the text actually
|
||||
// comes from a TYPE_STRING token parsed by Tokenizer. If it doesn't, the
|
||||
// result is undefined (possibly an assert failure).
|
||||
static void ParseString(const std::string& text, std::string* output);
|
||||
|
||||
// Identical to ParseString, but appends to output.
|
||||
static void ParseStringAppend(const std::string& text, std::string* output);
|
||||
|
||||
// Parses a TYPE_INTEGER token. Returns false if the result would be
|
||||
// greater than max_value. Otherwise, returns true and sets *output to the
|
||||
// result. If the text is not from a Token of type TYPE_INTEGER originally
|
||||
// parsed by a Tokenizer, the result is undefined (possibly an assert
|
||||
// failure).
|
||||
static bool ParseInteger(const std::string& text, uint64_t max_value,
|
||||
uint64_t* output);
|
||||
|
||||
// Options ---------------------------------------------------------
|
||||
|
||||
// Set true to allow floats to be suffixed with the letter 'f'. Tokens
|
||||
// which would otherwise be integers but which have the 'f' suffix will be
|
||||
// forced to be interpreted as floats. For all other purposes, the 'f' is
|
||||
// ignored.
|
||||
void set_allow_f_after_float(bool value) { allow_f_after_float_ = value; }
|
||||
|
||||
// Valid values for set_comment_style().
|
||||
enum CommentStyle {
|
||||
// Line comments begin with "//", block comments are delimited by "/*" and
|
||||
// "*/".
|
||||
CPP_COMMENT_STYLE,
|
||||
// Line comments begin with "#". No way to write block comments.
|
||||
SH_COMMENT_STYLE
|
||||
};
|
||||
|
||||
// Sets the comment style.
|
||||
void set_comment_style(CommentStyle style) { comment_style_ = style; }
|
||||
|
||||
// Whether to require whitespace between a number and a field name.
|
||||
// Default is true. Do not use this; for Google-internal cleanup only.
|
||||
void set_require_space_after_number(bool require) {
|
||||
require_space_after_number_ = require;
|
||||
}
|
||||
|
||||
// Whether to allow string literals to span multiple lines. Default is false.
|
||||
// Do not use this; for Google-internal cleanup only.
|
||||
void set_allow_multiline_strings(bool allow) {
|
||||
allow_multiline_strings_ = allow;
|
||||
}
|
||||
|
||||
// If true, whitespace tokens are reported by Next().
|
||||
// Note: `set_report_whitespace(false)` implies `set_report_newlines(false)`.
|
||||
bool report_whitespace() const;
|
||||
void set_report_whitespace(bool report);
|
||||
|
||||
// If true, newline tokens are reported by Next().
|
||||
// Note: `set_report_newlines(true)` implies `set_report_whitespace(true)`.
|
||||
bool report_newlines() const;
|
||||
void set_report_newlines(bool report);
|
||||
|
||||
// External helper: validate an identifier.
|
||||
static bool IsIdentifier(const std::string& text);
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Tokenizer);
|
||||
|
||||
Token current_; // Returned by current().
|
||||
Token previous_; // Returned by previous().
|
||||
|
||||
ZeroCopyInputStream* input_;
|
||||
ErrorCollector* error_collector_;
|
||||
|
||||
char current_char_; // == buffer_[buffer_pos_], updated by NextChar().
|
||||
const char* buffer_; // Current buffer returned from input_.
|
||||
int buffer_size_; // Size of buffer_.
|
||||
int buffer_pos_; // Current position within the buffer.
|
||||
bool read_error_; // Did we previously encounter a read error?
|
||||
|
||||
// Line and column number of current_char_ within the whole input stream.
|
||||
int line_;
|
||||
ColumnNumber column_;
|
||||
|
||||
// String to which text should be appended as we advance through it.
|
||||
// Call RecordTo(&str) to start recording and StopRecording() to stop.
|
||||
// E.g. StartToken() calls RecordTo(¤t_.text). record_start_ is the
|
||||
// position within the current buffer where recording started.
|
||||
std::string* record_target_;
|
||||
int record_start_;
|
||||
|
||||
// Options.
|
||||
bool allow_f_after_float_;
|
||||
CommentStyle comment_style_;
|
||||
bool require_space_after_number_;
|
||||
bool allow_multiline_strings_;
|
||||
bool report_whitespace_ = false;
|
||||
bool report_newlines_ = false;
|
||||
|
||||
// Since we count columns we need to interpret tabs somehow. We'll take
|
||||
// the standard 8-character definition for lack of any way to do better.
|
||||
// This must match the documentation of ColumnNumber.
|
||||
static const int kTabWidth = 8;
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// Helper methods.
|
||||
|
||||
// Consume this character and advance to the next one.
|
||||
void NextChar();
|
||||
|
||||
// Read a new buffer from the input.
|
||||
void Refresh();
|
||||
|
||||
inline void RecordTo(std::string* target);
|
||||
inline void StopRecording();
|
||||
|
||||
// Called when the current character is the first character of a new
|
||||
// token (not including whitespace or comments).
|
||||
inline void StartToken();
|
||||
// Called when the current character is the first character after the
|
||||
// end of the last token. After this returns, current_.text will
|
||||
// contain all text consumed since StartToken() was called.
|
||||
inline void EndToken();
|
||||
|
||||
// Convenience method to add an error at the current line and column.
|
||||
void AddError(const std::string& message) {
|
||||
error_collector_->AddError(line_, column_, message);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// The following four methods are used to consume tokens of specific
|
||||
// types. They are actually used to consume all characters *after*
|
||||
// the first, since the calling function consumes the first character
|
||||
// in order to decide what kind of token is being read.
|
||||
|
||||
// Read and consume a string, ending when the given delimiter is
|
||||
// consumed.
|
||||
void ConsumeString(char delimiter);
|
||||
|
||||
// Read and consume a number, returning TYPE_FLOAT or TYPE_INTEGER
|
||||
// depending on what was read. This needs to know if the first
|
||||
// character was a zero in order to correctly recognize hex and octal
|
||||
// numbers.
|
||||
// It also needs to know if the first character was a . to parse floating
|
||||
// point correctly.
|
||||
TokenType ConsumeNumber(bool started_with_zero, bool started_with_dot);
|
||||
|
||||
// Consume the rest of a line.
|
||||
void ConsumeLineComment(std::string* content);
|
||||
// Consume until "*/".
|
||||
void ConsumeBlockComment(std::string* content);
|
||||
|
||||
enum NextCommentStatus {
|
||||
// Started a line comment.
|
||||
LINE_COMMENT,
|
||||
|
||||
// Started a block comment.
|
||||
BLOCK_COMMENT,
|
||||
|
||||
// Consumed a slash, then realized it wasn't a comment. current_ has
|
||||
// been filled in with a slash token. The caller should return it.
|
||||
SLASH_NOT_COMMENT,
|
||||
|
||||
// We do not appear to be starting a comment here.
|
||||
NO_COMMENT
|
||||
};
|
||||
|
||||
// If we're at the start of a new comment, consume it and return what kind
|
||||
// of comment it is.
|
||||
NextCommentStatus TryConsumeCommentStart();
|
||||
|
||||
// If we're looking at a TYPE_WHITESPACE token and `report_whitespace_` is
|
||||
// true, consume it and return true.
|
||||
bool TryConsumeWhitespace();
|
||||
|
||||
// If we're looking at a TYPE_NEWLINE token and `report_newlines_` is true,
|
||||
// consume it and return true.
|
||||
bool TryConsumeNewline();
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// These helper methods make the parsing code more readable. The
|
||||
// "character classes" referred to are defined at the top of the .cc file.
|
||||
// Basically it is a C++ class with one method:
|
||||
// static bool InClass(char c);
|
||||
// The method returns true if c is a member of this "class", like "Letter"
|
||||
// or "Digit".
|
||||
|
||||
// Returns true if the current character is of the given character
|
||||
// class, but does not consume anything.
|
||||
template <typename CharacterClass>
|
||||
inline bool LookingAt();
|
||||
|
||||
// If the current character is in the given class, consume it and return
|
||||
// true. Otherwise return false.
|
||||
// e.g. TryConsumeOne<Letter>()
|
||||
template <typename CharacterClass>
|
||||
inline bool TryConsumeOne();
|
||||
|
||||
// Like above, but try to consume the specific character indicated.
|
||||
inline bool TryConsume(char c);
|
||||
|
||||
// Consume zero or more of the given character class.
|
||||
template <typename CharacterClass>
|
||||
inline void ConsumeZeroOrMore();
|
||||
|
||||
// Consume one or more of the given character class or log the given
|
||||
// error message.
|
||||
// e.g. ConsumeOneOrMore<Digit>("Expected digits.");
|
||||
template <typename CharacterClass>
|
||||
inline void ConsumeOneOrMore(const char* error);
|
||||
};
|
||||
|
||||
// inline methods ====================================================
|
||||
inline const Tokenizer::Token& Tokenizer::current() { return current_; }
|
||||
|
||||
inline const Tokenizer::Token& Tokenizer::previous() { return previous_; }
|
||||
|
||||
inline void Tokenizer::ParseString(const std::string& text,
|
||||
std::string* output) {
|
||||
output->clear();
|
||||
ParseStringAppend(text, output);
|
||||
}
|
||||
|
||||
} // namespace io
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_IO_TOKENIZER_H__
|
||||
@@ -1,260 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
//
|
||||
// This file contains the ZeroCopyInputStream and ZeroCopyOutputStream
|
||||
// interfaces, which represent abstract I/O streams to and from which
|
||||
// protocol buffers can be read and written. For a few simple
|
||||
// implementations of these interfaces, see zero_copy_stream_impl.h.
|
||||
//
|
||||
// These interfaces are different from classic I/O streams in that they
|
||||
// try to minimize the amount of data copying that needs to be done.
|
||||
// To accomplish this, responsibility for allocating buffers is moved to
|
||||
// the stream object, rather than being the responsibility of the caller.
|
||||
// So, the stream can return a buffer which actually points directly into
|
||||
// the final data structure where the bytes are to be stored, and the caller
|
||||
// can interact directly with that buffer, eliminating an intermediate copy
|
||||
// operation.
|
||||
//
|
||||
// As an example, consider the common case in which you are reading bytes
|
||||
// from an array that is already in memory (or perhaps an mmap()ed file).
|
||||
// With classic I/O streams, you would do something like:
|
||||
// char buffer[BUFFER_SIZE];
|
||||
// input->Read(buffer, BUFFER_SIZE);
|
||||
// DoSomething(buffer, BUFFER_SIZE);
|
||||
// Then, the stream basically just calls memcpy() to copy the data from
|
||||
// the array into your buffer. With a ZeroCopyInputStream, you would do
|
||||
// this instead:
|
||||
// const void* buffer;
|
||||
// int size;
|
||||
// input->Next(&buffer, &size);
|
||||
// DoSomething(buffer, size);
|
||||
// Here, no copy is performed. The input stream returns a pointer directly
|
||||
// into the backing array, and the caller ends up reading directly from it.
|
||||
//
|
||||
// If you want to be able to read the old-fashion way, you can create
|
||||
// a CodedInputStream or CodedOutputStream wrapping these objects and use
|
||||
// their ReadRaw()/WriteRaw() methods. These will, of course, add a copy
|
||||
// step, but Coded*Stream will handle buffering so at least it will be
|
||||
// reasonably efficient.
|
||||
//
|
||||
// ZeroCopyInputStream example:
|
||||
// // Read in a file and print its contents to stdout.
|
||||
// int fd = open("myfile", O_RDONLY);
|
||||
// ZeroCopyInputStream* input = new FileInputStream(fd);
|
||||
//
|
||||
// const void* buffer;
|
||||
// int size;
|
||||
// while (input->Next(&buffer, &size)) {
|
||||
// cout.write(buffer, size);
|
||||
// }
|
||||
//
|
||||
// delete input;
|
||||
// close(fd);
|
||||
//
|
||||
// ZeroCopyOutputStream example:
|
||||
// // Copy the contents of "infile" to "outfile", using plain read() for
|
||||
// // "infile" but a ZeroCopyOutputStream for "outfile".
|
||||
// int infd = open("infile", O_RDONLY);
|
||||
// int outfd = open("outfile", O_WRONLY);
|
||||
// ZeroCopyOutputStream* output = new FileOutputStream(outfd);
|
||||
//
|
||||
// void* buffer;
|
||||
// int size;
|
||||
// while (output->Next(&buffer, &size)) {
|
||||
// int bytes = read(infd, buffer, size);
|
||||
// if (bytes < size) {
|
||||
// // Reached EOF.
|
||||
// output->BackUp(size - bytes);
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// delete output;
|
||||
// close(infd);
|
||||
// close(outfd);
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_H__
|
||||
#define GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_H__
|
||||
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace io {
|
||||
|
||||
// Defined in this file.
|
||||
class ZeroCopyInputStream;
|
||||
class ZeroCopyOutputStream;
|
||||
|
||||
// Abstract interface similar to an input stream but designed to minimize
|
||||
// copying.
|
||||
class PROTOBUF_EXPORT ZeroCopyInputStream {
|
||||
public:
|
||||
ZeroCopyInputStream() {}
|
||||
virtual ~ZeroCopyInputStream() {}
|
||||
|
||||
// Obtains a chunk of data from the stream.
|
||||
//
|
||||
// Preconditions:
|
||||
// * "size" and "data" are not NULL.
|
||||
//
|
||||
// Postconditions:
|
||||
// * If the returned value is false, there is no more data to return or
|
||||
// an error occurred. All errors are permanent.
|
||||
// * Otherwise, "size" points to the actual number of bytes read and "data"
|
||||
// points to a pointer to a buffer containing these bytes.
|
||||
// * Ownership of this buffer remains with the stream, and the buffer
|
||||
// remains valid only until some other method of the stream is called
|
||||
// or the stream is destroyed.
|
||||
// * It is legal for the returned buffer to have zero size, as long
|
||||
// as repeatedly calling Next() eventually yields a buffer with non-zero
|
||||
// size.
|
||||
virtual bool Next(const void** data, int* size) = 0;
|
||||
|
||||
// Backs up a number of bytes, so that the next call to Next() returns
|
||||
// data again that was already returned by the last call to Next(). This
|
||||
// is useful when writing procedures that are only supposed to read up
|
||||
// to a certain point in the input, then return. If Next() returns a
|
||||
// buffer that goes beyond what you wanted to read, you can use BackUp()
|
||||
// to return to the point where you intended to finish.
|
||||
//
|
||||
// This method can be called with `count = 0` to finalize (flush) any
|
||||
// previously returned buffer. For example, a file output stream can
|
||||
// flush buffers returned from a previous call to Next() upon such
|
||||
// BackUp(0) invocations. ZeroCopyOutputStream callers should always
|
||||
// invoke BackUp() after a final Next() call, even if there is no
|
||||
// excess buffer data to be backed up to indicate a flush point.
|
||||
//
|
||||
// Preconditions:
|
||||
// * The last method called must have been Next().
|
||||
// * count must be less than or equal to the size of the last buffer
|
||||
// returned by Next().
|
||||
//
|
||||
// Postconditions:
|
||||
// * The last "count" bytes of the last buffer returned by Next() will be
|
||||
// pushed back into the stream. Subsequent calls to Next() will return
|
||||
// the same data again before producing new data.
|
||||
virtual void BackUp(int count) = 0;
|
||||
|
||||
// Skips a number of bytes. Returns false if the end of the stream is
|
||||
// reached or some input error occurred. In the end-of-stream case, the
|
||||
// stream is advanced to the end of the stream (so ByteCount() will return
|
||||
// the total size of the stream).
|
||||
virtual bool Skip(int count) = 0;
|
||||
|
||||
// Returns the total number of bytes read since this object was created.
|
||||
virtual int64_t ByteCount() const = 0;
|
||||
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ZeroCopyInputStream);
|
||||
};
|
||||
|
||||
// Abstract interface similar to an output stream but designed to minimize
|
||||
// copying.
|
||||
class PROTOBUF_EXPORT ZeroCopyOutputStream {
|
||||
public:
|
||||
ZeroCopyOutputStream() {}
|
||||
virtual ~ZeroCopyOutputStream() {}
|
||||
|
||||
// Obtains a buffer into which data can be written. Any data written
|
||||
// into this buffer will eventually (maybe instantly, maybe later on)
|
||||
// be written to the output.
|
||||
//
|
||||
// Preconditions:
|
||||
// * "size" and "data" are not NULL.
|
||||
//
|
||||
// Postconditions:
|
||||
// * If the returned value is false, an error occurred. All errors are
|
||||
// permanent.
|
||||
// * Otherwise, "size" points to the actual number of bytes in the buffer
|
||||
// and "data" points to the buffer.
|
||||
// * Ownership of this buffer remains with the stream, and the buffer
|
||||
// remains valid only until some other method of the stream is called
|
||||
// or the stream is destroyed.
|
||||
// * Any data which the caller stores in this buffer will eventually be
|
||||
// written to the output (unless BackUp() is called).
|
||||
// * It is legal for the returned buffer to have zero size, as long
|
||||
// as repeatedly calling Next() eventually yields a buffer with non-zero
|
||||
// size.
|
||||
virtual bool Next(void** data, int* size) = 0;
|
||||
|
||||
// Backs up a number of bytes, so that the end of the last buffer returned
|
||||
// by Next() is not actually written. This is needed when you finish
|
||||
// writing all the data you want to write, but the last buffer was bigger
|
||||
// than you needed. You don't want to write a bunch of garbage after the
|
||||
// end of your data, so you use BackUp() to back up.
|
||||
//
|
||||
// Preconditions:
|
||||
// * The last method called must have been Next().
|
||||
// * count must be less than or equal to the size of the last buffer
|
||||
// returned by Next().
|
||||
// * The caller must not have written anything to the last "count" bytes
|
||||
// of that buffer.
|
||||
//
|
||||
// Postconditions:
|
||||
// * The last "count" bytes of the last buffer returned by Next() will be
|
||||
// ignored.
|
||||
virtual void BackUp(int count) = 0;
|
||||
|
||||
// Returns the total number of bytes written since this object was created.
|
||||
virtual int64_t ByteCount() const = 0;
|
||||
|
||||
// Write a given chunk of data to the output. Some output streams may
|
||||
// implement this in a way that avoids copying. Check AllowsAliasing() before
|
||||
// calling WriteAliasedRaw(). It will GOOGLE_CHECK fail if WriteAliasedRaw() is
|
||||
// called on a stream that does not allow aliasing.
|
||||
//
|
||||
// NOTE: It is caller's responsibility to ensure that the chunk of memory
|
||||
// remains live until all of the data has been consumed from the stream.
|
||||
virtual bool WriteAliasedRaw(const void* data, int size);
|
||||
virtual bool AllowsAliasing() const { return false; }
|
||||
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ZeroCopyOutputStream);
|
||||
};
|
||||
|
||||
} // namespace io
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_H__
|
||||
@@ -1,336 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
//
|
||||
// This file contains common implementations of the interfaces defined in
|
||||
// zero_copy_stream.h which are only included in the full (non-lite)
|
||||
// protobuf library. These implementations include Unix file descriptors
|
||||
// and C++ iostreams. See also: zero_copy_stream_impl_lite.h
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_H__
|
||||
#define GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_H__
|
||||
|
||||
|
||||
#include <iosfwd>
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/io/zero_copy_stream.h>
|
||||
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace io {
|
||||
|
||||
// ===================================================================
|
||||
|
||||
// A ZeroCopyInputStream which reads from a file descriptor.
|
||||
//
|
||||
// FileInputStream is preferred over using an ifstream with IstreamInputStream.
|
||||
// The latter will introduce an extra layer of buffering, harming performance.
|
||||
// Also, it's conceivable that FileInputStream could someday be enhanced
|
||||
// to use zero-copy file descriptors on OSs which support them.
|
||||
class PROTOBUF_EXPORT FileInputStream PROTOBUF_FUTURE_FINAL
|
||||
: public ZeroCopyInputStream {
|
||||
public:
|
||||
// Creates a stream that reads from the given Unix file descriptor.
|
||||
// If a block_size is given, it specifies the number of bytes that
|
||||
// should be read and returned with each call to Next(). Otherwise,
|
||||
// a reasonable default is used.
|
||||
explicit FileInputStream(int file_descriptor, int block_size = -1);
|
||||
|
||||
// Flushes any buffers and closes the underlying file. Returns false if
|
||||
// an error occurs during the process; use GetErrno() to examine the error.
|
||||
// Even if an error occurs, the file descriptor is closed when this returns.
|
||||
bool Close();
|
||||
|
||||
// By default, the file descriptor is not closed when the stream is
|
||||
// destroyed. Call SetCloseOnDelete(true) to change that. WARNING:
|
||||
// This leaves no way for the caller to detect if close() fails. If
|
||||
// detecting close() errors is important to you, you should arrange
|
||||
// to close the descriptor yourself.
|
||||
void SetCloseOnDelete(bool value) { copying_input_.SetCloseOnDelete(value); }
|
||||
|
||||
// If an I/O error has occurred on this file descriptor, this is the
|
||||
// errno from that error. Otherwise, this is zero. Once an error
|
||||
// occurs, the stream is broken and all subsequent operations will
|
||||
// fail.
|
||||
int GetErrno() const { return copying_input_.GetErrno(); }
|
||||
|
||||
// implements ZeroCopyInputStream ----------------------------------
|
||||
bool Next(const void** data, int* size) override;
|
||||
void BackUp(int count) override;
|
||||
bool Skip(int count) override;
|
||||
int64_t ByteCount() const override;
|
||||
|
||||
private:
|
||||
class PROTOBUF_EXPORT CopyingFileInputStream PROTOBUF_FUTURE_FINAL
|
||||
: public CopyingInputStream {
|
||||
public:
|
||||
CopyingFileInputStream(int file_descriptor);
|
||||
~CopyingFileInputStream() override;
|
||||
|
||||
bool Close();
|
||||
void SetCloseOnDelete(bool value) { close_on_delete_ = value; }
|
||||
int GetErrno() const { return errno_; }
|
||||
|
||||
// implements CopyingInputStream ---------------------------------
|
||||
int Read(void* buffer, int size) override;
|
||||
int Skip(int count) override;
|
||||
|
||||
private:
|
||||
// The file descriptor.
|
||||
const int file_;
|
||||
bool close_on_delete_;
|
||||
bool is_closed_;
|
||||
|
||||
// The errno of the I/O error, if one has occurred. Otherwise, zero.
|
||||
int errno_;
|
||||
|
||||
// Did we try to seek once and fail? If so, we assume this file descriptor
|
||||
// doesn't support seeking and won't try again.
|
||||
bool previous_seek_failed_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingFileInputStream);
|
||||
};
|
||||
|
||||
CopyingFileInputStream copying_input_;
|
||||
CopyingInputStreamAdaptor impl_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileInputStream);
|
||||
};
|
||||
|
||||
// ===================================================================
|
||||
|
||||
// A ZeroCopyOutputStream which writes to a file descriptor.
|
||||
//
|
||||
// FileOutputStream is preferred over using an ofstream with
|
||||
// OstreamOutputStream. The latter will introduce an extra layer of buffering,
|
||||
// harming performance. Also, it's conceivable that FileOutputStream could
|
||||
// someday be enhanced to use zero-copy file descriptors on OSs which
|
||||
// support them.
|
||||
class PROTOBUF_EXPORT FileOutputStream PROTOBUF_FUTURE_FINAL
|
||||
: public CopyingOutputStreamAdaptor {
|
||||
public:
|
||||
// Creates a stream that writes to the given Unix file descriptor.
|
||||
// If a block_size is given, it specifies the size of the buffers
|
||||
// that should be returned by Next(). Otherwise, a reasonable default
|
||||
// is used.
|
||||
explicit FileOutputStream(int file_descriptor, int block_size = -1);
|
||||
|
||||
~FileOutputStream() override;
|
||||
|
||||
// Flushes any buffers and closes the underlying file. Returns false if
|
||||
// an error occurs during the process; use GetErrno() to examine the error.
|
||||
// Even if an error occurs, the file descriptor is closed when this returns.
|
||||
bool Close();
|
||||
|
||||
// By default, the file descriptor is not closed when the stream is
|
||||
// destroyed. Call SetCloseOnDelete(true) to change that. WARNING:
|
||||
// This leaves no way for the caller to detect if close() fails. If
|
||||
// detecting close() errors is important to you, you should arrange
|
||||
// to close the descriptor yourself.
|
||||
void SetCloseOnDelete(bool value) { copying_output_.SetCloseOnDelete(value); }
|
||||
|
||||
// If an I/O error has occurred on this file descriptor, this is the
|
||||
// errno from that error. Otherwise, this is zero. Once an error
|
||||
// occurs, the stream is broken and all subsequent operations will
|
||||
// fail.
|
||||
int GetErrno() const { return copying_output_.GetErrno(); }
|
||||
|
||||
private:
|
||||
class PROTOBUF_EXPORT CopyingFileOutputStream PROTOBUF_FUTURE_FINAL
|
||||
: public CopyingOutputStream {
|
||||
public:
|
||||
CopyingFileOutputStream(int file_descriptor);
|
||||
~CopyingFileOutputStream() override;
|
||||
|
||||
bool Close();
|
||||
void SetCloseOnDelete(bool value) { close_on_delete_ = value; }
|
||||
int GetErrno() const { return errno_; }
|
||||
|
||||
// implements CopyingOutputStream --------------------------------
|
||||
bool Write(const void* buffer, int size) override;
|
||||
|
||||
private:
|
||||
// The file descriptor.
|
||||
const int file_;
|
||||
bool close_on_delete_;
|
||||
bool is_closed_;
|
||||
|
||||
// The errno of the I/O error, if one has occurred. Otherwise, zero.
|
||||
int errno_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingFileOutputStream);
|
||||
};
|
||||
|
||||
CopyingFileOutputStream copying_output_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileOutputStream);
|
||||
};
|
||||
|
||||
// ===================================================================
|
||||
|
||||
// A ZeroCopyInputStream which reads from a C++ istream.
|
||||
//
|
||||
// Note that for reading files (or anything represented by a file descriptor),
|
||||
// FileInputStream is more efficient.
|
||||
class PROTOBUF_EXPORT IstreamInputStream PROTOBUF_FUTURE_FINAL
|
||||
: public ZeroCopyInputStream {
|
||||
public:
|
||||
// Creates a stream that reads from the given C++ istream.
|
||||
// If a block_size is given, it specifies the number of bytes that
|
||||
// should be read and returned with each call to Next(). Otherwise,
|
||||
// a reasonable default is used.
|
||||
explicit IstreamInputStream(std::istream* stream, int block_size = -1);
|
||||
|
||||
// implements ZeroCopyInputStream ----------------------------------
|
||||
bool Next(const void** data, int* size) override;
|
||||
void BackUp(int count) override;
|
||||
bool Skip(int count) override;
|
||||
int64_t ByteCount() const override;
|
||||
|
||||
private:
|
||||
class PROTOBUF_EXPORT CopyingIstreamInputStream PROTOBUF_FUTURE_FINAL
|
||||
: public CopyingInputStream {
|
||||
public:
|
||||
CopyingIstreamInputStream(std::istream* input);
|
||||
~CopyingIstreamInputStream() override;
|
||||
|
||||
// implements CopyingInputStream ---------------------------------
|
||||
int Read(void* buffer, int size) override;
|
||||
// (We use the default implementation of Skip().)
|
||||
|
||||
private:
|
||||
// The stream.
|
||||
std::istream* input_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingIstreamInputStream);
|
||||
};
|
||||
|
||||
CopyingIstreamInputStream copying_input_;
|
||||
CopyingInputStreamAdaptor impl_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(IstreamInputStream);
|
||||
};
|
||||
|
||||
// ===================================================================
|
||||
|
||||
// A ZeroCopyOutputStream which writes to a C++ ostream.
|
||||
//
|
||||
// Note that for writing files (or anything represented by a file descriptor),
|
||||
// FileOutputStream is more efficient.
|
||||
class PROTOBUF_EXPORT OstreamOutputStream PROTOBUF_FUTURE_FINAL
|
||||
: public ZeroCopyOutputStream {
|
||||
public:
|
||||
// Creates a stream that writes to the given C++ ostream.
|
||||
// If a block_size is given, it specifies the size of the buffers
|
||||
// that should be returned by Next(). Otherwise, a reasonable default
|
||||
// is used.
|
||||
explicit OstreamOutputStream(std::ostream* stream, int block_size = -1);
|
||||
~OstreamOutputStream() override;
|
||||
|
||||
// implements ZeroCopyOutputStream ---------------------------------
|
||||
bool Next(void** data, int* size) override;
|
||||
void BackUp(int count) override;
|
||||
int64_t ByteCount() const override;
|
||||
|
||||
private:
|
||||
class PROTOBUF_EXPORT CopyingOstreamOutputStream PROTOBUF_FUTURE_FINAL
|
||||
: public CopyingOutputStream {
|
||||
public:
|
||||
CopyingOstreamOutputStream(std::ostream* output);
|
||||
~CopyingOstreamOutputStream() override;
|
||||
|
||||
// implements CopyingOutputStream --------------------------------
|
||||
bool Write(const void* buffer, int size) override;
|
||||
|
||||
private:
|
||||
// The stream.
|
||||
std::ostream* output_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingOstreamOutputStream);
|
||||
};
|
||||
|
||||
CopyingOstreamOutputStream copying_output_;
|
||||
CopyingOutputStreamAdaptor impl_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(OstreamOutputStream);
|
||||
};
|
||||
|
||||
// ===================================================================
|
||||
|
||||
// A ZeroCopyInputStream which reads from several other streams in sequence.
|
||||
// ConcatenatingInputStream is unable to distinguish between end-of-stream
|
||||
// and read errors in the underlying streams, so it assumes any errors mean
|
||||
// end-of-stream. So, if the underlying streams fail for any other reason,
|
||||
// ConcatenatingInputStream may do odd things. It is suggested that you do
|
||||
// not use ConcatenatingInputStream on streams that might produce read errors
|
||||
// other than end-of-stream.
|
||||
class PROTOBUF_EXPORT ConcatenatingInputStream PROTOBUF_FUTURE_FINAL
|
||||
: public ZeroCopyInputStream {
|
||||
public:
|
||||
// All streams passed in as well as the array itself must remain valid
|
||||
// until the ConcatenatingInputStream is destroyed.
|
||||
ConcatenatingInputStream(ZeroCopyInputStream* const streams[], int count);
|
||||
~ConcatenatingInputStream() override = default;
|
||||
|
||||
// implements ZeroCopyInputStream ----------------------------------
|
||||
bool Next(const void** data, int* size) override;
|
||||
void BackUp(int count) override;
|
||||
bool Skip(int count) override;
|
||||
int64_t ByteCount() const override;
|
||||
|
||||
|
||||
private:
|
||||
// As streams are retired, streams_ is incremented and count_ is
|
||||
// decremented.
|
||||
ZeroCopyInputStream* const* streams_;
|
||||
int stream_count_;
|
||||
int64_t bytes_retired_; // Bytes read from previous streams.
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ConcatenatingInputStream);
|
||||
};
|
||||
|
||||
// ===================================================================
|
||||
|
||||
} // namespace io
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_H__
|
||||
@@ -1,413 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
//
|
||||
// This file contains common implementations of the interfaces defined in
|
||||
// zero_copy_stream.h which are included in the "lite" protobuf library.
|
||||
// These implementations cover I/O on raw arrays and strings, as well as
|
||||
// adaptors which make it easy to implement streams based on traditional
|
||||
// streams. Of course, many users will probably want to write their own
|
||||
// implementations of these interfaces specific to the particular I/O
|
||||
// abstractions they prefer to use, but these should cover the most common
|
||||
// cases.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_LITE_H__
|
||||
#define GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_LITE_H__
|
||||
|
||||
|
||||
#include <iosfwd>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/stubs/callback.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/io/zero_copy_stream.h>
|
||||
#include <google/protobuf/stubs/stl_util.h>
|
||||
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace io {
|
||||
|
||||
// ===================================================================
|
||||
|
||||
// A ZeroCopyInputStream backed by an in-memory array of bytes.
|
||||
class PROTOBUF_EXPORT ArrayInputStream PROTOBUF_FUTURE_FINAL
|
||||
: public ZeroCopyInputStream {
|
||||
public:
|
||||
// Create an InputStream that returns the bytes pointed to by "data".
|
||||
// "data" remains the property of the caller but must remain valid until
|
||||
// the stream is destroyed. If a block_size is given, calls to Next()
|
||||
// will return data blocks no larger than the given size. Otherwise, the
|
||||
// first call to Next() returns the entire array. block_size is mainly
|
||||
// useful for testing; in production you would probably never want to set
|
||||
// it.
|
||||
ArrayInputStream(const void* data, int size, int block_size = -1);
|
||||
~ArrayInputStream() override = default;
|
||||
|
||||
// implements ZeroCopyInputStream ----------------------------------
|
||||
bool Next(const void** data, int* size) override;
|
||||
void BackUp(int count) override;
|
||||
bool Skip(int count) override;
|
||||
int64_t ByteCount() const override;
|
||||
|
||||
|
||||
private:
|
||||
const uint8_t* const data_; // The byte array.
|
||||
const int size_; // Total size of the array.
|
||||
const int block_size_; // How many bytes to return at a time.
|
||||
|
||||
int position_;
|
||||
int last_returned_size_; // How many bytes we returned last time Next()
|
||||
// was called (used for error checking only).
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ArrayInputStream);
|
||||
};
|
||||
|
||||
// ===================================================================
|
||||
|
||||
// A ZeroCopyOutputStream backed by an in-memory array of bytes.
|
||||
class PROTOBUF_EXPORT ArrayOutputStream PROTOBUF_FUTURE_FINAL
|
||||
: public ZeroCopyOutputStream {
|
||||
public:
|
||||
// Create an OutputStream that writes to the bytes pointed to by "data".
|
||||
// "data" remains the property of the caller but must remain valid until
|
||||
// the stream is destroyed. If a block_size is given, calls to Next()
|
||||
// will return data blocks no larger than the given size. Otherwise, the
|
||||
// first call to Next() returns the entire array. block_size is mainly
|
||||
// useful for testing; in production you would probably never want to set
|
||||
// it.
|
||||
ArrayOutputStream(void* data, int size, int block_size = -1);
|
||||
~ArrayOutputStream() override = default;
|
||||
|
||||
// implements ZeroCopyOutputStream ---------------------------------
|
||||
bool Next(void** data, int* size) override;
|
||||
void BackUp(int count) override;
|
||||
int64_t ByteCount() const override;
|
||||
|
||||
private:
|
||||
uint8_t* const data_; // The byte array.
|
||||
const int size_; // Total size of the array.
|
||||
const int block_size_; // How many bytes to return at a time.
|
||||
|
||||
int position_;
|
||||
int last_returned_size_; // How many bytes we returned last time Next()
|
||||
// was called (used for error checking only).
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ArrayOutputStream);
|
||||
};
|
||||
|
||||
// ===================================================================
|
||||
|
||||
// A ZeroCopyOutputStream which appends bytes to a string.
|
||||
class PROTOBUF_EXPORT StringOutputStream PROTOBUF_FUTURE_FINAL
|
||||
: public ZeroCopyOutputStream {
|
||||
public:
|
||||
// Create a StringOutputStream which appends bytes to the given string.
|
||||
// The string remains property of the caller, but it is mutated in arbitrary
|
||||
// ways and MUST NOT be accessed in any way until you're done with the
|
||||
// stream. Either be sure there's no further usage, or (safest) destroy the
|
||||
// stream before using the contents.
|
||||
//
|
||||
// Hint: If you call target->reserve(n) before creating the stream,
|
||||
// the first call to Next() will return at least n bytes of buffer
|
||||
// space.
|
||||
explicit StringOutputStream(std::string* target);
|
||||
~StringOutputStream() override = default;
|
||||
|
||||
// implements ZeroCopyOutputStream ---------------------------------
|
||||
bool Next(void** data, int* size) override;
|
||||
void BackUp(int count) override;
|
||||
int64_t ByteCount() const override;
|
||||
|
||||
private:
|
||||
static constexpr size_t kMinimumSize = 16;
|
||||
|
||||
std::string* target_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringOutputStream);
|
||||
};
|
||||
|
||||
// Note: There is no StringInputStream. Instead, just create an
|
||||
// ArrayInputStream as follows:
|
||||
// ArrayInputStream input(str.data(), str.size());
|
||||
|
||||
// ===================================================================
|
||||
|
||||
// A generic traditional input stream interface.
|
||||
//
|
||||
// Lots of traditional input streams (e.g. file descriptors, C stdio
|
||||
// streams, and C++ iostreams) expose an interface where every read
|
||||
// involves copying bytes into a buffer. If you want to take such an
|
||||
// interface and make a ZeroCopyInputStream based on it, simply implement
|
||||
// CopyingInputStream and then use CopyingInputStreamAdaptor.
|
||||
//
|
||||
// CopyingInputStream implementations should avoid buffering if possible.
|
||||
// CopyingInputStreamAdaptor does its own buffering and will read data
|
||||
// in large blocks.
|
||||
class PROTOBUF_EXPORT CopyingInputStream {
|
||||
public:
|
||||
virtual ~CopyingInputStream() {}
|
||||
|
||||
// Reads up to "size" bytes into the given buffer. Returns the number of
|
||||
// bytes read. Read() waits until at least one byte is available, or
|
||||
// returns zero if no bytes will ever become available (EOF), or -1 if a
|
||||
// permanent read error occurred.
|
||||
virtual int Read(void* buffer, int size) = 0;
|
||||
|
||||
// Skips the next "count" bytes of input. Returns the number of bytes
|
||||
// actually skipped. This will always be exactly equal to "count" unless
|
||||
// EOF was reached or a permanent read error occurred.
|
||||
//
|
||||
// The default implementation just repeatedly calls Read() into a scratch
|
||||
// buffer.
|
||||
virtual int Skip(int count);
|
||||
};
|
||||
|
||||
// A ZeroCopyInputStream which reads from a CopyingInputStream. This is
|
||||
// useful for implementing ZeroCopyInputStreams that read from traditional
|
||||
// streams. Note that this class is not really zero-copy.
|
||||
//
|
||||
// If you want to read from file descriptors or C++ istreams, this is
|
||||
// already implemented for you: use FileInputStream or IstreamInputStream
|
||||
// respectively.
|
||||
class PROTOBUF_EXPORT CopyingInputStreamAdaptor : public ZeroCopyInputStream {
|
||||
public:
|
||||
// Creates a stream that reads from the given CopyingInputStream.
|
||||
// If a block_size is given, it specifies the number of bytes that
|
||||
// should be read and returned with each call to Next(). Otherwise,
|
||||
// a reasonable default is used. The caller retains ownership of
|
||||
// copying_stream unless SetOwnsCopyingStream(true) is called.
|
||||
explicit CopyingInputStreamAdaptor(CopyingInputStream* copying_stream,
|
||||
int block_size = -1);
|
||||
~CopyingInputStreamAdaptor() override;
|
||||
|
||||
// Call SetOwnsCopyingStream(true) to tell the CopyingInputStreamAdaptor to
|
||||
// delete the underlying CopyingInputStream when it is destroyed.
|
||||
void SetOwnsCopyingStream(bool value) { owns_copying_stream_ = value; }
|
||||
|
||||
// implements ZeroCopyInputStream ----------------------------------
|
||||
bool Next(const void** data, int* size) override;
|
||||
void BackUp(int count) override;
|
||||
bool Skip(int count) override;
|
||||
int64_t ByteCount() const override;
|
||||
|
||||
private:
|
||||
// Insures that buffer_ is not NULL.
|
||||
void AllocateBufferIfNeeded();
|
||||
// Frees the buffer and resets buffer_used_.
|
||||
void FreeBuffer();
|
||||
|
||||
// The underlying copying stream.
|
||||
CopyingInputStream* copying_stream_;
|
||||
bool owns_copying_stream_;
|
||||
|
||||
// True if we have seen a permanent error from the underlying stream.
|
||||
bool failed_;
|
||||
|
||||
// The current position of copying_stream_, relative to the point where
|
||||
// we started reading.
|
||||
int64_t position_;
|
||||
|
||||
// Data is read into this buffer. It may be NULL if no buffer is currently
|
||||
// in use. Otherwise, it points to an array of size buffer_size_.
|
||||
std::unique_ptr<uint8_t[]> buffer_;
|
||||
const int buffer_size_;
|
||||
|
||||
// Number of valid bytes currently in the buffer (i.e. the size last
|
||||
// returned by Next()). 0 <= buffer_used_ <= buffer_size_.
|
||||
int buffer_used_;
|
||||
|
||||
// Number of bytes in the buffer which were backed up over by a call to
|
||||
// BackUp(). These need to be returned again.
|
||||
// 0 <= backup_bytes_ <= buffer_used_
|
||||
int backup_bytes_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingInputStreamAdaptor);
|
||||
};
|
||||
|
||||
// ===================================================================
|
||||
|
||||
// A generic traditional output stream interface.
|
||||
//
|
||||
// Lots of traditional output streams (e.g. file descriptors, C stdio
|
||||
// streams, and C++ iostreams) expose an interface where every write
|
||||
// involves copying bytes from a buffer. If you want to take such an
|
||||
// interface and make a ZeroCopyOutputStream based on it, simply implement
|
||||
// CopyingOutputStream and then use CopyingOutputStreamAdaptor.
|
||||
//
|
||||
// CopyingOutputStream implementations should avoid buffering if possible.
|
||||
// CopyingOutputStreamAdaptor does its own buffering and will write data
|
||||
// in large blocks.
|
||||
class PROTOBUF_EXPORT CopyingOutputStream {
|
||||
public:
|
||||
virtual ~CopyingOutputStream() {}
|
||||
|
||||
// Writes "size" bytes from the given buffer to the output. Returns true
|
||||
// if successful, false on a write error.
|
||||
virtual bool Write(const void* buffer, int size) = 0;
|
||||
};
|
||||
|
||||
// A ZeroCopyOutputStream which writes to a CopyingOutputStream. This is
|
||||
// useful for implementing ZeroCopyOutputStreams that write to traditional
|
||||
// streams. Note that this class is not really zero-copy.
|
||||
//
|
||||
// If you want to write to file descriptors or C++ ostreams, this is
|
||||
// already implemented for you: use FileOutputStream or OstreamOutputStream
|
||||
// respectively.
|
||||
class PROTOBUF_EXPORT CopyingOutputStreamAdaptor : public ZeroCopyOutputStream {
|
||||
public:
|
||||
// Creates a stream that writes to the given Unix file descriptor.
|
||||
// If a block_size is given, it specifies the size of the buffers
|
||||
// that should be returned by Next(). Otherwise, a reasonable default
|
||||
// is used.
|
||||
explicit CopyingOutputStreamAdaptor(CopyingOutputStream* copying_stream,
|
||||
int block_size = -1);
|
||||
~CopyingOutputStreamAdaptor() override;
|
||||
|
||||
// Writes all pending data to the underlying stream. Returns false if a
|
||||
// write error occurred on the underlying stream. (The underlying
|
||||
// stream itself is not necessarily flushed.)
|
||||
bool Flush();
|
||||
|
||||
// Call SetOwnsCopyingStream(true) to tell the CopyingOutputStreamAdaptor to
|
||||
// delete the underlying CopyingOutputStream when it is destroyed.
|
||||
void SetOwnsCopyingStream(bool value) { owns_copying_stream_ = value; }
|
||||
|
||||
// implements ZeroCopyOutputStream ---------------------------------
|
||||
bool Next(void** data, int* size) override;
|
||||
void BackUp(int count) override;
|
||||
int64_t ByteCount() const override;
|
||||
bool WriteAliasedRaw(const void* data, int size) override;
|
||||
bool AllowsAliasing() const override { return true; }
|
||||
|
||||
private:
|
||||
// Write the current buffer, if it is present.
|
||||
bool WriteBuffer();
|
||||
// Insures that buffer_ is not NULL.
|
||||
void AllocateBufferIfNeeded();
|
||||
// Frees the buffer.
|
||||
void FreeBuffer();
|
||||
|
||||
// The underlying copying stream.
|
||||
CopyingOutputStream* copying_stream_;
|
||||
bool owns_copying_stream_;
|
||||
|
||||
// True if we have seen a permanent error from the underlying stream.
|
||||
bool failed_;
|
||||
|
||||
// The current position of copying_stream_, relative to the point where
|
||||
// we started writing.
|
||||
int64_t position_;
|
||||
|
||||
// Data is written from this buffer. It may be NULL if no buffer is
|
||||
// currently in use. Otherwise, it points to an array of size buffer_size_.
|
||||
std::unique_ptr<uint8_t[]> buffer_;
|
||||
const int buffer_size_;
|
||||
|
||||
// Number of valid bytes currently in the buffer (i.e. the size last
|
||||
// returned by Next()). When BackUp() is called, we just reduce this.
|
||||
// 0 <= buffer_used_ <= buffer_size_.
|
||||
int buffer_used_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingOutputStreamAdaptor);
|
||||
};
|
||||
|
||||
// ===================================================================
|
||||
|
||||
// A ZeroCopyInputStream which wraps some other stream and limits it to
|
||||
// a particular byte count.
|
||||
class PROTOBUF_EXPORT LimitingInputStream PROTOBUF_FUTURE_FINAL
|
||||
: public ZeroCopyInputStream {
|
||||
public:
|
||||
LimitingInputStream(ZeroCopyInputStream* input, int64_t limit);
|
||||
~LimitingInputStream() override;
|
||||
|
||||
// implements ZeroCopyInputStream ----------------------------------
|
||||
bool Next(const void** data, int* size) override;
|
||||
void BackUp(int count) override;
|
||||
bool Skip(int count) override;
|
||||
int64_t ByteCount() const override;
|
||||
|
||||
|
||||
private:
|
||||
ZeroCopyInputStream* input_;
|
||||
int64_t limit_; // Decreases as we go, becomes negative if we overshoot.
|
||||
int64_t prior_bytes_read_; // Bytes read on underlying stream at construction
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(LimitingInputStream);
|
||||
};
|
||||
|
||||
|
||||
// ===================================================================
|
||||
|
||||
// mutable_string_data() and as_string_data() are workarounds to improve
|
||||
// the performance of writing new data to an existing string. Unfortunately
|
||||
// the methods provided by the string class are suboptimal, and using memcpy()
|
||||
// is mildly annoying because it requires its pointer args to be non-NULL even
|
||||
// if we ask it to copy 0 bytes. Furthermore, string_as_array() has the
|
||||
// property that it always returns NULL if its arg is the empty string, exactly
|
||||
// what we want to avoid if we're using it in conjunction with memcpy()!
|
||||
// With C++11, the desired memcpy() boils down to memcpy(..., &(*s)[0], size),
|
||||
// where s is a string*. Without C++11, &(*s)[0] is not guaranteed to be safe,
|
||||
// so we use string_as_array(), and live with the extra logic that tests whether
|
||||
// *s is empty.
|
||||
|
||||
// Return a pointer to mutable characters underlying the given string. The
|
||||
// return value is valid until the next time the string is resized. We
|
||||
// trust the caller to treat the return value as an array of length s->size().
|
||||
inline char* mutable_string_data(std::string* s) {
|
||||
// This should be simpler & faster than string_as_array() because the latter
|
||||
// is guaranteed to return NULL when *s is empty, so it has to check for that.
|
||||
return &(*s)[0];
|
||||
}
|
||||
|
||||
// as_string_data(s) is equivalent to
|
||||
// ({ char* p = mutable_string_data(s); make_pair(p, p != NULL); })
|
||||
// Sometimes it's faster: in some scenarios p cannot be NULL, and then the
|
||||
// code can avoid that check.
|
||||
inline std::pair<char*, bool> as_string_data(std::string* s) {
|
||||
char* p = mutable_string_data(s);
|
||||
return std::make_pair(p, true);
|
||||
}
|
||||
|
||||
} // namespace io
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_LITE_H__
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,134 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_MAP_ENTRY_H__
|
||||
#define GOOGLE_PROTOBUF_MAP_ENTRY_H__
|
||||
|
||||
#include <google/protobuf/port.h>
|
||||
#include <google/protobuf/generated_message_reflection.h>
|
||||
#include <google/protobuf/map_entry_lite.h>
|
||||
#include <google/protobuf/map_type_handler.h>
|
||||
#include <google/protobuf/reflection_ops.h>
|
||||
#include <google/protobuf/unknown_field_set.h>
|
||||
#include <google/protobuf/wire_format_lite.h>
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
#ifdef SWIG
|
||||
#error "You cannot SWIG proto headers"
|
||||
#endif
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
class Arena;
|
||||
namespace internal {
|
||||
template <typename Derived, typename Key, typename Value,
|
||||
WireFormatLite::FieldType kKeyFieldType,
|
||||
WireFormatLite::FieldType kValueFieldType>
|
||||
class MapField;
|
||||
}
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
// MapEntry is the returned google::protobuf::Message when calling AddMessage of
|
||||
// google::protobuf::Reflection. In order to let it work with generated message
|
||||
// reflection, its in-memory type is the same as generated message with the same
|
||||
// fields. However, in order to decide the in-memory type of key/value, we need
|
||||
// to know both their cpp type in generated api and proto type. In
|
||||
// implementation, all in-memory types have related wire format functions to
|
||||
// support except ArenaStringPtr. Therefore, we need to define another type with
|
||||
// supporting wire format functions. Since this type is only used as return type
|
||||
// of MapEntry accessors, it's named MapEntry accessor type.
|
||||
//
|
||||
// cpp type: the type visible to users in public API.
|
||||
// proto type: WireFormatLite::FieldType of the field.
|
||||
// in-memory type: type of the data member used to stored this field.
|
||||
// MapEntry accessor type: type used in MapEntry getters/mutators to access the
|
||||
// field.
|
||||
//
|
||||
// cpp type | proto type | in-memory type | MapEntry accessor type
|
||||
// int32_t TYPE_INT32 int32_t int32_t
|
||||
// int32_t TYPE_FIXED32 int32_t int32_t
|
||||
// string TYPE_STRING ArenaStringPtr string
|
||||
// FooEnum TYPE_ENUM int int
|
||||
// FooMessage TYPE_MESSAGE FooMessage* FooMessage
|
||||
//
|
||||
// The in-memory types of primitive types can be inferred from its proto type,
|
||||
// while we need to explicitly specify the cpp type if proto type is
|
||||
// TYPE_MESSAGE to infer the in-memory type.
|
||||
template <typename Derived, typename Key, typename Value,
|
||||
WireFormatLite::FieldType kKeyFieldType,
|
||||
WireFormatLite::FieldType kValueFieldType>
|
||||
class MapEntry : public MapEntryImpl<Derived, Message, Key, Value,
|
||||
kKeyFieldType, kValueFieldType> {
|
||||
public:
|
||||
constexpr MapEntry() {}
|
||||
explicit MapEntry(Arena* arena)
|
||||
: MapEntryImpl<Derived, Message, Key, Value, kKeyFieldType,
|
||||
kValueFieldType>(arena) {}
|
||||
~MapEntry() override {
|
||||
Message::_internal_metadata_.template Delete<UnknownFieldSet>();
|
||||
}
|
||||
typedef void InternalArenaConstructable_;
|
||||
typedef void DestructorSkippable_;
|
||||
|
||||
typedef typename MapEntryImpl<Derived, Message, Key, Value, kKeyFieldType,
|
||||
kValueFieldType>::KeyTypeHandler KeyTypeHandler;
|
||||
typedef
|
||||
typename MapEntryImpl<Derived, Message, Key, Value, kKeyFieldType,
|
||||
kValueFieldType>::ValueTypeHandler ValueTypeHandler;
|
||||
size_t SpaceUsedLong() const override {
|
||||
size_t size = sizeof(Derived);
|
||||
size += KeyTypeHandler::SpaceUsedInMapEntryLong(this->key_);
|
||||
size += ValueTypeHandler::SpaceUsedInMapEntryLong(this->value_);
|
||||
return size;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class ::PROTOBUF_NAMESPACE_ID::Arena;
|
||||
template <typename C, typename K, typename V,
|
||||
WireFormatLite::FieldType k_wire_type, WireFormatLite::FieldType>
|
||||
friend class internal::MapField;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntry);
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_MAP_ENTRY_H__
|
||||
@@ -1,563 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_MAP_ENTRY_LITE_H__
|
||||
#define GOOGLE_PROTOBUF_MAP_ENTRY_LITE_H__
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include <google/protobuf/stubs/casts.h>
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/arena.h>
|
||||
#include <google/protobuf/port.h>
|
||||
#include <google/protobuf/arenastring.h>
|
||||
#include <google/protobuf/generated_message_util.h>
|
||||
#include <google/protobuf/map.h>
|
||||
#include <google/protobuf/map_type_handler.h>
|
||||
#include <google/protobuf/parse_context.h>
|
||||
#include <google/protobuf/wire_format_lite.h>
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
#ifdef SWIG
|
||||
#error "You cannot SWIG proto headers"
|
||||
#endif
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
template <typename Derived, typename Key, typename Value,
|
||||
WireFormatLite::FieldType kKeyFieldType,
|
||||
WireFormatLite::FieldType kValueFieldType>
|
||||
class MapEntry;
|
||||
template <typename Derived, typename Key, typename Value,
|
||||
WireFormatLite::FieldType kKeyFieldType,
|
||||
WireFormatLite::FieldType kValueFieldType>
|
||||
class MapFieldLite;
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
// MoveHelper::Move is used to set *dest. It copies *src, or moves it (in
|
||||
// the C++11 sense), or swaps it. *src is left in a sane state for
|
||||
// subsequent destruction, but shouldn't be used for anything.
|
||||
template <bool is_enum, bool is_message, bool is_stringlike, typename T>
|
||||
struct MoveHelper { // primitives
|
||||
static void Move(T* src, T* dest) { *dest = *src; }
|
||||
};
|
||||
|
||||
template <bool is_message, bool is_stringlike, typename T>
|
||||
struct MoveHelper<true, is_message, is_stringlike, T> { // enums
|
||||
static void Move(T* src, T* dest) { *dest = *src; }
|
||||
// T is an enum here, so allow conversions to and from int.
|
||||
static void Move(T* src, int* dest) { *dest = static_cast<int>(*src); }
|
||||
static void Move(int* src, T* dest) { *dest = static_cast<T>(*src); }
|
||||
};
|
||||
|
||||
template <bool is_stringlike, typename T>
|
||||
struct MoveHelper<false, true, is_stringlike, T> { // messages
|
||||
static void Move(T* src, T* dest) { dest->Swap(src); }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct MoveHelper<false, false, true, T> { // strings and similar
|
||||
static void Move(T* src, T* dest) {
|
||||
*dest = std::move(*src);
|
||||
}
|
||||
};
|
||||
|
||||
// MapEntryImpl is used to implement parsing and serialization of map entries.
|
||||
// It uses Curious Recursive Template Pattern (CRTP) to provide the type of
|
||||
// the eventual code to the template code.
|
||||
template <typename Derived, typename Base, typename Key, typename Value,
|
||||
WireFormatLite::FieldType kKeyFieldType,
|
||||
WireFormatLite::FieldType kValueFieldType>
|
||||
class MapEntryImpl : public Base {
|
||||
public:
|
||||
typedef MapEntryFuncs<Key, Value, kKeyFieldType, kValueFieldType> Funcs;
|
||||
|
||||
protected:
|
||||
// Provide utilities to parse/serialize key/value. Provide utilities to
|
||||
// manipulate internal stored type.
|
||||
typedef MapTypeHandler<kKeyFieldType, Key> KeyTypeHandler;
|
||||
typedef MapTypeHandler<kValueFieldType, Value> ValueTypeHandler;
|
||||
|
||||
// Define internal memory layout. Strings and messages are stored as
|
||||
// pointers, while other types are stored as values.
|
||||
typedef typename KeyTypeHandler::TypeOnMemory KeyOnMemory;
|
||||
typedef typename ValueTypeHandler::TypeOnMemory ValueOnMemory;
|
||||
|
||||
// Enum type cannot be used for MapTypeHandler::Read. Define a type
|
||||
// which will replace Enum with int.
|
||||
typedef typename KeyTypeHandler::MapEntryAccessorType KeyMapEntryAccessorType;
|
||||
typedef
|
||||
typename ValueTypeHandler::MapEntryAccessorType ValueMapEntryAccessorType;
|
||||
|
||||
// Constants for field number.
|
||||
static const int kKeyFieldNumber = 1;
|
||||
static const int kValueFieldNumber = 2;
|
||||
|
||||
// Constants for field tag.
|
||||
static const uint8_t kKeyTag =
|
||||
GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(kKeyFieldNumber, KeyTypeHandler::kWireType);
|
||||
static const uint8_t kValueTag = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(
|
||||
kValueFieldNumber, ValueTypeHandler::kWireType);
|
||||
static const size_t kTagSize = 1;
|
||||
|
||||
public:
|
||||
// Work-around for a compiler bug (see repeated_field.h).
|
||||
typedef void MapEntryHasMergeTypeTrait;
|
||||
typedef Derived EntryType;
|
||||
typedef Key EntryKeyType;
|
||||
typedef Value EntryValueType;
|
||||
static const WireFormatLite::FieldType kEntryKeyFieldType = kKeyFieldType;
|
||||
static const WireFormatLite::FieldType kEntryValueFieldType = kValueFieldType;
|
||||
|
||||
constexpr MapEntryImpl()
|
||||
: key_(KeyTypeHandler::Constinit()),
|
||||
value_(ValueTypeHandler::Constinit()),
|
||||
_has_bits_{} {}
|
||||
|
||||
explicit MapEntryImpl(Arena* arena)
|
||||
: Base(arena),
|
||||
key_(KeyTypeHandler::Constinit()),
|
||||
value_(ValueTypeHandler::Constinit()),
|
||||
_has_bits_{} {}
|
||||
|
||||
~MapEntryImpl() override {
|
||||
if (Base::GetArenaForAllocation() != nullptr) return;
|
||||
KeyTypeHandler::DeleteNoArena(key_);
|
||||
ValueTypeHandler::DeleteNoArena(value_);
|
||||
}
|
||||
|
||||
// accessors ======================================================
|
||||
|
||||
virtual inline const KeyMapEntryAccessorType& key() const {
|
||||
return KeyTypeHandler::GetExternalReference(key_);
|
||||
}
|
||||
virtual inline const ValueMapEntryAccessorType& value() const {
|
||||
return ValueTypeHandler::DefaultIfNotInitialized(value_);
|
||||
}
|
||||
inline KeyMapEntryAccessorType* mutable_key() {
|
||||
set_has_key();
|
||||
return KeyTypeHandler::EnsureMutable(&key_, Base::GetArenaForAllocation());
|
||||
}
|
||||
inline ValueMapEntryAccessorType* mutable_value() {
|
||||
set_has_value();
|
||||
return ValueTypeHandler::EnsureMutable(&value_,
|
||||
Base::GetArenaForAllocation());
|
||||
}
|
||||
|
||||
// implements MessageLite =========================================
|
||||
|
||||
// MapEntryImpl is for implementation only and this function isn't called
|
||||
// anywhere. Just provide a fake implementation here for MessageLite.
|
||||
std::string GetTypeName() const override { return ""; }
|
||||
|
||||
void CheckTypeAndMergeFrom(const MessageLite& other) override {
|
||||
MergeFromInternal(*::google::protobuf::internal::DownCast<const Derived*>(&other));
|
||||
}
|
||||
|
||||
const char* _InternalParse(const char* ptr, ParseContext* ctx) final {
|
||||
while (!ctx->Done(&ptr)) {
|
||||
uint32_t tag;
|
||||
ptr = ReadTag(ptr, &tag);
|
||||
GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
|
||||
if (tag == kKeyTag) {
|
||||
set_has_key();
|
||||
KeyMapEntryAccessorType* key = mutable_key();
|
||||
ptr = KeyTypeHandler::Read(ptr, ctx, key);
|
||||
if (!Derived::ValidateKey(key)) return nullptr;
|
||||
} else if (tag == kValueTag) {
|
||||
set_has_value();
|
||||
ValueMapEntryAccessorType* value = mutable_value();
|
||||
ptr = ValueTypeHandler::Read(ptr, ctx, value);
|
||||
if (!Derived::ValidateValue(value)) return nullptr;
|
||||
} else {
|
||||
if (tag == 0 || WireFormatLite::GetTagWireType(tag) ==
|
||||
WireFormatLite::WIRETYPE_END_GROUP) {
|
||||
ctx->SetLastTag(tag);
|
||||
return ptr;
|
||||
}
|
||||
ptr = UnknownFieldParse(tag, static_cast<std::string*>(nullptr), ptr,
|
||||
ctx);
|
||||
}
|
||||
GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
size_t ByteSizeLong() const override {
|
||||
size_t size = 0;
|
||||
size += kTagSize + static_cast<size_t>(KeyTypeHandler::ByteSize(key()));
|
||||
size += kTagSize + static_cast<size_t>(ValueTypeHandler::ByteSize(value()));
|
||||
return size;
|
||||
}
|
||||
|
||||
::uint8_t* _InternalSerialize(
|
||||
::uint8_t* ptr, io::EpsCopyOutputStream* stream) const override {
|
||||
ptr = KeyTypeHandler::Write(kKeyFieldNumber, key(), ptr, stream);
|
||||
return ValueTypeHandler::Write(kValueFieldNumber, value(), ptr, stream);
|
||||
}
|
||||
|
||||
// Don't override SerializeWithCachedSizesToArray. Use MessageLite's.
|
||||
|
||||
int GetCachedSize() const override {
|
||||
int size = 0;
|
||||
size += has_key() ? static_cast<int>(kTagSize) +
|
||||
KeyTypeHandler::GetCachedSize(key())
|
||||
: 0;
|
||||
size += has_value() ? static_cast<int>(kTagSize) +
|
||||
ValueTypeHandler::GetCachedSize(value())
|
||||
: 0;
|
||||
return size;
|
||||
}
|
||||
|
||||
bool IsInitialized() const override {
|
||||
return ValueTypeHandler::IsInitialized(value_);
|
||||
}
|
||||
|
||||
Base* New(Arena* arena) const override {
|
||||
Derived* entry = Arena::CreateMessage<Derived>(arena);
|
||||
return entry;
|
||||
}
|
||||
|
||||
protected:
|
||||
// We can't declare this function directly here as it would hide the other
|
||||
// overload (const Message&).
|
||||
void MergeFromInternal(const MapEntryImpl& from) {
|
||||
if (from._has_bits_[0]) {
|
||||
if (from.has_key()) {
|
||||
KeyTypeHandler::EnsureMutable(&key_, Base::GetArenaForAllocation());
|
||||
KeyTypeHandler::Merge(from.key(), &key_, Base::GetArenaForAllocation());
|
||||
set_has_key();
|
||||
}
|
||||
if (from.has_value()) {
|
||||
ValueTypeHandler::EnsureMutable(&value_, Base::GetArenaForAllocation());
|
||||
ValueTypeHandler::Merge(from.value(), &value_,
|
||||
Base::GetArenaForAllocation());
|
||||
set_has_value();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
void Clear() override {
|
||||
KeyTypeHandler::Clear(&key_, Base::GetArenaForAllocation());
|
||||
ValueTypeHandler::Clear(&value_, Base::GetArenaForAllocation());
|
||||
clear_has_key();
|
||||
clear_has_value();
|
||||
}
|
||||
|
||||
// Parsing using MergePartialFromCodedStream, above, is not as
|
||||
// efficient as it could be. This helper class provides a speedier way.
|
||||
template <typename MapField, typename Map>
|
||||
class Parser {
|
||||
public:
|
||||
explicit Parser(MapField* mf) : mf_(mf), map_(mf->MutableMap()) {}
|
||||
~Parser() {
|
||||
if (entry_ != nullptr && entry_->GetArenaForAllocation() == nullptr)
|
||||
delete entry_;
|
||||
}
|
||||
|
||||
const char* _InternalParse(const char* ptr, ParseContext* ctx) {
|
||||
if (PROTOBUF_PREDICT_TRUE(!ctx->Done(&ptr) && *ptr == kKeyTag)) {
|
||||
ptr = KeyTypeHandler::Read(ptr + 1, ctx, &key_);
|
||||
if (PROTOBUF_PREDICT_FALSE(!ptr || !Derived::ValidateKey(&key_))) {
|
||||
return nullptr;
|
||||
}
|
||||
if (PROTOBUF_PREDICT_TRUE(!ctx->Done(&ptr) && *ptr == kValueTag)) {
|
||||
typename Map::size_type map_size = map_->size();
|
||||
value_ptr_ = &(*map_)[key_];
|
||||
if (PROTOBUF_PREDICT_TRUE(map_size != map_->size())) {
|
||||
using T =
|
||||
typename MapIf<ValueTypeHandler::kIsEnum, int*, Value*>::type;
|
||||
ptr = ValueTypeHandler::Read(ptr + 1, ctx,
|
||||
reinterpret_cast<T>(value_ptr_));
|
||||
if (PROTOBUF_PREDICT_FALSE(!ptr ||
|
||||
!Derived::ValidateValue(value_ptr_))) {
|
||||
map_->erase(key_); // Failure! Undo insertion.
|
||||
return nullptr;
|
||||
}
|
||||
if (PROTOBUF_PREDICT_TRUE(ctx->Done(&ptr))) return ptr;
|
||||
if (!ptr) return nullptr;
|
||||
NewEntry();
|
||||
ValueMover::Move(value_ptr_, entry_->mutable_value());
|
||||
map_->erase(key_);
|
||||
goto move_key;
|
||||
}
|
||||
} else {
|
||||
if (!ptr) return nullptr;
|
||||
}
|
||||
NewEntry();
|
||||
move_key:
|
||||
KeyMover::Move(&key_, entry_->mutable_key());
|
||||
} else {
|
||||
if (!ptr) return nullptr;
|
||||
NewEntry();
|
||||
}
|
||||
ptr = entry_->_InternalParse(ptr, ctx);
|
||||
if (ptr) UseKeyAndValueFromEntry();
|
||||
return ptr;
|
||||
}
|
||||
|
||||
template <typename UnknownType>
|
||||
const char* ParseWithEnumValidation(const char* ptr, ParseContext* ctx,
|
||||
bool (*is_valid)(int),
|
||||
uint32_t field_num,
|
||||
InternalMetadata* metadata) {
|
||||
auto entry = NewEntry();
|
||||
ptr = entry->_InternalParse(ptr, ctx);
|
||||
if (!ptr) return nullptr;
|
||||
if (is_valid(entry->value())) {
|
||||
UseKeyAndValueFromEntry();
|
||||
} else {
|
||||
WriteLengthDelimited(field_num, entry->SerializeAsString(),
|
||||
metadata->mutable_unknown_fields<UnknownType>());
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
MapEntryImpl* NewEntry() { return entry_ = mf_->NewEntry(); }
|
||||
|
||||
const Key& key() const { return key_; }
|
||||
const Value& value() const { return *value_ptr_; }
|
||||
|
||||
const Key& entry_key() const { return entry_->key(); }
|
||||
const Value& entry_value() const { return entry_->value(); }
|
||||
|
||||
private:
|
||||
void UseKeyAndValueFromEntry() {
|
||||
// Update key_ in case we need it later (because key() is called).
|
||||
// This is potentially inefficient, especially if the key is
|
||||
// expensive to copy (e.g., a long string), but this is a cold
|
||||
// path, so it's not a big deal.
|
||||
key_ = entry_->key();
|
||||
value_ptr_ = &(*map_)[key_];
|
||||
ValueMover::Move(entry_->mutable_value(), value_ptr_);
|
||||
}
|
||||
|
||||
// After reading a key and value successfully, and inserting that data
|
||||
// into map_, we are not at the end of the input. This is unusual, but
|
||||
// allowed by the spec.
|
||||
bool ReadBeyondKeyValuePair(io::CodedInputStream* input) PROTOBUF_COLD {
|
||||
NewEntry();
|
||||
ValueMover::Move(value_ptr_, entry_->mutable_value());
|
||||
map_->erase(key_);
|
||||
KeyMover::Move(&key_, entry_->mutable_key());
|
||||
const bool result = entry_->MergePartialFromCodedStream(input);
|
||||
if (result) UseKeyAndValueFromEntry();
|
||||
return result;
|
||||
}
|
||||
|
||||
typedef MoveHelper<KeyTypeHandler::kIsEnum, KeyTypeHandler::kIsMessage,
|
||||
KeyTypeHandler::kWireType ==
|
||||
WireFormatLite::WIRETYPE_LENGTH_DELIMITED,
|
||||
Key>
|
||||
KeyMover;
|
||||
typedef MoveHelper<ValueTypeHandler::kIsEnum, ValueTypeHandler::kIsMessage,
|
||||
ValueTypeHandler::kWireType ==
|
||||
WireFormatLite::WIRETYPE_LENGTH_DELIMITED,
|
||||
Value>
|
||||
ValueMover;
|
||||
|
||||
MapField* const mf_;
|
||||
Map* const map_;
|
||||
Key key_;
|
||||
Value* value_ptr_;
|
||||
MapEntryImpl* entry_ = nullptr;
|
||||
};
|
||||
|
||||
protected:
|
||||
void set_has_key() { _has_bits_[0] |= 0x00000001u; }
|
||||
bool has_key() const { return (_has_bits_[0] & 0x00000001u) != 0; }
|
||||
void clear_has_key() { _has_bits_[0] &= ~0x00000001u; }
|
||||
void set_has_value() { _has_bits_[0] |= 0x00000002u; }
|
||||
bool has_value() const { return (_has_bits_[0] & 0x00000002u) != 0; }
|
||||
void clear_has_value() { _has_bits_[0] &= ~0x00000002u; }
|
||||
|
||||
public:
|
||||
inline Arena* GetArena() const { return Base::GetArena(); }
|
||||
|
||||
protected: // Needed for constructing tables
|
||||
KeyOnMemory key_;
|
||||
ValueOnMemory value_;
|
||||
uint32_t _has_bits_[1];
|
||||
|
||||
private:
|
||||
friend class ::PROTOBUF_NAMESPACE_ID::Arena;
|
||||
typedef void InternalArenaConstructable_;
|
||||
typedef void DestructorSkippable_;
|
||||
template <typename C, typename K, typename V, WireFormatLite::FieldType,
|
||||
WireFormatLite::FieldType>
|
||||
friend class internal::MapEntry;
|
||||
template <typename C, typename K, typename V, WireFormatLite::FieldType,
|
||||
WireFormatLite::FieldType>
|
||||
friend class internal::MapFieldLite;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntryImpl);
|
||||
};
|
||||
|
||||
template <typename T, typename Key, typename Value,
|
||||
WireFormatLite::FieldType kKeyFieldType,
|
||||
WireFormatLite::FieldType kValueFieldType>
|
||||
class MapEntryLite : public MapEntryImpl<T, MessageLite, Key, Value,
|
||||
kKeyFieldType, kValueFieldType> {
|
||||
public:
|
||||
typedef MapEntryImpl<T, MessageLite, Key, Value, kKeyFieldType,
|
||||
kValueFieldType>
|
||||
SuperType;
|
||||
constexpr MapEntryLite() {}
|
||||
explicit MapEntryLite(Arena* arena) : SuperType(arena) {}
|
||||
~MapEntryLite() override {
|
||||
MessageLite::_internal_metadata_.template Delete<std::string>();
|
||||
}
|
||||
void MergeFrom(const MapEntryLite& other) { MergeFromInternal(other); }
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntryLite);
|
||||
};
|
||||
|
||||
// Helpers for deterministic serialization =============================
|
||||
|
||||
// Iterator base for MapSorterFlat and MapSorterPtr.
|
||||
template <typename storage_type>
|
||||
struct MapSorterIt {
|
||||
storage_type* ptr;
|
||||
MapSorterIt(storage_type* ptr) : ptr(ptr) {}
|
||||
bool operator==(const MapSorterIt& other) const { return ptr == other.ptr; }
|
||||
bool operator!=(const MapSorterIt& other) const { return !(*this == other); }
|
||||
MapSorterIt& operator++() { ++ptr; return *this; }
|
||||
MapSorterIt operator++(int) { auto other = *this; ++ptr; return other; }
|
||||
MapSorterIt operator+(int v) { return MapSorterIt{ptr + v}; }
|
||||
};
|
||||
|
||||
// MapSorterFlat stores keys inline with pointers to map entries, so that
|
||||
// keys can be compared without indirection. This type is used for maps with
|
||||
// keys that are not strings.
|
||||
template <typename MapT>
|
||||
class MapSorterFlat {
|
||||
public:
|
||||
using value_type = typename MapT::value_type;
|
||||
using storage_type = std::pair<typename MapT::key_type, const value_type*>;
|
||||
|
||||
// This const_iterator dereferenes to the map entry stored in the sorting
|
||||
// array pairs. This is the same interface as the Map::const_iterator type,
|
||||
// and allows generated code to use the same loop body with either form:
|
||||
// for (const auto& entry : map) { ... }
|
||||
// for (const auto& entry : MapSorterFlat(map)) { ... }
|
||||
struct const_iterator : public MapSorterIt<storage_type> {
|
||||
using pointer = const typename MapT::value_type*;
|
||||
using reference = const typename MapT::value_type&;
|
||||
using MapSorterIt<storage_type>::MapSorterIt;
|
||||
|
||||
pointer operator->() const { return this->ptr->second; }
|
||||
reference operator*() const { return *this->operator->(); }
|
||||
};
|
||||
|
||||
explicit MapSorterFlat(const MapT& m)
|
||||
: size_(m.size()), items_(size_ ? new storage_type[size_] : nullptr) {
|
||||
if (!size_) return;
|
||||
storage_type* it = &items_[0];
|
||||
for (const auto& entry : m) {
|
||||
*it++ = {entry.first, &entry};
|
||||
}
|
||||
std::sort(&items_[0], &items_[size_],
|
||||
[](const storage_type& a, const storage_type& b) {
|
||||
return a.first < b.first;
|
||||
});
|
||||
}
|
||||
size_t size() const { return size_; }
|
||||
const_iterator begin() const { return {items_.get()}; }
|
||||
const_iterator end() const { return {items_.get() + size_}; }
|
||||
|
||||
private:
|
||||
size_t size_;
|
||||
std::unique_ptr<storage_type[]> items_;
|
||||
};
|
||||
|
||||
// MapSorterPtr stores and sorts pointers to map entries. This type is used for
|
||||
// maps with keys that are strings.
|
||||
template <typename MapT>
|
||||
class MapSorterPtr {
|
||||
public:
|
||||
using value_type = typename MapT::value_type;
|
||||
using storage_type = const typename MapT::value_type*;
|
||||
|
||||
// This const_iterator dereferenes the map entry pointer stored in the sorting
|
||||
// array. This is the same interface as the Map::const_iterator type, and
|
||||
// allows generated code to use the same loop body with either form:
|
||||
// for (const auto& entry : map) { ... }
|
||||
// for (const auto& entry : MapSorterPtr(map)) { ... }
|
||||
struct const_iterator : public MapSorterIt<storage_type> {
|
||||
using pointer = const typename MapT::value_type*;
|
||||
using reference = const typename MapT::value_type&;
|
||||
using MapSorterIt<storage_type>::MapSorterIt;
|
||||
|
||||
pointer operator->() const { return *this->ptr; }
|
||||
reference operator*() const { return *this->operator->(); }
|
||||
};
|
||||
|
||||
explicit MapSorterPtr(const MapT& m)
|
||||
: size_(m.size()), items_(size_ ? new storage_type[size_] : nullptr) {
|
||||
if (!size_) return;
|
||||
storage_type* it = &items_[0];
|
||||
for (const auto& entry : m) {
|
||||
*it++ = &entry;
|
||||
}
|
||||
std::sort(&items_[0], &items_[size_],
|
||||
[](const storage_type& a, const storage_type& b) {
|
||||
return a->first < b->first;
|
||||
});
|
||||
}
|
||||
size_t size() const { return size_; }
|
||||
const_iterator begin() const { return {items_.get()}; }
|
||||
const_iterator end() const { return {items_.get() + size_}; }
|
||||
|
||||
private:
|
||||
size_t size_;
|
||||
std::unique_ptr<storage_type[]> items_;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_MAP_ENTRY_LITE_H__
|
||||
@@ -1,946 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_MAP_FIELD_H__
|
||||
#define GOOGLE_PROTOBUF_MAP_FIELD_H__
|
||||
|
||||
#include <atomic>
|
||||
#include <functional>
|
||||
|
||||
#include <google/protobuf/arena.h>
|
||||
#include <google/protobuf/stubs/mutex.h>
|
||||
#include <google/protobuf/port.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/generated_message_reflection.h>
|
||||
#include <google/protobuf/generated_message_util.h>
|
||||
#include <google/protobuf/map_entry.h>
|
||||
#include <google/protobuf/map_field_lite.h>
|
||||
#include <google/protobuf/map_type_handler.h>
|
||||
#include <google/protobuf/message.h>
|
||||
#include <google/protobuf/repeated_field.h>
|
||||
#include <google/protobuf/unknown_field_set.h>
|
||||
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
#ifdef SWIG
|
||||
#error "You cannot SWIG proto headers"
|
||||
#endif
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
class DynamicMessage;
|
||||
class MapIterator;
|
||||
|
||||
// Microsoft compiler complains about non-virtual destructor,
|
||||
// even when the destructor is private.
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4265)
|
||||
#endif // _MSC_VER
|
||||
|
||||
#define TYPE_CHECK(EXPECTEDTYPE, METHOD) \
|
||||
if (type() != EXPECTEDTYPE) { \
|
||||
GOOGLE_LOG(FATAL) << "Protocol Buffer map usage error:\n" \
|
||||
<< METHOD << " type does not match\n" \
|
||||
<< " Expected : " \
|
||||
<< FieldDescriptor::CppTypeName(EXPECTEDTYPE) << "\n" \
|
||||
<< " Actual : " << FieldDescriptor::CppTypeName(type()); \
|
||||
}
|
||||
|
||||
// MapKey is an union type for representing any possible
|
||||
// map key.
|
||||
class PROTOBUF_EXPORT MapKey {
|
||||
public:
|
||||
MapKey() : type_() {}
|
||||
MapKey(const MapKey& other) : type_() { CopyFrom(other); }
|
||||
|
||||
MapKey& operator=(const MapKey& other) {
|
||||
CopyFrom(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
~MapKey() {
|
||||
if (type_ == FieldDescriptor::CPPTYPE_STRING) {
|
||||
val_.string_value_.Destruct();
|
||||
}
|
||||
}
|
||||
|
||||
FieldDescriptor::CppType type() const {
|
||||
if (type_ == FieldDescriptor::CppType()) {
|
||||
GOOGLE_LOG(FATAL) << "Protocol Buffer map usage error:\n"
|
||||
<< "MapKey::type MapKey is not initialized. "
|
||||
<< "Call set methods to initialize MapKey.";
|
||||
}
|
||||
return type_;
|
||||
}
|
||||
|
||||
void SetInt64Value(int64_t value) {
|
||||
SetType(FieldDescriptor::CPPTYPE_INT64);
|
||||
val_.int64_value_ = value;
|
||||
}
|
||||
void SetUInt64Value(uint64_t value) {
|
||||
SetType(FieldDescriptor::CPPTYPE_UINT64);
|
||||
val_.uint64_value_ = value;
|
||||
}
|
||||
void SetInt32Value(int32_t value) {
|
||||
SetType(FieldDescriptor::CPPTYPE_INT32);
|
||||
val_.int32_value_ = value;
|
||||
}
|
||||
void SetUInt32Value(uint32_t value) {
|
||||
SetType(FieldDescriptor::CPPTYPE_UINT32);
|
||||
val_.uint32_value_ = value;
|
||||
}
|
||||
void SetBoolValue(bool value) {
|
||||
SetType(FieldDescriptor::CPPTYPE_BOOL);
|
||||
val_.bool_value_ = value;
|
||||
}
|
||||
void SetStringValue(std::string val) {
|
||||
SetType(FieldDescriptor::CPPTYPE_STRING);
|
||||
*val_.string_value_.get_mutable() = std::move(val);
|
||||
}
|
||||
|
||||
int64_t GetInt64Value() const {
|
||||
TYPE_CHECK(FieldDescriptor::CPPTYPE_INT64, "MapKey::GetInt64Value");
|
||||
return val_.int64_value_;
|
||||
}
|
||||
uint64_t GetUInt64Value() const {
|
||||
TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT64, "MapKey::GetUInt64Value");
|
||||
return val_.uint64_value_;
|
||||
}
|
||||
int32_t GetInt32Value() const {
|
||||
TYPE_CHECK(FieldDescriptor::CPPTYPE_INT32, "MapKey::GetInt32Value");
|
||||
return val_.int32_value_;
|
||||
}
|
||||
uint32_t GetUInt32Value() const {
|
||||
TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT32, "MapKey::GetUInt32Value");
|
||||
return val_.uint32_value_;
|
||||
}
|
||||
bool GetBoolValue() const {
|
||||
TYPE_CHECK(FieldDescriptor::CPPTYPE_BOOL, "MapKey::GetBoolValue");
|
||||
return val_.bool_value_;
|
||||
}
|
||||
const std::string& GetStringValue() const {
|
||||
TYPE_CHECK(FieldDescriptor::CPPTYPE_STRING, "MapKey::GetStringValue");
|
||||
return val_.string_value_.get();
|
||||
}
|
||||
|
||||
bool operator<(const MapKey& other) const {
|
||||
if (type_ != other.type_) {
|
||||
// We could define a total order that handles this case, but
|
||||
// there currently no need. So, for now, fail.
|
||||
GOOGLE_LOG(FATAL) << "Unsupported: type mismatch";
|
||||
}
|
||||
switch (type()) {
|
||||
case FieldDescriptor::CPPTYPE_DOUBLE:
|
||||
case FieldDescriptor::CPPTYPE_FLOAT:
|
||||
case FieldDescriptor::CPPTYPE_ENUM:
|
||||
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||
GOOGLE_LOG(FATAL) << "Unsupported";
|
||||
return false;
|
||||
case FieldDescriptor::CPPTYPE_STRING:
|
||||
return val_.string_value_.get() < other.val_.string_value_.get();
|
||||
case FieldDescriptor::CPPTYPE_INT64:
|
||||
return val_.int64_value_ < other.val_.int64_value_;
|
||||
case FieldDescriptor::CPPTYPE_INT32:
|
||||
return val_.int32_value_ < other.val_.int32_value_;
|
||||
case FieldDescriptor::CPPTYPE_UINT64:
|
||||
return val_.uint64_value_ < other.val_.uint64_value_;
|
||||
case FieldDescriptor::CPPTYPE_UINT32:
|
||||
return val_.uint32_value_ < other.val_.uint32_value_;
|
||||
case FieldDescriptor::CPPTYPE_BOOL:
|
||||
return val_.bool_value_ < other.val_.bool_value_;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool operator==(const MapKey& other) const {
|
||||
if (type_ != other.type_) {
|
||||
// To be consistent with operator<, we don't allow this either.
|
||||
GOOGLE_LOG(FATAL) << "Unsupported: type mismatch";
|
||||
}
|
||||
switch (type()) {
|
||||
case FieldDescriptor::CPPTYPE_DOUBLE:
|
||||
case FieldDescriptor::CPPTYPE_FLOAT:
|
||||
case FieldDescriptor::CPPTYPE_ENUM:
|
||||
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||
GOOGLE_LOG(FATAL) << "Unsupported";
|
||||
break;
|
||||
case FieldDescriptor::CPPTYPE_STRING:
|
||||
return val_.string_value_.get() == other.val_.string_value_.get();
|
||||
case FieldDescriptor::CPPTYPE_INT64:
|
||||
return val_.int64_value_ == other.val_.int64_value_;
|
||||
case FieldDescriptor::CPPTYPE_INT32:
|
||||
return val_.int32_value_ == other.val_.int32_value_;
|
||||
case FieldDescriptor::CPPTYPE_UINT64:
|
||||
return val_.uint64_value_ == other.val_.uint64_value_;
|
||||
case FieldDescriptor::CPPTYPE_UINT32:
|
||||
return val_.uint32_value_ == other.val_.uint32_value_;
|
||||
case FieldDescriptor::CPPTYPE_BOOL:
|
||||
return val_.bool_value_ == other.val_.bool_value_;
|
||||
}
|
||||
GOOGLE_LOG(FATAL) << "Can't get here.";
|
||||
return false;
|
||||
}
|
||||
|
||||
void CopyFrom(const MapKey& other) {
|
||||
SetType(other.type());
|
||||
switch (type_) {
|
||||
case FieldDescriptor::CPPTYPE_DOUBLE:
|
||||
case FieldDescriptor::CPPTYPE_FLOAT:
|
||||
case FieldDescriptor::CPPTYPE_ENUM:
|
||||
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||
GOOGLE_LOG(FATAL) << "Unsupported";
|
||||
break;
|
||||
case FieldDescriptor::CPPTYPE_STRING:
|
||||
*val_.string_value_.get_mutable() = other.val_.string_value_.get();
|
||||
break;
|
||||
case FieldDescriptor::CPPTYPE_INT64:
|
||||
val_.int64_value_ = other.val_.int64_value_;
|
||||
break;
|
||||
case FieldDescriptor::CPPTYPE_INT32:
|
||||
val_.int32_value_ = other.val_.int32_value_;
|
||||
break;
|
||||
case FieldDescriptor::CPPTYPE_UINT64:
|
||||
val_.uint64_value_ = other.val_.uint64_value_;
|
||||
break;
|
||||
case FieldDescriptor::CPPTYPE_UINT32:
|
||||
val_.uint32_value_ = other.val_.uint32_value_;
|
||||
break;
|
||||
case FieldDescriptor::CPPTYPE_BOOL:
|
||||
val_.bool_value_ = other.val_.bool_value_;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename K, typename V>
|
||||
friend class internal::TypeDefinedMapFieldBase;
|
||||
friend class ::PROTOBUF_NAMESPACE_ID::MapIterator;
|
||||
friend class internal::DynamicMapField;
|
||||
|
||||
union KeyValue {
|
||||
KeyValue() {}
|
||||
internal::ExplicitlyConstructed<std::string> string_value_;
|
||||
int64_t int64_value_;
|
||||
int32_t int32_value_;
|
||||
uint64_t uint64_value_;
|
||||
uint32_t uint32_value_;
|
||||
bool bool_value_;
|
||||
} val_;
|
||||
|
||||
void SetType(FieldDescriptor::CppType type) {
|
||||
if (type_ == type) return;
|
||||
if (type_ == FieldDescriptor::CPPTYPE_STRING) {
|
||||
val_.string_value_.Destruct();
|
||||
}
|
||||
type_ = type;
|
||||
if (type_ == FieldDescriptor::CPPTYPE_STRING) {
|
||||
val_.string_value_.DefaultConstruct();
|
||||
}
|
||||
}
|
||||
|
||||
// type_ is 0 or a valid FieldDescriptor::CppType.
|
||||
// Use "CppType()" to indicate zero.
|
||||
FieldDescriptor::CppType type_;
|
||||
};
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
namespace std {
|
||||
template <>
|
||||
struct hash<::PROTOBUF_NAMESPACE_ID::MapKey> {
|
||||
size_t operator()(const ::PROTOBUF_NAMESPACE_ID::MapKey& map_key) const {
|
||||
switch (map_key.type()) {
|
||||
case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_DOUBLE:
|
||||
case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_FLOAT:
|
||||
case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_ENUM:
|
||||
case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_MESSAGE:
|
||||
GOOGLE_LOG(FATAL) << "Unsupported";
|
||||
break;
|
||||
case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_STRING:
|
||||
return hash<std::string>()(map_key.GetStringValue());
|
||||
case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_INT64: {
|
||||
auto value = map_key.GetInt64Value();
|
||||
return hash<decltype(value)>()(value);
|
||||
}
|
||||
case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_INT32: {
|
||||
auto value = map_key.GetInt32Value();
|
||||
return hash<decltype(value)>()(map_key.GetInt32Value());
|
||||
}
|
||||
case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_UINT64: {
|
||||
auto value = map_key.GetUInt64Value();
|
||||
return hash<decltype(value)>()(map_key.GetUInt64Value());
|
||||
}
|
||||
case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_UINT32: {
|
||||
auto value = map_key.GetUInt32Value();
|
||||
return hash<decltype(value)>()(map_key.GetUInt32Value());
|
||||
}
|
||||
case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_BOOL: {
|
||||
return hash<bool>()(map_key.GetBoolValue());
|
||||
}
|
||||
}
|
||||
GOOGLE_LOG(FATAL) << "Can't get here.";
|
||||
return 0;
|
||||
}
|
||||
bool operator()(const ::PROTOBUF_NAMESPACE_ID::MapKey& map_key1,
|
||||
const ::PROTOBUF_NAMESPACE_ID::MapKey& map_key2) const {
|
||||
return map_key1 < map_key2;
|
||||
}
|
||||
};
|
||||
} // namespace std
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
class ContendedMapCleanTest;
|
||||
class GeneratedMessageReflection;
|
||||
class MapFieldAccessor;
|
||||
|
||||
// This class provides access to map field using reflection, which is the same
|
||||
// as those provided for RepeatedPtrField<Message>. It is used for internal
|
||||
// reflection implementation only. Users should never use this directly.
|
||||
class PROTOBUF_EXPORT MapFieldBase {
|
||||
public:
|
||||
MapFieldBase()
|
||||
: arena_(nullptr), repeated_field_(nullptr), state_(STATE_MODIFIED_MAP) {}
|
||||
|
||||
// This constructor is for constant initialized global instances.
|
||||
// It uses a linker initialized mutex, so it is not compatible with regular
|
||||
// runtime instances.
|
||||
// Except in MSVC, where we can't have a constinit mutex.
|
||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||
constexpr MapFieldBase(ConstantInitialized)
|
||||
: arena_(nullptr),
|
||||
repeated_field_(nullptr),
|
||||
mutex_(GOOGLE_PROTOBUF_LINKER_INITIALIZED),
|
||||
state_(STATE_MODIFIED_MAP) {}
|
||||
explicit MapFieldBase(Arena* arena)
|
||||
: arena_(arena), repeated_field_(nullptr), state_(STATE_MODIFIED_MAP) {}
|
||||
|
||||
protected:
|
||||
~MapFieldBase() { // "protected" stops users from deleting a `MapFieldBase *`
|
||||
GOOGLE_DCHECK(repeated_field_ == nullptr);
|
||||
}
|
||||
void Destruct();
|
||||
|
||||
public:
|
||||
// Returns reference to internal repeated field. Data written using
|
||||
// Map's api prior to calling this function is guarantted to be
|
||||
// included in repeated field.
|
||||
const RepeatedPtrFieldBase& GetRepeatedField() const;
|
||||
|
||||
// Like above. Returns mutable pointer to the internal repeated field.
|
||||
RepeatedPtrFieldBase* MutableRepeatedField();
|
||||
|
||||
// Pure virtual map APIs for Map Reflection.
|
||||
virtual bool ContainsMapKey(const MapKey& map_key) const = 0;
|
||||
virtual bool InsertOrLookupMapValue(const MapKey& map_key,
|
||||
MapValueRef* val) = 0;
|
||||
virtual bool LookupMapValue(const MapKey& map_key,
|
||||
MapValueConstRef* val) const = 0;
|
||||
bool LookupMapValue(const MapKey&, MapValueRef*) const = delete;
|
||||
|
||||
// Returns whether changes to the map are reflected in the repeated field.
|
||||
bool IsRepeatedFieldValid() const;
|
||||
// Insures operations after won't get executed before calling this.
|
||||
bool IsMapValid() const;
|
||||
virtual bool DeleteMapValue(const MapKey& map_key) = 0;
|
||||
virtual bool EqualIterator(const MapIterator& a,
|
||||
const MapIterator& b) const = 0;
|
||||
virtual void MapBegin(MapIterator* map_iter) const = 0;
|
||||
virtual void MapEnd(MapIterator* map_iter) const = 0;
|
||||
virtual void MergeFrom(const MapFieldBase& other) = 0;
|
||||
virtual void Swap(MapFieldBase* other);
|
||||
virtual void UnsafeShallowSwap(MapFieldBase* other);
|
||||
// Sync Map with repeated field and returns the size of map.
|
||||
virtual int size() const = 0;
|
||||
virtual void Clear() = 0;
|
||||
|
||||
// Returns the number of bytes used by the repeated field, excluding
|
||||
// sizeof(*this)
|
||||
size_t SpaceUsedExcludingSelfLong() const;
|
||||
|
||||
int SpaceUsedExcludingSelf() const {
|
||||
return internal::ToIntSize(SpaceUsedExcludingSelfLong());
|
||||
}
|
||||
|
||||
protected:
|
||||
// Gets the size of space used by map field.
|
||||
virtual size_t SpaceUsedExcludingSelfNoLock() const;
|
||||
|
||||
// Synchronizes the content in Map to RepeatedPtrField if there is any change
|
||||
// to Map after last synchronization.
|
||||
void SyncRepeatedFieldWithMap() const;
|
||||
virtual void SyncRepeatedFieldWithMapNoLock() const;
|
||||
|
||||
// Synchronizes the content in RepeatedPtrField to Map if there is any change
|
||||
// to RepeatedPtrField after last synchronization.
|
||||
void SyncMapWithRepeatedField() const;
|
||||
virtual void SyncMapWithRepeatedFieldNoLock() const {}
|
||||
|
||||
// Tells MapFieldBase that there is new change to Map.
|
||||
void SetMapDirty();
|
||||
|
||||
// Tells MapFieldBase that there is new change to RepeatedPtrField.
|
||||
void SetRepeatedDirty();
|
||||
|
||||
// Provides derived class the access to repeated field.
|
||||
void* MutableRepeatedPtrField() const;
|
||||
|
||||
void InternalSwap(MapFieldBase* other);
|
||||
|
||||
// Support thread sanitizer (tsan) by making const / mutable races
|
||||
// more apparent. If one thread calls MutableAccess() while another
|
||||
// thread calls either ConstAccess() or MutableAccess(), on the same
|
||||
// MapFieldBase-derived object, and there is no synchronization going
|
||||
// on between them, tsan will alert.
|
||||
#if defined(__SANITIZE_THREAD__) || defined(THREAD_SANITIZER)
|
||||
void ConstAccess() const { GOOGLE_CHECK_EQ(seq1_, seq2_); }
|
||||
void MutableAccess() {
|
||||
if (seq1_ & 1) {
|
||||
seq2_ = ++seq1_;
|
||||
} else {
|
||||
seq1_ = ++seq2_;
|
||||
}
|
||||
}
|
||||
unsigned int seq1_ = 0, seq2_ = 0;
|
||||
#else
|
||||
void ConstAccess() const {}
|
||||
void MutableAccess() {}
|
||||
#endif
|
||||
enum State {
|
||||
STATE_MODIFIED_MAP = 0, // map has newly added data that has not been
|
||||
// synchronized to repeated field
|
||||
STATE_MODIFIED_REPEATED = 1, // repeated field has newly added data that
|
||||
// has not been synchronized to map
|
||||
CLEAN = 2, // data in map and repeated field are same
|
||||
};
|
||||
|
||||
Arena* arena_;
|
||||
mutable RepeatedPtrField<Message>* repeated_field_;
|
||||
|
||||
mutable internal::WrappedMutex
|
||||
mutex_; // The thread to synchronize map and repeated field
|
||||
// needs to get lock first;
|
||||
mutable std::atomic<State> state_;
|
||||
|
||||
private:
|
||||
friend class ContendedMapCleanTest;
|
||||
friend class GeneratedMessageReflection;
|
||||
friend class MapFieldAccessor;
|
||||
friend class ::PROTOBUF_NAMESPACE_ID::Reflection;
|
||||
friend class ::PROTOBUF_NAMESPACE_ID::DynamicMessage;
|
||||
|
||||
// Virtual helper methods for MapIterator. MapIterator doesn't have the
|
||||
// type helper for key and value. Call these help methods to deal with
|
||||
// different types. Real helper methods are implemented in
|
||||
// TypeDefinedMapFieldBase.
|
||||
friend class ::PROTOBUF_NAMESPACE_ID::MapIterator;
|
||||
// Allocate map<...>::iterator for MapIterator.
|
||||
virtual void InitializeIterator(MapIterator* map_iter) const = 0;
|
||||
|
||||
// DeleteIterator() is called by the destructor of MapIterator only.
|
||||
// It deletes map<...>::iterator for MapIterator.
|
||||
virtual void DeleteIterator(MapIterator* map_iter) const = 0;
|
||||
|
||||
// Copy the map<...>::iterator from other_iterator to
|
||||
// this_iterator.
|
||||
virtual void CopyIterator(MapIterator* this_iterator,
|
||||
const MapIterator& other_iterator) const = 0;
|
||||
|
||||
// IncreaseIterator() is called by operator++() of MapIterator only.
|
||||
// It implements the ++ operator of MapIterator.
|
||||
virtual void IncreaseIterator(MapIterator* map_iter) const = 0;
|
||||
|
||||
// Swaps state_ with another MapFieldBase
|
||||
void SwapState(MapFieldBase* other);
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapFieldBase);
|
||||
};
|
||||
|
||||
// This class provides common Map Reflection implementations for generated
|
||||
// message and dynamic message.
|
||||
template <typename Key, typename T>
|
||||
class TypeDefinedMapFieldBase : public MapFieldBase {
|
||||
public:
|
||||
TypeDefinedMapFieldBase() {}
|
||||
|
||||
// This constructor is for constant initialized global instances.
|
||||
// It uses a linker initialized mutex, so it is not compatible with regular
|
||||
// runtime instances.
|
||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||
constexpr TypeDefinedMapFieldBase(ConstantInitialized tag)
|
||||
: MapFieldBase(tag) {}
|
||||
explicit TypeDefinedMapFieldBase(Arena* arena) : MapFieldBase(arena) {}
|
||||
TypeDefinedMapFieldBase(ArenaInitialized, Arena* arena)
|
||||
: TypeDefinedMapFieldBase(arena) {}
|
||||
|
||||
protected:
|
||||
~TypeDefinedMapFieldBase() {}
|
||||
using MapFieldBase::Destruct;
|
||||
|
||||
public:
|
||||
void MapBegin(MapIterator* map_iter) const override;
|
||||
void MapEnd(MapIterator* map_iter) const override;
|
||||
bool EqualIterator(const MapIterator& a, const MapIterator& b) const override;
|
||||
|
||||
virtual const Map<Key, T>& GetMap() const = 0;
|
||||
virtual Map<Key, T>* MutableMap() = 0;
|
||||
|
||||
protected:
|
||||
typename Map<Key, T>::const_iterator& InternalGetIterator(
|
||||
const MapIterator* map_iter) const;
|
||||
|
||||
private:
|
||||
void InitializeIterator(MapIterator* map_iter) const override;
|
||||
void DeleteIterator(MapIterator* map_iter) const override;
|
||||
void CopyIterator(MapIterator* this_iteratorm,
|
||||
const MapIterator& that_iterator) const override;
|
||||
void IncreaseIterator(MapIterator* map_iter) const override;
|
||||
|
||||
virtual void SetMapIteratorValue(MapIterator* map_iter) const = 0;
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TypeDefinedMapFieldBase);
|
||||
};
|
||||
|
||||
// This class provides access to map field using generated api. It is used for
|
||||
// internal generated message implementation only. Users should never use this
|
||||
// directly.
|
||||
template <typename Derived, typename Key, typename T,
|
||||
WireFormatLite::FieldType kKeyFieldType,
|
||||
WireFormatLite::FieldType kValueFieldType>
|
||||
class MapField : public TypeDefinedMapFieldBase<Key, T> {
|
||||
// Provide utilities to parse/serialize key/value. Provide utilities to
|
||||
// manipulate internal stored type.
|
||||
typedef MapTypeHandler<kKeyFieldType, Key> KeyTypeHandler;
|
||||
typedef MapTypeHandler<kValueFieldType, T> ValueTypeHandler;
|
||||
|
||||
// Define message type for internal repeated field.
|
||||
typedef Derived EntryType;
|
||||
|
||||
// Define abbreviation for parent MapFieldLite
|
||||
typedef MapFieldLite<Derived, Key, T, kKeyFieldType, kValueFieldType>
|
||||
MapFieldLiteType;
|
||||
|
||||
// Enum needs to be handled differently from other types because it has
|
||||
// different exposed type in Map's api and repeated field's api. For
|
||||
// details see the comment in the implementation of
|
||||
// SyncMapWithRepeatedFieldNoLock.
|
||||
static constexpr bool kIsValueEnum = ValueTypeHandler::kIsEnum;
|
||||
typedef typename MapIf<kIsValueEnum, T, const T&>::type CastValueType;
|
||||
|
||||
public:
|
||||
typedef Map<Key, T> MapType;
|
||||
|
||||
MapField() : impl_() {}
|
||||
virtual ~MapField() {} // Destruct() must already have been called!
|
||||
void Destruct() {
|
||||
impl_.Destruct();
|
||||
TypeDefinedMapFieldBase<Key, T>::Destruct();
|
||||
}
|
||||
|
||||
// This constructor is for constant initialized global instances.
|
||||
// It uses a linker initialized mutex, so it is not compatible with regular
|
||||
// runtime instances.
|
||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||
constexpr MapField(ConstantInitialized tag)
|
||||
: TypeDefinedMapFieldBase<Key, T>(tag), impl_() {}
|
||||
explicit MapField(Arena* arena)
|
||||
: TypeDefinedMapFieldBase<Key, T>(arena), impl_(arena) {}
|
||||
MapField(ArenaInitialized, Arena* arena) : MapField(arena) {}
|
||||
|
||||
// Implement MapFieldBase
|
||||
bool ContainsMapKey(const MapKey& map_key) const override;
|
||||
bool InsertOrLookupMapValue(const MapKey& map_key, MapValueRef* val) override;
|
||||
bool LookupMapValue(const MapKey& map_key,
|
||||
MapValueConstRef* val) const override;
|
||||
bool LookupMapValue(const MapKey&, MapValueRef*) const = delete;
|
||||
bool DeleteMapValue(const MapKey& map_key) override;
|
||||
|
||||
const Map<Key, T>& GetMap() const override {
|
||||
MapFieldBase::SyncMapWithRepeatedField();
|
||||
return impl_.GetMap();
|
||||
}
|
||||
|
||||
Map<Key, T>* MutableMap() override {
|
||||
MapFieldBase::SyncMapWithRepeatedField();
|
||||
Map<Key, T>* result = impl_.MutableMap();
|
||||
MapFieldBase::SetMapDirty();
|
||||
return result;
|
||||
}
|
||||
|
||||
int size() const override;
|
||||
void Clear() override;
|
||||
void MergeFrom(const MapFieldBase& other) override;
|
||||
void Swap(MapFieldBase* other) override;
|
||||
void UnsafeShallowSwap(MapFieldBase* other) override;
|
||||
void InternalSwap(MapField* other);
|
||||
|
||||
// Used in the implementation of parsing. Caller should take the ownership iff
|
||||
// arena_ is nullptr.
|
||||
EntryType* NewEntry() const { return impl_.NewEntry(); }
|
||||
|
||||
const char* _InternalParse(const char* ptr, ParseContext* ctx) {
|
||||
return impl_._InternalParse(ptr, ctx);
|
||||
}
|
||||
template <typename UnknownType>
|
||||
const char* ParseWithEnumValidation(const char* ptr, ParseContext* ctx,
|
||||
bool (*is_valid)(int), uint32_t field_num,
|
||||
InternalMetadata* metadata) {
|
||||
return impl_.template ParseWithEnumValidation<UnknownType>(
|
||||
ptr, ctx, is_valid, field_num, metadata);
|
||||
}
|
||||
|
||||
private:
|
||||
MapFieldLiteType impl_;
|
||||
|
||||
typedef void InternalArenaConstructable_;
|
||||
typedef void DestructorSkippable_;
|
||||
|
||||
// Implements MapFieldBase
|
||||
void SyncRepeatedFieldWithMapNoLock() const override;
|
||||
void SyncMapWithRepeatedFieldNoLock() const override;
|
||||
size_t SpaceUsedExcludingSelfNoLock() const override;
|
||||
|
||||
void SetMapIteratorValue(MapIterator* map_iter) const override;
|
||||
|
||||
friend class ::PROTOBUF_NAMESPACE_ID::Arena;
|
||||
friend class MapFieldStateTest; // For testing, it needs raw access to impl_
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapField);
|
||||
};
|
||||
|
||||
template <typename Derived, typename Key, typename T,
|
||||
WireFormatLite::FieldType key_wire_type,
|
||||
WireFormatLite::FieldType value_wire_type>
|
||||
bool AllAreInitialized(
|
||||
const MapField<Derived, Key, T, key_wire_type, value_wire_type>& field) {
|
||||
const auto& t = field.GetMap();
|
||||
for (typename Map<Key, T>::const_iterator it = t.begin(); it != t.end();
|
||||
++it) {
|
||||
if (!it->second.IsInitialized()) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T, typename Key, typename Value,
|
||||
WireFormatLite::FieldType kKeyFieldType,
|
||||
WireFormatLite::FieldType kValueFieldType>
|
||||
struct MapEntryToMapField<
|
||||
MapEntry<T, Key, Value, kKeyFieldType, kValueFieldType>> {
|
||||
typedef MapField<T, Key, Value, kKeyFieldType, kValueFieldType> MapFieldType;
|
||||
};
|
||||
|
||||
class PROTOBUF_EXPORT DynamicMapField
|
||||
: public TypeDefinedMapFieldBase<MapKey, MapValueRef> {
|
||||
public:
|
||||
explicit DynamicMapField(const Message* default_entry);
|
||||
DynamicMapField(const Message* default_entry, Arena* arena);
|
||||
virtual ~DynamicMapField();
|
||||
|
||||
// Implement MapFieldBase
|
||||
bool ContainsMapKey(const MapKey& map_key) const override;
|
||||
bool InsertOrLookupMapValue(const MapKey& map_key, MapValueRef* val) override;
|
||||
bool LookupMapValue(const MapKey& map_key,
|
||||
MapValueConstRef* val) const override;
|
||||
bool LookupMapValue(const MapKey&, MapValueRef*) const = delete;
|
||||
bool DeleteMapValue(const MapKey& map_key) override;
|
||||
void MergeFrom(const MapFieldBase& other) override;
|
||||
void Swap(MapFieldBase* other) override;
|
||||
void UnsafeShallowSwap(MapFieldBase* other) override { Swap(other); }
|
||||
|
||||
const Map<MapKey, MapValueRef>& GetMap() const override;
|
||||
Map<MapKey, MapValueRef>* MutableMap() override;
|
||||
|
||||
int size() const override;
|
||||
void Clear() override;
|
||||
|
||||
private:
|
||||
Map<MapKey, MapValueRef> map_;
|
||||
const Message* default_entry_;
|
||||
|
||||
void AllocateMapValue(MapValueRef* map_val);
|
||||
|
||||
// Implements MapFieldBase
|
||||
void SyncRepeatedFieldWithMapNoLock() const override;
|
||||
void SyncMapWithRepeatedFieldNoLock() const override;
|
||||
size_t SpaceUsedExcludingSelfNoLock() const override;
|
||||
void SetMapIteratorValue(MapIterator* map_iter) const override;
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMapField);
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// MapValueConstRef points to a map value. Users can NOT modify
|
||||
// the map value.
|
||||
class PROTOBUF_EXPORT MapValueConstRef {
|
||||
public:
|
||||
MapValueConstRef() : data_(nullptr), type_() {}
|
||||
|
||||
int64_t GetInt64Value() const {
|
||||
TYPE_CHECK(FieldDescriptor::CPPTYPE_INT64,
|
||||
"MapValueConstRef::GetInt64Value");
|
||||
return *reinterpret_cast<int64_t*>(data_);
|
||||
}
|
||||
uint64_t GetUInt64Value() const {
|
||||
TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT64,
|
||||
"MapValueConstRef::GetUInt64Value");
|
||||
return *reinterpret_cast<uint64_t*>(data_);
|
||||
}
|
||||
int32_t GetInt32Value() const {
|
||||
TYPE_CHECK(FieldDescriptor::CPPTYPE_INT32,
|
||||
"MapValueConstRef::GetInt32Value");
|
||||
return *reinterpret_cast<int32_t*>(data_);
|
||||
}
|
||||
uint32_t GetUInt32Value() const {
|
||||
TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT32,
|
||||
"MapValueConstRef::GetUInt32Value");
|
||||
return *reinterpret_cast<uint32_t*>(data_);
|
||||
}
|
||||
bool GetBoolValue() const {
|
||||
TYPE_CHECK(FieldDescriptor::CPPTYPE_BOOL, "MapValueConstRef::GetBoolValue");
|
||||
return *reinterpret_cast<bool*>(data_);
|
||||
}
|
||||
int GetEnumValue() const {
|
||||
TYPE_CHECK(FieldDescriptor::CPPTYPE_ENUM, "MapValueConstRef::GetEnumValue");
|
||||
return *reinterpret_cast<int*>(data_);
|
||||
}
|
||||
const std::string& GetStringValue() const {
|
||||
TYPE_CHECK(FieldDescriptor::CPPTYPE_STRING,
|
||||
"MapValueConstRef::GetStringValue");
|
||||
return *reinterpret_cast<std::string*>(data_);
|
||||
}
|
||||
float GetFloatValue() const {
|
||||
TYPE_CHECK(FieldDescriptor::CPPTYPE_FLOAT,
|
||||
"MapValueConstRef::GetFloatValue");
|
||||
return *reinterpret_cast<float*>(data_);
|
||||
}
|
||||
double GetDoubleValue() const {
|
||||
TYPE_CHECK(FieldDescriptor::CPPTYPE_DOUBLE,
|
||||
"MapValueConstRef::GetDoubleValue");
|
||||
return *reinterpret_cast<double*>(data_);
|
||||
}
|
||||
|
||||
const Message& GetMessageValue() const {
|
||||
TYPE_CHECK(FieldDescriptor::CPPTYPE_MESSAGE,
|
||||
"MapValueConstRef::GetMessageValue");
|
||||
return *reinterpret_cast<Message*>(data_);
|
||||
}
|
||||
|
||||
protected:
|
||||
// data_ point to a map value. MapValueConstRef does not
|
||||
// own this value.
|
||||
void* data_;
|
||||
// type_ is 0 or a valid FieldDescriptor::CppType.
|
||||
// Use "CppType()" to indicate zero.
|
||||
FieldDescriptor::CppType type_;
|
||||
|
||||
FieldDescriptor::CppType type() const {
|
||||
if (type_ == FieldDescriptor::CppType() || data_ == nullptr) {
|
||||
GOOGLE_LOG(FATAL)
|
||||
<< "Protocol Buffer map usage error:\n"
|
||||
<< "MapValueConstRef::type MapValueConstRef is not initialized.";
|
||||
}
|
||||
return type_;
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename Derived, typename K, typename V,
|
||||
internal::WireFormatLite::FieldType key_wire_type,
|
||||
internal::WireFormatLite::FieldType value_wire_type>
|
||||
friend class internal::MapField;
|
||||
template <typename K, typename V>
|
||||
friend class internal::TypeDefinedMapFieldBase;
|
||||
friend class ::PROTOBUF_NAMESPACE_ID::MapIterator;
|
||||
friend class Reflection;
|
||||
friend class internal::DynamicMapField;
|
||||
|
||||
void SetType(FieldDescriptor::CppType type) { type_ = type; }
|
||||
void SetValue(const void* val) { data_ = const_cast<void*>(val); }
|
||||
void CopyFrom(const MapValueConstRef& other) {
|
||||
type_ = other.type_;
|
||||
data_ = other.data_;
|
||||
}
|
||||
};
|
||||
|
||||
// MapValueRef points to a map value. Users are able to modify
|
||||
// the map value.
|
||||
class PROTOBUF_EXPORT MapValueRef final : public MapValueConstRef {
|
||||
public:
|
||||
MapValueRef() {}
|
||||
|
||||
void SetInt64Value(int64_t value) {
|
||||
TYPE_CHECK(FieldDescriptor::CPPTYPE_INT64, "MapValueRef::SetInt64Value");
|
||||
*reinterpret_cast<int64_t*>(data_) = value;
|
||||
}
|
||||
void SetUInt64Value(uint64_t value) {
|
||||
TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT64, "MapValueRef::SetUInt64Value");
|
||||
*reinterpret_cast<uint64_t*>(data_) = value;
|
||||
}
|
||||
void SetInt32Value(int32_t value) {
|
||||
TYPE_CHECK(FieldDescriptor::CPPTYPE_INT32, "MapValueRef::SetInt32Value");
|
||||
*reinterpret_cast<int32_t*>(data_) = value;
|
||||
}
|
||||
void SetUInt32Value(uint32_t value) {
|
||||
TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT32, "MapValueRef::SetUInt32Value");
|
||||
*reinterpret_cast<uint32_t*>(data_) = value;
|
||||
}
|
||||
void SetBoolValue(bool value) {
|
||||
TYPE_CHECK(FieldDescriptor::CPPTYPE_BOOL, "MapValueRef::SetBoolValue");
|
||||
*reinterpret_cast<bool*>(data_) = value;
|
||||
}
|
||||
// TODO(jieluo) - Checks that enum is member.
|
||||
void SetEnumValue(int value) {
|
||||
TYPE_CHECK(FieldDescriptor::CPPTYPE_ENUM, "MapValueRef::SetEnumValue");
|
||||
*reinterpret_cast<int*>(data_) = value;
|
||||
}
|
||||
void SetStringValue(const std::string& value) {
|
||||
TYPE_CHECK(FieldDescriptor::CPPTYPE_STRING, "MapValueRef::SetStringValue");
|
||||
*reinterpret_cast<std::string*>(data_) = value;
|
||||
}
|
||||
void SetFloatValue(float value) {
|
||||
TYPE_CHECK(FieldDescriptor::CPPTYPE_FLOAT, "MapValueRef::SetFloatValue");
|
||||
*reinterpret_cast<float*>(data_) = value;
|
||||
}
|
||||
void SetDoubleValue(double value) {
|
||||
TYPE_CHECK(FieldDescriptor::CPPTYPE_DOUBLE, "MapValueRef::SetDoubleValue");
|
||||
*reinterpret_cast<double*>(data_) = value;
|
||||
}
|
||||
|
||||
Message* MutableMessageValue() {
|
||||
TYPE_CHECK(FieldDescriptor::CPPTYPE_MESSAGE,
|
||||
"MapValueRef::MutableMessageValue");
|
||||
return reinterpret_cast<Message*>(data_);
|
||||
}
|
||||
|
||||
private:
|
||||
friend class internal::DynamicMapField;
|
||||
|
||||
// Only used in DynamicMapField
|
||||
void DeleteData() {
|
||||
switch (type_) {
|
||||
#define HANDLE_TYPE(CPPTYPE, TYPE) \
|
||||
case FieldDescriptor::CPPTYPE_##CPPTYPE: { \
|
||||
delete reinterpret_cast<TYPE*>(data_); \
|
||||
break; \
|
||||
}
|
||||
HANDLE_TYPE(INT32, int32_t);
|
||||
HANDLE_TYPE(INT64, int64_t);
|
||||
HANDLE_TYPE(UINT32, uint32_t);
|
||||
HANDLE_TYPE(UINT64, uint64_t);
|
||||
HANDLE_TYPE(DOUBLE, double);
|
||||
HANDLE_TYPE(FLOAT, float);
|
||||
HANDLE_TYPE(BOOL, bool);
|
||||
HANDLE_TYPE(STRING, std::string);
|
||||
HANDLE_TYPE(ENUM, int32_t);
|
||||
HANDLE_TYPE(MESSAGE, Message);
|
||||
#undef HANDLE_TYPE
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#undef TYPE_CHECK
|
||||
|
||||
class PROTOBUF_EXPORT MapIterator {
|
||||
public:
|
||||
MapIterator(Message* message, const FieldDescriptor* field) {
|
||||
const Reflection* reflection = message->GetReflection();
|
||||
map_ = reflection->MutableMapData(message, field);
|
||||
key_.SetType(field->message_type()->map_key()->cpp_type());
|
||||
value_.SetType(field->message_type()->map_value()->cpp_type());
|
||||
map_->InitializeIterator(this);
|
||||
}
|
||||
MapIterator(const MapIterator& other) {
|
||||
map_ = other.map_;
|
||||
map_->InitializeIterator(this);
|
||||
map_->CopyIterator(this, other);
|
||||
}
|
||||
~MapIterator() { map_->DeleteIterator(this); }
|
||||
MapIterator& operator=(const MapIterator& other) {
|
||||
map_ = other.map_;
|
||||
map_->CopyIterator(this, other);
|
||||
return *this;
|
||||
}
|
||||
friend bool operator==(const MapIterator& a, const MapIterator& b) {
|
||||
return a.map_->EqualIterator(a, b);
|
||||
}
|
||||
friend bool operator!=(const MapIterator& a, const MapIterator& b) {
|
||||
return !a.map_->EqualIterator(a, b);
|
||||
}
|
||||
MapIterator& operator++() {
|
||||
map_->IncreaseIterator(this);
|
||||
return *this;
|
||||
}
|
||||
MapIterator operator++(int) {
|
||||
// iter_ is copied from Map<...>::iterator, no need to
|
||||
// copy from its self again. Use the same implementation
|
||||
// with operator++()
|
||||
map_->IncreaseIterator(this);
|
||||
return *this;
|
||||
}
|
||||
const MapKey& GetKey() { return key_; }
|
||||
const MapValueRef& GetValueRef() { return value_; }
|
||||
MapValueRef* MutableValueRef() {
|
||||
map_->SetMapDirty();
|
||||
return &value_;
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename Key, typename T>
|
||||
friend class internal::TypeDefinedMapFieldBase;
|
||||
friend class internal::DynamicMapField;
|
||||
template <typename Derived, typename Key, typename T,
|
||||
internal::WireFormatLite::FieldType kKeyFieldType,
|
||||
internal::WireFormatLite::FieldType kValueFieldType>
|
||||
friend class internal::MapField;
|
||||
|
||||
// reinterpret_cast from heap-allocated Map<...>::iterator*. MapIterator owns
|
||||
// the iterator. It is allocated by MapField<...>::InitializeIterator() called
|
||||
// in constructor and deleted by MapField<...>::DeleteIterator() called in
|
||||
// destructor.
|
||||
void* iter_;
|
||||
// Point to a MapField to call helper methods implemented in MapField.
|
||||
// MapIterator does not own this object.
|
||||
internal::MapFieldBase* map_;
|
||||
MapKey key_;
|
||||
MapValueRef value_;
|
||||
};
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop) // restore warning C4265
|
||||
#endif // _MSC_VER
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_MAP_FIELD_H__
|
||||
@@ -1,375 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_MAP_FIELD_INL_H__
|
||||
#define GOOGLE_PROTOBUF_MAP_FIELD_INL_H__
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <google/protobuf/stubs/casts.h>
|
||||
#include <google/protobuf/map.h>
|
||||
#include <google/protobuf/map_field.h>
|
||||
#include <google/protobuf/map_type_handler.h>
|
||||
|
||||
#ifdef SWIG
|
||||
#error "You cannot SWIG proto headers"
|
||||
#endif
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
// UnwrapMapKey template
|
||||
template <typename T>
|
||||
T UnwrapMapKey(const MapKey& map_key);
|
||||
template <>
|
||||
inline int32_t UnwrapMapKey<int32_t>(const MapKey& map_key) {
|
||||
return map_key.GetInt32Value();
|
||||
}
|
||||
template <>
|
||||
inline uint32_t UnwrapMapKey<uint32_t>(const MapKey& map_key) {
|
||||
return map_key.GetUInt32Value();
|
||||
}
|
||||
template <>
|
||||
inline int64_t UnwrapMapKey<int64_t>(const MapKey& map_key) {
|
||||
return map_key.GetInt64Value();
|
||||
}
|
||||
template <>
|
||||
inline uint64_t UnwrapMapKey<uint64_t>(const MapKey& map_key) {
|
||||
return map_key.GetUInt64Value();
|
||||
}
|
||||
template <>
|
||||
inline bool UnwrapMapKey<bool>(const MapKey& map_key) {
|
||||
return map_key.GetBoolValue();
|
||||
}
|
||||
template <>
|
||||
inline std::string UnwrapMapKey<std::string>(const MapKey& map_key) {
|
||||
return map_key.GetStringValue();
|
||||
}
|
||||
|
||||
// SetMapKey template
|
||||
template <typename T>
|
||||
inline void SetMapKey(MapKey* map_key, const T& value);
|
||||
template <>
|
||||
inline void SetMapKey<int32_t>(MapKey* map_key, const int32_t& value) {
|
||||
map_key->SetInt32Value(value);
|
||||
}
|
||||
template <>
|
||||
inline void SetMapKey<uint32_t>(MapKey* map_key, const uint32_t& value) {
|
||||
map_key->SetUInt32Value(value);
|
||||
}
|
||||
template <>
|
||||
inline void SetMapKey<int64_t>(MapKey* map_key, const int64_t& value) {
|
||||
map_key->SetInt64Value(value);
|
||||
}
|
||||
template <>
|
||||
inline void SetMapKey<uint64_t>(MapKey* map_key, const uint64_t& value) {
|
||||
map_key->SetUInt64Value(value);
|
||||
}
|
||||
template <>
|
||||
inline void SetMapKey<bool>(MapKey* map_key, const bool& value) {
|
||||
map_key->SetBoolValue(value);
|
||||
}
|
||||
template <>
|
||||
inline void SetMapKey<std::string>(MapKey* map_key, const std::string& value) {
|
||||
map_key->SetStringValue(value);
|
||||
}
|
||||
|
||||
// ------------------------TypeDefinedMapFieldBase---------------
|
||||
template <typename Key, typename T>
|
||||
typename Map<Key, T>::const_iterator&
|
||||
TypeDefinedMapFieldBase<Key, T>::InternalGetIterator(
|
||||
const MapIterator* map_iter) const {
|
||||
return *reinterpret_cast<typename Map<Key, T>::const_iterator*>(
|
||||
map_iter->iter_);
|
||||
}
|
||||
|
||||
template <typename Key, typename T>
|
||||
void TypeDefinedMapFieldBase<Key, T>::MapBegin(MapIterator* map_iter) const {
|
||||
InternalGetIterator(map_iter) = GetMap().begin();
|
||||
SetMapIteratorValue(map_iter);
|
||||
}
|
||||
|
||||
template <typename Key, typename T>
|
||||
void TypeDefinedMapFieldBase<Key, T>::MapEnd(MapIterator* map_iter) const {
|
||||
InternalGetIterator(map_iter) = GetMap().end();
|
||||
}
|
||||
|
||||
template <typename Key, typename T>
|
||||
bool TypeDefinedMapFieldBase<Key, T>::EqualIterator(
|
||||
const MapIterator& a, const MapIterator& b) const {
|
||||
return InternalGetIterator(&a) == InternalGetIterator(&b);
|
||||
}
|
||||
|
||||
template <typename Key, typename T>
|
||||
void TypeDefinedMapFieldBase<Key, T>::IncreaseIterator(
|
||||
MapIterator* map_iter) const {
|
||||
++InternalGetIterator(map_iter);
|
||||
SetMapIteratorValue(map_iter);
|
||||
}
|
||||
|
||||
template <typename Key, typename T>
|
||||
void TypeDefinedMapFieldBase<Key, T>::InitializeIterator(
|
||||
MapIterator* map_iter) const {
|
||||
map_iter->iter_ = new typename Map<Key, T>::const_iterator;
|
||||
GOOGLE_CHECK(map_iter->iter_ != nullptr);
|
||||
}
|
||||
|
||||
template <typename Key, typename T>
|
||||
void TypeDefinedMapFieldBase<Key, T>::DeleteIterator(
|
||||
MapIterator* map_iter) const {
|
||||
delete reinterpret_cast<typename Map<Key, T>::const_iterator*>(
|
||||
map_iter->iter_);
|
||||
}
|
||||
|
||||
template <typename Key, typename T>
|
||||
void TypeDefinedMapFieldBase<Key, T>::CopyIterator(
|
||||
MapIterator* this_iter, const MapIterator& that_iter) const {
|
||||
InternalGetIterator(this_iter) = InternalGetIterator(&that_iter);
|
||||
this_iter->key_.SetType(that_iter.key_.type());
|
||||
// MapValueRef::type() fails when containing data is null. However, if
|
||||
// this_iter points to MapEnd, data can be null.
|
||||
this_iter->value_.SetType(
|
||||
static_cast<FieldDescriptor::CppType>(that_iter.value_.type_));
|
||||
SetMapIteratorValue(this_iter);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
template <typename Derived, typename Key, typename T,
|
||||
WireFormatLite::FieldType kKeyFieldType,
|
||||
WireFormatLite::FieldType kValueFieldType>
|
||||
int MapField<Derived, Key, T, kKeyFieldType, kValueFieldType>::size() const {
|
||||
MapFieldBase::SyncMapWithRepeatedField();
|
||||
return static_cast<int>(impl_.GetMap().size());
|
||||
}
|
||||
|
||||
template <typename Derived, typename Key, typename T,
|
||||
WireFormatLite::FieldType kKeyFieldType,
|
||||
WireFormatLite::FieldType kValueFieldType>
|
||||
void MapField<Derived, Key, T, kKeyFieldType, kValueFieldType>::Clear() {
|
||||
if (this->MapFieldBase::repeated_field_ != nullptr) {
|
||||
RepeatedPtrField<EntryType>* repeated_field =
|
||||
reinterpret_cast<RepeatedPtrField<EntryType>*>(
|
||||
this->MapFieldBase::repeated_field_);
|
||||
repeated_field->Clear();
|
||||
}
|
||||
|
||||
impl_.MutableMap()->clear();
|
||||
// Data in map and repeated field are both empty, but we can't set status
|
||||
// CLEAN. Because clear is a generated API, we cannot invalidate previous
|
||||
// reference to map.
|
||||
MapFieldBase::SetMapDirty();
|
||||
}
|
||||
|
||||
template <typename Derived, typename Key, typename T,
|
||||
WireFormatLite::FieldType kKeyFieldType,
|
||||
WireFormatLite::FieldType kValueFieldType>
|
||||
void MapField<Derived, Key, T, kKeyFieldType,
|
||||
kValueFieldType>::SetMapIteratorValue(MapIterator* map_iter)
|
||||
const {
|
||||
const Map<Key, T>& map = impl_.GetMap();
|
||||
typename Map<Key, T>::const_iterator iter =
|
||||
TypeDefinedMapFieldBase<Key, T>::InternalGetIterator(map_iter);
|
||||
if (iter == map.end()) return;
|
||||
SetMapKey(&map_iter->key_, iter->first);
|
||||
map_iter->value_.SetValue(&iter->second);
|
||||
}
|
||||
|
||||
template <typename Derived, typename Key, typename T,
|
||||
WireFormatLite::FieldType kKeyFieldType,
|
||||
WireFormatLite::FieldType kValueFieldType>
|
||||
bool MapField<Derived, Key, T, kKeyFieldType, kValueFieldType>::ContainsMapKey(
|
||||
const MapKey& map_key) const {
|
||||
const Map<Key, T>& map = impl_.GetMap();
|
||||
const Key& key = UnwrapMapKey<Key>(map_key);
|
||||
typename Map<Key, T>::const_iterator iter = map.find(key);
|
||||
return iter != map.end();
|
||||
}
|
||||
|
||||
template <typename Derived, typename Key, typename T,
|
||||
WireFormatLite::FieldType kKeyFieldType,
|
||||
WireFormatLite::FieldType kValueFieldType>
|
||||
bool MapField<Derived, Key, T, kKeyFieldType,
|
||||
kValueFieldType>::InsertOrLookupMapValue(const MapKey& map_key,
|
||||
MapValueRef* val) {
|
||||
// Always use mutable map because users may change the map value by
|
||||
// MapValueRef.
|
||||
Map<Key, T>* map = MutableMap();
|
||||
const Key& key = UnwrapMapKey<Key>(map_key);
|
||||
typename Map<Key, T>::iterator iter = map->find(key);
|
||||
if (map->end() == iter) {
|
||||
val->SetValue(&((*map)[key]));
|
||||
return true;
|
||||
}
|
||||
// Key is already in the map. Make sure (*map)[key] is not called.
|
||||
// [] may reorder the map and iterators.
|
||||
val->SetValue(&(iter->second));
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename Derived, typename Key, typename T,
|
||||
WireFormatLite::FieldType kKeyFieldType,
|
||||
WireFormatLite::FieldType kValueFieldType>
|
||||
bool MapField<Derived, Key, T, kKeyFieldType, kValueFieldType>::LookupMapValue(
|
||||
const MapKey& map_key, MapValueConstRef* val) const {
|
||||
const Map<Key, T>& map = GetMap();
|
||||
const Key& key = UnwrapMapKey<Key>(map_key);
|
||||
typename Map<Key, T>::const_iterator iter = map.find(key);
|
||||
if (map.end() == iter) {
|
||||
return false;
|
||||
}
|
||||
// Key is already in the map. Make sure (*map)[key] is not called.
|
||||
// [] may reorder the map and iterators.
|
||||
val->SetValue(&(iter->second));
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Derived, typename Key, typename T,
|
||||
WireFormatLite::FieldType kKeyFieldType,
|
||||
WireFormatLite::FieldType kValueFieldType>
|
||||
bool MapField<Derived, Key, T, kKeyFieldType, kValueFieldType>::DeleteMapValue(
|
||||
const MapKey& map_key) {
|
||||
const Key& key = UnwrapMapKey<Key>(map_key);
|
||||
return MutableMap()->erase(key);
|
||||
}
|
||||
|
||||
template <typename Derived, typename Key, typename T,
|
||||
WireFormatLite::FieldType kKeyFieldType,
|
||||
WireFormatLite::FieldType kValueFieldType>
|
||||
void MapField<Derived, Key, T, kKeyFieldType, kValueFieldType>::MergeFrom(
|
||||
const MapFieldBase& other) {
|
||||
MapFieldBase::SyncMapWithRepeatedField();
|
||||
const MapField& other_field = static_cast<const MapField&>(other);
|
||||
other_field.SyncMapWithRepeatedField();
|
||||
impl_.MergeFrom(other_field.impl_);
|
||||
MapFieldBase::SetMapDirty();
|
||||
}
|
||||
|
||||
template <typename Derived, typename Key, typename T,
|
||||
WireFormatLite::FieldType kKeyFieldType,
|
||||
WireFormatLite::FieldType kValueFieldType>
|
||||
void MapField<Derived, Key, T, kKeyFieldType, kValueFieldType>::Swap(
|
||||
MapFieldBase* other) {
|
||||
MapFieldBase::Swap(other);
|
||||
MapField* other_field = down_cast<MapField*>(other);
|
||||
impl_.Swap(&other_field->impl_);
|
||||
}
|
||||
|
||||
template <typename Derived, typename Key, typename T,
|
||||
WireFormatLite::FieldType kKeyFieldType,
|
||||
WireFormatLite::FieldType kValueFieldType>
|
||||
void MapField<Derived, Key, T, kKeyFieldType,
|
||||
kValueFieldType>::UnsafeShallowSwap(MapFieldBase* other) {
|
||||
InternalSwap(down_cast<MapField*>(other));
|
||||
}
|
||||
|
||||
template <typename Derived, typename Key, typename T,
|
||||
WireFormatLite::FieldType kKeyFieldType,
|
||||
WireFormatLite::FieldType kValueFieldType>
|
||||
void MapField<Derived, Key, T, kKeyFieldType, kValueFieldType>::InternalSwap(
|
||||
MapField* other) {
|
||||
MapFieldBase::InternalSwap(other);
|
||||
impl_.InternalSwap(&other->impl_);
|
||||
}
|
||||
|
||||
template <typename Derived, typename Key, typename T,
|
||||
WireFormatLite::FieldType kKeyFieldType,
|
||||
WireFormatLite::FieldType kValueFieldType>
|
||||
void MapField<Derived, Key, T, kKeyFieldType,
|
||||
kValueFieldType>::SyncRepeatedFieldWithMapNoLock() const {
|
||||
if (this->MapFieldBase::repeated_field_ == nullptr) {
|
||||
this->MapFieldBase::repeated_field_ =
|
||||
Arena::CreateMessage<RepeatedPtrField<Message> >(
|
||||
this->MapFieldBase::arena_);
|
||||
}
|
||||
const Map<Key, T>& map = impl_.GetMap();
|
||||
RepeatedPtrField<EntryType>* repeated_field =
|
||||
reinterpret_cast<RepeatedPtrField<EntryType>*>(
|
||||
this->MapFieldBase::repeated_field_);
|
||||
|
||||
repeated_field->Clear();
|
||||
|
||||
// The only way we can get at this point is through reflection and the
|
||||
// only way we can get the reflection object is by having called GetReflection
|
||||
// on the encompassing field. So that type must have existed and hence we
|
||||
// know that this MapEntry default_type has also already been constructed.
|
||||
// So it's safe to just call internal_default_instance().
|
||||
const Message* default_entry = Derived::internal_default_instance();
|
||||
for (typename Map<Key, T>::const_iterator it = map.begin(); it != map.end();
|
||||
++it) {
|
||||
EntryType* new_entry =
|
||||
down_cast<EntryType*>(default_entry->New(this->MapFieldBase::arena_));
|
||||
repeated_field->AddAllocated(new_entry);
|
||||
(*new_entry->mutable_key()) = it->first;
|
||||
(*new_entry->mutable_value()) = it->second;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Derived, typename Key, typename T,
|
||||
WireFormatLite::FieldType kKeyFieldType,
|
||||
WireFormatLite::FieldType kValueFieldType>
|
||||
void MapField<Derived, Key, T, kKeyFieldType,
|
||||
kValueFieldType>::SyncMapWithRepeatedFieldNoLock() const {
|
||||
Map<Key, T>* map = const_cast<MapField*>(this)->impl_.MutableMap();
|
||||
RepeatedPtrField<EntryType>* repeated_field =
|
||||
reinterpret_cast<RepeatedPtrField<EntryType>*>(
|
||||
this->MapFieldBase::repeated_field_);
|
||||
GOOGLE_CHECK(this->MapFieldBase::repeated_field_ != nullptr);
|
||||
map->clear();
|
||||
for (typename RepeatedPtrField<EntryType>::iterator it =
|
||||
repeated_field->begin();
|
||||
it != repeated_field->end(); ++it) {
|
||||
// Cast is needed because Map's api and internal storage is different when
|
||||
// value is enum. For enum, we cannot cast an int to enum. Thus, we have to
|
||||
// copy value. For other types, they have same exposed api type and internal
|
||||
// stored type. We should not introduce value copy for them. We achieve this
|
||||
// by casting to value for enum while casting to reference for other types.
|
||||
(*map)[it->key()] = static_cast<CastValueType>(it->value());
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Derived, typename Key, typename T,
|
||||
WireFormatLite::FieldType kKeyFieldType,
|
||||
WireFormatLite::FieldType kValueFieldType>
|
||||
size_t MapField<Derived, Key, T, kKeyFieldType,
|
||||
kValueFieldType>::SpaceUsedExcludingSelfNoLock() const {
|
||||
size_t size = 0;
|
||||
if (this->MapFieldBase::repeated_field_ != nullptr) {
|
||||
size += this->MapFieldBase::repeated_field_->SpaceUsedExcludingSelfLong();
|
||||
}
|
||||
size += impl_.GetMap().SpaceUsedExcludingSelfLong();
|
||||
|
||||
return size;
|
||||
}
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_MAP_FIELD_INL_H__
|
||||
@@ -1,209 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_MAP_FIELD_LITE_H__
|
||||
#define GOOGLE_PROTOBUF_MAP_FIELD_LITE_H__
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/port.h>
|
||||
#include <google/protobuf/map.h>
|
||||
#include <google/protobuf/map_entry_lite.h>
|
||||
#include <google/protobuf/parse_context.h>
|
||||
#include <google/protobuf/wire_format_lite.h>
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
#ifdef SWIG
|
||||
#error "You cannot SWIG proto headers"
|
||||
#endif
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
#ifndef NDEBUG
|
||||
void MapFieldLiteNotDestructed(void* map_field_lite);
|
||||
#endif
|
||||
|
||||
// This class provides access to map field using generated api. It is used for
|
||||
// internal generated message implementation only. Users should never use this
|
||||
// directly.
|
||||
template <typename Derived, typename Key, typename T,
|
||||
WireFormatLite::FieldType key_wire_type,
|
||||
WireFormatLite::FieldType value_wire_type>
|
||||
class MapFieldLite {
|
||||
// Define message type for internal repeated field.
|
||||
typedef Derived EntryType;
|
||||
|
||||
public:
|
||||
typedef Map<Key, T> MapType;
|
||||
|
||||
constexpr MapFieldLite() : map_() {}
|
||||
explicit MapFieldLite(Arena* arena) : map_(arena) {}
|
||||
MapFieldLite(ArenaInitialized, Arena* arena) : MapFieldLite(arena) {}
|
||||
|
||||
#ifdef NDEBUG
|
||||
void Destruct() { map_.~Map(); }
|
||||
~MapFieldLite() {}
|
||||
#else
|
||||
void Destruct() {
|
||||
// We want to destruct the map in such a way that we can verify
|
||||
// that we've done that, but also be sure that we've deallocated
|
||||
// everything (as opposed to leaving an allocation behind with no
|
||||
// data in it, as would happen if a vector was resize'd to zero.
|
||||
// Map::Swap with an empty map accomplishes that.
|
||||
decltype(map_) swapped_map(map_.arena());
|
||||
map_.InternalSwap(swapped_map);
|
||||
}
|
||||
~MapFieldLite() {
|
||||
if (map_.arena() == nullptr && !map_.empty()) {
|
||||
MapFieldLiteNotDestructed(this);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// Accessors
|
||||
const Map<Key, T>& GetMap() const { return map_; }
|
||||
Map<Key, T>* MutableMap() { return &map_; }
|
||||
|
||||
// Convenient methods for generated message implementation.
|
||||
int size() const { return static_cast<int>(map_.size()); }
|
||||
void Clear() { return map_.clear(); }
|
||||
void MergeFrom(const MapFieldLite& other) {
|
||||
for (typename Map<Key, T>::const_iterator it = other.map_.begin();
|
||||
it != other.map_.end(); ++it) {
|
||||
map_[it->first] = it->second;
|
||||
}
|
||||
}
|
||||
void Swap(MapFieldLite* other) { map_.swap(other->map_); }
|
||||
void InternalSwap(MapFieldLite* other) { map_.InternalSwap(other->map_); }
|
||||
|
||||
// Used in the implementation of parsing. Caller should take the ownership iff
|
||||
// arena_ is nullptr.
|
||||
EntryType* NewEntry() const {
|
||||
return Arena::CreateMessage<EntryType>(map_.arena());
|
||||
}
|
||||
|
||||
const char* _InternalParse(const char* ptr, ParseContext* ctx) {
|
||||
typename Derived::template Parser<MapFieldLite, Map<Key, T>> parser(this);
|
||||
return parser._InternalParse(ptr, ctx);
|
||||
}
|
||||
|
||||
template <typename UnknownType>
|
||||
const char* ParseWithEnumValidation(const char* ptr, ParseContext* ctx,
|
||||
bool (*is_valid)(int), uint32_t field_num,
|
||||
InternalMetadata* metadata) {
|
||||
typename Derived::template Parser<MapFieldLite, Map<Key, T>> parser(this);
|
||||
return parser.template ParseWithEnumValidation<UnknownType>(
|
||||
ptr, ctx, is_valid, field_num, metadata);
|
||||
}
|
||||
|
||||
private:
|
||||
typedef void DestructorSkippable_;
|
||||
|
||||
// map_ is inside an anonymous union so we can explicitly control its
|
||||
// destruction
|
||||
union {
|
||||
Map<Key, T> map_;
|
||||
};
|
||||
|
||||
friend class ::PROTOBUF_NAMESPACE_ID::Arena;
|
||||
};
|
||||
|
||||
template <typename UnknownType, typename T>
|
||||
struct EnumParseWrapper {
|
||||
const char* _InternalParse(const char* ptr, ParseContext* ctx) {
|
||||
return map_field->template ParseWithEnumValidation<UnknownType>(
|
||||
ptr, ctx, is_valid, field_num, metadata);
|
||||
}
|
||||
T* map_field;
|
||||
bool (*is_valid)(int);
|
||||
uint32_t field_num;
|
||||
InternalMetadata* metadata;
|
||||
};
|
||||
|
||||
// Helper function because the typenames of maps are horrendous to print. This
|
||||
// leverages compiler type deduction, to keep all type data out of the
|
||||
// generated code
|
||||
template <typename UnknownType, typename T>
|
||||
EnumParseWrapper<UnknownType, T> InitEnumParseWrapper(
|
||||
T* map_field, bool (*is_valid)(int), uint32_t field_num,
|
||||
InternalMetadata* metadata) {
|
||||
return EnumParseWrapper<UnknownType, T>{map_field, is_valid, field_num,
|
||||
metadata};
|
||||
}
|
||||
|
||||
// True if IsInitialized() is true for value field in all elements of t. T is
|
||||
// expected to be message. It's useful to have this helper here to keep the
|
||||
// protobuf compiler from ever having to emit loops in IsInitialized() methods.
|
||||
// We want the C++ compiler to inline this or not as it sees fit.
|
||||
template <typename Derived, typename Key, typename T,
|
||||
WireFormatLite::FieldType key_wire_type,
|
||||
WireFormatLite::FieldType value_wire_type>
|
||||
bool AllAreInitialized(const MapFieldLite<Derived, Key, T, key_wire_type,
|
||||
value_wire_type>& field) {
|
||||
const auto& t = field.GetMap();
|
||||
for (typename Map<Key, T>::const_iterator it = t.begin(); it != t.end();
|
||||
++it) {
|
||||
if (!it->second.IsInitialized()) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename MEntry>
|
||||
struct MapEntryToMapField : MapEntryToMapField<typename MEntry::SuperType> {};
|
||||
|
||||
template <typename T, typename Key, typename Value,
|
||||
WireFormatLite::FieldType kKeyFieldType,
|
||||
WireFormatLite::FieldType kValueFieldType>
|
||||
struct MapEntryToMapField<
|
||||
MapEntryLite<T, Key, Value, kKeyFieldType, kValueFieldType>> {
|
||||
typedef MapFieldLite<
|
||||
MapEntryLite<T, Key, Value, kKeyFieldType, kValueFieldType>, Key, Value,
|
||||
kKeyFieldType, kValueFieldType>
|
||||
MapFieldType;
|
||||
};
|
||||
|
||||
#ifndef NDEBUG
|
||||
inline PROTOBUF_NOINLINE void MapFieldLiteNotDestructed(void* map_field_lite) {
|
||||
bool proper_destruct = false;
|
||||
GOOGLE_CHECK(proper_destruct) << map_field_lite;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_MAP_FIELD_LITE_H__
|
||||
@@ -1,736 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_MAP_TYPE_HANDLER_H__
|
||||
#define GOOGLE_PROTOBUF_MAP_TYPE_HANDLER_H__
|
||||
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/arena.h>
|
||||
#include <google/protobuf/arenastring.h>
|
||||
#include <google/protobuf/parse_context.h>
|
||||
#include <google/protobuf/wire_format_lite.h>
|
||||
|
||||
#ifdef SWIG
|
||||
#error "You cannot SWIG proto headers"
|
||||
#endif
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
// Used for compile time type selection. MapIf::type will be TrueType if Flag is
|
||||
// true and FalseType otherwise.
|
||||
template <bool Flag, typename TrueType, typename FalseType>
|
||||
struct MapIf;
|
||||
|
||||
template <typename TrueType, typename FalseType>
|
||||
struct MapIf<true, TrueType, FalseType> {
|
||||
typedef TrueType type;
|
||||
};
|
||||
|
||||
template <typename TrueType, typename FalseType>
|
||||
struct MapIf<false, TrueType, FalseType> {
|
||||
typedef FalseType type;
|
||||
};
|
||||
|
||||
template <typename Type, bool is_arena_constructable>
|
||||
class MapArenaMessageCreator {
|
||||
public:
|
||||
// Use arena to create message if Type is arena constructable. Otherwise,
|
||||
// create the message on heap.
|
||||
static inline Type* CreateMessage(Arena* arena);
|
||||
};
|
||||
template <typename Type>
|
||||
class MapArenaMessageCreator<Type, true> {
|
||||
public:
|
||||
static inline Type* CreateMessage(Arena* arena) {
|
||||
return Arena::CreateMessage<Type>(arena);
|
||||
}
|
||||
};
|
||||
template <typename Type>
|
||||
class MapArenaMessageCreator<Type, false> {
|
||||
public:
|
||||
static inline Type* CreateMessage(Arena* arena) {
|
||||
return Arena::Create<Type>(arena);
|
||||
}
|
||||
};
|
||||
|
||||
// Define constants for given wire field type
|
||||
template <WireFormatLite::FieldType field_type, typename Type>
|
||||
class MapWireFieldTypeTraits {};
|
||||
|
||||
#define TYPE_TRAITS(FieldType, CType, WireFormatType, IsMessage, IsEnum) \
|
||||
template <typename Type> \
|
||||
class MapWireFieldTypeTraits<WireFormatLite::TYPE_##FieldType, Type> { \
|
||||
public: \
|
||||
static const bool kIsMessage = IsMessage; \
|
||||
static const bool kIsEnum = IsEnum; \
|
||||
typedef typename MapIf<kIsMessage, Type*, CType>::type TypeOnMemory; \
|
||||
typedef typename MapIf<kIsEnum, int, Type>::type MapEntryAccessorType; \
|
||||
static const WireFormatLite::WireType kWireType = \
|
||||
WireFormatLite::WIRETYPE_##WireFormatType; \
|
||||
};
|
||||
|
||||
TYPE_TRAITS(MESSAGE, Type, LENGTH_DELIMITED, true, false)
|
||||
TYPE_TRAITS(STRING, ArenaStringPtr, LENGTH_DELIMITED, false, false)
|
||||
TYPE_TRAITS(BYTES, ArenaStringPtr, LENGTH_DELIMITED, false, false)
|
||||
TYPE_TRAITS(INT64, int64_t, VARINT, false, false)
|
||||
TYPE_TRAITS(UINT64, uint64_t, VARINT, false, false)
|
||||
TYPE_TRAITS(INT32, int32_t, VARINT, false, false)
|
||||
TYPE_TRAITS(UINT32, uint32_t, VARINT, false, false)
|
||||
TYPE_TRAITS(SINT64, int64_t, VARINT, false, false)
|
||||
TYPE_TRAITS(SINT32, int32_t, VARINT, false, false)
|
||||
TYPE_TRAITS(ENUM, int, VARINT, false, true)
|
||||
TYPE_TRAITS(DOUBLE, double, FIXED64, false, false)
|
||||
TYPE_TRAITS(FLOAT, float, FIXED32, false, false)
|
||||
TYPE_TRAITS(FIXED64, uint64_t, FIXED64, false, false)
|
||||
TYPE_TRAITS(FIXED32, uint32_t, FIXED32, false, false)
|
||||
TYPE_TRAITS(SFIXED64, int64_t, FIXED64, false, false)
|
||||
TYPE_TRAITS(SFIXED32, int32_t, FIXED32, false, false)
|
||||
TYPE_TRAITS(BOOL, bool, VARINT, false, false)
|
||||
|
||||
#undef TYPE_TRAITS
|
||||
|
||||
template <WireFormatLite::FieldType field_type, typename Type>
|
||||
class MapTypeHandler {};
|
||||
|
||||
template <typename Type>
|
||||
class MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type> {
|
||||
public:
|
||||
// Enum type cannot be used for MapTypeHandler::Read. Define a type which will
|
||||
// replace Enum with int.
|
||||
typedef typename MapWireFieldTypeTraits<WireFormatLite::TYPE_MESSAGE,
|
||||
Type>::MapEntryAccessorType
|
||||
MapEntryAccessorType;
|
||||
// Internal stored type in MapEntryLite for given wire field type.
|
||||
typedef typename MapWireFieldTypeTraits<WireFormatLite::TYPE_MESSAGE,
|
||||
Type>::TypeOnMemory TypeOnMemory;
|
||||
// Corresponding wire type for field type.
|
||||
static constexpr WireFormatLite::WireType kWireType =
|
||||
MapWireFieldTypeTraits<WireFormatLite::TYPE_MESSAGE, Type>::kWireType;
|
||||
// Whether wire type is for message.
|
||||
static constexpr bool kIsMessage =
|
||||
MapWireFieldTypeTraits<WireFormatLite::TYPE_MESSAGE, Type>::kIsMessage;
|
||||
// Whether wire type is for enum.
|
||||
static constexpr bool kIsEnum =
|
||||
MapWireFieldTypeTraits<WireFormatLite::TYPE_MESSAGE, Type>::kIsEnum;
|
||||
|
||||
// Functions used in parsing and serialization. ===================
|
||||
static inline size_t ByteSize(const MapEntryAccessorType& value);
|
||||
static inline int GetCachedSize(const MapEntryAccessorType& value);
|
||||
static inline bool Read(io::CodedInputStream* input,
|
||||
MapEntryAccessorType* value);
|
||||
static inline const char* Read(const char* ptr, ParseContext* ctx,
|
||||
MapEntryAccessorType* value);
|
||||
|
||||
static inline uint8_t* Write(int field, const MapEntryAccessorType& value,
|
||||
uint8_t* ptr, io::EpsCopyOutputStream* stream);
|
||||
|
||||
// Functions to manipulate data on memory. ========================
|
||||
static inline const Type& GetExternalReference(const Type* value);
|
||||
static inline void DeleteNoArena(const Type* x);
|
||||
static inline void Merge(const Type& from, Type** to, Arena* arena);
|
||||
static inline void Clear(Type** value, Arena* arena);
|
||||
static constexpr TypeOnMemory Constinit();
|
||||
|
||||
static inline Type* EnsureMutable(Type** value, Arena* arena);
|
||||
// SpaceUsedInMapEntry: Return bytes used by value in MapEntry, excluding
|
||||
// those already calculate in sizeof(MapField).
|
||||
static inline size_t SpaceUsedInMapEntryLong(const Type* value);
|
||||
// Return default instance if value is not initialized when calling const
|
||||
// reference accessor.
|
||||
static inline const Type& DefaultIfNotInitialized(const Type* value);
|
||||
// Check if all required fields have values set.
|
||||
static inline bool IsInitialized(Type* value);
|
||||
};
|
||||
|
||||
#define MAP_HANDLER(FieldType) \
|
||||
template <typename Type> \
|
||||
class MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type> { \
|
||||
public: \
|
||||
typedef typename MapWireFieldTypeTraits<WireFormatLite::TYPE_##FieldType, \
|
||||
Type>::MapEntryAccessorType \
|
||||
MapEntryAccessorType; \
|
||||
typedef typename MapWireFieldTypeTraits<WireFormatLite::TYPE_##FieldType, \
|
||||
Type>::TypeOnMemory TypeOnMemory; \
|
||||
static const WireFormatLite::WireType kWireType = \
|
||||
MapWireFieldTypeTraits<WireFormatLite::TYPE_##FieldType, \
|
||||
Type>::kWireType; \
|
||||
static const bool kIsMessage = \
|
||||
MapWireFieldTypeTraits<WireFormatLite::TYPE_##FieldType, \
|
||||
Type>::kIsMessage; \
|
||||
static const bool kIsEnum = \
|
||||
MapWireFieldTypeTraits<WireFormatLite::TYPE_##FieldType, \
|
||||
Type>::kIsEnum; \
|
||||
static inline int ByteSize(const MapEntryAccessorType& value); \
|
||||
static inline int GetCachedSize(const MapEntryAccessorType& value); \
|
||||
static inline bool Read(io::CodedInputStream* input, \
|
||||
MapEntryAccessorType* value); \
|
||||
static inline const char* Read(const char* begin, ParseContext* ctx, \
|
||||
MapEntryAccessorType* value); \
|
||||
static inline uint8_t* Write(int field, const MapEntryAccessorType& value, \
|
||||
uint8_t* ptr, \
|
||||
io::EpsCopyOutputStream* stream); \
|
||||
static inline const MapEntryAccessorType& GetExternalReference( \
|
||||
const TypeOnMemory& value); \
|
||||
static inline void DeleteNoArena(const TypeOnMemory& x); \
|
||||
static inline void Merge(const MapEntryAccessorType& from, \
|
||||
TypeOnMemory* to, Arena* arena); \
|
||||
static inline void Clear(TypeOnMemory* value, Arena* arena); \
|
||||
static inline size_t SpaceUsedInMapEntryLong(const TypeOnMemory& value); \
|
||||
static inline const MapEntryAccessorType& DefaultIfNotInitialized( \
|
||||
const TypeOnMemory& value); \
|
||||
static inline bool IsInitialized(const TypeOnMemory& value); \
|
||||
static void DeleteNoArena(TypeOnMemory& value); \
|
||||
static constexpr TypeOnMemory Constinit(); \
|
||||
static inline MapEntryAccessorType* EnsureMutable(TypeOnMemory* value, \
|
||||
Arena* arena); \
|
||||
};
|
||||
MAP_HANDLER(STRING)
|
||||
MAP_HANDLER(BYTES)
|
||||
MAP_HANDLER(INT64)
|
||||
MAP_HANDLER(UINT64)
|
||||
MAP_HANDLER(INT32)
|
||||
MAP_HANDLER(UINT32)
|
||||
MAP_HANDLER(SINT64)
|
||||
MAP_HANDLER(SINT32)
|
||||
MAP_HANDLER(ENUM)
|
||||
MAP_HANDLER(DOUBLE)
|
||||
MAP_HANDLER(FLOAT)
|
||||
MAP_HANDLER(FIXED64)
|
||||
MAP_HANDLER(FIXED32)
|
||||
MAP_HANDLER(SFIXED64)
|
||||
MAP_HANDLER(SFIXED32)
|
||||
MAP_HANDLER(BOOL)
|
||||
#undef MAP_HANDLER
|
||||
|
||||
template <typename Type>
|
||||
inline size_t MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::ByteSize(
|
||||
const MapEntryAccessorType& value) {
|
||||
return WireFormatLite::MessageSizeNoVirtual(value);
|
||||
}
|
||||
|
||||
#define GOOGLE_PROTOBUF_BYTE_SIZE(FieldType, DeclaredType) \
|
||||
template <typename Type> \
|
||||
inline int MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::ByteSize( \
|
||||
const MapEntryAccessorType& value) { \
|
||||
return static_cast<int>(WireFormatLite::DeclaredType##Size(value)); \
|
||||
}
|
||||
|
||||
GOOGLE_PROTOBUF_BYTE_SIZE(STRING, String)
|
||||
GOOGLE_PROTOBUF_BYTE_SIZE(BYTES, Bytes)
|
||||
GOOGLE_PROTOBUF_BYTE_SIZE(INT64, Int64)
|
||||
GOOGLE_PROTOBUF_BYTE_SIZE(UINT64, UInt64)
|
||||
GOOGLE_PROTOBUF_BYTE_SIZE(INT32, Int32)
|
||||
GOOGLE_PROTOBUF_BYTE_SIZE(UINT32, UInt32)
|
||||
GOOGLE_PROTOBUF_BYTE_SIZE(SINT64, SInt64)
|
||||
GOOGLE_PROTOBUF_BYTE_SIZE(SINT32, SInt32)
|
||||
GOOGLE_PROTOBUF_BYTE_SIZE(ENUM, Enum)
|
||||
|
||||
#undef GOOGLE_PROTOBUF_BYTE_SIZE
|
||||
|
||||
#define FIXED_BYTE_SIZE(FieldType, DeclaredType) \
|
||||
template <typename Type> \
|
||||
inline int MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::ByteSize( \
|
||||
const MapEntryAccessorType& /* value */) { \
|
||||
return WireFormatLite::k##DeclaredType##Size; \
|
||||
}
|
||||
|
||||
FIXED_BYTE_SIZE(DOUBLE, Double)
|
||||
FIXED_BYTE_SIZE(FLOAT, Float)
|
||||
FIXED_BYTE_SIZE(FIXED64, Fixed64)
|
||||
FIXED_BYTE_SIZE(FIXED32, Fixed32)
|
||||
FIXED_BYTE_SIZE(SFIXED64, SFixed64)
|
||||
FIXED_BYTE_SIZE(SFIXED32, SFixed32)
|
||||
FIXED_BYTE_SIZE(BOOL, Bool)
|
||||
|
||||
#undef FIXED_BYTE_SIZE
|
||||
|
||||
template <typename Type>
|
||||
inline int MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::GetCachedSize(
|
||||
const MapEntryAccessorType& value) {
|
||||
return static_cast<int>(WireFormatLite::LengthDelimitedSize(
|
||||
static_cast<size_t>(value.GetCachedSize())));
|
||||
}
|
||||
|
||||
#define GET_CACHED_SIZE(FieldType, DeclaredType) \
|
||||
template <typename Type> \
|
||||
inline int \
|
||||
MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::GetCachedSize( \
|
||||
const MapEntryAccessorType& value) { \
|
||||
return static_cast<int>(WireFormatLite::DeclaredType##Size(value)); \
|
||||
}
|
||||
|
||||
GET_CACHED_SIZE(STRING, String)
|
||||
GET_CACHED_SIZE(BYTES, Bytes)
|
||||
GET_CACHED_SIZE(INT64, Int64)
|
||||
GET_CACHED_SIZE(UINT64, UInt64)
|
||||
GET_CACHED_SIZE(INT32, Int32)
|
||||
GET_CACHED_SIZE(UINT32, UInt32)
|
||||
GET_CACHED_SIZE(SINT64, SInt64)
|
||||
GET_CACHED_SIZE(SINT32, SInt32)
|
||||
GET_CACHED_SIZE(ENUM, Enum)
|
||||
|
||||
#undef GET_CACHED_SIZE
|
||||
|
||||
#define GET_FIXED_CACHED_SIZE(FieldType, DeclaredType) \
|
||||
template <typename Type> \
|
||||
inline int \
|
||||
MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::GetCachedSize( \
|
||||
const MapEntryAccessorType& /* value */) { \
|
||||
return WireFormatLite::k##DeclaredType##Size; \
|
||||
}
|
||||
|
||||
GET_FIXED_CACHED_SIZE(DOUBLE, Double)
|
||||
GET_FIXED_CACHED_SIZE(FLOAT, Float)
|
||||
GET_FIXED_CACHED_SIZE(FIXED64, Fixed64)
|
||||
GET_FIXED_CACHED_SIZE(FIXED32, Fixed32)
|
||||
GET_FIXED_CACHED_SIZE(SFIXED64, SFixed64)
|
||||
GET_FIXED_CACHED_SIZE(SFIXED32, SFixed32)
|
||||
GET_FIXED_CACHED_SIZE(BOOL, Bool)
|
||||
|
||||
#undef GET_FIXED_CACHED_SIZE
|
||||
|
||||
template <typename Type>
|
||||
inline uint8_t* MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::Write(
|
||||
int field, const MapEntryAccessorType& value, uint8_t* ptr,
|
||||
io::EpsCopyOutputStream* stream) {
|
||||
ptr = stream->EnsureSpace(ptr);
|
||||
return WireFormatLite::InternalWriteMessage(
|
||||
field, value, value.GetCachedSize(), ptr, stream);
|
||||
}
|
||||
|
||||
#define WRITE_METHOD(FieldType, DeclaredType) \
|
||||
template <typename Type> \
|
||||
inline uint8_t* \
|
||||
MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Write( \
|
||||
int field, const MapEntryAccessorType& value, uint8_t* ptr, \
|
||||
io::EpsCopyOutputStream* stream) { \
|
||||
ptr = stream->EnsureSpace(ptr); \
|
||||
return stream->Write##DeclaredType(field, value, ptr); \
|
||||
}
|
||||
|
||||
WRITE_METHOD(STRING, String)
|
||||
WRITE_METHOD(BYTES, Bytes)
|
||||
|
||||
#undef WRITE_METHOD
|
||||
#define WRITE_METHOD(FieldType, DeclaredType) \
|
||||
template <typename Type> \
|
||||
inline uint8_t* \
|
||||
MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Write( \
|
||||
int field, const MapEntryAccessorType& value, uint8_t* ptr, \
|
||||
io::EpsCopyOutputStream* stream) { \
|
||||
ptr = stream->EnsureSpace(ptr); \
|
||||
return WireFormatLite::Write##DeclaredType##ToArray(field, value, ptr); \
|
||||
}
|
||||
|
||||
WRITE_METHOD(INT64, Int64)
|
||||
WRITE_METHOD(UINT64, UInt64)
|
||||
WRITE_METHOD(INT32, Int32)
|
||||
WRITE_METHOD(UINT32, UInt32)
|
||||
WRITE_METHOD(SINT64, SInt64)
|
||||
WRITE_METHOD(SINT32, SInt32)
|
||||
WRITE_METHOD(ENUM, Enum)
|
||||
WRITE_METHOD(DOUBLE, Double)
|
||||
WRITE_METHOD(FLOAT, Float)
|
||||
WRITE_METHOD(FIXED64, Fixed64)
|
||||
WRITE_METHOD(FIXED32, Fixed32)
|
||||
WRITE_METHOD(SFIXED64, SFixed64)
|
||||
WRITE_METHOD(SFIXED32, SFixed32)
|
||||
WRITE_METHOD(BOOL, Bool)
|
||||
|
||||
#undef WRITE_METHOD
|
||||
|
||||
template <typename Type>
|
||||
inline bool MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::Read(
|
||||
io::CodedInputStream* input, MapEntryAccessorType* value) {
|
||||
return WireFormatLite::ReadMessageNoVirtual(input, value);
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
inline bool MapTypeHandler<WireFormatLite::TYPE_STRING, Type>::Read(
|
||||
io::CodedInputStream* input, MapEntryAccessorType* value) {
|
||||
return WireFormatLite::ReadString(input, value);
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
inline bool MapTypeHandler<WireFormatLite::TYPE_BYTES, Type>::Read(
|
||||
io::CodedInputStream* input, MapEntryAccessorType* value) {
|
||||
return WireFormatLite::ReadBytes(input, value);
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
const char* MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::Read(
|
||||
const char* ptr, ParseContext* ctx, MapEntryAccessorType* value) {
|
||||
return ctx->ParseMessage(value, ptr);
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
const char* MapTypeHandler<WireFormatLite::TYPE_STRING, Type>::Read(
|
||||
const char* ptr, ParseContext* ctx, MapEntryAccessorType* value) {
|
||||
int size = ReadSize(&ptr);
|
||||
GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
|
||||
return ctx->ReadString(ptr, size, value);
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
const char* MapTypeHandler<WireFormatLite::TYPE_BYTES, Type>::Read(
|
||||
const char* ptr, ParseContext* ctx, MapEntryAccessorType* value) {
|
||||
int size = ReadSize(&ptr);
|
||||
GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
|
||||
return ctx->ReadString(ptr, size, value);
|
||||
}
|
||||
|
||||
inline const char* ReadINT64(const char* ptr, int64_t* value) {
|
||||
return VarintParse(ptr, reinterpret_cast<uint64_t*>(value));
|
||||
}
|
||||
inline const char* ReadUINT64(const char* ptr, uint64_t* value) {
|
||||
return VarintParse(ptr, value);
|
||||
}
|
||||
inline const char* ReadINT32(const char* ptr, int32_t* value) {
|
||||
return VarintParse(ptr, reinterpret_cast<uint32_t*>(value));
|
||||
}
|
||||
inline const char* ReadUINT32(const char* ptr, uint32_t* value) {
|
||||
return VarintParse(ptr, value);
|
||||
}
|
||||
inline const char* ReadSINT64(const char* ptr, int64_t* value) {
|
||||
*value = ReadVarintZigZag64(&ptr);
|
||||
return ptr;
|
||||
}
|
||||
inline const char* ReadSINT32(const char* ptr, int32_t* value) {
|
||||
*value = ReadVarintZigZag32(&ptr);
|
||||
return ptr;
|
||||
}
|
||||
template <typename E>
|
||||
inline const char* ReadENUM(const char* ptr, E* value) {
|
||||
*value = static_cast<E>(ReadVarint32(&ptr));
|
||||
return ptr;
|
||||
}
|
||||
inline const char* ReadBOOL(const char* ptr, bool* value) {
|
||||
*value = static_cast<bool>(ReadVarint32(&ptr));
|
||||
return ptr;
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
inline const char* ReadUnaligned(const char* ptr, F* value) {
|
||||
*value = UnalignedLoad<F>(ptr);
|
||||
return ptr + sizeof(F);
|
||||
}
|
||||
inline const char* ReadFLOAT(const char* ptr, float* value) {
|
||||
return ReadUnaligned(ptr, value);
|
||||
}
|
||||
inline const char* ReadDOUBLE(const char* ptr, double* value) {
|
||||
return ReadUnaligned(ptr, value);
|
||||
}
|
||||
inline const char* ReadFIXED64(const char* ptr, uint64_t* value) {
|
||||
return ReadUnaligned(ptr, value);
|
||||
}
|
||||
inline const char* ReadFIXED32(const char* ptr, uint32_t* value) {
|
||||
return ReadUnaligned(ptr, value);
|
||||
}
|
||||
inline const char* ReadSFIXED64(const char* ptr, int64_t* value) {
|
||||
return ReadUnaligned(ptr, value);
|
||||
}
|
||||
inline const char* ReadSFIXED32(const char* ptr, int32_t* value) {
|
||||
return ReadUnaligned(ptr, value);
|
||||
}
|
||||
|
||||
#define READ_METHOD(FieldType) \
|
||||
template <typename Type> \
|
||||
inline bool MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Read( \
|
||||
io::CodedInputStream* input, MapEntryAccessorType* value) { \
|
||||
return WireFormatLite::ReadPrimitive<TypeOnMemory, \
|
||||
WireFormatLite::TYPE_##FieldType>( \
|
||||
input, value); \
|
||||
} \
|
||||
template <typename Type> \
|
||||
const char* MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Read( \
|
||||
const char* begin, ParseContext* ctx, MapEntryAccessorType* value) { \
|
||||
(void)ctx; \
|
||||
return Read##FieldType(begin, value); \
|
||||
}
|
||||
|
||||
READ_METHOD(INT64)
|
||||
READ_METHOD(UINT64)
|
||||
READ_METHOD(INT32)
|
||||
READ_METHOD(UINT32)
|
||||
READ_METHOD(SINT64)
|
||||
READ_METHOD(SINT32)
|
||||
READ_METHOD(ENUM)
|
||||
READ_METHOD(DOUBLE)
|
||||
READ_METHOD(FLOAT)
|
||||
READ_METHOD(FIXED64)
|
||||
READ_METHOD(FIXED32)
|
||||
READ_METHOD(SFIXED64)
|
||||
READ_METHOD(SFIXED32)
|
||||
READ_METHOD(BOOL)
|
||||
|
||||
#undef READ_METHOD
|
||||
|
||||
// Definition for message handler
|
||||
|
||||
template <typename Type>
|
||||
inline const Type&
|
||||
MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::GetExternalReference(
|
||||
const Type* value) {
|
||||
return *value;
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
inline size_t MapTypeHandler<WireFormatLite::TYPE_MESSAGE,
|
||||
Type>::SpaceUsedInMapEntryLong(const Type* value) {
|
||||
return value->SpaceUsedLong();
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
inline void MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::Clear(
|
||||
Type** value, Arena* /* arena */) {
|
||||
if (*value != nullptr) (*value)->Clear();
|
||||
}
|
||||
template <typename Type>
|
||||
inline void MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::Merge(
|
||||
const Type& from, Type** to, Arena* /* arena */) {
|
||||
(*to)->MergeFrom(from);
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
void MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::DeleteNoArena(
|
||||
const Type* ptr) {
|
||||
delete ptr;
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
constexpr auto MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::Constinit()
|
||||
-> TypeOnMemory {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
inline Type* MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::EnsureMutable(
|
||||
Type** value, Arena* arena) {
|
||||
if (*value == nullptr) {
|
||||
*value = MapArenaMessageCreator<
|
||||
Type,
|
||||
Arena::is_arena_constructable<Type>::type::value>::CreateMessage(arena);
|
||||
}
|
||||
return *value;
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
inline const Type&
|
||||
MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::DefaultIfNotInitialized(
|
||||
const Type* value) {
|
||||
return value != nullptr ? *value : *Type::internal_default_instance();
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
inline bool MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::IsInitialized(
|
||||
Type* value) {
|
||||
return value ? value->IsInitialized() : false;
|
||||
}
|
||||
|
||||
// Definition for string/bytes handler
|
||||
|
||||
#define STRING_OR_BYTES_HANDLER_FUNCTIONS(FieldType) \
|
||||
template <typename Type> \
|
||||
inline const typename MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
|
||||
Type>::MapEntryAccessorType& \
|
||||
MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
|
||||
Type>::GetExternalReference(const TypeOnMemory& value) { \
|
||||
return value.Get(); \
|
||||
} \
|
||||
template <typename Type> \
|
||||
inline size_t \
|
||||
MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
|
||||
Type>::SpaceUsedInMapEntryLong(const TypeOnMemory& value) { \
|
||||
return sizeof(value); \
|
||||
} \
|
||||
template <typename Type> \
|
||||
inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Clear( \
|
||||
TypeOnMemory* value, Arena* /* arena */) { \
|
||||
value->ClearToEmpty(); \
|
||||
} \
|
||||
template <typename Type> \
|
||||
inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Merge( \
|
||||
const MapEntryAccessorType& from, TypeOnMemory* to, Arena* arena) { \
|
||||
to->Set(from, arena); \
|
||||
} \
|
||||
template <typename Type> \
|
||||
void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::DeleteNoArena( \
|
||||
TypeOnMemory& value) { \
|
||||
value.Destroy(); \
|
||||
} \
|
||||
template <typename Type> \
|
||||
constexpr auto \
|
||||
MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Constinit() \
|
||||
->TypeOnMemory { \
|
||||
return TypeOnMemory(&internal::fixed_address_empty_string, \
|
||||
ConstantInitialized{}); \
|
||||
} \
|
||||
template <typename Type> \
|
||||
inline typename MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
|
||||
Type>::MapEntryAccessorType* \
|
||||
MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::EnsureMutable( \
|
||||
TypeOnMemory* value, Arena* arena) { \
|
||||
return value->Mutable(arena); \
|
||||
} \
|
||||
template <typename Type> \
|
||||
inline const typename MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
|
||||
Type>::MapEntryAccessorType& \
|
||||
MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
|
||||
Type>::DefaultIfNotInitialized(const TypeOnMemory& value) { \
|
||||
return value.Get(); \
|
||||
} \
|
||||
template <typename Type> \
|
||||
inline bool \
|
||||
MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::IsInitialized( \
|
||||
const TypeOnMemory& /* value */) { \
|
||||
return true; \
|
||||
}
|
||||
STRING_OR_BYTES_HANDLER_FUNCTIONS(STRING)
|
||||
STRING_OR_BYTES_HANDLER_FUNCTIONS(BYTES)
|
||||
#undef STRING_OR_BYTES_HANDLER_FUNCTIONS
|
||||
|
||||
#define PRIMITIVE_HANDLER_FUNCTIONS(FieldType) \
|
||||
template <typename Type> \
|
||||
inline const typename MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
|
||||
Type>::MapEntryAccessorType& \
|
||||
MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
|
||||
Type>::GetExternalReference(const TypeOnMemory& value) { \
|
||||
return value; \
|
||||
} \
|
||||
template <typename Type> \
|
||||
inline size_t MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>:: \
|
||||
SpaceUsedInMapEntryLong(const TypeOnMemory& /* value */) { \
|
||||
return 0; \
|
||||
} \
|
||||
template <typename Type> \
|
||||
inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Clear( \
|
||||
TypeOnMemory* value, Arena* /* arena */) { \
|
||||
*value = 0; \
|
||||
} \
|
||||
template <typename Type> \
|
||||
inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Merge( \
|
||||
const MapEntryAccessorType& from, TypeOnMemory* to, \
|
||||
Arena* /* arena */) { \
|
||||
*to = from; \
|
||||
} \
|
||||
template <typename Type> \
|
||||
inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
|
||||
Type>::DeleteNoArena(TypeOnMemory& /* x */) {} \
|
||||
template <typename Type> \
|
||||
constexpr auto \
|
||||
MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Constinit() \
|
||||
->TypeOnMemory { \
|
||||
return 0; \
|
||||
} \
|
||||
template <typename Type> \
|
||||
inline typename MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
|
||||
Type>::MapEntryAccessorType* \
|
||||
MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::EnsureMutable( \
|
||||
TypeOnMemory* value, Arena* /* arena */) { \
|
||||
return value; \
|
||||
} \
|
||||
template <typename Type> \
|
||||
inline const typename MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
|
||||
Type>::MapEntryAccessorType& \
|
||||
MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
|
||||
Type>::DefaultIfNotInitialized(const TypeOnMemory& value) { \
|
||||
return value; \
|
||||
} \
|
||||
template <typename Type> \
|
||||
inline bool \
|
||||
MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::IsInitialized( \
|
||||
const TypeOnMemory& /* value */) { \
|
||||
return true; \
|
||||
}
|
||||
PRIMITIVE_HANDLER_FUNCTIONS(INT64)
|
||||
PRIMITIVE_HANDLER_FUNCTIONS(UINT64)
|
||||
PRIMITIVE_HANDLER_FUNCTIONS(INT32)
|
||||
PRIMITIVE_HANDLER_FUNCTIONS(UINT32)
|
||||
PRIMITIVE_HANDLER_FUNCTIONS(SINT64)
|
||||
PRIMITIVE_HANDLER_FUNCTIONS(SINT32)
|
||||
PRIMITIVE_HANDLER_FUNCTIONS(ENUM)
|
||||
PRIMITIVE_HANDLER_FUNCTIONS(DOUBLE)
|
||||
PRIMITIVE_HANDLER_FUNCTIONS(FLOAT)
|
||||
PRIMITIVE_HANDLER_FUNCTIONS(FIXED64)
|
||||
PRIMITIVE_HANDLER_FUNCTIONS(FIXED32)
|
||||
PRIMITIVE_HANDLER_FUNCTIONS(SFIXED64)
|
||||
PRIMITIVE_HANDLER_FUNCTIONS(SFIXED32)
|
||||
PRIMITIVE_HANDLER_FUNCTIONS(BOOL)
|
||||
#undef PRIMITIVE_HANDLER_FUNCTIONS
|
||||
|
||||
// Functions for operating on a map entry using type handlers.
|
||||
//
|
||||
// Does not contain any representation (this class is not intended to be
|
||||
// instantiated).
|
||||
template <typename Key, typename Value, WireFormatLite::FieldType kKeyFieldType,
|
||||
WireFormatLite::FieldType kValueFieldType>
|
||||
struct MapEntryFuncs {
|
||||
typedef MapTypeHandler<kKeyFieldType, Key> KeyTypeHandler;
|
||||
typedef MapTypeHandler<kValueFieldType, Value> ValueTypeHandler;
|
||||
enum : int {
|
||||
kKeyFieldNumber = 1,
|
||||
kValueFieldNumber = 2
|
||||
};
|
||||
|
||||
static uint8_t* InternalSerialize(int field_number, const Key& key,
|
||||
const Value& value, uint8_t* ptr,
|
||||
io::EpsCopyOutputStream* stream) {
|
||||
ptr = stream->EnsureSpace(ptr);
|
||||
ptr = WireFormatLite::WriteTagToArray(
|
||||
field_number, WireFormatLite::WIRETYPE_LENGTH_DELIMITED, ptr);
|
||||
ptr = io::CodedOutputStream::WriteVarint32ToArray(GetCachedSize(key, value),
|
||||
ptr);
|
||||
|
||||
ptr = KeyTypeHandler::Write(kKeyFieldNumber, key, ptr, stream);
|
||||
return ValueTypeHandler::Write(kValueFieldNumber, value, ptr, stream);
|
||||
}
|
||||
|
||||
static size_t ByteSizeLong(const Key& key, const Value& value) {
|
||||
// Tags for key and value will both be one byte (field numbers 1 and 2).
|
||||
size_t inner_length =
|
||||
2 + KeyTypeHandler::ByteSize(key) + ValueTypeHandler::ByteSize(value);
|
||||
return inner_length + io::CodedOutputStream::VarintSize32(
|
||||
static_cast<uint32_t>(inner_length));
|
||||
}
|
||||
|
||||
static int GetCachedSize(const Key& key, const Value& value) {
|
||||
// Tags for key and value will both be one byte (field numbers 1 and 2).
|
||||
return 2 + KeyTypeHandler::GetCachedSize(key) +
|
||||
ValueTypeHandler::GetCachedSize(value);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_MAP_TYPE_HANDLER_H__
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,591 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Authors: wink@google.com (Wink Saville),
|
||||
// kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
//
|
||||
// Defines MessageLite, the abstract interface implemented by all (lite
|
||||
// and non-lite) protocol message objects.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_MESSAGE_LITE_H__
|
||||
#define GOOGLE_PROTOBUF_MESSAGE_LITE_H__
|
||||
|
||||
|
||||
#include <climits>
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/logging.h>
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/arena.h>
|
||||
#include <google/protobuf/stubs/once.h>
|
||||
#include <google/protobuf/port.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
#include <google/protobuf/explicitly_constructed.h>
|
||||
#include <google/protobuf/metadata_lite.h>
|
||||
#include <google/protobuf/stubs/hash.h> // TODO(b/211442718): cleanup
|
||||
|
||||
// clang-format off
|
||||
#include <google/protobuf/port_def.inc>
|
||||
// clang-format on
|
||||
|
||||
#ifdef SWIG
|
||||
#error "You cannot SWIG proto headers"
|
||||
#endif
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
template <typename T>
|
||||
class RepeatedPtrField;
|
||||
|
||||
class FastReflectionMessageMutator;
|
||||
class FastReflectionStringSetter;
|
||||
class Reflection;
|
||||
|
||||
namespace io {
|
||||
|
||||
class CodedInputStream;
|
||||
class CodedOutputStream;
|
||||
class ZeroCopyInputStream;
|
||||
class ZeroCopyOutputStream;
|
||||
|
||||
} // namespace io
|
||||
namespace internal {
|
||||
|
||||
class SwapFieldHelper;
|
||||
|
||||
// See parse_context.h for explanation
|
||||
class ParseContext;
|
||||
|
||||
class ExtensionSet;
|
||||
class LazyField;
|
||||
class RepeatedPtrFieldBase;
|
||||
class TcParser;
|
||||
class WireFormatLite;
|
||||
class WeakFieldMap;
|
||||
|
||||
template <typename Type>
|
||||
class GenericTypeHandler; // defined in repeated_field.h
|
||||
|
||||
// We compute sizes as size_t but cache them as int. This function converts a
|
||||
// computed size to a cached size. Since we don't proceed with serialization
|
||||
// if the total size was > INT_MAX, it is not important what this function
|
||||
// returns for inputs > INT_MAX. However this case should not error or
|
||||
// GOOGLE_CHECK-fail, because the full size_t resolution is still returned from
|
||||
// ByteSizeLong() and checked against INT_MAX; we can catch the overflow
|
||||
// there.
|
||||
inline int ToCachedSize(size_t size) { return static_cast<int>(size); }
|
||||
|
||||
// We mainly calculate sizes in terms of size_t, but some functions that
|
||||
// compute sizes return "int". These int sizes are expected to always be
|
||||
// positive. This function is more efficient than casting an int to size_t
|
||||
// directly on 64-bit platforms because it avoids making the compiler emit a
|
||||
// sign extending instruction, which we don't want and don't want to pay for.
|
||||
inline size_t FromIntSize(int size) {
|
||||
// Convert to unsigned before widening so sign extension is not necessary.
|
||||
return static_cast<unsigned int>(size);
|
||||
}
|
||||
|
||||
// For cases where a legacy function returns an integer size. We GOOGLE_DCHECK()
|
||||
// that the conversion will fit within an integer; if this is false then we
|
||||
// are losing information.
|
||||
inline int ToIntSize(size_t size) {
|
||||
GOOGLE_DCHECK_LE(size, static_cast<size_t>(INT_MAX));
|
||||
return static_cast<int>(size);
|
||||
}
|
||||
|
||||
// Default empty string object. Don't use this directly. Instead, call
|
||||
// GetEmptyString() to get the reference. This empty string is aligned with a
|
||||
// minimum alignment of 8 bytes to match the requirement of ArenaStringPtr.
|
||||
PROTOBUF_EXPORT extern ExplicitlyConstructedArenaString
|
||||
fixed_address_empty_string;
|
||||
|
||||
|
||||
PROTOBUF_EXPORT constexpr const std::string& GetEmptyStringAlreadyInited() {
|
||||
return fixed_address_empty_string.get();
|
||||
}
|
||||
|
||||
PROTOBUF_EXPORT size_t StringSpaceUsedExcludingSelfLong(const std::string& str);
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// Interface to light weight protocol messages.
|
||||
//
|
||||
// This interface is implemented by all protocol message objects. Non-lite
|
||||
// messages additionally implement the Message interface, which is a
|
||||
// subclass of MessageLite. Use MessageLite instead when you only need
|
||||
// the subset of features which it supports -- namely, nothing that uses
|
||||
// descriptors or reflection. You can instruct the protocol compiler
|
||||
// to generate classes which implement only MessageLite, not the full
|
||||
// Message interface, by adding the following line to the .proto file:
|
||||
//
|
||||
// option optimize_for = LITE_RUNTIME;
|
||||
//
|
||||
// This is particularly useful on resource-constrained systems where
|
||||
// the full protocol buffers runtime library is too big.
|
||||
//
|
||||
// Note that on non-constrained systems (e.g. servers) when you need
|
||||
// to link in lots of protocol definitions, a better way to reduce
|
||||
// total code footprint is to use optimize_for = CODE_SIZE. This
|
||||
// will make the generated code smaller while still supporting all the
|
||||
// same features (at the expense of speed). optimize_for = LITE_RUNTIME
|
||||
// is best when you only have a small number of message types linked
|
||||
// into your binary, in which case the size of the protocol buffers
|
||||
// runtime itself is the biggest problem.
|
||||
//
|
||||
// Users must not derive from this class. Only the protocol compiler and
|
||||
// the internal library are allowed to create subclasses.
|
||||
class PROTOBUF_EXPORT MessageLite {
|
||||
public:
|
||||
constexpr MessageLite() {}
|
||||
virtual ~MessageLite() = default;
|
||||
|
||||
// Basic Operations ------------------------------------------------
|
||||
|
||||
// Get the name of this message type, e.g. "foo.bar.BazProto".
|
||||
virtual std::string GetTypeName() const = 0;
|
||||
|
||||
// Construct a new instance of the same type. Ownership is passed to the
|
||||
// caller.
|
||||
MessageLite* New() const { return New(nullptr); }
|
||||
|
||||
// Construct a new instance on the arena. Ownership is passed to the caller
|
||||
// if arena is a nullptr.
|
||||
virtual MessageLite* New(Arena* arena) const = 0;
|
||||
|
||||
// Returns user-owned arena; nullptr if it's message owned.
|
||||
Arena* GetArena() const { return _internal_metadata_.user_arena(); }
|
||||
|
||||
// Clear all fields of the message and set them to their default values.
|
||||
// Clear() assumes that any memory allocated to hold parts of the message
|
||||
// will likely be needed again, so the memory used may not be freed.
|
||||
// To ensure that all memory used by a Message is freed, you must delete it.
|
||||
virtual void Clear() = 0;
|
||||
|
||||
// Quickly check if all required fields have values set.
|
||||
virtual bool IsInitialized() const = 0;
|
||||
|
||||
// This is not implemented for Lite messages -- it just returns "(cannot
|
||||
// determine missing fields for lite message)". However, it is implemented
|
||||
// for full messages. See message.h.
|
||||
virtual std::string InitializationErrorString() const;
|
||||
|
||||
// If |other| is the exact same class as this, calls MergeFrom(). Otherwise,
|
||||
// results are undefined (probably crash).
|
||||
virtual void CheckTypeAndMergeFrom(const MessageLite& other) = 0;
|
||||
|
||||
// These methods return a human-readable summary of the message. Note that
|
||||
// since the MessageLite interface does not support reflection, there is very
|
||||
// little information that these methods can provide. They are shadowed by
|
||||
// methods of the same name on the Message interface which provide much more
|
||||
// information. The methods here are intended primarily to facilitate code
|
||||
// reuse for logic that needs to interoperate with both full and lite protos.
|
||||
//
|
||||
// The format of the returned string is subject to change, so please do not
|
||||
// assume it will remain stable over time.
|
||||
std::string DebugString() const;
|
||||
std::string ShortDebugString() const { return DebugString(); }
|
||||
// MessageLite::DebugString is already Utf8 Safe. This is to add compatibility
|
||||
// with Message.
|
||||
std::string Utf8DebugString() const { return DebugString(); }
|
||||
|
||||
// Parsing ---------------------------------------------------------
|
||||
// Methods for parsing in protocol buffer format. Most of these are
|
||||
// just simple wrappers around MergeFromCodedStream(). Clear() will be
|
||||
// called before merging the input.
|
||||
|
||||
// Fill the message with a protocol buffer parsed from the given input
|
||||
// stream. Returns false on a read error or if the input is in the wrong
|
||||
// format. A successful return does not indicate the entire input is
|
||||
// consumed, ensure you call ConsumedEntireMessage() to check that if
|
||||
// applicable.
|
||||
PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParseFromCodedStream(
|
||||
io::CodedInputStream* input);
|
||||
// Like ParseFromCodedStream(), but accepts messages that are missing
|
||||
// required fields.
|
||||
PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParsePartialFromCodedStream(
|
||||
io::CodedInputStream* input);
|
||||
// Read a protocol buffer from the given zero-copy input stream. If
|
||||
// successful, the entire input will be consumed.
|
||||
PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParseFromZeroCopyStream(
|
||||
io::ZeroCopyInputStream* input);
|
||||
// Like ParseFromZeroCopyStream(), but accepts messages that are missing
|
||||
// required fields.
|
||||
PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParsePartialFromZeroCopyStream(
|
||||
io::ZeroCopyInputStream* input);
|
||||
// Parse a protocol buffer from a file descriptor. If successful, the entire
|
||||
// input will be consumed.
|
||||
PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParseFromFileDescriptor(
|
||||
int file_descriptor);
|
||||
// Like ParseFromFileDescriptor(), but accepts messages that are missing
|
||||
// required fields.
|
||||
PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParsePartialFromFileDescriptor(
|
||||
int file_descriptor);
|
||||
// Parse a protocol buffer from a C++ istream. If successful, the entire
|
||||
// input will be consumed.
|
||||
PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParseFromIstream(std::istream* input);
|
||||
// Like ParseFromIstream(), but accepts messages that are missing
|
||||
// required fields.
|
||||
PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParsePartialFromIstream(
|
||||
std::istream* input);
|
||||
// Read a protocol buffer from the given zero-copy input stream, expecting
|
||||
// the message to be exactly "size" bytes long. If successful, exactly
|
||||
// this many bytes will have been consumed from the input.
|
||||
bool MergePartialFromBoundedZeroCopyStream(io::ZeroCopyInputStream* input,
|
||||
int size);
|
||||
// Like ParseFromBoundedZeroCopyStream(), but accepts messages that are
|
||||
// missing required fields.
|
||||
bool MergeFromBoundedZeroCopyStream(io::ZeroCopyInputStream* input, int size);
|
||||
PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParseFromBoundedZeroCopyStream(
|
||||
io::ZeroCopyInputStream* input, int size);
|
||||
// Like ParseFromBoundedZeroCopyStream(), but accepts messages that are
|
||||
// missing required fields.
|
||||
PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParsePartialFromBoundedZeroCopyStream(
|
||||
io::ZeroCopyInputStream* input, int size);
|
||||
// Parses a protocol buffer contained in a string. Returns true on success.
|
||||
// This function takes a string in the (non-human-readable) binary wire
|
||||
// format, matching the encoding output by MessageLite::SerializeToString().
|
||||
// If you'd like to convert a human-readable string into a protocol buffer
|
||||
// object, see google::protobuf::TextFormat::ParseFromString().
|
||||
PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParseFromString(ConstStringParam data);
|
||||
// Like ParseFromString(), but accepts messages that are missing
|
||||
// required fields.
|
||||
PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParsePartialFromString(
|
||||
ConstStringParam data);
|
||||
// Parse a protocol buffer contained in an array of bytes.
|
||||
PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParseFromArray(const void* data,
|
||||
int size);
|
||||
// Like ParseFromArray(), but accepts messages that are missing
|
||||
// required fields.
|
||||
PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParsePartialFromArray(const void* data,
|
||||
int size);
|
||||
|
||||
|
||||
// Reads a protocol buffer from the stream and merges it into this
|
||||
// Message. Singular fields read from the what is
|
||||
// already in the Message and repeated fields are appended to those
|
||||
// already present.
|
||||
//
|
||||
// It is the responsibility of the caller to call input->LastTagWas()
|
||||
// (for groups) or input->ConsumedEntireMessage() (for non-groups) after
|
||||
// this returns to verify that the message's end was delimited correctly.
|
||||
//
|
||||
// ParseFromCodedStream() is implemented as Clear() followed by
|
||||
// MergeFromCodedStream().
|
||||
bool MergeFromCodedStream(io::CodedInputStream* input);
|
||||
|
||||
// Like MergeFromCodedStream(), but succeeds even if required fields are
|
||||
// missing in the input.
|
||||
//
|
||||
// MergeFromCodedStream() is just implemented as MergePartialFromCodedStream()
|
||||
// followed by IsInitialized().
|
||||
bool MergePartialFromCodedStream(io::CodedInputStream* input);
|
||||
|
||||
// Merge a protocol buffer contained in a string.
|
||||
bool MergeFromString(ConstStringParam data);
|
||||
|
||||
|
||||
// Serialization ---------------------------------------------------
|
||||
// Methods for serializing in protocol buffer format. Most of these
|
||||
// are just simple wrappers around ByteSize() and SerializeWithCachedSizes().
|
||||
|
||||
// Write a protocol buffer of this message to the given output. Returns
|
||||
// false on a write error. If the message is missing required fields,
|
||||
// this may GOOGLE_CHECK-fail.
|
||||
bool SerializeToCodedStream(io::CodedOutputStream* output) const;
|
||||
// Like SerializeToCodedStream(), but allows missing required fields.
|
||||
bool SerializePartialToCodedStream(io::CodedOutputStream* output) const;
|
||||
// Write the message to the given zero-copy output stream. All required
|
||||
// fields must be set.
|
||||
bool SerializeToZeroCopyStream(io::ZeroCopyOutputStream* output) const;
|
||||
// Like SerializeToZeroCopyStream(), but allows missing required fields.
|
||||
bool SerializePartialToZeroCopyStream(io::ZeroCopyOutputStream* output) const;
|
||||
// Serialize the message and store it in the given string. All required
|
||||
// fields must be set.
|
||||
bool SerializeToString(std::string* output) const;
|
||||
// Like SerializeToString(), but allows missing required fields.
|
||||
bool SerializePartialToString(std::string* output) const;
|
||||
// Serialize the message and store it in the given byte array. All required
|
||||
// fields must be set.
|
||||
bool SerializeToArray(void* data, int size) const;
|
||||
// Like SerializeToArray(), but allows missing required fields.
|
||||
bool SerializePartialToArray(void* data, int size) const;
|
||||
|
||||
// Make a string encoding the message. Is equivalent to calling
|
||||
// SerializeToString() on a string and using that. Returns the empty
|
||||
// string if SerializeToString() would have returned an error.
|
||||
// Note: If you intend to generate many such strings, you may
|
||||
// reduce heap fragmentation by instead re-using the same string
|
||||
// object with calls to SerializeToString().
|
||||
std::string SerializeAsString() const;
|
||||
// Like SerializeAsString(), but allows missing required fields.
|
||||
std::string SerializePartialAsString() const;
|
||||
|
||||
// Serialize the message and write it to the given file descriptor. All
|
||||
// required fields must be set.
|
||||
bool SerializeToFileDescriptor(int file_descriptor) const;
|
||||
// Like SerializeToFileDescriptor(), but allows missing required fields.
|
||||
bool SerializePartialToFileDescriptor(int file_descriptor) const;
|
||||
// Serialize the message and write it to the given C++ ostream. All
|
||||
// required fields must be set.
|
||||
bool SerializeToOstream(std::ostream* output) const;
|
||||
// Like SerializeToOstream(), but allows missing required fields.
|
||||
bool SerializePartialToOstream(std::ostream* output) const;
|
||||
|
||||
// Like SerializeToString(), but appends to the data to the string's
|
||||
// existing contents. All required fields must be set.
|
||||
bool AppendToString(std::string* output) const;
|
||||
// Like AppendToString(), but allows missing required fields.
|
||||
bool AppendPartialToString(std::string* output) const;
|
||||
|
||||
|
||||
// Computes the serialized size of the message. This recursively calls
|
||||
// ByteSizeLong() on all embedded messages.
|
||||
//
|
||||
// ByteSizeLong() is generally linear in the number of fields defined for the
|
||||
// proto.
|
||||
virtual size_t ByteSizeLong() const = 0;
|
||||
|
||||
// Legacy ByteSize() API.
|
||||
PROTOBUF_DEPRECATED_MSG("Please use ByteSizeLong() instead")
|
||||
int ByteSize() const { return internal::ToIntSize(ByteSizeLong()); }
|
||||
|
||||
// Serializes the message without recomputing the size. The message must not
|
||||
// have changed since the last call to ByteSize(), and the value returned by
|
||||
// ByteSize must be non-negative. Otherwise the results are undefined.
|
||||
void SerializeWithCachedSizes(io::CodedOutputStream* output) const {
|
||||
output->SetCur(_InternalSerialize(output->Cur(), output->EpsCopy()));
|
||||
}
|
||||
|
||||
// Functions below here are not part of the public interface. It isn't
|
||||
// enforced, but they should be treated as private, and will be private
|
||||
// at some future time. Unfortunately the implementation of the "friend"
|
||||
// keyword in GCC is broken at the moment, but we expect it will be fixed.
|
||||
|
||||
// Like SerializeWithCachedSizes, but writes directly to *target, returning
|
||||
// a pointer to the byte immediately after the last byte written. "target"
|
||||
// must point at a byte array of at least ByteSize() bytes. Whether to use
|
||||
// deterministic serialization, e.g., maps in sorted order, is determined by
|
||||
// CodedOutputStream::IsDefaultSerializationDeterministic().
|
||||
uint8_t* SerializeWithCachedSizesToArray(uint8_t* target) const;
|
||||
|
||||
// Returns the result of the last call to ByteSize(). An embedded message's
|
||||
// size is needed both to serialize it (because embedded messages are
|
||||
// length-delimited) and to compute the outer message's size. Caching
|
||||
// the size avoids computing it multiple times.
|
||||
//
|
||||
// ByteSize() does not automatically use the cached size when available
|
||||
// because this would require invalidating it every time the message was
|
||||
// modified, which would be too hard and expensive. (E.g. if a deeply-nested
|
||||
// sub-message is changed, all of its parents' cached sizes would need to be
|
||||
// invalidated, which is too much work for an otherwise inlined setter
|
||||
// method.)
|
||||
virtual int GetCachedSize() const = 0;
|
||||
|
||||
virtual const char* _InternalParse(const char* /*ptr*/,
|
||||
internal::ParseContext* /*ctx*/) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
virtual void OnDemandRegisterArenaDtor(Arena* /*arena*/) {}
|
||||
|
||||
protected:
|
||||
template <typename T>
|
||||
static T* CreateMaybeMessage(Arena* arena) {
|
||||
return Arena::CreateMaybeMessage<T>(arena);
|
||||
}
|
||||
|
||||
inline explicit MessageLite(Arena* arena, bool is_message_owned = false)
|
||||
: _internal_metadata_(arena, is_message_owned) {}
|
||||
|
||||
// Returns the arena, if any, that directly owns this message and its internal
|
||||
// memory (Arena::Own is different in that the arena doesn't directly own the
|
||||
// internal memory). This method is used in proto's implementation for
|
||||
// swapping, moving and setting allocated, for deciding whether the ownership
|
||||
// of this message or its internal memory could be changed.
|
||||
Arena* GetOwningArena() const { return _internal_metadata_.owning_arena(); }
|
||||
|
||||
// Returns the arena, used for allocating internal objects(e.g., child
|
||||
// messages, etc), or owning incoming objects (e.g., set allocated).
|
||||
Arena* GetArenaForAllocation() const { return _internal_metadata_.arena(); }
|
||||
|
||||
// Returns true if this message is enabled for message-owned arena (MOA)
|
||||
// trials. No lite messages are eligible for MOA.
|
||||
static bool InMoaTrial() { return false; }
|
||||
|
||||
internal::InternalMetadata _internal_metadata_;
|
||||
|
||||
public:
|
||||
enum ParseFlags {
|
||||
kMerge = 0,
|
||||
kParse = 1,
|
||||
kMergePartial = 2,
|
||||
kParsePartial = 3,
|
||||
kMergeWithAliasing = 4,
|
||||
kParseWithAliasing = 5,
|
||||
kMergePartialWithAliasing = 6,
|
||||
kParsePartialWithAliasing = 7
|
||||
};
|
||||
|
||||
template <ParseFlags flags, typename T>
|
||||
bool ParseFrom(const T& input);
|
||||
|
||||
// Fast path when conditions match (ie. non-deterministic)
|
||||
// uint8_t* _InternalSerialize(uint8_t* ptr) const;
|
||||
virtual uint8_t* _InternalSerialize(
|
||||
uint8_t* ptr, io::EpsCopyOutputStream* stream) const = 0;
|
||||
|
||||
// Identical to IsInitialized() except that it logs an error message.
|
||||
bool IsInitializedWithErrors() const {
|
||||
if (IsInitialized()) return true;
|
||||
LogInitializationErrorMessage();
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class FastReflectionMessageMutator;
|
||||
friend class FastReflectionStringSetter;
|
||||
friend class Message;
|
||||
friend class Reflection;
|
||||
friend class internal::ExtensionSet;
|
||||
friend class internal::LazyField;
|
||||
friend class internal::SwapFieldHelper;
|
||||
friend class internal::TcParser;
|
||||
friend class internal::WeakFieldMap;
|
||||
friend class internal::WireFormatLite;
|
||||
|
||||
template <typename Type>
|
||||
friend class Arena::InternalHelper;
|
||||
template <typename Type>
|
||||
friend class internal::GenericTypeHandler;
|
||||
|
||||
void LogInitializationErrorMessage() const;
|
||||
|
||||
bool MergeFromImpl(io::CodedInputStream* input, ParseFlags parse_flags);
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageLite);
|
||||
};
|
||||
|
||||
namespace internal {
|
||||
|
||||
template <bool alias>
|
||||
bool MergeFromImpl(StringPiece input, MessageLite* msg,
|
||||
MessageLite::ParseFlags parse_flags);
|
||||
extern template bool MergeFromImpl<false>(StringPiece input,
|
||||
MessageLite* msg,
|
||||
MessageLite::ParseFlags parse_flags);
|
||||
extern template bool MergeFromImpl<true>(StringPiece input,
|
||||
MessageLite* msg,
|
||||
MessageLite::ParseFlags parse_flags);
|
||||
|
||||
template <bool alias>
|
||||
bool MergeFromImpl(io::ZeroCopyInputStream* input, MessageLite* msg,
|
||||
MessageLite::ParseFlags parse_flags);
|
||||
extern template bool MergeFromImpl<false>(io::ZeroCopyInputStream* input,
|
||||
MessageLite* msg,
|
||||
MessageLite::ParseFlags parse_flags);
|
||||
extern template bool MergeFromImpl<true>(io::ZeroCopyInputStream* input,
|
||||
MessageLite* msg,
|
||||
MessageLite::ParseFlags parse_flags);
|
||||
|
||||
struct BoundedZCIS {
|
||||
io::ZeroCopyInputStream* zcis;
|
||||
int limit;
|
||||
};
|
||||
|
||||
template <bool alias>
|
||||
bool MergeFromImpl(BoundedZCIS input, MessageLite* msg,
|
||||
MessageLite::ParseFlags parse_flags);
|
||||
extern template bool MergeFromImpl<false>(BoundedZCIS input, MessageLite* msg,
|
||||
MessageLite::ParseFlags parse_flags);
|
||||
extern template bool MergeFromImpl<true>(BoundedZCIS input, MessageLite* msg,
|
||||
MessageLite::ParseFlags parse_flags);
|
||||
|
||||
template <typename T>
|
||||
struct SourceWrapper;
|
||||
|
||||
template <bool alias, typename T>
|
||||
bool MergeFromImpl(const SourceWrapper<T>& input, MessageLite* msg,
|
||||
MessageLite::ParseFlags parse_flags) {
|
||||
return input.template MergeInto<alias>(msg, parse_flags);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
template <MessageLite::ParseFlags flags, typename T>
|
||||
bool MessageLite::ParseFrom(const T& input) {
|
||||
if (flags & kParse) Clear();
|
||||
constexpr bool alias = (flags & kMergeWithAliasing) != 0;
|
||||
return internal::MergeFromImpl<alias>(input, this, flags);
|
||||
}
|
||||
|
||||
// ===================================================================
|
||||
// Shutdown support.
|
||||
|
||||
|
||||
// Shut down the entire protocol buffers library, deleting all static-duration
|
||||
// objects allocated by the library or by generated .pb.cc files.
|
||||
//
|
||||
// There are two reasons you might want to call this:
|
||||
// * You use a draconian definition of "memory leak" in which you expect
|
||||
// every single malloc() to have a corresponding free(), even for objects
|
||||
// which live until program exit.
|
||||
// * You are writing a dynamically-loaded library which needs to clean up
|
||||
// after itself when the library is unloaded.
|
||||
//
|
||||
// It is safe to call this multiple times. However, it is not safe to use
|
||||
// any other part of the protocol buffers library after
|
||||
// ShutdownProtobufLibrary() has been called. Furthermore this call is not
|
||||
// thread safe, user needs to synchronize multiple calls.
|
||||
PROTOBUF_EXPORT void ShutdownProtobufLibrary();
|
||||
|
||||
namespace internal {
|
||||
|
||||
// Register a function to be called when ShutdownProtocolBuffers() is called.
|
||||
PROTOBUF_EXPORT void OnShutdown(void (*func)());
|
||||
// Run an arbitrary function on an arg
|
||||
PROTOBUF_EXPORT void OnShutdownRun(void (*f)(const void*), const void* arg);
|
||||
|
||||
template <typename T>
|
||||
T* OnShutdownDelete(T* p) {
|
||||
OnShutdownRun([](const void* pp) { delete static_cast<const T*>(pp); }, p);
|
||||
return p;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_MESSAGE_LITE_H__
|
||||
@@ -1,36 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_METADATA_H__
|
||||
#define GOOGLE_PROTOBUF_METADATA_H__
|
||||
|
||||
// TODO(b/151117630): Remove this file and all instances where it gets imported.
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_METADATA_H__
|
||||
@@ -1,316 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_METADATA_LITE_H__
|
||||
#define GOOGLE_PROTOBUF_METADATA_LITE_H__
|
||||
|
||||
#include <string>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/arena.h>
|
||||
#include <google/protobuf/port.h>
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
#ifdef SWIG
|
||||
#error "You cannot SWIG proto headers"
|
||||
#endif
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
// This is the representation for messages that support arena allocation. It
|
||||
// uses a tagged pointer to either store the owning Arena pointer, if there are
|
||||
// no unknown fields, or a pointer to a block of memory with both the owning
|
||||
// Arena pointer and the UnknownFieldSet, if there are unknown fields. Besides,
|
||||
// it also uses the tag to distinguish whether the owning Arena pointer is also
|
||||
// used by sub-structure allocation. This optimization allows for
|
||||
// "zero-overhead" storage of the Arena pointer, relative to the above baseline
|
||||
// implementation.
|
||||
//
|
||||
// The tagged pointer uses the least two significant bits to disambiguate cases.
|
||||
// It uses bit 0 == 0 to indicate an arena pointer and bit 0 == 1 to indicate a
|
||||
// UFS+Arena-container pointer. Besides it uses bit 1 == 0 to indicate arena
|
||||
// allocation and bit 1 == 1 to indicate heap allocation.
|
||||
class PROTOBUF_EXPORT InternalMetadata {
|
||||
public:
|
||||
constexpr InternalMetadata() : ptr_(0) {}
|
||||
explicit InternalMetadata(Arena* arena, bool is_message_owned = false) {
|
||||
SetArena(arena, is_message_owned);
|
||||
}
|
||||
|
||||
void SetArena(Arena* arena, bool is_message_owned) {
|
||||
ptr_ = is_message_owned
|
||||
? reinterpret_cast<intptr_t>(arena) | kMessageOwnedArenaTagMask
|
||||
: reinterpret_cast<intptr_t>(arena);
|
||||
GOOGLE_DCHECK(!is_message_owned || arena != nullptr);
|
||||
}
|
||||
|
||||
// To keep the ABI identical between debug and non-debug builds,
|
||||
// the destructor is always defined here even though it may delegate
|
||||
// to a non-inline private method.
|
||||
// (see https://github.com/protocolbuffers/protobuf/issues/9947)
|
||||
~InternalMetadata() {
|
||||
#if defined(NDEBUG) || defined(_MSC_VER)
|
||||
if (HasMessageOwnedArenaTag()) {
|
||||
delete reinterpret_cast<Arena*>(ptr_ - kMessageOwnedArenaTagMask);
|
||||
}
|
||||
#else
|
||||
CheckedDestruct();
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Delete() {
|
||||
// Note that Delete<> should be called not more than once.
|
||||
if (have_unknown_fields()) {
|
||||
DeleteOutOfLineHelper<T>();
|
||||
}
|
||||
}
|
||||
|
||||
// DeleteReturnArena will delete the unknown fields only if they weren't
|
||||
// allocated on an arena. Then it updates the flags so that if you call
|
||||
// have_unknown_fields(), it will return false. Finally, it returns the
|
||||
// current value of arena(). It is designed to be used as part of a
|
||||
// Message class's destructor call, so that when control eventually gets
|
||||
// to ~InternalMetadata(), we don't need to check for have_unknown_fields()
|
||||
// again.
|
||||
template <typename T>
|
||||
Arena* DeleteReturnArena() {
|
||||
if (have_unknown_fields()) {
|
||||
return DeleteOutOfLineHelper<T>();
|
||||
} else {
|
||||
return PtrValue<Arena>();
|
||||
}
|
||||
}
|
||||
|
||||
PROTOBUF_NDEBUG_INLINE Arena* owning_arena() const {
|
||||
return HasMessageOwnedArenaTag() ? nullptr : arena();
|
||||
}
|
||||
|
||||
PROTOBUF_NDEBUG_INLINE Arena* user_arena() const {
|
||||
Arena* a = arena();
|
||||
return a && !a->IsMessageOwned() ? a : nullptr;
|
||||
}
|
||||
|
||||
PROTOBUF_NDEBUG_INLINE Arena* arena() const {
|
||||
if (PROTOBUF_PREDICT_FALSE(have_unknown_fields())) {
|
||||
return PtrValue<ContainerBase>()->arena;
|
||||
} else {
|
||||
return PtrValue<Arena>();
|
||||
}
|
||||
}
|
||||
|
||||
PROTOBUF_NDEBUG_INLINE bool have_unknown_fields() const {
|
||||
return HasUnknownFieldsTag();
|
||||
}
|
||||
|
||||
PROTOBUF_NDEBUG_INLINE void* raw_arena_ptr() const {
|
||||
return reinterpret_cast<void*>(ptr_);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
PROTOBUF_NDEBUG_INLINE const T& unknown_fields(
|
||||
const T& (*default_instance)()) const {
|
||||
if (PROTOBUF_PREDICT_FALSE(have_unknown_fields())) {
|
||||
return PtrValue<Container<T>>()->unknown_fields;
|
||||
} else {
|
||||
return default_instance();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
PROTOBUF_NDEBUG_INLINE T* mutable_unknown_fields() {
|
||||
if (PROTOBUF_PREDICT_TRUE(have_unknown_fields())) {
|
||||
return &PtrValue<Container<T>>()->unknown_fields;
|
||||
} else {
|
||||
return mutable_unknown_fields_slow<T>();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
PROTOBUF_NDEBUG_INLINE void Swap(InternalMetadata* other) {
|
||||
// Semantics here are that we swap only the unknown fields, not the arena
|
||||
// pointer. We cannot simply swap ptr_ with other->ptr_ because we need to
|
||||
// maintain our own arena ptr. Also, our ptr_ and other's ptr_ may be in
|
||||
// different states (direct arena pointer vs. container with UFS) so we
|
||||
// cannot simply swap ptr_ and then restore the arena pointers. We reuse
|
||||
// UFS's swap implementation instead.
|
||||
if (have_unknown_fields() || other->have_unknown_fields()) {
|
||||
DoSwap<T>(other->mutable_unknown_fields<T>());
|
||||
}
|
||||
}
|
||||
|
||||
PROTOBUF_NDEBUG_INLINE void InternalSwap(InternalMetadata* other) {
|
||||
std::swap(ptr_, other->ptr_);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
PROTOBUF_NDEBUG_INLINE void MergeFrom(const InternalMetadata& other) {
|
||||
if (other.have_unknown_fields()) {
|
||||
DoMergeFrom<T>(other.unknown_fields<T>(nullptr));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
PROTOBUF_NDEBUG_INLINE void Clear() {
|
||||
if (have_unknown_fields()) {
|
||||
DoClear<T>();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
intptr_t ptr_;
|
||||
|
||||
// Tagged pointer implementation.
|
||||
static constexpr intptr_t kUnknownFieldsTagMask = 1;
|
||||
static constexpr intptr_t kMessageOwnedArenaTagMask = 2;
|
||||
static constexpr intptr_t kPtrTagMask =
|
||||
kUnknownFieldsTagMask | kMessageOwnedArenaTagMask;
|
||||
static constexpr intptr_t kPtrValueMask = ~kPtrTagMask;
|
||||
|
||||
// Accessors for pointer tag and pointer value.
|
||||
PROTOBUF_ALWAYS_INLINE bool HasUnknownFieldsTag() const {
|
||||
return ptr_ & kUnknownFieldsTagMask;
|
||||
}
|
||||
PROTOBUF_ALWAYS_INLINE bool HasMessageOwnedArenaTag() const {
|
||||
return ptr_ & kMessageOwnedArenaTagMask;
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
U* PtrValue() const {
|
||||
return reinterpret_cast<U*>(ptr_ & kPtrValueMask);
|
||||
}
|
||||
|
||||
// If ptr_'s tag is kTagContainer, it points to an instance of this struct.
|
||||
struct ContainerBase {
|
||||
Arena* arena;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct Container : public ContainerBase {
|
||||
T unknown_fields;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
PROTOBUF_NOINLINE Arena* DeleteOutOfLineHelper() {
|
||||
if (auto* a = arena()) {
|
||||
// Subtle: we want to preserve the message-owned arena flag, while at the
|
||||
// same time replacing the pointer to Container<T> with a pointer to the
|
||||
// arena.
|
||||
intptr_t message_owned_arena_tag = ptr_ & kMessageOwnedArenaTagMask;
|
||||
ptr_ = reinterpret_cast<intptr_t>(a) | message_owned_arena_tag;
|
||||
return a;
|
||||
} else {
|
||||
delete PtrValue<Container<T>>();
|
||||
ptr_ = 0;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
PROTOBUF_NOINLINE T* mutable_unknown_fields_slow() {
|
||||
Arena* my_arena = arena();
|
||||
Container<T>* container = Arena::Create<Container<T>>(my_arena);
|
||||
intptr_t message_owned_arena_tag = ptr_ & kMessageOwnedArenaTagMask;
|
||||
// Two-step assignment works around a bug in clang's static analyzer:
|
||||
// https://bugs.llvm.org/show_bug.cgi?id=34198.
|
||||
ptr_ = reinterpret_cast<intptr_t>(container);
|
||||
ptr_ |= kUnknownFieldsTagMask | message_owned_arena_tag;
|
||||
container->arena = my_arena;
|
||||
return &(container->unknown_fields);
|
||||
}
|
||||
|
||||
// Templated functions.
|
||||
|
||||
template <typename T>
|
||||
PROTOBUF_NOINLINE void DoClear() {
|
||||
mutable_unknown_fields<T>()->Clear();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
PROTOBUF_NOINLINE void DoMergeFrom(const T& other) {
|
||||
mutable_unknown_fields<T>()->MergeFrom(other);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
PROTOBUF_NOINLINE void DoSwap(T* other) {
|
||||
mutable_unknown_fields<T>()->Swap(other);
|
||||
}
|
||||
|
||||
// Private helper with debug checks for ~InternalMetadata()
|
||||
void CheckedDestruct();
|
||||
};
|
||||
|
||||
// String Template specializations.
|
||||
|
||||
template <>
|
||||
PROTOBUF_EXPORT void InternalMetadata::DoClear<std::string>();
|
||||
template <>
|
||||
PROTOBUF_EXPORT void InternalMetadata::DoMergeFrom<std::string>(
|
||||
const std::string& other);
|
||||
template <>
|
||||
PROTOBUF_EXPORT void InternalMetadata::DoSwap<std::string>(std::string* other);
|
||||
|
||||
// This helper RAII class is needed to efficiently parse unknown fields. We
|
||||
// should only call mutable_unknown_fields if there are actual unknown fields.
|
||||
// The obvious thing to just use a stack string and swap it at the end of
|
||||
// the parse won't work, because the destructor of StringOutputStream needs to
|
||||
// be called before we can modify the string (it check-fails). Using
|
||||
// LiteUnknownFieldSetter setter(&_internal_metadata_);
|
||||
// StringOutputStream stream(setter.buffer());
|
||||
// guarantees that the string is only swapped after stream is destroyed.
|
||||
class PROTOBUF_EXPORT LiteUnknownFieldSetter {
|
||||
public:
|
||||
explicit LiteUnknownFieldSetter(InternalMetadata* metadata)
|
||||
: metadata_(metadata) {
|
||||
if (metadata->have_unknown_fields()) {
|
||||
buffer_.swap(*metadata->mutable_unknown_fields<std::string>());
|
||||
}
|
||||
}
|
||||
~LiteUnknownFieldSetter() {
|
||||
if (!buffer_.empty())
|
||||
metadata_->mutable_unknown_fields<std::string>()->swap(buffer_);
|
||||
}
|
||||
std::string* buffer() { return &buffer_; }
|
||||
|
||||
private:
|
||||
InternalMetadata* metadata_;
|
||||
std::string buffer_;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_METADATA_LITE_H__
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,80 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// A common header that is included across all protobuf headers. We do our best
|
||||
// to avoid #defining any macros here; instead we generally put macros in
|
||||
// port_def.inc and port_undef.inc so they are not visible from outside of
|
||||
// protobuf.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_PORT_H__
|
||||
#define GOOGLE_PROTOBUF_PORT_H__
|
||||
|
||||
#include <cstddef>
|
||||
#include <new>
|
||||
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
inline void SizedDelete(void* p, size_t size) {
|
||||
#if defined(__cpp_sized_deallocation)
|
||||
::operator delete(p, size);
|
||||
#else
|
||||
::operator delete(p);
|
||||
#endif
|
||||
}
|
||||
inline void SizedArrayDelete(void* p, size_t size) {
|
||||
#if defined(__cpp_sized_deallocation)
|
||||
::operator delete[](p, size);
|
||||
#else
|
||||
::operator delete[](p);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Tag type used to invoke the constinit constructor overload of classes
|
||||
// such as ArenaStringPtr and MapFieldBase. Such constructors are internal
|
||||
// implementation details of the library.
|
||||
struct ConstantInitialized {
|
||||
explicit ConstantInitialized() = default;
|
||||
};
|
||||
|
||||
// Tag type used to invoke the arena constructor overload of classes such
|
||||
// as ExtensionSet and MapFieldLite in aggregate initialization. These
|
||||
// classes typically don't have move/copy constructors, which rules out
|
||||
// explicit initialization in pre-C++17.
|
||||
struct ArenaInitialized {
|
||||
explicit ArenaInitialized() = default;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_PORT_H__
|
||||
@@ -1,928 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// This file defines common macros that are used in protobuf.
|
||||
//
|
||||
// To hide these definitions from the outside world (and to prevent collisions
|
||||
// if more than one version of protobuf is #included in the same project) you
|
||||
// must follow this pattern when #including port_def.inc in a header file:
|
||||
//
|
||||
// #include "other_header.h"
|
||||
// #include "message.h"
|
||||
// // etc.
|
||||
//
|
||||
// #include "port_def.inc" // MUST be last header included
|
||||
//
|
||||
// // Definitions for this header.
|
||||
//
|
||||
// #include "port_undef.inc"
|
||||
//
|
||||
// This is a textual header with no include guard, because we want to
|
||||
// detect/prohibit anytime it is #included twice without a corresponding
|
||||
// #undef.
|
||||
|
||||
// The definitions in this file are intended to be portable across Clang,
|
||||
// GCC, and MSVC. Function-like macros are usable without an #ifdef guard.
|
||||
// Syntax macros (for example, attributes) are always defined, although
|
||||
// they may be empty.
|
||||
//
|
||||
// Some definitions rely on the NDEBUG macro and/or (in MSVC) _DEBUG:
|
||||
// - https://en.cppreference.com/w/c/error/assert
|
||||
// - https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros#microsoft-specific-predefined-macros
|
||||
//
|
||||
// References for predefined macros:
|
||||
// - Standard: https://en.cppreference.com/w/cpp/preprocessor/replace
|
||||
// - Clang: https://clang.llvm.org/docs/LanguageExtensions.html
|
||||
// (see also GCC predefined macros)
|
||||
// - GCC: https://gcc.gnu.org/onlinedocs/cpp/Predefined-Macros.html
|
||||
// - MSVC: https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros
|
||||
// - Interactive (Clang/GCC only): https://www.compiler-explorer.com/z/hc6jKd3sj
|
||||
//
|
||||
// References for attributes (and extension attributes):
|
||||
// - Standard: https://en.cppreference.com/w/cpp/language/attributes
|
||||
// - Clang: https://clang.llvm.org/docs/AttributeReference.html
|
||||
// - GCC: https://gcc.gnu.org/onlinedocs/gcc/Attribute-Syntax.html
|
||||
// (see Clang attribute docs as well)
|
||||
//
|
||||
// References for standard C++ language conformance (and minimum versions):
|
||||
// - Clang: https://clang.llvm.org/cxx_status.html
|
||||
// - GCC: https://gcc.gnu.org/projects/cxx-status.html
|
||||
// - MSVC: https://docs.microsoft.com/en-us/cpp/overview/visual-cpp-language-conformance
|
||||
//
|
||||
// Historical release notes (which can help to determine minimum versions):
|
||||
// - Clang: https://releases.llvm.org/
|
||||
// - GCC: https://gcc.gnu.org/releases.html
|
||||
// - MSVC: https://docs.microsoft.com/en-us/visualstudio/releases/2019/release-notes-history
|
||||
// https://docs.microsoft.com/en-us/visualstudio/releasenotes/vs2017-relnotes-history
|
||||
|
||||
// Portable fallbacks for C++20 feature test macros:
|
||||
// https://en.cppreference.com/w/cpp/feature_test
|
||||
#ifndef __has_cpp_attribute
|
||||
#define __has_cpp_attribute(x) 0
|
||||
#define PROTOBUF_has_cpp_attribute_DEFINED_
|
||||
#endif
|
||||
|
||||
// Portable fallback for Clang's __has_feature macro:
|
||||
// https://clang.llvm.org/docs/LanguageExtensions.html#has-feature-and-has-extension
|
||||
#ifndef __has_feature
|
||||
#define __has_feature(x) 0
|
||||
#define PROTOBUF_has_feature_DEFINED_
|
||||
#endif
|
||||
|
||||
// Portable fallback for Clang's __has_warning macro:
|
||||
#ifndef __has_warning
|
||||
#define __has_warning(x) 0
|
||||
#define PROTOBUF_has_warning_DEFINED_
|
||||
#endif
|
||||
|
||||
// Portable fallbacks for the __has_attribute macro (GCC and Clang):
|
||||
// https://clang.llvm.org/docs/LanguageExtensions.html#has-attribute
|
||||
// https://gcc.gnu.org/onlinedocs/cpp/_005f_005fhas_005fattribute.html
|
||||
#ifndef __has_attribute
|
||||
#define __has_attribute(x) 0
|
||||
#define PROTOBUF_has_attribute_DEFINED_
|
||||
#endif
|
||||
|
||||
// Portable fallback for __has_builtin (GCC and Clang):
|
||||
// https://clang.llvm.org/docs/LanguageExtensions.html#has-builtin
|
||||
// https://gcc.gnu.org/onlinedocs/cpp/_005f_005fhas_005fbuiltin.html
|
||||
#ifndef __has_builtin
|
||||
#define __has_builtin(x) 0
|
||||
#define PROTOBUF_has_builtin_DEFINED_
|
||||
#endif
|
||||
|
||||
// Portable PROTOBUF_BUILTIN_BSWAPxx definitions
|
||||
// Code must check for availability, e.g.: `defined(PROTOBUF_BUILTIN_BSWAP32)`
|
||||
#ifdef PROTOBUF_BUILTIN_BSWAP16
|
||||
#error PROTOBUF_BUILTIN_BSWAP16 was previously defined
|
||||
#endif
|
||||
#ifdef PROTOBUF_BUILTIN_BSWAP32
|
||||
#error PROTOBUF_BUILTIN_BSWAP32 was previously defined
|
||||
#endif
|
||||
#ifdef PROTOBUF_BUILTIN_BSWAP64
|
||||
#error PROTOBUF_BUILTIN_BSWAP64 was previously defined
|
||||
#endif
|
||||
#if defined(__GNUC__) || __has_builtin(__builtin_bswap16)
|
||||
#define PROTOBUF_BUILTIN_BSWAP16(x) __builtin_bswap16(x)
|
||||
#endif
|
||||
#if defined(__GNUC__) || __has_builtin(__builtin_bswap32)
|
||||
#define PROTOBUF_BUILTIN_BSWAP32(x) __builtin_bswap32(x)
|
||||
#endif
|
||||
#if defined(__GNUC__) || __has_builtin(__builtin_bswap64)
|
||||
#define PROTOBUF_BUILTIN_BSWAP64(x) __builtin_bswap64(x)
|
||||
#endif
|
||||
|
||||
// Portable check for GCC minimum version:
|
||||
// https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html
|
||||
#if defined(__GNUC__) && defined(__GNUC_MINOR__) \
|
||||
&& defined(__GNUC_PATCHLEVEL__)
|
||||
# define PROTOBUF_GNUC_MIN(x, y) \
|
||||
(__GNUC__ > (x) || __GNUC__ == (x) && __GNUC_MINOR__ >= (y))
|
||||
#else
|
||||
# define PROTOBUF_GNUC_MIN(x, y) 0
|
||||
#endif
|
||||
|
||||
// Portable check for MSVC minimum version:
|
||||
// https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros
|
||||
#if defined(_MSC_VER)
|
||||
#define PROTOBUF_MSC_VER_MIN(x) (_MSC_VER >= x)
|
||||
#else
|
||||
#define PROTOBUF_MSC_VER_MIN(x) 0
|
||||
#endif
|
||||
|
||||
// Portable check for minimum C++ language version:
|
||||
// https://en.cppreference.com/w/cpp/preprocessor/replace
|
||||
// https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros
|
||||
#if !defined(_MSVC_LANG)
|
||||
#define PROTOBUF_CPLUSPLUS_MIN(x) (__cplusplus >= x)
|
||||
#else
|
||||
#define PROTOBUF_CPLUSPLUS_MIN(x) (_MSVC_LANG >= x)
|
||||
#endif
|
||||
|
||||
// Future versions of protobuf will include breaking changes to some APIs.
|
||||
// This macro can be set to enable these API changes ahead of time, so that
|
||||
// user code can be updated before upgrading versions of protobuf.
|
||||
// PROTOBUF_FUTURE_FINAL is used on classes that are historically not marked as
|
||||
// final, but that may be marked final in future (breaking) releases.
|
||||
// #define PROTOBUF_FUTURE_BREAKING_CHANGES 1
|
||||
// #define PROTOBUF_FUTURE_FINAL final
|
||||
#define PROTOBUF_FUTURE_FINAL
|
||||
|
||||
#ifdef PROTOBUF_VERSION
|
||||
#error PROTOBUF_VERSION was previously defined
|
||||
#endif
|
||||
#define PROTOBUF_VERSION 3021012
|
||||
|
||||
#ifdef PROTOBUF_MIN_HEADER_VERSION_FOR_PROTOC
|
||||
#error PROTOBUF_MIN_HEADER_VERSION_FOR_PROTOC was previously defined
|
||||
#endif
|
||||
#define PROTOBUF_MIN_HEADER_VERSION_FOR_PROTOC 3021000
|
||||
|
||||
#ifdef PROTOBUF_MIN_PROTOC_VERSION
|
||||
#error PROTOBUF_MIN_PROTOC_VERSION was previously defined
|
||||
#endif
|
||||
#define PROTOBUF_MIN_PROTOC_VERSION 3021000
|
||||
|
||||
#ifdef PROTOBUF_VERSION_SUFFIX
|
||||
#error PROTOBUF_VERSION_SUFFIX was previously defined
|
||||
#endif
|
||||
#define PROTOBUF_VERSION_SUFFIX ""
|
||||
|
||||
#if defined(PROTOBUF_NAMESPACE) || defined(PROTOBUF_NAMESPACE_ID)
|
||||
#error PROTOBUF_NAMESPACE or PROTOBUF_NAMESPACE_ID was previously defined
|
||||
#endif
|
||||
#define PROTOBUF_NAMESPACE "google::protobuf"
|
||||
#define PROTOBUF_NAMESPACE_ID google::protobuf
|
||||
#define PROTOBUF_NAMESPACE_OPEN \
|
||||
namespace google { \
|
||||
namespace protobuf {
|
||||
#define PROTOBUF_NAMESPACE_CLOSE \
|
||||
} /* namespace protobuf */ \
|
||||
} /* namespace google */
|
||||
|
||||
#ifdef PROTOBUF_ALWAYS_INLINE
|
||||
#error PROTOBUF_ALWAYS_INLINE was previously defined
|
||||
#endif
|
||||
// For functions we want to force inline.
|
||||
#if defined(PROTOBUF_NO_INLINE)
|
||||
# define PROTOBUF_ALWAYS_INLINE
|
||||
#elif PROTOBUF_GNUC_MIN(3, 1)
|
||||
# define PROTOBUF_ALWAYS_INLINE __attribute__((always_inline))
|
||||
#elif defined(_MSC_VER)
|
||||
# define PROTOBUF_ALWAYS_INLINE __forceinline
|
||||
#else
|
||||
# define PROTOBUF_ALWAYS_INLINE
|
||||
#endif
|
||||
|
||||
#ifdef PROTOBUF_NDEBUG_INLINE
|
||||
#error PROTOBUF_NDEBUG_INLINE was previously defined
|
||||
#endif
|
||||
// Avoid excessive inlining in non-optimized builds. Without other optimizations
|
||||
// the inlining is not going to provide benefits anyway and the huge resulting
|
||||
// functions, especially in the proto-generated serialization functions, produce
|
||||
// stack frames so large that many tests run into stack overflows (b/32192897).
|
||||
#if defined(NDEBUG) || (defined(_MSC_VER) && !defined(_DEBUG))
|
||||
# define PROTOBUF_NDEBUG_INLINE PROTOBUF_ALWAYS_INLINE
|
||||
#else
|
||||
# define PROTOBUF_NDEBUG_INLINE
|
||||
#endif
|
||||
|
||||
// Note that PROTOBUF_NOINLINE is an attribute applied to functions, to prevent
|
||||
// them from being inlined by the compiler. This is different from
|
||||
// PROTOBUF_NO_INLINE, which is a user-supplied macro that disables forced
|
||||
// inlining by PROTOBUF_(ALWAYS|NDEBUG)_INLINE.
|
||||
#ifdef PROTOBUF_NOINLINE
|
||||
#error PROTOBUF_NOINLINE was previously defined
|
||||
#endif
|
||||
#if PROTOBUF_GNUC_MIN(3, 1)
|
||||
# define PROTOBUF_NOINLINE __attribute__((noinline))
|
||||
#elif defined(_MSC_VER)
|
||||
// Seems to have been around since at least Visual Studio 2005
|
||||
# define PROTOBUF_NOINLINE __declspec(noinline)
|
||||
#endif
|
||||
|
||||
#ifdef PROTOBUF_MUSTTAIL
|
||||
#error PROTOBUF_MUSTTAIL was previously defined
|
||||
#endif
|
||||
#ifdef PROTOBUF_TAILCALL
|
||||
#error PROTOBUF_TAILCALL was previously defined
|
||||
#endif
|
||||
#if __has_cpp_attribute(clang::musttail) && !defined(__arm__) && \
|
||||
!defined(_ARCH_PPC) && !defined(__wasm__) && \
|
||||
!(defined(_MSC_VER) && defined(_M_IX86)) && \
|
||||
!(defined(__NDK_MAJOR__) && __NDK_MAJOR <= 24)
|
||||
# ifndef PROTO2_OPENSOURCE
|
||||
// Compilation fails on ARM32: b/195943306
|
||||
// Compilation fails on powerpc64le: b/187985113
|
||||
// Compilation fails on X86 Windows:
|
||||
// https://github.com/llvm/llvm-project/issues/53271
|
||||
# endif
|
||||
#define PROTOBUF_MUSTTAIL [[clang::musttail]]
|
||||
#define PROTOBUF_TAILCALL true
|
||||
#else
|
||||
#define PROTOBUF_MUSTTAIL
|
||||
#define PROTOBUF_TAILCALL false
|
||||
#endif
|
||||
|
||||
#ifdef PROTOBUF_EXCLUSIVE_LOCKS_REQUIRED
|
||||
#error PROTOBUF_EXCLUSIVE_LOCKS_REQUIRED was previously defined
|
||||
#endif
|
||||
#if __has_attribute(exclusive_locks_required)
|
||||
#define PROTOBUF_EXCLUSIVE_LOCKS_REQUIRED(...) \
|
||||
__attribute__((exclusive_locks_required(__VA_ARGS__)))
|
||||
#else
|
||||
#define PROTOBUF_EXCLUSIVE_LOCKS_REQUIRED(...)
|
||||
#endif
|
||||
|
||||
#ifdef PROTOBUF_NO_THREAD_SAFETY_ANALYSIS
|
||||
#error PROTOBUF_NO_THREAD_SAFETY_ANALYSIS was previously defined
|
||||
#endif
|
||||
#if __has_attribute(no_thread_safety_analysis)
|
||||
#define PROTOBUF_NO_THREAD_SAFETY_ANALYSIS \
|
||||
__attribute__((no_thread_safety_analysis))
|
||||
#else
|
||||
#define PROTOBUF_NO_THREAD_SAFETY_ANALYSIS
|
||||
#endif
|
||||
|
||||
#ifdef PROTOBUF_GUARDED_BY
|
||||
#error PROTOBUF_GUARDED_BY was previously defined
|
||||
#endif
|
||||
#if __has_attribute(guarded_by)
|
||||
#define PROTOBUF_GUARDED_BY(x) __attribute__((guarded_by(x)))
|
||||
#else
|
||||
#define PROTOBUF_GUARDED_BY(x)
|
||||
#endif
|
||||
|
||||
#ifdef PROTOBUF_LOCKS_EXCLUDED
|
||||
#error PROTOBUF_LOCKS_EXCLUDED was previously defined
|
||||
#endif
|
||||
#if __has_attribute(locks_excluded)
|
||||
#define PROTOBUF_LOCKS_EXCLUDED(...) \
|
||||
__attribute__((locks_excluded(__VA_ARGS__)))
|
||||
#else
|
||||
#define PROTOBUF_LOCKS_EXCLUDED(...)
|
||||
#endif
|
||||
|
||||
#ifdef PROTOBUF_COLD
|
||||
#error PROTOBUF_COLD was previously defined
|
||||
#endif
|
||||
#if __has_attribute(cold) || PROTOBUF_GNUC_MIN(4, 3)
|
||||
# define PROTOBUF_COLD __attribute__((cold))
|
||||
#else
|
||||
# define PROTOBUF_COLD
|
||||
#endif
|
||||
|
||||
#ifdef PROTOBUF_SECTION_VARIABLE
|
||||
#error PROTOBUF_SECTION_VARIABLE was previously defined
|
||||
#endif
|
||||
#if (__has_attribute(section) || defined(__GNUC__)) && defined(__ELF__)
|
||||
// Place a variable in the given ELF section.
|
||||
# define PROTOBUF_SECTION_VARIABLE(x) __attribute__((section(#x)))
|
||||
#else
|
||||
# define PROTOBUF_SECTION_VARIABLE(x)
|
||||
#endif
|
||||
|
||||
#if defined(PROTOBUF_DEPRECATED)
|
||||
#error PROTOBUF_DEPRECATED was previously defined
|
||||
#endif
|
||||
#if defined(PROTOBUF_DEPRECATED_MSG)
|
||||
#error PROTOBUF_DEPRECATED_MSG was previously defined
|
||||
#endif
|
||||
#if __has_attribute(deprecated) || PROTOBUF_GNUC_MIN(3, 0)
|
||||
# define PROTOBUF_DEPRECATED __attribute__((deprecated))
|
||||
# define PROTOBUF_DEPRECATED_MSG(msg) __attribute__((deprecated(msg)))
|
||||
#elif defined(_MSC_VER)
|
||||
# define PROTOBUF_DEPRECATED __declspec(deprecated)
|
||||
# define PROTOBUF_DEPRECATED_MSG(msg) __declspec(deprecated(msg))
|
||||
#else
|
||||
# define PROTOBUF_DEPRECATED
|
||||
# define PROTOBUF_DEPRECATED_MSG(msg)
|
||||
#endif
|
||||
|
||||
#if defined(PROTOBUF_DEPRECATED_ENUM)
|
||||
#error PROTOBUF_DEPRECATED_ENUM was previously defined
|
||||
#endif
|
||||
#if defined(__clang__) || PROTOBUF_GNUC_MIN(6, 0)
|
||||
// https://gcc.gnu.org/gcc-6/changes.html
|
||||
# define PROTOBUF_DEPRECATED_ENUM __attribute__((deprecated))
|
||||
#else
|
||||
# define PROTOBUF_DEPRECATED_ENUM
|
||||
#endif
|
||||
|
||||
#ifdef PROTOBUF_FUNC_ALIGN
|
||||
#error PROTOBUF_FUNC_ALIGN was previously defined
|
||||
#endif
|
||||
#if __has_attribute(aligned) || PROTOBUF_GNUC_MIN(4, 3)
|
||||
#define PROTOBUF_FUNC_ALIGN(bytes) __attribute__((aligned(bytes)))
|
||||
#else
|
||||
#define PROTOBUF_FUNC_ALIGN(bytes)
|
||||
#endif
|
||||
|
||||
#ifdef PROTOBUF_RETURNS_NONNULL
|
||||
#error PROTOBUF_RETURNS_NONNULL was previously defined
|
||||
#endif
|
||||
#if __has_attribute(returns_nonnull) || PROTOBUF_GNUC_MIN(4, 9)
|
||||
#define PROTOBUF_RETURNS_NONNULL __attribute__((returns_nonnull))
|
||||
#else
|
||||
#define PROTOBUF_RETURNS_NONNULL
|
||||
#endif
|
||||
|
||||
#ifdef PROTOBUF_ATTRIBUTE_REINITIALIZES
|
||||
#error PROTOBUF_ATTRIBUTE_REINITIALIZES was previously defined
|
||||
#endif
|
||||
#if __has_cpp_attribute(clang::reinitializes)
|
||||
#define PROTOBUF_ATTRIBUTE_REINITIALIZES [[clang::reinitializes]]
|
||||
#else
|
||||
#define PROTOBUF_ATTRIBUTE_REINITIALIZES
|
||||
#endif
|
||||
|
||||
// The minimum library version which works with the current version of the
|
||||
// headers.
|
||||
#define GOOGLE_PROTOBUF_MIN_LIBRARY_VERSION 3021000
|
||||
|
||||
#ifdef PROTOBUF_RTTI
|
||||
#error PROTOBUF_RTTI was previously defined
|
||||
#endif
|
||||
#if defined(GOOGLE_PROTOBUF_NO_RTTI) && GOOGLE_PROTOBUF_NO_RTTI
|
||||
// A user-provided definition GOOGLE_PROTOBUF_NO_RTTI=1 disables RTTI.
|
||||
#define PROTOBUF_RTTI 0
|
||||
#elif defined(__cpp_rtti)
|
||||
// https://en.cppreference.com/w/cpp/feature_test
|
||||
#define PROTOBUF_RTTI 1
|
||||
#elif __has_feature(cxx_rtti)
|
||||
// https://clang.llvm.org/docs/LanguageExtensions.html#c-rtti
|
||||
#define PROTOBUF_RTTI 1
|
||||
#elif defined(__GXX_RTTI)
|
||||
// https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html
|
||||
#define PROTOBUF_RTTI 1
|
||||
#elif defined(_CPPRTTI)
|
||||
// https://docs.microsoft.com/en-us/cpp/build/reference/gr-enable-run-time-type-information
|
||||
#define PROTOBUF_RTTI 1
|
||||
#else
|
||||
#define PROTOBUF_RTTI 0
|
||||
#endif
|
||||
|
||||
// Returns the offset of the given field within the given aggregate type.
|
||||
// This is equivalent to the ANSI C offsetof() macro. However, according
|
||||
// to the C++ standard, offsetof() only works on POD types, and GCC
|
||||
// enforces this requirement with a warning. In practice, this rule is
|
||||
// unnecessarily strict; there is probably no compiler or platform on
|
||||
// which the offsets of the direct fields of a class are non-constant.
|
||||
// Fields inherited from superclasses *can* have non-constant offsets,
|
||||
// but that's not what this macro will be used for.
|
||||
#ifdef PROTOBUF_FIELD_OFFSET
|
||||
#error PROTOBUF_FIELD_OFFSET was previously defined
|
||||
#endif
|
||||
#if defined(__clang__)
|
||||
// For Clang we use __builtin_offsetof() and suppress the warning,
|
||||
// to avoid Control Flow Integrity and UBSan vptr sanitizers from
|
||||
// crashing while trying to validate the invalid reinterpret_casts.
|
||||
#define PROTOBUF_FIELD_OFFSET(TYPE, FIELD) \
|
||||
_Pragma("clang diagnostic push") \
|
||||
_Pragma("clang diagnostic ignored \"-Winvalid-offsetof\"") \
|
||||
__builtin_offsetof(TYPE, FIELD) \
|
||||
_Pragma("clang diagnostic pop")
|
||||
#elif PROTOBUF_GNUC_MIN(4, 8)
|
||||
#define PROTOBUF_FIELD_OFFSET(TYPE, FIELD) __builtin_offsetof(TYPE, FIELD)
|
||||
#else // defined(__clang__)
|
||||
// Note that we calculate relative to the pointer value 16 here since if we
|
||||
// just use zero, GCC complains about dereferencing a NULL pointer. We
|
||||
// choose 16 rather than some other number just in case the compiler would
|
||||
// be confused by an unaligned pointer.
|
||||
#define PROTOBUF_FIELD_OFFSET(TYPE, FIELD) \
|
||||
static_cast< ::uint32_t>(reinterpret_cast<const char*>( \
|
||||
&reinterpret_cast<const TYPE*>(16)->FIELD) - \
|
||||
reinterpret_cast<const char*>(16))
|
||||
#endif
|
||||
|
||||
#ifdef PROTOBUF_EXPORT
|
||||
#error PROTOBUF_EXPORT was previously defined
|
||||
#endif
|
||||
|
||||
#if defined(PROTOBUF_USE_DLLS) && defined(_MSC_VER)
|
||||
# if defined(LIBPROTOBUF_EXPORTS)
|
||||
# define PROTOBUF_EXPORT __declspec(dllexport)
|
||||
# define PROTOBUF_EXPORT_TEMPLATE_DECLARE
|
||||
# define PROTOBUF_EXPORT_TEMPLATE_DEFINE __declspec(dllexport)
|
||||
# else
|
||||
# define PROTOBUF_EXPORT __declspec(dllimport)
|
||||
# define PROTOBUF_EXPORT_TEMPLATE_DECLARE
|
||||
# define PROTOBUF_EXPORT_TEMPLATE_DEFINE __declspec(dllimport)
|
||||
# endif // defined(LIBPROTOBUF_EXPORTS)
|
||||
#elif defined(PROTOBUF_USE_DLLS) && defined(LIBPROTOBUF_EXPORTS)
|
||||
# define PROTOBUF_EXPORT __attribute__((visibility("default")))
|
||||
# define PROTOBUF_EXPORT_TEMPLATE_DECLARE __attribute__((visibility("default")))
|
||||
# define PROTOBUF_EXPORT_TEMPLATE_DEFINE
|
||||
#else
|
||||
# define PROTOBUF_EXPORT
|
||||
# define PROTOBUF_EXPORT_TEMPLATE_DECLARE
|
||||
# define PROTOBUF_EXPORT_TEMPLATE_DEFINE
|
||||
#endif
|
||||
|
||||
#ifdef PROTOC_EXPORT
|
||||
#error PROTOC_EXPORT was previously defined
|
||||
#endif
|
||||
|
||||
#if defined(PROTOBUF_USE_DLLS) && defined(_MSC_VER)
|
||||
# if defined(LIBPROTOC_EXPORTS)
|
||||
# define PROTOC_EXPORT __declspec(dllexport)
|
||||
# else
|
||||
# define PROTOC_EXPORT __declspec(dllimport)
|
||||
# endif // defined(LIBPROTOC_EXPORTS)
|
||||
#elif defined(PROTOBUF_USE_DLLS) && defined(LIBPROTOC_EXPORTS)
|
||||
# define PROTOC_EXPORT __attribute__((visibility("default")))
|
||||
#else
|
||||
# define PROTOC_EXPORT
|
||||
#endif
|
||||
|
||||
#if defined(PROTOBUF_PREDICT_TRUE) || defined(PROTOBUF_PREDICT_FALSE)
|
||||
#error PROTOBUF_PREDICT_(TRUE|FALSE) was previously defined
|
||||
#endif
|
||||
#if PROTOBUF_GNUC_MIN(3, 0)
|
||||
# define PROTOBUF_PREDICT_TRUE(x) (__builtin_expect(false || (x), true))
|
||||
# define PROTOBUF_PREDICT_FALSE(x) (__builtin_expect(false || (x), false))
|
||||
#else
|
||||
# define PROTOBUF_PREDICT_TRUE(x) (x)
|
||||
# define PROTOBUF_PREDICT_FALSE(x) (x)
|
||||
#endif
|
||||
|
||||
#ifdef PROTOBUF_NODISCARD
|
||||
#error PROTOBUF_NODISCARD was previously defined
|
||||
#endif
|
||||
#if __has_cpp_attribute(nodiscard) && PROTOBUF_CPLUSPLUS_MIN(201703L)
|
||||
#define PROTOBUF_NODISCARD [[nodiscard]]
|
||||
#elif __has_attribute(warn_unused_result) || PROTOBUF_GNUC_MIN(4, 8)
|
||||
#define PROTOBUF_NODISCARD __attribute__((warn_unused_result))
|
||||
#else
|
||||
#define PROTOBUF_NODISCARD
|
||||
#endif
|
||||
|
||||
// Enable all stable experiments if this flag is set. This allows us to group
|
||||
// all of these experiments under a single build flag, which can be enabled in
|
||||
// the protobuf.stable-experiments TAP project.
|
||||
#ifdef PROTOBUF_ENABLE_STABLE_EXPERIMENTS
|
||||
#define PROTOBUF_FORCE_MESSAGE_OWNED_ARENA
|
||||
#endif // !PROTOBUF_ENABLE_STABLE_EXPERIMENTS
|
||||
|
||||
#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE
|
||||
#error PROTOBUF_FORCE_COPY_IN_RELEASE was previously defined
|
||||
#endif
|
||||
|
||||
#ifdef PROTOBUF_FORCE_COPY_IN_SWAP
|
||||
#error PROTOBUF_FORCE_COPY_IN_SWAP was previously defined
|
||||
#endif
|
||||
|
||||
#ifdef PROTOBUF_FORCE_COPY_IN_MOVE
|
||||
#error PROTOBUF_FORCE_COPY_IN_MOVE was previously defined
|
||||
#endif
|
||||
|
||||
#ifdef PROTOBUF_FORCE_RESET_IN_CLEAR
|
||||
#error PROTOBUF_FORCE_RESET_IN_CLEAR was previously defined
|
||||
#endif
|
||||
|
||||
// Force copy the default string to a string field so that non-optimized builds
|
||||
// have harder-to-rely-on address stability.
|
||||
#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
|
||||
#error PROTOBUF_FORCE_COPY_DEFAULT_STRING was previously defined
|
||||
#endif
|
||||
|
||||
#ifdef PROTOBUF_FALLTHROUGH_INTENDED
|
||||
#error PROTOBUF_FALLTHROUGH_INTENDED was previously defined
|
||||
#endif
|
||||
#if __has_cpp_attribute(fallthrough)
|
||||
#define PROTOBUF_FALLTHROUGH_INTENDED [[fallthrough]]
|
||||
#elif __has_feature(cxx_attributes) && __has_warning("-Wimplicit-fallthrough")
|
||||
#define PROTOBUF_FALLTHROUGH_INTENDED [[clang::fallthrough]]
|
||||
#elif PROTOBUF_GNUC_MIN(7, 0)
|
||||
#define PROTOBUF_FALLTHROUGH_INTENDED [[gnu::fallthrough]]
|
||||
#else
|
||||
#define PROTOBUF_FALLTHROUGH_INTENDED
|
||||
#endif
|
||||
|
||||
// PROTOBUF_ASSUME(pred) tells the compiler that it can assume pred is true. To
|
||||
// be safe, we also validate the assumption with a GOOGLE_DCHECK in unoptimized
|
||||
// builds. The macro does not do anything useful if the compiler does not
|
||||
// support __builtin_assume.
|
||||
#ifdef PROTOBUF_ASSUME
|
||||
#error PROTOBUF_ASSUME was previously defined
|
||||
#endif
|
||||
#if __has_builtin(__builtin_assume)
|
||||
#define PROTOBUF_ASSUME(pred) \
|
||||
GOOGLE_DCHECK(pred); \
|
||||
__builtin_assume(pred)
|
||||
#else
|
||||
#define PROTOBUF_ASSUME(pred) GOOGLE_DCHECK(pred)
|
||||
#endif
|
||||
|
||||
// Specify memory alignment for structs, classes, etc.
|
||||
// Use like:
|
||||
// class PROTOBUF_ALIGNAS(16) MyClass { ... }
|
||||
// PROTOBUF_ALIGNAS(16) int array[4];
|
||||
//
|
||||
// In most places you can use the C++11 keyword "alignas", which is preferred.
|
||||
//
|
||||
// But compilers have trouble mixing __attribute__((...)) syntax with
|
||||
// alignas(...) syntax.
|
||||
//
|
||||
// Doesn't work in clang or gcc:
|
||||
// struct alignas(16) __attribute__((packed)) S { char c; };
|
||||
// Works in clang but not gcc:
|
||||
// struct __attribute__((packed)) alignas(16) S2 { char c; };
|
||||
// Works in clang and gcc:
|
||||
// struct alignas(16) S3 { char c; } __attribute__((packed));
|
||||
//
|
||||
// There are also some attributes that must be specified *before* a class
|
||||
// definition: visibility (used for exporting functions/classes) is one of
|
||||
// these attributes. This means that it is not possible to use alignas() with a
|
||||
// class that is marked as exported.
|
||||
#ifdef PROTOBUF_ALIGNAS
|
||||
#error PROTOBUF_ALIGNAS was previously defined
|
||||
#endif
|
||||
#if defined(_MSC_VER)
|
||||
#define PROTOBUF_ALIGNAS(byte_alignment) __declspec(align(byte_alignment))
|
||||
#elif PROTOBUF_GNUC_MIN(3, 0)
|
||||
#define PROTOBUF_ALIGNAS(byte_alignment) \
|
||||
__attribute__((aligned(byte_alignment)))
|
||||
#else
|
||||
#define PROTOBUF_ALIGNAS(byte_alignment) alignas(byte_alignment)
|
||||
#endif
|
||||
|
||||
#ifdef PROTOBUF_FINAL
|
||||
#error PROTOBUF_FINAL was previously defined
|
||||
#endif
|
||||
#define PROTOBUF_FINAL final
|
||||
|
||||
#ifdef PROTOBUF_THREAD_LOCAL
|
||||
#error PROTOBUF_THREAD_LOCAL was previously defined
|
||||
#endif
|
||||
#if defined(_MSC_VER)
|
||||
#define PROTOBUF_THREAD_LOCAL __declspec(thread)
|
||||
#else
|
||||
#define PROTOBUF_THREAD_LOCAL __thread
|
||||
#endif
|
||||
|
||||
// TODO(b/228173843): cleanup PROTOBUF_LITTLE_ENDIAN in various 3p forks.
|
||||
#if (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && \
|
||||
__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
|
||||
#define PROTOBUF_LITTLE_ENDIAN 1
|
||||
#ifdef PROTOBUF_BIG_ENDIAN
|
||||
#error Conflicting PROTOBUF_BIG_ENDIAN was previously defined
|
||||
#endif
|
||||
#elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && \
|
||||
__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
#define PROTOBUF_BIG_ENDIAN 1
|
||||
#elif defined(_WIN32) || defined(__x86_64__) || defined(__aarch64__)
|
||||
#define PROTOBUF_LITTLE_ENDIAN 1
|
||||
#else
|
||||
#error "endian detection failed for current compiler"
|
||||
#endif
|
||||
|
||||
// For enabling message owned arena, one major blocker is semantic change from
|
||||
// moving to copying when there is ownership transfer (e.g., move ctor, swap,
|
||||
// set allocated, release). This change not only causes performance regression
|
||||
// but also breaks users code (e.g., dangling reference). For top-level
|
||||
// messages, since it owns the arena, we can mitigate the issue by transferring
|
||||
// ownership of arena. However, we cannot do that for nested messages. In order
|
||||
// to tell how many usages of nested messages affected by message owned arena,
|
||||
// we need to simulate the arena ownership.
|
||||
// This experiment is purely for the purpose of gathering data. All code guarded
|
||||
// by this flag is supposed to be removed after this experiment.
|
||||
#define PROTOBUF_MESSAGE_OWNED_ARENA_EXPERIMENT
|
||||
#ifdef PROTOBUF_CONSTINIT
|
||||
#error PROTOBUF_CONSTINIT was previously defined
|
||||
#endif
|
||||
#if defined(__cpp_constinit) && !defined(_MSC_VER)
|
||||
#define PROTOBUF_CONSTINIT constinit
|
||||
#define PROTOBUF_CONSTEXPR constexpr
|
||||
// Some older Clang versions incorrectly raise an error about
|
||||
// constant-initializing weak default instance pointers. Versions 12.0 and
|
||||
// higher seem to work, except that XCode 12.5.1 shows the error even though it
|
||||
// uses Clang 12.0.5.
|
||||
// Clang-cl on Windows raises error also.
|
||||
#elif !defined(_MSC_VER) && __has_cpp_attribute(clang::require_constant_initialization) && \
|
||||
((defined(__APPLE__) && __clang_major__ >= 13) || \
|
||||
(!defined(__APPLE__) && __clang_major__ >= 12))
|
||||
#define PROTOBUF_CONSTINIT [[clang::require_constant_initialization]]
|
||||
#define PROTOBUF_CONSTEXPR constexpr
|
||||
#elif PROTOBUF_GNUC_MIN(12, 2)
|
||||
#define PROTOBUF_CONSTINIT __constinit
|
||||
#define PROTOBUF_CONSTEXPR constexpr
|
||||
// MSVC 17 currently seems to raise an error about constant-initialized pointers.
|
||||
#elif defined(_MSC_VER) && _MSC_VER >= 1930
|
||||
#define PROTOBUF_CONSTINIT
|
||||
#define PROTOBUF_CONSTEXPR constexpr
|
||||
#else
|
||||
#define PROTOBUF_CONSTINIT
|
||||
#define PROTOBUF_CONSTEXPR
|
||||
#endif
|
||||
|
||||
// Some globals with an empty non-trivial destructor are annotated with
|
||||
// no_destroy for performance reasons. It reduces the cost of these globals in
|
||||
// non-opt mode and under sanitizers.
|
||||
#ifdef PROTOBUF_ATTRIBUTE_NO_DESTROY
|
||||
#error PROTOBUF_ATTRIBUTE_NO_DESTROY was previously defined
|
||||
#endif
|
||||
#if __has_cpp_attribute(clang::no_destroy)
|
||||
#define PROTOBUF_ATTRIBUTE_NO_DESTROY [[clang::no_destroy]]
|
||||
#else
|
||||
#define PROTOBUF_ATTRIBUTE_NO_DESTROY
|
||||
#endif
|
||||
|
||||
// Force clang to always emit complete debug info for a type.
|
||||
// Clang uses constructor homing to determine when to emit debug info for a
|
||||
// type. If the constructor of a type is never used, which can happen in some
|
||||
// cases where member variables are constructed in place for optimization
|
||||
// purposes (see b/208803175 for an example), the type will have incomplete
|
||||
// debug info unless this attribute is used.
|
||||
#ifdef PROTOBUF_ATTRIBUTE_STANDALONE_DEBUG
|
||||
#error PROTOBUF_ATTRIBUTE_STANDALONE_DEBUG was previously defined
|
||||
#endif
|
||||
#if __has_cpp_attribute(clang::standalone_debug)
|
||||
#define PROTOBUF_ATTRIBUTE_STANDALONE_DEBUG [[clang::standalone_debug]]
|
||||
#else
|
||||
#define PROTOBUF_ATTRIBUTE_STANDALONE_DEBUG
|
||||
#endif
|
||||
|
||||
// Protobuf extensions and reflection require registration of the protos linked
|
||||
// in the binary. Not until everything is registered does the runtime have a
|
||||
// complete view on all protos. When code is using reflection or extensions
|
||||
// in between registration calls this can lead to surprising behavior. By
|
||||
// having the registration run first we mitigate this scenario.
|
||||
// Highest priority is 101. We use 102 for registration, to allow code that
|
||||
// really wants to higher priority to still beat us. Some initialization happens
|
||||
// at higher priority, though, since it is needed before registration.
|
||||
#ifdef PROTOBUF_ATTRIBUTE_INIT_PRIORITY1
|
||||
#error PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 was previously defined
|
||||
#endif
|
||||
#ifdef PROTOBUF_ATTRIBUTE_INIT_PRIORITY2
|
||||
#error PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 was previously defined
|
||||
#endif
|
||||
#if PROTOBUF_GNUC_MIN(3, 0) && (!defined(__APPLE__) || defined(__clang__)) && \
|
||||
!((defined(sun) || defined(__sun)) && \
|
||||
(defined(__SVR4) || defined(__svr4__)))
|
||||
#define PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 __attribute__((init_priority((101))))
|
||||
#define PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 __attribute__((init_priority((102))))
|
||||
#else
|
||||
#define PROTOBUF_ATTRIBUTE_INIT_PRIORITY1
|
||||
#define PROTOBUF_ATTRIBUTE_INIT_PRIORITY2
|
||||
#endif
|
||||
|
||||
#ifdef PROTOBUF_PRAGMA_INIT_SEG
|
||||
#error PROTOBUF_PRAGMA_INIT_SEG was previously defined
|
||||
#endif
|
||||
#ifdef _MSC_VER
|
||||
#define PROTOBUF_PRAGMA_INIT_SEG __pragma(init_seg(lib))
|
||||
#else
|
||||
#define PROTOBUF_PRAGMA_INIT_SEG
|
||||
#endif
|
||||
|
||||
#ifdef PROTOBUF_ATTRIBUTE_WEAK
|
||||
#error PROTOBUF_ATTRIBUTE_WEAK was previously defined
|
||||
#endif
|
||||
#if __has_attribute(weak) && \
|
||||
!defined(__APPLE__) && \
|
||||
(!defined(_WIN32) || __clang_major__ < 9) && \
|
||||
!defined(__MINGW32__)
|
||||
#define PROTOBUF_ATTRIBUTE_WEAK __attribute__((weak))
|
||||
#define PROTOBUF_HAVE_ATTRIBUTE_WEAK 1
|
||||
#else
|
||||
#define PROTOBUF_ATTRIBUTE_WEAK
|
||||
#define PROTOBUF_HAVE_ATTRIBUTE_WEAK 0
|
||||
#endif
|
||||
|
||||
// Macros to detect sanitizers.
|
||||
#ifdef PROTOBUF_ASAN
|
||||
#error PROTOBUF_ASAN was previously defined
|
||||
#endif
|
||||
#ifdef PROTOBUF_MSAN
|
||||
#error PROTOBUF_MSAN was previously defined
|
||||
#endif
|
||||
#ifdef PROTOBUF_TSAN
|
||||
#error PROTOBUF_TSAN was previously defined
|
||||
#endif
|
||||
#if defined(__clang__)
|
||||
# if __has_feature(address_sanitizer)
|
||||
# define PROTOBUF_ASAN 1
|
||||
# endif
|
||||
# if __has_feature(thread_sanitizer)
|
||||
# define PROTOBUF_TSAN 1
|
||||
# endif
|
||||
# if __has_feature(memory_sanitizer)
|
||||
# define PROTOBUF_MSAN 1
|
||||
# endif
|
||||
#elif PROTOBUF_GNUC_MIN(3, 0)
|
||||
// Double-guard is needed for -Wundef:
|
||||
# ifdef __SANITIZE_ADDRESS__
|
||||
# if __SANITIZE_ADDRESS__
|
||||
# define PROTOBUF_ASAN 1
|
||||
# endif
|
||||
# endif
|
||||
# ifdef __SANITIZE_THREAD__
|
||||
# if __SANITIZE_THREAD__
|
||||
# define PROTOBUF_TSAN 1
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// Tail call table-driven parsing can be enabled by defining
|
||||
// PROTOBUF_EXPERIMENTAL_USE_TAIL_CALL_TABLE_PARSER at compilation time. Note
|
||||
// that this macro is for small-scale testing only, and is not supported.
|
||||
#ifdef PROTOBUF_TAIL_CALL_TABLE_PARSER_ENABLED
|
||||
#error PROTOBUF_TAIL_CALL_TABLE_PARSER_ENABLED was previously declared
|
||||
#endif
|
||||
#if defined(PROTOBUF_EXPERIMENTAL_USE_TAIL_CALL_TABLE_PARSER)
|
||||
#define PROTOBUF_TAIL_CALL_TABLE_PARSER_ENABLED 1
|
||||
#endif
|
||||
|
||||
#define PROTOBUF_TC_PARAM_DECL \
|
||||
::google::protobuf::MessageLite *msg, const char *ptr, \
|
||||
::google::protobuf::internal::ParseContext *ctx, \
|
||||
const ::google::protobuf::internal::TcParseTableBase *table, \
|
||||
uint64_t hasbits, ::google::protobuf::internal::TcFieldData data
|
||||
|
||||
#ifdef PROTOBUF_UNUSED
|
||||
#error PROTOBUF_UNUSED was previously defined
|
||||
#endif
|
||||
#if __has_cpp_attribute(maybe_unused) || \
|
||||
(PROTOBUF_MSC_VER_MIN(1911) && PROTOBUF_CPLUSPLUS_MIN(201703L))
|
||||
#define PROTOBUF_UNUSED [[maybe_unused]]
|
||||
#elif __has_attribute(unused) || PROTOBUF_GNUC_MIN(3, 0)
|
||||
#define PROTOBUF_UNUSED __attribute__((__unused__))
|
||||
#else
|
||||
#define PROTOBUF_UNUSED
|
||||
#endif
|
||||
|
||||
// ThreadSafeArenaz is turned off completely in opensource builds.
|
||||
|
||||
// Windows declares several inconvenient macro names. We #undef them and then
|
||||
// restore them in port_undef.inc.
|
||||
#ifdef _MSC_VER
|
||||
#pragma push_macro("CREATE_NEW")
|
||||
#undef CREATE_NEW
|
||||
#pragma push_macro("DELETE")
|
||||
#undef DELETE
|
||||
#pragma push_macro("DOUBLE_CLICK")
|
||||
#undef DOUBLE_CLICK
|
||||
#pragma push_macro("ERROR")
|
||||
#undef ERROR
|
||||
#pragma push_macro("ERROR_BUSY")
|
||||
#undef ERROR_BUSY
|
||||
#pragma push_macro("ERROR_INSTALL_FAILED")
|
||||
#undef ERROR_INSTALL_FAILED
|
||||
#pragma push_macro("ERROR_NOT_FOUND")
|
||||
#undef ERROR_NOT_FOUND
|
||||
#pragma push_macro("GetClassName")
|
||||
#undef GetClassName
|
||||
#pragma push_macro("GetMessage")
|
||||
#undef GetMessage
|
||||
#pragma push_macro("GetObject")
|
||||
#undef GetObject
|
||||
#pragma push_macro("IGNORE")
|
||||
#undef IGNORE
|
||||
#pragma push_macro("IN")
|
||||
#undef IN
|
||||
#pragma push_macro("INPUT_KEYBOARD")
|
||||
#undef INPUT_KEYBOARD
|
||||
#pragma push_macro("NO_ERROR")
|
||||
#undef NO_ERROR
|
||||
#pragma push_macro("OUT")
|
||||
#undef OUT
|
||||
#pragma push_macro("OPTIONAL")
|
||||
#undef OPTIONAL
|
||||
#pragma push_macro("min")
|
||||
#undef min
|
||||
#pragma push_macro("max")
|
||||
#undef max
|
||||
#pragma push_macro("NEAR")
|
||||
#undef NEAR
|
||||
#pragma push_macro("NO_DATA")
|
||||
#undef NO_DATA
|
||||
#pragma push_macro("REASON_UNKNOWN")
|
||||
#undef REASON_UNKNOWN
|
||||
#pragma push_macro("SERVICE_DISABLED")
|
||||
#undef SERVICE_DISABLED
|
||||
#pragma push_macro("SEVERITY_ERROR")
|
||||
#undef SEVERITY_ERROR
|
||||
#pragma push_macro("STATUS_PENDING")
|
||||
#undef STATUS_PENDING
|
||||
#pragma push_macro("STRICT")
|
||||
#undef STRICT
|
||||
#pragma push_macro("timezone")
|
||||
#undef timezone
|
||||
#endif // _MSC_VER
|
||||
|
||||
#ifdef __APPLE__
|
||||
// Inconvenient macro names from usr/include/math.h in some macOS SDKs.
|
||||
#pragma push_macro("DOMAIN")
|
||||
#undef DOMAIN
|
||||
// Inconvenient macro names from /usr/include/mach/boolean.h in some macOS SDKs.
|
||||
#pragma push_macro("TRUE")
|
||||
#undef TRUE
|
||||
#pragma push_macro("FALSE")
|
||||
#undef FALSE
|
||||
// Inconvenient macro names from usr/include/sys/syslimits.h in some macOS SDKs.
|
||||
#pragma push_macro("UID_MAX")
|
||||
#undef UID_MAX
|
||||
#endif // __APPLE__
|
||||
|
||||
#if defined(__clang__) || PROTOBUF_GNUC_MIN(3, 0) || defined(_MSC_VER)
|
||||
// Don't let Objective-C Macros interfere with proto identifiers with the same
|
||||
// name.
|
||||
#pragma push_macro("DEBUG")
|
||||
#undef DEBUG
|
||||
#endif // defined(__clang__) || PROTOBUF_GNUC_MIN(3, 0) || defined(_MSC_VER)
|
||||
|
||||
#if PROTOBUF_GNUC_MIN(3, 0)
|
||||
// GCC does not allow disabling diagnostics within an expression:
|
||||
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60875, so we disable this one
|
||||
// globally even though it's only used for PROTOBUF_FIELD_OFFSET.
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Winvalid-offsetof"
|
||||
#endif
|
||||
|
||||
// Silence some MSVC warnings in all our code.
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
// For non-trivial unions
|
||||
#pragma warning(disable : 4582)
|
||||
#pragma warning(disable : 4583)
|
||||
// For init_seg(lib)
|
||||
#pragma warning(disable : 4073)
|
||||
// To silence the fact that we will pop this push from another file
|
||||
#pragma warning(disable : 5031)
|
||||
// Conditional expression is constant
|
||||
#pragma warning(disable: 4127)
|
||||
// decimal digit terminates octal escape sequence
|
||||
#pragma warning(disable: 4125)
|
||||
#endif
|
||||
|
||||
// We don't want code outside port_def doing complex testing, so
|
||||
// remove our portable condition test macros to nudge folks away from
|
||||
// using it themselves.
|
||||
#ifdef PROTOBUF_has_cpp_attribute_DEFINED_
|
||||
# undef __has_cpp_attribute
|
||||
# undef PROTOBUF_has_cpp_attribute_DEFINED_
|
||||
#endif
|
||||
#ifdef PROTOBUF_has_feature_DEFINED_
|
||||
# undef __has_feature
|
||||
# undef PROTOBUF_has_feature_DEFINED_
|
||||
#endif
|
||||
#ifdef PROTOBUF_has_warning_DEFINED_
|
||||
# undef __has_warning
|
||||
# undef PROTOBUF_has_warning_DEFINED_
|
||||
#endif
|
||||
#ifdef PROTOBUF_has_attribute_DEFINED_
|
||||
# undef __has_attribute
|
||||
# undef PROTOBUF_has_attribute_DEFINED_
|
||||
#endif
|
||||
#ifdef PROTOBUF_has_builtin_DEFINED_
|
||||
# undef __has_builtin
|
||||
# undef PROTOBUF_has_builtin_DEFINED_
|
||||
#endif
|
||||
@@ -1,160 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// #undefs all macros defined in port_def.inc. See comments in port_def.inc
|
||||
// for more info.
|
||||
|
||||
#ifndef PROTOBUF_NAMESPACE
|
||||
#error "port_undef.inc must be included after port_def.inc"
|
||||
#endif
|
||||
|
||||
#undef PROTOBUF_BUILTIN_BSWAP16
|
||||
#undef PROTOBUF_BUILTIN_BSWAP32
|
||||
#undef PROTOBUF_BUILTIN_BSWAP64
|
||||
#undef PROTOBUF_GNUC_MIN
|
||||
#undef PROTOBUF_MSC_VER_MIN
|
||||
#undef PROTOBUF_CPLUSPLUS_MIN
|
||||
#undef PROTOBUF_NAMESPACE
|
||||
#undef PROTOBUF_NAMESPACE_ID
|
||||
#undef PROTOBUF_ALWAYS_INLINE
|
||||
#undef PROTOBUF_NDEBUG_INLINE
|
||||
#undef PROTOBUF_MUSTTAIL
|
||||
#undef PROTOBUF_TAILCALL
|
||||
#undef PROTOBUF_COLD
|
||||
#undef PROTOBUF_NOINLINE
|
||||
#undef PROTOBUF_SECTION_VARIABLE
|
||||
#undef PROTOBUF_DEPRECATED
|
||||
#undef PROTOBUF_DEPRECATED_ENUM
|
||||
#undef PROTOBUF_DEPRECATED_MSG
|
||||
#undef PROTOBUF_FUNC_ALIGN
|
||||
#undef PROTOBUF_RETURNS_NONNULL
|
||||
#undef PROTOBUF_ATTRIBUTE_REINITIALIZES
|
||||
#undef PROTOBUF_RTTI
|
||||
#undef PROTOBUF_VERSION
|
||||
#undef PROTOBUF_VERSION_SUFFIX
|
||||
#undef PROTOBUF_FIELD_OFFSET
|
||||
#undef PROTOBUF_MIN_HEADER_VERSION_FOR_PROTOC
|
||||
#undef PROTOBUF_MIN_PROTOC_VERSION
|
||||
#undef PROTOBUF_PREDICT_TRUE
|
||||
#undef PROTOBUF_PREDICT_FALSE
|
||||
#undef PROTOBUF_FALLTHROUGH_INTENDED
|
||||
#undef PROTOBUF_EXPORT
|
||||
#undef PROTOC_EXPORT
|
||||
#undef PROTOBUF_NODISCARD
|
||||
#undef PROTOBUF_FORCE_COPY_IN_RELEASE
|
||||
#undef PROTOBUF_FORCE_COPY_IN_SWAP
|
||||
#undef PROTOBUF_FORCE_COPY_IN_MOVE
|
||||
#undef PROTOBUF_FORCE_RESET_IN_CLEAR
|
||||
#undef PROTOBUF_FORCE_COPY_DEFAULT_STRING
|
||||
#undef PROTOBUF_NAMESPACE_OPEN
|
||||
#undef PROTOBUF_NAMESPACE_CLOSE
|
||||
#undef PROTOBUF_UNUSED
|
||||
#undef PROTOBUF_ASSUME
|
||||
#undef PROTOBUF_EXPORT_TEMPLATE_DECLARE
|
||||
#undef PROTOBUF_EXPORT_TEMPLATE_DEFINE
|
||||
#undef PROTOBUF_ALIGNAS
|
||||
#undef PROTOBUF_FINAL
|
||||
#undef PROTOBUF_FUTURE_FINAL
|
||||
#undef PROTOBUF_THREAD_LOCAL
|
||||
#undef PROTOBUF_LITTLE_ENDIAN
|
||||
#undef PROTOBUF_BIG_ENDIAN
|
||||
#undef PROTOBUF_MESSAGE_OWNED_ARENA_EXPERIMENT
|
||||
#undef PROTOBUF_CONSTINIT
|
||||
#undef PROTOBUF_CONSTEXPR
|
||||
#undef PROTOBUF_ATTRIBUTE_WEAK
|
||||
#undef PROTOBUF_HAVE_ATTRIBUTE_WEAK
|
||||
#undef PROTOBUF_ATTRIBUTE_NO_DESTROY
|
||||
#undef PROTOBUF_ATTRIBUTE_STANDALONE_DEBUG
|
||||
#undef PROTOBUF_ATTRIBUTE_INIT_PRIORITY1
|
||||
#undef PROTOBUF_ATTRIBUTE_INIT_PRIORITY2
|
||||
#undef PROTOBUF_PRAGMA_INIT_SEG
|
||||
#undef PROTOBUF_ASAN
|
||||
#undef PROTOBUF_MSAN
|
||||
#undef PROTOBUF_TSAN
|
||||
#undef PROTOBUF_TAIL_CALL_TABLE_PARSER_ENABLED
|
||||
#undef PROTOBUF_TC_PARAM_DECL
|
||||
#undef PROTOBUF_EXCLUSIVE_LOCKS_REQUIRED
|
||||
#undef PROTOBUF_LOCKS_EXCLUDED
|
||||
#undef PROTOBUF_NO_THREAD_SAFETY_ANALYSIS
|
||||
#undef PROTOBUF_GUARDED_BY
|
||||
|
||||
#ifdef PROTOBUF_FUTURE_BREAKING_CHANGES
|
||||
#undef PROTOBUF_FUTURE_BREAKING_CHANGES
|
||||
#endif
|
||||
|
||||
// Restore macro that may have been #undef'd in port_def.inc.
|
||||
#ifdef _MSC_VER
|
||||
#pragma pop_macro("CREATE_NEW")
|
||||
#pragma pop_macro("DELETE")
|
||||
#pragma pop_macro("DOUBLE_CLICK")
|
||||
#pragma pop_macro("ERROR")
|
||||
#pragma pop_macro("ERROR_BUSY")
|
||||
#pragma pop_macro("ERROR_INSTALL_FAILED")
|
||||
#pragma pop_macro("ERROR_NOT_FOUND")
|
||||
#pragma pop_macro("GetClassName")
|
||||
#pragma pop_macro("GetMessage")
|
||||
#pragma pop_macro("GetObject")
|
||||
#pragma pop_macro("IGNORE")
|
||||
#pragma pop_macro("IN")
|
||||
#pragma pop_macro("INPUT_KEYBOARD")
|
||||
#pragma pop_macro("OUT")
|
||||
#pragma pop_macro("OPTIONAL")
|
||||
#pragma pop_macro("min")
|
||||
#pragma pop_macro("max")
|
||||
#pragma pop_macro("NEAR")
|
||||
#pragma pop_macro("NO_DATA")
|
||||
#pragma pop_macro("NO_ERROR")
|
||||
#pragma pop_macro("REASON_UNKNOWN")
|
||||
#pragma pop_macro("SERVICE_DISABLED")
|
||||
#pragma pop_macro("SEVERITY_ERROR")
|
||||
#pragma pop_macro("STRICT")
|
||||
#pragma pop_macro("STATUS_PENDING")
|
||||
#pragma pop_macro("timezone")
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
#pragma pop_macro("DOMAIN")
|
||||
#pragma pop_macro("TRUE")
|
||||
#pragma pop_macro("FALSE")
|
||||
#pragma pop_macro("UID_MAX")
|
||||
#endif // __APPLE__
|
||||
|
||||
#if defined(__clang__) || defined(__GNUC__) || defined(_MSC_VER)
|
||||
#pragma pop_macro("DEBUG")
|
||||
#endif // defined(__clang__) || defined(__GNUC__) || defined(_MSC_VER)
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
// Pop the warning(push) from port_def.inc
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
@@ -1,570 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// This header defines the RepeatedFieldRef class template used to access
|
||||
// repeated fields with protobuf reflection API.
|
||||
#ifndef GOOGLE_PROTOBUF_REFLECTION_H__
|
||||
#define GOOGLE_PROTOBUF_REFLECTION_H__
|
||||
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <google/protobuf/message.h>
|
||||
#include <google/protobuf/generated_enum_util.h>
|
||||
|
||||
#ifdef SWIG
|
||||
#error "You cannot SWIG proto headers"
|
||||
#endif
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
template <typename T, typename Enable = void>
|
||||
struct RefTypeTraits;
|
||||
} // namespace internal
|
||||
|
||||
template <typename T>
|
||||
RepeatedFieldRef<T> Reflection::GetRepeatedFieldRef(
|
||||
const Message& message, const FieldDescriptor* field) const {
|
||||
return RepeatedFieldRef<T>(message, field);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
MutableRepeatedFieldRef<T> Reflection::GetMutableRepeatedFieldRef(
|
||||
Message* message, const FieldDescriptor* field) const {
|
||||
return MutableRepeatedFieldRef<T>(message, field);
|
||||
}
|
||||
|
||||
// RepeatedFieldRef definition for non-message types.
|
||||
template <typename T>
|
||||
class RepeatedFieldRef<
|
||||
T, typename std::enable_if<!std::is_base_of<Message, T>::value>::type> {
|
||||
typedef typename internal::RefTypeTraits<T>::iterator IteratorType;
|
||||
typedef typename internal::RefTypeTraits<T>::AccessorType AccessorType;
|
||||
|
||||
public:
|
||||
bool empty() const { return accessor_->IsEmpty(data_); }
|
||||
int size() const { return accessor_->Size(data_); }
|
||||
T Get(int index) const { return accessor_->template Get<T>(data_, index); }
|
||||
|
||||
typedef IteratorType iterator;
|
||||
typedef IteratorType const_iterator;
|
||||
typedef T value_type;
|
||||
typedef T& reference;
|
||||
typedef const T& const_reference;
|
||||
typedef int size_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
|
||||
iterator begin() const { return iterator(data_, accessor_, true); }
|
||||
iterator end() const { return iterator(data_, accessor_, false); }
|
||||
|
||||
private:
|
||||
friend class Reflection;
|
||||
RepeatedFieldRef(const Message& message, const FieldDescriptor* field) {
|
||||
const Reflection* reflection = message.GetReflection();
|
||||
data_ = reflection->RepeatedFieldData(const_cast<Message*>(&message), field,
|
||||
internal::RefTypeTraits<T>::cpp_type,
|
||||
nullptr);
|
||||
accessor_ = reflection->RepeatedFieldAccessor(field);
|
||||
}
|
||||
|
||||
const void* data_;
|
||||
const AccessorType* accessor_;
|
||||
};
|
||||
|
||||
// MutableRepeatedFieldRef definition for non-message types.
|
||||
template <typename T>
|
||||
class MutableRepeatedFieldRef<
|
||||
T, typename std::enable_if<!std::is_base_of<Message, T>::value>::type> {
|
||||
typedef typename internal::RefTypeTraits<T>::AccessorType AccessorType;
|
||||
|
||||
public:
|
||||
bool empty() const { return accessor_->IsEmpty(data_); }
|
||||
int size() const { return accessor_->Size(data_); }
|
||||
T Get(int index) const { return accessor_->template Get<T>(data_, index); }
|
||||
|
||||
void Set(int index, const T& value) const {
|
||||
accessor_->template Set<T>(data_, index, value);
|
||||
}
|
||||
void Add(const T& value) const { accessor_->template Add<T>(data_, value); }
|
||||
void RemoveLast() const { accessor_->RemoveLast(data_); }
|
||||
void SwapElements(int index1, int index2) const {
|
||||
accessor_->SwapElements(data_, index1, index2);
|
||||
}
|
||||
void Clear() const { accessor_->Clear(data_); }
|
||||
|
||||
void Swap(const MutableRepeatedFieldRef& other) const {
|
||||
accessor_->Swap(data_, other.accessor_, other.data_);
|
||||
}
|
||||
|
||||
template <typename Container>
|
||||
void MergeFrom(const Container& container) const {
|
||||
typedef typename Container::const_iterator Iterator;
|
||||
for (Iterator it = container.begin(); it != container.end(); ++it) {
|
||||
Add(*it);
|
||||
}
|
||||
}
|
||||
template <typename Container>
|
||||
void CopyFrom(const Container& container) const {
|
||||
Clear();
|
||||
MergeFrom(container);
|
||||
}
|
||||
|
||||
private:
|
||||
friend class Reflection;
|
||||
MutableRepeatedFieldRef(Message* message, const FieldDescriptor* field) {
|
||||
const Reflection* reflection = message->GetReflection();
|
||||
data_ = reflection->RepeatedFieldData(
|
||||
message, field, internal::RefTypeTraits<T>::cpp_type, nullptr);
|
||||
accessor_ = reflection->RepeatedFieldAccessor(field);
|
||||
}
|
||||
|
||||
void* data_;
|
||||
const AccessorType* accessor_;
|
||||
};
|
||||
|
||||
// RepeatedFieldRef definition for message types.
|
||||
template <typename T>
|
||||
class RepeatedFieldRef<
|
||||
T, typename std::enable_if<std::is_base_of<Message, T>::value>::type> {
|
||||
typedef typename internal::RefTypeTraits<T>::iterator IteratorType;
|
||||
typedef typename internal::RefTypeTraits<T>::AccessorType AccessorType;
|
||||
|
||||
public:
|
||||
bool empty() const { return accessor_->IsEmpty(data_); }
|
||||
int size() const { return accessor_->Size(data_); }
|
||||
// This method returns a reference to the underlying message object if it
|
||||
// exists. If a message object doesn't exist (e.g., data stored in serialized
|
||||
// form), scratch_space will be filled with the data and a reference to it
|
||||
// will be returned.
|
||||
//
|
||||
// Example:
|
||||
// RepeatedFieldRef<Message> h = ...
|
||||
// unique_ptr<Message> scratch_space(h.NewMessage());
|
||||
// const Message& item = h.Get(index, scratch_space.get());
|
||||
const T& Get(int index, T* scratch_space) const {
|
||||
return *static_cast<const T*>(accessor_->Get(data_, index, scratch_space));
|
||||
}
|
||||
// Create a new message of the same type as the messages stored in this
|
||||
// repeated field. Caller takes ownership of the returned object.
|
||||
T* NewMessage() const { return static_cast<T*>(default_instance_->New()); }
|
||||
|
||||
typedef IteratorType iterator;
|
||||
typedef IteratorType const_iterator;
|
||||
typedef T value_type;
|
||||
typedef T& reference;
|
||||
typedef const T& const_reference;
|
||||
typedef int size_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
|
||||
iterator begin() const {
|
||||
return iterator(data_, accessor_, true, NewMessage());
|
||||
}
|
||||
iterator end() const {
|
||||
// The end iterator must not be dereferenced, no need for scratch space.
|
||||
return iterator(data_, accessor_, false, nullptr);
|
||||
}
|
||||
|
||||
private:
|
||||
friend class Reflection;
|
||||
RepeatedFieldRef(const Message& message, const FieldDescriptor* field) {
|
||||
const Reflection* reflection = message.GetReflection();
|
||||
data_ = reflection->RepeatedFieldData(
|
||||
const_cast<Message*>(&message), field,
|
||||
internal::RefTypeTraits<T>::cpp_type,
|
||||
internal::RefTypeTraits<T>::GetMessageFieldDescriptor());
|
||||
accessor_ = reflection->RepeatedFieldAccessor(field);
|
||||
default_instance_ =
|
||||
reflection->GetMessageFactory()->GetPrototype(field->message_type());
|
||||
}
|
||||
|
||||
const void* data_;
|
||||
const AccessorType* accessor_;
|
||||
const Message* default_instance_;
|
||||
};
|
||||
|
||||
// MutableRepeatedFieldRef definition for message types.
|
||||
template <typename T>
|
||||
class MutableRepeatedFieldRef<
|
||||
T, typename std::enable_if<std::is_base_of<Message, T>::value>::type> {
|
||||
typedef typename internal::RefTypeTraits<T>::AccessorType AccessorType;
|
||||
|
||||
public:
|
||||
bool empty() const { return accessor_->IsEmpty(data_); }
|
||||
int size() const { return accessor_->Size(data_); }
|
||||
// See comments for RepeatedFieldRef<Message>::Get()
|
||||
const T& Get(int index, T* scratch_space) const {
|
||||
return *static_cast<const T*>(accessor_->Get(data_, index, scratch_space));
|
||||
}
|
||||
// Create a new message of the same type as the messages stored in this
|
||||
// repeated field. Caller takes ownership of the returned object.
|
||||
T* NewMessage() const { return static_cast<T*>(default_instance_->New()); }
|
||||
|
||||
void Set(int index, const T& value) const {
|
||||
accessor_->Set(data_, index, &value);
|
||||
}
|
||||
void Add(const T& value) const { accessor_->Add(data_, &value); }
|
||||
void RemoveLast() const { accessor_->RemoveLast(data_); }
|
||||
void SwapElements(int index1, int index2) const {
|
||||
accessor_->SwapElements(data_, index1, index2);
|
||||
}
|
||||
void Clear() const { accessor_->Clear(data_); }
|
||||
|
||||
void Swap(const MutableRepeatedFieldRef& other) const {
|
||||
accessor_->Swap(data_, other.accessor_, other.data_);
|
||||
}
|
||||
|
||||
template <typename Container>
|
||||
void MergeFrom(const Container& container) const {
|
||||
typedef typename Container::const_iterator Iterator;
|
||||
for (Iterator it = container.begin(); it != container.end(); ++it) {
|
||||
Add(*it);
|
||||
}
|
||||
}
|
||||
template <typename Container>
|
||||
void CopyFrom(const Container& container) const {
|
||||
Clear();
|
||||
MergeFrom(container);
|
||||
}
|
||||
|
||||
private:
|
||||
friend class Reflection;
|
||||
MutableRepeatedFieldRef(Message* message, const FieldDescriptor* field) {
|
||||
const Reflection* reflection = message->GetReflection();
|
||||
data_ = reflection->RepeatedFieldData(
|
||||
message, field, internal::RefTypeTraits<T>::cpp_type,
|
||||
internal::RefTypeTraits<T>::GetMessageFieldDescriptor());
|
||||
accessor_ = reflection->RepeatedFieldAccessor(field);
|
||||
default_instance_ =
|
||||
reflection->GetMessageFactory()->GetPrototype(field->message_type());
|
||||
}
|
||||
|
||||
void* data_;
|
||||
const AccessorType* accessor_;
|
||||
const Message* default_instance_;
|
||||
};
|
||||
|
||||
namespace internal {
|
||||
// Interfaces used to implement reflection RepeatedFieldRef API.
|
||||
// Reflection::GetRepeatedAccessor() should return a pointer to an singleton
|
||||
// object that implements the below interface.
|
||||
//
|
||||
// This interface passes/returns values using void pointers. The actual type
|
||||
// of the value depends on the field's cpp_type. Following is a mapping from
|
||||
// cpp_type to the type that should be used in this interface:
|
||||
//
|
||||
// field->cpp_type() T Actual type of void*
|
||||
// CPPTYPE_INT32 int32_t int32_t
|
||||
// CPPTYPE_UINT32 uint32_t uint32_t
|
||||
// CPPTYPE_INT64 int64_t int64_t
|
||||
// CPPTYPE_UINT64 uint64_t uint64_t
|
||||
// CPPTYPE_DOUBLE double double
|
||||
// CPPTYPE_FLOAT float float
|
||||
// CPPTYPE_BOOL bool bool
|
||||
// CPPTYPE_ENUM generated enum type int32_t
|
||||
// CPPTYPE_STRING string std::string
|
||||
// CPPTYPE_MESSAGE generated message type google::protobuf::Message
|
||||
// or google::protobuf::Message
|
||||
//
|
||||
// Note that for enums we use int32_t in the interface.
|
||||
//
|
||||
// You can map from T to the actual type using RefTypeTraits:
|
||||
// typedef RefTypeTraits<T>::AccessorValueType ActualType;
|
||||
class PROTOBUF_EXPORT RepeatedFieldAccessor {
|
||||
public:
|
||||
// Typedefs for clarity.
|
||||
typedef void Field;
|
||||
typedef void Value;
|
||||
typedef void Iterator;
|
||||
|
||||
virtual bool IsEmpty(const Field* data) const = 0;
|
||||
virtual int Size(const Field* data) const = 0;
|
||||
// Depends on the underlying representation of the repeated field, this
|
||||
// method can return a pointer to the underlying object if such an object
|
||||
// exists, or fill the data into scratch_space and return scratch_space.
|
||||
// Callers of this method must ensure scratch_space is a valid pointer
|
||||
// to a mutable object of the correct type.
|
||||
virtual const Value* Get(const Field* data, int index,
|
||||
Value* scratch_space) const = 0;
|
||||
|
||||
virtual void Clear(Field* data) const = 0;
|
||||
virtual void Set(Field* data, int index, const Value* value) const = 0;
|
||||
virtual void Add(Field* data, const Value* value) const = 0;
|
||||
virtual void RemoveLast(Field* data) const = 0;
|
||||
virtual void SwapElements(Field* data, int index1, int index2) const = 0;
|
||||
virtual void Swap(Field* data, const RepeatedFieldAccessor* other_mutator,
|
||||
Field* other_data) const = 0;
|
||||
|
||||
// Create an iterator that points at the beginning of the repeated field.
|
||||
virtual Iterator* BeginIterator(const Field* data) const = 0;
|
||||
// Create an iterator that points at the end of the repeated field.
|
||||
virtual Iterator* EndIterator(const Field* data) const = 0;
|
||||
// Make a copy of an iterator and return the new copy.
|
||||
virtual Iterator* CopyIterator(const Field* data,
|
||||
const Iterator* iterator) const = 0;
|
||||
// Move an iterator to point to the next element.
|
||||
virtual Iterator* AdvanceIterator(const Field* data,
|
||||
Iterator* iterator) const = 0;
|
||||
// Compare whether two iterators point to the same element.
|
||||
virtual bool EqualsIterator(const Field* data, const Iterator* a,
|
||||
const Iterator* b) const = 0;
|
||||
// Delete an iterator created by BeginIterator(), EndIterator() and
|
||||
// CopyIterator().
|
||||
virtual void DeleteIterator(const Field* data, Iterator* iterator) const = 0;
|
||||
// Like Get() but for iterators.
|
||||
virtual const Value* GetIteratorValue(const Field* data,
|
||||
const Iterator* iterator,
|
||||
Value* scratch_space) const = 0;
|
||||
|
||||
// Templated methods that make using this interface easier for non-message
|
||||
// types.
|
||||
template <typename T>
|
||||
T Get(const Field* data, int index) const {
|
||||
typedef typename RefTypeTraits<T>::AccessorValueType ActualType;
|
||||
ActualType scratch_space;
|
||||
return static_cast<T>(*reinterpret_cast<const ActualType*>(
|
||||
Get(data, index, static_cast<Value*>(&scratch_space))));
|
||||
}
|
||||
|
||||
template <typename T, typename ValueType>
|
||||
void Set(Field* data, int index, const ValueType& value) const {
|
||||
typedef typename RefTypeTraits<T>::AccessorValueType ActualType;
|
||||
// In this RepeatedFieldAccessor interface we pass/return data using
|
||||
// raw pointers. Type of the data these raw pointers point to should
|
||||
// be ActualType. Here we have a ValueType object and want a ActualType
|
||||
// pointer. We can't cast a ValueType pointer to an ActualType pointer
|
||||
// directly because their type might be different (for enums ValueType
|
||||
// may be a generated enum type while ActualType is int32_t). To be safe
|
||||
// we make a copy to get a temporary ActualType object and use it.
|
||||
ActualType tmp = static_cast<ActualType>(value);
|
||||
Set(data, index, static_cast<const Value*>(&tmp));
|
||||
}
|
||||
|
||||
template <typename T, typename ValueType>
|
||||
void Add(Field* data, const ValueType& value) const {
|
||||
typedef typename RefTypeTraits<T>::AccessorValueType ActualType;
|
||||
// In this RepeatedFieldAccessor interface we pass/return data using
|
||||
// raw pointers. Type of the data these raw pointers point to should
|
||||
// be ActualType. Here we have a ValueType object and want a ActualType
|
||||
// pointer. We can't cast a ValueType pointer to an ActualType pointer
|
||||
// directly because their type might be different (for enums ValueType
|
||||
// may be a generated enum type while ActualType is int32_t). To be safe
|
||||
// we make a copy to get a temporary ActualType object and use it.
|
||||
ActualType tmp = static_cast<ActualType>(value);
|
||||
Add(data, static_cast<const Value*>(&tmp));
|
||||
}
|
||||
|
||||
protected:
|
||||
// We want the destructor to be completely trivial as to allow it to be
|
||||
// a function local static. Hence we make it non-virtual and protected,
|
||||
// this class only live as part of a global singleton and should not be
|
||||
// deleted.
|
||||
~RepeatedFieldAccessor() = default;
|
||||
};
|
||||
|
||||
// Implement (Mutable)RepeatedFieldRef::iterator
|
||||
template <typename T>
|
||||
class RepeatedFieldRefIterator {
|
||||
typedef typename RefTypeTraits<T>::AccessorValueType AccessorValueType;
|
||||
typedef typename RefTypeTraits<T>::IteratorValueType IteratorValueType;
|
||||
typedef typename RefTypeTraits<T>::IteratorPointerType IteratorPointerType;
|
||||
|
||||
public:
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
using value_type = T;
|
||||
using pointer = T*;
|
||||
using reference = T&;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
|
||||
// Constructor for non-message fields.
|
||||
RepeatedFieldRefIterator(const void* data,
|
||||
const RepeatedFieldAccessor* accessor, bool begin)
|
||||
: data_(data),
|
||||
accessor_(accessor),
|
||||
iterator_(begin ? accessor->BeginIterator(data)
|
||||
: accessor->EndIterator(data)),
|
||||
// The end iterator must not be dereferenced, no need for scratch space.
|
||||
scratch_space_(begin ? new AccessorValueType : nullptr) {}
|
||||
// Constructor for message fields.
|
||||
RepeatedFieldRefIterator(const void* data,
|
||||
const RepeatedFieldAccessor* accessor, bool begin,
|
||||
AccessorValueType* scratch_space)
|
||||
: data_(data),
|
||||
accessor_(accessor),
|
||||
iterator_(begin ? accessor->BeginIterator(data)
|
||||
: accessor->EndIterator(data)),
|
||||
scratch_space_(scratch_space) {}
|
||||
~RepeatedFieldRefIterator() { accessor_->DeleteIterator(data_, iterator_); }
|
||||
RepeatedFieldRefIterator operator++(int) {
|
||||
RepeatedFieldRefIterator tmp(*this);
|
||||
iterator_ = accessor_->AdvanceIterator(data_, iterator_);
|
||||
return tmp;
|
||||
}
|
||||
RepeatedFieldRefIterator& operator++() {
|
||||
iterator_ = accessor_->AdvanceIterator(data_, iterator_);
|
||||
return *this;
|
||||
}
|
||||
IteratorValueType operator*() const {
|
||||
return static_cast<IteratorValueType>(
|
||||
*static_cast<const AccessorValueType*>(accessor_->GetIteratorValue(
|
||||
data_, iterator_, scratch_space_.get())));
|
||||
}
|
||||
IteratorPointerType operator->() const {
|
||||
return static_cast<IteratorPointerType>(
|
||||
accessor_->GetIteratorValue(data_, iterator_, scratch_space_.get()));
|
||||
}
|
||||
bool operator!=(const RepeatedFieldRefIterator& other) const {
|
||||
assert(data_ == other.data_);
|
||||
assert(accessor_ == other.accessor_);
|
||||
return !accessor_->EqualsIterator(data_, iterator_, other.iterator_);
|
||||
}
|
||||
bool operator==(const RepeatedFieldRefIterator& other) const {
|
||||
return !this->operator!=(other);
|
||||
}
|
||||
|
||||
RepeatedFieldRefIterator(const RepeatedFieldRefIterator& other)
|
||||
: data_(other.data_),
|
||||
accessor_(other.accessor_),
|
||||
iterator_(accessor_->CopyIterator(data_, other.iterator_)) {}
|
||||
RepeatedFieldRefIterator& operator=(const RepeatedFieldRefIterator& other) {
|
||||
if (this != &other) {
|
||||
accessor_->DeleteIterator(data_, iterator_);
|
||||
data_ = other.data_;
|
||||
accessor_ = other.accessor_;
|
||||
iterator_ = accessor_->CopyIterator(data_, other.iterator_);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
protected:
|
||||
const void* data_;
|
||||
const RepeatedFieldAccessor* accessor_;
|
||||
void* iterator_;
|
||||
std::unique_ptr<AccessorValueType> scratch_space_;
|
||||
};
|
||||
|
||||
// TypeTraits that maps the type parameter T of RepeatedFieldRef or
|
||||
// MutableRepeatedFieldRef to corresponding iterator type,
|
||||
// RepeatedFieldAccessor type, etc.
|
||||
template <typename T>
|
||||
struct PrimitiveTraits {
|
||||
static constexpr bool is_primitive = false;
|
||||
};
|
||||
#define DEFINE_PRIMITIVE(TYPE, type) \
|
||||
template <> \
|
||||
struct PrimitiveTraits<type> { \
|
||||
static const bool is_primitive = true; \
|
||||
static const FieldDescriptor::CppType cpp_type = \
|
||||
FieldDescriptor::CPPTYPE_##TYPE; \
|
||||
};
|
||||
DEFINE_PRIMITIVE(INT32, int32_t)
|
||||
DEFINE_PRIMITIVE(UINT32, uint32_t)
|
||||
DEFINE_PRIMITIVE(INT64, int64_t)
|
||||
DEFINE_PRIMITIVE(UINT64, uint64_t)
|
||||
DEFINE_PRIMITIVE(FLOAT, float)
|
||||
DEFINE_PRIMITIVE(DOUBLE, double)
|
||||
DEFINE_PRIMITIVE(BOOL, bool)
|
||||
#undef DEFINE_PRIMITIVE
|
||||
|
||||
template <typename T>
|
||||
struct RefTypeTraits<
|
||||
T, typename std::enable_if<PrimitiveTraits<T>::is_primitive>::type> {
|
||||
typedef RepeatedFieldRefIterator<T> iterator;
|
||||
typedef RepeatedFieldAccessor AccessorType;
|
||||
typedef T AccessorValueType;
|
||||
typedef T IteratorValueType;
|
||||
typedef T* IteratorPointerType;
|
||||
static constexpr FieldDescriptor::CppType cpp_type =
|
||||
PrimitiveTraits<T>::cpp_type;
|
||||
static const Descriptor* GetMessageFieldDescriptor() { return nullptr; }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct RefTypeTraits<
|
||||
T, typename std::enable_if<is_proto_enum<T>::value>::type> {
|
||||
typedef RepeatedFieldRefIterator<T> iterator;
|
||||
typedef RepeatedFieldAccessor AccessorType;
|
||||
// We use int32_t for repeated enums in RepeatedFieldAccessor.
|
||||
typedef int32_t AccessorValueType;
|
||||
typedef T IteratorValueType;
|
||||
typedef int32_t* IteratorPointerType;
|
||||
static constexpr FieldDescriptor::CppType cpp_type =
|
||||
FieldDescriptor::CPPTYPE_ENUM;
|
||||
static const Descriptor* GetMessageFieldDescriptor() { return nullptr; }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct RefTypeTraits<
|
||||
T, typename std::enable_if<std::is_same<std::string, T>::value>::type> {
|
||||
typedef RepeatedFieldRefIterator<T> iterator;
|
||||
typedef RepeatedFieldAccessor AccessorType;
|
||||
typedef std::string AccessorValueType;
|
||||
typedef const std::string IteratorValueType;
|
||||
typedef const std::string* IteratorPointerType;
|
||||
static constexpr FieldDescriptor::CppType cpp_type =
|
||||
FieldDescriptor::CPPTYPE_STRING;
|
||||
static const Descriptor* GetMessageFieldDescriptor() { return nullptr; }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct MessageDescriptorGetter {
|
||||
static const Descriptor* get() {
|
||||
return T::default_instance().GetDescriptor();
|
||||
}
|
||||
};
|
||||
template <>
|
||||
struct MessageDescriptorGetter<Message> {
|
||||
static const Descriptor* get() { return nullptr; }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct RefTypeTraits<
|
||||
T, typename std::enable_if<std::is_base_of<Message, T>::value>::type> {
|
||||
typedef RepeatedFieldRefIterator<T> iterator;
|
||||
typedef RepeatedFieldAccessor AccessorType;
|
||||
typedef Message AccessorValueType;
|
||||
typedef const T& IteratorValueType;
|
||||
typedef const T* IteratorPointerType;
|
||||
static constexpr FieldDescriptor::CppType cpp_type =
|
||||
FieldDescriptor::CPPTYPE_MESSAGE;
|
||||
static const Descriptor* GetMessageFieldDescriptor() {
|
||||
return MessageDescriptorGetter<T>::get();
|
||||
}
|
||||
};
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_REFLECTION_H__
|
||||
@@ -1,364 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_REFLECTION_INTERNAL_H__
|
||||
#define GOOGLE_PROTOBUF_REFLECTION_INTERNAL_H__
|
||||
|
||||
#include <google/protobuf/map_field.h>
|
||||
#include <google/protobuf/reflection.h>
|
||||
#include <google/protobuf/repeated_field.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
// A base class for RepeatedFieldAccessor implementations that can support
|
||||
// random-access efficiently. All iterator methods delegates the work to
|
||||
// corresponding random-access methods.
|
||||
class RandomAccessRepeatedFieldAccessor : public RepeatedFieldAccessor {
|
||||
public:
|
||||
Iterator* BeginIterator(const Field* /*data*/) const override {
|
||||
return PositionToIterator(0);
|
||||
}
|
||||
Iterator* EndIterator(const Field* data) const override {
|
||||
return PositionToIterator(this->Size(data));
|
||||
}
|
||||
Iterator* CopyIterator(const Field* /*data*/,
|
||||
const Iterator* iterator) const override {
|
||||
return const_cast<Iterator*>(iterator);
|
||||
}
|
||||
Iterator* AdvanceIterator(const Field* /*data*/,
|
||||
Iterator* iterator) const override {
|
||||
return PositionToIterator(IteratorToPosition(iterator) + 1);
|
||||
}
|
||||
bool EqualsIterator(const Field* /*data*/, const Iterator* a,
|
||||
const Iterator* b) const override {
|
||||
return a == b;
|
||||
}
|
||||
void DeleteIterator(const Field* /*data*/,
|
||||
Iterator* /*iterator*/) const override {}
|
||||
const Value* GetIteratorValue(const Field* data, const Iterator* iterator,
|
||||
Value* scratch_space) const override {
|
||||
return Get(data, static_cast<int>(IteratorToPosition(iterator)),
|
||||
scratch_space);
|
||||
}
|
||||
|
||||
protected:
|
||||
~RandomAccessRepeatedFieldAccessor() = default;
|
||||
|
||||
private:
|
||||
static intptr_t IteratorToPosition(const Iterator* iterator) {
|
||||
return reinterpret_cast<intptr_t>(iterator);
|
||||
}
|
||||
static Iterator* PositionToIterator(intptr_t position) {
|
||||
return reinterpret_cast<Iterator*>(position);
|
||||
}
|
||||
};
|
||||
|
||||
// Base class for RepeatedFieldAccessor implementations that manipulates
|
||||
// RepeatedField<T>.
|
||||
template <typename T>
|
||||
class RepeatedFieldWrapper : public RandomAccessRepeatedFieldAccessor {
|
||||
public:
|
||||
RepeatedFieldWrapper() {}
|
||||
bool IsEmpty(const Field* data) const override {
|
||||
return GetRepeatedField(data)->empty();
|
||||
}
|
||||
int Size(const Field* data) const override {
|
||||
return GetRepeatedField(data)->size();
|
||||
}
|
||||
const Value* Get(const Field* data, int index,
|
||||
Value* scratch_space) const override {
|
||||
return ConvertFromT(GetRepeatedField(data)->Get(index), scratch_space);
|
||||
}
|
||||
void Clear(Field* data) const override {
|
||||
MutableRepeatedField(data)->Clear();
|
||||
}
|
||||
void Set(Field* data, int index, const Value* value) const override {
|
||||
MutableRepeatedField(data)->Set(index, ConvertToT(value));
|
||||
}
|
||||
void Add(Field* data, const Value* value) const override {
|
||||
MutableRepeatedField(data)->Add(ConvertToT(value));
|
||||
}
|
||||
void RemoveLast(Field* data) const override {
|
||||
MutableRepeatedField(data)->RemoveLast();
|
||||
}
|
||||
void SwapElements(Field* data, int index1, int index2) const override {
|
||||
MutableRepeatedField(data)->SwapElements(index1, index2);
|
||||
}
|
||||
|
||||
protected:
|
||||
~RepeatedFieldWrapper() = default;
|
||||
typedef RepeatedField<T> RepeatedFieldType;
|
||||
static const RepeatedFieldType* GetRepeatedField(const Field* data) {
|
||||
return reinterpret_cast<const RepeatedFieldType*>(data);
|
||||
}
|
||||
static RepeatedFieldType* MutableRepeatedField(Field* data) {
|
||||
return reinterpret_cast<RepeatedFieldType*>(data);
|
||||
}
|
||||
|
||||
// Convert an object received by this accessor to an object to be stored in
|
||||
// the underlying RepeatedField.
|
||||
virtual T ConvertToT(const Value* value) const = 0;
|
||||
|
||||
// Convert an object stored in RepeatedPtrField to an object that will be
|
||||
// returned by this accessor. If the two objects have the same type (true for
|
||||
// string fields with ctype=STRING), a pointer to the source object can be
|
||||
// returned directly. Otherwise, data should be copied from value to
|
||||
// scratch_space and scratch_space should be returned.
|
||||
virtual const Value* ConvertFromT(const T& value,
|
||||
Value* scratch_space) const = 0;
|
||||
};
|
||||
|
||||
// Base class for RepeatedFieldAccessor implementations that manipulates
|
||||
// RepeatedPtrField<T>.
|
||||
template <typename T>
|
||||
class RepeatedPtrFieldWrapper : public RandomAccessRepeatedFieldAccessor {
|
||||
public:
|
||||
bool IsEmpty(const Field* data) const override {
|
||||
return GetRepeatedField(data)->empty();
|
||||
}
|
||||
int Size(const Field* data) const override {
|
||||
return GetRepeatedField(data)->size();
|
||||
}
|
||||
const Value* Get(const Field* data, int index,
|
||||
Value* scratch_space) const override {
|
||||
return ConvertFromT(GetRepeatedField(data)->Get(index), scratch_space);
|
||||
}
|
||||
void Clear(Field* data) const override {
|
||||
MutableRepeatedField(data)->Clear();
|
||||
}
|
||||
void Set(Field* data, int index, const Value* value) const override {
|
||||
ConvertToT(value, MutableRepeatedField(data)->Mutable(index));
|
||||
}
|
||||
void Add(Field* data, const Value* value) const override {
|
||||
T* allocated = New(value);
|
||||
ConvertToT(value, allocated);
|
||||
MutableRepeatedField(data)->AddAllocated(allocated);
|
||||
}
|
||||
void RemoveLast(Field* data) const override {
|
||||
MutableRepeatedField(data)->RemoveLast();
|
||||
}
|
||||
void SwapElements(Field* data, int index1, int index2) const override {
|
||||
MutableRepeatedField(data)->SwapElements(index1, index2);
|
||||
}
|
||||
|
||||
protected:
|
||||
~RepeatedPtrFieldWrapper() = default;
|
||||
typedef RepeatedPtrField<T> RepeatedFieldType;
|
||||
static const RepeatedFieldType* GetRepeatedField(const Field* data) {
|
||||
return reinterpret_cast<const RepeatedFieldType*>(data);
|
||||
}
|
||||
static RepeatedFieldType* MutableRepeatedField(Field* data) {
|
||||
return reinterpret_cast<RepeatedFieldType*>(data);
|
||||
}
|
||||
|
||||
// Create a new T instance. For repeated message fields, T can be specified
|
||||
// as google::protobuf::Message so we can't use "new T()" directly. In that case, value
|
||||
// should be a message of the same type (it's ensured by the caller) and a
|
||||
// new message object will be created using it.
|
||||
virtual T* New(const Value* value) const = 0;
|
||||
|
||||
// Convert an object received by this accessor to an object that will be
|
||||
// stored in the underlying RepeatedPtrField.
|
||||
virtual void ConvertToT(const Value* value, T* result) const = 0;
|
||||
|
||||
// Convert an object stored in RepeatedPtrField to an object that will be
|
||||
// returned by this accessor. If the two objects have the same type (true for
|
||||
// string fields with ctype=STRING), a pointer to the source object can be
|
||||
// returned directly. Otherwise, data should be copied from value to
|
||||
// scratch_space and scratch_space should be returned.
|
||||
virtual const Value* ConvertFromT(const T& value,
|
||||
Value* scratch_space) const = 0;
|
||||
};
|
||||
|
||||
// An implementation of RandomAccessRepeatedFieldAccessor that manipulates
|
||||
// MapFieldBase.
|
||||
class MapFieldAccessor final : public RandomAccessRepeatedFieldAccessor {
|
||||
public:
|
||||
MapFieldAccessor() {}
|
||||
virtual ~MapFieldAccessor() {}
|
||||
bool IsEmpty(const Field* data) const override {
|
||||
return GetRepeatedField(data)->empty();
|
||||
}
|
||||
int Size(const Field* data) const override {
|
||||
return GetRepeatedField(data)->size();
|
||||
}
|
||||
const Value* Get(const Field* data, int index,
|
||||
Value* scratch_space) const override {
|
||||
return ConvertFromEntry(GetRepeatedField(data)->Get(index), scratch_space);
|
||||
}
|
||||
void Clear(Field* data) const override {
|
||||
MutableRepeatedField(data)->Clear();
|
||||
}
|
||||
void Set(Field* data, int index, const Value* value) const override {
|
||||
ConvertToEntry(value, MutableRepeatedField(data)->Mutable(index));
|
||||
}
|
||||
void Add(Field* data, const Value* value) const override {
|
||||
Message* allocated = New(value);
|
||||
ConvertToEntry(value, allocated);
|
||||
MutableRepeatedField(data)->AddAllocated(allocated);
|
||||
}
|
||||
void RemoveLast(Field* data) const override {
|
||||
MutableRepeatedField(data)->RemoveLast();
|
||||
}
|
||||
void SwapElements(Field* data, int index1, int index2) const override {
|
||||
MutableRepeatedField(data)->SwapElements(index1, index2);
|
||||
}
|
||||
void Swap(Field* data, const internal::RepeatedFieldAccessor* other_mutator,
|
||||
Field* other_data) const override {
|
||||
GOOGLE_CHECK(this == other_mutator);
|
||||
MutableRepeatedField(data)->Swap(MutableRepeatedField(other_data));
|
||||
}
|
||||
|
||||
protected:
|
||||
typedef RepeatedPtrField<Message> RepeatedFieldType;
|
||||
static const RepeatedFieldType* GetRepeatedField(const Field* data) {
|
||||
return reinterpret_cast<const RepeatedFieldType*>(
|
||||
(&reinterpret_cast<const MapFieldBase*>(data)->GetRepeatedField()));
|
||||
}
|
||||
static RepeatedFieldType* MutableRepeatedField(Field* data) {
|
||||
return reinterpret_cast<RepeatedFieldType*>(
|
||||
reinterpret_cast<MapFieldBase*>(data)->MutableRepeatedField());
|
||||
}
|
||||
virtual Message* New(const Value* value) const {
|
||||
return static_cast<const Message*>(value)->New();
|
||||
}
|
||||
// Convert an object received by this accessor to an MapEntry message to be
|
||||
// stored in the underlying MapFieldBase.
|
||||
virtual void ConvertToEntry(const Value* value, Message* result) const {
|
||||
result->CopyFrom(*static_cast<const Message*>(value));
|
||||
}
|
||||
// Convert a MapEntry message stored in the underlying MapFieldBase to an
|
||||
// object that will be returned by this accessor.
|
||||
virtual const Value* ConvertFromEntry(const Message& value,
|
||||
Value* /*scratch_space*/) const {
|
||||
return static_cast<const Value*>(&value);
|
||||
}
|
||||
};
|
||||
|
||||
// Default implementations of RepeatedFieldAccessor for primitive types.
|
||||
template <typename T>
|
||||
class RepeatedFieldPrimitiveAccessor final : public RepeatedFieldWrapper<T> {
|
||||
typedef void Field;
|
||||
typedef void Value;
|
||||
using RepeatedFieldWrapper<T>::MutableRepeatedField;
|
||||
|
||||
public:
|
||||
RepeatedFieldPrimitiveAccessor() {}
|
||||
void Swap(Field* data, const internal::RepeatedFieldAccessor* other_mutator,
|
||||
Field* other_data) const override {
|
||||
// Currently RepeatedFieldPrimitiveAccessor is the only implementation of
|
||||
// RepeatedFieldAccessor for primitive types. As we are using singletons
|
||||
// for these accessors, here "other_mutator" must be "this".
|
||||
GOOGLE_CHECK(this == other_mutator);
|
||||
MutableRepeatedField(data)->Swap(MutableRepeatedField(other_data));
|
||||
}
|
||||
|
||||
protected:
|
||||
T ConvertToT(const Value* value) const override {
|
||||
return *static_cast<const T*>(value);
|
||||
}
|
||||
const Value* ConvertFromT(const T& value,
|
||||
Value* /*scratch_space*/) const override {
|
||||
return static_cast<const Value*>(&value);
|
||||
}
|
||||
};
|
||||
|
||||
// Default implementation of RepeatedFieldAccessor for string fields with
|
||||
// ctype=STRING.
|
||||
class RepeatedPtrFieldStringAccessor final
|
||||
: public RepeatedPtrFieldWrapper<std::string> {
|
||||
typedef void Field;
|
||||
typedef void Value;
|
||||
using RepeatedFieldAccessor::Add;
|
||||
|
||||
public:
|
||||
RepeatedPtrFieldStringAccessor() {}
|
||||
void Swap(Field* data, const internal::RepeatedFieldAccessor* other_mutator,
|
||||
Field* other_data) const override {
|
||||
if (this == other_mutator) {
|
||||
MutableRepeatedField(data)->Swap(MutableRepeatedField(other_data));
|
||||
} else {
|
||||
RepeatedPtrField<std::string> tmp;
|
||||
tmp.Swap(MutableRepeatedField(data));
|
||||
int other_size = other_mutator->Size(other_data);
|
||||
for (int i = 0; i < other_size; ++i) {
|
||||
Add<std::string>(data, other_mutator->Get<std::string>(other_data, i));
|
||||
}
|
||||
int size = Size(data);
|
||||
other_mutator->Clear(other_data);
|
||||
for (int i = 0; i < size; ++i) {
|
||||
other_mutator->Add<std::string>(other_data, tmp.Get(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
std::string* New(const Value*) const override { return new std::string(); }
|
||||
void ConvertToT(const Value* value, std::string* result) const override {
|
||||
*result = *static_cast<const std::string*>(value);
|
||||
}
|
||||
const Value* ConvertFromT(const std::string& value,
|
||||
Value* /*scratch_space*/) const override {
|
||||
return static_cast<const Value*>(&value);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class RepeatedPtrFieldMessageAccessor final
|
||||
: public RepeatedPtrFieldWrapper<Message> {
|
||||
typedef void Field;
|
||||
typedef void Value;
|
||||
|
||||
public:
|
||||
RepeatedPtrFieldMessageAccessor() {}
|
||||
void Swap(Field* data, const internal::RepeatedFieldAccessor* other_mutator,
|
||||
Field* other_data) const override {
|
||||
GOOGLE_CHECK(this == other_mutator);
|
||||
MutableRepeatedField(data)->Swap(MutableRepeatedField(other_data));
|
||||
}
|
||||
|
||||
protected:
|
||||
Message* New(const Value* value) const override {
|
||||
return static_cast<const Message*>(value)->New();
|
||||
}
|
||||
void ConvertToT(const Value* value, Message* result) const override {
|
||||
result->CopyFrom(*static_cast<const Message*>(value));
|
||||
}
|
||||
const Value* ConvertFromT(const Message& value,
|
||||
Value* /*scratch_space*/) const override {
|
||||
return static_cast<const Value*>(&value);
|
||||
}
|
||||
};
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_REFLECTION_INTERNAL_H__
|
||||
@@ -1,92 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
//
|
||||
// This header is logically internal, but is made public because it is used
|
||||
// from protocol-compiler-generated code, which may reside in other components.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_REFLECTION_OPS_H__
|
||||
#define GOOGLE_PROTOBUF_REFLECTION_OPS_H__
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/message.h>
|
||||
|
||||
#ifdef SWIG
|
||||
#error "You cannot SWIG proto headers"
|
||||
#endif
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
// Basic operations that can be performed using reflection.
|
||||
// These can be used as a cheap way to implement the corresponding
|
||||
// methods of the Message interface, though they are likely to be
|
||||
// slower than implementations tailored for the specific message type.
|
||||
//
|
||||
// This class should stay limited to operations needed to implement
|
||||
// the Message interface.
|
||||
//
|
||||
// This class is really a namespace that contains only static methods.
|
||||
class PROTOBUF_EXPORT ReflectionOps {
|
||||
public:
|
||||
static void Copy(const Message& from, Message* to);
|
||||
static void Merge(const Message& from, Message* to);
|
||||
static void Clear(Message* message);
|
||||
static bool IsInitialized(const Message& message);
|
||||
static bool IsInitialized(const Message& message, bool check_fields,
|
||||
bool check_descendants);
|
||||
static void DiscardUnknownFields(Message* message);
|
||||
|
||||
// Finds all unset required fields in the message and adds their full
|
||||
// paths (e.g. "foo.bar[5].baz") to *names. "prefix" will be attached to
|
||||
// the front of each name.
|
||||
static void FindInitializationErrors(const Message& message,
|
||||
const std::string& prefix,
|
||||
std::vector<std::string>* errors);
|
||||
|
||||
private:
|
||||
// All methods are static. No need to construct.
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ReflectionOps);
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_REFLECTION_OPS_H__
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,295 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
//
|
||||
// DEPRECATED: This module declares the abstract interfaces underlying proto2
|
||||
// RPC services. These are intended to be independent of any particular RPC
|
||||
// implementation, so that proto2 services can be used on top of a variety
|
||||
// of implementations. Starting with version 2.3.0, RPC implementations should
|
||||
// not try to build on these, but should instead provide code generator plugins
|
||||
// which generate code specific to the particular RPC implementation. This way
|
||||
// the generated code can be more appropriate for the implementation in use
|
||||
// and can avoid unnecessary layers of indirection.
|
||||
//
|
||||
//
|
||||
// When you use the protocol compiler to compile a service definition, it
|
||||
// generates two classes: An abstract interface for the service (with
|
||||
// methods matching the service definition) and a "stub" implementation.
|
||||
// A stub is just a type-safe wrapper around an RpcChannel which emulates a
|
||||
// local implementation of the service.
|
||||
//
|
||||
// For example, the service definition:
|
||||
// service MyService {
|
||||
// rpc Foo(MyRequest) returns(MyResponse);
|
||||
// }
|
||||
// will generate abstract interface "MyService" and class "MyService::Stub".
|
||||
// You could implement a MyService as follows:
|
||||
// class MyServiceImpl : public MyService {
|
||||
// public:
|
||||
// MyServiceImpl() {}
|
||||
// ~MyServiceImpl() {}
|
||||
//
|
||||
// // implements MyService ---------------------------------------
|
||||
//
|
||||
// void Foo(google::protobuf::RpcController* controller,
|
||||
// const MyRequest* request,
|
||||
// MyResponse* response,
|
||||
// Closure* done) {
|
||||
// // ... read request and fill in response ...
|
||||
// done->Run();
|
||||
// }
|
||||
// };
|
||||
// You would then register an instance of MyServiceImpl with your RPC server
|
||||
// implementation. (How to do that depends on the implementation.)
|
||||
//
|
||||
// To call a remote MyServiceImpl, first you need an RpcChannel connected to it.
|
||||
// How to construct a channel depends, again, on your RPC implementation.
|
||||
// Here we use a hypothetical "MyRpcChannel" as an example:
|
||||
// MyRpcChannel channel("rpc:hostname:1234/myservice");
|
||||
// MyRpcController controller;
|
||||
// MyServiceImpl::Stub stub(&channel);
|
||||
// FooRequest request;
|
||||
// FooResponse response;
|
||||
//
|
||||
// // ... fill in request ...
|
||||
//
|
||||
// stub.Foo(&controller, request, &response, NewCallback(HandleResponse));
|
||||
//
|
||||
// On Thread-Safety:
|
||||
//
|
||||
// Different RPC implementations may make different guarantees about what
|
||||
// threads they may run callbacks on, and what threads the application is
|
||||
// allowed to use to call the RPC system. Portable software should be ready
|
||||
// for callbacks to be called on any thread, but should not try to call the
|
||||
// RPC system from any thread except for the ones on which it received the
|
||||
// callbacks. Realistically, though, simple software will probably want to
|
||||
// use a single-threaded RPC system while high-end software will want to
|
||||
// use multiple threads. RPC implementations should provide multiple
|
||||
// choices.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_SERVICE_H__
|
||||
#define GOOGLE_PROTOBUF_SERVICE_H__
|
||||
|
||||
|
||||
#include <string>
|
||||
#include <google/protobuf/stubs/callback.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
#ifdef SWIG
|
||||
#error "You cannot SWIG proto headers"
|
||||
#endif
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
// Defined in this file.
|
||||
class Service;
|
||||
class RpcController;
|
||||
class RpcChannel;
|
||||
|
||||
// Defined in other files.
|
||||
class Descriptor; // descriptor.h
|
||||
class ServiceDescriptor; // descriptor.h
|
||||
class MethodDescriptor; // descriptor.h
|
||||
class Message; // message.h
|
||||
|
||||
// Abstract base interface for protocol-buffer-based RPC services. Services
|
||||
// themselves are abstract interfaces (implemented either by servers or as
|
||||
// stubs), but they subclass this base interface. The methods of this
|
||||
// interface can be used to call the methods of the Service without knowing
|
||||
// its exact type at compile time (analogous to Reflection).
|
||||
class PROTOBUF_EXPORT Service {
|
||||
public:
|
||||
inline Service() {}
|
||||
virtual ~Service();
|
||||
|
||||
// When constructing a stub, you may pass STUB_OWNS_CHANNEL as the second
|
||||
// parameter to the constructor to tell it to delete its RpcChannel when
|
||||
// destroyed.
|
||||
enum ChannelOwnership { STUB_OWNS_CHANNEL, STUB_DOESNT_OWN_CHANNEL };
|
||||
|
||||
// Get the ServiceDescriptor describing this service and its methods.
|
||||
virtual const ServiceDescriptor* GetDescriptor() = 0;
|
||||
|
||||
// Call a method of the service specified by MethodDescriptor. This is
|
||||
// normally implemented as a simple switch() that calls the standard
|
||||
// definitions of the service's methods.
|
||||
//
|
||||
// Preconditions:
|
||||
// * method->service() == GetDescriptor()
|
||||
// * request and response are of the exact same classes as the objects
|
||||
// returned by GetRequestPrototype(method) and
|
||||
// GetResponsePrototype(method).
|
||||
// * After the call has started, the request must not be modified and the
|
||||
// response must not be accessed at all until "done" is called.
|
||||
// * "controller" is of the correct type for the RPC implementation being
|
||||
// used by this Service. For stubs, the "correct type" depends on the
|
||||
// RpcChannel which the stub is using. Server-side Service
|
||||
// implementations are expected to accept whatever type of RpcController
|
||||
// the server-side RPC implementation uses.
|
||||
//
|
||||
// Postconditions:
|
||||
// * "done" will be called when the method is complete. This may be
|
||||
// before CallMethod() returns or it may be at some point in the future.
|
||||
// * If the RPC succeeded, "response" contains the response returned by
|
||||
// the server.
|
||||
// * If the RPC failed, "response"'s contents are undefined. The
|
||||
// RpcController can be queried to determine if an error occurred and
|
||||
// possibly to get more information about the error.
|
||||
virtual void CallMethod(const MethodDescriptor* method,
|
||||
RpcController* controller, const Message* request,
|
||||
Message* response, Closure* done) = 0;
|
||||
|
||||
// CallMethod() requires that the request and response passed in are of a
|
||||
// particular subclass of Message. GetRequestPrototype() and
|
||||
// GetResponsePrototype() get the default instances of these required types.
|
||||
// You can then call Message::New() on these instances to construct mutable
|
||||
// objects which you can then pass to CallMethod().
|
||||
//
|
||||
// Example:
|
||||
// const MethodDescriptor* method =
|
||||
// service->GetDescriptor()->FindMethodByName("Foo");
|
||||
// Message* request = stub->GetRequestPrototype (method)->New();
|
||||
// Message* response = stub->GetResponsePrototype(method)->New();
|
||||
// request->ParseFromString(input);
|
||||
// service->CallMethod(method, *request, response, callback);
|
||||
virtual const Message& GetRequestPrototype(
|
||||
const MethodDescriptor* method) const = 0;
|
||||
virtual const Message& GetResponsePrototype(
|
||||
const MethodDescriptor* method) const = 0;
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Service);
|
||||
};
|
||||
|
||||
// An RpcController mediates a single method call. The primary purpose of
|
||||
// the controller is to provide a way to manipulate settings specific to the
|
||||
// RPC implementation and to find out about RPC-level errors.
|
||||
//
|
||||
// The methods provided by the RpcController interface are intended to be a
|
||||
// "least common denominator" set of features which we expect all
|
||||
// implementations to support. Specific implementations may provide more
|
||||
// advanced features (e.g. deadline propagation).
|
||||
class PROTOBUF_EXPORT RpcController {
|
||||
public:
|
||||
inline RpcController() {}
|
||||
virtual ~RpcController();
|
||||
|
||||
// Client-side methods ---------------------------------------------
|
||||
// These calls may be made from the client side only. Their results
|
||||
// are undefined on the server side (may crash).
|
||||
|
||||
// Resets the RpcController to its initial state so that it may be reused in
|
||||
// a new call. Must not be called while an RPC is in progress.
|
||||
virtual void Reset() = 0;
|
||||
|
||||
// After a call has finished, returns true if the call failed. The possible
|
||||
// reasons for failure depend on the RPC implementation. Failed() must not
|
||||
// be called before a call has finished. If Failed() returns true, the
|
||||
// contents of the response message are undefined.
|
||||
virtual bool Failed() const = 0;
|
||||
|
||||
// If Failed() is true, returns a human-readable description of the error.
|
||||
virtual std::string ErrorText() const = 0;
|
||||
|
||||
// Advises the RPC system that the caller desires that the RPC call be
|
||||
// canceled. The RPC system may cancel it immediately, may wait awhile and
|
||||
// then cancel it, or may not even cancel the call at all. If the call is
|
||||
// canceled, the "done" callback will still be called and the RpcController
|
||||
// will indicate that the call failed at that time.
|
||||
virtual void StartCancel() = 0;
|
||||
|
||||
// Server-side methods ---------------------------------------------
|
||||
// These calls may be made from the server side only. Their results
|
||||
// are undefined on the client side (may crash).
|
||||
|
||||
// Causes Failed() to return true on the client side. "reason" will be
|
||||
// incorporated into the message returned by ErrorText(). If you find
|
||||
// you need to return machine-readable information about failures, you
|
||||
// should incorporate it into your response protocol buffer and should
|
||||
// NOT call SetFailed().
|
||||
virtual void SetFailed(const std::string& reason) = 0;
|
||||
|
||||
// If true, indicates that the client canceled the RPC, so the server may
|
||||
// as well give up on replying to it. The server should still call the
|
||||
// final "done" callback.
|
||||
virtual bool IsCanceled() const = 0;
|
||||
|
||||
// Asks that the given callback be called when the RPC is canceled. The
|
||||
// callback will always be called exactly once. If the RPC completes without
|
||||
// being canceled, the callback will be called after completion. If the RPC
|
||||
// has already been canceled when NotifyOnCancel() is called, the callback
|
||||
// will be called immediately.
|
||||
//
|
||||
// NotifyOnCancel() must be called no more than once per request.
|
||||
virtual void NotifyOnCancel(Closure* callback) = 0;
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RpcController);
|
||||
};
|
||||
|
||||
// Abstract interface for an RPC channel. An RpcChannel represents a
|
||||
// communication line to a Service which can be used to call that Service's
|
||||
// methods. The Service may be running on another machine. Normally, you
|
||||
// should not call an RpcChannel directly, but instead construct a stub Service
|
||||
// wrapping it. Example:
|
||||
// RpcChannel* channel = new MyRpcChannel("remotehost.example.com:1234");
|
||||
// MyService* service = new MyService::Stub(channel);
|
||||
// service->MyMethod(request, &response, callback);
|
||||
class PROTOBUF_EXPORT RpcChannel {
|
||||
public:
|
||||
inline RpcChannel() {}
|
||||
virtual ~RpcChannel();
|
||||
|
||||
// Call the given method of the remote service. The signature of this
|
||||
// procedure looks the same as Service::CallMethod(), but the requirements
|
||||
// are less strict in one important way: the request and response objects
|
||||
// need not be of any specific class as long as their descriptors are
|
||||
// method->input_type() and method->output_type().
|
||||
virtual void CallMethod(const MethodDescriptor* method,
|
||||
RpcController* controller, const Message* request,
|
||||
Message* response, Closure* done) = 0;
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RpcChannel);
|
||||
};
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_SERVICE_H__
|
||||
@@ -1,282 +0,0 @@
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: google/protobuf/source_context.proto
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fsource_5fcontext_2eproto
|
||||
#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fsource_5fcontext_2eproto
|
||||
|
||||
#include <limits>
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/port_def.inc>
|
||||
#if PROTOBUF_VERSION < 3021000
|
||||
#error This file was generated by a newer version of protoc which is
|
||||
#error incompatible with your Protocol Buffer headers. Please update
|
||||
#error your headers.
|
||||
#endif
|
||||
#if 3021012 < PROTOBUF_MIN_PROTOC_VERSION
|
||||
#error This file was generated by an older version of protoc which is
|
||||
#error incompatible with your Protocol Buffer headers. Please
|
||||
#error regenerate this file with a newer version of protoc.
|
||||
#endif
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/arena.h>
|
||||
#include <google/protobuf/arenastring.h>
|
||||
#include <google/protobuf/generated_message_util.h>
|
||||
#include <google/protobuf/metadata_lite.h>
|
||||
#include <google/protobuf/generated_message_reflection.h>
|
||||
#include <google/protobuf/message.h>
|
||||
#include <google/protobuf/repeated_field.h> // IWYU pragma: export
|
||||
#include <google/protobuf/extension_set.h> // IWYU pragma: export
|
||||
#include <google/protobuf/unknown_field_set.h>
|
||||
// @@protoc_insertion_point(includes)
|
||||
#include <google/protobuf/port_def.inc>
|
||||
#define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fsource_5fcontext_2eproto PROTOBUF_EXPORT
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
namespace internal {
|
||||
class AnyMetadata;
|
||||
} // namespace internal
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
|
||||
// Internal implementation detail -- do not use these members.
|
||||
struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2fsource_5fcontext_2eproto {
|
||||
static const uint32_t offsets[];
|
||||
};
|
||||
PROTOBUF_EXPORT extern const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto;
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
class SourceContext;
|
||||
struct SourceContextDefaultTypeInternal;
|
||||
PROTOBUF_EXPORT extern SourceContextDefaultTypeInternal _SourceContext_default_instance_;
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::SourceContext* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::SourceContext>(Arena*);
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
|
||||
// ===================================================================
|
||||
|
||||
class PROTOBUF_EXPORT SourceContext final :
|
||||
public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.SourceContext) */ {
|
||||
public:
|
||||
inline SourceContext() : SourceContext(nullptr) {}
|
||||
~SourceContext() override;
|
||||
explicit PROTOBUF_CONSTEXPR SourceContext(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
|
||||
|
||||
SourceContext(const SourceContext& from);
|
||||
SourceContext(SourceContext&& from) noexcept
|
||||
: SourceContext() {
|
||||
*this = ::std::move(from);
|
||||
}
|
||||
|
||||
inline SourceContext& operator=(const SourceContext& from) {
|
||||
CopyFrom(from);
|
||||
return *this;
|
||||
}
|
||||
inline SourceContext& operator=(SourceContext&& from) noexcept {
|
||||
if (this == &from) return *this;
|
||||
if (GetOwningArena() == from.GetOwningArena()
|
||||
#ifdef PROTOBUF_FORCE_COPY_IN_MOVE
|
||||
&& GetOwningArena() != nullptr
|
||||
#endif // !PROTOBUF_FORCE_COPY_IN_MOVE
|
||||
) {
|
||||
InternalSwap(&from);
|
||||
} else {
|
||||
CopyFrom(from);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() {
|
||||
return GetDescriptor();
|
||||
}
|
||||
static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
|
||||
return default_instance().GetMetadata().descriptor;
|
||||
}
|
||||
static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
|
||||
return default_instance().GetMetadata().reflection;
|
||||
}
|
||||
static const SourceContext& default_instance() {
|
||||
return *internal_default_instance();
|
||||
}
|
||||
static inline const SourceContext* internal_default_instance() {
|
||||
return reinterpret_cast<const SourceContext*>(
|
||||
&_SourceContext_default_instance_);
|
||||
}
|
||||
static constexpr int kIndexInFileMessages =
|
||||
0;
|
||||
|
||||
friend void swap(SourceContext& a, SourceContext& b) {
|
||||
a.Swap(&b);
|
||||
}
|
||||
inline void Swap(SourceContext* other) {
|
||||
if (other == this) return;
|
||||
#ifdef PROTOBUF_FORCE_COPY_IN_SWAP
|
||||
if (GetOwningArena() != nullptr &&
|
||||
GetOwningArena() == other->GetOwningArena()) {
|
||||
#else // PROTOBUF_FORCE_COPY_IN_SWAP
|
||||
if (GetOwningArena() == other->GetOwningArena()) {
|
||||
#endif // !PROTOBUF_FORCE_COPY_IN_SWAP
|
||||
InternalSwap(other);
|
||||
} else {
|
||||
::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
|
||||
}
|
||||
}
|
||||
void UnsafeArenaSwap(SourceContext* other) {
|
||||
if (other == this) return;
|
||||
GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
|
||||
InternalSwap(other);
|
||||
}
|
||||
|
||||
// implements Message ----------------------------------------------
|
||||
|
||||
SourceContext* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final {
|
||||
return CreateMaybeMessage<SourceContext>(arena);
|
||||
}
|
||||
using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
|
||||
void CopyFrom(const SourceContext& from);
|
||||
using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
|
||||
void MergeFrom( const SourceContext& from) {
|
||||
SourceContext::MergeImpl(*this, from);
|
||||
}
|
||||
private:
|
||||
static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg);
|
||||
public:
|
||||
PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
|
||||
bool IsInitialized() const final;
|
||||
|
||||
size_t ByteSizeLong() const final;
|
||||
const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
|
||||
uint8_t* _InternalSerialize(
|
||||
uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
|
||||
int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
|
||||
|
||||
private:
|
||||
void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned);
|
||||
void SharedDtor();
|
||||
void SetCachedSize(int size) const final;
|
||||
void InternalSwap(SourceContext* other);
|
||||
|
||||
private:
|
||||
friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
|
||||
static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
|
||||
return "google.protobuf.SourceContext";
|
||||
}
|
||||
protected:
|
||||
explicit SourceContext(::PROTOBUF_NAMESPACE_ID::Arena* arena,
|
||||
bool is_message_owned = false);
|
||||
public:
|
||||
|
||||
static const ClassData _class_data_;
|
||||
const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
|
||||
|
||||
::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
|
||||
|
||||
// nested types ----------------------------------------------------
|
||||
|
||||
// accessors -------------------------------------------------------
|
||||
|
||||
enum : int {
|
||||
kFileNameFieldNumber = 1,
|
||||
};
|
||||
// string file_name = 1;
|
||||
void clear_file_name();
|
||||
const std::string& file_name() const;
|
||||
template <typename ArgT0 = const std::string&, typename... ArgT>
|
||||
void set_file_name(ArgT0&& arg0, ArgT... args);
|
||||
std::string* mutable_file_name();
|
||||
PROTOBUF_NODISCARD std::string* release_file_name();
|
||||
void set_allocated_file_name(std::string* file_name);
|
||||
private:
|
||||
const std::string& _internal_file_name() const;
|
||||
inline PROTOBUF_ALWAYS_INLINE void _internal_set_file_name(const std::string& value);
|
||||
std::string* _internal_mutable_file_name();
|
||||
public:
|
||||
|
||||
// @@protoc_insertion_point(class_scope:google.protobuf.SourceContext)
|
||||
private:
|
||||
class _Internal;
|
||||
|
||||
template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper;
|
||||
typedef void InternalArenaConstructable_;
|
||||
typedef void DestructorSkippable_;
|
||||
struct Impl_ {
|
||||
::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr file_name_;
|
||||
mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
|
||||
};
|
||||
union { Impl_ _impl_; };
|
||||
friend struct ::TableStruct_google_2fprotobuf_2fsource_5fcontext_2eproto;
|
||||
};
|
||||
// ===================================================================
|
||||
|
||||
|
||||
// ===================================================================
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
|
||||
#endif // __GNUC__
|
||||
// SourceContext
|
||||
|
||||
// string file_name = 1;
|
||||
inline void SourceContext::clear_file_name() {
|
||||
_impl_.file_name_.ClearToEmpty();
|
||||
}
|
||||
inline const std::string& SourceContext::file_name() const {
|
||||
// @@protoc_insertion_point(field_get:google.protobuf.SourceContext.file_name)
|
||||
return _internal_file_name();
|
||||
}
|
||||
template <typename ArgT0, typename... ArgT>
|
||||
inline PROTOBUF_ALWAYS_INLINE
|
||||
void SourceContext::set_file_name(ArgT0&& arg0, ArgT... args) {
|
||||
|
||||
_impl_.file_name_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
|
||||
// @@protoc_insertion_point(field_set:google.protobuf.SourceContext.file_name)
|
||||
}
|
||||
inline std::string* SourceContext::mutable_file_name() {
|
||||
std::string* _s = _internal_mutable_file_name();
|
||||
// @@protoc_insertion_point(field_mutable:google.protobuf.SourceContext.file_name)
|
||||
return _s;
|
||||
}
|
||||
inline const std::string& SourceContext::_internal_file_name() const {
|
||||
return _impl_.file_name_.Get();
|
||||
}
|
||||
inline void SourceContext::_internal_set_file_name(const std::string& value) {
|
||||
|
||||
_impl_.file_name_.Set(value, GetArenaForAllocation());
|
||||
}
|
||||
inline std::string* SourceContext::_internal_mutable_file_name() {
|
||||
|
||||
return _impl_.file_name_.Mutable(GetArenaForAllocation());
|
||||
}
|
||||
inline std::string* SourceContext::release_file_name() {
|
||||
// @@protoc_insertion_point(field_release:google.protobuf.SourceContext.file_name)
|
||||
return _impl_.file_name_.Release();
|
||||
}
|
||||
inline void SourceContext::set_allocated_file_name(std::string* file_name) {
|
||||
if (file_name != nullptr) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
_impl_.file_name_.SetAllocated(file_name, GetArenaForAllocation());
|
||||
#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
|
||||
if (_impl_.file_name_.IsDefault()) {
|
||||
_impl_.file_name_.Set("", GetArenaForAllocation());
|
||||
}
|
||||
#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
|
||||
// @@protoc_insertion_point(field_set_allocated:google.protobuf.SourceContext.file_name)
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif // __GNUC__
|
||||
|
||||
// @@protoc_insertion_point(namespace_scope)
|
||||
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
|
||||
// @@protoc_insertion_point(global_scope)
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
#endif // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fsource_5fcontext_2eproto
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,351 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// This file declares the ByteSink and ByteSource abstract interfaces. These
|
||||
// interfaces represent objects that consume (ByteSink) or produce (ByteSource)
|
||||
// a sequence of bytes. Using these abstract interfaces in your APIs can help
|
||||
// make your code work with a variety of input and output types.
|
||||
//
|
||||
// This file also declares the following commonly used implementations of these
|
||||
// interfaces.
|
||||
//
|
||||
// ByteSink:
|
||||
// UncheckedArrayByteSink Writes to an array, without bounds checking
|
||||
// CheckedArrayByteSink Writes to an array, with bounds checking
|
||||
// GrowingArrayByteSink Allocates and writes to a growable buffer
|
||||
// StringByteSink Writes to an STL string
|
||||
// NullByteSink Consumes a never-ending stream of bytes
|
||||
//
|
||||
// ByteSource:
|
||||
// ArrayByteSource Reads from an array or string/StringPiece
|
||||
// LimitedByteSource Limits the number of bytes read from an
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_STUBS_BYTESTREAM_H_
|
||||
#define GOOGLE_PROTOBUF_STUBS_BYTESTREAM_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/stringpiece.h>
|
||||
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
class CordByteSink;
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace strings {
|
||||
|
||||
// An abstract interface for an object that consumes a sequence of bytes. This
|
||||
// interface offers a way to append data as well as a Flush() function.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// string my_data;
|
||||
// ...
|
||||
// ByteSink* sink = ...
|
||||
// sink->Append(my_data.data(), my_data.size());
|
||||
// sink->Flush();
|
||||
//
|
||||
class PROTOBUF_EXPORT ByteSink {
|
||||
public:
|
||||
ByteSink() {}
|
||||
virtual ~ByteSink() {}
|
||||
|
||||
// Appends the "n" bytes starting at "bytes".
|
||||
virtual void Append(const char* bytes, size_t n) = 0;
|
||||
|
||||
// Flushes internal buffers. The default implementation does nothing. ByteSink
|
||||
// subclasses may use internal buffers that require calling Flush() at the end
|
||||
// of the stream.
|
||||
virtual void Flush();
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ByteSink);
|
||||
};
|
||||
|
||||
// An abstract interface for an object that produces a fixed-size sequence of
|
||||
// bytes.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// ByteSource* source = ...
|
||||
// while (source->Available() > 0) {
|
||||
// StringPiece data = source->Peek();
|
||||
// ... do something with "data" ...
|
||||
// source->Skip(data.length());
|
||||
// }
|
||||
//
|
||||
class PROTOBUF_EXPORT ByteSource {
|
||||
public:
|
||||
ByteSource() {}
|
||||
virtual ~ByteSource() {}
|
||||
|
||||
// Returns the number of bytes left to read from the source. Available()
|
||||
// should decrease by N each time Skip(N) is called. Available() may not
|
||||
// increase. Available() returning 0 indicates that the ByteSource is
|
||||
// exhausted.
|
||||
//
|
||||
// Note: Size() may have been a more appropriate name as it's more
|
||||
// indicative of the fixed-size nature of a ByteSource.
|
||||
virtual size_t Available() const = 0;
|
||||
|
||||
// Returns a StringPiece of the next contiguous region of the source. Does not
|
||||
// reposition the source. The returned region is empty iff Available() == 0.
|
||||
//
|
||||
// The returned region is valid until the next call to Skip() or until this
|
||||
// object is destroyed, whichever occurs first.
|
||||
//
|
||||
// The length of the returned StringPiece will be <= Available().
|
||||
virtual StringPiece Peek() = 0;
|
||||
|
||||
// Skips the next n bytes. Invalidates any StringPiece returned by a previous
|
||||
// call to Peek().
|
||||
//
|
||||
// REQUIRES: Available() >= n
|
||||
virtual void Skip(size_t n) = 0;
|
||||
|
||||
// Writes the next n bytes in this ByteSource to the given ByteSink, and
|
||||
// advances this ByteSource past the copied bytes. The default implementation
|
||||
// of this method just copies the bytes normally, but subclasses might
|
||||
// override CopyTo to optimize certain cases.
|
||||
//
|
||||
// REQUIRES: Available() >= n
|
||||
virtual void CopyTo(ByteSink* sink, size_t n);
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ByteSource);
|
||||
};
|
||||
|
||||
//
|
||||
// Some commonly used implementations of ByteSink
|
||||
//
|
||||
|
||||
// Implementation of ByteSink that writes to an unsized byte array. No
|
||||
// bounds-checking is performed--it is the caller's responsibility to ensure
|
||||
// that the destination array is large enough.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// char buf[10];
|
||||
// UncheckedArrayByteSink sink(buf);
|
||||
// sink.Append("hi", 2); // OK
|
||||
// sink.Append(data, 100); // WOOPS! Overflows buf[10].
|
||||
//
|
||||
class PROTOBUF_EXPORT UncheckedArrayByteSink : public ByteSink {
|
||||
public:
|
||||
explicit UncheckedArrayByteSink(char* dest) : dest_(dest) {}
|
||||
virtual void Append(const char* data, size_t n) override;
|
||||
|
||||
// Returns the current output pointer so that a caller can see how many bytes
|
||||
// were produced.
|
||||
//
|
||||
// Note: this method is not part of the ByteSink interface.
|
||||
char* CurrentDestination() const { return dest_; }
|
||||
|
||||
private:
|
||||
char* dest_;
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(UncheckedArrayByteSink);
|
||||
};
|
||||
|
||||
// Implementation of ByteSink that writes to a sized byte array. This sink will
|
||||
// not write more than "capacity" bytes to outbuf. Once "capacity" bytes are
|
||||
// appended, subsequent bytes will be ignored and Overflowed() will return true.
|
||||
// Overflowed() does not cause a runtime error (i.e., it does not CHECK fail).
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// char buf[10];
|
||||
// CheckedArrayByteSink sink(buf, 10);
|
||||
// sink.Append("hi", 2); // OK
|
||||
// sink.Append(data, 100); // Will only write 8 more bytes
|
||||
//
|
||||
class PROTOBUF_EXPORT CheckedArrayByteSink : public ByteSink {
|
||||
public:
|
||||
CheckedArrayByteSink(char* outbuf, size_t capacity);
|
||||
virtual void Append(const char* bytes, size_t n) override;
|
||||
|
||||
// Returns the number of bytes actually written to the sink.
|
||||
size_t NumberOfBytesWritten() const { return size_; }
|
||||
|
||||
// Returns true if any bytes were discarded, i.e., if there was an
|
||||
// attempt to write more than 'capacity' bytes.
|
||||
bool Overflowed() const { return overflowed_; }
|
||||
|
||||
private:
|
||||
char* outbuf_;
|
||||
const size_t capacity_;
|
||||
size_t size_;
|
||||
bool overflowed_;
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CheckedArrayByteSink);
|
||||
};
|
||||
|
||||
// Implementation of ByteSink that allocates an internal buffer (a char array)
|
||||
// and expands it as needed to accommodate appended data (similar to a string),
|
||||
// and allows the caller to take ownership of the internal buffer via the
|
||||
// GetBuffer() method. The buffer returned from GetBuffer() must be deleted by
|
||||
// the caller with delete[]. GetBuffer() also sets the internal buffer to be
|
||||
// empty, and subsequent appends to the sink will create a new buffer. The
|
||||
// destructor will free the internal buffer if GetBuffer() was not called.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// GrowingArrayByteSink sink(10);
|
||||
// sink.Append("hi", 2);
|
||||
// sink.Append(data, n);
|
||||
// const char* buf = sink.GetBuffer(); // Ownership transferred
|
||||
// delete[] buf;
|
||||
//
|
||||
class PROTOBUF_EXPORT GrowingArrayByteSink : public strings::ByteSink {
|
||||
public:
|
||||
explicit GrowingArrayByteSink(size_t estimated_size);
|
||||
virtual ~GrowingArrayByteSink();
|
||||
virtual void Append(const char* bytes, size_t n) override;
|
||||
|
||||
// Returns the allocated buffer, and sets nbytes to its size. The caller takes
|
||||
// ownership of the buffer and must delete it with delete[].
|
||||
char* GetBuffer(size_t* nbytes);
|
||||
|
||||
private:
|
||||
void Expand(size_t amount);
|
||||
void ShrinkToFit();
|
||||
|
||||
size_t capacity_;
|
||||
char* buf_;
|
||||
size_t size_;
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GrowingArrayByteSink);
|
||||
};
|
||||
|
||||
// Implementation of ByteSink that appends to the given string.
|
||||
// Existing contents of "dest" are not modified; new data is appended.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// string dest = "Hello ";
|
||||
// StringByteSink sink(&dest);
|
||||
// sink.Append("World", 5);
|
||||
// assert(dest == "Hello World");
|
||||
//
|
||||
class PROTOBUF_EXPORT StringByteSink : public ByteSink {
|
||||
public:
|
||||
explicit StringByteSink(std::string* dest) : dest_(dest) {}
|
||||
virtual void Append(const char* data, size_t n) override;
|
||||
|
||||
private:
|
||||
std::string* dest_;
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringByteSink);
|
||||
};
|
||||
|
||||
// Implementation of ByteSink that discards all data.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// NullByteSink sink;
|
||||
// sink.Append(data, data.size()); // All data ignored.
|
||||
//
|
||||
class PROTOBUF_EXPORT NullByteSink : public ByteSink {
|
||||
public:
|
||||
NullByteSink() {}
|
||||
void Append(const char* /*data*/, size_t /*n*/) override {}
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(NullByteSink);
|
||||
};
|
||||
|
||||
//
|
||||
// Some commonly used implementations of ByteSource
|
||||
//
|
||||
|
||||
// Implementation of ByteSource that reads from a StringPiece.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// string data = "Hello";
|
||||
// ArrayByteSource source(data);
|
||||
// assert(source.Available() == 5);
|
||||
// assert(source.Peek() == "Hello");
|
||||
//
|
||||
class PROTOBUF_EXPORT ArrayByteSource : public ByteSource {
|
||||
public:
|
||||
explicit ArrayByteSource(StringPiece s) : input_(s) {}
|
||||
|
||||
virtual size_t Available() const override;
|
||||
virtual StringPiece Peek() override;
|
||||
virtual void Skip(size_t n) override;
|
||||
|
||||
private:
|
||||
StringPiece input_;
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ArrayByteSource);
|
||||
};
|
||||
|
||||
// Implementation of ByteSource that wraps another ByteSource, limiting the
|
||||
// number of bytes returned.
|
||||
//
|
||||
// The caller maintains ownership of the underlying source, and may not use the
|
||||
// underlying source while using the LimitByteSource object. The underlying
|
||||
// source's pointer is advanced by n bytes every time this LimitByteSource
|
||||
// object is advanced by n.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// string data = "Hello World";
|
||||
// ArrayByteSource abs(data);
|
||||
// assert(abs.Available() == data.size());
|
||||
//
|
||||
// LimitByteSource limit(abs, 5);
|
||||
// assert(limit.Available() == 5);
|
||||
// assert(limit.Peek() == "Hello");
|
||||
//
|
||||
class PROTOBUF_EXPORT LimitByteSource : public ByteSource {
|
||||
public:
|
||||
// Returns at most "limit" bytes from "source".
|
||||
LimitByteSource(ByteSource* source, size_t limit);
|
||||
|
||||
virtual size_t Available() const override;
|
||||
virtual StringPiece Peek() override;
|
||||
virtual void Skip(size_t n) override;
|
||||
|
||||
// We override CopyTo so that we can forward to the underlying source, in
|
||||
// case it has an efficient implementation of CopyTo.
|
||||
virtual void CopyTo(ByteSink* sink, size_t n) override;
|
||||
|
||||
private:
|
||||
ByteSource* source_;
|
||||
size_t limit_;
|
||||
};
|
||||
|
||||
} // namespace strings
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_STUBS_BYTESTREAM_H_
|
||||
@@ -1,583 +0,0 @@
|
||||
#ifndef GOOGLE_PROTOBUF_STUBS_CALLBACK_H_
|
||||
#define GOOGLE_PROTOBUF_STUBS_CALLBACK_H_
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include <google/protobuf/stubs/macros.h>
|
||||
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
// ===================================================================
|
||||
// emulates google3/base/callback.h
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
// Abstract interface for a callback. When calling an RPC, you must provide
|
||||
// a Closure to call when the procedure completes. See the Service interface
|
||||
// in service.h.
|
||||
//
|
||||
// To automatically construct a Closure which calls a particular function or
|
||||
// method with a particular set of parameters, use the NewCallback() function.
|
||||
// Example:
|
||||
// void FooDone(const FooResponse* response) {
|
||||
// ...
|
||||
// }
|
||||
//
|
||||
// void CallFoo() {
|
||||
// ...
|
||||
// // When done, call FooDone() and pass it a pointer to the response.
|
||||
// Closure* callback = NewCallback(&FooDone, response);
|
||||
// // Make the call.
|
||||
// service->Foo(controller, request, response, callback);
|
||||
// }
|
||||
//
|
||||
// Example that calls a method:
|
||||
// class Handler {
|
||||
// public:
|
||||
// ...
|
||||
//
|
||||
// void FooDone(const FooResponse* response) {
|
||||
// ...
|
||||
// }
|
||||
//
|
||||
// void CallFoo() {
|
||||
// ...
|
||||
// // When done, call FooDone() and pass it a pointer to the response.
|
||||
// Closure* callback = NewCallback(this, &Handler::FooDone, response);
|
||||
// // Make the call.
|
||||
// service->Foo(controller, request, response, callback);
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// Currently NewCallback() supports binding zero, one, or two arguments.
|
||||
//
|
||||
// Callbacks created with NewCallback() automatically delete themselves when
|
||||
// executed. They should be used when a callback is to be called exactly
|
||||
// once (usually the case with RPC callbacks). If a callback may be called
|
||||
// a different number of times (including zero), create it with
|
||||
// NewPermanentCallback() instead. You are then responsible for deleting the
|
||||
// callback (using the "delete" keyword as normal).
|
||||
//
|
||||
// Note that NewCallback() is a bit touchy regarding argument types. Generally,
|
||||
// the values you provide for the parameter bindings must exactly match the
|
||||
// types accepted by the callback function. For example:
|
||||
// void Foo(std::string s);
|
||||
// NewCallback(&Foo, "foo"); // WON'T WORK: const char* != string
|
||||
// NewCallback(&Foo, std::string("foo")); // WORKS
|
||||
// Also note that the arguments cannot be references:
|
||||
// void Foo(const std::string& s);
|
||||
// std::string my_str;
|
||||
// NewCallback(&Foo, my_str); // WON'T WORK: Can't use references.
|
||||
// However, correctly-typed pointers will work just fine.
|
||||
class PROTOBUF_EXPORT Closure {
|
||||
public:
|
||||
Closure() {}
|
||||
virtual ~Closure();
|
||||
|
||||
virtual void Run() = 0;
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Closure);
|
||||
};
|
||||
|
||||
template<typename R>
|
||||
class ResultCallback {
|
||||
public:
|
||||
ResultCallback() {}
|
||||
virtual ~ResultCallback() {}
|
||||
|
||||
virtual R Run() = 0;
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ResultCallback);
|
||||
};
|
||||
|
||||
template <typename R, typename A1>
|
||||
class PROTOBUF_EXPORT ResultCallback1 {
|
||||
public:
|
||||
ResultCallback1() {}
|
||||
virtual ~ResultCallback1() {}
|
||||
|
||||
virtual R Run(A1) = 0;
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ResultCallback1);
|
||||
};
|
||||
|
||||
template <typename R, typename A1, typename A2>
|
||||
class PROTOBUF_EXPORT ResultCallback2 {
|
||||
public:
|
||||
ResultCallback2() {}
|
||||
virtual ~ResultCallback2() {}
|
||||
|
||||
virtual R Run(A1,A2) = 0;
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ResultCallback2);
|
||||
};
|
||||
|
||||
namespace internal {
|
||||
|
||||
class PROTOBUF_EXPORT FunctionClosure0 : public Closure {
|
||||
public:
|
||||
typedef void (*FunctionType)();
|
||||
|
||||
FunctionClosure0(FunctionType function, bool self_deleting)
|
||||
: function_(function), self_deleting_(self_deleting) {}
|
||||
~FunctionClosure0();
|
||||
|
||||
void Run() override {
|
||||
bool needs_delete = self_deleting_; // read in case callback deletes
|
||||
function_();
|
||||
if (needs_delete) delete this;
|
||||
}
|
||||
|
||||
private:
|
||||
FunctionType function_;
|
||||
bool self_deleting_;
|
||||
};
|
||||
|
||||
template <typename Class>
|
||||
class MethodClosure0 : public Closure {
|
||||
public:
|
||||
typedef void (Class::*MethodType)();
|
||||
|
||||
MethodClosure0(Class* object, MethodType method, bool self_deleting)
|
||||
: object_(object), method_(method), self_deleting_(self_deleting) {}
|
||||
~MethodClosure0() {}
|
||||
|
||||
void Run() override {
|
||||
bool needs_delete = self_deleting_; // read in case callback deletes
|
||||
(object_->*method_)();
|
||||
if (needs_delete) delete this;
|
||||
}
|
||||
|
||||
private:
|
||||
Class* object_;
|
||||
MethodType method_;
|
||||
bool self_deleting_;
|
||||
};
|
||||
|
||||
template <typename Arg1>
|
||||
class FunctionClosure1 : public Closure {
|
||||
public:
|
||||
typedef void (*FunctionType)(Arg1 arg1);
|
||||
|
||||
FunctionClosure1(FunctionType function, bool self_deleting,
|
||||
Arg1 arg1)
|
||||
: function_(function), self_deleting_(self_deleting),
|
||||
arg1_(arg1) {}
|
||||
~FunctionClosure1() {}
|
||||
|
||||
void Run() override {
|
||||
bool needs_delete = self_deleting_; // read in case callback deletes
|
||||
function_(arg1_);
|
||||
if (needs_delete) delete this;
|
||||
}
|
||||
|
||||
private:
|
||||
FunctionType function_;
|
||||
bool self_deleting_;
|
||||
Arg1 arg1_;
|
||||
};
|
||||
|
||||
template <typename Class, typename Arg1>
|
||||
class MethodClosure1 : public Closure {
|
||||
public:
|
||||
typedef void (Class::*MethodType)(Arg1 arg1);
|
||||
|
||||
MethodClosure1(Class* object, MethodType method, bool self_deleting,
|
||||
Arg1 arg1)
|
||||
: object_(object), method_(method), self_deleting_(self_deleting),
|
||||
arg1_(arg1) {}
|
||||
~MethodClosure1() {}
|
||||
|
||||
void Run() override {
|
||||
bool needs_delete = self_deleting_; // read in case callback deletes
|
||||
(object_->*method_)(arg1_);
|
||||
if (needs_delete) delete this;
|
||||
}
|
||||
|
||||
private:
|
||||
Class* object_;
|
||||
MethodType method_;
|
||||
bool self_deleting_;
|
||||
Arg1 arg1_;
|
||||
};
|
||||
|
||||
template <typename Arg1, typename Arg2>
|
||||
class FunctionClosure2 : public Closure {
|
||||
public:
|
||||
typedef void (*FunctionType)(Arg1 arg1, Arg2 arg2);
|
||||
|
||||
FunctionClosure2(FunctionType function, bool self_deleting,
|
||||
Arg1 arg1, Arg2 arg2)
|
||||
: function_(function), self_deleting_(self_deleting),
|
||||
arg1_(arg1), arg2_(arg2) {}
|
||||
~FunctionClosure2() {}
|
||||
|
||||
void Run() override {
|
||||
bool needs_delete = self_deleting_; // read in case callback deletes
|
||||
function_(arg1_, arg2_);
|
||||
if (needs_delete) delete this;
|
||||
}
|
||||
|
||||
private:
|
||||
FunctionType function_;
|
||||
bool self_deleting_;
|
||||
Arg1 arg1_;
|
||||
Arg2 arg2_;
|
||||
};
|
||||
|
||||
template <typename Class, typename Arg1, typename Arg2>
|
||||
class MethodClosure2 : public Closure {
|
||||
public:
|
||||
typedef void (Class::*MethodType)(Arg1 arg1, Arg2 arg2);
|
||||
|
||||
MethodClosure2(Class* object, MethodType method, bool self_deleting,
|
||||
Arg1 arg1, Arg2 arg2)
|
||||
: object_(object), method_(method), self_deleting_(self_deleting),
|
||||
arg1_(arg1), arg2_(arg2) {}
|
||||
~MethodClosure2() {}
|
||||
|
||||
void Run() override {
|
||||
bool needs_delete = self_deleting_; // read in case callback deletes
|
||||
(object_->*method_)(arg1_, arg2_);
|
||||
if (needs_delete) delete this;
|
||||
}
|
||||
|
||||
private:
|
||||
Class* object_;
|
||||
MethodType method_;
|
||||
bool self_deleting_;
|
||||
Arg1 arg1_;
|
||||
Arg2 arg2_;
|
||||
};
|
||||
|
||||
template<typename R>
|
||||
class FunctionResultCallback_0_0 : public ResultCallback<R> {
|
||||
public:
|
||||
typedef R (*FunctionType)();
|
||||
|
||||
FunctionResultCallback_0_0(FunctionType function, bool self_deleting)
|
||||
: function_(function), self_deleting_(self_deleting) {}
|
||||
~FunctionResultCallback_0_0() {}
|
||||
|
||||
R Run() override {
|
||||
bool needs_delete = self_deleting_; // read in case callback deletes
|
||||
R result = function_();
|
||||
if (needs_delete) delete this;
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
FunctionType function_;
|
||||
bool self_deleting_;
|
||||
};
|
||||
|
||||
template<typename R, typename P1>
|
||||
class FunctionResultCallback_1_0 : public ResultCallback<R> {
|
||||
public:
|
||||
typedef R (*FunctionType)(P1);
|
||||
|
||||
FunctionResultCallback_1_0(FunctionType function, bool self_deleting,
|
||||
P1 p1)
|
||||
: function_(function), self_deleting_(self_deleting), p1_(p1) {}
|
||||
~FunctionResultCallback_1_0() {}
|
||||
|
||||
R Run() override {
|
||||
bool needs_delete = self_deleting_; // read in case callback deletes
|
||||
R result = function_(p1_);
|
||||
if (needs_delete) delete this;
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
FunctionType function_;
|
||||
bool self_deleting_;
|
||||
P1 p1_;
|
||||
};
|
||||
|
||||
template<typename R, typename Arg1>
|
||||
class FunctionResultCallback_0_1 : public ResultCallback1<R, Arg1> {
|
||||
public:
|
||||
typedef R (*FunctionType)(Arg1 arg1);
|
||||
|
||||
FunctionResultCallback_0_1(FunctionType function, bool self_deleting)
|
||||
: function_(function), self_deleting_(self_deleting) {}
|
||||
~FunctionResultCallback_0_1() {}
|
||||
|
||||
R Run(Arg1 a1) override {
|
||||
bool needs_delete = self_deleting_; // read in case callback deletes
|
||||
R result = function_(a1);
|
||||
if (needs_delete) delete this;
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
FunctionType function_;
|
||||
bool self_deleting_;
|
||||
};
|
||||
|
||||
template<typename R, typename P1, typename A1>
|
||||
class FunctionResultCallback_1_1 : public ResultCallback1<R, A1> {
|
||||
public:
|
||||
typedef R (*FunctionType)(P1, A1);
|
||||
|
||||
FunctionResultCallback_1_1(FunctionType function, bool self_deleting,
|
||||
P1 p1)
|
||||
: function_(function), self_deleting_(self_deleting), p1_(p1) {}
|
||||
~FunctionResultCallback_1_1() {}
|
||||
|
||||
R Run(A1 a1) override {
|
||||
bool needs_delete = self_deleting_; // read in case callback deletes
|
||||
R result = function_(p1_, a1);
|
||||
if (needs_delete) delete this;
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
FunctionType function_;
|
||||
bool self_deleting_;
|
||||
P1 p1_;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct InternalConstRef {
|
||||
typedef typename std::remove_reference<T>::type base_type;
|
||||
typedef const base_type& type;
|
||||
};
|
||||
|
||||
template<typename R, typename T>
|
||||
class MethodResultCallback_0_0 : public ResultCallback<R> {
|
||||
public:
|
||||
typedef R (T::*MethodType)();
|
||||
MethodResultCallback_0_0(T* object, MethodType method, bool self_deleting)
|
||||
: object_(object),
|
||||
method_(method),
|
||||
self_deleting_(self_deleting) {}
|
||||
~MethodResultCallback_0_0() {}
|
||||
|
||||
R Run() {
|
||||
bool needs_delete = self_deleting_;
|
||||
R result = (object_->*method_)();
|
||||
if (needs_delete) delete this;
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
T* object_;
|
||||
MethodType method_;
|
||||
bool self_deleting_;
|
||||
};
|
||||
|
||||
template <typename R, typename T, typename P1, typename P2, typename P3,
|
||||
typename P4, typename P5, typename P6, typename A1, typename A2>
|
||||
class MethodResultCallback_6_2 : public ResultCallback2<R, A1, A2> {
|
||||
public:
|
||||
typedef R (T::*MethodType)(P1, P2, P3, P4, P5, P6, A1, A2);
|
||||
MethodResultCallback_6_2(T* object, MethodType method, bool self_deleting,
|
||||
P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6)
|
||||
: object_(object),
|
||||
method_(method),
|
||||
self_deleting_(self_deleting),
|
||||
p1_(p1),
|
||||
p2_(p2),
|
||||
p3_(p3),
|
||||
p4_(p4),
|
||||
p5_(p5),
|
||||
p6_(p6) {}
|
||||
~MethodResultCallback_6_2() {}
|
||||
|
||||
R Run(A1 a1, A2 a2) override {
|
||||
bool needs_delete = self_deleting_;
|
||||
R result = (object_->*method_)(p1_, p2_, p3_, p4_, p5_, p6_, a1, a2);
|
||||
if (needs_delete) delete this;
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
T* object_;
|
||||
MethodType method_;
|
||||
bool self_deleting_;
|
||||
typename std::remove_reference<P1>::type p1_;
|
||||
typename std::remove_reference<P2>::type p2_;
|
||||
typename std::remove_reference<P3>::type p3_;
|
||||
typename std::remove_reference<P4>::type p4_;
|
||||
typename std::remove_reference<P5>::type p5_;
|
||||
typename std::remove_reference<P6>::type p6_;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// See Closure.
|
||||
inline Closure* NewCallback(void (*function)()) {
|
||||
return new internal::FunctionClosure0(function, true);
|
||||
}
|
||||
|
||||
// See Closure.
|
||||
inline Closure* NewPermanentCallback(void (*function)()) {
|
||||
return new internal::FunctionClosure0(function, false);
|
||||
}
|
||||
|
||||
// See Closure.
|
||||
template <typename Class>
|
||||
inline Closure* NewCallback(Class* object, void (Class::*method)()) {
|
||||
return new internal::MethodClosure0<Class>(object, method, true);
|
||||
}
|
||||
|
||||
// See Closure.
|
||||
template <typename Class>
|
||||
inline Closure* NewPermanentCallback(Class* object, void (Class::*method)()) {
|
||||
return new internal::MethodClosure0<Class>(object, method, false);
|
||||
}
|
||||
|
||||
// See Closure.
|
||||
template <typename Arg1>
|
||||
inline Closure* NewCallback(void (*function)(Arg1),
|
||||
Arg1 arg1) {
|
||||
return new internal::FunctionClosure1<Arg1>(function, true, arg1);
|
||||
}
|
||||
|
||||
// See Closure.
|
||||
template <typename Arg1>
|
||||
inline Closure* NewPermanentCallback(void (*function)(Arg1),
|
||||
Arg1 arg1) {
|
||||
return new internal::FunctionClosure1<Arg1>(function, false, arg1);
|
||||
}
|
||||
|
||||
// See Closure.
|
||||
template <typename Class, typename Arg1>
|
||||
inline Closure* NewCallback(Class* object, void (Class::*method)(Arg1),
|
||||
Arg1 arg1) {
|
||||
return new internal::MethodClosure1<Class, Arg1>(object, method, true, arg1);
|
||||
}
|
||||
|
||||
// See Closure.
|
||||
template <typename Class, typename Arg1>
|
||||
inline Closure* NewPermanentCallback(Class* object, void (Class::*method)(Arg1),
|
||||
Arg1 arg1) {
|
||||
return new internal::MethodClosure1<Class, Arg1>(object, method, false, arg1);
|
||||
}
|
||||
|
||||
// See Closure.
|
||||
template <typename Arg1, typename Arg2>
|
||||
inline Closure* NewCallback(void (*function)(Arg1, Arg2),
|
||||
Arg1 arg1, Arg2 arg2) {
|
||||
return new internal::FunctionClosure2<Arg1, Arg2>(
|
||||
function, true, arg1, arg2);
|
||||
}
|
||||
|
||||
// See Closure.
|
||||
template <typename Arg1, typename Arg2>
|
||||
inline Closure* NewPermanentCallback(void (*function)(Arg1, Arg2),
|
||||
Arg1 arg1, Arg2 arg2) {
|
||||
return new internal::FunctionClosure2<Arg1, Arg2>(
|
||||
function, false, arg1, arg2);
|
||||
}
|
||||
|
||||
// See Closure.
|
||||
template <typename Class, typename Arg1, typename Arg2>
|
||||
inline Closure* NewCallback(Class* object, void (Class::*method)(Arg1, Arg2),
|
||||
Arg1 arg1, Arg2 arg2) {
|
||||
return new internal::MethodClosure2<Class, Arg1, Arg2>(
|
||||
object, method, true, arg1, arg2);
|
||||
}
|
||||
|
||||
// See Closure.
|
||||
template <typename Class, typename Arg1, typename Arg2>
|
||||
inline Closure* NewPermanentCallback(
|
||||
Class* object, void (Class::*method)(Arg1, Arg2),
|
||||
Arg1 arg1, Arg2 arg2) {
|
||||
return new internal::MethodClosure2<Class, Arg1, Arg2>(
|
||||
object, method, false, arg1, arg2);
|
||||
}
|
||||
|
||||
// See ResultCallback
|
||||
template<typename R>
|
||||
inline ResultCallback<R>* NewCallback(R (*function)()) {
|
||||
return new internal::FunctionResultCallback_0_0<R>(function, true);
|
||||
}
|
||||
|
||||
// See ResultCallback
|
||||
template<typename R>
|
||||
inline ResultCallback<R>* NewPermanentCallback(R (*function)()) {
|
||||
return new internal::FunctionResultCallback_0_0<R>(function, false);
|
||||
}
|
||||
|
||||
// See ResultCallback
|
||||
template<typename R, typename P1>
|
||||
inline ResultCallback<R>* NewCallback(R (*function)(P1), P1 p1) {
|
||||
return new internal::FunctionResultCallback_1_0<R, P1>(
|
||||
function, true, p1);
|
||||
}
|
||||
|
||||
// See ResultCallback
|
||||
template<typename R, typename P1>
|
||||
inline ResultCallback<R>* NewPermanentCallback(
|
||||
R (*function)(P1), P1 p1) {
|
||||
return new internal::FunctionResultCallback_1_0<R, P1>(
|
||||
function, false, p1);
|
||||
}
|
||||
|
||||
// See ResultCallback1
|
||||
template<typename R, typename A1>
|
||||
inline ResultCallback1<R, A1>* NewCallback(R (*function)(A1)) {
|
||||
return new internal::FunctionResultCallback_0_1<R, A1>(function, true);
|
||||
}
|
||||
|
||||
// See ResultCallback1
|
||||
template<typename R, typename A1>
|
||||
inline ResultCallback1<R, A1>* NewPermanentCallback(R (*function)(A1)) {
|
||||
return new internal::FunctionResultCallback_0_1<R, A1>(function, false);
|
||||
}
|
||||
|
||||
// See ResultCallback1
|
||||
template<typename R, typename P1, typename A1>
|
||||
inline ResultCallback1<R, A1>* NewCallback(R (*function)(P1, A1), P1 p1) {
|
||||
return new internal::FunctionResultCallback_1_1<R, P1, A1>(
|
||||
function, true, p1);
|
||||
}
|
||||
|
||||
// See ResultCallback1
|
||||
template<typename R, typename P1, typename A1>
|
||||
inline ResultCallback1<R, A1>* NewPermanentCallback(
|
||||
R (*function)(P1, A1), P1 p1) {
|
||||
return new internal::FunctionResultCallback_1_1<R, P1, A1>(
|
||||
function, false, p1);
|
||||
}
|
||||
|
||||
// See MethodResultCallback_0_0
|
||||
template <typename R, typename T1, typename T2>
|
||||
inline ResultCallback<R>* NewPermanentCallback(
|
||||
T1* object, R (T2::*function)()) {
|
||||
return new internal::MethodResultCallback_0_0<R, T1>(object, function, false);
|
||||
}
|
||||
|
||||
// See MethodResultCallback_6_2
|
||||
template <typename R, typename T, typename P1, typename P2, typename P3,
|
||||
typename P4, typename P5, typename P6, typename A1, typename A2>
|
||||
inline ResultCallback2<R, A1, A2>* NewPermanentCallback(
|
||||
T* object, R (T::*function)(P1, P2, P3, P4, P5, P6, A1, A2),
|
||||
typename internal::InternalConstRef<P1>::type p1,
|
||||
typename internal::InternalConstRef<P2>::type p2,
|
||||
typename internal::InternalConstRef<P3>::type p3,
|
||||
typename internal::InternalConstRef<P4>::type p4,
|
||||
typename internal::InternalConstRef<P5>::type p5,
|
||||
typename internal::InternalConstRef<P6>::type p6) {
|
||||
return new internal::MethodResultCallback_6_2<R, T, P1, P2, P3, P4, P5, P6,
|
||||
A1, A2>(object, function, false,
|
||||
p1, p2, p3, p4, p5, p6);
|
||||
}
|
||||
|
||||
// A function which does nothing. Useful for creating no-op callbacks, e.g.:
|
||||
// Closure* nothing = NewCallback(&DoNothing);
|
||||
void PROTOBUF_EXPORT DoNothing();
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_STUBS_CALLBACK_H_
|
||||
@@ -1,138 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2014 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_CASTS_H__
|
||||
#define GOOGLE_PROTOBUF_CASTS_H__
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
#include <google/protobuf/port_def.inc>
|
||||
#include <type_traits>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
// Use implicit_cast as a safe version of static_cast or const_cast
|
||||
// for upcasting in the type hierarchy (i.e. casting a pointer to Foo
|
||||
// to a pointer to SuperclassOfFoo or casting a pointer to Foo to
|
||||
// a const pointer to Foo).
|
||||
// When you use implicit_cast, the compiler checks that the cast is safe.
|
||||
// Such explicit implicit_casts are necessary in surprisingly many
|
||||
// situations where C++ demands an exact type match instead of an
|
||||
// argument type convertible to a target type.
|
||||
//
|
||||
// The From type can be inferred, so the preferred syntax for using
|
||||
// implicit_cast is the same as for static_cast etc.:
|
||||
//
|
||||
// implicit_cast<ToType>(expr)
|
||||
//
|
||||
// implicit_cast would have been part of the C++ standard library,
|
||||
// but the proposal was submitted too late. It will probably make
|
||||
// its way into the language in the future.
|
||||
template<typename To, typename From>
|
||||
inline To implicit_cast(From const &f) {
|
||||
return f;
|
||||
}
|
||||
|
||||
// When you upcast (that is, cast a pointer from type Foo to type
|
||||
// SuperclassOfFoo), it's fine to use implicit_cast<>, since upcasts
|
||||
// always succeed. When you downcast (that is, cast a pointer from
|
||||
// type Foo to type SubclassOfFoo), static_cast<> isn't safe, because
|
||||
// how do you know the pointer is really of type SubclassOfFoo? It
|
||||
// could be a bare Foo, or of type DifferentSubclassOfFoo. Thus,
|
||||
// when you downcast, you should use this macro. In debug mode, we
|
||||
// use dynamic_cast<> to double-check the downcast is legal (we die
|
||||
// if it's not). In normal mode, we do the efficient static_cast<>
|
||||
// instead. Thus, it's important to test in debug mode to make sure
|
||||
// the cast is legal!
|
||||
// This is the only place in the code we should use dynamic_cast<>.
|
||||
// In particular, you SHOULDN'T be using dynamic_cast<> in order to
|
||||
// do RTTI (eg code like this:
|
||||
// if (dynamic_cast<Subclass1>(foo)) HandleASubclass1Object(foo);
|
||||
// if (dynamic_cast<Subclass2>(foo)) HandleASubclass2Object(foo);
|
||||
// You should design the code some other way not to need this.
|
||||
|
||||
template<typename To, typename From> // use like this: down_cast<T*>(foo);
|
||||
inline To down_cast(From* f) { // so we only accept pointers
|
||||
// Ensures that To is a sub-type of From *. This test is here only
|
||||
// for compile-time type checking, and has no overhead in an
|
||||
// optimized build at run-time, as it will be optimized away
|
||||
// completely.
|
||||
if (false) {
|
||||
implicit_cast<From*, To>(0);
|
||||
}
|
||||
|
||||
#if !defined(NDEBUG) && PROTOBUF_RTTI
|
||||
assert(f == nullptr || dynamic_cast<To>(f) != nullptr); // RTTI: debug mode only!
|
||||
#endif
|
||||
return static_cast<To>(f);
|
||||
}
|
||||
|
||||
template<typename To, typename From> // use like this: down_cast<T&>(foo);
|
||||
inline To down_cast(From& f) {
|
||||
typedef typename std::remove_reference<To>::type* ToAsPointer;
|
||||
// Ensures that To is a sub-type of From *. This test is here only
|
||||
// for compile-time type checking, and has no overhead in an
|
||||
// optimized build at run-time, as it will be optimized away
|
||||
// completely.
|
||||
if (false) {
|
||||
implicit_cast<From*, ToAsPointer>(0);
|
||||
}
|
||||
|
||||
#if !defined(NDEBUG) && PROTOBUF_RTTI
|
||||
// RTTI: debug mode only!
|
||||
assert(dynamic_cast<ToAsPointer>(&f) != nullptr);
|
||||
#endif
|
||||
return *static_cast<ToAsPointer>(&f);
|
||||
}
|
||||
|
||||
template<typename To, typename From>
|
||||
inline To bit_cast(const From& from) {
|
||||
static_assert(sizeof(From) == sizeof(To), "bit_cast_with_different_sizes");
|
||||
To dest;
|
||||
memcpy(&dest, &from, sizeof(dest));
|
||||
return dest;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// We made these internal so that they would show up as such in the docs,
|
||||
// but we don't want to stick "internal::" in front of them everywhere.
|
||||
using internal::implicit_cast;
|
||||
using internal::down_cast;
|
||||
using internal::bit_cast;
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_CASTS_H__
|
||||
@@ -1,197 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda) and others
|
||||
//
|
||||
// Contains basic types and utilities used by the rest of the library.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_COMMON_H__
|
||||
#define GOOGLE_PROTOBUF_COMMON_H__
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <google/protobuf/stubs/macros.h>
|
||||
#include <google/protobuf/stubs/platform_macros.h>
|
||||
#include <google/protobuf/stubs/port.h>
|
||||
#include <google/protobuf/stubs/stringpiece.h>
|
||||
|
||||
#ifndef PROTOBUF_USE_EXCEPTIONS
|
||||
#if defined(_MSC_VER) && defined(_CPPUNWIND)
|
||||
#define PROTOBUF_USE_EXCEPTIONS 1
|
||||
#elif defined(__EXCEPTIONS)
|
||||
#define PROTOBUF_USE_EXCEPTIONS 1
|
||||
#else
|
||||
#define PROTOBUF_USE_EXCEPTIONS 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if PROTOBUF_USE_EXCEPTIONS
|
||||
#include <exception>
|
||||
#endif
|
||||
#if defined(__APPLE__)
|
||||
#include <TargetConditionals.h> // for TARGET_OS_IPHONE
|
||||
#endif
|
||||
|
||||
#if defined(__ANDROID__) || defined(GOOGLE_PROTOBUF_OS_ANDROID) || (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) || defined(GOOGLE_PROTOBUF_OS_IPHONE)
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace std {}
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
// Some of these constants are macros rather than const ints so that they can
|
||||
// be used in #if directives.
|
||||
|
||||
// The current version, represented as a single integer to make comparison
|
||||
// easier: major * 10^6 + minor * 10^3 + micro
|
||||
#define GOOGLE_PROTOBUF_VERSION 3021012
|
||||
|
||||
// A suffix string for alpha, beta or rc releases. Empty for stable releases.
|
||||
#define GOOGLE_PROTOBUF_VERSION_SUFFIX ""
|
||||
|
||||
// The minimum header version which works with the current version of
|
||||
// the library. This constant should only be used by protoc's C++ code
|
||||
// generator.
|
||||
static const int kMinHeaderVersionForLibrary = 3021000;
|
||||
|
||||
// The minimum protoc version which works with the current version of the
|
||||
// headers.
|
||||
#define GOOGLE_PROTOBUF_MIN_PROTOC_VERSION 3021000
|
||||
|
||||
// The minimum header version which works with the current version of
|
||||
// protoc. This constant should only be used in VerifyVersion().
|
||||
static const int kMinHeaderVersionForProtoc = 3021000;
|
||||
|
||||
// Verifies that the headers and libraries are compatible. Use the macro
|
||||
// below to call this.
|
||||
void PROTOBUF_EXPORT VerifyVersion(int headerVersion, int minLibraryVersion,
|
||||
const char* filename);
|
||||
|
||||
// Converts a numeric version number to a string.
|
||||
std::string PROTOBUF_EXPORT VersionString(int version);
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// Place this macro in your main() function (or somewhere before you attempt
|
||||
// to use the protobuf library) to verify that the version you link against
|
||||
// matches the headers you compiled against. If a version mismatch is
|
||||
// detected, the process will abort.
|
||||
#define GOOGLE_PROTOBUF_VERIFY_VERSION \
|
||||
::google::protobuf::internal::VerifyVersion( \
|
||||
GOOGLE_PROTOBUF_VERSION, GOOGLE_PROTOBUF_MIN_LIBRARY_VERSION, \
|
||||
__FILE__)
|
||||
|
||||
|
||||
// ===================================================================
|
||||
// from google3/util/utf8/public/unilib.h
|
||||
|
||||
namespace internal {
|
||||
|
||||
// Checks if the buffer contains structurally-valid UTF-8. Implemented in
|
||||
// structurally_valid.cc.
|
||||
PROTOBUF_EXPORT bool IsStructurallyValidUTF8(const char* buf, int len);
|
||||
|
||||
inline bool IsStructurallyValidUTF8(StringPiece str) {
|
||||
return IsStructurallyValidUTF8(str.data(), static_cast<int>(str.length()));
|
||||
}
|
||||
|
||||
// Returns initial number of bytes of structurally valid UTF-8.
|
||||
PROTOBUF_EXPORT int UTF8SpnStructurallyValid(StringPiece str);
|
||||
|
||||
// Coerce UTF-8 byte string in src_str to be
|
||||
// a structurally-valid equal-length string by selectively
|
||||
// overwriting illegal bytes with replace_char (typically ' ' or '?').
|
||||
// replace_char must be legal printable 7-bit Ascii 0x20..0x7e.
|
||||
// src_str is read-only.
|
||||
//
|
||||
// Returns pointer to output buffer, src_str.data() if no changes were made,
|
||||
// or idst if some bytes were changed. idst is allocated by the caller
|
||||
// and must be at least as big as src_str
|
||||
//
|
||||
// Optimized for: all structurally valid and no byte copying is done.
|
||||
//
|
||||
PROTOBUF_EXPORT char* UTF8CoerceToStructurallyValid(StringPiece str, char* dst,
|
||||
char replace_char);
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// This lives in message_lite.h now, but we leave this here for any users that
|
||||
// #include common.h and not message_lite.h.
|
||||
PROTOBUF_EXPORT void ShutdownProtobufLibrary();
|
||||
|
||||
namespace internal {
|
||||
|
||||
// Strongly references the given variable such that the linker will be forced
|
||||
// to pull in this variable's translation unit.
|
||||
template <typename T>
|
||||
void StrongReference(const T& var) {
|
||||
auto volatile unused = &var;
|
||||
(void)&unused; // Use address to avoid an extra load of "unused".
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
#if PROTOBUF_USE_EXCEPTIONS
|
||||
class FatalException : public std::exception {
|
||||
public:
|
||||
FatalException(const char* filename, int line, const std::string& message)
|
||||
: filename_(filename), line_(line), message_(message) {}
|
||||
virtual ~FatalException() throw();
|
||||
|
||||
const char* what() const throw() override;
|
||||
|
||||
const char* filename() const { return filename_; }
|
||||
int line() const { return line_; }
|
||||
const std::string& message() const { return message_; }
|
||||
|
||||
private:
|
||||
const char* filename_;
|
||||
const int line_;
|
||||
const std::string message_;
|
||||
};
|
||||
#endif
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_COMMON_H__
|
||||
@@ -1,114 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_STUBS_HASH_H__
|
||||
#define GOOGLE_PROTOBUF_STUBS_HASH_H__
|
||||
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
||||
# define GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_START \
|
||||
namespace google { \
|
||||
namespace protobuf {
|
||||
# define GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_END }}
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
template <typename Key>
|
||||
struct hash : public std::hash<Key> {};
|
||||
|
||||
template <typename Key>
|
||||
struct hash<const Key*> {
|
||||
inline size_t operator()(const Key* key) const {
|
||||
return reinterpret_cast<size_t>(key);
|
||||
}
|
||||
};
|
||||
|
||||
// Unlike the old SGI version, the TR1 "hash" does not special-case char*. So,
|
||||
// we go ahead and provide our own implementation.
|
||||
template <>
|
||||
struct hash<const char*> {
|
||||
inline size_t operator()(const char* str) const {
|
||||
size_t result = 0;
|
||||
for (; *str != '\0'; str++) {
|
||||
result = 5 * result + static_cast<size_t>(*str);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct hash<bool> {
|
||||
size_t operator()(bool x) const {
|
||||
return static_cast<size_t>(x);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct hash<std::string> {
|
||||
inline size_t operator()(const std::string& key) const {
|
||||
return hash<const char*>()(key.c_str());
|
||||
}
|
||||
|
||||
static const size_t bucket_size = 4;
|
||||
static const size_t min_buckets = 8;
|
||||
inline bool operator()(const std::string& a, const std::string& b) const {
|
||||
return a < b;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename First, typename Second>
|
||||
struct hash<std::pair<First, Second> > {
|
||||
inline size_t operator()(const std::pair<First, Second>& key) const {
|
||||
size_t first_hash = hash<First>()(key.first);
|
||||
size_t second_hash = hash<Second>()(key.second);
|
||||
|
||||
// FIXME(kenton): What is the best way to compute this hash? I have
|
||||
// no idea! This seems a bit better than an XOR.
|
||||
return first_hash * ((1 << 16) - 1) + second_hash;
|
||||
}
|
||||
|
||||
static const size_t bucket_size = 4;
|
||||
static const size_t min_buckets = 8;
|
||||
inline bool operator()(const std::pair<First, Second>& a,
|
||||
const std::pair<First, Second>& b) const {
|
||||
return a < b;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_STUBS_HASH_H__
|
||||
@@ -1,387 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef GOOGLE_PROTOBUF_STUBS_INT128_H_
|
||||
#define GOOGLE_PROTOBUF_STUBS_INT128_H_
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
#include <iosfwd>
|
||||
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
struct uint128_pod;
|
||||
|
||||
// TODO(xiaofeng): Define GOOGLE_PROTOBUF_HAS_CONSTEXPR when constexpr is
|
||||
// available.
|
||||
#ifdef GOOGLE_PROTOBUF_HAS_CONSTEXPR
|
||||
# define UINT128_CONSTEXPR constexpr
|
||||
#else
|
||||
# define UINT128_CONSTEXPR
|
||||
#endif
|
||||
|
||||
// An unsigned 128-bit integer type. Thread-compatible.
|
||||
class PROTOBUF_EXPORT uint128 {
|
||||
public:
|
||||
UINT128_CONSTEXPR uint128(); // Sets to 0, but don't trust on this behavior.
|
||||
UINT128_CONSTEXPR uint128(uint64_t top, uint64_t bottom);
|
||||
#ifndef SWIG
|
||||
UINT128_CONSTEXPR uint128(int bottom);
|
||||
UINT128_CONSTEXPR uint128(uint32_t bottom); // Top 96 bits = 0
|
||||
#endif
|
||||
UINT128_CONSTEXPR uint128(uint64_t bottom); // hi_ = 0
|
||||
UINT128_CONSTEXPR uint128(const uint128_pod &val);
|
||||
|
||||
// Trivial copy constructor, assignment operator and destructor.
|
||||
|
||||
void Initialize(uint64_t top, uint64_t bottom);
|
||||
|
||||
// Arithmetic operators.
|
||||
uint128& operator+=(const uint128& b);
|
||||
uint128& operator-=(const uint128& b);
|
||||
uint128& operator*=(const uint128& b);
|
||||
// Long division/modulo for uint128.
|
||||
uint128& operator/=(const uint128& b);
|
||||
uint128& operator%=(const uint128& b);
|
||||
uint128 operator++(int);
|
||||
uint128 operator--(int);
|
||||
uint128& operator<<=(int);
|
||||
uint128& operator>>=(int);
|
||||
uint128& operator&=(const uint128& b);
|
||||
uint128& operator|=(const uint128& b);
|
||||
uint128& operator^=(const uint128& b);
|
||||
uint128& operator++();
|
||||
uint128& operator--();
|
||||
|
||||
friend uint64_t Uint128Low64(const uint128& v);
|
||||
friend uint64_t Uint128High64(const uint128& v);
|
||||
|
||||
// We add "std::" to avoid including all of port.h.
|
||||
PROTOBUF_EXPORT friend std::ostream& operator<<(std::ostream& o,
|
||||
const uint128& b);
|
||||
|
||||
private:
|
||||
static void DivModImpl(uint128 dividend, uint128 divisor,
|
||||
uint128* quotient_ret, uint128* remainder_ret);
|
||||
|
||||
// Little-endian memory order optimizations can benefit from
|
||||
// having lo_ first, hi_ last.
|
||||
// See util/endian/endian.h and Load128/Store128 for storing a uint128.
|
||||
uint64_t lo_;
|
||||
uint64_t hi_;
|
||||
|
||||
// Not implemented, just declared for catching automatic type conversions.
|
||||
uint128(uint8_t);
|
||||
uint128(uint16_t);
|
||||
uint128(float v);
|
||||
uint128(double v);
|
||||
};
|
||||
|
||||
// This is a POD form of uint128 which can be used for static variables which
|
||||
// need to be operated on as uint128.
|
||||
struct uint128_pod {
|
||||
// Note: The ordering of fields is different than 'class uint128' but the
|
||||
// same as its 2-arg constructor. This enables more obvious initialization
|
||||
// of static instances, which is the primary reason for this struct in the
|
||||
// first place. This does not seem to defeat any optimizations wrt
|
||||
// operations involving this struct.
|
||||
uint64_t hi;
|
||||
uint64_t lo;
|
||||
};
|
||||
|
||||
PROTOBUF_EXPORT extern const uint128_pod kuint128max;
|
||||
|
||||
// allow uint128 to be logged
|
||||
PROTOBUF_EXPORT extern std::ostream& operator<<(std::ostream& o,
|
||||
const uint128& b);
|
||||
|
||||
// Methods to access low and high pieces of 128-bit value.
|
||||
// Defined externally from uint128 to facilitate conversion
|
||||
// to native 128-bit types when compilers support them.
|
||||
inline uint64_t Uint128Low64(const uint128& v) { return v.lo_; }
|
||||
inline uint64_t Uint128High64(const uint128& v) { return v.hi_; }
|
||||
|
||||
// TODO: perhaps it would be nice to have int128, a signed 128-bit type?
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Implementation details follow
|
||||
// --------------------------------------------------------------------------
|
||||
inline bool operator==(const uint128& lhs, const uint128& rhs) {
|
||||
return (Uint128Low64(lhs) == Uint128Low64(rhs) &&
|
||||
Uint128High64(lhs) == Uint128High64(rhs));
|
||||
}
|
||||
inline bool operator!=(const uint128& lhs, const uint128& rhs) {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
inline UINT128_CONSTEXPR uint128::uint128() : lo_(0), hi_(0) {}
|
||||
inline UINT128_CONSTEXPR uint128::uint128(uint64_t top, uint64_t bottom)
|
||||
: lo_(bottom), hi_(top) {}
|
||||
inline UINT128_CONSTEXPR uint128::uint128(const uint128_pod& v)
|
||||
: lo_(v.lo), hi_(v.hi) {}
|
||||
inline UINT128_CONSTEXPR uint128::uint128(uint64_t bottom)
|
||||
: lo_(bottom), hi_(0) {}
|
||||
#ifndef SWIG
|
||||
inline UINT128_CONSTEXPR uint128::uint128(uint32_t bottom)
|
||||
: lo_(bottom), hi_(0) {}
|
||||
inline UINT128_CONSTEXPR uint128::uint128(int bottom)
|
||||
: lo_(bottom), hi_(static_cast<int64_t>((bottom < 0) ? -1 : 0)) {}
|
||||
#endif
|
||||
|
||||
#undef UINT128_CONSTEXPR
|
||||
|
||||
inline void uint128::Initialize(uint64_t top, uint64_t bottom) {
|
||||
hi_ = top;
|
||||
lo_ = bottom;
|
||||
}
|
||||
|
||||
// Comparison operators.
|
||||
|
||||
#define CMP128(op) \
|
||||
inline bool operator op(const uint128& lhs, const uint128& rhs) { \
|
||||
return (Uint128High64(lhs) == Uint128High64(rhs)) ? \
|
||||
(Uint128Low64(lhs) op Uint128Low64(rhs)) : \
|
||||
(Uint128High64(lhs) op Uint128High64(rhs)); \
|
||||
}
|
||||
|
||||
CMP128(<)
|
||||
CMP128(>)
|
||||
CMP128(>=)
|
||||
CMP128(<=)
|
||||
|
||||
#undef CMP128
|
||||
|
||||
// Unary operators
|
||||
|
||||
inline uint128 operator-(const uint128& val) {
|
||||
const uint64_t hi_flip = ~Uint128High64(val);
|
||||
const uint64_t lo_flip = ~Uint128Low64(val);
|
||||
const uint64_t lo_add = lo_flip + 1;
|
||||
if (lo_add < lo_flip) {
|
||||
return uint128(hi_flip + 1, lo_add);
|
||||
}
|
||||
return uint128(hi_flip, lo_add);
|
||||
}
|
||||
|
||||
inline bool operator!(const uint128& val) {
|
||||
return !Uint128High64(val) && !Uint128Low64(val);
|
||||
}
|
||||
|
||||
// Logical operators.
|
||||
|
||||
inline uint128 operator~(const uint128& val) {
|
||||
return uint128(~Uint128High64(val), ~Uint128Low64(val));
|
||||
}
|
||||
|
||||
#define LOGIC128(op) \
|
||||
inline uint128 operator op(const uint128& lhs, const uint128& rhs) { \
|
||||
return uint128(Uint128High64(lhs) op Uint128High64(rhs), \
|
||||
Uint128Low64(lhs) op Uint128Low64(rhs)); \
|
||||
}
|
||||
|
||||
LOGIC128(|)
|
||||
LOGIC128(&)
|
||||
LOGIC128(^)
|
||||
|
||||
#undef LOGIC128
|
||||
|
||||
#define LOGICASSIGN128(op) \
|
||||
inline uint128& uint128::operator op(const uint128& other) { \
|
||||
hi_ op other.hi_; \
|
||||
lo_ op other.lo_; \
|
||||
return *this; \
|
||||
}
|
||||
|
||||
LOGICASSIGN128(|=)
|
||||
LOGICASSIGN128(&=)
|
||||
LOGICASSIGN128(^=)
|
||||
|
||||
#undef LOGICASSIGN128
|
||||
|
||||
// Shift operators.
|
||||
|
||||
inline uint128 operator<<(const uint128& val, int amount) {
|
||||
// uint64 shifts of >= 64 are undefined, so we will need some special-casing.
|
||||
if (amount < 64) {
|
||||
if (amount == 0) {
|
||||
return val;
|
||||
}
|
||||
uint64_t new_hi = (Uint128High64(val) << amount) |
|
||||
(Uint128Low64(val) >> (64 - amount));
|
||||
uint64_t new_lo = Uint128Low64(val) << amount;
|
||||
return uint128(new_hi, new_lo);
|
||||
} else if (amount < 128) {
|
||||
return uint128(Uint128Low64(val) << (amount - 64), 0);
|
||||
} else {
|
||||
return uint128(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
inline uint128 operator>>(const uint128& val, int amount) {
|
||||
// uint64 shifts of >= 64 are undefined, so we will need some special-casing.
|
||||
if (amount < 64) {
|
||||
if (amount == 0) {
|
||||
return val;
|
||||
}
|
||||
uint64_t new_hi = Uint128High64(val) >> amount;
|
||||
uint64_t new_lo = (Uint128Low64(val) >> amount) |
|
||||
(Uint128High64(val) << (64 - amount));
|
||||
return uint128(new_hi, new_lo);
|
||||
} else if (amount < 128) {
|
||||
return uint128(0, Uint128High64(val) >> (amount - 64));
|
||||
} else {
|
||||
return uint128(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
inline uint128& uint128::operator<<=(int amount) {
|
||||
// uint64 shifts of >= 64 are undefined, so we will need some special-casing.
|
||||
if (amount < 64) {
|
||||
if (amount != 0) {
|
||||
hi_ = (hi_ << amount) | (lo_ >> (64 - amount));
|
||||
lo_ = lo_ << amount;
|
||||
}
|
||||
} else if (amount < 128) {
|
||||
hi_ = lo_ << (amount - 64);
|
||||
lo_ = 0;
|
||||
} else {
|
||||
hi_ = 0;
|
||||
lo_ = 0;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline uint128& uint128::operator>>=(int amount) {
|
||||
// uint64 shifts of >= 64 are undefined, so we will need some special-casing.
|
||||
if (amount < 64) {
|
||||
if (amount != 0) {
|
||||
lo_ = (lo_ >> amount) | (hi_ << (64 - amount));
|
||||
hi_ = hi_ >> amount;
|
||||
}
|
||||
} else if (amount < 128) {
|
||||
lo_ = hi_ >> (amount - 64);
|
||||
hi_ = 0;
|
||||
} else {
|
||||
lo_ = 0;
|
||||
hi_ = 0;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline uint128 operator+(const uint128& lhs, const uint128& rhs) {
|
||||
return uint128(lhs) += rhs;
|
||||
}
|
||||
|
||||
inline uint128 operator-(const uint128& lhs, const uint128& rhs) {
|
||||
return uint128(lhs) -= rhs;
|
||||
}
|
||||
|
||||
inline uint128 operator*(const uint128& lhs, const uint128& rhs) {
|
||||
return uint128(lhs) *= rhs;
|
||||
}
|
||||
|
||||
inline uint128 operator/(const uint128& lhs, const uint128& rhs) {
|
||||
return uint128(lhs) /= rhs;
|
||||
}
|
||||
|
||||
inline uint128 operator%(const uint128& lhs, const uint128& rhs) {
|
||||
return uint128(lhs) %= rhs;
|
||||
}
|
||||
|
||||
inline uint128& uint128::operator+=(const uint128& b) {
|
||||
hi_ += b.hi_;
|
||||
uint64_t lolo = lo_ + b.lo_;
|
||||
if (lolo < lo_)
|
||||
++hi_;
|
||||
lo_ = lolo;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline uint128& uint128::operator-=(const uint128& b) {
|
||||
hi_ -= b.hi_;
|
||||
if (b.lo_ > lo_)
|
||||
--hi_;
|
||||
lo_ -= b.lo_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline uint128& uint128::operator*=(const uint128& b) {
|
||||
uint64_t a96 = hi_ >> 32;
|
||||
uint64_t a64 = hi_ & 0xffffffffu;
|
||||
uint64_t a32 = lo_ >> 32;
|
||||
uint64_t a00 = lo_ & 0xffffffffu;
|
||||
uint64_t b96 = b.hi_ >> 32;
|
||||
uint64_t b64 = b.hi_ & 0xffffffffu;
|
||||
uint64_t b32 = b.lo_ >> 32;
|
||||
uint64_t b00 = b.lo_ & 0xffffffffu;
|
||||
// multiply [a96 .. a00] x [b96 .. b00]
|
||||
// terms higher than c96 disappear off the high side
|
||||
// terms c96 and c64 are safe to ignore carry bit
|
||||
uint64_t c96 = a96 * b00 + a64 * b32 + a32 * b64 + a00 * b96;
|
||||
uint64_t c64 = a64 * b00 + a32 * b32 + a00 * b64;
|
||||
this->hi_ = (c96 << 32) + c64;
|
||||
this->lo_ = 0;
|
||||
// add terms after this one at a time to capture carry
|
||||
*this += uint128(a32 * b00) << 32;
|
||||
*this += uint128(a00 * b32) << 32;
|
||||
*this += a00 * b00;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline uint128 uint128::operator++(int) {
|
||||
uint128 tmp(*this);
|
||||
*this += 1;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
inline uint128 uint128::operator--(int) {
|
||||
uint128 tmp(*this);
|
||||
*this -= 1;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
inline uint128& uint128::operator++() {
|
||||
*this += 1;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline uint128& uint128::operator--() {
|
||||
*this -= 1;
|
||||
return *this;
|
||||
}
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_STUBS_INT128_H_
|
||||
@@ -1,239 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_STUBS_LOGGING_H_
|
||||
#define GOOGLE_PROTOBUF_STUBS_LOGGING_H_
|
||||
|
||||
#include <google/protobuf/stubs/macros.h>
|
||||
#include <google/protobuf/stubs/port.h>
|
||||
#include <google/protobuf/stubs/status.h>
|
||||
#include <google/protobuf/stubs/stringpiece.h>
|
||||
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
// ===================================================================
|
||||
// emulates google3/base/logging.h
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
enum LogLevel {
|
||||
LOGLEVEL_INFO, // Informational. This is never actually used by
|
||||
// libprotobuf.
|
||||
LOGLEVEL_WARNING, // Warns about issues that, although not technically a
|
||||
// problem now, could cause problems in the future. For
|
||||
// example, a // warning will be printed when parsing a
|
||||
// message that is near the message size limit.
|
||||
LOGLEVEL_ERROR, // An error occurred which should never happen during
|
||||
// normal use.
|
||||
LOGLEVEL_FATAL, // An error occurred from which the library cannot
|
||||
// recover. This usually indicates a programming error
|
||||
// in the code which calls the library, especially when
|
||||
// compiled in debug mode.
|
||||
|
||||
#ifdef NDEBUG
|
||||
LOGLEVEL_DFATAL = LOGLEVEL_ERROR
|
||||
#else
|
||||
LOGLEVEL_DFATAL = LOGLEVEL_FATAL
|
||||
#endif
|
||||
};
|
||||
|
||||
class uint128;
|
||||
namespace internal {
|
||||
|
||||
class LogFinisher;
|
||||
|
||||
class PROTOBUF_EXPORT LogMessage {
|
||||
public:
|
||||
LogMessage(LogLevel level, const char* filename, int line);
|
||||
~LogMessage();
|
||||
|
||||
LogMessage& operator<<(const std::string& value);
|
||||
LogMessage& operator<<(const char* value);
|
||||
LogMessage& operator<<(char value);
|
||||
LogMessage& operator<<(int value);
|
||||
LogMessage& operator<<(uint value);
|
||||
LogMessage& operator<<(long value);
|
||||
LogMessage& operator<<(unsigned long value);
|
||||
LogMessage& operator<<(long long value);
|
||||
LogMessage& operator<<(unsigned long long value);
|
||||
LogMessage& operator<<(double value);
|
||||
LogMessage& operator<<(void* value);
|
||||
LogMessage& operator<<(const StringPiece& value);
|
||||
LogMessage& operator<<(const util::Status& status);
|
||||
LogMessage& operator<<(const uint128& value);
|
||||
|
||||
private:
|
||||
friend class LogFinisher;
|
||||
void Finish();
|
||||
|
||||
LogLevel level_;
|
||||
const char* filename_;
|
||||
int line_;
|
||||
std::string message_;
|
||||
};
|
||||
|
||||
// Used to make the entire "LOG(BLAH) << etc." expression have a void return
|
||||
// type and print a newline after each message.
|
||||
class PROTOBUF_EXPORT LogFinisher {
|
||||
public:
|
||||
void operator=(LogMessage& other);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
bool IsOk(T status) { return status.ok(); }
|
||||
template<>
|
||||
inline bool IsOk(bool status) { return status; }
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// Undef everything in case we're being mixed with some other Google library
|
||||
// which already defined them itself. Presumably all Google libraries will
|
||||
// support the same syntax for these so it should not be a big deal if they
|
||||
// end up using our definitions instead.
|
||||
#undef GOOGLE_LOG
|
||||
#undef GOOGLE_LOG_IF
|
||||
|
||||
#undef GOOGLE_CHECK
|
||||
#undef GOOGLE_CHECK_OK
|
||||
#undef GOOGLE_CHECK_EQ
|
||||
#undef GOOGLE_CHECK_NE
|
||||
#undef GOOGLE_CHECK_LT
|
||||
#undef GOOGLE_CHECK_LE
|
||||
#undef GOOGLE_CHECK_GT
|
||||
#undef GOOGLE_CHECK_GE
|
||||
#undef GOOGLE_CHECK_NOTNULL
|
||||
|
||||
#undef GOOGLE_DLOG
|
||||
#undef GOOGLE_DCHECK
|
||||
#undef GOOGLE_DCHECK_OK
|
||||
#undef GOOGLE_DCHECK_EQ
|
||||
#undef GOOGLE_DCHECK_NE
|
||||
#undef GOOGLE_DCHECK_LT
|
||||
#undef GOOGLE_DCHECK_LE
|
||||
#undef GOOGLE_DCHECK_GT
|
||||
#undef GOOGLE_DCHECK_GE
|
||||
|
||||
#define GOOGLE_LOG(LEVEL) \
|
||||
::google::protobuf::internal::LogFinisher() = \
|
||||
::google::protobuf::internal::LogMessage( \
|
||||
::google::protobuf::LOGLEVEL_##LEVEL, __FILE__, __LINE__)
|
||||
#define GOOGLE_LOG_IF(LEVEL, CONDITION) \
|
||||
!(CONDITION) ? (void)0 : GOOGLE_LOG(LEVEL)
|
||||
|
||||
#define GOOGLE_CHECK(EXPRESSION) \
|
||||
GOOGLE_LOG_IF(FATAL, !(EXPRESSION)) << "CHECK failed: " #EXPRESSION ": "
|
||||
#define GOOGLE_CHECK_OK(A) GOOGLE_CHECK(::google::protobuf::internal::IsOk(A))
|
||||
#define GOOGLE_CHECK_EQ(A, B) GOOGLE_CHECK((A) == (B))
|
||||
#define GOOGLE_CHECK_NE(A, B) GOOGLE_CHECK((A) != (B))
|
||||
#define GOOGLE_CHECK_LT(A, B) GOOGLE_CHECK((A) < (B))
|
||||
#define GOOGLE_CHECK_LE(A, B) GOOGLE_CHECK((A) <= (B))
|
||||
#define GOOGLE_CHECK_GT(A, B) GOOGLE_CHECK((A) > (B))
|
||||
#define GOOGLE_CHECK_GE(A, B) GOOGLE_CHECK((A) >= (B))
|
||||
|
||||
namespace internal {
|
||||
template<typename T>
|
||||
T* CheckNotNull(const char* /* file */, int /* line */,
|
||||
const char* name, T* val) {
|
||||
if (val == nullptr) {
|
||||
GOOGLE_LOG(FATAL) << name;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
} // namespace internal
|
||||
#define GOOGLE_CHECK_NOTNULL(A) \
|
||||
::google::protobuf::internal::CheckNotNull( \
|
||||
__FILE__, __LINE__, "'" #A "' must not be nullptr", (A))
|
||||
|
||||
#ifdef NDEBUG
|
||||
|
||||
#define GOOGLE_DLOG(LEVEL) GOOGLE_LOG_IF(LEVEL, false)
|
||||
|
||||
#define GOOGLE_DCHECK(EXPRESSION) while(false) GOOGLE_CHECK(EXPRESSION)
|
||||
#define GOOGLE_DCHECK_OK(E) GOOGLE_DCHECK(::google::protobuf::internal::IsOk(E))
|
||||
#define GOOGLE_DCHECK_EQ(A, B) GOOGLE_DCHECK((A) == (B))
|
||||
#define GOOGLE_DCHECK_NE(A, B) GOOGLE_DCHECK((A) != (B))
|
||||
#define GOOGLE_DCHECK_LT(A, B) GOOGLE_DCHECK((A) < (B))
|
||||
#define GOOGLE_DCHECK_LE(A, B) GOOGLE_DCHECK((A) <= (B))
|
||||
#define GOOGLE_DCHECK_GT(A, B) GOOGLE_DCHECK((A) > (B))
|
||||
#define GOOGLE_DCHECK_GE(A, B) GOOGLE_DCHECK((A) >= (B))
|
||||
|
||||
#else // NDEBUG
|
||||
|
||||
#define GOOGLE_DLOG GOOGLE_LOG
|
||||
|
||||
#define GOOGLE_DCHECK GOOGLE_CHECK
|
||||
#define GOOGLE_DCHECK_OK GOOGLE_CHECK_OK
|
||||
#define GOOGLE_DCHECK_EQ GOOGLE_CHECK_EQ
|
||||
#define GOOGLE_DCHECK_NE GOOGLE_CHECK_NE
|
||||
#define GOOGLE_DCHECK_LT GOOGLE_CHECK_LT
|
||||
#define GOOGLE_DCHECK_LE GOOGLE_CHECK_LE
|
||||
#define GOOGLE_DCHECK_GT GOOGLE_CHECK_GT
|
||||
#define GOOGLE_DCHECK_GE GOOGLE_CHECK_GE
|
||||
|
||||
#endif // !NDEBUG
|
||||
|
||||
typedef void LogHandler(LogLevel level, const char* filename, int line,
|
||||
const std::string& message);
|
||||
|
||||
// The protobuf library sometimes writes warning and error messages to
|
||||
// stderr. These messages are primarily useful for developers, but may
|
||||
// also help end users figure out a problem. If you would prefer that
|
||||
// these messages be sent somewhere other than stderr, call SetLogHandler()
|
||||
// to set your own handler. This returns the old handler. Set the handler
|
||||
// to nullptr to ignore log messages (but see also LogSilencer, below).
|
||||
//
|
||||
// Obviously, SetLogHandler is not thread-safe. You should only call it
|
||||
// at initialization time, and probably not from library code. If you
|
||||
// simply want to suppress log messages temporarily (e.g. because you
|
||||
// have some code that tends to trigger them frequently and you know
|
||||
// the warnings are not important to you), use the LogSilencer class
|
||||
// below.
|
||||
PROTOBUF_EXPORT LogHandler* SetLogHandler(LogHandler* new_func);
|
||||
|
||||
// Create a LogSilencer if you want to temporarily suppress all log
|
||||
// messages. As long as any LogSilencer objects exist, non-fatal
|
||||
// log messages will be discarded (the current LogHandler will *not*
|
||||
// be called). Constructing a LogSilencer is thread-safe. You may
|
||||
// accidentally suppress log messages occurring in another thread, but
|
||||
// since messages are generally for debugging purposes only, this isn't
|
||||
// a big deal. If you want to intercept log messages, use SetLogHandler().
|
||||
class PROTOBUF_EXPORT LogSilencer {
|
||||
public:
|
||||
LogSilencer();
|
||||
~LogSilencer();
|
||||
};
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_STUBS_LOGGING_H_
|
||||
@@ -1,93 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_MACROS_H__
|
||||
#define GOOGLE_PROTOBUF_MACROS_H__
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
#undef GOOGLE_DISALLOW_EVIL_CONSTRUCTORS
|
||||
#define GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TypeName) \
|
||||
TypeName(const TypeName&) = delete; \
|
||||
void operator=(const TypeName&) = delete
|
||||
|
||||
#undef GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS
|
||||
#define GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
|
||||
TypeName() = delete; \
|
||||
TypeName(const TypeName&) = delete; \
|
||||
void operator=(const TypeName&) = delete
|
||||
|
||||
// ===================================================================
|
||||
// from google3/base/basictypes.h
|
||||
|
||||
// The GOOGLE_ARRAYSIZE(arr) macro returns the # of elements in an array arr.
|
||||
// The expression is a compile-time constant, and therefore can be
|
||||
// used in defining new arrays, for example.
|
||||
//
|
||||
// GOOGLE_ARRAYSIZE catches a few type errors. If you see a compiler error
|
||||
//
|
||||
// "warning: division by zero in ..."
|
||||
//
|
||||
// when using GOOGLE_ARRAYSIZE, you are (wrongfully) giving it a pointer.
|
||||
// You should only use GOOGLE_ARRAYSIZE on statically allocated arrays.
|
||||
//
|
||||
// The following comments are on the implementation details, and can
|
||||
// be ignored by the users.
|
||||
//
|
||||
// ARRAYSIZE(arr) works by inspecting sizeof(arr) (the # of bytes in
|
||||
// the array) and sizeof(*(arr)) (the # of bytes in one array
|
||||
// element). If the former is divisible by the latter, perhaps arr is
|
||||
// indeed an array, in which case the division result is the # of
|
||||
// elements in the array. Otherwise, arr cannot possibly be an array,
|
||||
// and we generate a compiler error to prevent the code from
|
||||
// compiling.
|
||||
//
|
||||
// Since the size of bool is implementation-defined, we need to cast
|
||||
// !(sizeof(a) & sizeof(*(a))) to size_t in order to ensure the final
|
||||
// result has type size_t.
|
||||
//
|
||||
// This macro is not perfect as it wrongfully accepts certain
|
||||
// pointers, namely where the pointer size is divisible by the pointee
|
||||
// size. Since all our code has to go through a 32-bit compiler,
|
||||
// where a pointer is 4 bytes, this means all pointers to a type whose
|
||||
// size is 3 or greater than 4 will be (righteously) rejected.
|
||||
//
|
||||
// Kudos to Jorg Brown for this simple and elegant implementation.
|
||||
|
||||
#undef GOOGLE_ARRAYSIZE
|
||||
#define GOOGLE_ARRAYSIZE(a) \
|
||||
((sizeof(a) / sizeof(*(a))) / \
|
||||
static_cast<size_t>(!(sizeof(a) % sizeof(*(a)))))
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_MACROS_H__
|
||||
@@ -1,769 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2014 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// from google3/util/gtl/map_util.h
|
||||
// Author: Anton Carver
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_STUBS_MAP_UTIL_H__
|
||||
#define GOOGLE_PROTOBUF_STUBS_MAP_UTIL_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
// Local implementation of RemoveConst to avoid including base/type_traits.h.
|
||||
template <class T> struct RemoveConst { typedef T type; };
|
||||
template <class T> struct RemoveConst<const T> : RemoveConst<T> {};
|
||||
} // namespace internal
|
||||
|
||||
//
|
||||
// Find*()
|
||||
//
|
||||
|
||||
// Returns a const reference to the value associated with the given key if it
|
||||
// exists. Crashes otherwise.
|
||||
//
|
||||
// This is intended as a replacement for operator[] as an rvalue (for reading)
|
||||
// when the key is guaranteed to exist.
|
||||
//
|
||||
// operator[] for lookup is discouraged for several reasons:
|
||||
// * It has a side-effect of inserting missing keys
|
||||
// * It is not thread-safe (even when it is not inserting, it can still
|
||||
// choose to resize the underlying storage)
|
||||
// * It invalidates iterators (when it chooses to resize)
|
||||
// * It default constructs a value object even if it doesn't need to
|
||||
//
|
||||
// This version assumes the key is printable, and includes it in the fatal log
|
||||
// message.
|
||||
template <class Collection>
|
||||
const typename Collection::value_type::second_type&
|
||||
FindOrDie(const Collection& collection,
|
||||
const typename Collection::value_type::first_type& key) {
|
||||
typename Collection::const_iterator it = collection.find(key);
|
||||
GOOGLE_CHECK(it != collection.end()) << "Map key not found: " << key;
|
||||
return it->second;
|
||||
}
|
||||
|
||||
// Same as above, but returns a non-const reference.
|
||||
template <class Collection>
|
||||
typename Collection::value_type::second_type&
|
||||
FindOrDie(Collection& collection, // NOLINT
|
||||
const typename Collection::value_type::first_type& key) {
|
||||
typename Collection::iterator it = collection.find(key);
|
||||
GOOGLE_CHECK(it != collection.end()) << "Map key not found: " << key;
|
||||
return it->second;
|
||||
}
|
||||
|
||||
// Same as FindOrDie above, but doesn't log the key on failure.
|
||||
template <class Collection>
|
||||
const typename Collection::value_type::second_type&
|
||||
FindOrDieNoPrint(const Collection& collection,
|
||||
const typename Collection::value_type::first_type& key) {
|
||||
typename Collection::const_iterator it = collection.find(key);
|
||||
GOOGLE_CHECK(it != collection.end()) << "Map key not found";
|
||||
return it->second;
|
||||
}
|
||||
|
||||
// Same as above, but returns a non-const reference.
|
||||
template <class Collection>
|
||||
typename Collection::value_type::second_type&
|
||||
FindOrDieNoPrint(Collection& collection, // NOLINT
|
||||
const typename Collection::value_type::first_type& key) {
|
||||
typename Collection::iterator it = collection.find(key);
|
||||
GOOGLE_CHECK(it != collection.end()) << "Map key not found";
|
||||
return it->second;
|
||||
}
|
||||
|
||||
// Returns a const reference to the value associated with the given key if it
|
||||
// exists, otherwise returns a const reference to the provided default value.
|
||||
//
|
||||
// WARNING: If a temporary object is passed as the default "value,"
|
||||
// this function will return a reference to that temporary object,
|
||||
// which will be destroyed at the end of the statement. A common
|
||||
// example: if you have a map with string values, and you pass a char*
|
||||
// as the default "value," either use the returned value immediately
|
||||
// or store it in a string (not string&).
|
||||
// Details: http://go/findwithdefault
|
||||
template <class Collection>
|
||||
const typename Collection::value_type::second_type&
|
||||
FindWithDefault(const Collection& collection,
|
||||
const typename Collection::value_type::first_type& key,
|
||||
const typename Collection::value_type::second_type& value) {
|
||||
typename Collection::const_iterator it = collection.find(key);
|
||||
if (it == collection.end()) {
|
||||
return value;
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
|
||||
// Returns a pointer to the const value associated with the given key if it
|
||||
// exists, or nullptr otherwise.
|
||||
template <class Collection>
|
||||
const typename Collection::value_type::second_type*
|
||||
FindOrNull(const Collection& collection,
|
||||
const typename Collection::value_type::first_type& key) {
|
||||
typename Collection::const_iterator it = collection.find(key);
|
||||
if (it == collection.end()) {
|
||||
return 0;
|
||||
}
|
||||
return &it->second;
|
||||
}
|
||||
|
||||
// Same as above but returns a pointer to the non-const value.
|
||||
template <class Collection>
|
||||
typename Collection::value_type::second_type*
|
||||
FindOrNull(Collection& collection, // NOLINT
|
||||
const typename Collection::value_type::first_type& key) {
|
||||
typename Collection::iterator it = collection.find(key);
|
||||
if (it == collection.end()) {
|
||||
return 0;
|
||||
}
|
||||
return &it->second;
|
||||
}
|
||||
|
||||
// Returns the pointer value associated with the given key. If none is found,
|
||||
// nullptr is returned. The function is designed to be used with a map of keys to
|
||||
// pointers.
|
||||
//
|
||||
// This function does not distinguish between a missing key and a key mapped
|
||||
// to nullptr.
|
||||
template <class Collection>
|
||||
typename Collection::value_type::second_type
|
||||
FindPtrOrNull(const Collection& collection,
|
||||
const typename Collection::value_type::first_type& key) {
|
||||
typename Collection::const_iterator it = collection.find(key);
|
||||
if (it == collection.end()) {
|
||||
return typename Collection::value_type::second_type();
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
|
||||
// Same as above, except takes non-const reference to collection.
|
||||
//
|
||||
// This function is needed for containers that propagate constness to the
|
||||
// pointee, such as boost::ptr_map.
|
||||
template <class Collection>
|
||||
typename Collection::value_type::second_type
|
||||
FindPtrOrNull(Collection& collection, // NOLINT
|
||||
const typename Collection::value_type::first_type& key) {
|
||||
typename Collection::iterator it = collection.find(key);
|
||||
if (it == collection.end()) {
|
||||
return typename Collection::value_type::second_type();
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
|
||||
// Finds the pointer value associated with the given key in a map whose values
|
||||
// are linked_ptrs. Returns nullptr if key is not found.
|
||||
template <class Collection>
|
||||
typename Collection::value_type::second_type::element_type*
|
||||
FindLinkedPtrOrNull(const Collection& collection,
|
||||
const typename Collection::value_type::first_type& key) {
|
||||
typename Collection::const_iterator it = collection.find(key);
|
||||
if (it == collection.end()) {
|
||||
return 0;
|
||||
}
|
||||
// Since linked_ptr::get() is a const member returning a non const,
|
||||
// we do not need a version of this function taking a non const collection.
|
||||
return it->second.get();
|
||||
}
|
||||
|
||||
// Same as above, but dies if the key is not found.
|
||||
template <class Collection>
|
||||
typename Collection::value_type::second_type::element_type&
|
||||
FindLinkedPtrOrDie(const Collection& collection,
|
||||
const typename Collection::value_type::first_type& key) {
|
||||
typename Collection::const_iterator it = collection.find(key);
|
||||
GOOGLE_CHECK(it != collection.end()) << "key not found: " << key;
|
||||
// Since linked_ptr::operator*() is a const member returning a non const,
|
||||
// we do not need a version of this function taking a non const collection.
|
||||
return *it->second;
|
||||
}
|
||||
|
||||
// Finds the value associated with the given key and copies it to *value (if not
|
||||
// nullptr). Returns false if the key was not found, true otherwise.
|
||||
template <class Collection, class Key, class Value>
|
||||
bool FindCopy(const Collection& collection,
|
||||
const Key& key,
|
||||
Value* const value) {
|
||||
typename Collection::const_iterator it = collection.find(key);
|
||||
if (it == collection.end()) {
|
||||
return false;
|
||||
}
|
||||
if (value) {
|
||||
*value = it->second;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// Contains*()
|
||||
//
|
||||
|
||||
// Returns true if and only if the given collection contains the given key.
|
||||
template <class Collection, class Key>
|
||||
bool ContainsKey(const Collection& collection, const Key& key) {
|
||||
return collection.find(key) != collection.end();
|
||||
}
|
||||
|
||||
// Returns true if and only if the given collection contains the given key-value
|
||||
// pair.
|
||||
template <class Collection, class Key, class Value>
|
||||
bool ContainsKeyValuePair(const Collection& collection,
|
||||
const Key& key,
|
||||
const Value& value) {
|
||||
typedef typename Collection::const_iterator const_iterator;
|
||||
std::pair<const_iterator, const_iterator> range = collection.equal_range(key);
|
||||
for (const_iterator it = range.first; it != range.second; ++it) {
|
||||
if (it->second == value) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// Insert*()
|
||||
//
|
||||
|
||||
// Inserts the given key-value pair into the collection. Returns true if and
|
||||
// only if the key from the given pair didn't previously exist. Otherwise, the
|
||||
// value in the map is replaced with the value from the given pair.
|
||||
template <class Collection>
|
||||
bool InsertOrUpdate(Collection* const collection,
|
||||
const typename Collection::value_type& vt) {
|
||||
std::pair<typename Collection::iterator, bool> ret = collection->insert(vt);
|
||||
if (!ret.second) {
|
||||
// update
|
||||
ret.first->second = vt.second;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Same as above, except that the key and value are passed separately.
|
||||
template <class Collection>
|
||||
bool InsertOrUpdate(Collection* const collection,
|
||||
const typename Collection::value_type::first_type& key,
|
||||
const typename Collection::value_type::second_type& value) {
|
||||
return InsertOrUpdate(
|
||||
collection, typename Collection::value_type(key, value));
|
||||
}
|
||||
|
||||
// Inserts/updates all the key-value pairs from the range defined by the
|
||||
// iterators "first" and "last" into the given collection.
|
||||
template <class Collection, class InputIterator>
|
||||
void InsertOrUpdateMany(Collection* const collection,
|
||||
InputIterator first, InputIterator last) {
|
||||
for (; first != last; ++first) {
|
||||
InsertOrUpdate(collection, *first);
|
||||
}
|
||||
}
|
||||
|
||||
// Change the value associated with a particular key in a map or hash_map
|
||||
// of the form map<Key, Value*> which owns the objects pointed to by the
|
||||
// value pointers. If there was an existing value for the key, it is deleted.
|
||||
// True indicates an insert took place, false indicates an update + delete.
|
||||
template <class Collection>
|
||||
bool InsertAndDeleteExisting(
|
||||
Collection* const collection,
|
||||
const typename Collection::value_type::first_type& key,
|
||||
const typename Collection::value_type::second_type& value) {
|
||||
std::pair<typename Collection::iterator, bool> ret =
|
||||
collection->insert(typename Collection::value_type(key, value));
|
||||
if (!ret.second) {
|
||||
delete ret.first->second;
|
||||
ret.first->second = value;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Inserts the given key and value into the given collection if and only if the
|
||||
// given key did NOT already exist in the collection. If the key previously
|
||||
// existed in the collection, the value is not changed. Returns true if the
|
||||
// key-value pair was inserted; returns false if the key was already present.
|
||||
template <class Collection>
|
||||
bool InsertIfNotPresent(Collection* const collection,
|
||||
const typename Collection::value_type& vt) {
|
||||
return collection->insert(vt).second;
|
||||
}
|
||||
|
||||
// Same as above except the key and value are passed separately.
|
||||
template <class Collection>
|
||||
bool InsertIfNotPresent(
|
||||
Collection* const collection,
|
||||
const typename Collection::value_type::first_type& key,
|
||||
const typename Collection::value_type::second_type& value) {
|
||||
return InsertIfNotPresent(
|
||||
collection, typename Collection::value_type(key, value));
|
||||
}
|
||||
|
||||
// Same as above except dies if the key already exists in the collection.
|
||||
template <class Collection>
|
||||
void InsertOrDie(Collection* const collection,
|
||||
const typename Collection::value_type& value) {
|
||||
GOOGLE_CHECK(InsertIfNotPresent(collection, value))
|
||||
<< "duplicate value: " << value;
|
||||
}
|
||||
|
||||
// Same as above except doesn't log the value on error.
|
||||
template <class Collection>
|
||||
void InsertOrDieNoPrint(Collection* const collection,
|
||||
const typename Collection::value_type& value) {
|
||||
GOOGLE_CHECK(InsertIfNotPresent(collection, value)) << "duplicate value.";
|
||||
}
|
||||
|
||||
// Inserts the key-value pair into the collection. Dies if key was already
|
||||
// present.
|
||||
template <class Collection>
|
||||
void InsertOrDie(Collection* const collection,
|
||||
const typename Collection::value_type::first_type& key,
|
||||
const typename Collection::value_type::second_type& data) {
|
||||
GOOGLE_CHECK(InsertIfNotPresent(collection, key, data))
|
||||
<< "duplicate key: " << key;
|
||||
}
|
||||
|
||||
// Same as above except doesn't log the key on error.
|
||||
template <class Collection>
|
||||
void InsertOrDieNoPrint(
|
||||
Collection* const collection,
|
||||
const typename Collection::value_type::first_type& key,
|
||||
const typename Collection::value_type::second_type& data) {
|
||||
GOOGLE_CHECK(InsertIfNotPresent(collection, key, data)) << "duplicate key.";
|
||||
}
|
||||
|
||||
// Inserts a new key and default-initialized value. Dies if the key was already
|
||||
// present. Returns a reference to the value. Example usage:
|
||||
//
|
||||
// map<int, SomeProto> m;
|
||||
// SomeProto& proto = InsertKeyOrDie(&m, 3);
|
||||
// proto.set_field("foo");
|
||||
template <class Collection>
|
||||
typename Collection::value_type::second_type& InsertKeyOrDie(
|
||||
Collection* const collection,
|
||||
const typename Collection::value_type::first_type& key) {
|
||||
typedef typename Collection::value_type value_type;
|
||||
std::pair<typename Collection::iterator, bool> res =
|
||||
collection->insert(value_type(key, typename value_type::second_type()));
|
||||
GOOGLE_CHECK(res.second) << "duplicate key: " << key;
|
||||
return res.first->second;
|
||||
}
|
||||
|
||||
//
|
||||
// Lookup*()
|
||||
//
|
||||
|
||||
// Looks up a given key and value pair in a collection and inserts the key-value
|
||||
// pair if it's not already present. Returns a reference to the value associated
|
||||
// with the key.
|
||||
template <class Collection>
|
||||
typename Collection::value_type::second_type&
|
||||
LookupOrInsert(Collection* const collection,
|
||||
const typename Collection::value_type& vt) {
|
||||
return collection->insert(vt).first->second;
|
||||
}
|
||||
|
||||
// Same as above except the key-value are passed separately.
|
||||
template <class Collection>
|
||||
typename Collection::value_type::second_type&
|
||||
LookupOrInsert(Collection* const collection,
|
||||
const typename Collection::value_type::first_type& key,
|
||||
const typename Collection::value_type::second_type& value) {
|
||||
return LookupOrInsert(
|
||||
collection, typename Collection::value_type(key, value));
|
||||
}
|
||||
|
||||
// Counts the number of equivalent elements in the given "sequence", and stores
|
||||
// the results in "count_map" with element as the key and count as the value.
|
||||
//
|
||||
// Example:
|
||||
// vector<string> v = {"a", "b", "c", "a", "b"};
|
||||
// map<string, int> m;
|
||||
// AddTokenCounts(v, 1, &m);
|
||||
// assert(m["a"] == 2);
|
||||
// assert(m["b"] == 2);
|
||||
// assert(m["c"] == 1);
|
||||
template <typename Sequence, typename Collection>
|
||||
void AddTokenCounts(
|
||||
const Sequence& sequence,
|
||||
const typename Collection::value_type::second_type& increment,
|
||||
Collection* const count_map) {
|
||||
for (typename Sequence::const_iterator it = sequence.begin();
|
||||
it != sequence.end(); ++it) {
|
||||
typename Collection::value_type::second_type& value =
|
||||
LookupOrInsert(count_map, *it,
|
||||
typename Collection::value_type::second_type());
|
||||
value += increment;
|
||||
}
|
||||
}
|
||||
|
||||
// Returns a reference to the value associated with key. If not found, a value
|
||||
// is default constructed on the heap and added to the map.
|
||||
//
|
||||
// This function is useful for containers of the form map<Key, Value*>, where
|
||||
// inserting a new key, value pair involves constructing a new heap-allocated
|
||||
// Value, and storing a pointer to that in the collection.
|
||||
template <class Collection>
|
||||
typename Collection::value_type::second_type&
|
||||
LookupOrInsertNew(Collection* const collection,
|
||||
const typename Collection::value_type::first_type& key) {
|
||||
typedef typename std::iterator_traits<
|
||||
typename Collection::value_type::second_type>::value_type Element;
|
||||
std::pair<typename Collection::iterator, bool> ret =
|
||||
collection->insert(typename Collection::value_type(
|
||||
key,
|
||||
static_cast<typename Collection::value_type::second_type>(nullptr)));
|
||||
if (ret.second) {
|
||||
ret.first->second = new Element();
|
||||
}
|
||||
return ret.first->second;
|
||||
}
|
||||
|
||||
// Same as above but constructs the value using the single-argument constructor
|
||||
// and the given "arg".
|
||||
template <class Collection, class Arg>
|
||||
typename Collection::value_type::second_type&
|
||||
LookupOrInsertNew(Collection* const collection,
|
||||
const typename Collection::value_type::first_type& key,
|
||||
const Arg& arg) {
|
||||
typedef typename std::iterator_traits<
|
||||
typename Collection::value_type::second_type>::value_type Element;
|
||||
std::pair<typename Collection::iterator, bool> ret =
|
||||
collection->insert(typename Collection::value_type(
|
||||
key,
|
||||
static_cast<typename Collection::value_type::second_type>(nullptr)));
|
||||
if (ret.second) {
|
||||
ret.first->second = new Element(arg);
|
||||
}
|
||||
return ret.first->second;
|
||||
}
|
||||
|
||||
// Lookup of linked/shared pointers is used in two scenarios:
|
||||
//
|
||||
// Use LookupOrInsertNewLinkedPtr if the container owns the elements.
|
||||
// In this case it is fine working with the raw pointer as long as it is
|
||||
// guaranteed that no other thread can delete/update an accessed element.
|
||||
// A mutex will need to lock the container operation as well as the use
|
||||
// of the returned elements. Finding an element may be performed using
|
||||
// FindLinkedPtr*().
|
||||
//
|
||||
// Use LookupOrInsertNewSharedPtr if the container does not own the elements
|
||||
// for their whole lifetime. This is typically the case when a reader allows
|
||||
// parallel updates to the container. In this case a Mutex only needs to lock
|
||||
// container operations, but all element operations must be performed on the
|
||||
// shared pointer. Finding an element must be performed using FindPtr*() and
|
||||
// cannot be done with FindLinkedPtr*() even though it compiles.
|
||||
|
||||
// Lookup a key in a map or hash_map whose values are linked_ptrs. If it is
|
||||
// missing, set collection[key].reset(new Value::element_type) and return that.
|
||||
// Value::element_type must be default constructable.
|
||||
template <class Collection>
|
||||
typename Collection::value_type::second_type::element_type*
|
||||
LookupOrInsertNewLinkedPtr(
|
||||
Collection* const collection,
|
||||
const typename Collection::value_type::first_type& key) {
|
||||
typedef typename Collection::value_type::second_type Value;
|
||||
std::pair<typename Collection::iterator, bool> ret =
|
||||
collection->insert(typename Collection::value_type(key, Value()));
|
||||
if (ret.second) {
|
||||
ret.first->second.reset(new typename Value::element_type);
|
||||
}
|
||||
return ret.first->second.get();
|
||||
}
|
||||
|
||||
// A variant of LookupOrInsertNewLinkedPtr where the value is constructed using
|
||||
// a single-parameter constructor. Note: the constructor argument is computed
|
||||
// even if it will not be used, so only values cheap to compute should be passed
|
||||
// here. On the other hand it does not matter how expensive the construction of
|
||||
// the actual stored value is, as that only occurs if necessary.
|
||||
template <class Collection, class Arg>
|
||||
typename Collection::value_type::second_type::element_type*
|
||||
LookupOrInsertNewLinkedPtr(
|
||||
Collection* const collection,
|
||||
const typename Collection::value_type::first_type& key,
|
||||
const Arg& arg) {
|
||||
typedef typename Collection::value_type::second_type Value;
|
||||
std::pair<typename Collection::iterator, bool> ret =
|
||||
collection->insert(typename Collection::value_type(key, Value()));
|
||||
if (ret.second) {
|
||||
ret.first->second.reset(new typename Value::element_type(arg));
|
||||
}
|
||||
return ret.first->second.get();
|
||||
}
|
||||
|
||||
// Lookup a key in a map or hash_map whose values are shared_ptrs. If it is
|
||||
// missing, set collection[key].reset(new Value::element_type). Unlike
|
||||
// LookupOrInsertNewLinkedPtr, this function returns the shared_ptr instead of
|
||||
// the raw pointer. Value::element_type must be default constructable.
|
||||
template <class Collection>
|
||||
typename Collection::value_type::second_type&
|
||||
LookupOrInsertNewSharedPtr(
|
||||
Collection* const collection,
|
||||
const typename Collection::value_type::first_type& key) {
|
||||
typedef typename Collection::value_type::second_type SharedPtr;
|
||||
typedef typename Collection::value_type::second_type::element_type Element;
|
||||
std::pair<typename Collection::iterator, bool> ret =
|
||||
collection->insert(typename Collection::value_type(key, SharedPtr()));
|
||||
if (ret.second) {
|
||||
ret.first->second.reset(new Element());
|
||||
}
|
||||
return ret.first->second;
|
||||
}
|
||||
|
||||
// A variant of LookupOrInsertNewSharedPtr where the value is constructed using
|
||||
// a single-parameter constructor. Note: the constructor argument is computed
|
||||
// even if it will not be used, so only values cheap to compute should be passed
|
||||
// here. On the other hand it does not matter how expensive the construction of
|
||||
// the actual stored value is, as that only occurs if necessary.
|
||||
template <class Collection, class Arg>
|
||||
typename Collection::value_type::second_type&
|
||||
LookupOrInsertNewSharedPtr(
|
||||
Collection* const collection,
|
||||
const typename Collection::value_type::first_type& key,
|
||||
const Arg& arg) {
|
||||
typedef typename Collection::value_type::second_type SharedPtr;
|
||||
typedef typename Collection::value_type::second_type::element_type Element;
|
||||
std::pair<typename Collection::iterator, bool> ret =
|
||||
collection->insert(typename Collection::value_type(key, SharedPtr()));
|
||||
if (ret.second) {
|
||||
ret.first->second.reset(new Element(arg));
|
||||
}
|
||||
return ret.first->second;
|
||||
}
|
||||
|
||||
//
|
||||
// Misc Utility Functions
|
||||
//
|
||||
|
||||
// Updates the value associated with the given key. If the key was not already
|
||||
// present, then the key-value pair are inserted and "previous" is unchanged. If
|
||||
// the key was already present, the value is updated and "*previous" will
|
||||
// contain a copy of the old value.
|
||||
//
|
||||
// InsertOrReturnExisting has complementary behavior that returns the
|
||||
// address of an already existing value, rather than updating it.
|
||||
template <class Collection>
|
||||
bool UpdateReturnCopy(Collection* const collection,
|
||||
const typename Collection::value_type::first_type& key,
|
||||
const typename Collection::value_type::second_type& value,
|
||||
typename Collection::value_type::second_type* previous) {
|
||||
std::pair<typename Collection::iterator, bool> ret =
|
||||
collection->insert(typename Collection::value_type(key, value));
|
||||
if (!ret.second) {
|
||||
// update
|
||||
if (previous) {
|
||||
*previous = ret.first->second;
|
||||
}
|
||||
ret.first->second = value;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Same as above except that the key and value are passed as a pair.
|
||||
template <class Collection>
|
||||
bool UpdateReturnCopy(Collection* const collection,
|
||||
const typename Collection::value_type& vt,
|
||||
typename Collection::value_type::second_type* previous) {
|
||||
std::pair<typename Collection::iterator, bool> ret = collection->insert(vt);
|
||||
if (!ret.second) {
|
||||
// update
|
||||
if (previous) {
|
||||
*previous = ret.first->second;
|
||||
}
|
||||
ret.first->second = vt.second;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Tries to insert the given key-value pair into the collection. Returns nullptr if
|
||||
// the insert succeeds. Otherwise, returns a pointer to the existing value.
|
||||
//
|
||||
// This complements UpdateReturnCopy in that it allows to update only after
|
||||
// verifying the old value and still insert quickly without having to look up
|
||||
// twice. Unlike UpdateReturnCopy this also does not come with the issue of an
|
||||
// undefined previous* in case new data was inserted.
|
||||
template <class Collection>
|
||||
typename Collection::value_type::second_type* InsertOrReturnExisting(
|
||||
Collection* const collection, const typename Collection::value_type& vt) {
|
||||
std::pair<typename Collection::iterator, bool> ret = collection->insert(vt);
|
||||
if (ret.second) {
|
||||
return nullptr; // Inserted, no existing previous value.
|
||||
} else {
|
||||
return &ret.first->second; // Return address of already existing value.
|
||||
}
|
||||
}
|
||||
|
||||
// Same as above, except for explicit key and data.
|
||||
template <class Collection>
|
||||
typename Collection::value_type::second_type* InsertOrReturnExisting(
|
||||
Collection* const collection,
|
||||
const typename Collection::value_type::first_type& key,
|
||||
const typename Collection::value_type::second_type& data) {
|
||||
return InsertOrReturnExisting(collection,
|
||||
typename Collection::value_type(key, data));
|
||||
}
|
||||
|
||||
// Erases the collection item identified by the given key, and returns the value
|
||||
// associated with that key. It is assumed that the value (i.e., the
|
||||
// mapped_type) is a pointer. Returns nullptr if the key was not found in the
|
||||
// collection.
|
||||
//
|
||||
// Examples:
|
||||
// map<string, MyType*> my_map;
|
||||
//
|
||||
// One line cleanup:
|
||||
// delete EraseKeyReturnValuePtr(&my_map, "abc");
|
||||
//
|
||||
// Use returned value:
|
||||
// std::unique_ptr<MyType> value_ptr(
|
||||
// EraseKeyReturnValuePtr(&my_map, "abc"));
|
||||
// if (value_ptr.get())
|
||||
// value_ptr->DoSomething();
|
||||
//
|
||||
template <class Collection>
|
||||
typename Collection::value_type::second_type EraseKeyReturnValuePtr(
|
||||
Collection* const collection,
|
||||
const typename Collection::value_type::first_type& key) {
|
||||
typename Collection::iterator it = collection->find(key);
|
||||
if (it == collection->end()) {
|
||||
return nullptr;
|
||||
}
|
||||
typename Collection::value_type::second_type v = it->second;
|
||||
collection->erase(it);
|
||||
return v;
|
||||
}
|
||||
|
||||
// Inserts all the keys from map_container into key_container, which must
|
||||
// support insert(MapContainer::key_type).
|
||||
//
|
||||
// Note: any initial contents of the key_container are not cleared.
|
||||
template <class MapContainer, class KeyContainer>
|
||||
void InsertKeysFromMap(const MapContainer& map_container,
|
||||
KeyContainer* key_container) {
|
||||
GOOGLE_CHECK(key_container != nullptr);
|
||||
for (typename MapContainer::const_iterator it = map_container.begin();
|
||||
it != map_container.end(); ++it) {
|
||||
key_container->insert(it->first);
|
||||
}
|
||||
}
|
||||
|
||||
// Appends all the keys from map_container into key_container, which must
|
||||
// support push_back(MapContainer::key_type).
|
||||
//
|
||||
// Note: any initial contents of the key_container are not cleared.
|
||||
template <class MapContainer, class KeyContainer>
|
||||
void AppendKeysFromMap(const MapContainer& map_container,
|
||||
KeyContainer* key_container) {
|
||||
GOOGLE_CHECK(key_container != nullptr);
|
||||
for (typename MapContainer::const_iterator it = map_container.begin();
|
||||
it != map_container.end(); ++it) {
|
||||
key_container->push_back(it->first);
|
||||
}
|
||||
}
|
||||
|
||||
// A more specialized overload of AppendKeysFromMap to optimize reallocations
|
||||
// for the common case in which we're appending keys to a vector and hence can
|
||||
// (and sometimes should) call reserve() first.
|
||||
//
|
||||
// (It would be possible to play SFINAE games to call reserve() for any
|
||||
// container that supports it, but this seems to get us 99% of what we need
|
||||
// without the complexity of a SFINAE-based solution.)
|
||||
template <class MapContainer, class KeyType>
|
||||
void AppendKeysFromMap(const MapContainer& map_container,
|
||||
std::vector<KeyType>* key_container) {
|
||||
GOOGLE_CHECK(key_container != nullptr);
|
||||
// We now have the opportunity to call reserve(). Calling reserve() every
|
||||
// time is a bad idea for some use cases: libstdc++'s implementation of
|
||||
// vector<>::reserve() resizes the vector's backing store to exactly the
|
||||
// given size (unless it's already at least that big). Because of this,
|
||||
// the use case that involves appending a lot of small maps (total size
|
||||
// N) one by one to a vector would be O(N^2). But never calling reserve()
|
||||
// loses the opportunity to improve the use case of adding from a large
|
||||
// map to an empty vector (this improves performance by up to 33%). A
|
||||
// number of heuristics are possible; see the discussion in
|
||||
// cl/34081696. Here we use the simplest one.
|
||||
if (key_container->empty()) {
|
||||
key_container->reserve(map_container.size());
|
||||
}
|
||||
for (typename MapContainer::const_iterator it = map_container.begin();
|
||||
it != map_container.end(); ++it) {
|
||||
key_container->push_back(it->first);
|
||||
}
|
||||
}
|
||||
|
||||
// Inserts all the values from map_container into value_container, which must
|
||||
// support push_back(MapContainer::mapped_type).
|
||||
//
|
||||
// Note: any initial contents of the value_container are not cleared.
|
||||
template <class MapContainer, class ValueContainer>
|
||||
void AppendValuesFromMap(const MapContainer& map_container,
|
||||
ValueContainer* value_container) {
|
||||
GOOGLE_CHECK(value_container != nullptr);
|
||||
for (typename MapContainer::const_iterator it = map_container.begin();
|
||||
it != map_container.end(); ++it) {
|
||||
value_container->push_back(it->second);
|
||||
}
|
||||
}
|
||||
|
||||
// A more specialized overload of AppendValuesFromMap to optimize reallocations
|
||||
// for the common case in which we're appending values to a vector and hence
|
||||
// can (and sometimes should) call reserve() first.
|
||||
//
|
||||
// (It would be possible to play SFINAE games to call reserve() for any
|
||||
// container that supports it, but this seems to get us 99% of what we need
|
||||
// without the complexity of a SFINAE-based solution.)
|
||||
template <class MapContainer, class ValueType>
|
||||
void AppendValuesFromMap(const MapContainer& map_container,
|
||||
std::vector<ValueType>* value_container) {
|
||||
GOOGLE_CHECK(value_container != nullptr);
|
||||
// See AppendKeysFromMap for why this is done.
|
||||
if (value_container->empty()) {
|
||||
value_container->reserve(map_container.size());
|
||||
}
|
||||
for (typename MapContainer::const_iterator it = map_container.begin();
|
||||
it != map_container.end(); ++it) {
|
||||
value_container->push_back(it->second);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_STUBS_MAP_UTIL_H__
|
||||
@@ -1,162 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef GOOGLE_PROTOBUF_STUBS_MATHUTIL_H_
|
||||
#define GOOGLE_PROTOBUF_STUBS_MATHUTIL_H_
|
||||
|
||||
#include <cmath>
|
||||
#include <float.h>
|
||||
#include <limits>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/logging.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
// Like std::make_unsigned_t except floating point types map to themselves.
|
||||
template <typename T>
|
||||
using MakeUnsignedT =
|
||||
typename std::conditional<std::is_integral<T>::value, std::make_unsigned<T>,
|
||||
std::common_type<T>>::type::type;
|
||||
|
||||
// Like std::isnan() except a template function that is defined for all numeric
|
||||
// types.
|
||||
template <typename T,
|
||||
typename std::enable_if<std::is_integral<T>::value, int>::type = 0>
|
||||
bool IsNan(T /*val*/) {
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename T, typename std::enable_if<std::is_floating_point<T>::value,
|
||||
int>::type = 0>
|
||||
bool IsNan(T val) {
|
||||
return std::isnan(val);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool AlmostEquals(T a, T b) {
|
||||
return a == b;
|
||||
}
|
||||
template<>
|
||||
inline bool AlmostEquals(float a, float b) {
|
||||
return fabs(a - b) < 32 * FLT_EPSILON;
|
||||
}
|
||||
|
||||
template<>
|
||||
inline bool AlmostEquals(double a, double b) {
|
||||
return fabs(a - b) < 32 * DBL_EPSILON;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
class MathUtil {
|
||||
public:
|
||||
template <typename T>
|
||||
static T Sign(T value) {
|
||||
if (value == T(0) || internal::IsNan(value)) {
|
||||
return value;
|
||||
}
|
||||
return value > T(0) ? 1 : -1;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static bool AlmostEquals(T a, T b) {
|
||||
return internal::AlmostEquals(a, b);
|
||||
}
|
||||
|
||||
// Largest of two values.
|
||||
// Works correctly for special floating point values.
|
||||
// Note: 0.0 and -0.0 are not differentiated by Max (Max(0.0, -0.0) is -0.0),
|
||||
// which should be OK because, although they (can) have different
|
||||
// bit representation, they are observably the same when examined
|
||||
// with arithmetic and (in)equality operators.
|
||||
template <typename T>
|
||||
static T Max(const T x, const T y) {
|
||||
return internal::IsNan(x) || x > y ? x : y;
|
||||
}
|
||||
|
||||
// Absolute value of x
|
||||
// Works correctly for unsigned types and
|
||||
// for special floating point values.
|
||||
// Note: 0.0 and -0.0 are not differentiated by Abs (Abs(0.0) is -0.0),
|
||||
// which should be OK: see the comment for Max above.
|
||||
template<typename T>
|
||||
static T Abs(const T x) {
|
||||
return x > T(0) ? x : -x;
|
||||
}
|
||||
|
||||
// Absolute value of the difference between two numbers.
|
||||
// Works correctly for signed types and special floating point values.
|
||||
template <typename T>
|
||||
static typename internal::MakeUnsignedT<T> AbsDiff(const T x, const T y) {
|
||||
// Carries out arithmetic as unsigned to avoid overflow.
|
||||
typedef typename internal::MakeUnsignedT<T> R;
|
||||
return x > y ? R(x) - R(y) : R(y) - R(x);
|
||||
}
|
||||
|
||||
// If two (usually floating point) numbers are within a certain
|
||||
// fraction of their magnitude or within a certain absolute margin of error.
|
||||
// This is the same as the following but faster:
|
||||
// WithinFraction(x, y, fraction) || WithinMargin(x, y, margin)
|
||||
// E.g. WithinFraction(0.0, 1e-10, 1e-5) is false but
|
||||
// WithinFractionOrMargin(0.0, 1e-10, 1e-5, 1e-5) is true.
|
||||
template<typename T>
|
||||
static bool WithinFractionOrMargin(const T x, const T y,
|
||||
const T fraction, const T margin);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
bool MathUtil::WithinFractionOrMargin(const T x, const T y,
|
||||
const T fraction, const T margin) {
|
||||
// Not just "0 <= fraction" to fool the compiler for unsigned types.
|
||||
GOOGLE_DCHECK((T(0) < fraction || T(0) == fraction) &&
|
||||
fraction < T(1) &&
|
||||
margin >= T(0));
|
||||
|
||||
// Template specialization will convert the if() condition to a constant,
|
||||
// which will cause the compiler to generate code for either the "if" part
|
||||
// or the "then" part. In this way we avoid a compiler warning
|
||||
// about a potential integer overflow in crosstool v12 (gcc 4.3.1).
|
||||
if (std::numeric_limits<T>::is_integer) {
|
||||
return x == y;
|
||||
} else {
|
||||
if (!std::isfinite(x) || !std::isfinite(y)) {
|
||||
return false;
|
||||
}
|
||||
T relative_margin = static_cast<T>(fraction * Max(Abs(x), Abs(y)));
|
||||
return AbsDiff(x, y) <= Max(margin, relative_margin);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_STUBS_MATHUTIL_H_
|
||||
@@ -1,218 +0,0 @@
|
||||
// Copyright (c) 2006, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_STUBS_MUTEX_H_
|
||||
#define GOOGLE_PROTOBUF_STUBS_MUTEX_H_
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#ifdef GOOGLE_PROTOBUF_SUPPORT_WINDOWS_XP
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
// GetMessage conflicts with GeneratedMessageReflection::GetMessage().
|
||||
#ifdef GetMessage
|
||||
#undef GetMessage
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#include <google/protobuf/stubs/macros.h>
|
||||
|
||||
// Define thread-safety annotations for use below, if we are building with
|
||||
// Clang.
|
||||
#if defined(__clang__) && !defined(SWIG)
|
||||
#define GOOGLE_PROTOBUF_ACQUIRE(...) \
|
||||
__attribute__((acquire_capability(__VA_ARGS__)))
|
||||
#define GOOGLE_PROTOBUF_RELEASE(...) \
|
||||
__attribute__((release_capability(__VA_ARGS__)))
|
||||
#define GOOGLE_PROTOBUF_SCOPED_CAPABILITY __attribute__((scoped_lockable))
|
||||
#define GOOGLE_PROTOBUF_CAPABILITY(x) __attribute__((capability(x)))
|
||||
#else
|
||||
#define GOOGLE_PROTOBUF_ACQUIRE(...)
|
||||
#define GOOGLE_PROTOBUF_RELEASE(...)
|
||||
#define GOOGLE_PROTOBUF_SCOPED_CAPABILITY
|
||||
#define GOOGLE_PROTOBUF_CAPABILITY(x)
|
||||
#endif
|
||||
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
// ===================================================================
|
||||
// emulates google3/base/mutex.h
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
#define GOOGLE_PROTOBUF_LINKER_INITIALIZED
|
||||
|
||||
#ifdef GOOGLE_PROTOBUF_SUPPORT_WINDOWS_XP
|
||||
|
||||
// This class is a lightweight replacement for std::mutex on Windows platforms.
|
||||
// std::mutex does not work on Windows XP SP2 with the latest VC++ libraries,
|
||||
// because it utilizes the Concurrency Runtime that is only supported on Windows
|
||||
// XP SP3 and above.
|
||||
class PROTOBUF_EXPORT CriticalSectionLock {
|
||||
public:
|
||||
CriticalSectionLock() { InitializeCriticalSection(&critical_section_); }
|
||||
~CriticalSectionLock() { DeleteCriticalSection(&critical_section_); }
|
||||
void lock() { EnterCriticalSection(&critical_section_); }
|
||||
void unlock() { LeaveCriticalSection(&critical_section_); }
|
||||
|
||||
private:
|
||||
CRITICAL_SECTION critical_section_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CriticalSectionLock);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
// In MSVC std::mutex does not have a constexpr constructor.
|
||||
// This wrapper makes the constructor constexpr.
|
||||
template <typename T>
|
||||
class CallOnceInitializedMutex {
|
||||
public:
|
||||
constexpr CallOnceInitializedMutex() : flag_{}, buf_{} {}
|
||||
~CallOnceInitializedMutex() { get().~T(); }
|
||||
|
||||
void lock() { get().lock(); }
|
||||
void unlock() { get().unlock(); }
|
||||
|
||||
private:
|
||||
T& get() {
|
||||
std::call_once(flag_, [&] { ::new (static_cast<void*>(&buf_)) T(); });
|
||||
return reinterpret_cast<T&>(buf_);
|
||||
}
|
||||
|
||||
std::once_flag flag_;
|
||||
alignas(T) char buf_[sizeof(T)];
|
||||
};
|
||||
|
||||
// Mutex is a natural type to wrap. As both google and other organization have
|
||||
// specialized mutexes. gRPC also provides an injection mechanism for custom
|
||||
// mutexes.
|
||||
class GOOGLE_PROTOBUF_CAPABILITY("mutex") PROTOBUF_EXPORT WrappedMutex {
|
||||
public:
|
||||
#if defined(__QNX__)
|
||||
constexpr WrappedMutex() = default;
|
||||
#else
|
||||
constexpr WrappedMutex() {}
|
||||
#endif
|
||||
void Lock() GOOGLE_PROTOBUF_ACQUIRE() { mu_.lock(); }
|
||||
void Unlock() GOOGLE_PROTOBUF_RELEASE() { mu_.unlock(); }
|
||||
// Crash if this Mutex is not held exclusively by this thread.
|
||||
// May fail to crash when it should; will never crash when it should not.
|
||||
void AssertHeld() const {}
|
||||
|
||||
private:
|
||||
#if defined(GOOGLE_PROTOBUF_SUPPORT_WINDOWS_XP)
|
||||
CallOnceInitializedMutex<CriticalSectionLock> mu_{};
|
||||
#elif defined(_WIN32)
|
||||
CallOnceInitializedMutex<std::mutex> mu_{};
|
||||
#else
|
||||
std::mutex mu_{};
|
||||
#endif
|
||||
};
|
||||
|
||||
using Mutex = WrappedMutex;
|
||||
|
||||
// MutexLock(mu) acquires mu when constructed and releases it when destroyed.
|
||||
class GOOGLE_PROTOBUF_SCOPED_CAPABILITY PROTOBUF_EXPORT MutexLock {
|
||||
public:
|
||||
explicit MutexLock(Mutex* mu) GOOGLE_PROTOBUF_ACQUIRE(mu) : mu_(mu) {
|
||||
this->mu_->Lock();
|
||||
}
|
||||
~MutexLock() GOOGLE_PROTOBUF_RELEASE() { this->mu_->Unlock(); }
|
||||
|
||||
private:
|
||||
Mutex *const mu_;
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MutexLock);
|
||||
};
|
||||
|
||||
// TODO(kenton): Implement these? Hard to implement portably.
|
||||
typedef MutexLock ReaderMutexLock;
|
||||
typedef MutexLock WriterMutexLock;
|
||||
|
||||
// MutexLockMaybe is like MutexLock, but is a no-op when mu is nullptr.
|
||||
class PROTOBUF_EXPORT MutexLockMaybe {
|
||||
public:
|
||||
explicit MutexLockMaybe(Mutex *mu) :
|
||||
mu_(mu) { if (this->mu_ != nullptr) { this->mu_->Lock(); } }
|
||||
~MutexLockMaybe() { if (this->mu_ != nullptr) { this->mu_->Unlock(); } }
|
||||
private:
|
||||
Mutex *const mu_;
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MutexLockMaybe);
|
||||
};
|
||||
|
||||
#if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL)
|
||||
template<typename T>
|
||||
class ThreadLocalStorage {
|
||||
public:
|
||||
ThreadLocalStorage() {
|
||||
pthread_key_create(&key_, &ThreadLocalStorage::Delete);
|
||||
}
|
||||
~ThreadLocalStorage() {
|
||||
pthread_key_delete(key_);
|
||||
}
|
||||
T* Get() {
|
||||
T* result = static_cast<T*>(pthread_getspecific(key_));
|
||||
if (result == nullptr) {
|
||||
result = new T();
|
||||
pthread_setspecific(key_, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
private:
|
||||
static void Delete(void* value) {
|
||||
delete static_cast<T*>(value);
|
||||
}
|
||||
pthread_key_t key_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ThreadLocalStorage);
|
||||
};
|
||||
#endif
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// We made these internal so that they would show up as such in the docs,
|
||||
// but we don't want to stick "internal::" in front of them everywhere.
|
||||
using internal::Mutex;
|
||||
using internal::MutexLock;
|
||||
using internal::ReaderMutexLock;
|
||||
using internal::WriterMutexLock;
|
||||
using internal::MutexLockMaybe;
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#undef GOOGLE_PROTOBUF_ACQUIRE
|
||||
#undef GOOGLE_PROTOBUF_RELEASE
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_STUBS_MUTEX_H_
|
||||
@@ -1,55 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_STUBS_ONCE_H__
|
||||
#define GOOGLE_PROTOBUF_STUBS_ONCE_H__
|
||||
|
||||
#include <mutex>
|
||||
#include <utility>
|
||||
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
using once_flag = std::once_flag;
|
||||
template <typename... Args>
|
||||
void call_once(Args&&... args ) {
|
||||
std::call_once(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_STUBS_ONCE_H__
|
||||
@@ -1,138 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2012 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_PLATFORM_MACROS_H_
|
||||
#define GOOGLE_PROTOBUF_PLATFORM_MACROS_H_
|
||||
|
||||
#define GOOGLE_PROTOBUF_PLATFORM_ERROR \
|
||||
#error "Host platform was not detected as supported by protobuf"
|
||||
|
||||
// Processor architecture detection. For more info on what's defined, see:
|
||||
// http://msdn.microsoft.com/en-us/library/b0084kay.aspx
|
||||
// http://www.agner.org/optimize/calling_conventions.pdf
|
||||
// or with gcc, run: "echo | gcc -E -dM -"
|
||||
#if defined(_M_X64) || defined(__x86_64__)
|
||||
#define GOOGLE_PROTOBUF_ARCH_X64 1
|
||||
#define GOOGLE_PROTOBUF_ARCH_64_BIT 1
|
||||
#elif defined(_M_IX86) || defined(__i386__)
|
||||
#define GOOGLE_PROTOBUF_ARCH_IA32 1
|
||||
#define GOOGLE_PROTOBUF_ARCH_32_BIT 1
|
||||
#elif defined(__QNX__)
|
||||
#define GOOGLE_PROTOBUF_ARCH_ARM_QNX 1
|
||||
#if defined(__aarch64__)
|
||||
#define GOOGLE_PROTOBUF_ARCH_64_BIT 1
|
||||
#else
|
||||
#define GOOGLE_PROTOBUF_ARCH_32_BIT 1
|
||||
#endif
|
||||
#elif defined(_M_ARM) || defined(__ARMEL__)
|
||||
#define GOOGLE_PROTOBUF_ARCH_ARM 1
|
||||
#define GOOGLE_PROTOBUF_ARCH_32_BIT 1
|
||||
#elif defined(_M_ARM64)
|
||||
#define GOOGLE_PROTOBUF_ARCH_ARM 1
|
||||
#define GOOGLE_PROTOBUF_ARCH_64_BIT 1
|
||||
#elif defined(__aarch64__)
|
||||
#define GOOGLE_PROTOBUF_ARCH_AARCH64 1
|
||||
#define GOOGLE_PROTOBUF_ARCH_64_BIT 1
|
||||
#elif defined(__mips__)
|
||||
#if defined(__LP64__)
|
||||
#define GOOGLE_PROTOBUF_ARCH_MIPS64 1
|
||||
#define GOOGLE_PROTOBUF_ARCH_64_BIT 1
|
||||
#else
|
||||
#define GOOGLE_PROTOBUF_ARCH_MIPS 1
|
||||
#define GOOGLE_PROTOBUF_ARCH_32_BIT 1
|
||||
#endif
|
||||
#elif defined(__pnacl__)
|
||||
#define GOOGLE_PROTOBUF_ARCH_32_BIT 1
|
||||
#elif defined(sparc)
|
||||
#define GOOGLE_PROTOBUF_ARCH_SPARC 1
|
||||
#if defined(__sparc_v9__) || defined(__sparcv9) || defined(__arch64__)
|
||||
#define GOOGLE_PROTOBUF_ARCH_64_BIT 1
|
||||
#else
|
||||
#define GOOGLE_PROTOBUF_ARCH_32_BIT 1
|
||||
#endif
|
||||
#elif defined(_POWER) || defined(__powerpc64__) || defined(__PPC64__)
|
||||
#define GOOGLE_PROTOBUF_ARCH_POWER 1
|
||||
#define GOOGLE_PROTOBUF_ARCH_64_BIT 1
|
||||
#elif defined(__PPC__)
|
||||
#define GOOGLE_PROTOBUF_ARCH_PPC 1
|
||||
#define GOOGLE_PROTOBUF_ARCH_32_BIT 1
|
||||
#elif defined(__GNUC__)
|
||||
# if (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4))
|
||||
// We fallback to the generic Clang/GCC >= 4.7 implementation in atomicops.h
|
||||
# elif defined(__clang__)
|
||||
# if !__has_extension(c_atomic)
|
||||
GOOGLE_PROTOBUF_PLATFORM_ERROR
|
||||
# endif
|
||||
// We fallback to the generic Clang/GCC >= 4.7 implementation in atomicops.h
|
||||
# endif
|
||||
# if __LP64__
|
||||
# define GOOGLE_PROTOBUF_ARCH_64_BIT 1
|
||||
# else
|
||||
# define GOOGLE_PROTOBUF_ARCH_32_BIT 1
|
||||
# endif
|
||||
#else
|
||||
GOOGLE_PROTOBUF_PLATFORM_ERROR
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#define GOOGLE_PROTOBUF_OS_APPLE
|
||||
#include <Availability.h>
|
||||
#include <TargetConditionals.h>
|
||||
#if TARGET_OS_IPHONE
|
||||
#define GOOGLE_PROTOBUF_OS_IPHONE
|
||||
#endif
|
||||
#elif defined(__EMSCRIPTEN__)
|
||||
#define GOOGLE_PROTOBUF_OS_EMSCRIPTEN
|
||||
#elif defined(__native_client__)
|
||||
#define GOOGLE_PROTOBUF_OS_NACL
|
||||
#elif defined(sun)
|
||||
#define GOOGLE_PROTOBUF_OS_SOLARIS
|
||||
#elif defined(_AIX)
|
||||
#define GOOGLE_PROTOBUF_OS_AIX
|
||||
#elif defined(__ANDROID__)
|
||||
#define GOOGLE_PROTOBUF_OS_ANDROID
|
||||
#endif
|
||||
|
||||
#undef GOOGLE_PROTOBUF_PLATFORM_ERROR
|
||||
|
||||
#if defined(GOOGLE_PROTOBUF_OS_ANDROID) || defined(GOOGLE_PROTOBUF_OS_IPHONE)
|
||||
// Android ndk does not support the __thread keyword very well yet. Here
|
||||
// we use pthread_key_create()/pthread_getspecific()/... methods for
|
||||
// TLS support on android.
|
||||
// iOS also does not support the __thread keyword.
|
||||
#define GOOGLE_PROTOBUF_NO_THREADLOCAL
|
||||
#endif
|
||||
|
||||
#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 1070
|
||||
// __thread keyword requires at least 10.7
|
||||
#define GOOGLE_PROTOBUF_NO_THREADLOCAL
|
||||
#endif
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_PLATFORM_MACROS_H_
|
||||
@@ -1,413 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_STUBS_PORT_H_
|
||||
#define GOOGLE_PROTOBUF_STUBS_PORT_H_
|
||||
|
||||
#include <assert.h>
|
||||
#include <cstdint>
|
||||
#include <stdlib.h>
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
#include <string.h>
|
||||
|
||||
#include <google/protobuf/stubs/platform_macros.h>
|
||||
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
#undef PROTOBUF_LITTLE_ENDIAN
|
||||
#ifdef _WIN32
|
||||
// Assuming windows is always little-endian.
|
||||
// TODO(xiaofeng): The PROTOBUF_LITTLE_ENDIAN is not only used for
|
||||
// optimization but also for correctness. We should define an
|
||||
// different macro to test the big-endian code path in coded_stream.
|
||||
#if !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST)
|
||||
#define PROTOBUF_LITTLE_ENDIAN 1
|
||||
#endif
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1300 && !defined(__INTEL_COMPILER)
|
||||
// If MSVC has "/RTCc" set, it will complain about truncating casts at
|
||||
// runtime. This file contains some intentional truncating casts.
|
||||
#pragma runtime_checks("c", off)
|
||||
#endif
|
||||
#else
|
||||
#ifdef __APPLE__
|
||||
#include <machine/endian.h> // __BYTE_ORDER
|
||||
#elif defined(__FreeBSD__)
|
||||
#include <sys/endian.h> // __BYTE_ORDER
|
||||
#elif (defined(sun) || defined(__sun)) && (defined(__SVR4) || defined(__svr4__))
|
||||
#include <sys/isa_defs.h> // __BYTE_ORDER
|
||||
#elif defined(_AIX) || defined(__TOS_AIX__)
|
||||
#include <sys/machine.h> // BYTE_ORDER
|
||||
#else
|
||||
#if !defined(__QNX__)
|
||||
#include <endian.h> // __BYTE_ORDER
|
||||
#endif
|
||||
#endif
|
||||
#if ((defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)) || \
|
||||
(defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN) || \
|
||||
(defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN)) && \
|
||||
!defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST)
|
||||
#define PROTOBUF_LITTLE_ENDIAN 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// These #includes are for the byte swap functions declared later on.
|
||||
#ifdef _MSC_VER
|
||||
#include <stdlib.h> // NOLINT(build/include)
|
||||
#include <intrin.h>
|
||||
#elif defined(__APPLE__)
|
||||
#include <libkern/OSByteOrder.h>
|
||||
#elif defined(__linux__) || defined(__ANDROID__) || defined(__CYGWIN__)
|
||||
#include <byteswap.h> // IWYU pragma: export
|
||||
#endif
|
||||
|
||||
// Legacy: some users reference these (internal-only) macros even though we
|
||||
// don't need them any more.
|
||||
#if defined(_MSC_VER) && defined(PROTOBUF_USE_DLLS)
|
||||
#ifdef LIBPROTOBUF_EXPORTS
|
||||
#define LIBPROTOBUF_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define LIBPROTOBUF_EXPORT __declspec(dllimport)
|
||||
#endif
|
||||
#ifdef LIBPROTOC_EXPORTS
|
||||
#define LIBPROTOC_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define LIBPROTOC_EXPORT __declspec(dllimport)
|
||||
#endif
|
||||
#else
|
||||
#define LIBPROTOBUF_EXPORT
|
||||
#define LIBPROTOC_EXPORT
|
||||
#endif
|
||||
|
||||
#define PROTOBUF_RUNTIME_DEPRECATED(message) PROTOBUF_DEPRECATED_MSG(message)
|
||||
#define GOOGLE_PROTOBUF_RUNTIME_DEPRECATED(message) \
|
||||
PROTOBUF_DEPRECATED_MSG(message)
|
||||
|
||||
// ===================================================================
|
||||
// from google3/base/port.h
|
||||
|
||||
#if (defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L || \
|
||||
(defined(_MSC_VER) && _MSC_VER >= 1900))
|
||||
// Define this to 1 if the code is compiled in C++11 mode; leave it
|
||||
// undefined otherwise. Do NOT define it to 0 -- that causes
|
||||
// '#ifdef LANG_CXX11' to behave differently from '#if LANG_CXX11'.
|
||||
#define LANG_CXX11 1
|
||||
#else
|
||||
#error "Protobuf requires at least C++11."
|
||||
#endif
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
using ConstStringParam = const std::string &;
|
||||
|
||||
typedef unsigned int uint;
|
||||
|
||||
typedef int8_t int8;
|
||||
typedef int16_t int16;
|
||||
typedef int32_t int32;
|
||||
typedef int64_t int64;
|
||||
|
||||
typedef uint8_t uint8;
|
||||
typedef uint16_t uint16;
|
||||
typedef uint32_t uint32;
|
||||
typedef uint64_t uint64;
|
||||
|
||||
static const int32 kint32max = 0x7FFFFFFF;
|
||||
static const int32 kint32min = -kint32max - 1;
|
||||
static const int64 kint64max = int64_t{0x7FFFFFFFFFFFFFFF};
|
||||
static const int64 kint64min = -kint64max - 1;
|
||||
static const uint32 kuint32max = 0xFFFFFFFFu;
|
||||
static const uint64 kuint64max = uint64_t{0xFFFFFFFFFFFFFFFFu};
|
||||
|
||||
#if defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER) ||\
|
||||
defined(MEMORY_SANITIZER)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
uint16_t __sanitizer_unaligned_load16(const void *p);
|
||||
uint32_t __sanitizer_unaligned_load32(const void *p);
|
||||
uint64_t __sanitizer_unaligned_load64(const void *p);
|
||||
void __sanitizer_unaligned_store16(void *p, uint16_t v);
|
||||
void __sanitizer_unaligned_store32(void *p, uint32_t v);
|
||||
void __sanitizer_unaligned_store64(void *p, uint64_t v);
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif // __cplusplus
|
||||
|
||||
inline uint16_t GOOGLE_UNALIGNED_LOAD16(const void *p) {
|
||||
return __sanitizer_unaligned_load16(p);
|
||||
}
|
||||
|
||||
inline uint32_t GOOGLE_UNALIGNED_LOAD32(const void *p) {
|
||||
return __sanitizer_unaligned_load32(p);
|
||||
}
|
||||
|
||||
inline uint64_t GOOGLE_UNALIGNED_LOAD64(const void *p) {
|
||||
return __sanitizer_unaligned_load64(p);
|
||||
}
|
||||
|
||||
inline void GOOGLE_UNALIGNED_STORE16(void *p, uint16_t v) {
|
||||
__sanitizer_unaligned_store16(p, v);
|
||||
}
|
||||
|
||||
inline void GOOGLE_UNALIGNED_STORE32(void *p, uint32_t v) {
|
||||
__sanitizer_unaligned_store32(p, v);
|
||||
}
|
||||
|
||||
inline void GOOGLE_UNALIGNED_STORE64(void *p, uint64_t v) {
|
||||
__sanitizer_unaligned_store64(p, v);
|
||||
}
|
||||
|
||||
#elif defined(GOOGLE_PROTOBUF_USE_UNALIGNED) && GOOGLE_PROTOBUF_USE_UNALIGNED
|
||||
|
||||
#define GOOGLE_UNALIGNED_LOAD16(_p) (*reinterpret_cast<const uint16_t *>(_p))
|
||||
#define GOOGLE_UNALIGNED_LOAD32(_p) (*reinterpret_cast<const uint32_t *>(_p))
|
||||
#define GOOGLE_UNALIGNED_LOAD64(_p) (*reinterpret_cast<const uint64_t *>(_p))
|
||||
|
||||
#define GOOGLE_UNALIGNED_STORE16(_p, _val) (*reinterpret_cast<uint16_t *>(_p) = (_val))
|
||||
#define GOOGLE_UNALIGNED_STORE32(_p, _val) (*reinterpret_cast<uint32_t *>(_p) = (_val))
|
||||
#define GOOGLE_UNALIGNED_STORE64(_p, _val) (*reinterpret_cast<uint64_t *>(_p) = (_val))
|
||||
|
||||
#else
|
||||
inline uint16_t GOOGLE_UNALIGNED_LOAD16(const void *p) {
|
||||
uint16_t t;
|
||||
memcpy(&t, p, sizeof t);
|
||||
return t;
|
||||
}
|
||||
|
||||
inline uint32_t GOOGLE_UNALIGNED_LOAD32(const void *p) {
|
||||
uint32_t t;
|
||||
memcpy(&t, p, sizeof t);
|
||||
return t;
|
||||
}
|
||||
|
||||
inline uint64_t GOOGLE_UNALIGNED_LOAD64(const void *p) {
|
||||
uint64_t t;
|
||||
memcpy(&t, p, sizeof t);
|
||||
return t;
|
||||
}
|
||||
|
||||
inline void GOOGLE_UNALIGNED_STORE16(void *p, uint16_t v) {
|
||||
memcpy(p, &v, sizeof v);
|
||||
}
|
||||
|
||||
inline void GOOGLE_UNALIGNED_STORE32(void *p, uint32_t v) {
|
||||
memcpy(p, &v, sizeof v);
|
||||
}
|
||||
|
||||
inline void GOOGLE_UNALIGNED_STORE64(void *p, uint64_t v) {
|
||||
memcpy(p, &v, sizeof v);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(GOOGLE_PROTOBUF_OS_NACL) \
|
||||
|| (defined(__ANDROID__) && defined(__clang__) \
|
||||
&& (__clang_major__ == 3 && __clang_minor__ == 8) \
|
||||
&& (__clang_patchlevel__ < 275480))
|
||||
# define GOOGLE_PROTOBUF_USE_PORTABLE_LOG2
|
||||
#endif
|
||||
|
||||
// The following guarantees declaration of the byte swap functions.
|
||||
#ifdef _MSC_VER
|
||||
#define bswap_16(x) _byteswap_ushort(x)
|
||||
#define bswap_32(x) _byteswap_ulong(x)
|
||||
#define bswap_64(x) _byteswap_uint64(x)
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
// Mac OS X / Darwin features
|
||||
#define bswap_16(x) OSSwapInt16(x)
|
||||
#define bswap_32(x) OSSwapInt32(x)
|
||||
#define bswap_64(x) OSSwapInt64(x)
|
||||
|
||||
#elif !defined(__linux__) && !defined(__ANDROID__) && !defined(__CYGWIN__)
|
||||
|
||||
#ifndef bswap_16
|
||||
static inline uint16_t bswap_16(uint16_t x) {
|
||||
return static_cast<uint16_t>(((x & 0xFF) << 8) | ((x & 0xFF00) >> 8));
|
||||
}
|
||||
#define bswap_16(x) bswap_16(x)
|
||||
#endif
|
||||
|
||||
#ifndef bswap_32
|
||||
static inline uint32_t bswap_32(uint32_t x) {
|
||||
return (((x & 0xFF) << 24) |
|
||||
((x & 0xFF00) << 8) |
|
||||
((x & 0xFF0000) >> 8) |
|
||||
((x & 0xFF000000) >> 24));
|
||||
}
|
||||
#define bswap_32(x) bswap_32(x)
|
||||
#endif
|
||||
|
||||
#ifndef bswap_64
|
||||
static inline uint64_t bswap_64(uint64_t x) {
|
||||
return (((x & uint64_t{0xFFu}) << 56) | ((x & uint64_t{0xFF00u}) << 40) |
|
||||
((x & uint64_t{0xFF0000u}) << 24) |
|
||||
((x & uint64_t{0xFF000000u}) << 8) |
|
||||
((x & uint64_t{0xFF00000000u}) >> 8) |
|
||||
((x & uint64_t{0xFF0000000000u}) >> 24) |
|
||||
((x & uint64_t{0xFF000000000000u}) >> 40) |
|
||||
((x & uint64_t{0xFF00000000000000u}) >> 56));
|
||||
}
|
||||
#define bswap_64(x) bswap_64(x)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
// ===================================================================
|
||||
// from google3/util/bits/bits.h
|
||||
|
||||
class Bits {
|
||||
public:
|
||||
static uint32_t Log2FloorNonZero(uint32_t n) {
|
||||
#if defined(__GNUC__)
|
||||
return 31 ^ static_cast<uint32_t>(__builtin_clz(n));
|
||||
#elif defined(_MSC_VER)
|
||||
unsigned long where;
|
||||
_BitScanReverse(&where, n);
|
||||
return where;
|
||||
#else
|
||||
return Log2FloorNonZero_Portable(n);
|
||||
#endif
|
||||
}
|
||||
|
||||
static uint32_t Log2FloorNonZero64(uint64_t n) {
|
||||
// Older versions of clang run into an instruction-selection failure when
|
||||
// it encounters __builtin_clzll:
|
||||
// https://bugs.chromium.org/p/nativeclient/issues/detail?id=4395
|
||||
// This includes arm-nacl-clang and clang in older Android NDK versions.
|
||||
// To work around this, when we build with those we use the portable
|
||||
// implementation instead.
|
||||
#if defined(__GNUC__) && !defined(GOOGLE_PROTOBUF_USE_PORTABLE_LOG2)
|
||||
return 63 ^ static_cast<uint32_t>(__builtin_clzll(n));
|
||||
#elif defined(_MSC_VER) && defined(_M_X64)
|
||||
unsigned long where;
|
||||
_BitScanReverse64(&where, n);
|
||||
return where;
|
||||
#else
|
||||
return Log2FloorNonZero64_Portable(n);
|
||||
#endif
|
||||
}
|
||||
private:
|
||||
static int Log2FloorNonZero_Portable(uint32_t n) {
|
||||
if (n == 0)
|
||||
return -1;
|
||||
int log = 0;
|
||||
uint32_t value = n;
|
||||
for (int i = 4; i >= 0; --i) {
|
||||
int shift = (1 << i);
|
||||
uint32_t x = value >> shift;
|
||||
if (x != 0) {
|
||||
value = x;
|
||||
log += shift;
|
||||
}
|
||||
}
|
||||
assert(value == 1);
|
||||
return log;
|
||||
}
|
||||
|
||||
static int Log2FloorNonZero64_Portable(uint64_t n) {
|
||||
const uint32_t topbits = static_cast<uint32_t>(n >> 32);
|
||||
if (topbits == 0) {
|
||||
// Top bits are zero, so scan in bottom bits
|
||||
return static_cast<int>(Log2FloorNonZero(static_cast<uint32_t>(n)));
|
||||
} else {
|
||||
return 32 + static_cast<int>(Log2FloorNonZero(topbits));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// ===================================================================
|
||||
// from google3/util/endian/endian.h
|
||||
PROTOBUF_EXPORT uint32_t ghtonl(uint32_t x);
|
||||
|
||||
class BigEndian {
|
||||
public:
|
||||
#ifdef PROTOBUF_LITTLE_ENDIAN
|
||||
|
||||
static uint16_t FromHost16(uint16_t x) { return bswap_16(x); }
|
||||
static uint16_t ToHost16(uint16_t x) { return bswap_16(x); }
|
||||
|
||||
static uint32_t FromHost32(uint32_t x) { return bswap_32(x); }
|
||||
static uint32_t ToHost32(uint32_t x) { return bswap_32(x); }
|
||||
|
||||
static uint64_t FromHost64(uint64_t x) { return bswap_64(x); }
|
||||
static uint64_t ToHost64(uint64_t x) { return bswap_64(x); }
|
||||
|
||||
static bool IsLittleEndian() { return true; }
|
||||
|
||||
#else
|
||||
|
||||
static uint16_t FromHost16(uint16_t x) { return x; }
|
||||
static uint16_t ToHost16(uint16_t x) { return x; }
|
||||
|
||||
static uint32_t FromHost32(uint32_t x) { return x; }
|
||||
static uint32_t ToHost32(uint32_t x) { return x; }
|
||||
|
||||
static uint64_t FromHost64(uint64_t x) { return x; }
|
||||
static uint64_t ToHost64(uint64_t x) { return x; }
|
||||
|
||||
static bool IsLittleEndian() { return false; }
|
||||
|
||||
#endif /* ENDIAN */
|
||||
|
||||
// Functions to do unaligned loads and stores in big-endian order.
|
||||
static uint16_t Load16(const void *p) {
|
||||
return ToHost16(GOOGLE_UNALIGNED_LOAD16(p));
|
||||
}
|
||||
|
||||
static void Store16(void *p, uint16_t v) {
|
||||
GOOGLE_UNALIGNED_STORE16(p, FromHost16(v));
|
||||
}
|
||||
|
||||
static uint32_t Load32(const void *p) {
|
||||
return ToHost32(GOOGLE_UNALIGNED_LOAD32(p));
|
||||
}
|
||||
|
||||
static void Store32(void *p, uint32_t v) {
|
||||
GOOGLE_UNALIGNED_STORE32(p, FromHost32(v));
|
||||
}
|
||||
|
||||
static uint64_t Load64(const void *p) {
|
||||
return ToHost64(GOOGLE_UNALIGNED_LOAD64(p));
|
||||
}
|
||||
|
||||
static void Store64(void *p, uint64_t v) {
|
||||
GOOGLE_UNALIGNED_STORE64(p, FromHost64(v));
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_STUBS_PORT_H_
|
||||
@@ -1,196 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_STUBS_STATUS_H_
|
||||
#define GOOGLE_PROTOBUF_STUBS_STATUS_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/stubs/stringpiece.h>
|
||||
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace util {
|
||||
namespace status_internal {
|
||||
|
||||
// These values must match error codes defined in google/rpc/code.proto.
|
||||
enum class StatusCode : int {
|
||||
kOk = 0,
|
||||
kCancelled = 1,
|
||||
kUnknown = 2,
|
||||
kInvalidArgument = 3,
|
||||
kDeadlineExceeded = 4,
|
||||
kNotFound = 5,
|
||||
kAlreadyExists = 6,
|
||||
kPermissionDenied = 7,
|
||||
kUnauthenticated = 16,
|
||||
kResourceExhausted = 8,
|
||||
kFailedPrecondition = 9,
|
||||
kAborted = 10,
|
||||
kOutOfRange = 11,
|
||||
kUnimplemented = 12,
|
||||
kInternal = 13,
|
||||
kUnavailable = 14,
|
||||
kDataLoss = 15,
|
||||
};
|
||||
|
||||
class PROTOBUF_EXPORT Status {
|
||||
public:
|
||||
// Creates a "successful" status.
|
||||
Status();
|
||||
|
||||
// Create a status in the canonical error space with the specified
|
||||
// code, and error message. If "code == 0", error_message is
|
||||
// ignored and a Status object identical to Status::kOk is
|
||||
// constructed.
|
||||
Status(StatusCode error_code, StringPiece error_message);
|
||||
Status(const Status&);
|
||||
Status& operator=(const Status& x);
|
||||
~Status() {}
|
||||
|
||||
// Accessor
|
||||
bool ok() const { return error_code_ == StatusCode::kOk; }
|
||||
StatusCode code() const { return error_code_; }
|
||||
StringPiece message() const {
|
||||
return error_message_;
|
||||
}
|
||||
|
||||
bool operator==(const Status& x) const;
|
||||
bool operator!=(const Status& x) const {
|
||||
return !operator==(x);
|
||||
}
|
||||
|
||||
// Return a combination of the error code name and message.
|
||||
std::string ToString() const;
|
||||
|
||||
private:
|
||||
StatusCode error_code_;
|
||||
std::string error_message_;
|
||||
};
|
||||
|
||||
// Returns an OK status, equivalent to a default constructed instance. Prefer
|
||||
// usage of `OkStatus()` when constructing such an OK status.
|
||||
PROTOBUF_EXPORT Status OkStatus();
|
||||
|
||||
// Prints a human-readable representation of 'x' to 'os'.
|
||||
PROTOBUF_EXPORT std::ostream& operator<<(std::ostream& os, const Status& x);
|
||||
|
||||
// These convenience functions return `true` if a given status matches the
|
||||
// `StatusCode` error code of its associated function.
|
||||
PROTOBUF_EXPORT bool IsAborted(const Status& status);
|
||||
PROTOBUF_EXPORT bool IsAlreadyExists(const Status& status);
|
||||
PROTOBUF_EXPORT bool IsCancelled(const Status& status);
|
||||
PROTOBUF_EXPORT bool IsDataLoss(const Status& status);
|
||||
PROTOBUF_EXPORT bool IsDeadlineExceeded(const Status& status);
|
||||
PROTOBUF_EXPORT bool IsFailedPrecondition(const Status& status);
|
||||
PROTOBUF_EXPORT bool IsInternal(const Status& status);
|
||||
PROTOBUF_EXPORT bool IsInvalidArgument(const Status& status);
|
||||
PROTOBUF_EXPORT bool IsNotFound(const Status& status);
|
||||
PROTOBUF_EXPORT bool IsOutOfRange(const Status& status);
|
||||
PROTOBUF_EXPORT bool IsPermissionDenied(const Status& status);
|
||||
PROTOBUF_EXPORT bool IsResourceExhausted(const Status& status);
|
||||
PROTOBUF_EXPORT bool IsUnauthenticated(const Status& status);
|
||||
PROTOBUF_EXPORT bool IsUnavailable(const Status& status);
|
||||
PROTOBUF_EXPORT bool IsUnimplemented(const Status& status);
|
||||
PROTOBUF_EXPORT bool IsUnknown(const Status& status);
|
||||
|
||||
// These convenience functions create an `Status` object with an error code as
|
||||
// indicated by the associated function name, using the error message passed in
|
||||
// `message`.
|
||||
//
|
||||
// These functions are intentionally named `*Error` rather than `*Status` to
|
||||
// match the names from Abseil:
|
||||
// https://github.com/abseil/abseil-cpp/blob/2e9532cc6c701a8323d0cffb468999ab804095ab/absl/status/status.h#L716
|
||||
PROTOBUF_EXPORT Status AbortedError(StringPiece message);
|
||||
PROTOBUF_EXPORT Status AlreadyExistsError(StringPiece message);
|
||||
PROTOBUF_EXPORT Status CancelledError(StringPiece message);
|
||||
PROTOBUF_EXPORT Status DataLossError(StringPiece message);
|
||||
PROTOBUF_EXPORT Status DeadlineExceededError(StringPiece message);
|
||||
PROTOBUF_EXPORT Status FailedPreconditionError(StringPiece message);
|
||||
PROTOBUF_EXPORT Status InternalError(StringPiece message);
|
||||
PROTOBUF_EXPORT Status InvalidArgumentError(StringPiece message);
|
||||
PROTOBUF_EXPORT Status NotFoundError(StringPiece message);
|
||||
PROTOBUF_EXPORT Status OutOfRangeError(StringPiece message);
|
||||
PROTOBUF_EXPORT Status PermissionDeniedError(StringPiece message);
|
||||
PROTOBUF_EXPORT Status ResourceExhaustedError(StringPiece message);
|
||||
PROTOBUF_EXPORT Status UnauthenticatedError(StringPiece message);
|
||||
PROTOBUF_EXPORT Status UnavailableError(StringPiece message);
|
||||
PROTOBUF_EXPORT Status UnimplementedError(StringPiece message);
|
||||
PROTOBUF_EXPORT Status UnknownError(StringPiece message);
|
||||
|
||||
} // namespace status_internal
|
||||
|
||||
using ::google::protobuf::util::status_internal::Status;
|
||||
using ::google::protobuf::util::status_internal::StatusCode;
|
||||
|
||||
using ::google::protobuf::util::status_internal::IsAborted;
|
||||
using ::google::protobuf::util::status_internal::IsAlreadyExists;
|
||||
using ::google::protobuf::util::status_internal::IsCancelled;
|
||||
using ::google::protobuf::util::status_internal::IsDataLoss;
|
||||
using ::google::protobuf::util::status_internal::IsDeadlineExceeded;
|
||||
using ::google::protobuf::util::status_internal::IsFailedPrecondition;
|
||||
using ::google::protobuf::util::status_internal::IsInternal;
|
||||
using ::google::protobuf::util::status_internal::IsInvalidArgument;
|
||||
using ::google::protobuf::util::status_internal::IsNotFound;
|
||||
using ::google::protobuf::util::status_internal::IsOutOfRange;
|
||||
using ::google::protobuf::util::status_internal::IsPermissionDenied;
|
||||
using ::google::protobuf::util::status_internal::IsResourceExhausted;
|
||||
using ::google::protobuf::util::status_internal::IsUnauthenticated;
|
||||
using ::google::protobuf::util::status_internal::IsUnavailable;
|
||||
using ::google::protobuf::util::status_internal::IsUnimplemented;
|
||||
using ::google::protobuf::util::status_internal::IsUnknown;
|
||||
|
||||
using ::google::protobuf::util::status_internal::AbortedError;
|
||||
using ::google::protobuf::util::status_internal::AlreadyExistsError;
|
||||
using ::google::protobuf::util::status_internal::CancelledError;
|
||||
using ::google::protobuf::util::status_internal::DataLossError;
|
||||
using ::google::protobuf::util::status_internal::DeadlineExceededError;
|
||||
using ::google::protobuf::util::status_internal::FailedPreconditionError;
|
||||
using ::google::protobuf::util::status_internal::InternalError;
|
||||
using ::google::protobuf::util::status_internal::InvalidArgumentError;
|
||||
using ::google::protobuf::util::status_internal::NotFoundError;
|
||||
using ::google::protobuf::util::status_internal::OkStatus;
|
||||
using ::google::protobuf::util::status_internal::OutOfRangeError;
|
||||
using ::google::protobuf::util::status_internal::PermissionDeniedError;
|
||||
using ::google::protobuf::util::status_internal::ResourceExhaustedError;
|
||||
using ::google::protobuf::util::status_internal::UnauthenticatedError;
|
||||
using ::google::protobuf::util::status_internal::UnavailableError;
|
||||
using ::google::protobuf::util::status_internal::UnimplementedError;
|
||||
using ::google::protobuf::util::status_internal::UnknownError;
|
||||
|
||||
} // namespace util
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_STUBS_STATUS_H_
|
||||
@@ -1,89 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// From: util/task/contrib/status_macros/status_macros.h
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_STUBS_STATUS_MACROS_H_
|
||||
#define GOOGLE_PROTOBUF_STUBS_STATUS_MACROS_H_
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/status.h>
|
||||
#include <google/protobuf/stubs/statusor.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace util {
|
||||
|
||||
// Run a command that returns a util::Status. If the called code returns an
|
||||
// error status, return that status up out of this method too.
|
||||
//
|
||||
// Example:
|
||||
// RETURN_IF_ERROR(DoThings(4));
|
||||
#define RETURN_IF_ERROR(expr) \
|
||||
do { \
|
||||
/* Using _status below to avoid capture problems if expr is "status". */ \
|
||||
const PROTOBUF_NAMESPACE_ID::util::Status _status = (expr); \
|
||||
if (PROTOBUF_PREDICT_FALSE(!_status.ok())) return _status; \
|
||||
} while (0)
|
||||
|
||||
// Internal helper for concatenating macro values.
|
||||
#define STATUS_MACROS_CONCAT_NAME_INNER(x, y) x##y
|
||||
#define STATUS_MACROS_CONCAT_NAME(x, y) STATUS_MACROS_CONCAT_NAME_INNER(x, y)
|
||||
|
||||
template<typename T>
|
||||
Status DoAssignOrReturn(T& lhs, StatusOr<T> result) {
|
||||
if (result.ok()) {
|
||||
lhs = result.value();
|
||||
}
|
||||
return result.status();
|
||||
}
|
||||
|
||||
#define ASSIGN_OR_RETURN_IMPL(status, lhs, rexpr) \
|
||||
Status status = DoAssignOrReturn(lhs, (rexpr)); \
|
||||
if (PROTOBUF_PREDICT_FALSE(!status.ok())) return status;
|
||||
|
||||
// Executes an expression that returns a util::StatusOr, extracting its value
|
||||
// into the variable defined by lhs (or returning on error).
|
||||
//
|
||||
// Example: Assigning to an existing value
|
||||
// ValueType value;
|
||||
// ASSIGN_OR_RETURN(value, MaybeGetValue(arg));
|
||||
//
|
||||
// WARNING: ASSIGN_OR_RETURN expands into multiple statements; it cannot be used
|
||||
// in a single statement (e.g. as the body of an if statement without {})!
|
||||
#define ASSIGN_OR_RETURN(lhs, rexpr) \
|
||||
ASSIGN_OR_RETURN_IMPL( \
|
||||
STATUS_MACROS_CONCAT_NAME(_status_or_value, __COUNTER__), lhs, rexpr);
|
||||
|
||||
} // namespace util
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_STUBS_STATUS_H_
|
||||
@@ -1,253 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// StatusOr<T> is the union of a Status object and a T
|
||||
// object. StatusOr models the concept of an object that is either a
|
||||
// usable value, or an error Status explaining why such a value is
|
||||
// not present. To this end, StatusOr<T> does not allow its Status
|
||||
// value to be OkStatus(). Further, StatusOr<T*> does not allow the
|
||||
// contained pointer to be nullptr.
|
||||
//
|
||||
// The primary use-case for StatusOr<T> is as the return value of a
|
||||
// function which may fail.
|
||||
//
|
||||
// Example client usage for a StatusOr<T>, where T is not a pointer:
|
||||
//
|
||||
// StatusOr<float> result = DoBigCalculationThatCouldFail();
|
||||
// if (result.ok()) {
|
||||
// float answer = result.value();
|
||||
// printf("Big calculation yielded: %f", answer);
|
||||
// } else {
|
||||
// LOG(ERROR) << result.status();
|
||||
// }
|
||||
//
|
||||
// Example client usage for a StatusOr<T*>:
|
||||
//
|
||||
// StatusOr<Foo*> result = FooFactory::MakeNewFoo(arg);
|
||||
// if (result.ok()) {
|
||||
// std::unique_ptr<Foo> foo(result.value());
|
||||
// foo->DoSomethingCool();
|
||||
// } else {
|
||||
// LOG(ERROR) << result.status();
|
||||
// }
|
||||
//
|
||||
// Example factory implementation returning StatusOr<T*>:
|
||||
//
|
||||
// StatusOr<Foo*> FooFactory::MakeNewFoo(int arg) {
|
||||
// if (arg <= 0) {
|
||||
// return InvalidArgumentError("Arg must be positive");
|
||||
// } else {
|
||||
// return new Foo(arg);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_STUBS_STATUSOR_H_
|
||||
#define GOOGLE_PROTOBUF_STUBS_STATUSOR_H_
|
||||
|
||||
#include <new>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include <google/protobuf/stubs/status.h>
|
||||
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace util {
|
||||
namespace statusor_internal {
|
||||
|
||||
template<typename T>
|
||||
class StatusOr {
|
||||
template<typename U> friend class StatusOr;
|
||||
|
||||
public:
|
||||
using value_type = T;
|
||||
|
||||
// Construct a new StatusOr with Status::UNKNOWN status.
|
||||
// Construct a new StatusOr with UnknownError() status.
|
||||
explicit StatusOr();
|
||||
|
||||
// Construct a new StatusOr with the given non-ok status. After calling
|
||||
// this constructor, calls to value() will CHECK-fail.
|
||||
//
|
||||
// NOTE: Not explicit - we want to use StatusOr<T> as a return
|
||||
// value, so it is convenient and sensible to be able to do 'return
|
||||
// Status()' when the return type is StatusOr<T>.
|
||||
//
|
||||
// REQUIRES: status != OkStatus(). This requirement is DCHECKed.
|
||||
// In optimized builds, passing OkStatus() here will have the effect
|
||||
// of passing PosixErrorSpace::EINVAL as a fallback.
|
||||
StatusOr(const Status& status); // NOLINT
|
||||
|
||||
// Construct a new StatusOr with the given value. If T is a plain pointer,
|
||||
// value must not be nullptr. After calling this constructor, calls to
|
||||
// value() will succeed, and calls to status() will return OK.
|
||||
//
|
||||
// NOTE: Not explicit - we want to use StatusOr<T> as a return type
|
||||
// so it is convenient and sensible to be able to do 'return T()'
|
||||
// when when the return type is StatusOr<T>.
|
||||
//
|
||||
// REQUIRES: if T is a plain pointer, value != nullptr. This requirement is
|
||||
// DCHECKed. In optimized builds, passing a null pointer here will have
|
||||
// the effect of passing PosixErrorSpace::EINVAL as a fallback.
|
||||
StatusOr(const T& value); // NOLINT
|
||||
|
||||
// Copy constructor.
|
||||
StatusOr(const StatusOr& other);
|
||||
|
||||
// Conversion copy constructor, T must be copy constructible from U
|
||||
template<typename U>
|
||||
StatusOr(const StatusOr<U>& other);
|
||||
|
||||
// Assignment operator.
|
||||
StatusOr& operator=(const StatusOr& other);
|
||||
|
||||
// Conversion assignment operator, T must be assignable from U
|
||||
template<typename U>
|
||||
StatusOr& operator=(const StatusOr<U>& other);
|
||||
|
||||
// Returns a reference to our status. If this contains a T, then
|
||||
// returns OkStatus().
|
||||
const Status& status() const;
|
||||
|
||||
// Returns this->status().ok()
|
||||
bool ok() const;
|
||||
|
||||
// Returns a reference to our current value, or CHECK-fails if !this->ok().
|
||||
const T& value () const;
|
||||
|
||||
private:
|
||||
Status status_;
|
||||
T value_;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Implementation details for StatusOr<T>
|
||||
|
||||
class PROTOBUF_EXPORT StatusOrHelper {
|
||||
public:
|
||||
// Move type-agnostic error handling to the .cc.
|
||||
static void Crash(const util::Status& status);
|
||||
|
||||
// Customized behavior for StatusOr<T> vs. StatusOr<T*>
|
||||
template<typename T>
|
||||
struct Specialize;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct StatusOrHelper::Specialize {
|
||||
// For non-pointer T, a reference can never be nullptr.
|
||||
static inline bool IsValueNull(const T& /*t*/) { return false; }
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct StatusOrHelper::Specialize<T*> {
|
||||
static inline bool IsValueNull(const T* t) { return t == nullptr; }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
inline StatusOr<T>::StatusOr() : status_(util::UnknownError("")) {}
|
||||
|
||||
template<typename T>
|
||||
inline StatusOr<T>::StatusOr(const Status& status) {
|
||||
if (status.ok()) {
|
||||
status_ = util::InternalError("OkStatus() is not a valid argument.");
|
||||
} else {
|
||||
status_ = status;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline StatusOr<T>::StatusOr(const T& value) {
|
||||
if (StatusOrHelper::Specialize<T>::IsValueNull(value)) {
|
||||
status_ = util::InternalError("nullptr is not a valid argument.");
|
||||
} else {
|
||||
status_ = util::OkStatus();
|
||||
value_ = value;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline StatusOr<T>::StatusOr(const StatusOr<T>& other)
|
||||
: status_(other.status_), value_(other.value_) {
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline StatusOr<T>& StatusOr<T>::operator=(const StatusOr<T>& other) {
|
||||
status_ = other.status_;
|
||||
value_ = other.value_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
inline StatusOr<T>::StatusOr(const StatusOr<U>& other)
|
||||
: status_(other.status_), value_(other.status_.ok() ? other.value_ : T()) {
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
inline StatusOr<T>& StatusOr<T>::operator=(const StatusOr<U>& other) {
|
||||
status_ = other.status_;
|
||||
if (status_.ok()) value_ = other.value_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline const Status& StatusOr<T>::status() const {
|
||||
return status_;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline bool StatusOr<T>::ok() const {
|
||||
return status().ok();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline const T& StatusOr<T>::value() const {
|
||||
if (!status_.ok()) {
|
||||
StatusOrHelper::Crash(status_);
|
||||
}
|
||||
return value_;
|
||||
}
|
||||
|
||||
} // namespace statusor_internal
|
||||
|
||||
using ::google::protobuf::util::statusor_internal::StatusOr;
|
||||
|
||||
} // namespace util
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_STUBS_STATUSOR_H_
|
||||
@@ -1,90 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// from google3/util/gtl/stl_util.h
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_STUBS_STL_UTIL_H__
|
||||
#define GOOGLE_PROTOBUF_STUBS_STL_UTIL_H__
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
// Must be last.
|
||||
#include <google/protobuf/port_def.inc> // NOLINT
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
// Inside Google, this function implements a horrible, disgusting hack in which
|
||||
// we reach into the string's private implementation and resize it without
|
||||
// initializing the new bytes. In some cases doing this can significantly
|
||||
// improve performance. However, since it's totally non-portable it has no
|
||||
// place in open source code. Feel free to fill this function in with your
|
||||
// own disgusting hack if you want the perf boost.
|
||||
inline void STLStringResizeUninitialized(std::string* s, size_t new_size) {
|
||||
s->resize(new_size);
|
||||
}
|
||||
|
||||
// As above, but we make sure to follow amortized growth in which we always
|
||||
// increase the capacity by at least a constant factor >1.
|
||||
inline void STLStringResizeUninitializedAmortized(std::string* s,
|
||||
size_t new_size) {
|
||||
const size_t cap = s->capacity();
|
||||
if (new_size > cap) {
|
||||
// Make sure to always grow by at least a factor of 2x.
|
||||
s->reserve(std::max<size_t>(new_size, 2 * cap));
|
||||
}
|
||||
STLStringResizeUninitialized(s, new_size);
|
||||
}
|
||||
|
||||
// Return a mutable char* pointing to a string's internal buffer,
|
||||
// which may not be null-terminated. Writing through this pointer will
|
||||
// modify the string.
|
||||
//
|
||||
// string_as_array(&str)[i] is valid for 0 <= i < str.size() until the
|
||||
// next call to a string method that invalidates iterators.
|
||||
//
|
||||
// As of 2006-04, there is no standard-blessed way of getting a
|
||||
// mutable reference to a string's internal buffer. However, issue 530
|
||||
// (http://www.open-std.org/JTC1/SC22/WG21/docs/lwg-active.html#530)
|
||||
// proposes this as the method. According to Matt Austern, this should
|
||||
// already work on all current implementations.
|
||||
inline char* string_as_array(std::string* str) {
|
||||
// DO NOT USE const_cast<char*>(str->data())! See the unittest for why.
|
||||
return str->empty() ? nullptr : &*str->begin();
|
||||
}
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc> // NOLINT
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_STUBS_STL_UTIL_H__
|
||||
@@ -1,402 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// A StringPiece points to part or all of a string, Cord, double-quoted string
|
||||
// literal, or other string-like object. A StringPiece does *not* own the
|
||||
// string to which it points. A StringPiece is not null-terminated.
|
||||
//
|
||||
// You can use StringPiece as a function or method parameter. A StringPiece
|
||||
// parameter can receive a double-quoted string literal argument, a "const
|
||||
// char*" argument, a string argument, or a StringPiece argument with no data
|
||||
// copying. Systematic use of StringPiece for arguments reduces data
|
||||
// copies and strlen() calls.
|
||||
//
|
||||
// Prefer passing StringPieces by value:
|
||||
// void MyFunction(StringPiece arg);
|
||||
// If circumstances require, you may also pass by const reference:
|
||||
// void MyFunction(const StringPiece& arg); // not preferred
|
||||
// Both of these have the same lifetime semantics. Passing by value
|
||||
// generates slightly smaller code. For more discussion, see the thread
|
||||
// go/stringpiecebyvalue on c-users.
|
||||
//
|
||||
// StringPiece is also suitable for local variables if you know that
|
||||
// the lifetime of the underlying object is longer than the lifetime
|
||||
// of your StringPiece variable.
|
||||
//
|
||||
// Beware of binding a StringPiece to a temporary:
|
||||
// StringPiece sp = obj.MethodReturningString(); // BAD: lifetime problem
|
||||
//
|
||||
// This code is okay:
|
||||
// string str = obj.MethodReturningString(); // str owns its contents
|
||||
// StringPiece sp(str); // GOOD, because str outlives sp
|
||||
//
|
||||
// StringPiece is sometimes a poor choice for a return value and usually a poor
|
||||
// choice for a data member. If you do use a StringPiece this way, it is your
|
||||
// responsibility to ensure that the object pointed to by the StringPiece
|
||||
// outlives the StringPiece.
|
||||
//
|
||||
// A StringPiece may represent just part of a string; thus the name "Piece".
|
||||
// For example, when splitting a string, vector<StringPiece> is a natural data
|
||||
// type for the output. For another example, a Cord is a non-contiguous,
|
||||
// potentially very long string-like object. The Cord class has an interface
|
||||
// that iteratively provides StringPiece objects that point to the
|
||||
// successive pieces of a Cord object.
|
||||
//
|
||||
// A StringPiece is not null-terminated. If you write code that scans a
|
||||
// StringPiece, you must check its length before reading any characters.
|
||||
// Common idioms that work on null-terminated strings do not work on
|
||||
// StringPiece objects.
|
||||
//
|
||||
// There are several ways to create a null StringPiece:
|
||||
// StringPiece()
|
||||
// StringPiece(nullptr)
|
||||
// StringPiece(nullptr, 0)
|
||||
// For all of the above, sp.data() == nullptr, sp.length() == 0,
|
||||
// and sp.empty() == true. Also, if you create a StringPiece with
|
||||
// a non-null pointer then sp.data() != nullptr. Once created,
|
||||
// sp.data() will stay either nullptr or not-nullptr, except if you call
|
||||
// sp.clear() or sp.set().
|
||||
//
|
||||
// Thus, you can use StringPiece(nullptr) to signal an out-of-band value
|
||||
// that is different from other StringPiece values. This is similar
|
||||
// to the way that const char* p1 = nullptr; is different from
|
||||
// const char* p2 = "";.
|
||||
//
|
||||
// There are many ways to create an empty StringPiece:
|
||||
// StringPiece()
|
||||
// StringPiece(nullptr)
|
||||
// StringPiece(nullptr, 0)
|
||||
// StringPiece("")
|
||||
// StringPiece("", 0)
|
||||
// StringPiece("abcdef", 0)
|
||||
// StringPiece("abcdef"+6, 0)
|
||||
// For all of the above, sp.length() will be 0 and sp.empty() will be true.
|
||||
// For some empty StringPiece values, sp.data() will be nullptr.
|
||||
// For some empty StringPiece values, sp.data() will not be nullptr.
|
||||
//
|
||||
// Be careful not to confuse: null StringPiece and empty StringPiece.
|
||||
// The set of empty StringPieces properly includes the set of null StringPieces.
|
||||
// That is, every null StringPiece is an empty StringPiece,
|
||||
// but some non-null StringPieces are empty Stringpieces too.
|
||||
//
|
||||
// All empty StringPiece values compare equal to each other.
|
||||
// Even a null StringPieces compares equal to a non-null empty StringPiece:
|
||||
// StringPiece() == StringPiece("", 0)
|
||||
// StringPiece(nullptr) == StringPiece("abc", 0)
|
||||
// StringPiece(nullptr, 0) == StringPiece("abcdef"+6, 0)
|
||||
//
|
||||
// Look carefully at this example:
|
||||
// StringPiece("") == nullptr
|
||||
// True or false? TRUE, because StringPiece::operator== converts
|
||||
// the right-hand side from nullptr to StringPiece(nullptr),
|
||||
// and then compares two zero-length spans of characters.
|
||||
// However, we are working to make this example produce a compile error.
|
||||
//
|
||||
// Suppose you want to write:
|
||||
// bool TestWhat?(StringPiece sp) { return sp == nullptr; } // BAD
|
||||
// Do not do that. Write one of these instead:
|
||||
// bool TestNull(StringPiece sp) { return sp.data() == nullptr; }
|
||||
// bool TestEmpty(StringPiece sp) { return sp.empty(); }
|
||||
// The intent of TestWhat? is unclear. Did you mean TestNull or TestEmpty?
|
||||
// Right now, TestWhat? behaves likes TestEmpty.
|
||||
// We are working to make TestWhat? produce a compile error.
|
||||
// TestNull is good to test for an out-of-band signal.
|
||||
// TestEmpty is good to test for an empty StringPiece.
|
||||
//
|
||||
// Caveats (again):
|
||||
// (1) The lifetime of the pointed-to string (or piece of a string)
|
||||
// must be longer than the lifetime of the StringPiece.
|
||||
// (2) There may or may not be a '\0' character after the end of
|
||||
// StringPiece data.
|
||||
// (3) A null StringPiece is empty.
|
||||
// An empty StringPiece may or may not be a null StringPiece.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_STUBS_STRINGPIECE_H_
|
||||
#define GOOGLE_PROTOBUF_STUBS_STRINGPIECE_H_
|
||||
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <iosfwd>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
|
||||
#if defined(__cpp_lib_string_view)
|
||||
#include <string_view>
|
||||
#endif
|
||||
|
||||
#include <google/protobuf/stubs/hash.h>
|
||||
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace stringpiece_internal {
|
||||
|
||||
class PROTOBUF_EXPORT StringPiece {
|
||||
public:
|
||||
using traits_type = std::char_traits<char>;
|
||||
using value_type = char;
|
||||
using pointer = char*;
|
||||
using const_pointer = const char*;
|
||||
using reference = char&;
|
||||
using const_reference = const char&;
|
||||
using const_iterator = const char*;
|
||||
using iterator = const_iterator;
|
||||
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
||||
using reverse_iterator = const_reverse_iterator;
|
||||
using size_type = size_t;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
|
||||
private:
|
||||
const char* ptr_;
|
||||
size_type length_;
|
||||
|
||||
static constexpr size_type kMaxSize =
|
||||
(std::numeric_limits<difference_type>::max)();
|
||||
|
||||
static size_type CheckSize(size_type size) {
|
||||
#if !defined(NDEBUG) || defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0
|
||||
if (PROTOBUF_PREDICT_FALSE(size > kMaxSize)) {
|
||||
// Some people grep for this message in logs
|
||||
// so take care if you ever change it.
|
||||
LogFatalSizeTooBig(size, "string length exceeds max size");
|
||||
}
|
||||
#endif
|
||||
return size;
|
||||
}
|
||||
|
||||
// Out-of-line error path.
|
||||
static void LogFatalSizeTooBig(size_type size, const char* details);
|
||||
|
||||
public:
|
||||
// We provide non-explicit singleton constructors so users can pass
|
||||
// in a "const char*" or a "string" wherever a "StringPiece" is
|
||||
// expected.
|
||||
//
|
||||
// Style guide exception granted:
|
||||
// http://goto/style-guide-exception-20978288
|
||||
StringPiece() : ptr_(nullptr), length_(0) {}
|
||||
|
||||
StringPiece(const char* str) // NOLINT(runtime/explicit)
|
||||
: ptr_(str), length_(0) {
|
||||
if (str != nullptr) {
|
||||
length_ = CheckSize(strlen(str));
|
||||
}
|
||||
}
|
||||
|
||||
template <class Allocator>
|
||||
StringPiece( // NOLINT(runtime/explicit)
|
||||
const std::basic_string<char, std::char_traits<char>, Allocator>& str)
|
||||
: ptr_(str.data()), length_(0) {
|
||||
length_ = CheckSize(str.size());
|
||||
}
|
||||
|
||||
#if defined(__cpp_lib_string_view)
|
||||
StringPiece( // NOLINT(runtime/explicit)
|
||||
std::string_view str)
|
||||
: ptr_(str.data()), length_(0) {
|
||||
length_ = CheckSize(str.size());
|
||||
}
|
||||
#endif
|
||||
|
||||
StringPiece(const char* offset, size_type len)
|
||||
: ptr_(offset), length_(CheckSize(len)) {}
|
||||
|
||||
// data() may return a pointer to a buffer with embedded NULs, and the
|
||||
// returned buffer may or may not be null terminated. Therefore it is
|
||||
// typically a mistake to pass data() to a routine that expects a NUL
|
||||
// terminated string.
|
||||
const_pointer data() const { return ptr_; }
|
||||
size_type size() const { return length_; }
|
||||
size_type length() const { return length_; }
|
||||
bool empty() const { return length_ == 0; }
|
||||
|
||||
char operator[](size_type i) const {
|
||||
assert(i < length_);
|
||||
return ptr_[i];
|
||||
}
|
||||
|
||||
void remove_prefix(size_type n) {
|
||||
assert(length_ >= n);
|
||||
ptr_ += n;
|
||||
length_ -= n;
|
||||
}
|
||||
|
||||
void remove_suffix(size_type n) {
|
||||
assert(length_ >= n);
|
||||
length_ -= n;
|
||||
}
|
||||
|
||||
// returns {-1, 0, 1}
|
||||
int compare(StringPiece x) const {
|
||||
size_type min_size = length_ < x.length_ ? length_ : x.length_;
|
||||
int r = memcmp(ptr_, x.ptr_, static_cast<size_t>(min_size));
|
||||
if (r < 0) return -1;
|
||||
if (r > 0) return 1;
|
||||
if (length_ < x.length_) return -1;
|
||||
if (length_ > x.length_) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string as_string() const { return ToString(); }
|
||||
// We also define ToString() here, since many other string-like
|
||||
// interfaces name the routine that converts to a C++ string
|
||||
// "ToString", and it's confusing to have the method that does that
|
||||
// for a StringPiece be called "as_string()". We also leave the
|
||||
// "as_string()" method defined here for existing code.
|
||||
std::string ToString() const {
|
||||
if (ptr_ == nullptr) return "";
|
||||
return std::string(data(), static_cast<size_type>(size()));
|
||||
}
|
||||
|
||||
explicit operator std::string() const { return ToString(); }
|
||||
|
||||
void CopyToString(std::string* target) const;
|
||||
void AppendToString(std::string* target) const;
|
||||
|
||||
bool starts_with(StringPiece x) const {
|
||||
return (length_ >= x.length_) &&
|
||||
(memcmp(ptr_, x.ptr_, static_cast<size_t>(x.length_)) == 0);
|
||||
}
|
||||
|
||||
bool ends_with(StringPiece x) const {
|
||||
return ((length_ >= x.length_) &&
|
||||
(memcmp(ptr_ + (length_-x.length_), x.ptr_,
|
||||
static_cast<size_t>(x.length_)) == 0));
|
||||
}
|
||||
|
||||
// Checks whether StringPiece starts with x and if so advances the beginning
|
||||
// of it to past the match. It's basically a shortcut for starts_with
|
||||
// followed by remove_prefix.
|
||||
bool Consume(StringPiece x);
|
||||
// Like above but for the end of the string.
|
||||
bool ConsumeFromEnd(StringPiece x);
|
||||
|
||||
// standard STL container boilerplate
|
||||
static const size_type npos;
|
||||
const_iterator begin() const { return ptr_; }
|
||||
const_iterator end() const { return ptr_ + length_; }
|
||||
const_reverse_iterator rbegin() const {
|
||||
return const_reverse_iterator(ptr_ + length_);
|
||||
}
|
||||
const_reverse_iterator rend() const {
|
||||
return const_reverse_iterator(ptr_);
|
||||
}
|
||||
size_type max_size() const { return length_; }
|
||||
size_type capacity() const { return length_; }
|
||||
|
||||
// cpplint.py emits a false positive [build/include_what_you_use]
|
||||
size_type copy(char* buf, size_type n, size_type pos = 0) const; // NOLINT
|
||||
|
||||
bool contains(StringPiece s) const;
|
||||
|
||||
size_type find(StringPiece s, size_type pos = 0) const;
|
||||
size_type find(char c, size_type pos = 0) const;
|
||||
size_type rfind(StringPiece s, size_type pos = npos) const;
|
||||
size_type rfind(char c, size_type pos = npos) const;
|
||||
|
||||
size_type find_first_of(StringPiece s, size_type pos = 0) const;
|
||||
size_type find_first_of(char c, size_type pos = 0) const {
|
||||
return find(c, pos);
|
||||
}
|
||||
size_type find_first_not_of(StringPiece s, size_type pos = 0) const;
|
||||
size_type find_first_not_of(char c, size_type pos = 0) const;
|
||||
size_type find_last_of(StringPiece s, size_type pos = npos) const;
|
||||
size_type find_last_of(char c, size_type pos = npos) const {
|
||||
return rfind(c, pos);
|
||||
}
|
||||
size_type find_last_not_of(StringPiece s, size_type pos = npos) const;
|
||||
size_type find_last_not_of(char c, size_type pos = npos) const;
|
||||
|
||||
StringPiece substr(size_type pos, size_type n = npos) const;
|
||||
};
|
||||
|
||||
// This large function is defined inline so that in a fairly common case where
|
||||
// one of the arguments is a literal, the compiler can elide a lot of the
|
||||
// following comparisons.
|
||||
inline bool operator==(StringPiece x, StringPiece y) {
|
||||
StringPiece::size_type len = x.size();
|
||||
if (len != y.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return x.data() == y.data() || len <= 0 ||
|
||||
memcmp(x.data(), y.data(), static_cast<size_t>(len)) == 0;
|
||||
}
|
||||
|
||||
inline bool operator!=(StringPiece x, StringPiece y) {
|
||||
return !(x == y);
|
||||
}
|
||||
|
||||
inline bool operator<(StringPiece x, StringPiece y) {
|
||||
const StringPiece::size_type min_size =
|
||||
x.size() < y.size() ? x.size() : y.size();
|
||||
const int r = memcmp(x.data(), y.data(), static_cast<size_t>(min_size));
|
||||
return (r < 0) || (r == 0 && x.size() < y.size());
|
||||
}
|
||||
|
||||
inline bool operator>(StringPiece x, StringPiece y) {
|
||||
return y < x;
|
||||
}
|
||||
|
||||
inline bool operator<=(StringPiece x, StringPiece y) {
|
||||
return !(x > y);
|
||||
}
|
||||
|
||||
inline bool operator>=(StringPiece x, StringPiece y) {
|
||||
return !(x < y);
|
||||
}
|
||||
|
||||
// allow StringPiece to be logged
|
||||
extern std::ostream& operator<<(std::ostream& o, StringPiece piece);
|
||||
|
||||
} // namespace stringpiece_internal
|
||||
|
||||
using ::google::protobuf::stringpiece_internal::StringPiece;
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_START
|
||||
template<> struct hash<StringPiece> {
|
||||
size_t operator()(const StringPiece& s) const {
|
||||
size_t result = 0;
|
||||
for (const char *str = s.data(), *end = str + s.size(); str < end; str++) {
|
||||
result = 5 * result + static_cast<size_t>(*str);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_END
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // STRINGS_STRINGPIECE_H_
|
||||
@@ -1,85 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2012 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// from google3/base/stringprintf.h
|
||||
//
|
||||
// Printf variants that place their output in a C++ string.
|
||||
//
|
||||
// Usage:
|
||||
// string result = StringPrintf("%d %s\n", 10, "hello");
|
||||
// SStringPrintf(&result, "%d %s\n", 10, "hello");
|
||||
// StringAppendF(&result, "%d %s\n", 20, "there");
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_STUBS_STRINGPRINTF_H
|
||||
#define GOOGLE_PROTOBUF_STUBS_STRINGPRINTF_H
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
// Return a C++ string
|
||||
PROTOBUF_EXPORT extern std::string StringPrintf(const char* format, ...);
|
||||
|
||||
// Store result into a supplied string and return it
|
||||
PROTOBUF_EXPORT extern const std::string& SStringPrintf(std::string* dst,
|
||||
const char* format,
|
||||
...);
|
||||
|
||||
// Append result to a supplied string
|
||||
PROTOBUF_EXPORT extern void StringAppendF(std::string* dst, const char* format,
|
||||
...);
|
||||
|
||||
// Lower-level routine that takes a va_list and appends to a specified
|
||||
// string. All other routines are just convenience wrappers around it.
|
||||
PROTOBUF_EXPORT extern void StringAppendV(std::string* dst, const char* format,
|
||||
va_list ap);
|
||||
|
||||
// The max arguments supported by StringPrintfVector
|
||||
PROTOBUF_EXPORT extern const int kStringPrintfVectorMaxArgs;
|
||||
|
||||
// You can use this version when all your arguments are strings, but
|
||||
// you don't know how many arguments you'll have at compile time.
|
||||
// StringPrintfVector will LOG(FATAL) if v.size() > kStringPrintfVectorMaxArgs
|
||||
PROTOBUF_EXPORT extern std::string StringPrintfVector(
|
||||
const char* format, const std::vector<std::string>& v);
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_STUBS_STRINGPRINTF_H
|
||||
@@ -1,950 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// from google3/strings/strutil.h
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_STUBS_STRUTIL_H__
|
||||
#define GOOGLE_PROTOBUF_STUBS_STRUTIL_H__
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/stringpiece.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <cstring>
|
||||
#include <google/protobuf/port_def.inc>
|
||||
#include <vector>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1800
|
||||
#define strtoll _strtoi64
|
||||
#define strtoull _strtoui64
|
||||
#elif defined(__DECCXX) && defined(__osf__)
|
||||
// HP C++ on Tru64 does not have strtoll, but strtol is already 64-bit.
|
||||
#define strtoll strtol
|
||||
#define strtoull strtoul
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// ascii_isalnum()
|
||||
// Check if an ASCII character is alphanumeric. We can't use ctype's
|
||||
// isalnum() because it is affected by locale. This function is applied
|
||||
// to identifiers in the protocol buffer language, not to natural-language
|
||||
// strings, so locale should not be taken into account.
|
||||
// ascii_isdigit()
|
||||
// Like above, but only accepts digits.
|
||||
// ascii_isspace()
|
||||
// Check if the character is a space character.
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline bool ascii_isalnum(char c) {
|
||||
return ('a' <= c && c <= 'z') ||
|
||||
('A' <= c && c <= 'Z') ||
|
||||
('0' <= c && c <= '9');
|
||||
}
|
||||
|
||||
inline bool ascii_isdigit(char c) {
|
||||
return ('0' <= c && c <= '9');
|
||||
}
|
||||
|
||||
inline bool ascii_isspace(char c) {
|
||||
return c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\f' ||
|
||||
c == '\r';
|
||||
}
|
||||
|
||||
inline bool ascii_isupper(char c) {
|
||||
return c >= 'A' && c <= 'Z';
|
||||
}
|
||||
|
||||
inline bool ascii_islower(char c) {
|
||||
return c >= 'a' && c <= 'z';
|
||||
}
|
||||
|
||||
inline char ascii_toupper(char c) {
|
||||
return ascii_islower(c) ? c - ('a' - 'A') : c;
|
||||
}
|
||||
|
||||
inline char ascii_tolower(char c) {
|
||||
return ascii_isupper(c) ? c + ('a' - 'A') : c;
|
||||
}
|
||||
|
||||
inline int hex_digit_to_int(char c) {
|
||||
/* Assume ASCII. */
|
||||
int x = static_cast<unsigned char>(c);
|
||||
if (x > '9') {
|
||||
x += 9;
|
||||
}
|
||||
return x & 0xf;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// HasPrefixString()
|
||||
// Check if a string begins with a given prefix.
|
||||
// StripPrefixString()
|
||||
// Given a string and a putative prefix, returns the string minus the
|
||||
// prefix string if the prefix matches, otherwise the original
|
||||
// string.
|
||||
// ----------------------------------------------------------------------
|
||||
inline bool HasPrefixString(StringPiece str, StringPiece prefix) {
|
||||
return str.size() >= prefix.size() &&
|
||||
memcmp(str.data(), prefix.data(), prefix.size()) == 0;
|
||||
}
|
||||
|
||||
inline std::string StripPrefixString(const std::string& str,
|
||||
const std::string& prefix) {
|
||||
if (HasPrefixString(str, prefix)) {
|
||||
return str.substr(prefix.size());
|
||||
} else {
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// HasSuffixString()
|
||||
// Return true if str ends in suffix.
|
||||
// StripSuffixString()
|
||||
// Given a string and a putative suffix, returns the string minus the
|
||||
// suffix string if the suffix matches, otherwise the original
|
||||
// string.
|
||||
// ----------------------------------------------------------------------
|
||||
inline bool HasSuffixString(StringPiece str, StringPiece suffix) {
|
||||
return str.size() >= suffix.size() &&
|
||||
memcmp(str.data() + str.size() - suffix.size(), suffix.data(),
|
||||
suffix.size()) == 0;
|
||||
}
|
||||
|
||||
inline std::string StripSuffixString(const std::string& str,
|
||||
const std::string& suffix) {
|
||||
if (HasSuffixString(str, suffix)) {
|
||||
return str.substr(0, str.size() - suffix.size());
|
||||
} else {
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// ReplaceCharacters
|
||||
// Replaces any occurrence of the character 'remove' (or the characters
|
||||
// in 'remove') with the character 'replacewith'.
|
||||
// Good for keeping html characters or protocol characters (\t) out
|
||||
// of places where they might cause a problem.
|
||||
// StripWhitespace
|
||||
// Removes whitespaces from both ends of the given string.
|
||||
// ----------------------------------------------------------------------
|
||||
PROTOBUF_EXPORT void ReplaceCharacters(std::string* s, const char* remove,
|
||||
char replacewith);
|
||||
|
||||
PROTOBUF_EXPORT void StripWhitespace(std::string* s);
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// LowerString()
|
||||
// UpperString()
|
||||
// ToUpper()
|
||||
// Convert the characters in "s" to lowercase or uppercase. ASCII-only:
|
||||
// these functions intentionally ignore locale because they are applied to
|
||||
// identifiers used in the Protocol Buffer language, not to natural-language
|
||||
// strings.
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline void LowerString(std::string* s) {
|
||||
std::string::iterator end = s->end();
|
||||
for (std::string::iterator i = s->begin(); i != end; ++i) {
|
||||
// tolower() changes based on locale. We don't want this!
|
||||
if ('A' <= *i && *i <= 'Z') *i += 'a' - 'A';
|
||||
}
|
||||
}
|
||||
|
||||
inline void UpperString(std::string* s) {
|
||||
std::string::iterator end = s->end();
|
||||
for (std::string::iterator i = s->begin(); i != end; ++i) {
|
||||
// toupper() changes based on locale. We don't want this!
|
||||
if ('a' <= *i && *i <= 'z') *i += 'A' - 'a';
|
||||
}
|
||||
}
|
||||
|
||||
inline void ToUpper(std::string* s) { UpperString(s); }
|
||||
|
||||
inline std::string ToUpper(const std::string& s) {
|
||||
std::string out = s;
|
||||
UpperString(&out);
|
||||
return out;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// StringReplace()
|
||||
// Give me a string and two patterns "old" and "new", and I replace
|
||||
// the first instance of "old" in the string with "new", if it
|
||||
// exists. RETURN a new string, regardless of whether the replacement
|
||||
// happened or not.
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
PROTOBUF_EXPORT std::string StringReplace(const std::string& s,
|
||||
const std::string& oldsub,
|
||||
const std::string& newsub,
|
||||
bool replace_all);
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// SplitStringUsing()
|
||||
// Split a string using a character delimiter. Append the components
|
||||
// to 'result'. If there are consecutive delimiters, this function skips
|
||||
// over all of them.
|
||||
// ----------------------------------------------------------------------
|
||||
PROTOBUF_EXPORT void SplitStringUsing(StringPiece full, const char* delim,
|
||||
std::vector<std::string>* res);
|
||||
|
||||
// Split a string using one or more byte delimiters, presented
|
||||
// as a nul-terminated c string. Append the components to 'result'.
|
||||
// If there are consecutive delimiters, this function will return
|
||||
// corresponding empty strings. If you want to drop the empty
|
||||
// strings, try SplitStringUsing().
|
||||
//
|
||||
// If "full" is the empty string, yields an empty string as the only value.
|
||||
// ----------------------------------------------------------------------
|
||||
PROTOBUF_EXPORT void SplitStringAllowEmpty(StringPiece full, const char* delim,
|
||||
std::vector<std::string>* result);
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Split()
|
||||
// Split a string using a character delimiter.
|
||||
// ----------------------------------------------------------------------
|
||||
inline std::vector<std::string> Split(StringPiece full, const char* delim,
|
||||
bool skip_empty = true) {
|
||||
std::vector<std::string> result;
|
||||
if (skip_empty) {
|
||||
SplitStringUsing(full, delim, &result);
|
||||
} else {
|
||||
SplitStringAllowEmpty(full, delim, &result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// JoinStrings()
|
||||
// These methods concatenate a vector of strings into a C++ string, using
|
||||
// the C-string "delim" as a separator between components. There are two
|
||||
// flavors of the function, one flavor returns the concatenated string,
|
||||
// another takes a pointer to the target string. In the latter case the
|
||||
// target string is cleared and overwritten.
|
||||
// ----------------------------------------------------------------------
|
||||
PROTOBUF_EXPORT void JoinStrings(const std::vector<std::string>& components,
|
||||
const char* delim, std::string* result);
|
||||
|
||||
inline std::string JoinStrings(const std::vector<std::string>& components,
|
||||
const char* delim) {
|
||||
std::string result;
|
||||
JoinStrings(components, delim, &result);
|
||||
return result;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// UnescapeCEscapeSequences()
|
||||
// Copies "source" to "dest", rewriting C-style escape sequences
|
||||
// -- '\n', '\r', '\\', '\ooo', etc -- to their ASCII
|
||||
// equivalents. "dest" must be sufficiently large to hold all
|
||||
// the characters in the rewritten string (i.e. at least as large
|
||||
// as strlen(source) + 1 should be safe, since the replacements
|
||||
// are always shorter than the original escaped sequences). It's
|
||||
// safe for source and dest to be the same. RETURNS the length
|
||||
// of dest.
|
||||
//
|
||||
// It allows hex sequences \xhh, or generally \xhhhhh with an
|
||||
// arbitrary number of hex digits, but all of them together must
|
||||
// specify a value of a single byte (e.g. \x0045 is equivalent
|
||||
// to \x45, and \x1234 is erroneous).
|
||||
//
|
||||
// It also allows escape sequences of the form \uhhhh (exactly four
|
||||
// hex digits, upper or lower case) or \Uhhhhhhhh (exactly eight
|
||||
// hex digits, upper or lower case) to specify a Unicode code
|
||||
// point. The dest array will contain the UTF8-encoded version of
|
||||
// that code-point (e.g., if source contains \u2019, then dest will
|
||||
// contain the three bytes 0xE2, 0x80, and 0x99).
|
||||
//
|
||||
// Errors: In the first form of the call, errors are reported with
|
||||
// LOG(ERROR). The same is true for the second form of the call if
|
||||
// the pointer to the string std::vector is nullptr; otherwise, error
|
||||
// messages are stored in the std::vector. In either case, the effect on
|
||||
// the dest array is not defined, but rest of the source will be
|
||||
// processed.
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
PROTOBUF_EXPORT int UnescapeCEscapeSequences(const char* source, char* dest);
|
||||
PROTOBUF_EXPORT int UnescapeCEscapeSequences(const char* source, char* dest,
|
||||
std::vector<std::string>* errors);
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// UnescapeCEscapeString()
|
||||
// This does the same thing as UnescapeCEscapeSequences, but creates
|
||||
// a new string. The caller does not need to worry about allocating
|
||||
// a dest buffer. This should be used for non performance critical
|
||||
// tasks such as printing debug messages. It is safe for src and dest
|
||||
// to be the same.
|
||||
//
|
||||
// The second call stores its errors in a supplied string vector.
|
||||
// If the string vector pointer is nullptr, it reports the errors with LOG().
|
||||
//
|
||||
// In the first and second calls, the length of dest is returned. In the
|
||||
// the third call, the new string is returned.
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
PROTOBUF_EXPORT int UnescapeCEscapeString(const std::string& src,
|
||||
std::string* dest);
|
||||
PROTOBUF_EXPORT int UnescapeCEscapeString(const std::string& src,
|
||||
std::string* dest,
|
||||
std::vector<std::string>* errors);
|
||||
PROTOBUF_EXPORT std::string UnescapeCEscapeString(const std::string& src);
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// CEscape()
|
||||
// Escapes 'src' using C-style escape sequences and returns the resulting
|
||||
// string.
|
||||
//
|
||||
// Escaped chars: \n, \r, \t, ", ', \, and !isprint().
|
||||
// ----------------------------------------------------------------------
|
||||
PROTOBUF_EXPORT std::string CEscape(const std::string& src);
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// CEscapeAndAppend()
|
||||
// Escapes 'src' using C-style escape sequences, and appends the escaped
|
||||
// string to 'dest'.
|
||||
// ----------------------------------------------------------------------
|
||||
PROTOBUF_EXPORT void CEscapeAndAppend(StringPiece src, std::string* dest);
|
||||
|
||||
namespace strings {
|
||||
// Like CEscape() but does not escape bytes with the upper bit set.
|
||||
PROTOBUF_EXPORT std::string Utf8SafeCEscape(const std::string& src);
|
||||
|
||||
// Like CEscape() but uses hex (\x) escapes instead of octals.
|
||||
PROTOBUF_EXPORT std::string CHexEscape(const std::string& src);
|
||||
} // namespace strings
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// strto32()
|
||||
// strtou32()
|
||||
// strto64()
|
||||
// strtou64()
|
||||
// Architecture-neutral plug compatible replacements for strtol() and
|
||||
// strtoul(). Long's have different lengths on ILP-32 and LP-64
|
||||
// platforms, so using these is safer, from the point of view of
|
||||
// overflow behavior, than using the standard libc functions.
|
||||
// ----------------------------------------------------------------------
|
||||
PROTOBUF_EXPORT int32_t strto32_adaptor(const char* nptr, char** endptr,
|
||||
int base);
|
||||
PROTOBUF_EXPORT uint32_t strtou32_adaptor(const char* nptr, char** endptr,
|
||||
int base);
|
||||
|
||||
inline int32_t strto32(const char *nptr, char **endptr, int base) {
|
||||
if (sizeof(int32_t) == sizeof(long))
|
||||
return strtol(nptr, endptr, base);
|
||||
else
|
||||
return strto32_adaptor(nptr, endptr, base);
|
||||
}
|
||||
|
||||
inline uint32_t strtou32(const char *nptr, char **endptr, int base) {
|
||||
if (sizeof(uint32_t) == sizeof(unsigned long))
|
||||
return strtoul(nptr, endptr, base);
|
||||
else
|
||||
return strtou32_adaptor(nptr, endptr, base);
|
||||
}
|
||||
|
||||
// For now, long long is 64-bit on all the platforms we care about, so these
|
||||
// functions can simply pass the call to strto[u]ll.
|
||||
inline int64_t strto64(const char *nptr, char **endptr, int base) {
|
||||
static_assert(sizeof(int64_t) == sizeof(long long),
|
||||
"sizeof int64_t is not sizeof long long");
|
||||
return strtoll(nptr, endptr, base);
|
||||
}
|
||||
|
||||
inline uint64_t strtou64(const char *nptr, char **endptr, int base) {
|
||||
static_assert(sizeof(uint64_t) == sizeof(unsigned long long),
|
||||
"sizeof uint64_t is not sizeof unsigned long long");
|
||||
return strtoull(nptr, endptr, base);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// safe_strtob()
|
||||
// safe_strto32()
|
||||
// safe_strtou32()
|
||||
// safe_strto64()
|
||||
// safe_strtou64()
|
||||
// safe_strtof()
|
||||
// safe_strtod()
|
||||
// ----------------------------------------------------------------------
|
||||
PROTOBUF_EXPORT bool safe_strtob(StringPiece str, bool* value);
|
||||
|
||||
PROTOBUF_EXPORT bool safe_strto32(const std::string& str, int32_t* value);
|
||||
PROTOBUF_EXPORT bool safe_strtou32(const std::string& str, uint32_t* value);
|
||||
inline bool safe_strto32(const char* str, int32_t* value) {
|
||||
return safe_strto32(std::string(str), value);
|
||||
}
|
||||
inline bool safe_strto32(StringPiece str, int32_t* value) {
|
||||
return safe_strto32(str.ToString(), value);
|
||||
}
|
||||
inline bool safe_strtou32(const char* str, uint32_t* value) {
|
||||
return safe_strtou32(std::string(str), value);
|
||||
}
|
||||
inline bool safe_strtou32(StringPiece str, uint32_t* value) {
|
||||
return safe_strtou32(str.ToString(), value);
|
||||
}
|
||||
|
||||
PROTOBUF_EXPORT bool safe_strto64(const std::string& str, int64_t* value);
|
||||
PROTOBUF_EXPORT bool safe_strtou64(const std::string& str, uint64_t* value);
|
||||
inline bool safe_strto64(const char* str, int64_t* value) {
|
||||
return safe_strto64(std::string(str), value);
|
||||
}
|
||||
inline bool safe_strto64(StringPiece str, int64_t* value) {
|
||||
return safe_strto64(str.ToString(), value);
|
||||
}
|
||||
inline bool safe_strtou64(const char* str, uint64_t* value) {
|
||||
return safe_strtou64(std::string(str), value);
|
||||
}
|
||||
inline bool safe_strtou64(StringPiece str, uint64_t* value) {
|
||||
return safe_strtou64(str.ToString(), value);
|
||||
}
|
||||
|
||||
PROTOBUF_EXPORT bool safe_strtof(const char* str, float* value);
|
||||
PROTOBUF_EXPORT bool safe_strtod(const char* str, double* value);
|
||||
inline bool safe_strtof(const std::string& str, float* value) {
|
||||
return safe_strtof(str.c_str(), value);
|
||||
}
|
||||
inline bool safe_strtod(const std::string& str, double* value) {
|
||||
return safe_strtod(str.c_str(), value);
|
||||
}
|
||||
inline bool safe_strtof(StringPiece str, float* value) {
|
||||
return safe_strtof(str.ToString(), value);
|
||||
}
|
||||
inline bool safe_strtod(StringPiece str, double* value) {
|
||||
return safe_strtod(str.ToString(), value);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// FastIntToBuffer()
|
||||
// FastHexToBuffer()
|
||||
// FastHex64ToBuffer()
|
||||
// FastHex32ToBuffer()
|
||||
// FastTimeToBuffer()
|
||||
// These are intended for speed. FastIntToBuffer() assumes the
|
||||
// integer is non-negative. FastHexToBuffer() puts output in
|
||||
// hex rather than decimal. FastTimeToBuffer() puts the output
|
||||
// into RFC822 format.
|
||||
//
|
||||
// FastHex64ToBuffer() puts a 64-bit unsigned value in hex-format,
|
||||
// padded to exactly 16 bytes (plus one byte for '\0')
|
||||
//
|
||||
// FastHex32ToBuffer() puts a 32-bit unsigned value in hex-format,
|
||||
// padded to exactly 8 bytes (plus one byte for '\0')
|
||||
//
|
||||
// All functions take the output buffer as an arg.
|
||||
// They all return a pointer to the beginning of the output,
|
||||
// which may not be the beginning of the input buffer.
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
// Suggested buffer size for FastToBuffer functions. Also works with
|
||||
// DoubleToBuffer() and FloatToBuffer().
|
||||
static const int kFastToBufferSize = 32;
|
||||
|
||||
PROTOBUF_EXPORT char* FastInt32ToBuffer(int32_t i, char* buffer);
|
||||
PROTOBUF_EXPORT char* FastInt64ToBuffer(int64_t i, char* buffer);
|
||||
char* FastUInt32ToBuffer(uint32_t i, char* buffer); // inline below
|
||||
char* FastUInt64ToBuffer(uint64_t i, char* buffer); // inline below
|
||||
PROTOBUF_EXPORT char* FastHexToBuffer(int i, char* buffer);
|
||||
PROTOBUF_EXPORT char* FastHex64ToBuffer(uint64_t i, char* buffer);
|
||||
PROTOBUF_EXPORT char* FastHex32ToBuffer(uint32_t i, char* buffer);
|
||||
|
||||
// at least 22 bytes long
|
||||
inline char* FastIntToBuffer(int i, char* buffer) {
|
||||
return (sizeof(i) == 4 ?
|
||||
FastInt32ToBuffer(i, buffer) : FastInt64ToBuffer(i, buffer));
|
||||
}
|
||||
inline char* FastUIntToBuffer(unsigned int i, char* buffer) {
|
||||
return (sizeof(i) == 4 ?
|
||||
FastUInt32ToBuffer(i, buffer) : FastUInt64ToBuffer(i, buffer));
|
||||
}
|
||||
inline char* FastLongToBuffer(long i, char* buffer) {
|
||||
return (sizeof(i) == 4 ?
|
||||
FastInt32ToBuffer(i, buffer) : FastInt64ToBuffer(i, buffer));
|
||||
}
|
||||
inline char* FastULongToBuffer(unsigned long i, char* buffer) {
|
||||
return (sizeof(i) == 4 ?
|
||||
FastUInt32ToBuffer(i, buffer) : FastUInt64ToBuffer(i, buffer));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// FastInt32ToBufferLeft()
|
||||
// FastUInt32ToBufferLeft()
|
||||
// FastInt64ToBufferLeft()
|
||||
// FastUInt64ToBufferLeft()
|
||||
//
|
||||
// Like the Fast*ToBuffer() functions above, these are intended for speed.
|
||||
// Unlike the Fast*ToBuffer() functions, however, these functions write
|
||||
// their output to the beginning of the buffer (hence the name, as the
|
||||
// output is left-aligned). The caller is responsible for ensuring that
|
||||
// the buffer has enough space to hold the output.
|
||||
//
|
||||
// Returns a pointer to the end of the string (i.e. the null character
|
||||
// terminating the string).
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
PROTOBUF_EXPORT char* FastInt32ToBufferLeft(int32_t i, char* buffer);
|
||||
PROTOBUF_EXPORT char* FastUInt32ToBufferLeft(uint32_t i, char* buffer);
|
||||
PROTOBUF_EXPORT char* FastInt64ToBufferLeft(int64_t i, char* buffer);
|
||||
PROTOBUF_EXPORT char* FastUInt64ToBufferLeft(uint64_t i, char* buffer);
|
||||
|
||||
// Just define these in terms of the above.
|
||||
inline char* FastUInt32ToBuffer(uint32_t i, char* buffer) {
|
||||
FastUInt32ToBufferLeft(i, buffer);
|
||||
return buffer;
|
||||
}
|
||||
inline char* FastUInt64ToBuffer(uint64_t i, char* buffer) {
|
||||
FastUInt64ToBufferLeft(i, buffer);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
inline std::string SimpleBtoa(bool value) { return value ? "true" : "false"; }
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// SimpleItoa()
|
||||
// Description: converts an integer to a string.
|
||||
//
|
||||
// Return value: string
|
||||
// ----------------------------------------------------------------------
|
||||
PROTOBUF_EXPORT std::string SimpleItoa(int i);
|
||||
PROTOBUF_EXPORT std::string SimpleItoa(unsigned int i);
|
||||
PROTOBUF_EXPORT std::string SimpleItoa(long i);
|
||||
PROTOBUF_EXPORT std::string SimpleItoa(unsigned long i);
|
||||
PROTOBUF_EXPORT std::string SimpleItoa(long long i);
|
||||
PROTOBUF_EXPORT std::string SimpleItoa(unsigned long long i);
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// SimpleDtoa()
|
||||
// SimpleFtoa()
|
||||
// DoubleToBuffer()
|
||||
// FloatToBuffer()
|
||||
// Description: converts a double or float to a string which, if
|
||||
// passed to NoLocaleStrtod(), will produce the exact same original double
|
||||
// (except in case of NaN; all NaNs are considered the same value).
|
||||
// We try to keep the string short but it's not guaranteed to be as
|
||||
// short as possible.
|
||||
//
|
||||
// DoubleToBuffer() and FloatToBuffer() write the text to the given
|
||||
// buffer and return it. The buffer must be at least
|
||||
// kDoubleToBufferSize bytes for doubles and kFloatToBufferSize
|
||||
// bytes for floats. kFastToBufferSize is also guaranteed to be large
|
||||
// enough to hold either.
|
||||
//
|
||||
// Return value: string
|
||||
// ----------------------------------------------------------------------
|
||||
PROTOBUF_EXPORT std::string SimpleDtoa(double value);
|
||||
PROTOBUF_EXPORT std::string SimpleFtoa(float value);
|
||||
|
||||
PROTOBUF_EXPORT char* DoubleToBuffer(double i, char* buffer);
|
||||
PROTOBUF_EXPORT char* FloatToBuffer(float i, char* buffer);
|
||||
|
||||
// In practice, doubles should never need more than 24 bytes and floats
|
||||
// should never need more than 14 (including null terminators), but we
|
||||
// overestimate to be safe.
|
||||
static const int kDoubleToBufferSize = 32;
|
||||
static const int kFloatToBufferSize = 24;
|
||||
|
||||
namespace strings {
|
||||
|
||||
enum PadSpec {
|
||||
NO_PAD = 1,
|
||||
ZERO_PAD_2,
|
||||
ZERO_PAD_3,
|
||||
ZERO_PAD_4,
|
||||
ZERO_PAD_5,
|
||||
ZERO_PAD_6,
|
||||
ZERO_PAD_7,
|
||||
ZERO_PAD_8,
|
||||
ZERO_PAD_9,
|
||||
ZERO_PAD_10,
|
||||
ZERO_PAD_11,
|
||||
ZERO_PAD_12,
|
||||
ZERO_PAD_13,
|
||||
ZERO_PAD_14,
|
||||
ZERO_PAD_15,
|
||||
ZERO_PAD_16,
|
||||
};
|
||||
|
||||
struct Hex {
|
||||
uint64_t value;
|
||||
enum PadSpec spec;
|
||||
template <class Int>
|
||||
explicit Hex(Int v, PadSpec s = NO_PAD)
|
||||
: spec(s) {
|
||||
// Prevent sign-extension by casting integers to
|
||||
// their unsigned counterparts.
|
||||
#ifdef LANG_CXX11
|
||||
static_assert(
|
||||
sizeof(v) == 1 || sizeof(v) == 2 || sizeof(v) == 4 || sizeof(v) == 8,
|
||||
"Unknown integer type");
|
||||
#endif
|
||||
value = sizeof(v) == 1 ? static_cast<uint8_t>(v)
|
||||
: sizeof(v) == 2 ? static_cast<uint16_t>(v)
|
||||
: sizeof(v) == 4 ? static_cast<uint32_t>(v)
|
||||
: static_cast<uint64_t>(v);
|
||||
}
|
||||
};
|
||||
|
||||
struct PROTOBUF_EXPORT AlphaNum {
|
||||
const char *piece_data_; // move these to string_ref eventually
|
||||
size_t piece_size_; // move these to string_ref eventually
|
||||
|
||||
char digits[kFastToBufferSize];
|
||||
|
||||
// No bool ctor -- bools convert to an integral type.
|
||||
// A bool ctor would also convert incoming pointers (bletch).
|
||||
|
||||
AlphaNum(int i32)
|
||||
: piece_data_(digits),
|
||||
piece_size_(FastInt32ToBufferLeft(i32, digits) - &digits[0]) {}
|
||||
AlphaNum(unsigned int u32)
|
||||
: piece_data_(digits),
|
||||
piece_size_(FastUInt32ToBufferLeft(u32, digits) - &digits[0]) {}
|
||||
AlphaNum(long long i64)
|
||||
: piece_data_(digits),
|
||||
piece_size_(FastInt64ToBufferLeft(i64, digits) - &digits[0]) {}
|
||||
AlphaNum(unsigned long long u64)
|
||||
: piece_data_(digits),
|
||||
piece_size_(FastUInt64ToBufferLeft(u64, digits) - &digits[0]) {}
|
||||
|
||||
// Note: on some architectures, "long" is only 32 bits, not 64, but the
|
||||
// performance hit of using FastInt64ToBufferLeft to handle 32-bit values
|
||||
// is quite minor.
|
||||
AlphaNum(long i64)
|
||||
: piece_data_(digits),
|
||||
piece_size_(FastInt64ToBufferLeft(i64, digits) - &digits[0]) {}
|
||||
AlphaNum(unsigned long u64)
|
||||
: piece_data_(digits),
|
||||
piece_size_(FastUInt64ToBufferLeft(u64, digits) - &digits[0]) {}
|
||||
|
||||
AlphaNum(float f)
|
||||
: piece_data_(digits), piece_size_(strlen(FloatToBuffer(f, digits))) {}
|
||||
AlphaNum(double f)
|
||||
: piece_data_(digits), piece_size_(strlen(DoubleToBuffer(f, digits))) {}
|
||||
|
||||
AlphaNum(Hex hex);
|
||||
|
||||
AlphaNum(const char* c_str)
|
||||
: piece_data_(c_str), piece_size_(strlen(c_str)) {}
|
||||
// TODO: Add a string_ref constructor, eventually
|
||||
// AlphaNum(const StringPiece &pc) : piece(pc) {}
|
||||
|
||||
AlphaNum(const std::string& str)
|
||||
: piece_data_(str.data()), piece_size_(str.size()) {}
|
||||
|
||||
AlphaNum(StringPiece str)
|
||||
: piece_data_(str.data()), piece_size_(str.size()) {}
|
||||
|
||||
size_t size() const { return piece_size_; }
|
||||
const char *data() const { return piece_data_; }
|
||||
|
||||
private:
|
||||
// Use ":" not ':'
|
||||
AlphaNum(char c); // NOLINT(runtime/explicit)
|
||||
|
||||
// Disallow copy and assign.
|
||||
AlphaNum(const AlphaNum&);
|
||||
void operator=(const AlphaNum&);
|
||||
};
|
||||
|
||||
} // namespace strings
|
||||
|
||||
using strings::AlphaNum;
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// StrCat()
|
||||
// This merges the given strings or numbers, with no delimiter. This
|
||||
// is designed to be the fastest possible way to construct a string out
|
||||
// of a mix of raw C strings, strings, bool values,
|
||||
// and numeric values.
|
||||
//
|
||||
// Don't use this for user-visible strings. The localization process
|
||||
// works poorly on strings built up out of fragments.
|
||||
//
|
||||
// For clarity and performance, don't use StrCat when appending to a
|
||||
// string. In particular, avoid using any of these (anti-)patterns:
|
||||
// str.append(StrCat(...)
|
||||
// str += StrCat(...)
|
||||
// str = StrCat(str, ...)
|
||||
// where the last is the worse, with the potential to change a loop
|
||||
// from a linear time operation with O(1) dynamic allocations into a
|
||||
// quadratic time operation with O(n) dynamic allocations. StrAppend
|
||||
// is a better choice than any of the above, subject to the restriction
|
||||
// of StrAppend(&str, a, b, c, ...) that none of the a, b, c, ... may
|
||||
// be a reference into str.
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
PROTOBUF_EXPORT std::string StrCat(const AlphaNum& a, const AlphaNum& b);
|
||||
PROTOBUF_EXPORT std::string StrCat(const AlphaNum& a, const AlphaNum& b,
|
||||
const AlphaNum& c);
|
||||
PROTOBUF_EXPORT std::string StrCat(const AlphaNum& a, const AlphaNum& b,
|
||||
const AlphaNum& c, const AlphaNum& d);
|
||||
PROTOBUF_EXPORT std::string StrCat(const AlphaNum& a, const AlphaNum& b,
|
||||
const AlphaNum& c, const AlphaNum& d,
|
||||
const AlphaNum& e);
|
||||
PROTOBUF_EXPORT std::string StrCat(const AlphaNum& a, const AlphaNum& b,
|
||||
const AlphaNum& c, const AlphaNum& d,
|
||||
const AlphaNum& e, const AlphaNum& f);
|
||||
PROTOBUF_EXPORT std::string StrCat(const AlphaNum& a, const AlphaNum& b,
|
||||
const AlphaNum& c, const AlphaNum& d,
|
||||
const AlphaNum& e, const AlphaNum& f,
|
||||
const AlphaNum& g);
|
||||
PROTOBUF_EXPORT std::string StrCat(const AlphaNum& a, const AlphaNum& b,
|
||||
const AlphaNum& c, const AlphaNum& d,
|
||||
const AlphaNum& e, const AlphaNum& f,
|
||||
const AlphaNum& g, const AlphaNum& h);
|
||||
PROTOBUF_EXPORT std::string StrCat(const AlphaNum& a, const AlphaNum& b,
|
||||
const AlphaNum& c, const AlphaNum& d,
|
||||
const AlphaNum& e, const AlphaNum& f,
|
||||
const AlphaNum& g, const AlphaNum& h,
|
||||
const AlphaNum& i);
|
||||
|
||||
inline std::string StrCat(const AlphaNum& a) {
|
||||
return std::string(a.data(), a.size());
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// StrAppend()
|
||||
// Same as above, but adds the output to the given string.
|
||||
// WARNING: For speed, StrAppend does not try to check each of its input
|
||||
// arguments to be sure that they are not a subset of the string being
|
||||
// appended to. That is, while this will work:
|
||||
//
|
||||
// string s = "foo";
|
||||
// s += s;
|
||||
//
|
||||
// This will not (necessarily) work:
|
||||
//
|
||||
// string s = "foo";
|
||||
// StrAppend(&s, s);
|
||||
//
|
||||
// Note: while StrCat supports appending up to 9 arguments, StrAppend
|
||||
// is currently limited to 4. That's rarely an issue except when
|
||||
// automatically transforming StrCat to StrAppend, and can easily be
|
||||
// worked around as consecutive calls to StrAppend are quite efficient.
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
PROTOBUF_EXPORT void StrAppend(std::string* dest, const AlphaNum& a);
|
||||
PROTOBUF_EXPORT void StrAppend(std::string* dest, const AlphaNum& a,
|
||||
const AlphaNum& b);
|
||||
PROTOBUF_EXPORT void StrAppend(std::string* dest, const AlphaNum& a,
|
||||
const AlphaNum& b, const AlphaNum& c);
|
||||
PROTOBUF_EXPORT void StrAppend(std::string* dest, const AlphaNum& a,
|
||||
const AlphaNum& b, const AlphaNum& c,
|
||||
const AlphaNum& d);
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Join()
|
||||
// These methods concatenate a range of components into a C++ string, using
|
||||
// the C-string "delim" as a separator between components.
|
||||
// ----------------------------------------------------------------------
|
||||
template <typename Iterator>
|
||||
void Join(Iterator start, Iterator end, const char* delim,
|
||||
std::string* result) {
|
||||
for (Iterator it = start; it != end; ++it) {
|
||||
if (it != start) {
|
||||
result->append(delim);
|
||||
}
|
||||
StrAppend(result, *it);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Range>
|
||||
std::string Join(const Range& components, const char* delim) {
|
||||
std::string result;
|
||||
Join(components.begin(), components.end(), delim, &result);
|
||||
return result;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// ToHex()
|
||||
// Return a lower-case hex string representation of the given integer.
|
||||
// ----------------------------------------------------------------------
|
||||
PROTOBUF_EXPORT std::string ToHex(uint64_t num);
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// GlobalReplaceSubstring()
|
||||
// Replaces all instances of a substring in a string. Does nothing
|
||||
// if 'substring' is empty. Returns the number of replacements.
|
||||
//
|
||||
// NOTE: The string pieces must not overlap s.
|
||||
// ----------------------------------------------------------------------
|
||||
PROTOBUF_EXPORT int GlobalReplaceSubstring(const std::string& substring,
|
||||
const std::string& replacement,
|
||||
std::string* s);
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Base64Unescape()
|
||||
// Converts "src" which is encoded in Base64 to its binary equivalent and
|
||||
// writes it to "dest". If src contains invalid characters, dest is cleared
|
||||
// and the function returns false. Returns true on success.
|
||||
// ----------------------------------------------------------------------
|
||||
PROTOBUF_EXPORT bool Base64Unescape(StringPiece src, std::string* dest);
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// WebSafeBase64Unescape()
|
||||
// This is a variation of Base64Unescape which uses '-' instead of '+', and
|
||||
// '_' instead of '/'. src is not null terminated, instead specify len. I
|
||||
// recommend that slen<szdest, but we honor szdest anyway.
|
||||
// RETURNS the length of dest, or -1 if src contains invalid chars.
|
||||
|
||||
// The variation that stores into a string clears the string first, and
|
||||
// returns false (with dest empty) if src contains invalid chars; for
|
||||
// this version src and dest must be different strings.
|
||||
// ----------------------------------------------------------------------
|
||||
PROTOBUF_EXPORT int WebSafeBase64Unescape(const char* src, int slen, char* dest,
|
||||
int szdest);
|
||||
PROTOBUF_EXPORT bool WebSafeBase64Unescape(StringPiece src, std::string* dest);
|
||||
|
||||
// Return the length to use for the output buffer given to the base64 escape
|
||||
// routines. Make sure to use the same value for do_padding in both.
|
||||
// This function may return incorrect results if given input_len values that
|
||||
// are extremely high, which should happen rarely.
|
||||
PROTOBUF_EXPORT int CalculateBase64EscapedLen(int input_len, bool do_padding);
|
||||
// Use this version when calling Base64Escape without a do_padding arg.
|
||||
PROTOBUF_EXPORT int CalculateBase64EscapedLen(int input_len);
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Base64Escape()
|
||||
// WebSafeBase64Escape()
|
||||
// Encode "src" to "dest" using base64 encoding.
|
||||
// src is not null terminated, instead specify len.
|
||||
// 'dest' should have at least CalculateBase64EscapedLen() length.
|
||||
// RETURNS the length of dest.
|
||||
// The WebSafe variation use '-' instead of '+' and '_' instead of '/'
|
||||
// so that we can place the out in the URL or cookies without having
|
||||
// to escape them. It also has an extra parameter "do_padding",
|
||||
// which when set to false will prevent padding with "=".
|
||||
// ----------------------------------------------------------------------
|
||||
PROTOBUF_EXPORT int Base64Escape(const unsigned char* src, int slen, char* dest,
|
||||
int szdest);
|
||||
PROTOBUF_EXPORT int WebSafeBase64Escape(const unsigned char* src, int slen,
|
||||
char* dest, int szdest,
|
||||
bool do_padding);
|
||||
// Encode src into dest with padding.
|
||||
PROTOBUF_EXPORT void Base64Escape(StringPiece src, std::string* dest);
|
||||
// Encode src into dest web-safely without padding.
|
||||
PROTOBUF_EXPORT void WebSafeBase64Escape(StringPiece src, std::string* dest);
|
||||
// Encode src into dest web-safely with padding.
|
||||
PROTOBUF_EXPORT void WebSafeBase64EscapeWithPadding(StringPiece src,
|
||||
std::string* dest);
|
||||
|
||||
PROTOBUF_EXPORT void Base64Escape(const unsigned char* src, int szsrc,
|
||||
std::string* dest, bool do_padding);
|
||||
PROTOBUF_EXPORT void WebSafeBase64Escape(const unsigned char* src, int szsrc,
|
||||
std::string* dest, bool do_padding);
|
||||
|
||||
inline bool IsValidCodePoint(uint32_t code_point) {
|
||||
return code_point < 0xD800 ||
|
||||
(code_point >= 0xE000 && code_point <= 0x10FFFF);
|
||||
}
|
||||
|
||||
static const int UTFmax = 4;
|
||||
// ----------------------------------------------------------------------
|
||||
// EncodeAsUTF8Char()
|
||||
// Helper to append a Unicode code point to a string as UTF8, without bringing
|
||||
// in any external dependencies. The output buffer must be as least 4 bytes
|
||||
// large.
|
||||
// ----------------------------------------------------------------------
|
||||
PROTOBUF_EXPORT int EncodeAsUTF8Char(uint32_t code_point, char* output);
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// UTF8FirstLetterNumBytes()
|
||||
// Length of the first UTF-8 character.
|
||||
// ----------------------------------------------------------------------
|
||||
PROTOBUF_EXPORT int UTF8FirstLetterNumBytes(const char* src, int len);
|
||||
|
||||
// From google3/third_party/absl/strings/escaping.h
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// CleanStringLineEndings()
|
||||
// Clean up a multi-line string to conform to Unix line endings.
|
||||
// Reads from src and appends to dst, so usually dst should be empty.
|
||||
//
|
||||
// If there is no line ending at the end of a non-empty string, it can
|
||||
// be added automatically.
|
||||
//
|
||||
// Four different types of input are correctly handled:
|
||||
//
|
||||
// - Unix/Linux files: line ending is LF: pass through unchanged
|
||||
//
|
||||
// - DOS/Windows files: line ending is CRLF: convert to LF
|
||||
//
|
||||
// - Legacy Mac files: line ending is CR: convert to LF
|
||||
//
|
||||
// - Garbled files: random line endings: convert gracefully
|
||||
// lonely CR, lonely LF, CRLF: convert to LF
|
||||
//
|
||||
// @param src The multi-line string to convert
|
||||
// @param dst The converted string is appended to this string
|
||||
// @param auto_end_last_line Automatically terminate the last line
|
||||
//
|
||||
// Limitations:
|
||||
//
|
||||
// This does not do the right thing for CRCRLF files created by
|
||||
// broken programs that do another Unix->DOS conversion on files
|
||||
// that are already in CRLF format. For this, a two-pass approach
|
||||
// brute-force would be needed that
|
||||
//
|
||||
// (1) determines the presence of LF (first one is ok)
|
||||
// (2) if yes, removes any CR, else convert every CR to LF
|
||||
PROTOBUF_EXPORT void CleanStringLineEndings(const std::string& src,
|
||||
std::string* dst,
|
||||
bool auto_end_last_line);
|
||||
|
||||
// Same as above, but transforms the argument in place.
|
||||
PROTOBUF_EXPORT void CleanStringLineEndings(std::string* str,
|
||||
bool auto_end_last_line);
|
||||
|
||||
namespace strings {
|
||||
inline bool EndsWith(StringPiece text, StringPiece suffix) {
|
||||
return suffix.empty() ||
|
||||
(text.size() >= suffix.size() &&
|
||||
memcmp(text.data() + (text.size() - suffix.size()), suffix.data(),
|
||||
suffix.size()) == 0);
|
||||
}
|
||||
} // namespace strings
|
||||
|
||||
namespace internal {
|
||||
|
||||
// A locale-independent version of the standard strtod(), which always
|
||||
// uses a dot as the decimal separator.
|
||||
double NoLocaleStrtod(const char* str, char** endptr);
|
||||
|
||||
} // namespace internal
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_STUBS_STRUTIL_H__
|
||||
@@ -1,178 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// from google3/strings/substitute.h
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/stringpiece.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_STUBS_SUBSTITUTE_H_
|
||||
#define GOOGLE_PROTOBUF_STUBS_SUBSTITUTE_H_
|
||||
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace strings {
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// strings::Substitute()
|
||||
// strings::SubstituteAndAppend()
|
||||
// Kind of like StringPrintf, but different.
|
||||
//
|
||||
// Example:
|
||||
// string GetMessage(string first_name, string last_name, int age) {
|
||||
// return strings::Substitute("My name is $0 $1 and I am $2 years old.",
|
||||
// first_name, last_name, age);
|
||||
// }
|
||||
//
|
||||
// Differences from StringPrintf:
|
||||
// * The format string does not identify the types of arguments.
|
||||
// Instead, the magic of C++ deals with this for us. See below
|
||||
// for a list of accepted types.
|
||||
// * Substitutions in the format string are identified by a '$'
|
||||
// followed by a digit. So, you can use arguments out-of-order and
|
||||
// use the same argument multiple times.
|
||||
// * It's much faster than StringPrintf.
|
||||
//
|
||||
// Supported types:
|
||||
// * Strings (const char*, const string&)
|
||||
// * Note that this means you do not have to add .c_str() to all of
|
||||
// your strings. In fact, you shouldn't; it will be slower.
|
||||
// * int32, int64, uint32, uint64: Formatted using SimpleItoa().
|
||||
// * float, double: Formatted using SimpleFtoa() and SimpleDtoa().
|
||||
// * bool: Printed as "true" or "false".
|
||||
//
|
||||
// SubstituteAndAppend() is like Substitute() but appends the result to
|
||||
// *output. Example:
|
||||
//
|
||||
// string str;
|
||||
// strings::SubstituteAndAppend(&str,
|
||||
// "My name is $0 $1 and I am $2 years old.",
|
||||
// first_name, last_name, age);
|
||||
//
|
||||
// Substitute() is significantly faster than StringPrintf(). For very
|
||||
// large strings, it may be orders of magnitude faster.
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
namespace internal { // Implementation details.
|
||||
|
||||
class SubstituteArg {
|
||||
public:
|
||||
inline SubstituteArg(const char* value)
|
||||
: text_(value), size_(strlen(text_)) {}
|
||||
inline SubstituteArg(const std::string& value)
|
||||
: text_(value.data()), size_(value.size()) {}
|
||||
inline SubstituteArg(const StringPiece value)
|
||||
: text_(value.data()), size_(value.size()) {}
|
||||
|
||||
// Indicates that no argument was given.
|
||||
inline explicit SubstituteArg()
|
||||
: text_(nullptr), size_(-1) {}
|
||||
|
||||
// Primitives
|
||||
// We don't overload for signed and unsigned char because if people are
|
||||
// explicitly declaring their chars as signed or unsigned then they are
|
||||
// probably actually using them as 8-bit integers and would probably
|
||||
// prefer an integer representation. But, we don't really know. So, we
|
||||
// make the caller decide what to do.
|
||||
inline SubstituteArg(char value)
|
||||
: text_(scratch_), size_(1) { scratch_[0] = value; }
|
||||
inline SubstituteArg(short value)
|
||||
: text_(FastInt32ToBuffer(value, scratch_)), size_(strlen(text_)) {}
|
||||
inline SubstituteArg(unsigned short value)
|
||||
: text_(FastUInt32ToBuffer(value, scratch_)), size_(strlen(text_)) {}
|
||||
inline SubstituteArg(int value)
|
||||
: text_(FastInt32ToBuffer(value, scratch_)), size_(strlen(text_)) {}
|
||||
inline SubstituteArg(unsigned int value)
|
||||
: text_(FastUInt32ToBuffer(value, scratch_)), size_(strlen(text_)) {}
|
||||
inline SubstituteArg(long value)
|
||||
: text_(FastLongToBuffer(value, scratch_)), size_(strlen(text_)) {}
|
||||
inline SubstituteArg(unsigned long value)
|
||||
: text_(FastULongToBuffer(value, scratch_)), size_(strlen(text_)) {}
|
||||
inline SubstituteArg(long long value)
|
||||
: text_(FastInt64ToBuffer(value, scratch_)), size_(strlen(text_)) {}
|
||||
inline SubstituteArg(unsigned long long value)
|
||||
: text_(FastUInt64ToBuffer(value, scratch_)), size_(strlen(text_)) {}
|
||||
inline SubstituteArg(float value)
|
||||
: text_(FloatToBuffer(value, scratch_)), size_(strlen(text_)) {}
|
||||
inline SubstituteArg(double value)
|
||||
: text_(DoubleToBuffer(value, scratch_)), size_(strlen(text_)) {}
|
||||
inline SubstituteArg(bool value)
|
||||
: text_(value ? "true" : "false"), size_(strlen(text_)) {}
|
||||
|
||||
inline const char* data() const { return text_; }
|
||||
inline int size() const { return size_; }
|
||||
|
||||
private:
|
||||
const char* text_;
|
||||
int size_;
|
||||
char scratch_[kFastToBufferSize];
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
PROTOBUF_EXPORT std::string Substitute(
|
||||
const std::string& format,
|
||||
const internal::SubstituteArg& arg0 = internal::SubstituteArg(),
|
||||
const internal::SubstituteArg& arg1 = internal::SubstituteArg(),
|
||||
const internal::SubstituteArg& arg2 = internal::SubstituteArg(),
|
||||
const internal::SubstituteArg& arg3 = internal::SubstituteArg(),
|
||||
const internal::SubstituteArg& arg4 = internal::SubstituteArg(),
|
||||
const internal::SubstituteArg& arg5 = internal::SubstituteArg(),
|
||||
const internal::SubstituteArg& arg6 = internal::SubstituteArg(),
|
||||
const internal::SubstituteArg& arg7 = internal::SubstituteArg(),
|
||||
const internal::SubstituteArg& arg8 = internal::SubstituteArg(),
|
||||
const internal::SubstituteArg& arg9 = internal::SubstituteArg());
|
||||
|
||||
PROTOBUF_EXPORT void SubstituteAndAppend(
|
||||
std::string* output, const char* format,
|
||||
const internal::SubstituteArg& arg0 = internal::SubstituteArg(),
|
||||
const internal::SubstituteArg& arg1 = internal::SubstituteArg(),
|
||||
const internal::SubstituteArg& arg2 = internal::SubstituteArg(),
|
||||
const internal::SubstituteArg& arg3 = internal::SubstituteArg(),
|
||||
const internal::SubstituteArg& arg4 = internal::SubstituteArg(),
|
||||
const internal::SubstituteArg& arg5 = internal::SubstituteArg(),
|
||||
const internal::SubstituteArg& arg6 = internal::SubstituteArg(),
|
||||
const internal::SubstituteArg& arg7 = internal::SubstituteArg(),
|
||||
const internal::SubstituteArg& arg8 = internal::SubstituteArg(),
|
||||
const internal::SubstituteArg& arg9 = internal::SubstituteArg());
|
||||
|
||||
} // namespace strings
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_STUBS_SUBSTITUTE_H_
|
||||
@@ -1,138 +0,0 @@
|
||||
// Copyright 2005 Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// ----
|
||||
// Author: lar@google.com (Laramie Leavitt)
|
||||
//
|
||||
// Template metaprogramming utility functions.
|
||||
//
|
||||
// This code is compiled directly on many platforms, including client
|
||||
// platforms like Windows, Mac, and embedded systems. Before making
|
||||
// any changes here, make sure that you're not breaking any platforms.
|
||||
//
|
||||
//
|
||||
// The names chosen here reflect those used in tr1 and the boost::mpl
|
||||
// library, there are similar operations used in the Loki library as
|
||||
// well. I prefer the boost names for 2 reasons:
|
||||
// 1. I think that portions of the Boost libraries are more likely to
|
||||
// be included in the c++ standard.
|
||||
// 2. It is not impossible that some of the boost libraries will be
|
||||
// included in our own build in the future.
|
||||
// Both of these outcomes means that we may be able to directly replace
|
||||
// some of these with boost equivalents.
|
||||
//
|
||||
#ifndef GOOGLE_PROTOBUF_TEMPLATE_UTIL_H_
|
||||
#define GOOGLE_PROTOBUF_TEMPLATE_UTIL_H_
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
// Types small_ and big_ are guaranteed such that sizeof(small_) <
|
||||
// sizeof(big_)
|
||||
typedef char small_;
|
||||
|
||||
struct big_ {
|
||||
char dummy[2];
|
||||
};
|
||||
|
||||
// Identity metafunction.
|
||||
template <class T>
|
||||
struct identity_ {
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
// integral_constant, defined in tr1, is a wrapper for an integer
|
||||
// value. We don't really need this generality; we could get away
|
||||
// with hardcoding the integer type to bool. We use the fully
|
||||
// general integer_constant for compatibility with tr1.
|
||||
|
||||
template<class T, T v>
|
||||
struct integral_constant {
|
||||
static const T value = v;
|
||||
typedef T value_type;
|
||||
typedef integral_constant<T, v> type;
|
||||
};
|
||||
|
||||
template <class T, T v> const T integral_constant<T, v>::value;
|
||||
|
||||
|
||||
// Abbreviations: true_type and false_type are structs that represent boolean
|
||||
// true and false values. Also define the boost::mpl versions of those names,
|
||||
// true_ and false_.
|
||||
typedef integral_constant<bool, true> true_type;
|
||||
typedef integral_constant<bool, false> false_type;
|
||||
typedef true_type true_;
|
||||
typedef false_type false_;
|
||||
|
||||
// if_ is a templatized conditional statement.
|
||||
// if_<cond, A, B> is a compile time evaluation of cond.
|
||||
// if_<>::type contains A if cond is true, B otherwise.
|
||||
template<bool cond, typename A, typename B>
|
||||
struct if_{
|
||||
typedef A type;
|
||||
};
|
||||
|
||||
template<typename A, typename B>
|
||||
struct if_<false, A, B> {
|
||||
typedef B type;
|
||||
};
|
||||
|
||||
|
||||
// type_equals_ is a template type comparator, similar to Loki IsSameType.
|
||||
// type_equals_<A, B>::value is true iff "A" is the same type as "B".
|
||||
//
|
||||
// New code should prefer base::is_same, defined in base/type_traits.h.
|
||||
// It is functionally identical, but is_same is the standard spelling.
|
||||
template<typename A, typename B>
|
||||
struct type_equals_ : public false_ {
|
||||
};
|
||||
|
||||
template<typename A>
|
||||
struct type_equals_<A, A> : public true_ {
|
||||
};
|
||||
|
||||
// and_ is a template && operator.
|
||||
// and_<A, B>::value evaluates "A::value && B::value".
|
||||
template<typename A, typename B>
|
||||
struct and_ : public integral_constant<bool, (A::value && B::value)> {
|
||||
};
|
||||
|
||||
// or_ is a template || operator.
|
||||
// or_<A, B>::value evaluates "A::value || B::value".
|
||||
template<typename A, typename B>
|
||||
struct or_ : public integral_constant<bool, (A::value || B::value)> {
|
||||
};
|
||||
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_TEMPLATE_UTIL_H_
|
||||
@@ -1,82 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef GOOGLE_PROTOBUF_STUBS_TIME_H_
|
||||
#define GOOGLE_PROTOBUF_STUBS_TIME_H_
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
struct DateTime {
|
||||
int year;
|
||||
int month;
|
||||
int day;
|
||||
int hour;
|
||||
int minute;
|
||||
int second;
|
||||
};
|
||||
|
||||
// Converts a timestamp (seconds elapsed since 1970-01-01T00:00:00, could be
|
||||
// negative to represent time before 1970-01-01) to DateTime. Returns false
|
||||
// if the timestamp is not in the range between 0001-01-01T00:00:00 and
|
||||
// 9999-12-31T23:59:59.
|
||||
bool PROTOBUF_EXPORT SecondsToDateTime(int64_t seconds, DateTime* time);
|
||||
// Converts DateTime to a timestamp (seconds since 1970-01-01T00:00:00).
|
||||
// Returns false if the DateTime is not valid or is not in the valid range.
|
||||
bool PROTOBUF_EXPORT DateTimeToSeconds(const DateTime& time, int64_t* seconds);
|
||||
|
||||
void PROTOBUF_EXPORT GetCurrentTime(int64_t* seconds, int32_t* nanos);
|
||||
|
||||
// Formats a time string in RFC3339 format.
|
||||
//
|
||||
// For example, "2015-05-20T13:29:35.120Z". For nanos, 0, 3, 6 or 9 fractional
|
||||
// digits will be used depending on how many are required to represent the exact
|
||||
// value.
|
||||
//
|
||||
// Note that "nanos" must in the range of [0, 999999999].
|
||||
std::string PROTOBUF_EXPORT FormatTime(int64_t seconds, int32_t nanos);
|
||||
// Parses a time string. This method accepts RFC3339 date/time string with UTC
|
||||
// offset. For example, "2015-05-20T13:29:35.120-08:00".
|
||||
bool PROTOBUF_EXPORT ParseTime(const std::string& value, int64_t* seconds,
|
||||
int32_t* nanos);
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_STUBS_TIME_H_
|
||||
@@ -1,693 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: jschorr@google.com (Joseph Schorr)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
//
|
||||
// Utilities for printing and parsing protocol messages in a human-readable,
|
||||
// text-based format.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_TEXT_FORMAT_H__
|
||||
#define GOOGLE_PROTOBUF_TEXT_FORMAT_H__
|
||||
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/port.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/message.h>
|
||||
#include <google/protobuf/message_lite.h>
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
#ifdef SWIG
|
||||
#error "You cannot SWIG proto headers"
|
||||
#endif
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
namespace internal {
|
||||
PROTOBUF_EXPORT extern const char kDebugStringSilentMarker[1];
|
||||
PROTOBUF_EXPORT extern const char kDebugStringSilentMarkerForDetection[3];
|
||||
} // namespace internal
|
||||
|
||||
namespace io {
|
||||
class ErrorCollector; // tokenizer.h
|
||||
}
|
||||
|
||||
// This class implements protocol buffer text format, colloquially known as text
|
||||
// proto. Printing and parsing protocol messages in text format is useful for
|
||||
// debugging and human editing of messages.
|
||||
//
|
||||
// This class is really a namespace that contains only static methods.
|
||||
class PROTOBUF_EXPORT TextFormat {
|
||||
public:
|
||||
// Outputs a textual representation of the given message to the given
|
||||
// output stream. Returns false if printing fails.
|
||||
static bool Print(const Message& message, io::ZeroCopyOutputStream* output);
|
||||
|
||||
// Print the fields in an UnknownFieldSet. They are printed by tag number
|
||||
// only. Embedded messages are heuristically identified by attempting to
|
||||
// parse them. Returns false if printing fails.
|
||||
static bool PrintUnknownFields(const UnknownFieldSet& unknown_fields,
|
||||
io::ZeroCopyOutputStream* output);
|
||||
|
||||
// Like Print(), but outputs directly to a string.
|
||||
// Note: output will be cleared prior to printing, and will be left empty
|
||||
// even if printing fails. Returns false if printing fails.
|
||||
static bool PrintToString(const Message& message, std::string* output);
|
||||
|
||||
// Like PrintUnknownFields(), but outputs directly to a string. Returns
|
||||
// false if printing fails.
|
||||
static bool PrintUnknownFieldsToString(const UnknownFieldSet& unknown_fields,
|
||||
std::string* output);
|
||||
|
||||
// Outputs a textual representation of the value of the field supplied on
|
||||
// the message supplied. For non-repeated fields, an index of -1 must
|
||||
// be supplied. Note that this method will print the default value for a
|
||||
// field if it is not set.
|
||||
static void PrintFieldValueToString(const Message& message,
|
||||
const FieldDescriptor* field, int index,
|
||||
std::string* output);
|
||||
|
||||
class PROTOBUF_EXPORT BaseTextGenerator {
|
||||
public:
|
||||
virtual ~BaseTextGenerator();
|
||||
|
||||
virtual void Indent() {}
|
||||
virtual void Outdent() {}
|
||||
// Returns the current indentation size in characters.
|
||||
virtual size_t GetCurrentIndentationSize() const { return 0; }
|
||||
|
||||
// Print text to the output stream.
|
||||
virtual void Print(const char* text, size_t size) = 0;
|
||||
|
||||
void PrintString(const std::string& str) { Print(str.data(), str.size()); }
|
||||
|
||||
template <size_t n>
|
||||
void PrintLiteral(const char (&text)[n]) {
|
||||
Print(text, n - 1); // n includes the terminating zero character.
|
||||
}
|
||||
};
|
||||
|
||||
// The default printer that converts scalar values from fields into their
|
||||
// string representation.
|
||||
// You can derive from this FastFieldValuePrinter if you want to have fields
|
||||
// to be printed in a different way and register it at the Printer.
|
||||
class PROTOBUF_EXPORT FastFieldValuePrinter {
|
||||
public:
|
||||
FastFieldValuePrinter();
|
||||
virtual ~FastFieldValuePrinter();
|
||||
virtual void PrintBool(bool val, BaseTextGenerator* generator) const;
|
||||
virtual void PrintInt32(int32_t val, BaseTextGenerator* generator) const;
|
||||
virtual void PrintUInt32(uint32_t val, BaseTextGenerator* generator) const;
|
||||
virtual void PrintInt64(int64_t val, BaseTextGenerator* generator) const;
|
||||
virtual void PrintUInt64(uint64_t val, BaseTextGenerator* generator) const;
|
||||
virtual void PrintFloat(float val, BaseTextGenerator* generator) const;
|
||||
virtual void PrintDouble(double val, BaseTextGenerator* generator) const;
|
||||
virtual void PrintString(const std::string& val,
|
||||
BaseTextGenerator* generator) const;
|
||||
virtual void PrintBytes(const std::string& val,
|
||||
BaseTextGenerator* generator) const;
|
||||
virtual void PrintEnum(int32_t val, const std::string& name,
|
||||
BaseTextGenerator* generator) const;
|
||||
virtual void PrintFieldName(const Message& message, int field_index,
|
||||
int field_count, const Reflection* reflection,
|
||||
const FieldDescriptor* field,
|
||||
BaseTextGenerator* generator) const;
|
||||
virtual void PrintFieldName(const Message& message,
|
||||
const Reflection* reflection,
|
||||
const FieldDescriptor* field,
|
||||
BaseTextGenerator* generator) const;
|
||||
virtual void PrintMessageStart(const Message& message, int field_index,
|
||||
int field_count, bool single_line_mode,
|
||||
BaseTextGenerator* generator) const;
|
||||
// Allows to override the logic on how to print the content of a message.
|
||||
// Return false to use the default printing logic. Note that it is legal for
|
||||
// this function to print something and then return false to use the default
|
||||
// content printing (although at that point it would behave similarly to
|
||||
// PrintMessageStart).
|
||||
virtual bool PrintMessageContent(const Message& message, int field_index,
|
||||
int field_count, bool single_line_mode,
|
||||
BaseTextGenerator* generator) const;
|
||||
virtual void PrintMessageEnd(const Message& message, int field_index,
|
||||
int field_count, bool single_line_mode,
|
||||
BaseTextGenerator* generator) const;
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FastFieldValuePrinter);
|
||||
};
|
||||
|
||||
// Deprecated: please use FastFieldValuePrinter instead.
|
||||
class PROTOBUF_EXPORT FieldValuePrinter {
|
||||
public:
|
||||
FieldValuePrinter();
|
||||
virtual ~FieldValuePrinter();
|
||||
virtual std::string PrintBool(bool val) const;
|
||||
virtual std::string PrintInt32(int32_t val) const;
|
||||
virtual std::string PrintUInt32(uint32_t val) const;
|
||||
virtual std::string PrintInt64(int64_t val) const;
|
||||
virtual std::string PrintUInt64(uint64_t val) const;
|
||||
virtual std::string PrintFloat(float val) const;
|
||||
virtual std::string PrintDouble(double val) const;
|
||||
virtual std::string PrintString(const std::string& val) const;
|
||||
virtual std::string PrintBytes(const std::string& val) const;
|
||||
virtual std::string PrintEnum(int32_t val, const std::string& name) const;
|
||||
virtual std::string PrintFieldName(const Message& message,
|
||||
const Reflection* reflection,
|
||||
const FieldDescriptor* field) const;
|
||||
virtual std::string PrintMessageStart(const Message& message,
|
||||
int field_index, int field_count,
|
||||
bool single_line_mode) const;
|
||||
virtual std::string PrintMessageEnd(const Message& message, int field_index,
|
||||
int field_count,
|
||||
bool single_line_mode) const;
|
||||
|
||||
private:
|
||||
FastFieldValuePrinter delegate_;
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldValuePrinter);
|
||||
};
|
||||
|
||||
class PROTOBUF_EXPORT MessagePrinter {
|
||||
public:
|
||||
MessagePrinter() {}
|
||||
virtual ~MessagePrinter() {}
|
||||
virtual void Print(const Message& message, bool single_line_mode,
|
||||
BaseTextGenerator* generator) const = 0;
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessagePrinter);
|
||||
};
|
||||
|
||||
// Interface that Printers or Parsers can use to find extensions, or types
|
||||
// referenced in Any messages.
|
||||
class PROTOBUF_EXPORT Finder {
|
||||
public:
|
||||
virtual ~Finder();
|
||||
|
||||
// Try to find an extension of *message by fully-qualified field
|
||||
// name. Returns nullptr if no extension is known for this name or number.
|
||||
// The base implementation uses the extensions already known by the message.
|
||||
virtual const FieldDescriptor* FindExtension(Message* message,
|
||||
const std::string& name) const;
|
||||
|
||||
// Similar to FindExtension, but uses a Descriptor and the extension number
|
||||
// instead of using a Message and the name when doing the look up.
|
||||
virtual const FieldDescriptor* FindExtensionByNumber(
|
||||
const Descriptor* descriptor, int number) const;
|
||||
|
||||
// Find the message type for an Any proto.
|
||||
// Returns nullptr if no message is known for this name.
|
||||
// The base implementation only accepts prefixes of type.googleprod.com/ or
|
||||
// type.googleapis.com/, and searches the DescriptorPool of the parent
|
||||
// message.
|
||||
virtual const Descriptor* FindAnyType(const Message& message,
|
||||
const std::string& prefix,
|
||||
const std::string& name) const;
|
||||
|
||||
// Find the message factory for the given extension field. This can be used
|
||||
// to generalize the Parser to add extension fields to a message in the same
|
||||
// way as the "input" message for the Parser.
|
||||
virtual MessageFactory* FindExtensionFactory(
|
||||
const FieldDescriptor* field) const;
|
||||
};
|
||||
|
||||
// Class for those users which require more fine-grained control over how
|
||||
// a protobuffer message is printed out.
|
||||
class PROTOBUF_EXPORT Printer {
|
||||
public:
|
||||
Printer();
|
||||
|
||||
// Like TextFormat::Print
|
||||
bool Print(const Message& message, io::ZeroCopyOutputStream* output) const;
|
||||
// Like TextFormat::PrintUnknownFields
|
||||
bool PrintUnknownFields(const UnknownFieldSet& unknown_fields,
|
||||
io::ZeroCopyOutputStream* output) const;
|
||||
// Like TextFormat::PrintToString
|
||||
bool PrintToString(const Message& message, std::string* output) const;
|
||||
// Like TextFormat::PrintUnknownFieldsToString
|
||||
bool PrintUnknownFieldsToString(const UnknownFieldSet& unknown_fields,
|
||||
std::string* output) const;
|
||||
// Like TextFormat::PrintFieldValueToString
|
||||
void PrintFieldValueToString(const Message& message,
|
||||
const FieldDescriptor* field, int index,
|
||||
std::string* output) const;
|
||||
|
||||
// Adjust the initial indent level of all output. Each indent level is
|
||||
// equal to two spaces.
|
||||
void SetInitialIndentLevel(int indent_level) {
|
||||
initial_indent_level_ = indent_level;
|
||||
}
|
||||
|
||||
// If printing in single line mode, then the entire message will be output
|
||||
// on a single line with no line breaks.
|
||||
void SetSingleLineMode(bool single_line_mode) {
|
||||
single_line_mode_ = single_line_mode;
|
||||
}
|
||||
|
||||
bool IsInSingleLineMode() const { return single_line_mode_; }
|
||||
|
||||
// If use_field_number is true, uses field number instead of field name.
|
||||
void SetUseFieldNumber(bool use_field_number) {
|
||||
use_field_number_ = use_field_number;
|
||||
}
|
||||
|
||||
// Set true to print repeated primitives in a format like:
|
||||
// field_name: [1, 2, 3, 4]
|
||||
// instead of printing each value on its own line. Short format applies
|
||||
// only to primitive values -- i.e. everything except strings and
|
||||
// sub-messages/groups.
|
||||
void SetUseShortRepeatedPrimitives(bool use_short_repeated_primitives) {
|
||||
use_short_repeated_primitives_ = use_short_repeated_primitives;
|
||||
}
|
||||
|
||||
// Set true to output UTF-8 instead of ASCII. The only difference
|
||||
// is that bytes >= 0x80 in string fields will not be escaped,
|
||||
// because they are assumed to be part of UTF-8 multi-byte
|
||||
// sequences. This will change the default FastFieldValuePrinter.
|
||||
void SetUseUtf8StringEscaping(bool as_utf8);
|
||||
|
||||
// Set the default FastFieldValuePrinter that is used for all fields that
|
||||
// don't have a field-specific printer registered.
|
||||
// Takes ownership of the printer.
|
||||
void SetDefaultFieldValuePrinter(const FastFieldValuePrinter* printer);
|
||||
|
||||
PROTOBUF_DEPRECATED_MSG("Please use FastFieldValuePrinter")
|
||||
void SetDefaultFieldValuePrinter(const FieldValuePrinter* printer);
|
||||
|
||||
// Sets whether we want to hide unknown fields or not.
|
||||
// Usually unknown fields are printed in a generic way that includes the
|
||||
// tag number of the field instead of field name. However, sometimes it
|
||||
// is useful to be able to print the message without unknown fields (e.g.
|
||||
// for the python protobuf version to maintain consistency between its pure
|
||||
// python and c++ implementations).
|
||||
void SetHideUnknownFields(bool hide) { hide_unknown_fields_ = hide; }
|
||||
|
||||
// If print_message_fields_in_index_order is true, fields of a proto message
|
||||
// will be printed using the order defined in source code instead of the
|
||||
// field number, extensions will be printed at the end of the message
|
||||
// and their relative order is determined by the extension number.
|
||||
// By default, use the field number order.
|
||||
void SetPrintMessageFieldsInIndexOrder(
|
||||
bool print_message_fields_in_index_order) {
|
||||
print_message_fields_in_index_order_ =
|
||||
print_message_fields_in_index_order;
|
||||
}
|
||||
|
||||
// If expand==true, expand google.protobuf.Any payloads. The output
|
||||
// will be of form
|
||||
// [type_url] { <value_printed_in_text> }
|
||||
//
|
||||
// If expand==false, print Any using the default printer. The output will
|
||||
// look like
|
||||
// type_url: "<type_url>" value: "serialized_content"
|
||||
void SetExpandAny(bool expand) { expand_any_ = expand; }
|
||||
|
||||
// Set how parser finds message for Any payloads.
|
||||
void SetFinder(const Finder* finder) { finder_ = finder; }
|
||||
|
||||
// If non-zero, we truncate all string fields that are longer than
|
||||
// this threshold. This is useful when the proto message has very long
|
||||
// strings, e.g., dump of encoded image file.
|
||||
//
|
||||
// NOTE(hfgong): Setting a non-zero value breaks round-trip safe
|
||||
// property of TextFormat::Printer. That is, from the printed message, we
|
||||
// cannot fully recover the original string field any more.
|
||||
void SetTruncateStringFieldLongerThan(
|
||||
const int64_t truncate_string_field_longer_than) {
|
||||
truncate_string_field_longer_than_ = truncate_string_field_longer_than;
|
||||
}
|
||||
|
||||
// Register a custom field-specific FastFieldValuePrinter for fields
|
||||
// with a particular FieldDescriptor.
|
||||
// Returns "true" if the registration succeeded, or "false", if there is
|
||||
// already a printer for that FieldDescriptor.
|
||||
// Takes ownership of the printer on successful registration.
|
||||
bool RegisterFieldValuePrinter(const FieldDescriptor* field,
|
||||
const FastFieldValuePrinter* printer);
|
||||
|
||||
PROTOBUF_DEPRECATED_MSG("Please use FastFieldValuePrinter")
|
||||
bool RegisterFieldValuePrinter(const FieldDescriptor* field,
|
||||
const FieldValuePrinter* printer);
|
||||
|
||||
// Register a custom message-specific MessagePrinter for messages with a
|
||||
// particular Descriptor.
|
||||
// Returns "true" if the registration succeeded, or "false" if there is
|
||||
// already a printer for that Descriptor.
|
||||
bool RegisterMessagePrinter(const Descriptor* descriptor,
|
||||
const MessagePrinter* printer);
|
||||
|
||||
private:
|
||||
friend std::string Message::DebugString() const;
|
||||
friend std::string Message::ShortDebugString() const;
|
||||
friend std::string Message::Utf8DebugString() const;
|
||||
|
||||
// Sets whether *DebugString should insert a silent marker.
|
||||
void SetInsertSilentMarker(bool v) { insert_silent_marker_ = v; }
|
||||
|
||||
// Forward declaration of an internal class used to print the text
|
||||
// output to the OutputStream (see text_format.cc for implementation).
|
||||
class TextGenerator;
|
||||
|
||||
// Forward declaration of an internal class used to print field values for
|
||||
// DebugString APIs (see text_format.cc for implementation).
|
||||
class DebugStringFieldValuePrinter;
|
||||
|
||||
// Forward declaration of an internal class used to print UTF-8 escaped
|
||||
// strings (see text_format.cc for implementation).
|
||||
class FastFieldValuePrinterUtf8Escaping;
|
||||
|
||||
static const char* const kDoNotParse;
|
||||
|
||||
// Internal Print method, used for writing to the OutputStream via
|
||||
// the TextGenerator class.
|
||||
void Print(const Message& message, TextGenerator* generator) const;
|
||||
|
||||
// Print a single field.
|
||||
void PrintField(const Message& message, const Reflection* reflection,
|
||||
const FieldDescriptor* field,
|
||||
TextGenerator* generator) const;
|
||||
|
||||
// Print a repeated primitive field in short form.
|
||||
void PrintShortRepeatedField(const Message& message,
|
||||
const Reflection* reflection,
|
||||
const FieldDescriptor* field,
|
||||
TextGenerator* generator) const;
|
||||
|
||||
// Print the name of a field -- i.e. everything that comes before the
|
||||
// ':' for a single name/value pair.
|
||||
void PrintFieldName(const Message& message, int field_index,
|
||||
int field_count, const Reflection* reflection,
|
||||
const FieldDescriptor* field,
|
||||
TextGenerator* generator) const;
|
||||
|
||||
// Outputs a textual representation of the value of the field supplied on
|
||||
// the message supplied or the default value if not set.
|
||||
void PrintFieldValue(const Message& message, const Reflection* reflection,
|
||||
const FieldDescriptor* field, int index,
|
||||
TextGenerator* generator) const;
|
||||
|
||||
// Print the fields in an UnknownFieldSet. They are printed by tag number
|
||||
// only. Embedded messages are heuristically identified by attempting to
|
||||
// parse them (subject to the recursion budget).
|
||||
void PrintUnknownFields(const UnknownFieldSet& unknown_fields,
|
||||
TextGenerator* generator,
|
||||
int recursion_budget) const;
|
||||
|
||||
bool PrintAny(const Message& message, TextGenerator* generator) const;
|
||||
|
||||
const FastFieldValuePrinter* GetFieldPrinter(
|
||||
const FieldDescriptor* field) const {
|
||||
auto it = custom_printers_.find(field);
|
||||
return it == custom_printers_.end() ? default_field_value_printer_.get()
|
||||
: it->second.get();
|
||||
}
|
||||
|
||||
int initial_indent_level_;
|
||||
bool single_line_mode_;
|
||||
bool use_field_number_;
|
||||
bool use_short_repeated_primitives_;
|
||||
bool insert_silent_marker_;
|
||||
bool hide_unknown_fields_;
|
||||
bool print_message_fields_in_index_order_;
|
||||
bool expand_any_;
|
||||
int64_t truncate_string_field_longer_than_;
|
||||
|
||||
std::unique_ptr<const FastFieldValuePrinter> default_field_value_printer_;
|
||||
typedef std::map<const FieldDescriptor*,
|
||||
std::unique_ptr<const FastFieldValuePrinter>>
|
||||
CustomPrinterMap;
|
||||
CustomPrinterMap custom_printers_;
|
||||
|
||||
typedef std::map<const Descriptor*, std::unique_ptr<const MessagePrinter>>
|
||||
CustomMessagePrinterMap;
|
||||
CustomMessagePrinterMap custom_message_printers_;
|
||||
|
||||
const Finder* finder_;
|
||||
};
|
||||
|
||||
// Parses a text-format protocol message from the given input stream to
|
||||
// the given message object. This function parses the human-readable
|
||||
// serialization format written by Print(). Returns true on success. The
|
||||
// message is cleared first, even if the function fails -- See Merge() to
|
||||
// avoid this behavior.
|
||||
//
|
||||
// Example input: "user {\n id: 123 extra { gender: MALE language: 'en' }\n}"
|
||||
//
|
||||
// One common use for this function is parsing handwritten strings in test
|
||||
// code.
|
||||
//
|
||||
// If you would like to read a protocol buffer serialized in the
|
||||
// (non-human-readable) binary wire format, see
|
||||
// google::protobuf::MessageLite::ParseFromString().
|
||||
static bool Parse(io::ZeroCopyInputStream* input, Message* output);
|
||||
// Like Parse(), but reads directly from a string.
|
||||
static bool ParseFromString(ConstStringParam input, Message* output);
|
||||
|
||||
// Like Parse(), but the data is merged into the given message, as if
|
||||
// using Message::MergeFrom().
|
||||
static bool Merge(io::ZeroCopyInputStream* input, Message* output);
|
||||
// Like Merge(), but reads directly from a string.
|
||||
static bool MergeFromString(ConstStringParam input, Message* output);
|
||||
|
||||
// Parse the given text as a single field value and store it into the
|
||||
// given field of the given message. If the field is a repeated field,
|
||||
// the new value will be added to the end
|
||||
static bool ParseFieldValueFromString(const std::string& input,
|
||||
const FieldDescriptor* field,
|
||||
Message* message);
|
||||
|
||||
// A location in the parsed text.
|
||||
struct ParseLocation {
|
||||
int line;
|
||||
int column;
|
||||
|
||||
ParseLocation() : line(-1), column(-1) {}
|
||||
ParseLocation(int line_param, int column_param)
|
||||
: line(line_param), column(column_param) {}
|
||||
};
|
||||
|
||||
// A range of locations in the parsed text, including `start` and excluding
|
||||
// `end`.
|
||||
struct ParseLocationRange {
|
||||
ParseLocation start;
|
||||
ParseLocation end;
|
||||
ParseLocationRange() : start(), end() {}
|
||||
ParseLocationRange(ParseLocation start_param, ParseLocation end_param)
|
||||
: start(start_param), end(end_param) {}
|
||||
};
|
||||
|
||||
// Data structure which is populated with the locations of each field
|
||||
// value parsed from the text.
|
||||
class PROTOBUF_EXPORT ParseInfoTree {
|
||||
public:
|
||||
ParseInfoTree() = default;
|
||||
ParseInfoTree(const ParseInfoTree&) = delete;
|
||||
ParseInfoTree& operator=(const ParseInfoTree&) = delete;
|
||||
|
||||
// Returns the parse location range for index-th value of the field in
|
||||
// the parsed text. If none exists, returns a location with start and end
|
||||
// line -1. Index should be -1 for not-repeated fields.
|
||||
ParseLocationRange GetLocationRange(const FieldDescriptor* field,
|
||||
int index) const;
|
||||
|
||||
// Returns the starting parse location for index-th value of the field in
|
||||
// the parsed text. If none exists, returns a location with line = -1. Index
|
||||
// should be -1 for not-repeated fields.
|
||||
ParseLocation GetLocation(const FieldDescriptor* field, int index) const {
|
||||
return GetLocationRange(field, index).start;
|
||||
}
|
||||
|
||||
// Returns the parse info tree for the given field, which must be a message
|
||||
// type. The nested information tree is owned by the root tree and will be
|
||||
// deleted when it is deleted.
|
||||
ParseInfoTree* GetTreeForNested(const FieldDescriptor* field,
|
||||
int index) const;
|
||||
|
||||
private:
|
||||
// Allow the text format parser to record information into the tree.
|
||||
friend class TextFormat;
|
||||
|
||||
// Records the starting and ending locations of a single value for a field.
|
||||
void RecordLocation(const FieldDescriptor* field, ParseLocationRange range);
|
||||
|
||||
// Create and records a nested tree for a nested message field.
|
||||
ParseInfoTree* CreateNested(const FieldDescriptor* field);
|
||||
|
||||
// Defines the map from the index-th field descriptor to its parse location.
|
||||
typedef std::map<const FieldDescriptor*, std::vector<ParseLocationRange>>
|
||||
LocationMap;
|
||||
|
||||
// Defines the map from the index-th field descriptor to the nested parse
|
||||
// info tree.
|
||||
typedef std::map<const FieldDescriptor*,
|
||||
std::vector<std::unique_ptr<ParseInfoTree>>>
|
||||
NestedMap;
|
||||
|
||||
LocationMap locations_;
|
||||
NestedMap nested_;
|
||||
};
|
||||
|
||||
// For more control over parsing, use this class.
|
||||
class PROTOBUF_EXPORT Parser {
|
||||
public:
|
||||
Parser();
|
||||
~Parser();
|
||||
|
||||
// Like TextFormat::Parse().
|
||||
bool Parse(io::ZeroCopyInputStream* input, Message* output);
|
||||
// Like TextFormat::ParseFromString().
|
||||
bool ParseFromString(ConstStringParam input, Message* output);
|
||||
// Like TextFormat::Merge().
|
||||
bool Merge(io::ZeroCopyInputStream* input, Message* output);
|
||||
// Like TextFormat::MergeFromString().
|
||||
bool MergeFromString(ConstStringParam input, Message* output);
|
||||
|
||||
// Set where to report parse errors. If nullptr (the default), errors will
|
||||
// be printed to stderr.
|
||||
void RecordErrorsTo(io::ErrorCollector* error_collector) {
|
||||
error_collector_ = error_collector;
|
||||
}
|
||||
|
||||
// Set how parser finds extensions. If nullptr (the default), the
|
||||
// parser will use the standard Reflection object associated with
|
||||
// the message being parsed.
|
||||
void SetFinder(const Finder* finder) { finder_ = finder; }
|
||||
|
||||
// Sets where location information about the parse will be written. If
|
||||
// nullptr
|
||||
// (the default), then no location will be written.
|
||||
void WriteLocationsTo(ParseInfoTree* tree) { parse_info_tree_ = tree; }
|
||||
|
||||
// Normally parsing fails if, after parsing, output->IsInitialized()
|
||||
// returns false. Call AllowPartialMessage(true) to skip this check.
|
||||
void AllowPartialMessage(bool allow) { allow_partial_ = allow; }
|
||||
|
||||
// Allow field names to be matched case-insensitively.
|
||||
// This is not advisable if there are fields that only differ in case, or
|
||||
// if you want to enforce writing in the canonical form.
|
||||
// This is 'false' by default.
|
||||
void AllowCaseInsensitiveField(bool allow) {
|
||||
allow_case_insensitive_field_ = allow;
|
||||
}
|
||||
|
||||
// Like TextFormat::ParseFieldValueFromString
|
||||
bool ParseFieldValueFromString(const std::string& input,
|
||||
const FieldDescriptor* field,
|
||||
Message* output);
|
||||
|
||||
// When an unknown extension is met, parsing will fail if this option is
|
||||
// set to false (the default). If true, unknown extensions will be ignored
|
||||
// and a warning message will be generated.
|
||||
// Beware! Setting this option true may hide some errors (e.g. spelling
|
||||
// error on extension name). This allows data loss; unlike binary format,
|
||||
// text format cannot preserve unknown extensions. Avoid using this option
|
||||
// if possible.
|
||||
void AllowUnknownExtension(bool allow) { allow_unknown_extension_ = allow; }
|
||||
|
||||
// When an unknown field is met, parsing will fail if this option is set
|
||||
// to false (the default). If true, unknown fields will be ignored and
|
||||
// a warning message will be generated.
|
||||
// Beware! Setting this option true may hide some errors (e.g. spelling
|
||||
// error on field name). This allows data loss; unlike binary format, text
|
||||
// format cannot preserve unknown fields. Avoid using this option
|
||||
// if possible.
|
||||
void AllowUnknownField(bool allow) { allow_unknown_field_ = allow; }
|
||||
|
||||
|
||||
void AllowFieldNumber(bool allow) { allow_field_number_ = allow; }
|
||||
|
||||
// Sets maximum recursion depth which parser can use. This is effectively
|
||||
// the maximum allowed nesting of proto messages.
|
||||
void SetRecursionLimit(int limit) { recursion_limit_ = limit; }
|
||||
|
||||
private:
|
||||
// Forward declaration of an internal class used to parse text
|
||||
// representations (see text_format.cc for implementation).
|
||||
class ParserImpl;
|
||||
|
||||
// Like TextFormat::Merge(). The provided implementation is used
|
||||
// to do the parsing.
|
||||
bool MergeUsingImpl(io::ZeroCopyInputStream* input, Message* output,
|
||||
ParserImpl* parser_impl);
|
||||
|
||||
io::ErrorCollector* error_collector_;
|
||||
const Finder* finder_;
|
||||
ParseInfoTree* parse_info_tree_;
|
||||
bool allow_partial_;
|
||||
bool allow_case_insensitive_field_;
|
||||
bool allow_unknown_field_;
|
||||
bool allow_unknown_extension_;
|
||||
bool allow_unknown_enum_;
|
||||
bool allow_field_number_;
|
||||
bool allow_relaxed_whitespace_;
|
||||
bool allow_singular_overwrites_;
|
||||
int recursion_limit_;
|
||||
};
|
||||
|
||||
|
||||
private:
|
||||
// Hack: ParseInfoTree declares TextFormat as a friend which should extend
|
||||
// the friendship to TextFormat::Parser::ParserImpl, but unfortunately some
|
||||
// old compilers (e.g. GCC 3.4.6) don't implement this correctly. We provide
|
||||
// helpers for ParserImpl to call methods of ParseInfoTree.
|
||||
static inline void RecordLocation(ParseInfoTree* info_tree,
|
||||
const FieldDescriptor* field,
|
||||
ParseLocationRange location);
|
||||
static inline ParseInfoTree* CreateNested(ParseInfoTree* info_tree,
|
||||
const FieldDescriptor* field);
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TextFormat);
|
||||
};
|
||||
|
||||
inline void TextFormat::RecordLocation(ParseInfoTree* info_tree,
|
||||
const FieldDescriptor* field,
|
||||
ParseLocationRange location) {
|
||||
info_tree->RecordLocation(field, location);
|
||||
}
|
||||
|
||||
inline TextFormat::ParseInfoTree* TextFormat::CreateNested(
|
||||
ParseInfoTree* info_tree, const FieldDescriptor* field) {
|
||||
return info_tree->CreateNested(field);
|
||||
}
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_TEXT_FORMAT_H__
|
||||
@@ -1,278 +0,0 @@
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: google/protobuf/timestamp.proto
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2ftimestamp_2eproto
|
||||
#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2ftimestamp_2eproto
|
||||
|
||||
#include <limits>
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/port_def.inc>
|
||||
#if PROTOBUF_VERSION < 3021000
|
||||
#error This file was generated by a newer version of protoc which is
|
||||
#error incompatible with your Protocol Buffer headers. Please update
|
||||
#error your headers.
|
||||
#endif
|
||||
#if 3021012 < PROTOBUF_MIN_PROTOC_VERSION
|
||||
#error This file was generated by an older version of protoc which is
|
||||
#error incompatible with your Protocol Buffer headers. Please
|
||||
#error regenerate this file with a newer version of protoc.
|
||||
#endif
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/arena.h>
|
||||
#include <google/protobuf/arenastring.h>
|
||||
#include <google/protobuf/generated_message_util.h>
|
||||
#include <google/protobuf/metadata_lite.h>
|
||||
#include <google/protobuf/generated_message_reflection.h>
|
||||
#include <google/protobuf/message.h>
|
||||
#include <google/protobuf/repeated_field.h> // IWYU pragma: export
|
||||
#include <google/protobuf/extension_set.h> // IWYU pragma: export
|
||||
#include <google/protobuf/unknown_field_set.h>
|
||||
// @@protoc_insertion_point(includes)
|
||||
#include <google/protobuf/port_def.inc>
|
||||
#define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2ftimestamp_2eproto PROTOBUF_EXPORT
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
namespace internal {
|
||||
class AnyMetadata;
|
||||
} // namespace internal
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
|
||||
// Internal implementation detail -- do not use these members.
|
||||
struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2ftimestamp_2eproto {
|
||||
static const uint32_t offsets[];
|
||||
};
|
||||
PROTOBUF_EXPORT extern const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2ftimestamp_2eproto;
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
class Timestamp;
|
||||
struct TimestampDefaultTypeInternal;
|
||||
PROTOBUF_EXPORT extern TimestampDefaultTypeInternal _Timestamp_default_instance_;
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Timestamp* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Timestamp>(Arena*);
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
|
||||
// ===================================================================
|
||||
|
||||
class PROTOBUF_EXPORT Timestamp final :
|
||||
public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Timestamp) */ {
|
||||
public:
|
||||
inline Timestamp() : Timestamp(nullptr) {}
|
||||
~Timestamp() override;
|
||||
explicit PROTOBUF_CONSTEXPR Timestamp(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
|
||||
|
||||
Timestamp(const Timestamp& from);
|
||||
Timestamp(Timestamp&& from) noexcept
|
||||
: Timestamp() {
|
||||
*this = ::std::move(from);
|
||||
}
|
||||
|
||||
inline Timestamp& operator=(const Timestamp& from) {
|
||||
CopyFrom(from);
|
||||
return *this;
|
||||
}
|
||||
inline Timestamp& operator=(Timestamp&& from) noexcept {
|
||||
if (this == &from) return *this;
|
||||
if (GetOwningArena() == from.GetOwningArena()
|
||||
#ifdef PROTOBUF_FORCE_COPY_IN_MOVE
|
||||
&& GetOwningArena() != nullptr
|
||||
#endif // !PROTOBUF_FORCE_COPY_IN_MOVE
|
||||
) {
|
||||
InternalSwap(&from);
|
||||
} else {
|
||||
CopyFrom(from);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() {
|
||||
return GetDescriptor();
|
||||
}
|
||||
static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
|
||||
return default_instance().GetMetadata().descriptor;
|
||||
}
|
||||
static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
|
||||
return default_instance().GetMetadata().reflection;
|
||||
}
|
||||
static const Timestamp& default_instance() {
|
||||
return *internal_default_instance();
|
||||
}
|
||||
static inline const Timestamp* internal_default_instance() {
|
||||
return reinterpret_cast<const Timestamp*>(
|
||||
&_Timestamp_default_instance_);
|
||||
}
|
||||
static constexpr int kIndexInFileMessages =
|
||||
0;
|
||||
|
||||
friend void swap(Timestamp& a, Timestamp& b) {
|
||||
a.Swap(&b);
|
||||
}
|
||||
inline void Swap(Timestamp* other) {
|
||||
if (other == this) return;
|
||||
#ifdef PROTOBUF_FORCE_COPY_IN_SWAP
|
||||
if (GetOwningArena() != nullptr &&
|
||||
GetOwningArena() == other->GetOwningArena()) {
|
||||
#else // PROTOBUF_FORCE_COPY_IN_SWAP
|
||||
if (GetOwningArena() == other->GetOwningArena()) {
|
||||
#endif // !PROTOBUF_FORCE_COPY_IN_SWAP
|
||||
InternalSwap(other);
|
||||
} else {
|
||||
::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
|
||||
}
|
||||
}
|
||||
void UnsafeArenaSwap(Timestamp* other) {
|
||||
if (other == this) return;
|
||||
GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
|
||||
InternalSwap(other);
|
||||
}
|
||||
|
||||
// implements Message ----------------------------------------------
|
||||
|
||||
Timestamp* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final {
|
||||
return CreateMaybeMessage<Timestamp>(arena);
|
||||
}
|
||||
using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
|
||||
void CopyFrom(const Timestamp& from);
|
||||
using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
|
||||
void MergeFrom( const Timestamp& from) {
|
||||
Timestamp::MergeImpl(*this, from);
|
||||
}
|
||||
private:
|
||||
static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg);
|
||||
public:
|
||||
PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
|
||||
bool IsInitialized() const final;
|
||||
|
||||
size_t ByteSizeLong() const final;
|
||||
const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
|
||||
uint8_t* _InternalSerialize(
|
||||
uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
|
||||
int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
|
||||
|
||||
private:
|
||||
void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned);
|
||||
void SharedDtor();
|
||||
void SetCachedSize(int size) const final;
|
||||
void InternalSwap(Timestamp* other);
|
||||
|
||||
private:
|
||||
friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
|
||||
static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
|
||||
return "google.protobuf.Timestamp";
|
||||
}
|
||||
protected:
|
||||
explicit Timestamp(::PROTOBUF_NAMESPACE_ID::Arena* arena,
|
||||
bool is_message_owned = false);
|
||||
public:
|
||||
|
||||
static const ClassData _class_data_;
|
||||
const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
|
||||
|
||||
::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
|
||||
|
||||
// nested types ----------------------------------------------------
|
||||
|
||||
// accessors -------------------------------------------------------
|
||||
|
||||
enum : int {
|
||||
kSecondsFieldNumber = 1,
|
||||
kNanosFieldNumber = 2,
|
||||
};
|
||||
// int64 seconds = 1;
|
||||
void clear_seconds();
|
||||
int64_t seconds() const;
|
||||
void set_seconds(int64_t value);
|
||||
private:
|
||||
int64_t _internal_seconds() const;
|
||||
void _internal_set_seconds(int64_t value);
|
||||
public:
|
||||
|
||||
// int32 nanos = 2;
|
||||
void clear_nanos();
|
||||
int32_t nanos() const;
|
||||
void set_nanos(int32_t value);
|
||||
private:
|
||||
int32_t _internal_nanos() const;
|
||||
void _internal_set_nanos(int32_t value);
|
||||
public:
|
||||
|
||||
// @@protoc_insertion_point(class_scope:google.protobuf.Timestamp)
|
||||
private:
|
||||
class _Internal;
|
||||
|
||||
template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper;
|
||||
typedef void InternalArenaConstructable_;
|
||||
typedef void DestructorSkippable_;
|
||||
struct Impl_ {
|
||||
int64_t seconds_;
|
||||
int32_t nanos_;
|
||||
mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
|
||||
};
|
||||
union { Impl_ _impl_; };
|
||||
friend struct ::TableStruct_google_2fprotobuf_2ftimestamp_2eproto;
|
||||
};
|
||||
// ===================================================================
|
||||
|
||||
|
||||
// ===================================================================
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
|
||||
#endif // __GNUC__
|
||||
// Timestamp
|
||||
|
||||
// int64 seconds = 1;
|
||||
inline void Timestamp::clear_seconds() {
|
||||
_impl_.seconds_ = int64_t{0};
|
||||
}
|
||||
inline int64_t Timestamp::_internal_seconds() const {
|
||||
return _impl_.seconds_;
|
||||
}
|
||||
inline int64_t Timestamp::seconds() const {
|
||||
// @@protoc_insertion_point(field_get:google.protobuf.Timestamp.seconds)
|
||||
return _internal_seconds();
|
||||
}
|
||||
inline void Timestamp::_internal_set_seconds(int64_t value) {
|
||||
|
||||
_impl_.seconds_ = value;
|
||||
}
|
||||
inline void Timestamp::set_seconds(int64_t value) {
|
||||
_internal_set_seconds(value);
|
||||
// @@protoc_insertion_point(field_set:google.protobuf.Timestamp.seconds)
|
||||
}
|
||||
|
||||
// int32 nanos = 2;
|
||||
inline void Timestamp::clear_nanos() {
|
||||
_impl_.nanos_ = 0;
|
||||
}
|
||||
inline int32_t Timestamp::_internal_nanos() const {
|
||||
return _impl_.nanos_;
|
||||
}
|
||||
inline int32_t Timestamp::nanos() const {
|
||||
// @@protoc_insertion_point(field_get:google.protobuf.Timestamp.nanos)
|
||||
return _internal_nanos();
|
||||
}
|
||||
inline void Timestamp::_internal_set_nanos(int32_t value) {
|
||||
|
||||
_impl_.nanos_ = value;
|
||||
}
|
||||
inline void Timestamp::set_nanos(int32_t value) {
|
||||
_internal_set_nanos(value);
|
||||
// @@protoc_insertion_point(field_set:google.protobuf.Timestamp.nanos)
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif // __GNUC__
|
||||
|
||||
// @@protoc_insertion_point(namespace_scope)
|
||||
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
|
||||
// @@protoc_insertion_point(global_scope)
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
#endif // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2ftimestamp_2eproto
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,407 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
//
|
||||
// Contains classes used to keep track of unrecognized fields seen while
|
||||
// parsing a protocol message.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_UNKNOWN_FIELD_SET_H__
|
||||
#define GOOGLE_PROTOBUF_UNKNOWN_FIELD_SET_H__
|
||||
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/logging.h>
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
|
||||
#include <google/protobuf/port.h>
|
||||
#include <google/protobuf/message_lite.h>
|
||||
#include <google/protobuf/parse_context.h>
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
#ifdef SWIG
|
||||
#error "You cannot SWIG proto headers"
|
||||
#endif
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
class InternalMetadata; // metadata_lite.h
|
||||
class WireFormat; // wire_format.h
|
||||
class MessageSetFieldSkipperUsingCord;
|
||||
// extension_set_heavy.cc
|
||||
} // namespace internal
|
||||
|
||||
class Message; // message.h
|
||||
class UnknownField; // below
|
||||
|
||||
// An UnknownFieldSet contains fields that were encountered while parsing a
|
||||
// message but were not defined by its type. Keeping track of these can be
|
||||
// useful, especially in that they may be written if the message is serialized
|
||||
// again without being cleared in between. This means that software which
|
||||
// simply receives messages and forwards them to other servers does not need
|
||||
// to be updated every time a new field is added to the message definition.
|
||||
//
|
||||
// To get the UnknownFieldSet attached to any message, call
|
||||
// Reflection::GetUnknownFields().
|
||||
//
|
||||
// This class is necessarily tied to the protocol buffer wire format, unlike
|
||||
// the Reflection interface which is independent of any serialization scheme.
|
||||
class PROTOBUF_EXPORT UnknownFieldSet {
|
||||
public:
|
||||
UnknownFieldSet();
|
||||
~UnknownFieldSet();
|
||||
|
||||
// Remove all fields.
|
||||
inline void Clear();
|
||||
|
||||
// Remove all fields and deallocate internal data objects
|
||||
void ClearAndFreeMemory();
|
||||
|
||||
// Is this set empty?
|
||||
inline bool empty() const;
|
||||
|
||||
// Merge the contents of some other UnknownFieldSet with this one.
|
||||
void MergeFrom(const UnknownFieldSet& other);
|
||||
|
||||
// Similar to above, but this function will destroy the contents of other.
|
||||
void MergeFromAndDestroy(UnknownFieldSet* other);
|
||||
|
||||
// Merge the contents an UnknownFieldSet with the UnknownFieldSet in
|
||||
// *metadata, if there is one. If *metadata doesn't have an UnknownFieldSet
|
||||
// then add one to it and make it be a copy of the first arg.
|
||||
static void MergeToInternalMetadata(const UnknownFieldSet& other,
|
||||
internal::InternalMetadata* metadata);
|
||||
|
||||
// Swaps the contents of some other UnknownFieldSet with this one.
|
||||
inline void Swap(UnknownFieldSet* x);
|
||||
|
||||
// Computes (an estimate of) the total number of bytes currently used for
|
||||
// storing the unknown fields in memory. Does NOT include
|
||||
// sizeof(*this) in the calculation.
|
||||
size_t SpaceUsedExcludingSelfLong() const;
|
||||
|
||||
int SpaceUsedExcludingSelf() const {
|
||||
return internal::ToIntSize(SpaceUsedExcludingSelfLong());
|
||||
}
|
||||
|
||||
// Version of SpaceUsed() including sizeof(*this).
|
||||
size_t SpaceUsedLong() const;
|
||||
|
||||
int SpaceUsed() const { return internal::ToIntSize(SpaceUsedLong()); }
|
||||
|
||||
// Returns the number of fields present in the UnknownFieldSet.
|
||||
inline int field_count() const;
|
||||
// Get a field in the set, where 0 <= index < field_count(). The fields
|
||||
// appear in the order in which they were added.
|
||||
inline const UnknownField& field(int index) const;
|
||||
// Get a mutable pointer to a field in the set, where
|
||||
// 0 <= index < field_count(). The fields appear in the order in which
|
||||
// they were added.
|
||||
inline UnknownField* mutable_field(int index);
|
||||
|
||||
// Adding fields ---------------------------------------------------
|
||||
|
||||
void AddVarint(int number, uint64_t value);
|
||||
void AddFixed32(int number, uint32_t value);
|
||||
void AddFixed64(int number, uint64_t value);
|
||||
void AddLengthDelimited(int number, const std::string& value);
|
||||
std::string* AddLengthDelimited(int number);
|
||||
UnknownFieldSet* AddGroup(int number);
|
||||
|
||||
// Adds an unknown field from another set.
|
||||
void AddField(const UnknownField& field);
|
||||
|
||||
// Delete fields with indices in the range [start .. start+num-1].
|
||||
// Caution: implementation moves all fields with indices [start+num .. ].
|
||||
void DeleteSubrange(int start, int num);
|
||||
|
||||
// Delete all fields with a specific field number. The order of left fields
|
||||
// is preserved.
|
||||
// Caution: implementation moves all fields after the first deleted field.
|
||||
void DeleteByNumber(int number);
|
||||
|
||||
// Parsing helpers -------------------------------------------------
|
||||
// These work exactly like the similarly-named methods of Message.
|
||||
|
||||
bool MergeFromCodedStream(io::CodedInputStream* input);
|
||||
bool ParseFromCodedStream(io::CodedInputStream* input);
|
||||
bool ParseFromZeroCopyStream(io::ZeroCopyInputStream* input);
|
||||
bool ParseFromArray(const void* data, int size);
|
||||
inline bool ParseFromString(const std::string& data) {
|
||||
return ParseFromArray(data.data(), static_cast<int>(data.size()));
|
||||
}
|
||||
|
||||
// Merges this message's unknown field data (if any). This works whether
|
||||
// the message is a lite or full proto (for legacy reasons, lite and full
|
||||
// return different types for MessageType::unknown_fields()).
|
||||
template <typename MessageType>
|
||||
bool MergeFromMessage(const MessageType& message);
|
||||
|
||||
// Serialization.
|
||||
bool SerializeToString(std::string* output) const;
|
||||
bool SerializeToCodedStream(io::CodedOutputStream* output) const;
|
||||
static const UnknownFieldSet& default_instance();
|
||||
|
||||
private:
|
||||
// For InternalMergeFrom
|
||||
friend class UnknownField;
|
||||
// Merges from other UnknownFieldSet. This method assumes, that this object
|
||||
// is newly created and has no fields.
|
||||
void InternalMergeFrom(const UnknownFieldSet& other);
|
||||
void ClearFallback();
|
||||
|
||||
template <typename MessageType,
|
||||
typename std::enable_if<
|
||||
std::is_base_of<Message, MessageType>::value, int>::type = 0>
|
||||
bool InternalMergeFromMessage(const MessageType& message) {
|
||||
MergeFrom(message.GetReflection()->GetUnknownFields(message));
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename MessageType,
|
||||
typename std::enable_if<
|
||||
std::is_base_of<MessageLite, MessageType>::value &&
|
||||
!std::is_base_of<Message, MessageType>::value,
|
||||
int>::type = 0>
|
||||
bool InternalMergeFromMessage(const MessageType& message) {
|
||||
const auto& unknown_fields = message.unknown_fields();
|
||||
io::ArrayInputStream array_stream(unknown_fields.data(),
|
||||
unknown_fields.size());
|
||||
io::CodedInputStream coded_stream(&array_stream);
|
||||
return MergeFromCodedStream(&coded_stream);
|
||||
}
|
||||
|
||||
std::vector<UnknownField> fields_;
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(UnknownFieldSet);
|
||||
};
|
||||
|
||||
namespace internal {
|
||||
|
||||
inline void WriteVarint(uint32_t num, uint64_t val, UnknownFieldSet* unknown) {
|
||||
unknown->AddVarint(num, val);
|
||||
}
|
||||
inline void WriteLengthDelimited(uint32_t num, StringPiece val,
|
||||
UnknownFieldSet* unknown) {
|
||||
unknown->AddLengthDelimited(num)->assign(val.data(), val.size());
|
||||
}
|
||||
|
||||
PROTOBUF_EXPORT
|
||||
const char* UnknownGroupParse(UnknownFieldSet* unknown, const char* ptr,
|
||||
ParseContext* ctx);
|
||||
PROTOBUF_EXPORT
|
||||
const char* UnknownFieldParse(uint64_t tag, UnknownFieldSet* unknown,
|
||||
const char* ptr, ParseContext* ctx);
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// Represents one field in an UnknownFieldSet.
|
||||
class PROTOBUF_EXPORT UnknownField {
|
||||
public:
|
||||
enum Type {
|
||||
TYPE_VARINT,
|
||||
TYPE_FIXED32,
|
||||
TYPE_FIXED64,
|
||||
TYPE_LENGTH_DELIMITED,
|
||||
TYPE_GROUP
|
||||
};
|
||||
|
||||
// The field's field number, as seen on the wire.
|
||||
inline int number() const;
|
||||
|
||||
// The field type.
|
||||
inline Type type() const;
|
||||
|
||||
// Accessors -------------------------------------------------------
|
||||
// Each method works only for UnknownFields of the corresponding type.
|
||||
|
||||
inline uint64_t varint() const;
|
||||
inline uint32_t fixed32() const;
|
||||
inline uint64_t fixed64() const;
|
||||
inline const std::string& length_delimited() const;
|
||||
inline const UnknownFieldSet& group() const;
|
||||
|
||||
inline void set_varint(uint64_t value);
|
||||
inline void set_fixed32(uint32_t value);
|
||||
inline void set_fixed64(uint64_t value);
|
||||
inline void set_length_delimited(const std::string& value);
|
||||
inline std::string* mutable_length_delimited();
|
||||
inline UnknownFieldSet* mutable_group();
|
||||
|
||||
inline size_t GetLengthDelimitedSize() const;
|
||||
uint8_t* InternalSerializeLengthDelimitedNoTag(
|
||||
uint8_t* target, io::EpsCopyOutputStream* stream) const;
|
||||
|
||||
|
||||
// If this UnknownField contains a pointer, delete it.
|
||||
void Delete();
|
||||
|
||||
// Make a deep copy of any pointers in this UnknownField.
|
||||
void DeepCopy(const UnknownField& other);
|
||||
|
||||
// Set the wire type of this UnknownField. Should only be used when this
|
||||
// UnknownField is being created.
|
||||
inline void SetType(Type type);
|
||||
|
||||
union LengthDelimited {
|
||||
std::string* string_value;
|
||||
};
|
||||
|
||||
uint32_t number_;
|
||||
uint32_t type_;
|
||||
union {
|
||||
uint64_t varint_;
|
||||
uint32_t fixed32_;
|
||||
uint64_t fixed64_;
|
||||
mutable union LengthDelimited length_delimited_;
|
||||
UnknownFieldSet* group_;
|
||||
} data_;
|
||||
};
|
||||
|
||||
// ===================================================================
|
||||
// inline implementations
|
||||
|
||||
inline UnknownFieldSet::UnknownFieldSet() {}
|
||||
|
||||
inline UnknownFieldSet::~UnknownFieldSet() { Clear(); }
|
||||
|
||||
inline void UnknownFieldSet::ClearAndFreeMemory() { Clear(); }
|
||||
|
||||
inline void UnknownFieldSet::Clear() {
|
||||
if (!fields_.empty()) {
|
||||
ClearFallback();
|
||||
}
|
||||
}
|
||||
|
||||
inline bool UnknownFieldSet::empty() const { return fields_.empty(); }
|
||||
|
||||
inline void UnknownFieldSet::Swap(UnknownFieldSet* x) {
|
||||
fields_.swap(x->fields_);
|
||||
}
|
||||
|
||||
inline int UnknownFieldSet::field_count() const {
|
||||
return static_cast<int>(fields_.size());
|
||||
}
|
||||
inline const UnknownField& UnknownFieldSet::field(int index) const {
|
||||
return (fields_)[static_cast<size_t>(index)];
|
||||
}
|
||||
inline UnknownField* UnknownFieldSet::mutable_field(int index) {
|
||||
return &(fields_)[static_cast<size_t>(index)];
|
||||
}
|
||||
|
||||
inline void UnknownFieldSet::AddLengthDelimited(int number,
|
||||
const std::string& value) {
|
||||
AddLengthDelimited(number)->assign(value);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
inline int UnknownField::number() const { return static_cast<int>(number_); }
|
||||
inline UnknownField::Type UnknownField::type() const {
|
||||
return static_cast<Type>(type_);
|
||||
}
|
||||
|
||||
inline uint64_t UnknownField::varint() const {
|
||||
assert(type() == TYPE_VARINT);
|
||||
return data_.varint_;
|
||||
}
|
||||
inline uint32_t UnknownField::fixed32() const {
|
||||
assert(type() == TYPE_FIXED32);
|
||||
return data_.fixed32_;
|
||||
}
|
||||
inline uint64_t UnknownField::fixed64() const {
|
||||
assert(type() == TYPE_FIXED64);
|
||||
return data_.fixed64_;
|
||||
}
|
||||
inline const std::string& UnknownField::length_delimited() const {
|
||||
assert(type() == TYPE_LENGTH_DELIMITED);
|
||||
return *data_.length_delimited_.string_value;
|
||||
}
|
||||
inline const UnknownFieldSet& UnknownField::group() const {
|
||||
assert(type() == TYPE_GROUP);
|
||||
return *data_.group_;
|
||||
}
|
||||
|
||||
inline void UnknownField::set_varint(uint64_t value) {
|
||||
assert(type() == TYPE_VARINT);
|
||||
data_.varint_ = value;
|
||||
}
|
||||
inline void UnknownField::set_fixed32(uint32_t value) {
|
||||
assert(type() == TYPE_FIXED32);
|
||||
data_.fixed32_ = value;
|
||||
}
|
||||
inline void UnknownField::set_fixed64(uint64_t value) {
|
||||
assert(type() == TYPE_FIXED64);
|
||||
data_.fixed64_ = value;
|
||||
}
|
||||
inline void UnknownField::set_length_delimited(const std::string& value) {
|
||||
assert(type() == TYPE_LENGTH_DELIMITED);
|
||||
data_.length_delimited_.string_value->assign(value);
|
||||
}
|
||||
inline std::string* UnknownField::mutable_length_delimited() {
|
||||
assert(type() == TYPE_LENGTH_DELIMITED);
|
||||
return data_.length_delimited_.string_value;
|
||||
}
|
||||
inline UnknownFieldSet* UnknownField::mutable_group() {
|
||||
assert(type() == TYPE_GROUP);
|
||||
return data_.group_;
|
||||
}
|
||||
template <typename MessageType>
|
||||
bool UnknownFieldSet::MergeFromMessage(const MessageType& message) {
|
||||
// SFINAE will route to the right version.
|
||||
return InternalMergeFromMessage(message);
|
||||
}
|
||||
|
||||
|
||||
inline size_t UnknownField::GetLengthDelimitedSize() const {
|
||||
GOOGLE_DCHECK_EQ(TYPE_LENGTH_DELIMITED, type());
|
||||
return data_.length_delimited_.string_value->size();
|
||||
}
|
||||
|
||||
inline void UnknownField::SetType(Type type) {
|
||||
type_ = type;
|
||||
}
|
||||
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
#endif // GOOGLE_PROTOBUF_UNKNOWN_FIELD_SET_H__
|
||||
@@ -1,109 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Adapted from the patch of kenton@google.com (Kenton Varda)
|
||||
// See https://github.com/protocolbuffers/protobuf/pull/710 for details.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_UTIL_DELIMITED_MESSAGE_UTIL_H__
|
||||
#define GOOGLE_PROTOBUF_UTIL_DELIMITED_MESSAGE_UTIL_H__
|
||||
|
||||
|
||||
#include <ostream>
|
||||
|
||||
#include <google/protobuf/message_lite.h>
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/io/zero_copy_stream_impl.h>
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace util {
|
||||
|
||||
// Write a single size-delimited message from the given stream. Delimited
|
||||
// format allows a single file or stream to contain multiple messages,
|
||||
// whereas normally writing multiple non-delimited messages to the same
|
||||
// stream would cause them to be merged. A delimited message is a varint
|
||||
// encoding the message size followed by a message of exactly that size.
|
||||
//
|
||||
// Note that if you want to *read* a delimited message from a file descriptor
|
||||
// or istream, you will need to construct an io::FileInputStream or
|
||||
// io::OstreamInputStream (implementations of io::ZeroCopyStream) and use the
|
||||
// utility function ParseDelimitedFromZeroCopyStream(). You must then
|
||||
// continue to use the same ZeroCopyInputStream to read all further data from
|
||||
// the stream until EOF. This is because these ZeroCopyInputStream
|
||||
// implementations are buffered: they read a big chunk of data at a time,
|
||||
// then parse it. As a result, they may read past the end of the delimited
|
||||
// message. There is no way for them to push the extra data back into the
|
||||
// underlying source, so instead you must keep using the same stream object.
|
||||
bool PROTOBUF_EXPORT SerializeDelimitedToFileDescriptor(
|
||||
const MessageLite& message, int file_descriptor);
|
||||
|
||||
bool PROTOBUF_EXPORT SerializeDelimitedToOstream(const MessageLite& message,
|
||||
std::ostream* output);
|
||||
|
||||
// Read a single size-delimited message from the given stream. Delimited
|
||||
// format allows a single file or stream to contain multiple messages,
|
||||
// whereas normally parsing consumes the entire input. A delimited message
|
||||
// is a varint encoding the message size followed by a message of exactly
|
||||
// that size.
|
||||
//
|
||||
// If |clean_eof| is not NULL, then it will be set to indicate whether the
|
||||
// stream ended cleanly. That is, if the stream ends without this method
|
||||
// having read any data at all from it, then *clean_eof will be set true,
|
||||
// otherwise it will be set false. Note that these methods return false
|
||||
// on EOF, but they also return false on other errors, so |clean_eof| is
|
||||
// needed to distinguish a clean end from errors.
|
||||
bool PROTOBUF_EXPORT ParseDelimitedFromZeroCopyStream(
|
||||
MessageLite* message, io::ZeroCopyInputStream* input, bool* clean_eof);
|
||||
|
||||
bool PROTOBUF_EXPORT ParseDelimitedFromCodedStream(MessageLite* message,
|
||||
io::CodedInputStream* input,
|
||||
bool* clean_eof);
|
||||
|
||||
// Write a single size-delimited message from the given stream. Delimited
|
||||
// format allows a single file or stream to contain multiple messages,
|
||||
// whereas normally writing multiple non-delimited messages to the same
|
||||
// stream would cause them to be merged. A delimited message is a varint
|
||||
// encoding the message size followed by a message of exactly that size.
|
||||
bool PROTOBUF_EXPORT SerializeDelimitedToZeroCopyStream(
|
||||
const MessageLite& message, io::ZeroCopyOutputStream* output);
|
||||
|
||||
bool PROTOBUF_EXPORT SerializeDelimitedToCodedStream(
|
||||
const MessageLite& message, io::CodedOutputStream* output);
|
||||
|
||||
} // namespace util
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_UTIL_DELIMITED_MESSAGE_UTIL_H__
|
||||
@@ -1,288 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Defines classes for field comparison.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_UTIL_FIELD_COMPARATOR_H__
|
||||
#define GOOGLE_PROTOBUF_UTIL_FIELD_COMPARATOR_H__
|
||||
|
||||
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
class Message;
|
||||
class EnumValueDescriptor;
|
||||
class FieldDescriptor;
|
||||
|
||||
namespace util {
|
||||
|
||||
class FieldContext;
|
||||
class MessageDifferencer;
|
||||
|
||||
// Base class specifying the interface for comparing protocol buffer fields.
|
||||
// Regular users should consider using or subclassing DefaultFieldComparator
|
||||
// rather than this interface.
|
||||
// Currently, this does not support comparing unknown fields.
|
||||
class PROTOBUF_EXPORT FieldComparator {
|
||||
public:
|
||||
FieldComparator();
|
||||
virtual ~FieldComparator();
|
||||
|
||||
enum ComparisonResult {
|
||||
SAME, // Compared fields are equal. In case of comparing submessages,
|
||||
// user should not recursively compare their contents.
|
||||
DIFFERENT, // Compared fields are different. In case of comparing
|
||||
// submessages, user should not recursively compare their
|
||||
// contents.
|
||||
RECURSE, // Compared submessages need to be compared recursively.
|
||||
// FieldComparator does not specify the semantics of recursive
|
||||
// comparison. This value should not be returned for simple
|
||||
// values.
|
||||
};
|
||||
|
||||
// Compares the values of a field in two protocol buffer messages.
|
||||
// Returns SAME or DIFFERENT for simple values, and SAME, DIFFERENT or RECURSE
|
||||
// for submessages. Returning RECURSE for fields not being submessages is
|
||||
// illegal.
|
||||
// In case the given FieldDescriptor points to a repeated field, the indices
|
||||
// need to be valid. Otherwise they should be ignored.
|
||||
//
|
||||
// FieldContext contains information about the specific instances of the
|
||||
// fields being compared, versus FieldDescriptor which only contains general
|
||||
// type information about the fields.
|
||||
virtual ComparisonResult Compare(const Message& message_1,
|
||||
const Message& message_2,
|
||||
const FieldDescriptor* field, int index_1,
|
||||
int index_2,
|
||||
const util::FieldContext* field_context) = 0;
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldComparator);
|
||||
};
|
||||
|
||||
// Basic implementation of FieldComparator. Supports three modes of floating
|
||||
// point value comparison: exact, approximate using MathUtil::AlmostEqual
|
||||
// method, and arbitrarily precise using MathUtil::WithinFractionOrMargin.
|
||||
class PROTOBUF_EXPORT SimpleFieldComparator : public FieldComparator {
|
||||
public:
|
||||
enum FloatComparison {
|
||||
EXACT, // Floats and doubles are compared exactly.
|
||||
APPROXIMATE, // Floats and doubles are compared using the
|
||||
// MathUtil::AlmostEqual method or
|
||||
// MathUtil::WithinFractionOrMargin method.
|
||||
// TODO(ksroka): Introduce third value to differentiate uses of AlmostEqual
|
||||
// and WithinFractionOrMargin.
|
||||
};
|
||||
|
||||
// Creates new comparator with float comparison set to EXACT.
|
||||
SimpleFieldComparator();
|
||||
|
||||
~SimpleFieldComparator() override;
|
||||
|
||||
void set_float_comparison(FloatComparison float_comparison) {
|
||||
float_comparison_ = float_comparison;
|
||||
}
|
||||
|
||||
FloatComparison float_comparison() const { return float_comparison_; }
|
||||
|
||||
// Set whether the FieldComparator shall treat floats or doubles that are both
|
||||
// NaN as equal (treat_nan_as_equal = true) or as different
|
||||
// (treat_nan_as_equal = false). Default is treating NaNs always as different.
|
||||
void set_treat_nan_as_equal(bool treat_nan_as_equal) {
|
||||
treat_nan_as_equal_ = treat_nan_as_equal;
|
||||
}
|
||||
|
||||
bool treat_nan_as_equal() const { return treat_nan_as_equal_; }
|
||||
|
||||
// Sets the fraction and margin for the float comparison of a given field.
|
||||
// Uses MathUtil::WithinFractionOrMargin to compare the values.
|
||||
//
|
||||
// REQUIRES: field->cpp_type == FieldDescriptor::CPPTYPE_DOUBLE or
|
||||
// field->cpp_type == FieldDescriptor::CPPTYPE_FLOAT
|
||||
// REQUIRES: float_comparison_ == APPROXIMATE
|
||||
void SetFractionAndMargin(const FieldDescriptor* field, double fraction,
|
||||
double margin);
|
||||
|
||||
// Sets the fraction and margin for the float comparison of all float and
|
||||
// double fields, unless a field has been given a specific setting via
|
||||
// SetFractionAndMargin() above.
|
||||
// Uses MathUtil::WithinFractionOrMargin to compare the values.
|
||||
//
|
||||
// REQUIRES: float_comparison_ == APPROXIMATE
|
||||
void SetDefaultFractionAndMargin(double fraction, double margin);
|
||||
|
||||
protected:
|
||||
// Returns the comparison result for the given field in two messages.
|
||||
//
|
||||
// This function is called directly by DefaultFieldComparator::Compare.
|
||||
// Subclasses can call this function to compare fields they do not need to
|
||||
// handle specially.
|
||||
ComparisonResult SimpleCompare(const Message& message_1,
|
||||
const Message& message_2,
|
||||
const FieldDescriptor* field, int index_1,
|
||||
int index_2,
|
||||
const util::FieldContext* field_context);
|
||||
|
||||
// Compare using the provided message_differencer. For example, a subclass can
|
||||
// use this method to compare some field in a certain way using the same
|
||||
// message_differencer instance and the field context.
|
||||
bool CompareWithDifferencer(MessageDifferencer* differencer,
|
||||
const Message& message1, const Message& message2,
|
||||
const util::FieldContext* field_context);
|
||||
|
||||
// Returns FieldComparator::SAME if boolean_result is true and
|
||||
// FieldComparator::DIFFERENT otherwise.
|
||||
ComparisonResult ResultFromBoolean(bool boolean_result) const;
|
||||
|
||||
private:
|
||||
// Defines the tolerance for floating point comparison (fraction and margin).
|
||||
struct Tolerance {
|
||||
double fraction;
|
||||
double margin;
|
||||
Tolerance() : fraction(0.0), margin(0.0) {}
|
||||
Tolerance(double f, double m) : fraction(f), margin(m) {}
|
||||
};
|
||||
|
||||
// Defines the map to store the tolerances for floating point comparison.
|
||||
typedef std::map<const FieldDescriptor*, Tolerance> ToleranceMap;
|
||||
|
||||
friend class MessageDifferencer;
|
||||
// The following methods get executed when CompareFields is called for the
|
||||
// basic types (instead of submessages). They return true on success. One
|
||||
// can use ResultFromBoolean() to convert that boolean to a ComparisonResult
|
||||
// value.
|
||||
bool CompareBool(const FieldDescriptor& /* unused */, bool value_1,
|
||||
bool value_2) {
|
||||
return value_1 == value_2;
|
||||
}
|
||||
|
||||
// Uses CompareDoubleOrFloat, a helper function used by both CompareDouble and
|
||||
// CompareFloat.
|
||||
bool CompareDouble(const FieldDescriptor& field, double value_1,
|
||||
double value_2);
|
||||
|
||||
bool CompareEnum(const FieldDescriptor& field,
|
||||
const EnumValueDescriptor* value_1,
|
||||
const EnumValueDescriptor* value_2);
|
||||
|
||||
// Uses CompareDoubleOrFloat, a helper function used by both CompareDouble and
|
||||
// CompareFloat.
|
||||
bool CompareFloat(const FieldDescriptor& field, float value_1, float value_2);
|
||||
|
||||
bool CompareInt32(const FieldDescriptor& /* unused */, int32_t value_1,
|
||||
int32_t value_2) {
|
||||
return value_1 == value_2;
|
||||
}
|
||||
|
||||
bool CompareInt64(const FieldDescriptor& /* unused */, int64_t value_1,
|
||||
int64_t value_2) {
|
||||
return value_1 == value_2;
|
||||
}
|
||||
|
||||
bool CompareString(const FieldDescriptor& /* unused */,
|
||||
const std::string& value_1, const std::string& value_2) {
|
||||
return value_1 == value_2;
|
||||
}
|
||||
|
||||
bool CompareUInt32(const FieldDescriptor& /* unused */, uint32_t value_1,
|
||||
uint32_t value_2) {
|
||||
return value_1 == value_2;
|
||||
}
|
||||
|
||||
bool CompareUInt64(const FieldDescriptor& /* unused */, uint64_t value_1,
|
||||
uint64_t value_2) {
|
||||
return value_1 == value_2;
|
||||
}
|
||||
|
||||
// This function is used by CompareDouble and CompareFloat to avoid code
|
||||
// duplication. There are no checks done against types of the values passed,
|
||||
// but it's likely to fail if passed non-numeric arguments.
|
||||
template <typename T>
|
||||
bool CompareDoubleOrFloat(const FieldDescriptor& field, T value_1, T value_2);
|
||||
|
||||
FloatComparison float_comparison_;
|
||||
|
||||
// If true, floats and doubles that are both NaN are considered to be
|
||||
// equal. Otherwise, two floats or doubles that are NaN are considered to be
|
||||
// different.
|
||||
bool treat_nan_as_equal_;
|
||||
|
||||
// True iff default_tolerance_ has been explicitly set.
|
||||
//
|
||||
// If false, then the default tolerance for floats and doubles is that which
|
||||
// is used by MathUtil::AlmostEquals().
|
||||
bool has_default_tolerance_;
|
||||
|
||||
// Default float/double tolerance. Only meaningful if
|
||||
// has_default_tolerance_ == true.
|
||||
Tolerance default_tolerance_;
|
||||
|
||||
// Field-specific float/double tolerances, which override any default for
|
||||
// those particular fields.
|
||||
ToleranceMap map_tolerance_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SimpleFieldComparator);
|
||||
};
|
||||
|
||||
// Default field comparison: use the basic implementation of FieldComparator.
|
||||
#ifdef PROTOBUF_FUTURE_BREAKING_CHANGES
|
||||
class PROTOBUF_EXPORT DefaultFieldComparator final
|
||||
: public SimpleFieldComparator
|
||||
#else // PROTOBUF_FUTURE_BREAKING_CHANGES
|
||||
class PROTOBUF_EXPORT DefaultFieldComparator : public SimpleFieldComparator
|
||||
#endif // PROTOBUF_FUTURE_BREAKING_CHANGES
|
||||
{
|
||||
public:
|
||||
ComparisonResult Compare(const Message& message_1, const Message& message_2,
|
||||
const FieldDescriptor* field, int index_1,
|
||||
int index_2,
|
||||
const util::FieldContext* field_context) override {
|
||||
return SimpleCompare(message_1, message_2, field, index_1, index_2,
|
||||
field_context);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace util
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_UTIL_FIELD_COMPARATOR_H__
|
||||
@@ -1,263 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Defines utilities for the FieldMask well known type.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_UTIL_FIELD_MASK_UTIL_H__
|
||||
#define GOOGLE_PROTOBUF_UTIL_FIELD_MASK_UTIL_H__
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/field_mask.pb.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace util {
|
||||
|
||||
class PROTOBUF_EXPORT FieldMaskUtil {
|
||||
typedef google::protobuf::FieldMask FieldMask;
|
||||
|
||||
public:
|
||||
// Converts FieldMask to/from string, formatted by separating each path
|
||||
// with a comma (e.g., "foo_bar,baz.quz").
|
||||
static std::string ToString(const FieldMask& mask);
|
||||
static void FromString(StringPiece str, FieldMask* out);
|
||||
|
||||
// Populates the FieldMask with the paths corresponding to the fields with the
|
||||
// given numbers, after checking that all field numbers are valid.
|
||||
template <typename T>
|
||||
static void FromFieldNumbers(const std::vector<int64_t>& field_numbers,
|
||||
FieldMask* out) {
|
||||
for (const auto field_number : field_numbers) {
|
||||
const FieldDescriptor* field_desc =
|
||||
T::descriptor()->FindFieldByNumber(field_number);
|
||||
GOOGLE_CHECK(field_desc != nullptr)
|
||||
<< "Invalid field number for " << T::descriptor()->full_name() << ": "
|
||||
<< field_number;
|
||||
AddPathToFieldMask<T>(field_desc->lowercase_name(), out);
|
||||
}
|
||||
}
|
||||
|
||||
// Converts FieldMask to/from string, formatted according to proto3 JSON
|
||||
// spec for FieldMask (e.g., "fooBar,baz.quz"). If the field name is not
|
||||
// style conforming (i.e., not snake_case when converted to string, or not
|
||||
// camelCase when converted from string), the conversion will fail.
|
||||
static bool ToJsonString(const FieldMask& mask, std::string* out);
|
||||
static bool FromJsonString(StringPiece str, FieldMask* out);
|
||||
|
||||
// Get the descriptors of the fields which the given path from the message
|
||||
// descriptor traverses, if field_descriptors is not null.
|
||||
// Return false if the path is not valid, and the content of field_descriptors
|
||||
// is unspecified.
|
||||
static bool GetFieldDescriptors(
|
||||
const Descriptor* descriptor, StringPiece path,
|
||||
std::vector<const FieldDescriptor*>* field_descriptors);
|
||||
|
||||
// Checks whether the given path is valid for type T.
|
||||
template <typename T>
|
||||
static bool IsValidPath(StringPiece path) {
|
||||
return GetFieldDescriptors(T::descriptor(), path, nullptr);
|
||||
}
|
||||
|
||||
// Checks whether the given FieldMask is valid for type T.
|
||||
template <typename T>
|
||||
static bool IsValidFieldMask(const FieldMask& mask) {
|
||||
for (int i = 0; i < mask.paths_size(); ++i) {
|
||||
if (!GetFieldDescriptors(T::descriptor(), mask.paths(i), nullptr)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Adds a path to FieldMask after checking whether the given path is valid.
|
||||
// This method check-fails if the path is not a valid path for type T.
|
||||
template <typename T>
|
||||
static void AddPathToFieldMask(StringPiece path, FieldMask* mask) {
|
||||
GOOGLE_CHECK(IsValidPath<T>(path)) << path;
|
||||
mask->add_paths(std::string(path));
|
||||
}
|
||||
|
||||
// Creates a FieldMask with all fields of type T. This FieldMask only
|
||||
// contains fields of T but not any sub-message fields.
|
||||
template <typename T>
|
||||
static FieldMask GetFieldMaskForAllFields() {
|
||||
FieldMask out;
|
||||
GetFieldMaskForAllFields(T::descriptor(), &out);
|
||||
return out;
|
||||
}
|
||||
template <typename T>
|
||||
PROTOBUF_DEPRECATED_MSG("Use *out = GetFieldMaskForAllFields() instead")
|
||||
static void GetFieldMaskForAllFields(FieldMask* out) {
|
||||
GetFieldMaskForAllFields(T::descriptor(), out);
|
||||
}
|
||||
// This flavor takes the protobuf type descriptor as an argument.
|
||||
// Useful when the type is not known at compile time.
|
||||
static void GetFieldMaskForAllFields(const Descriptor* descriptor,
|
||||
FieldMask* out);
|
||||
|
||||
// Converts a FieldMask to the canonical form. It will:
|
||||
// 1. Remove paths that are covered by another path. For example,
|
||||
// "foo.bar" is covered by "foo" and will be removed if "foo"
|
||||
// is also in the FieldMask.
|
||||
// 2. Sort all paths in alphabetical order.
|
||||
static void ToCanonicalForm(const FieldMask& mask, FieldMask* out);
|
||||
|
||||
// Creates an union of two FieldMasks.
|
||||
static void Union(const FieldMask& mask1, const FieldMask& mask2,
|
||||
FieldMask* out);
|
||||
|
||||
// Creates an intersection of two FieldMasks.
|
||||
static void Intersect(const FieldMask& mask1, const FieldMask& mask2,
|
||||
FieldMask* out);
|
||||
|
||||
// Subtracts mask2 from mask1 base of type T.
|
||||
template <typename T>
|
||||
static void Subtract(const FieldMask& mask1, const FieldMask& mask2,
|
||||
FieldMask* out) {
|
||||
Subtract(T::descriptor(), mask1, mask2, out);
|
||||
}
|
||||
// This flavor takes the protobuf type descriptor as an argument.
|
||||
// Useful when the type is not known at compile time.
|
||||
static void Subtract(const Descriptor* descriptor, const FieldMask& mask1,
|
||||
const FieldMask& mask2, FieldMask* out);
|
||||
|
||||
// Returns true if path is covered by the given FieldMask. Note that path
|
||||
// "foo.bar" covers all paths like "foo.bar.baz", "foo.bar.quz.x", etc.
|
||||
// Also note that parent paths are not covered by explicit child path, i.e.
|
||||
// "foo.bar" does NOT cover "foo", even if "bar" is the only child.
|
||||
static bool IsPathInFieldMask(StringPiece path, const FieldMask& mask);
|
||||
|
||||
class MergeOptions;
|
||||
// Merges fields specified in a FieldMask into another message.
|
||||
static void MergeMessageTo(const Message& source, const FieldMask& mask,
|
||||
const MergeOptions& options, Message* destination);
|
||||
|
||||
class TrimOptions;
|
||||
// Removes from 'message' any field that is not represented in the given
|
||||
// FieldMask. If the FieldMask is empty, does nothing.
|
||||
// Returns true if the message is modified.
|
||||
static bool TrimMessage(const FieldMask& mask, Message* message);
|
||||
|
||||
// Removes from 'message' any field that is not represented in the given
|
||||
// FieldMask with customized TrimOptions.
|
||||
// If the FieldMask is empty, does nothing.
|
||||
// Returns true if the message is modified.
|
||||
static bool TrimMessage(const FieldMask& mask, Message* message,
|
||||
const TrimOptions& options);
|
||||
|
||||
private:
|
||||
friend class SnakeCaseCamelCaseTest;
|
||||
// Converts a field name from snake_case to camelCase:
|
||||
// 1. Every character after "_" will be converted to uppercase.
|
||||
// 2. All "_"s are removed.
|
||||
// The conversion will fail if:
|
||||
// 1. The field name contains uppercase letters.
|
||||
// 2. Any character after a "_" is not a lowercase letter.
|
||||
// If the conversion succeeds, it's guaranteed that the resulted
|
||||
// camelCase name will yield the original snake_case name when
|
||||
// converted using CamelCaseToSnakeCase().
|
||||
//
|
||||
// Note that the input can contain characters not allowed in C identifiers.
|
||||
// For example, "foo_bar,baz_quz" will be converted to "fooBar,bazQuz"
|
||||
// successfully.
|
||||
static bool SnakeCaseToCamelCase(StringPiece input,
|
||||
std::string* output);
|
||||
// Converts a field name from camelCase to snake_case:
|
||||
// 1. Every uppercase letter is converted to lowercase with an additional
|
||||
// preceding "_".
|
||||
// The conversion will fail if:
|
||||
// 1. The field name contains "_"s.
|
||||
// If the conversion succeeds, it's guaranteed that the resulted
|
||||
// snake_case name will yield the original camelCase name when
|
||||
// converted using SnakeCaseToCamelCase().
|
||||
//
|
||||
// Note that the input can contain characters not allowed in C identifiers.
|
||||
// For example, "fooBar,bazQuz" will be converted to "foo_bar,baz_quz"
|
||||
// successfully.
|
||||
static bool CamelCaseToSnakeCase(StringPiece input,
|
||||
std::string* output);
|
||||
};
|
||||
|
||||
class PROTOBUF_EXPORT FieldMaskUtil::MergeOptions {
|
||||
public:
|
||||
MergeOptions()
|
||||
: replace_message_fields_(false), replace_repeated_fields_(false) {}
|
||||
// When merging message fields, the default behavior is to merge the
|
||||
// content of two message fields together. If you instead want to use
|
||||
// the field from the source message to replace the corresponding field
|
||||
// in the destination message, set this flag to true. When this flag is set,
|
||||
// specified submessage fields that are missing in source will be cleared in
|
||||
// destination.
|
||||
void set_replace_message_fields(bool value) {
|
||||
replace_message_fields_ = value;
|
||||
}
|
||||
bool replace_message_fields() const { return replace_message_fields_; }
|
||||
// The default merging behavior will append entries from the source
|
||||
// repeated field to the destination repeated field. If you only want
|
||||
// to keep the entries from the source repeated field, set this flag
|
||||
// to true.
|
||||
void set_replace_repeated_fields(bool value) {
|
||||
replace_repeated_fields_ = value;
|
||||
}
|
||||
bool replace_repeated_fields() const { return replace_repeated_fields_; }
|
||||
|
||||
private:
|
||||
bool replace_message_fields_;
|
||||
bool replace_repeated_fields_;
|
||||
};
|
||||
|
||||
class PROTOBUF_EXPORT FieldMaskUtil::TrimOptions {
|
||||
public:
|
||||
TrimOptions() : keep_required_fields_(false) {}
|
||||
// When trimming message fields, the default behavior is to trim required
|
||||
// fields of the present message if they are not specified in the field mask.
|
||||
// If you instead want to keep required fields of the present message even
|
||||
// when they are not specified in the field mask, set this flag to true.
|
||||
void set_keep_required_fields(bool value) { keep_required_fields_ = value; }
|
||||
bool keep_required_fields() const { return keep_required_fields_; }
|
||||
|
||||
private:
|
||||
bool keep_required_fields_;
|
||||
};
|
||||
|
||||
} // namespace util
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_UTIL_FIELD_MASK_UTIL_H__
|
||||
@@ -1,101 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_UTIL_INTERNAL_CONSTANTS_H__
|
||||
#define GOOGLE_PROTOBUF_UTIL_INTERNAL_CONSTANTS_H__
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
// This file contains constants used by //net/proto2/util/converter.
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace util {
|
||||
namespace converter {
|
||||
// Prefix for type URLs.
|
||||
const char kTypeServiceBaseUrl[] = "type.googleapis.com";
|
||||
|
||||
// Format string for RFC3339 timestamp formatting.
|
||||
const char kRfc3339TimeFormat[] = "%E4Y-%m-%dT%H:%M:%S";
|
||||
|
||||
// Same as above, but the year value is not zero-padded i.e. this accepts
|
||||
// timestamps like "1-01-0001T23:59:59Z" instead of "0001-01-0001T23:59:59Z".
|
||||
const char kRfc3339TimeFormatNoPadding[] = "%Y-%m-%dT%H:%M:%S";
|
||||
|
||||
// Minimum seconds allowed in a google.protobuf.Timestamp value.
|
||||
const int64_t kTimestampMinSeconds = -62135596800LL;
|
||||
|
||||
// Maximum seconds allowed in a google.protobuf.Timestamp value.
|
||||
const int64_t kTimestampMaxSeconds = 253402300799LL;
|
||||
|
||||
// Minimum seconds allowed in a google.protobuf.Duration value.
|
||||
const int64_t kDurationMinSeconds = -315576000000LL;
|
||||
|
||||
// Maximum seconds allowed in a google.protobuf.Duration value.
|
||||
const int64_t kDurationMaxSeconds = 315576000000LL;
|
||||
|
||||
// Nano seconds in a second.
|
||||
const int32_t kNanosPerSecond = 1000000000;
|
||||
|
||||
// Type url representing NULL values in google.protobuf.Struct type.
|
||||
const char kStructNullValueTypeUrl[] =
|
||||
"type.googleapis.com/google.protobuf.NullValue";
|
||||
|
||||
// Type string for google.protobuf.Struct
|
||||
const char kStructType[] = "google.protobuf.Struct";
|
||||
|
||||
// Type string for struct.proto's google.protobuf.Value value type.
|
||||
const char kStructValueType[] = "google.protobuf.Value";
|
||||
|
||||
// Type string for struct.proto's google.protobuf.ListValue value type.
|
||||
const char kStructListValueType[] = "google.protobuf.ListValue";
|
||||
|
||||
// Type string for google.protobuf.Timestamp
|
||||
const char kTimestampType[] = "google.protobuf.Timestamp";
|
||||
|
||||
// Type string for google.protobuf.Duration
|
||||
const char kDurationType[] = "google.protobuf.Duration";
|
||||
|
||||
// Type URL for struct value type google.protobuf.Value
|
||||
const char kStructValueTypeUrl[] = "type.googleapis.com/google.protobuf.Value";
|
||||
|
||||
// Type string for google.protobuf.Any
|
||||
const char kAnyType[] = "google.protobuf.Any";
|
||||
|
||||
// The protobuf option name of jspb.message_id;
|
||||
const char kOptionJspbMessageId[] = "jspb.message_id";
|
||||
|
||||
} // namespace converter
|
||||
} // namespace util
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_UTIL_INTERNAL_CONSTANTS_H__
|
||||
@@ -1,219 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_UTIL_INTERNAL_DATAPIECE_H__
|
||||
#define GOOGLE_PROTOBUF_UTIL_INTERNAL_DATAPIECE_H__
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/logging.h>
|
||||
#include <google/protobuf/type.pb.h>
|
||||
#include <google/protobuf/stubs/statusor.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace util {
|
||||
namespace converter {
|
||||
class ProtoWriter;
|
||||
|
||||
// Container for a single piece of data together with its data type.
|
||||
//
|
||||
// For primitive types (int32, int64, uint32, uint64, double, float, bool),
|
||||
// the data is stored by value.
|
||||
//
|
||||
// For string, a StringPiece is stored. For Cord, a pointer to Cord is stored.
|
||||
// Just like StringPiece, the DataPiece class does not own the storage for
|
||||
// the actual string or Cord, so it is the user's responsibility to guarantee
|
||||
// that the underlying storage is still valid when the DataPiece is accessed.
|
||||
class PROTOBUF_EXPORT DataPiece {
|
||||
public:
|
||||
// Identifies data type of the value.
|
||||
// These are the types supported by DataPiece.
|
||||
enum Type {
|
||||
TYPE_INT32 = 1,
|
||||
TYPE_INT64 = 2,
|
||||
TYPE_UINT32 = 3,
|
||||
TYPE_UINT64 = 4,
|
||||
TYPE_DOUBLE = 5,
|
||||
TYPE_FLOAT = 6,
|
||||
TYPE_BOOL = 7,
|
||||
TYPE_ENUM = 8,
|
||||
TYPE_STRING = 9,
|
||||
TYPE_BYTES = 10,
|
||||
TYPE_NULL = 11, // explicit NULL type
|
||||
};
|
||||
|
||||
// Constructors and Destructor
|
||||
explicit DataPiece(const int32_t value)
|
||||
: type_(TYPE_INT32), i32_(value), use_strict_base64_decoding_(false) {}
|
||||
explicit DataPiece(const int64_t value)
|
||||
: type_(TYPE_INT64), i64_(value), use_strict_base64_decoding_(false) {}
|
||||
explicit DataPiece(const uint32_t value)
|
||||
: type_(TYPE_UINT32), u32_(value), use_strict_base64_decoding_(false) {}
|
||||
explicit DataPiece(const uint64_t value)
|
||||
: type_(TYPE_UINT64), u64_(value), use_strict_base64_decoding_(false) {}
|
||||
explicit DataPiece(const double value)
|
||||
: type_(TYPE_DOUBLE),
|
||||
double_(value),
|
||||
use_strict_base64_decoding_(false) {}
|
||||
explicit DataPiece(const float value)
|
||||
: type_(TYPE_FLOAT), float_(value), use_strict_base64_decoding_(false) {}
|
||||
explicit DataPiece(const bool value)
|
||||
: type_(TYPE_BOOL), bool_(value), use_strict_base64_decoding_(false) {}
|
||||
DataPiece(StringPiece value, bool use_strict_base64_decoding)
|
||||
: type_(TYPE_STRING),
|
||||
str_(value),
|
||||
use_strict_base64_decoding_(use_strict_base64_decoding) {}
|
||||
// Constructor for bytes. The second parameter is not used.
|
||||
DataPiece(StringPiece value, bool /*dummy*/, bool use_strict_base64_decoding)
|
||||
: type_(TYPE_BYTES),
|
||||
str_(value),
|
||||
use_strict_base64_decoding_(use_strict_base64_decoding) {}
|
||||
|
||||
DataPiece(const DataPiece& r) : type_(r.type_) { InternalCopy(r); }
|
||||
|
||||
DataPiece& operator=(const DataPiece& x) {
|
||||
InternalCopy(x);
|
||||
return *this;
|
||||
}
|
||||
|
||||
static DataPiece NullData() { return DataPiece(TYPE_NULL, 0); }
|
||||
|
||||
virtual ~DataPiece() {
|
||||
}
|
||||
|
||||
// Accessors
|
||||
Type type() const { return type_; }
|
||||
|
||||
bool use_strict_base64_decoding() { return use_strict_base64_decoding_; }
|
||||
|
||||
StringPiece str() const {
|
||||
GOOGLE_LOG_IF(DFATAL, type_ != TYPE_STRING) << "Not a string type.";
|
||||
return str_;
|
||||
}
|
||||
|
||||
|
||||
// Parses, casts or converts the value stored in the DataPiece into an int32.
|
||||
util::StatusOr<int32_t> ToInt32() const;
|
||||
|
||||
// Parses, casts or converts the value stored in the DataPiece into a uint32.
|
||||
util::StatusOr<uint32_t> ToUint32() const;
|
||||
|
||||
// Parses, casts or converts the value stored in the DataPiece into an int64.
|
||||
util::StatusOr<int64_t> ToInt64() const;
|
||||
|
||||
// Parses, casts or converts the value stored in the DataPiece into a uint64.
|
||||
util::StatusOr<uint64_t> ToUint64() const;
|
||||
|
||||
// Parses, casts or converts the value stored in the DataPiece into a double.
|
||||
util::StatusOr<double> ToDouble() const;
|
||||
|
||||
// Parses, casts or converts the value stored in the DataPiece into a float.
|
||||
util::StatusOr<float> ToFloat() const;
|
||||
|
||||
// Parses, casts or converts the value stored in the DataPiece into a bool.
|
||||
util::StatusOr<bool> ToBool() const;
|
||||
|
||||
// Parses, casts or converts the value stored in the DataPiece into a string.
|
||||
util::StatusOr<std::string> ToString() const;
|
||||
|
||||
// Tries to convert the value contained in this datapiece to string. If the
|
||||
// conversion fails, it returns the default_string.
|
||||
std::string ValueAsStringOrDefault(StringPiece default_string) const;
|
||||
|
||||
util::StatusOr<std::string> ToBytes() const;
|
||||
|
||||
private:
|
||||
friend class ProtoWriter;
|
||||
|
||||
// Disallow implicit constructor.
|
||||
DataPiece();
|
||||
|
||||
// Helper to create NULL or ENUM types.
|
||||
DataPiece(Type type, int32_t val)
|
||||
: type_(type), i32_(val), use_strict_base64_decoding_(false) {}
|
||||
|
||||
// Same as the ToEnum() method above but with additional flag to ignore
|
||||
// unknown enum values.
|
||||
util::StatusOr<int> ToEnum(const google::protobuf::Enum* enum_type,
|
||||
bool use_lower_camel_for_enums,
|
||||
bool case_insensitive_enum_parsing,
|
||||
bool ignore_unknown_enum_values,
|
||||
bool* is_unknown_enum_value) const;
|
||||
|
||||
// For numeric conversion between
|
||||
// int32, int64, uint32, uint64, double, float and bool
|
||||
template <typename To>
|
||||
util::StatusOr<To> GenericConvert() const;
|
||||
|
||||
// For conversion from string to
|
||||
// int32, int64, uint32, uint64, double, float and bool
|
||||
template <typename To>
|
||||
util::StatusOr<To> StringToNumber(bool (*func)(StringPiece, To*)) const;
|
||||
|
||||
// Decodes a base64 string. Returns true on success.
|
||||
bool DecodeBase64(StringPiece src, std::string* dest) const;
|
||||
|
||||
// Helper function to initialize this DataPiece with 'other'.
|
||||
void InternalCopy(const DataPiece& other);
|
||||
|
||||
// Data type for this piece of data.
|
||||
Type type_;
|
||||
|
||||
// Stored piece of data.
|
||||
union {
|
||||
int32_t i32_;
|
||||
int64_t i64_;
|
||||
uint32_t u32_;
|
||||
uint64_t u64_;
|
||||
double double_;
|
||||
float float_;
|
||||
bool bool_;
|
||||
StringPiece str_;
|
||||
};
|
||||
|
||||
// Uses a stricter version of base64 decoding for byte fields.
|
||||
bool use_strict_base64_decoding_;
|
||||
};
|
||||
|
||||
} // namespace converter
|
||||
} // namespace util
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_UTIL_INTERNAL_DATAPIECE_H__
|
||||
@@ -1,332 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_UTIL_INTERNAL_DEFAULT_VALUE_OBJECTWRITER_H__
|
||||
#define GOOGLE_PROTOBUF_UTIL_INTERNAL_DEFAULT_VALUE_OBJECTWRITER_H__
|
||||
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <stack>
|
||||
#include <vector>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
#include <google/protobuf/util/internal/datapiece.h>
|
||||
#include <google/protobuf/util/internal/object_writer.h>
|
||||
#include <google/protobuf/util/internal/type_info.h>
|
||||
#include <google/protobuf/util/internal/utility.h>
|
||||
#include <google/protobuf/util/type_resolver.h>
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace util {
|
||||
namespace converter {
|
||||
|
||||
// An ObjectWriter that renders non-repeated primitive fields of proto messages
|
||||
// with their default values. DefaultValueObjectWriter holds objects, lists and
|
||||
// fields it receives in a tree structure and writes them out to another
|
||||
// ObjectWriter when EndObject() is called on the root object. It also writes
|
||||
// out all non-repeated primitive fields that haven't been explicitly rendered
|
||||
// with their default values (0 for numbers, "" for strings, etc).
|
||||
class PROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter {
|
||||
public:
|
||||
// A Callback function to check whether a field needs to be scrubbed.
|
||||
//
|
||||
// Returns true if the field should not be present in the output. Returns
|
||||
// false otherwise.
|
||||
//
|
||||
// The 'path' parameter is a vector of path to the field from root. For
|
||||
// example: if a nested field "a.b.c" (b is the parent message field of c and
|
||||
// a is the parent message field of b), then the vector should contain { "a",
|
||||
// "b", "c" }.
|
||||
//
|
||||
// The Field* should point to the google::protobuf::Field of "c".
|
||||
typedef std::function<bool(
|
||||
const std::vector<std::string>& /*path of the field*/,
|
||||
const google::protobuf::Field* /*field*/)>
|
||||
FieldScrubCallBack;
|
||||
|
||||
DefaultValueObjectWriter(TypeResolver* type_resolver,
|
||||
const google::protobuf::Type& type,
|
||||
ObjectWriter* ow);
|
||||
|
||||
~DefaultValueObjectWriter() override;
|
||||
|
||||
// ObjectWriter methods.
|
||||
DefaultValueObjectWriter* StartObject(StringPiece name) override;
|
||||
|
||||
DefaultValueObjectWriter* EndObject() override;
|
||||
|
||||
DefaultValueObjectWriter* StartList(StringPiece name) override;
|
||||
|
||||
DefaultValueObjectWriter* EndList() override;
|
||||
|
||||
DefaultValueObjectWriter* RenderBool(StringPiece name,
|
||||
bool value) override;
|
||||
|
||||
DefaultValueObjectWriter* RenderInt32(StringPiece name,
|
||||
int32_t value) override;
|
||||
|
||||
DefaultValueObjectWriter* RenderUint32(StringPiece name,
|
||||
uint32_t value) override;
|
||||
|
||||
DefaultValueObjectWriter* RenderInt64(StringPiece name,
|
||||
int64_t value) override;
|
||||
|
||||
DefaultValueObjectWriter* RenderUint64(StringPiece name,
|
||||
uint64_t value) override;
|
||||
|
||||
DefaultValueObjectWriter* RenderDouble(StringPiece name,
|
||||
double value) override;
|
||||
|
||||
DefaultValueObjectWriter* RenderFloat(StringPiece name,
|
||||
float value) override;
|
||||
|
||||
DefaultValueObjectWriter* RenderString(StringPiece name,
|
||||
StringPiece value) override;
|
||||
DefaultValueObjectWriter* RenderBytes(StringPiece name,
|
||||
StringPiece value) override;
|
||||
|
||||
DefaultValueObjectWriter* RenderNull(StringPiece name) override;
|
||||
|
||||
// Register the callback for scrubbing of fields.
|
||||
void RegisterFieldScrubCallBack(FieldScrubCallBack field_scrub_callback);
|
||||
|
||||
// If set to true, empty lists are suppressed from output when default values
|
||||
// are written.
|
||||
void set_suppress_empty_list(bool value) { suppress_empty_list_ = value; }
|
||||
|
||||
// If set to true, original proto field names are used
|
||||
void set_preserve_proto_field_names(bool value) {
|
||||
preserve_proto_field_names_ = value;
|
||||
}
|
||||
|
||||
// If set to true, enums are rendered as ints from output when default values
|
||||
// are written.
|
||||
void set_print_enums_as_ints(bool value) { use_ints_for_enums_ = value; }
|
||||
|
||||
protected:
|
||||
enum NodeKind {
|
||||
PRIMITIVE = 0,
|
||||
OBJECT = 1,
|
||||
LIST = 2,
|
||||
MAP = 3,
|
||||
};
|
||||
|
||||
// "Node" represents a node in the tree that holds the input of
|
||||
// DefaultValueObjectWriter.
|
||||
class PROTOBUF_EXPORT Node {
|
||||
public:
|
||||
Node(const std::string& name, const google::protobuf::Type* type,
|
||||
NodeKind kind, const DataPiece& data, bool is_placeholder,
|
||||
const std::vector<std::string>& path, bool suppress_empty_list,
|
||||
bool preserve_proto_field_names, bool use_ints_for_enums,
|
||||
FieldScrubCallBack field_scrub_callback);
|
||||
virtual ~Node() {
|
||||
for (size_t i = 0; i < children_.size(); ++i) {
|
||||
delete children_[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Adds a child to this node. Takes ownership of this child.
|
||||
void AddChild(Node* child) { children_.push_back(child); }
|
||||
|
||||
// Finds the child given its name.
|
||||
Node* FindChild(StringPiece name);
|
||||
|
||||
// Populates children of this Node based on its type. If there are already
|
||||
// children created, they will be merged to the result. Caller should pass
|
||||
// in TypeInfo for looking up types of the children.
|
||||
virtual void PopulateChildren(const TypeInfo* typeinfo);
|
||||
|
||||
// If this node is a leaf (has data), writes the current node to the
|
||||
// ObjectWriter; if not, then recursively writes the children to the
|
||||
// ObjectWriter.
|
||||
virtual void WriteTo(ObjectWriter* ow);
|
||||
|
||||
// Accessors
|
||||
const std::string& name() const { return name_; }
|
||||
|
||||
const std::vector<std::string>& path() const { return path_; }
|
||||
|
||||
const google::protobuf::Type* type() const { return type_; }
|
||||
|
||||
void set_type(const google::protobuf::Type* type) { type_ = type; }
|
||||
|
||||
NodeKind kind() const { return kind_; }
|
||||
|
||||
int number_of_children() const { return children_.size(); }
|
||||
|
||||
void set_data(const DataPiece& data) { data_ = data; }
|
||||
|
||||
bool is_any() const { return is_any_; }
|
||||
|
||||
void set_is_any(bool is_any) { is_any_ = is_any; }
|
||||
|
||||
void set_is_placeholder(bool is_placeholder) {
|
||||
is_placeholder_ = is_placeholder;
|
||||
}
|
||||
|
||||
protected:
|
||||
// Returns the Value Type of a map given the Type of the map entry and a
|
||||
// TypeInfo instance.
|
||||
const google::protobuf::Type* GetMapValueType(
|
||||
const google::protobuf::Type& found_type, const TypeInfo* typeinfo);
|
||||
|
||||
// Calls WriteTo() on every child in children_.
|
||||
void WriteChildren(ObjectWriter* ow);
|
||||
|
||||
// The name of this node.
|
||||
std::string name_;
|
||||
// google::protobuf::Type of this node. Owned by TypeInfo.
|
||||
const google::protobuf::Type* type_;
|
||||
// The kind of this node.
|
||||
NodeKind kind_;
|
||||
// Whether this is a node for "Any".
|
||||
bool is_any_;
|
||||
// The data of this node when it is a leaf node.
|
||||
DataPiece data_;
|
||||
// Children of this node.
|
||||
std::vector<Node*> children_;
|
||||
// Whether this node is a placeholder for an object or list automatically
|
||||
// generated when creating the parent node. Should be set to false after
|
||||
// the parent node's StartObject()/StartList() method is called with this
|
||||
// node's name.
|
||||
bool is_placeholder_;
|
||||
|
||||
// Path of the field of this node
|
||||
std::vector<std::string> path_;
|
||||
|
||||
// Whether to suppress empty list output.
|
||||
bool suppress_empty_list_;
|
||||
|
||||
// Whether to preserve original proto field names
|
||||
bool preserve_proto_field_names_;
|
||||
|
||||
// Whether to always print enums as ints
|
||||
bool use_ints_for_enums_;
|
||||
|
||||
// Function for determining whether a field needs to be scrubbed or not.
|
||||
FieldScrubCallBack field_scrub_callback_;
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Node);
|
||||
};
|
||||
|
||||
// Creates a new Node and returns it. Caller owns memory of returned object.
|
||||
virtual Node* CreateNewNode(const std::string& name,
|
||||
const google::protobuf::Type* type, NodeKind kind,
|
||||
const DataPiece& data, bool is_placeholder,
|
||||
const std::vector<std::string>& path,
|
||||
bool suppress_empty_list,
|
||||
bool preserve_proto_field_names,
|
||||
bool use_ints_for_enums,
|
||||
FieldScrubCallBack field_scrub_callback);
|
||||
|
||||
// Creates a DataPiece containing the default value of the type of the field.
|
||||
static DataPiece CreateDefaultDataPieceForField(
|
||||
const google::protobuf::Field& field, const TypeInfo* typeinfo) {
|
||||
return CreateDefaultDataPieceForField(field, typeinfo, false);
|
||||
}
|
||||
|
||||
// Same as the above but with a flag to use ints instead of enum names.
|
||||
static DataPiece CreateDefaultDataPieceForField(
|
||||
const google::protobuf::Field& field, const TypeInfo* typeinfo,
|
||||
bool use_ints_for_enums);
|
||||
|
||||
protected:
|
||||
// Returns a pointer to current Node in tree.
|
||||
Node* current() { return current_; }
|
||||
|
||||
private:
|
||||
// Populates children of "node" if it is an "any" Node and its real type has
|
||||
// been given.
|
||||
void MaybePopulateChildrenOfAny(Node* node);
|
||||
|
||||
// Writes the root_ node to ow_ and resets the root_ and current_ pointer to
|
||||
// nullptr.
|
||||
void WriteRoot();
|
||||
|
||||
// Adds or replaces the data_ of a primitive child node.
|
||||
void RenderDataPiece(StringPiece name, const DataPiece& data);
|
||||
|
||||
// Returns the default enum value as a DataPiece, or the first enum value if
|
||||
// there is no default. For proto3, where we cannot specify an explicit
|
||||
// default, a zero value will always be returned.
|
||||
static DataPiece FindEnumDefault(const google::protobuf::Field& field,
|
||||
const TypeInfo* typeinfo,
|
||||
bool use_ints_for_enums);
|
||||
|
||||
// Type information for all the types used in the descriptor. Used to find
|
||||
// google::protobuf::Type of nested messages/enums.
|
||||
const TypeInfo* typeinfo_;
|
||||
// Whether the TypeInfo object is owned by this class.
|
||||
bool own_typeinfo_;
|
||||
// google::protobuf::Type of the root message type.
|
||||
const google::protobuf::Type& type_;
|
||||
// Holds copies of strings passed to RenderString.
|
||||
std::vector<std::unique_ptr<std::string>> string_values_;
|
||||
|
||||
// The current Node. Owned by its parents.
|
||||
Node* current_;
|
||||
// The root Node.
|
||||
std::unique_ptr<Node> root_;
|
||||
// The stack to hold the path of Nodes from current_ to root_;
|
||||
std::stack<Node*> stack_;
|
||||
|
||||
// Whether to suppress output of empty lists.
|
||||
bool suppress_empty_list_;
|
||||
|
||||
// Whether to preserve original proto field names
|
||||
bool preserve_proto_field_names_;
|
||||
|
||||
// Whether to always print enums as ints
|
||||
bool use_ints_for_enums_;
|
||||
|
||||
// Function for determining whether a field needs to be scrubbed or not.
|
||||
FieldScrubCallBack field_scrub_callback_;
|
||||
|
||||
ObjectWriter* ow_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DefaultValueObjectWriter);
|
||||
};
|
||||
|
||||
} // namespace converter
|
||||
} // namespace util
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_UTIL_INTERNAL_DEFAULT_VALUE_OBJECTWRITER_H__
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user