add external dependencies in a pre-built way to avoid incompatibilities

This commit is contained in:
Sven Czarnian
2021-08-09 22:07:00 +02:00
parent 5f702016ad
commit 4cde0f9baf
197 changed files with 74244 additions and 0 deletions

View File

@@ -0,0 +1,108 @@
// 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>
#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__

View File

@@ -0,0 +1,285 @@
// 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>
#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__

View File

@@ -0,0 +1,262 @@
// 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/descriptor.h>
#include <google/protobuf/stubs/strutil.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
// 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__

View File

@@ -0,0 +1,204 @@
// 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.
// Utility functions to convert between protobuf binary format and proto3 JSON
// format.
#ifndef GOOGLE_PROTOBUF_UTIL_JSON_UTIL_H__
#define GOOGLE_PROTOBUF_UTIL_JSON_UTIL_H__
#include <google/protobuf/message.h>
#include <google/protobuf/util/type_resolver.h>
#include <google/protobuf/stubs/bytestream.h>
#include <google/protobuf/stubs/status.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/port_def.inc>
namespace google {
namespace protobuf {
namespace io {
class ZeroCopyInputStream;
class ZeroCopyOutputStream;
} // namespace io
namespace util {
struct JsonParseOptions {
// Whether to ignore unknown JSON fields during parsing
bool ignore_unknown_fields;
// If true, when a lowercase enum value fails to parse, try convert it to
// UPPER_CASE and see if it matches a valid enum.
// WARNING: This option exists only to preserve legacy behavior. Avoid using
// this option. If your enum needs to support different casing, consider using
// allow_alias instead.
bool case_insensitive_enum_parsing;
JsonParseOptions()
: ignore_unknown_fields(false),
case_insensitive_enum_parsing(false) {}
};
struct JsonPrintOptions {
// Whether to add spaces, line breaks and indentation to make the JSON output
// easy to read.
bool add_whitespace;
// Whether to always print primitive fields. By default proto3 primitive
// fields with default values will be omitted in JSON output. For example, an
// int32 field set to 0 will be omitted. Set this flag to true will override
// the default behavior and print primitive fields regardless of their values.
bool always_print_primitive_fields;
// Whether to always print enums as ints. By default they are rendered as
// strings.
bool always_print_enums_as_ints;
// Whether to preserve proto field names
bool preserve_proto_field_names;
JsonPrintOptions()
: add_whitespace(false),
always_print_primitive_fields(false),
always_print_enums_as_ints(false),
preserve_proto_field_names(false) {}
};
// DEPRECATED. Use JsonPrintOptions instead.
typedef JsonPrintOptions JsonOptions;
// Converts from protobuf message to JSON and appends it to |output|. This is a
// simple wrapper of BinaryToJsonString(). It will use the DescriptorPool of the
// passed-in message to resolve Any types.
PROTOBUF_EXPORT util::Status MessageToJsonString(const Message& message,
std::string* output,
const JsonOptions& options);
inline util::Status MessageToJsonString(const Message& message,
std::string* output) {
return MessageToJsonString(message, output, JsonOptions());
}
// Converts from JSON to protobuf message. This is a simple wrapper of
// JsonStringToBinary(). It will use the DescriptorPool of the passed-in
// message to resolve Any types.
PROTOBUF_EXPORT util::Status JsonStringToMessage(
StringPiece input, Message* message, const JsonParseOptions& options);
inline util::Status JsonStringToMessage(StringPiece input,
Message* message) {
return JsonStringToMessage(input, message, JsonParseOptions());
}
// Converts protobuf binary data to JSON.
// The conversion will fail if:
// 1. TypeResolver fails to resolve a type.
// 2. input is not valid protobuf wire format, or conflicts with the type
// information returned by TypeResolver.
// Note that unknown fields will be discarded silently.
PROTOBUF_EXPORT util::Status BinaryToJsonStream(
TypeResolver* resolver, const std::string& type_url,
io::ZeroCopyInputStream* binary_input,
io::ZeroCopyOutputStream* json_output, const JsonPrintOptions& options);
inline util::Status BinaryToJsonStream(TypeResolver* resolver,
const std::string& type_url,
io::ZeroCopyInputStream* binary_input,
io::ZeroCopyOutputStream* json_output) {
return BinaryToJsonStream(resolver, type_url, binary_input, json_output,
JsonPrintOptions());
}
PROTOBUF_EXPORT util::Status BinaryToJsonString(
TypeResolver* resolver, const std::string& type_url,
const std::string& binary_input, std::string* json_output,
const JsonPrintOptions& options);
inline util::Status BinaryToJsonString(TypeResolver* resolver,
const std::string& type_url,
const std::string& binary_input,
std::string* json_output) {
return BinaryToJsonString(resolver, type_url, binary_input, json_output,
JsonPrintOptions());
}
// Converts JSON data to protobuf binary format.
// The conversion will fail if:
// 1. TypeResolver fails to resolve a type.
// 2. input is not valid JSON format, or conflicts with the type
// information returned by TypeResolver.
PROTOBUF_EXPORT util::Status JsonToBinaryStream(
TypeResolver* resolver, const std::string& type_url,
io::ZeroCopyInputStream* json_input,
io::ZeroCopyOutputStream* binary_output, const JsonParseOptions& options);
inline util::Status JsonToBinaryStream(
TypeResolver* resolver, const std::string& type_url,
io::ZeroCopyInputStream* json_input,
io::ZeroCopyOutputStream* binary_output) {
return JsonToBinaryStream(resolver, type_url, json_input, binary_output,
JsonParseOptions());
}
PROTOBUF_EXPORT util::Status JsonToBinaryString(
TypeResolver* resolver, const std::string& type_url,
StringPiece json_input, std::string* binary_output,
const JsonParseOptions& options);
inline util::Status JsonToBinaryString(TypeResolver* resolver,
const std::string& type_url,
StringPiece json_input,
std::string* binary_output) {
return JsonToBinaryString(resolver, type_url, json_input, binary_output,
JsonParseOptions());
}
namespace internal {
// Internal helper class. Put in the header so we can write unit-tests for it.
class PROTOBUF_EXPORT ZeroCopyStreamByteSink : public strings::ByteSink {
public:
explicit ZeroCopyStreamByteSink(io::ZeroCopyOutputStream* stream)
: stream_(stream), buffer_(NULL), buffer_size_(0) {}
~ZeroCopyStreamByteSink();
void Append(const char* bytes, size_t len) override;
private:
io::ZeroCopyOutputStream* stream_;
void* buffer_;
int buffer_size_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ZeroCopyStreamByteSink);
};
} // namespace internal
} // namespace util
} // namespace protobuf
} // namespace google
#include <google/protobuf/port_undef.inc>
#endif // GOOGLE_PROTOBUF_UTIL_JSON_UTIL_H__

View File

@@ -0,0 +1,972 @@
// 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.
//
// This file defines static methods and classes for comparing Protocol
// Messages.
//
// Aug. 2008: Added Unknown Fields Comparison for messages.
// Aug. 2009: Added different options to compare repeated fields.
// Apr. 2010: Moved field comparison to FieldComparator
// Sep. 2020: Added option to output map keys in path
#ifndef GOOGLE_PROTOBUF_UTIL_MESSAGE_DIFFERENCER_H__
#define GOOGLE_PROTOBUF_UTIL_MESSAGE_DIFFERENCER_H__
#include <functional>
#include <map>
#include <memory>
#include <set>
#include <string>
#include <vector>
#include <google/protobuf/descriptor.h> // FieldDescriptor
#include <google/protobuf/message.h> // Message
#include <google/protobuf/unknown_field_set.h>
#include <google/protobuf/util/field_comparator.h>
// Always include as last one, otherwise it can break compilation
#include <google/protobuf/port_def.inc>
namespace google {
namespace protobuf {
class DynamicMessageFactory;
class FieldDescriptor;
namespace io {
class ZeroCopyOutputStream;
class Printer;
} // namespace io
namespace util {
class DefaultFieldComparator;
class FieldContext; // declared below MessageDifferencer
// Defines a collection of field descriptors.
// In case of internal google codebase we are using absl::FixedArray instead
// of vector. It significantly speeds up proto comparison (by ~30%) by
// reducing the number of malloc/free operations
typedef std::vector<const FieldDescriptor*> FieldDescriptorArray;
// A basic differencer that can be used to determine
// the differences between two specified Protocol Messages. If any differences
// are found, the Compare method will return false, and any differencer reporter
// specified via ReportDifferencesTo will have its reporting methods called (see
// below for implementation of the report). Based off of the original
// ProtocolDifferencer implementation in //net/proto/protocol-differencer.h
// (Thanks Todd!).
//
// MessageDifferencer REQUIRES that compared messages be the same type, defined
// as messages that share the same descriptor. If not, the behavior of this
// class is undefined.
//
// People disagree on what MessageDifferencer should do when asked to compare
// messages with different descriptors. Some people think it should always
// return false. Others expect it to try to look for similar fields and
// compare them anyway -- especially if the descriptors happen to be identical.
// If we chose either of these behaviors, some set of people would find it
// surprising, and could end up writing code expecting the other behavior
// without realizing their error. Therefore, we forbid that usage.
//
// This class is implemented based on the proto2 reflection. The performance
// should be good enough for normal usages. However, for places where the
// performance is extremely sensitive, there are several alternatives:
// - Comparing serialized string
// Downside: false negatives (there are messages that are the same but their
// serialized strings are different).
// - Equals code generator by compiler plugin (net/proto2/contrib/equals_plugin)
// Downside: more generated code; maintenance overhead for the additional rule
// (must be in sync with the original proto_library).
//
// Note on handling of google.protobuf.Any: MessageDifferencer automatically
// unpacks Any::value into a Message and compares its individual fields.
// Messages encoded in a repeated Any cannot be compared using TreatAsMap.
//
// Note on thread-safety: MessageDifferencer is *not* thread-safe. You need to
// guard it with a lock to use the same MessageDifferencer instance from
// multiple threads. Note that it's fine to call static comparison methods
// (like MessageDifferencer::Equals) concurrently, but it's not recommended for
// performance critical code as it leads to extra allocations.
class PROTOBUF_EXPORT MessageDifferencer {
public:
// Determines whether the supplied messages are equal. Equality is defined as
// all fields within the two messages being set to the same value. Primitive
// fields and strings are compared by value while embedded messages/groups
// are compared as if via a recursive call. Use Compare() with IgnoreField()
// if some fields should be ignored in the comparison. Use Compare() with
// TreatAsSet() if there are repeated fields where ordering does not matter.
//
// This method REQUIRES that the two messages have the same
// Descriptor (message1.GetDescriptor() == message2.GetDescriptor()).
static bool Equals(const Message& message1, const Message& message2);
// Determines whether the supplied messages are equivalent. Equivalency is
// defined as all fields within the two messages having the same value. This
// differs from the Equals method above in that fields with default values
// are considered set to said value automatically. For details on how default
// values are defined for each field type, see:
// https://developers.google.com/protocol-buffers/docs/proto?csw=1#optional.
// Also, Equivalent() ignores unknown fields. Use IgnoreField() and Compare()
// if some fields should be ignored in the comparison.
//
// This method REQUIRES that the two messages have the same
// Descriptor (message1.GetDescriptor() == message2.GetDescriptor()).
static bool Equivalent(const Message& message1, const Message& message2);
// Determines whether the supplied messages are approximately equal.
// Approximate equality is defined as all fields within the two messages
// being approximately equal. Primitive (non-float) fields and strings are
// compared by value, floats are compared using MathUtil::AlmostEquals() and
// embedded messages/groups are compared as if via a recursive call. Use
// IgnoreField() and Compare() if some fields should be ignored in the
// comparison.
//
// This method REQUIRES that the two messages have the same
// Descriptor (message1.GetDescriptor() == message2.GetDescriptor()).
static bool ApproximatelyEquals(const Message& message1,
const Message& message2);
// Determines whether the supplied messages are approximately equivalent.
// Approximate equivalency is defined as all fields within the two messages
// being approximately equivalent. As in
// MessageDifferencer::ApproximatelyEquals, primitive (non-float) fields and
// strings are compared by value, floats are compared using
// MathUtil::AlmostEquals() and embedded messages/groups are compared as if
// via a recursive call. However, fields with default values are considered
// set to said value, as per MessageDiffencer::Equivalent. Use IgnoreField()
// and Compare() if some fields should be ignored in the comparison.
//
// This method REQUIRES that the two messages have the same
// Descriptor (message1.GetDescriptor() == message2.GetDescriptor()).
static bool ApproximatelyEquivalent(const Message& message1,
const Message& message2);
// Identifies an individual field in a message instance. Used for field_path,
// below.
struct SpecificField {
// For known fields, "field" is filled in and "unknown_field_number" is -1.
// For unknown fields, "field" is NULL, "unknown_field_number" is the field
// number, and "unknown_field_type" is its type.
const FieldDescriptor* field = nullptr;
int unknown_field_number = -1;
UnknownField::Type unknown_field_type = UnknownField::Type::TYPE_VARINT;
// If this a repeated field, "index" is the index within it. For unknown
// fields, this is the index of the field among all unknown fields of the
// same field number and type.
int index = -1;
// If "field" is a repeated field which is being treated as a map or
// a set (see TreatAsMap() and TreatAsSet(), below), new_index indicates
// the index the position to which the element has moved. If the element
// has not moved, "new_index" will have the same value as "index".
int new_index = -1;
// For unknown fields, these are the pointers to the UnknownFieldSet
// containing the unknown fields. In certain cases (e.g. proto1's
// MessageSet, or nested groups of unknown fields), these may differ from
// the messages' internal UnknownFieldSets.
const UnknownFieldSet* unknown_field_set1 = nullptr;
const UnknownFieldSet* unknown_field_set2 = nullptr;
// For unknown fields, these are the index of the field within the
// UnknownFieldSets. One or the other will be -1 when
// reporting an addition or deletion.
int unknown_field_index1 = -1;
int unknown_field_index2 = -1;
};
// Class for processing Any deserialization. This logic is used by both the
// MessageDifferencer and StreamReporter classes.
class UnpackAnyField {
private:
std::unique_ptr<DynamicMessageFactory> dynamic_message_factory_;
public:
UnpackAnyField() = default;
~UnpackAnyField() = default;
// If "any" is of type google.protobuf.Any, extract its payload using
// DynamicMessageFactory and store in "data".
bool UnpackAny(const Message& any, std::unique_ptr<Message>* data);
};
// Abstract base class from which all MessageDifferencer
// reporters derive. The five Report* methods below will be called when
// a field has been added, deleted, modified, moved, or matched. The third
// argument is a vector of FieldDescriptor pointers which describes the chain
// of fields that was taken to find the current field. For example, for a
// field found in an embedded message, the vector will contain two
// FieldDescriptors. The first will be the field of the embedded message
// itself and the second will be the actual field in the embedded message
// that was added/deleted/modified.
// Fields will be reported in PostTraversalOrder.
// For example, given following proto, if both baz and quux are changed.
// foo {
// bar {
// baz: 1
// quux: 2
// }
// }
// ReportModified will be invoked with following order:
// 1. foo.bar.baz or foo.bar.quux
// 2. foo.bar.quux or foo.bar.baz
// 2. foo.bar
// 3. foo
class PROTOBUF_EXPORT Reporter {
public:
Reporter();
virtual ~Reporter();
// Reports that a field has been added into Message2.
virtual void ReportAdded(const Message& message1, const Message& message2,
const std::vector<SpecificField>& field_path) = 0;
// Reports that a field has been deleted from Message1.
virtual void ReportDeleted(
const Message& message1, const Message& message2,
const std::vector<SpecificField>& field_path) = 0;
// Reports that the value of a field has been modified.
virtual void ReportModified(
const Message& message1, const Message& message2,
const std::vector<SpecificField>& field_path) = 0;
// Reports that a repeated field has been moved to another location. This
// only applies when using TreatAsSet or TreatAsMap() -- see below. Also
// note that for any given field, ReportModified and ReportMoved are
// mutually exclusive. If a field has been both moved and modified, then
// only ReportModified will be called.
virtual void ReportMoved(
const Message& /* message1 */, const Message& /* message2 */,
const std::vector<SpecificField>& /* field_path */) {}
// Reports that two fields match. Useful for doing side-by-side diffs.
// This function is mutually exclusive with ReportModified and ReportMoved.
// Note that you must call set_report_matches(true) before calling Compare
// to make use of this function.
virtual void ReportMatched(
const Message& /* message1 */, const Message& /* message2 */,
const std::vector<SpecificField>& /* field_path */) {}
// Reports that two fields would have been compared, but the
// comparison has been skipped because the field was marked as
// 'ignored' using IgnoreField(). This function is mutually
// exclusive with all the other Report() functions.
//
// The contract of ReportIgnored is slightly different than the
// other Report() functions, in that |field_path.back().index| is
// always equal to -1, even if the last field is repeated. This is
// because while the other Report() functions indicate where in a
// repeated field the action (Addition, Deletion, etc...)
// happened, when a repeated field is 'ignored', the differencer
// simply calls ReportIgnored on the repeated field as a whole and
// moves on without looking at its individual elements.
//
// Furthermore, ReportIgnored() does not indicate whether the
// fields were in fact equal or not, as Compare() does not inspect
// these fields at all. It is up to the Reporter to decide whether
// the fields are equal or not (perhaps with a second call to
// Compare()), if it cares.
virtual void ReportIgnored(
const Message& /* message1 */, const Message& /* message2 */,
const std::vector<SpecificField>& /* field_path */) {}
// Report that an unknown field is ignored. (see comment above).
// Note this is a different function since the last SpecificField in field
// path has a null field. This could break existing Reporter.
virtual void ReportUnknownFieldIgnored(
const Message& /* message1 */, const Message& /* message2 */,
const std::vector<SpecificField>& /* field_path */) {}
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Reporter);
};
// MapKeyComparator is used to determine if two elements have the same key
// when comparing elements of a repeated field as a map.
class PROTOBUF_EXPORT MapKeyComparator {
public:
MapKeyComparator();
virtual ~MapKeyComparator();
virtual bool IsMatch(
const Message& /* message1 */, const Message& /* message2 */,
const std::vector<SpecificField>& /* parent_fields */) const {
GOOGLE_CHECK(false) << "IsMatch() is not implemented.";
return false;
}
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapKeyComparator);
};
// Abstract base class from which all IgnoreCriteria derive.
// By adding IgnoreCriteria more complex ignore logic can be implemented.
// IgnoreCriteria are registered with AddIgnoreCriteria. For each compared
// field IsIgnored is called on each added IgnoreCriteria until one returns
// true or all return false.
// IsIgnored is called for fields where at least one side has a value.
class PROTOBUF_EXPORT IgnoreCriteria {
public:
IgnoreCriteria();
virtual ~IgnoreCriteria();
// Returns true if the field should be ignored.
virtual bool IsIgnored(
const Message& /* message1 */, const Message& /* message2 */,
const FieldDescriptor* /* field */,
const std::vector<SpecificField>& /* parent_fields */) = 0;
// Returns true if the unknown field should be ignored.
// Note: This will be called for unknown fields as well in which case
// field.field will be null.
virtual bool IsUnknownFieldIgnored(
const Message& /* message1 */, const Message& /* message2 */,
const SpecificField& /* field */,
const std::vector<SpecificField>& /* parent_fields */) {
return false;
}
};
// To add a Reporter, construct default here, then use ReportDifferencesTo or
// ReportDifferencesToString.
explicit MessageDifferencer();
~MessageDifferencer();
enum MessageFieldComparison {
EQUAL, // Fields must be present in both messages
// for the messages to be considered the same.
EQUIVALENT, // Fields with default values are considered set
// for comparison purposes even if not explicitly
// set in the messages themselves. Unknown fields
// are ignored.
};
enum Scope {
FULL, // All fields of both messages are considered in the comparison.
PARTIAL // Only fields present in the first message are considered; fields
// set only in the second message will be skipped during
// comparison.
};
// DEPRECATED. Use FieldComparator::FloatComparison instead.
enum FloatComparison {
EXACT, // Floats and doubles are compared exactly.
APPROXIMATE // Floats and doubles are compared using the
// MathUtil::AlmostEquals method.
};
enum RepeatedFieldComparison {
AS_LIST, // Repeated fields are compared in order. Differing values at
// the same index are reported using ReportModified(). If the
// repeated fields have different numbers of elements, the
// unpaired elements are reported using ReportAdded() or
// ReportDeleted().
AS_SET, // Treat all the repeated fields as sets.
// See TreatAsSet(), as below.
AS_SMART_LIST, // Similar to AS_SET, but preserve the order and find the
// longest matching sequence from the first matching
// element. To use an optimal solution, call
// SetMatchIndicesForSmartListCallback() to pass it in.
AS_SMART_SET, // Similar to AS_SET, but match elements with fewest diffs.
};
// The elements of the given repeated field will be treated as a set for
// diffing purposes, so different orderings of the same elements will be
// considered equal. Elements which are present on both sides of the
// comparison but which have changed position will be reported with
// ReportMoved(). Elements which only exist on one side or the other are
// reported with ReportAdded() and ReportDeleted() regardless of their
// positions. ReportModified() is never used for this repeated field. If
// the only differences between the compared messages is that some fields
// have been moved, then the comparison returns true.
//
// Note that despite the name of this method, this is really
// comparison as multisets: if one side of the comparison has a duplicate
// in the repeated field but the other side doesn't, this will count as
// a mismatch.
//
// If the scope of comparison is set to PARTIAL, then in addition to what's
// above, extra values added to repeated fields of the second message will
// not cause the comparison to fail.
//
// Note that set comparison is currently O(k * n^2) (where n is the total
// number of elements, and k is the average size of each element). In theory
// it could be made O(n * k) with a more complex hashing implementation. Feel
// free to contribute one if the current implementation is too slow for you.
// If partial matching is also enabled, the time complexity will be O(k * n^2
// + n^3) in which n^3 is the time complexity of the maximum matching
// algorithm.
//
// REQUIRES: field->is_repeated() and field not registered with TreatAsMap*
void TreatAsSet(const FieldDescriptor* field);
void TreatAsSmartSet(const FieldDescriptor* field);
// The elements of the given repeated field will be treated as a list for
// diffing purposes, so different orderings of the same elements will NOT be
// considered equal.
//
// REQUIRES: field->is_repeated() and field not registered with TreatAsMap*
void TreatAsList(const FieldDescriptor* field);
// Note that the complexity is similar to treating as SET.
void TreatAsSmartList(const FieldDescriptor* field);
// The elements of the given repeated field will be treated as a map for
// diffing purposes, with |key| being the map key. Thus, elements with the
// same key will be compared even if they do not appear at the same index.
// Differences are reported similarly to TreatAsSet(), except that
// ReportModified() is used to report elements with the same key but
// different values. Note that if an element is both moved and modified,
// only ReportModified() will be called. As with TreatAsSet, if the only
// differences between the compared messages is that some fields have been
// moved, then the comparison returns true. See TreatAsSet for notes on
// performance.
//
// REQUIRES: field->is_repeated()
// REQUIRES: field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE
// REQUIRES: key->containing_type() == field->message_type()
void TreatAsMap(const FieldDescriptor* field, const FieldDescriptor* key);
// Same as TreatAsMap except that this method will use multiple fields as
// the key in comparison. All specified fields in 'key_fields' should be
// present in the compared elements. Two elements will be treated as having
// the same key iff they have the same value for every specified field. There
// are two steps in the comparison process. The first one is key matching.
// Every element from one message will be compared to every element from
// the other message. Only fields in 'key_fields' are compared in this step
// to decide if two elements have the same key. The second step is value
// comparison. Those pairs of elements with the same key (with equal value
// for every field in 'key_fields') will be compared in this step.
// Time complexity of the first step is O(s * m * n ^ 2) where s is the
// average size of the fields specified in 'key_fields', m is the number of
// fields in 'key_fields' and n is the number of elements. If partial
// matching is enabled, an extra O(n^3) will be incured by the maximum
// matching algorithm. The second step is O(k * n) where k is the average
// size of each element.
void TreatAsMapWithMultipleFieldsAsKey(
const FieldDescriptor* field,
const std::vector<const FieldDescriptor*>& key_fields);
// Same as TreatAsMapWithMultipleFieldsAsKey, except that each of the field
// do not necessarily need to be a direct subfield. Each element in
// key_field_paths indicate a path from the message being compared, listing
// successive subfield to reach the key field.
//
// REQUIRES:
// for key_field_path in key_field_paths:
// key_field_path[0]->containing_type() == field->message_type()
// for i in [0, key_field_path.size() - 1):
// key_field_path[i+1]->containing_type() ==
// key_field_path[i]->message_type()
// key_field_path[i]->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE
// !key_field_path[i]->is_repeated()
void TreatAsMapWithMultipleFieldPathsAsKey(
const FieldDescriptor* field,
const std::vector<std::vector<const FieldDescriptor*> >& key_field_paths);
// Uses a custom MapKeyComparator to determine if two elements have the same
// key when comparing a repeated field as a map.
// The caller is responsible to delete the key_comparator.
// This method varies from TreatAsMapWithMultipleFieldsAsKey only in the
// first key matching step. Rather than comparing some specified fields, it
// will invoke the IsMatch method of the given 'key_comparator' to decide if
// two elements have the same key.
void TreatAsMapUsingKeyComparator(const FieldDescriptor* field,
const MapKeyComparator* key_comparator);
// Initiates and returns a new instance of MultipleFieldsMapKeyComparator.
MapKeyComparator* CreateMultipleFieldsMapKeyComparator(
const std::vector<std::vector<const FieldDescriptor*> >& key_field_paths);
// Add a custom ignore criteria that is evaluated in addition to the
// ignored fields added with IgnoreField.
// Takes ownership of ignore_criteria.
void AddIgnoreCriteria(IgnoreCriteria* ignore_criteria);
// Indicates that any field with the given descriptor should be
// ignored for the purposes of comparing two messages. This applies
// to fields nested in the message structure as well as top level
// ones. When the MessageDifferencer encounters an ignored field,
// ReportIgnored is called on the reporter, if one is specified.
//
// The only place where the field's 'ignored' status is not applied is when
// it is being used as a key in a field passed to TreatAsMap or is one of
// the fields passed to TreatAsMapWithMultipleFieldsAsKey.
// In this case it is compared in key matching but after that it's ignored
// in value comparison.
void IgnoreField(const FieldDescriptor* field);
// Sets the field comparator used to determine differences between protocol
// buffer fields. By default it's set to a DefaultFieldComparator instance.
// MessageDifferencer doesn't take ownership over the passed object.
// Note that this method must be called before Compare for the comparator to
// be used.
void set_field_comparator(FieldComparator* comparator);
#ifdef PROTOBUF_FUTURE_BREAKING_CHANGES
void set_field_comparator(DefaultFieldComparator* comparator);
#endif // PROTOBUF_FUTURE_BREAKING_CHANGES
// DEPRECATED. Pass a DefaultFieldComparator instance instead.
// Sets the fraction and margin for the float comparison of a given field.
// Uses MathUtil::WithinFractionOrMargin to compare the values.
// NOTE: this method does nothing if differencer's field comparator has been
// set to a custom object.
//
// 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 type of comparison (as defined in the MessageFieldComparison
// enumeration above) that is used by this differencer when determining how
// to compare fields in messages.
void set_message_field_comparison(MessageFieldComparison comparison);
// Tells the differencer whether or not to report matches. This method must
// be called before Compare. The default for a new differencer is false.
void set_report_matches(bool report_matches) {
report_matches_ = report_matches;
}
// Tells the differencer whether or not to report moves (in a set or map
// repeated field). This method must be called before Compare. The default for
// a new differencer is true.
void set_report_moves(bool report_moves) { report_moves_ = report_moves; }
// Tells the differencer whether or not to report ignored values. This method
// must be called before Compare. The default for a new differencer is true.
void set_report_ignores(bool report_ignores) {
report_ignores_ = report_ignores;
}
// Sets the scope of the comparison (as defined in the Scope enumeration
// above) that is used by this differencer when determining which fields to
// compare between the messages.
void set_scope(Scope scope);
// Returns the current scope used by this differencer.
Scope scope();
// DEPRECATED. Pass a DefaultFieldComparator instance instead.
// Sets the type of comparison (as defined in the FloatComparison enumeration
// above) that is used by this differencer when comparing float (and double)
// fields in messages.
// NOTE: this method does nothing if differencer's field comparator has been
// set to a custom object.
void set_float_comparison(FloatComparison comparison);
// Sets the type of comparison for repeated field (as defined in the
// RepeatedFieldComparison enumeration above) that is used by this
// differencer when compare repeated fields in messages.
void set_repeated_field_comparison(RepeatedFieldComparison comparison);
// Returns the current repeated field comparison used by this differencer.
RepeatedFieldComparison repeated_field_comparison();
// Compares the two specified messages, returning true if they are the same,
// false otherwise. If this method returns false, any changes between the
// two messages will be reported if a Reporter was specified via
// ReportDifferencesTo (see also ReportDifferencesToString).
//
// This method REQUIRES that the two messages have the same
// Descriptor (message1.GetDescriptor() == message2.GetDescriptor()).
bool Compare(const Message& message1, const Message& message2);
// Same as above, except comparing only the list of fields specified by the
// two vectors of FieldDescriptors.
bool CompareWithFields(
const Message& message1, const Message& message2,
const std::vector<const FieldDescriptor*>& message1_fields,
const std::vector<const FieldDescriptor*>& message2_fields);
// Automatically creates a reporter that will output the differences
// found (if any) to the specified output string pointer. Note that this
// method must be called before Compare.
void ReportDifferencesToString(std::string* output);
// Tells the MessageDifferencer to report differences via the specified
// reporter. Note that this method must be called before Compare for
// the reporter to be used. It is the responsibility of the caller to delete
// this object.
// If the provided pointer equals NULL, the MessageDifferencer stops reporting
// differences to any previously set reporters or output strings.
void ReportDifferencesTo(Reporter* reporter);
// An implementation of the MessageDifferencer Reporter that outputs
// any differences found in human-readable form to the supplied
// ZeroCopyOutputStream or Printer. If a printer is used, the delimiter
// *must* be '$'.
//
// WARNING: this reporter does not necessarily flush its output until it is
// destroyed. As a result, it is not safe to assume the output is valid or
// complete until after you destroy the reporter. For example, if you use a
// StreamReporter to write to a StringOutputStream, the target string may
// contain uninitialized data until the reporter is destroyed.
class PROTOBUF_EXPORT StreamReporter : public Reporter {
public:
explicit StreamReporter(io::ZeroCopyOutputStream* output);
explicit StreamReporter(io::Printer* printer); // delimiter '$'
~StreamReporter() override;
// When set to true, the stream reporter will also output aggregates nodes
// (i.e. messages and groups) whose subfields have been modified. When
// false, will only report the individual subfields. Defaults to false.
void set_report_modified_aggregates(bool report) {
report_modified_aggregates_ = report;
}
// The following are implementations of the methods described above.
void ReportAdded(const Message& message1, const Message& message2,
const std::vector<SpecificField>& field_path) override;
void ReportDeleted(const Message& message1, const Message& message2,
const std::vector<SpecificField>& field_path) override;
void ReportModified(const Message& message1, const Message& message2,
const std::vector<SpecificField>& field_path) override;
void ReportMoved(const Message& message1, const Message& message2,
const std::vector<SpecificField>& field_path) override;
void ReportMatched(const Message& message1, const Message& message2,
const std::vector<SpecificField>& field_path) override;
void ReportIgnored(const Message& message1, const Message& message2,
const std::vector<SpecificField>& field_path) override;
void ReportUnknownFieldIgnored(
const Message& message1, const Message& message2,
const std::vector<SpecificField>& field_path) override;
// Messages that are being compared must be provided to StreamReporter prior
// to processing
void SetMessages(const Message& message1, const Message& message2);
protected:
// Prints the specified path of fields to the buffer.
virtual void PrintPath(const std::vector<SpecificField>& field_path,
bool left_side);
// Prints the value of fields to the buffer. left_side is true if the
// given message is from the left side of the comparison, false if it
// was the right. This is relevant only to decide whether to follow
// unknown_field_index1 or unknown_field_index2 when an unknown field
// is encountered in field_path.
virtual void PrintValue(const Message& message,
const std::vector<SpecificField>& field_path,
bool left_side);
// Prints the specified path of unknown fields to the buffer.
virtual void PrintUnknownFieldValue(const UnknownField* unknown_field);
// Just print a string
void Print(const std::string& str);
// helper function for PrintPath that contains logic for printing maps
void PrintMapKey(const std::vector<SpecificField>& field_path,
bool left_side, const SpecificField& specific_field,
size_t target_field_index);
private:
io::Printer* printer_;
bool delete_printer_;
bool report_modified_aggregates_;
const Message* message1_;
const Message* message2_;
MessageDifferencer::UnpackAnyField unpack_any_field_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StreamReporter);
};
private:
friend class SimpleFieldComparator;
// A MapKeyComparator to be used in TreatAsMapUsingKeyComparator.
// Implementation of this class needs to do field value comparison which
// relies on some private methods of MessageDifferencer. That's why this
// class is declared as a nested class of MessageDifferencer.
class MultipleFieldsMapKeyComparator;
// A MapKeyComparator for use with map_entries.
class PROTOBUF_EXPORT MapEntryKeyComparator : public MapKeyComparator {
public:
explicit MapEntryKeyComparator(MessageDifferencer* message_differencer);
bool IsMatch(
const Message& message1, const Message& message2,
const std::vector<SpecificField>& parent_fields) const override;
private:
MessageDifferencer* message_differencer_;
};
// Returns true if field1's number() is less than field2's.
static bool FieldBefore(const FieldDescriptor* field1,
const FieldDescriptor* field2);
// Retrieve all the set fields, including extensions.
FieldDescriptorArray RetrieveFields(const Message& message,
bool base_message);
// Combine the two lists of fields into the combined_fields output vector.
// All fields present in both lists will always be included in the combined
// list. Fields only present in one of the lists will only appear in the
// combined list if the corresponding fields_scope option is set to FULL.
FieldDescriptorArray CombineFields(const FieldDescriptorArray& fields1,
Scope fields1_scope,
const FieldDescriptorArray& fields2,
Scope fields2_scope);
// Internal version of the Compare method which performs the actual
// comparison. The parent_fields vector is a vector containing field
// descriptors of all fields accessed to get to this comparison operation
// (i.e. if the current message is an embedded message, the parent_fields
// vector will contain the field that has this embedded message).
bool Compare(const Message& message1, const Message& message2,
std::vector<SpecificField>* parent_fields);
// Compares all the unknown fields in two messages.
bool CompareUnknownFields(const Message& message1, const Message& message2,
const UnknownFieldSet&, const UnknownFieldSet&,
std::vector<SpecificField>* parent_fields);
// Compares the specified messages for the requested field lists. The field
// lists are modified depending on comparison settings, and then passed to
// CompareWithFieldsInternal.
bool CompareRequestedFieldsUsingSettings(
const Message& message1, const Message& message2,
const FieldDescriptorArray& message1_fields,
const FieldDescriptorArray& message2_fields,
std::vector<SpecificField>* parent_fields);
// Compares the specified messages with the specified field lists.
bool CompareWithFieldsInternal(const Message& message1,
const Message& message2,
const FieldDescriptorArray& message1_fields,
const FieldDescriptorArray& message2_fields,
std::vector<SpecificField>* parent_fields);
// Compares the repeated fields, and report the error.
bool CompareRepeatedField(const Message& message1, const Message& message2,
const FieldDescriptor* field,
std::vector<SpecificField>* parent_fields);
// Compares map fields, and report the error.
bool CompareMapField(const Message& message1, const Message& message2,
const FieldDescriptor* field,
std::vector<SpecificField>* parent_fields);
// Helper for CompareRepeatedField and CompareMapField: compares and reports
// differences element-wise. This is the implementation for non-map fields,
// and can also compare map fields by using the underlying representation.
bool CompareRepeatedRep(const Message& message1, const Message& message2,
const FieldDescriptor* field,
std::vector<SpecificField>* parent_fields);
// Helper for CompareMapField: compare the map fields using map reflection
// instead of sync to repeated.
bool CompareMapFieldByMapReflection(const Message& message1,
const Message& message2,
const FieldDescriptor* field,
std::vector<SpecificField>* parent_fields,
DefaultFieldComparator* comparator);
// Shorthand for CompareFieldValueUsingParentFields with NULL parent_fields.
bool CompareFieldValue(const Message& message1, const Message& message2,
const FieldDescriptor* field, int index1, int index2);
// Compares the specified field on the two messages, returning
// true if they are the same, false otherwise. For repeated fields,
// this method only compares the value in the specified index. This method
// uses Compare functions to recurse into submessages.
// The parent_fields vector is used in calls to a Reporter instance calls.
// It can be NULL, in which case the MessageDifferencer will create new
// list of parent messages if it needs to recursively compare the given field.
// To avoid confusing users you should not set it to NULL unless you modified
// Reporter to handle the change of parent_fields correctly.
bool CompareFieldValueUsingParentFields(
const Message& message1, const Message& message2,
const FieldDescriptor* field, int index1, int index2,
std::vector<SpecificField>* parent_fields);
// Compares the specified field on the two messages, returning comparison
// result, as returned by appropriate FieldComparator.
FieldComparator::ComparisonResult GetFieldComparisonResult(
const Message& message1, const Message& message2,
const FieldDescriptor* field, int index1, int index2,
const FieldContext* field_context);
// Check if the two elements in the repeated field are match to each other.
// if the key_comprator is NULL, this function returns true when the two
// elements are equal.
bool IsMatch(const FieldDescriptor* repeated_field,
const MapKeyComparator* key_comparator, const Message* message1,
const Message* message2,
const std::vector<SpecificField>& parent_fields,
Reporter* reporter, int index1, int index2);
// Returns true when this repeated field has been configured to be treated
// as a Set / SmartSet / SmartList.
bool IsTreatedAsSet(const FieldDescriptor* field);
bool IsTreatedAsSmartSet(const FieldDescriptor* field);
bool IsTreatedAsSmartList(const FieldDescriptor* field);
// When treating as SMART_LIST, it uses MatchIndicesPostProcessorForSmartList
// by default to find the longest matching sequence from the first matching
// element. The callback takes two vectors showing the matching indices from
// the other vector, where -1 means an unmatch.
void SetMatchIndicesForSmartListCallback(
std::function<void(std::vector<int>*, std::vector<int>*)> callback);
// Returns true when this repeated field is to be compared as a subset, ie.
// has been configured to be treated as a set or map and scope is set to
// PARTIAL.
bool IsTreatedAsSubset(const FieldDescriptor* field);
// Returns true if this field is to be ignored when this
// MessageDifferencer compares messages.
bool IsIgnored(const Message& message1, const Message& message2,
const FieldDescriptor* field,
const std::vector<SpecificField>& parent_fields);
// Returns true if this unknown field is to be ignored when this
// MessageDifferencer compares messages.
bool IsUnknownFieldIgnored(const Message& message1, const Message& message2,
const SpecificField& field,
const std::vector<SpecificField>& parent_fields);
// Returns MapKeyComparator* when this field has been configured to be treated
// as a map or its is_map() return true. If not, returns NULL.
const MapKeyComparator* GetMapKeyComparator(
const FieldDescriptor* field) const;
// Attempts to match indices of a repeated field, so that the contained values
// match. Clears output vectors and sets their values to indices of paired
// messages, ie. if message1[0] matches message2[1], then match_list1[0] == 1
// and match_list2[1] == 0. The unmatched indices are indicated by -1.
// Assumes the repeated field is not treated as a simple list.
// This method returns false if the match failed. However, it doesn't mean
// that the comparison succeeds when this method returns true (you need to
// double-check in this case).
bool MatchRepeatedFieldIndices(
const Message& message1, const Message& message2,
const FieldDescriptor* repeated_field,
const MapKeyComparator* key_comparator,
const std::vector<SpecificField>& parent_fields,
std::vector<int>* match_list1, std::vector<int>* match_list2);
// Checks if index is equal to new_index in all the specific fields.
static bool CheckPathChanged(const std::vector<SpecificField>& parent_fields);
// CHECKs that the given repeated field can be compared according to
// new_comparison.
void CheckRepeatedFieldComparisons(
const FieldDescriptor* field,
const RepeatedFieldComparison& new_comparison);
// Defines a map between field descriptors and their MapKeyComparators.
// Used for repeated fields when they are configured as TreatAsMap.
typedef std::map<const FieldDescriptor*, const MapKeyComparator*>
FieldKeyComparatorMap;
// Defines a set to store field descriptors. Used for repeated fields when
// they are configured as TreatAsSet.
typedef std::set<const FieldDescriptor*> FieldSet;
typedef std::map<const FieldDescriptor*, RepeatedFieldComparison> FieldMap;
Reporter* reporter_;
DefaultFieldComparator default_field_comparator_;
MessageFieldComparison message_field_comparison_;
Scope scope_;
RepeatedFieldComparison repeated_field_comparison_;
FieldMap repeated_field_comparisons_;
// Keeps track of MapKeyComparators that are created within
// MessageDifferencer. These MapKeyComparators should be deleted
// before MessageDifferencer is destroyed.
// When TreatAsMap or TreatAsMapWithMultipleFieldsAsKey is called, we don't
// store the supplied FieldDescriptors directly. Instead, a new
// MapKeyComparator is created for comparison purpose.
std::vector<MapKeyComparator*> owned_key_comparators_;
FieldKeyComparatorMap map_field_key_comparator_;
MapEntryKeyComparator map_entry_key_comparator_;
std::vector<IgnoreCriteria*> ignore_criteria_;
// Reused multiple times in RetrieveFields to avoid extra allocations
std::vector<const FieldDescriptor*> tmp_message_fields_;
FieldSet ignored_fields_;
union {
DefaultFieldComparator* default_impl;
FieldComparator* base;
} field_comparator_ = {&default_field_comparator_};
enum { kFCDefault, kFCBase } field_comparator_kind_ = kFCDefault;
bool report_matches_;
bool report_moves_;
bool report_ignores_;
std::string* output_string_;
// Callback to post-process the matched indices to support SMART_LIST.
std::function<void(std::vector<int>*, std::vector<int>*)>
match_indices_for_smart_list_callback_;
MessageDifferencer::UnpackAnyField unpack_any_field_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageDifferencer);
};
// This class provides extra information to the FieldComparator::Compare
// function.
class PROTOBUF_EXPORT FieldContext {
public:
explicit FieldContext(
std::vector<MessageDifferencer::SpecificField>* parent_fields)
: parent_fields_(parent_fields) {}
std::vector<MessageDifferencer::SpecificField>* parent_fields() const {
return parent_fields_;
}
private:
std::vector<MessageDifferencer::SpecificField>* parent_fields_;
};
} // namespace util
} // namespace protobuf
} // namespace google
#include <google/protobuf/port_undef.inc>
#endif // GOOGLE_PROTOBUF_UTIL_MESSAGE_DIFFERENCER_H__

View File

@@ -0,0 +1,313 @@
// 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 Timestamp and Duration well known types.
#ifndef GOOGLE_PROTOBUF_UTIL_TIME_UTIL_H__
#define GOOGLE_PROTOBUF_UTIL_TIME_UTIL_H__
#include <cstdint>
#include <ctime>
#include <ostream>
#include <string>
#ifdef _MSC_VER
#ifdef _XBOX_ONE
struct timeval {
int64 tv_sec; /* seconds */
int64 tv_usec; /* and microseconds */
};
#else
#include <winsock2.h>
#endif // _XBOX_ONE
#else
#include <sys/time.h>
#endif
#include <google/protobuf/duration.pb.h>
#include <google/protobuf/timestamp.pb.h>
#include <google/protobuf/port_def.inc>
namespace google {
namespace protobuf {
namespace util {
// Utility functions for Timestamp and Duration.
class PROTOBUF_EXPORT TimeUtil {
typedef google::protobuf::Timestamp Timestamp;
typedef google::protobuf::Duration Duration;
public:
// The min/max Timestamp/Duration values we support.
//
// For "0001-01-01T00:00:00Z".
static const int64_t kTimestampMinSeconds = -62135596800LL;
// For "9999-12-31T23:59:59.999999999Z".
static const int64_t kTimestampMaxSeconds = 253402300799LL;
static const int64_t kDurationMinSeconds = -315576000000LL;
static const int64_t kDurationMaxSeconds = 315576000000LL;
// Converts Timestamp to/from RFC 3339 date string format.
// Generated output will always be Z-normalized and uses 3, 6 or 9
// fractional digits as required to represent the exact time. When
// parsing, any fractional digits (or none) and any offset are
// accepted as long as they fit into nano-seconds precision.
// Note that Timestamp can only represent time from
// 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. Converting
// a Timestamp outside of this range is undefined behavior.
// See https://www.ietf.org/rfc/rfc3339.txt
//
// Example of generated format:
// "1972-01-01T10:00:20.021Z"
//
// Example of accepted format:
// "1972-01-01T10:00:20.021-05:00"
static std::string ToString(const Timestamp& timestamp);
static bool FromString(const std::string& value, Timestamp* timestamp);
// Converts Duration to/from string format. The string format will contains
// 3, 6, or 9 fractional digits depending on the precision required to
// represent the exact Duration value. For example:
// "1s", "1.010s", "1.000000100s", "-3.100s"
// The range that can be represented by Duration is from -315,576,000,000
// to +315,576,000,000 inclusive (in seconds).
static std::string ToString(const Duration& duration);
static bool FromString(const std::string& value, Duration* timestamp);
#ifdef GetCurrentTime
#undef GetCurrentTime // Visual Studio has macro GetCurrentTime
#endif
// Gets the current UTC time.
static Timestamp GetCurrentTime();
// Returns the Time representing "1970-01-01 00:00:00".
static Timestamp GetEpoch();
// Converts between Duration and integer types. The behavior is undefined if
// the input value is not in the valid range of Duration.
static Duration NanosecondsToDuration(int64_t nanos);
static Duration MicrosecondsToDuration(int64_t micros);
static Duration MillisecondsToDuration(int64_t millis);
static Duration SecondsToDuration(int64_t seconds);
static Duration MinutesToDuration(int64_t minutes);
static Duration HoursToDuration(int64_t hours);
// Result will be truncated towards zero. For example, "-1.5s" will be
// truncated to "-1s", and "1.5s" to "1s" when converting to seconds.
// It's undefined behavior if the input duration is not valid or the result
// exceeds the range of int64. A duration is not valid if it's not in the
// valid range of Duration, or have an invalid nanos value (i.e., larger
// than 999999999, less than -999999999, or have a different sign from the
// seconds part).
static int64_t DurationToNanoseconds(const Duration& duration);
static int64_t DurationToMicroseconds(const Duration& duration);
static int64_t DurationToMilliseconds(const Duration& duration);
static int64_t DurationToSeconds(const Duration& duration);
static int64_t DurationToMinutes(const Duration& duration);
static int64_t DurationToHours(const Duration& duration);
// Creates Timestamp from integer types. The integer value indicates the
// time elapsed from Epoch time. The behavior is undefined if the input
// value is not in the valid range of Timestamp.
static Timestamp NanosecondsToTimestamp(int64_t nanos);
static Timestamp MicrosecondsToTimestamp(int64_t micros);
static Timestamp MillisecondsToTimestamp(int64_t millis);
static Timestamp SecondsToTimestamp(int64_t seconds);
// Result will be truncated down to the nearest integer value. For example,
// with "1969-12-31T23:59:59.9Z", TimestampToMilliseconds() returns -100
// and TimestampToSeconds() returns -1. It's undefined behavior if the input
// Timestamp is not valid (i.e., its seconds part or nanos part does not fall
// in the valid range) or the return value doesn't fit into int64.
static int64_t TimestampToNanoseconds(const Timestamp& timestamp);
static int64_t TimestampToMicroseconds(const Timestamp& timestamp);
static int64_t TimestampToMilliseconds(const Timestamp& timestamp);
static int64_t TimestampToSeconds(const Timestamp& timestamp);
// Conversion to/from other time/date types. Note that these types may
// have a different precision and time range from Timestamp/Duration.
// When converting to a lower precision type, the value will be truncated
// to the nearest value that can be represented. If the value is
// out of the range of the result type, the return value is undefined.
//
// Conversion to/from time_t
static Timestamp TimeTToTimestamp(time_t value);
static time_t TimestampToTimeT(const Timestamp& value);
// Conversion to/from timeval
static Timestamp TimevalToTimestamp(const timeval& value);
static timeval TimestampToTimeval(const Timestamp& value);
static Duration TimevalToDuration(const timeval& value);
static timeval DurationToTimeval(const Duration& value);
};
} // namespace util
} // namespace protobuf
} // namespace google
namespace google {
namespace protobuf {
// Overloaded operators for Duration.
//
// Assignment operators.
PROTOBUF_EXPORT Duration& operator+=(Duration& d1,
const Duration& d2); // NOLINT
PROTOBUF_EXPORT Duration& operator-=(Duration& d1,
const Duration& d2); // NOLINT
PROTOBUF_EXPORT Duration& operator*=(Duration& d, int64_t r); // NOLINT
PROTOBUF_EXPORT Duration& operator*=(Duration& d, double r); // NOLINT
PROTOBUF_EXPORT Duration& operator/=(Duration& d, int64_t r); // NOLINT
PROTOBUF_EXPORT Duration& operator/=(Duration& d, double r); // NOLINT
// Overload for other integer types.
template <typename T>
Duration& operator*=(Duration& d, T r) { // NOLINT
int64_t x = r;
return d *= x;
}
template <typename T>
Duration& operator/=(Duration& d, T r) { // NOLINT
int64_t x = r;
return d /= x;
}
PROTOBUF_EXPORT Duration& operator%=(Duration& d1,
const Duration& d2); // NOLINT
// Relational operators.
inline bool operator<(const Duration& d1, const Duration& d2) {
if (d1.seconds() == d2.seconds()) {
return d1.nanos() < d2.nanos();
}
return d1.seconds() < d2.seconds();
}
inline bool operator>(const Duration& d1, const Duration& d2) {
return d2 < d1;
}
inline bool operator>=(const Duration& d1, const Duration& d2) {
return !(d1 < d2);
}
inline bool operator<=(const Duration& d1, const Duration& d2) {
return !(d2 < d1);
}
inline bool operator==(const Duration& d1, const Duration& d2) {
return d1.seconds() == d2.seconds() && d1.nanos() == d2.nanos();
}
inline bool operator!=(const Duration& d1, const Duration& d2) {
return !(d1 == d2);
}
// Additive operators
inline Duration operator-(const Duration& d) {
Duration result;
result.set_seconds(-d.seconds());
result.set_nanos(-d.nanos());
return result;
}
inline Duration operator+(const Duration& d1, const Duration& d2) {
Duration result = d1;
return result += d2;
}
inline Duration operator-(const Duration& d1, const Duration& d2) {
Duration result = d1;
return result -= d2;
}
// Multiplicative operators
template <typename T>
inline Duration operator*(Duration d, T r) {
return d *= r;
}
template <typename T>
inline Duration operator*(T r, Duration d) {
return d *= r;
}
template <typename T>
inline Duration operator/(Duration d, T r) {
return d /= r;
}
PROTOBUF_EXPORT int64_t operator/(const Duration& d1, const Duration& d2);
inline Duration operator%(const Duration& d1, const Duration& d2) {
Duration result = d1;
return result %= d2;
}
inline std::ostream& operator<<(std::ostream& out, const Duration& d) {
out << ::PROTOBUF_NAMESPACE_ID::util::TimeUtil::ToString(d);
return out;
}
// Overloaded operators for Timestamp
//
// Assignment operators.
PROTOBUF_EXPORT Timestamp& operator+=(Timestamp& t,
const Duration& d); // NOLINT
PROTOBUF_EXPORT Timestamp& operator-=(Timestamp& t,
const Duration& d); // NOLINT
// Relational operators.
inline bool operator<(const Timestamp& t1, const Timestamp& t2) {
if (t1.seconds() == t2.seconds()) {
return t1.nanos() < t2.nanos();
}
return t1.seconds() < t2.seconds();
}
inline bool operator>(const Timestamp& t1, const Timestamp& t2) {
return t2 < t1;
}
inline bool operator>=(const Timestamp& t1, const Timestamp& t2) {
return !(t1 < t2);
}
inline bool operator<=(const Timestamp& t1, const Timestamp& t2) {
return !(t2 < t1);
}
inline bool operator==(const Timestamp& t1, const Timestamp& t2) {
return t1.seconds() == t2.seconds() && t1.nanos() == t2.nanos();
}
inline bool operator!=(const Timestamp& t1, const Timestamp& t2) {
return !(t1 == t2);
}
// Additive operators.
inline Timestamp operator+(const Timestamp& t, const Duration& d) {
Timestamp result = t;
return result += d;
}
inline Timestamp operator+(const Duration& d, const Timestamp& t) {
Timestamp result = t;
return result += d;
}
inline Timestamp operator-(const Timestamp& t, const Duration& d) {
Timestamp result = t;
return result -= d;
}
PROTOBUF_EXPORT Duration operator-(const Timestamp& t1, const Timestamp& t2);
inline std::ostream& operator<<(std::ostream& out, const Timestamp& t) {
out << ::PROTOBUF_NAMESPACE_ID::util::TimeUtil::ToString(t);
return out;
}
} // namespace protobuf
} // namespace google
#include <google/protobuf/port_undef.inc>
#endif // GOOGLE_PROTOBUF_UTIL_TIME_UTIL_H__

View File

@@ -0,0 +1,76 @@
// 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 a TypeResolver for the Any message.
#ifndef GOOGLE_PROTOBUF_UTIL_TYPE_RESOLVER_H__
#define GOOGLE_PROTOBUF_UTIL_TYPE_RESOLVER_H__
#include <string>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/type.pb.h>
#include <google/protobuf/stubs/status.h>
#include <google/protobuf/stubs/status.h>
#include <google/protobuf/port_def.inc>
namespace google {
namespace protobuf {
class DescriptorPool;
namespace util {
// Abstract interface for a type resolver.
//
// Implementations of this interface must be thread-safe.
class PROTOBUF_EXPORT TypeResolver {
public:
TypeResolver() {}
virtual ~TypeResolver() {}
// Resolves a type url for a message type.
virtual util::Status ResolveMessageType(
const std::string& type_url, google::protobuf::Type* message_type) = 0;
// Resolves a type url for an enum type.
virtual util::Status ResolveEnumType(const std::string& type_url,
google::protobuf::Enum* enum_type) = 0;
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TypeResolver);
};
} // namespace util
} // namespace protobuf
} // namespace google
#include <google/protobuf/port_undef.inc>
#endif // GOOGLE_PROTOBUF_UTIL_TYPE_RESOLVER_H__

View File

@@ -0,0 +1,57 @@
// 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 TypeResolver.
#ifndef GOOGLE_PROTOBUF_UTIL_TYPE_RESOLVER_UTIL_H__
#define GOOGLE_PROTOBUF_UTIL_TYPE_RESOLVER_UTIL_H__
#include <string>
namespace google {
namespace protobuf {
class DescriptorPool;
namespace util {
class TypeResolver;
#include <google/protobuf/port_def.inc>
// Creates a TypeResolver that serves type information in the given descriptor
// pool. Caller takes ownership of the returned TypeResolver.
PROTOBUF_EXPORT TypeResolver* NewTypeResolverForDescriptorPool(
const std::string& url_prefix, const DescriptorPool* pool);
} // namespace util
} // namespace protobuf
} // namespace google
#include <google/protobuf/port_undef.inc>
#endif // GOOGLE_PROTOBUF_UTIL_TYPE_RESOLVER_UTIL_H__