diff options
author | monster <monster@ydb.tech> | 2022-07-07 14:41:37 +0300 |
---|---|---|
committer | monster <monster@ydb.tech> | 2022-07-07 14:41:37 +0300 |
commit | 06e5c21a835c0e923506c4ff27929f34e00761c2 (patch) | |
tree | 75efcbc6854ef9bd476eb8bf00cc5c900da436a2 /contrib/libs/protobuf_std/src/google/protobuf/util | |
parent | 03f024c4412e3aa613bb543cf1660176320ba8f4 (diff) | |
download | ydb-06e5c21a835c0e923506c4ff27929f34e00761c2.tar.gz |
fix ya.make
Diffstat (limited to 'contrib/libs/protobuf_std/src/google/protobuf/util')
47 files changed, 0 insertions, 17063 deletions
diff --git a/contrib/libs/protobuf_std/src/google/protobuf/util/delimited_message_util.cc b/contrib/libs/protobuf_std/src/google/protobuf/util/delimited_message_util.cc deleted file mode 100644 index 80cab309be..0000000000 --- a/contrib/libs/protobuf_std/src/google/protobuf/util/delimited_message_util.cc +++ /dev/null @@ -1,127 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Adapted from the patch of kenton@google.com (Kenton Varda) -// See https://github.com/protocolbuffers/protobuf/pull/710 for details. - -#include <google/protobuf/util/delimited_message_util.h> -#include <google/protobuf/io/coded_stream.h> - -namespace google { -namespace protobuf { -namespace util { - -bool SerializeDelimitedToFileDescriptor(const MessageLite& message, - int file_descriptor) { - io::FileOutputStream output(file_descriptor); - return SerializeDelimitedToZeroCopyStream(message, &output); -} - -bool SerializeDelimitedToOstream(const MessageLite& message, - std::ostream* output) { - { - io::OstreamOutputStream zero_copy_output(output); - if (!SerializeDelimitedToZeroCopyStream(message, &zero_copy_output)) - return false; - } - return output->good(); -} - -bool ParseDelimitedFromZeroCopyStream(MessageLite* message, - io::ZeroCopyInputStream* input, - bool* clean_eof) { - io::CodedInputStream coded_input(input); - return ParseDelimitedFromCodedStream(message, &coded_input, clean_eof); -} - -bool ParseDelimitedFromCodedStream(MessageLite* message, - io::CodedInputStream* input, - bool* clean_eof) { - if (clean_eof != NULL) *clean_eof = false; - int start = input->CurrentPosition(); - - // Read the size. - uint32 size; - if (!input->ReadVarint32(&size)) { - if (clean_eof != NULL) *clean_eof = input->CurrentPosition() == start; - return false; - } - - // Get the position after any size bytes have been read (and only the message - // itself remains). - int position_after_size = input->CurrentPosition(); - - // Tell the stream not to read beyond that size. - io::CodedInputStream::Limit limit = input->PushLimit(size); - - // Parse the message. - if (!message->MergeFromCodedStream(input)) return false; - if (!input->ConsumedEntireMessage()) return false; - if (input->CurrentPosition() - position_after_size != static_cast<int>(size)) - return false; - - // Release the limit. - input->PopLimit(limit); - - return true; -} - -bool SerializeDelimitedToZeroCopyStream(const MessageLite& message, - io::ZeroCopyOutputStream* output) { - io::CodedOutputStream coded_output(output); - return SerializeDelimitedToCodedStream(message, &coded_output); -} - -bool SerializeDelimitedToCodedStream(const MessageLite& message, - io::CodedOutputStream* output) { - // Write the size. - size_t size = message.ByteSizeLong(); - if (size > INT_MAX) return false; - - output->WriteVarint32(size); - - // Write the content. - uint8* buffer = output->GetDirectBufferForNBytesAndAdvance(size); - if (buffer != NULL) { - // Optimization: The message fits in one buffer, so use the faster - // direct-to-array serialization path. - message.SerializeWithCachedSizesToArray(buffer); - } else { - // Slightly-slower path when the message is multiple buffers. - message.SerializeWithCachedSizes(output); - if (output->HadError()) return false; - } - - return true; -} - -} // namespace util -} // namespace protobuf -} // namespace google diff --git a/contrib/libs/protobuf_std/src/google/protobuf/util/delimited_message_util.h b/contrib/libs/protobuf_std/src/google/protobuf/util/delimited_message_util.h deleted file mode 100644 index d3f7dbe8ad..0000000000 --- a/contrib/libs/protobuf_std/src/google/protobuf/util/delimited_message_util.h +++ /dev/null @@ -1,108 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Adapted from the patch of kenton@google.com (Kenton Varda) -// See https://github.com/protocolbuffers/protobuf/pull/710 for details. - -#ifndef GOOGLE_PROTOBUF_UTIL_DELIMITED_MESSAGE_UTIL_H__ -#define GOOGLE_PROTOBUF_UTIL_DELIMITED_MESSAGE_UTIL_H__ - - -#include <ostream> - -#include <google/protobuf/message_lite.h> -#include <google/protobuf/io/coded_stream.h> -#include <google/protobuf/io/zero_copy_stream_impl.h> - -#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__ diff --git a/contrib/libs/protobuf_std/src/google/protobuf/util/field_comparator.cc b/contrib/libs/protobuf_std/src/google/protobuf/util/field_comparator.cc deleted file mode 100644 index 46d5dbaf3d..0000000000 --- a/contrib/libs/protobuf_std/src/google/protobuf/util/field_comparator.cc +++ /dev/null @@ -1,210 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: ksroka@google.com (Krzysztof Sroka) - -#include <google/protobuf/util/field_comparator.h> - -#include <limits> -#include <string> - -#include <google/protobuf/descriptor.h> -#include <google/protobuf/message.h> -#include <google/protobuf/util/message_differencer.h> -#include <google/protobuf/stubs/map_util.h> -#include <google/protobuf/stubs/mathutil.h> - -namespace google { -namespace protobuf { -namespace util { - -FieldComparator::FieldComparator() {} -FieldComparator::~FieldComparator() {} - -SimpleFieldComparator::SimpleFieldComparator() - : float_comparison_(EXACT), - treat_nan_as_equal_(false), - has_default_tolerance_(false) {} - -SimpleFieldComparator::~SimpleFieldComparator() {} - -FieldComparator::ComparisonResult SimpleFieldComparator::SimpleCompare( - const Message& message_1, const Message& message_2, - const FieldDescriptor* field, int index_1, int index_2, - const util::FieldContext* field_context) { - const Reflection* reflection_1 = message_1.GetReflection(); - const Reflection* reflection_2 = message_2.GetReflection(); - - switch (field->cpp_type()) { -#define COMPARE_FIELD(METHOD) \ - if (field->is_repeated()) { \ - return ResultFromBoolean(Compare##METHOD( \ - *field, reflection_1->GetRepeated##METHOD(message_1, field, index_1), \ - reflection_2->GetRepeated##METHOD(message_2, field, index_2))); \ - } else { \ - return ResultFromBoolean( \ - Compare##METHOD(*field, reflection_1->Get##METHOD(message_1, field), \ - reflection_2->Get##METHOD(message_2, field))); \ - } \ - break; // Make sure no fall-through is introduced. - - case FieldDescriptor::CPPTYPE_BOOL: - COMPARE_FIELD(Bool); - case FieldDescriptor::CPPTYPE_DOUBLE: - COMPARE_FIELD(Double); - case FieldDescriptor::CPPTYPE_ENUM: - COMPARE_FIELD(Enum); - case FieldDescriptor::CPPTYPE_FLOAT: - COMPARE_FIELD(Float); - case FieldDescriptor::CPPTYPE_INT32: - COMPARE_FIELD(Int32); - case FieldDescriptor::CPPTYPE_INT64: - COMPARE_FIELD(Int64); - case FieldDescriptor::CPPTYPE_STRING: - if (field->is_repeated()) { - // Allocate scratch strings to store the result if a conversion is - // needed. - std::string scratch1; - std::string scratch2; - return ResultFromBoolean( - CompareString(*field, - reflection_1->GetRepeatedStringReference( - message_1, field, index_1, &scratch1), - reflection_2->GetRepeatedStringReference( - message_2, field, index_2, &scratch2))); - } else { - // Allocate scratch strings to store the result if a conversion is - // needed. - std::string scratch1; - std::string scratch2; - return ResultFromBoolean(CompareString( - *field, - reflection_1->GetStringReference(message_1, field, &scratch1), - reflection_2->GetStringReference(message_2, field, &scratch2))); - } - break; - case FieldDescriptor::CPPTYPE_UINT32: - COMPARE_FIELD(UInt32); - case FieldDescriptor::CPPTYPE_UINT64: - COMPARE_FIELD(UInt64); - -#undef COMPARE_FIELD - - case FieldDescriptor::CPPTYPE_MESSAGE: - return RECURSE; - - default: - GOOGLE_LOG(FATAL) << "No comparison code for field " << field->full_name() - << " of CppType = " << field->cpp_type(); - return DIFFERENT; - } -} - -bool SimpleFieldComparator::CompareWithDifferencer( - MessageDifferencer* differencer, const Message& message1, - const Message& message2, const util::FieldContext* field_context) { - return differencer->Compare(message1, message2, - field_context->parent_fields()); -} - -void SimpleFieldComparator::SetDefaultFractionAndMargin(double fraction, - double margin) { - default_tolerance_ = Tolerance(fraction, margin); - has_default_tolerance_ = true; -} - -void SimpleFieldComparator::SetFractionAndMargin(const FieldDescriptor* field, - double fraction, - double margin) { - GOOGLE_CHECK(FieldDescriptor::CPPTYPE_FLOAT == field->cpp_type() || - FieldDescriptor::CPPTYPE_DOUBLE == field->cpp_type()) - << "Field has to be float or double type. Field name is: " - << field->full_name(); - map_tolerance_[field] = Tolerance(fraction, margin); -} - -bool SimpleFieldComparator::CompareDouble(const FieldDescriptor& field, - double value_1, double value_2) { - return CompareDoubleOrFloat(field, value_1, value_2); -} - -bool SimpleFieldComparator::CompareEnum(const FieldDescriptor& field, - const EnumValueDescriptor* value_1, - const EnumValueDescriptor* value_2) { - return value_1->number() == value_2->number(); -} - -bool SimpleFieldComparator::CompareFloat(const FieldDescriptor& field, - float value_1, float value_2) { - return CompareDoubleOrFloat(field, value_1, value_2); -} - -template <typename T> -bool SimpleFieldComparator::CompareDoubleOrFloat(const FieldDescriptor& field, - T value_1, T value_2) { - if (value_1 == value_2) { - // Covers +inf and -inf (which are not within margin or fraction of - // themselves), and is a shortcut for finite values. - return true; - } else if (float_comparison_ == EXACT) { - if (treat_nan_as_equal_ && std::isnan(value_1) && std::isnan(value_2)) { - return true; - } - return false; - } else { - if (treat_nan_as_equal_ && std::isnan(value_1) && std::isnan(value_2)) { - return true; - } - // float_comparison_ == APPROXIMATE covers two use cases. - Tolerance* tolerance = FindOrNull(map_tolerance_, &field); - if (tolerance == NULL && has_default_tolerance_) { - tolerance = &default_tolerance_; - } - if (tolerance == NULL) { - return MathUtil::AlmostEquals(value_1, value_2); - } else { - // Use user-provided fraction and margin. Since they are stored as - // doubles, we explicitly cast them to types of values provided. This - // is very likely to fail if provided values are not numeric. - return MathUtil::WithinFractionOrMargin( - value_1, value_2, static_cast<T>(tolerance->fraction), - static_cast<T>(tolerance->margin)); - } - } -} - -FieldComparator::ComparisonResult SimpleFieldComparator::ResultFromBoolean( - bool boolean_result) const { - return boolean_result ? FieldComparator::SAME : FieldComparator::DIFFERENT; -} - -} // namespace util -} // namespace protobuf -} // namespace google diff --git a/contrib/libs/protobuf_std/src/google/protobuf/util/field_comparator.h b/contrib/libs/protobuf_std/src/google/protobuf/util/field_comparator.h deleted file mode 100644 index dd1a486996..0000000000 --- a/contrib/libs/protobuf_std/src/google/protobuf/util/field_comparator.h +++ /dev/null @@ -1,285 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// 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__ diff --git a/contrib/libs/protobuf_std/src/google/protobuf/util/field_mask_util.cc b/contrib/libs/protobuf_std/src/google/protobuf/util/field_mask_util.cc deleted file mode 100644 index 646f80706c..0000000000 --- a/contrib/libs/protobuf_std/src/google/protobuf/util/field_mask_util.cc +++ /dev/null @@ -1,720 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include <google/protobuf/util/field_mask_util.h> - -#include <cstdint> - -#include <google/protobuf/message.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/stubs/map_util.h> - -// Must be included last. -#include <google/protobuf/port_def.inc> - -namespace google { -namespace protobuf { -namespace util { - -using google::protobuf::FieldMask; - -std::string FieldMaskUtil::ToString(const FieldMask& mask) { - return Join(mask.paths(), ","); -} - -void FieldMaskUtil::FromString(StringPiece str, FieldMask* out) { - out->Clear(); - std::vector<std::string> paths = Split(str, ","); - for (const std::string& path : paths) { - if (path.empty()) continue; - out->add_paths(path); - } -} - -bool FieldMaskUtil::SnakeCaseToCamelCase(StringPiece input, - std::string* output) { - output->clear(); - bool after_underscore = false; - for (const char& input_char : input) { - if (input_char >= 'A' && input_char <= 'Z') { - // The field name must not contain uppercase letters. - return false; - } - if (after_underscore) { - if (input_char >= 'a' && input_char <= 'z') { - output->push_back(input_char + 'A' - 'a'); - after_underscore = false; - } else { - // The character after a "_" must be a lowercase letter. - return false; - } - } else if (input_char == '_') { - after_underscore = true; - } else { - output->push_back(input_char); - } - } - if (after_underscore) { - // Trailing "_". - return false; - } - return true; -} - -bool FieldMaskUtil::CamelCaseToSnakeCase(StringPiece input, - std::string* output) { - output->clear(); - for (const char c : input) { - if (c == '_') { - // The field name must not contain "_"s. - return false; - } - if (c >= 'A' && c <= 'Z') { - output->push_back('_'); - output->push_back(c + 'a' - 'A'); - } else { - output->push_back(c); - } - } - return true; -} - -bool FieldMaskUtil::ToJsonString(const FieldMask& mask, std::string* out) { - out->clear(); - for (int i = 0; i < mask.paths_size(); ++i) { - const std::string& path = mask.paths(i); - std::string camelcase_path; - if (!SnakeCaseToCamelCase(path, &camelcase_path)) { - return false; - } - if (i > 0) { - out->push_back(','); - } - out->append(camelcase_path); - } - return true; -} - -bool FieldMaskUtil::FromJsonString(StringPiece str, FieldMask* out) { - out->Clear(); - std::vector<std::string> paths = Split(str, ","); - for (const std::string& path : paths) { - if (path.empty()) continue; - std::string snakecase_path; - if (!CamelCaseToSnakeCase(path, &snakecase_path)) { - return false; - } - out->add_paths(snakecase_path); - } - return true; -} - -bool FieldMaskUtil::GetFieldDescriptors( - const Descriptor* descriptor, StringPiece path, - std::vector<const FieldDescriptor*>* field_descriptors) { - if (field_descriptors != nullptr) { - field_descriptors->clear(); - } - std::vector<std::string> parts = Split(path, "."); - for (const std::string& field_name : parts) { - if (descriptor == nullptr) { - return false; - } - const FieldDescriptor* field = descriptor->FindFieldByName(field_name); - if (field == nullptr) { - return false; - } - if (field_descriptors != nullptr) { - field_descriptors->push_back(field); - } - if (!field->is_repeated() && - field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - descriptor = field->message_type(); - } else { - descriptor = nullptr; - } - } - return true; -} - -void FieldMaskUtil::GetFieldMaskForAllFields(const Descriptor* descriptor, - FieldMask* out) { - for (int i = 0; i < descriptor->field_count(); ++i) { - out->add_paths(descriptor->field(i)->name()); - } -} - -namespace { -// A FieldMaskTree represents a FieldMask in a tree structure. For example, -// given a FieldMask "foo.bar,foo.baz,bar.baz", the FieldMaskTree will be: -// -// [root] -+- foo -+- bar -// | | -// | +- baz -// | -// +- bar --- baz -// -// In the tree, each leaf node represents a field path. -class FieldMaskTree { - public: - FieldMaskTree(); - ~FieldMaskTree(); - - void MergeFromFieldMask(const FieldMask& mask); - void MergeToFieldMask(FieldMask* mask); - - // Add a field path into the tree. In a FieldMask, each field path matches - // the specified field and also all its sub-fields. If the field path to - // add is a sub-path of an existing field path in the tree (i.e., a leaf - // node), it means the tree already matches the given path so nothing will - // be added to the tree. If the path matches an existing non-leaf node in the - // tree, that non-leaf node will be turned into a leaf node with all its - // children removed because the path matches all the node's children. - void AddPath(const std::string& path); - - // Remove a path from the tree. - // If the path is a sub-path of an existing field path in the tree, it means - // we need remove the existing field path and add all sub-paths except - // specified path. If the path matches an existing node in the tree, this node - // will be moved. - void RemovePath(const std::string& path, const Descriptor* descriptor); - - // Calculate the intersection part of a field path with this tree and add - // the intersection field path into out. - void IntersectPath(const std::string& path, FieldMaskTree* out); - - // Merge all fields specified by this tree from one message to another. - void MergeMessage(const Message& source, - const FieldMaskUtil::MergeOptions& options, - Message* destination) { - // Do nothing if the tree is empty. - if (root_.children.empty()) { - return; - } - MergeMessage(&root_, source, options, destination); - } - - // Add required field path of the message to this tree based on current tree - // structure. If a message is present in the tree, add the path of its - // required field to the tree. This is to make sure that after trimming a - // message with required fields are set, check IsInitialized() will not fail. - void AddRequiredFieldPath(const Descriptor* descriptor) { - // Do nothing if the tree is empty. - if (root_.children.empty()) { - return; - } - AddRequiredFieldPath(&root_, descriptor); - } - - // Trims all fields not specified by this tree from the given message. - // Returns true if the message is modified. - bool TrimMessage(Message* message) { - // Do nothing if the tree is empty. - if (root_.children.empty()) { - return false; - } - return TrimMessage(&root_, message); - } - - private: - struct Node { - Node() {} - - ~Node() { ClearChildren(); } - - void ClearChildren() { - for (std::map<std::string, Node*>::iterator it = children.begin(); - it != children.end(); ++it) { - delete it->second; - } - children.clear(); - } - - std::map<std::string, Node*> children; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Node); - }; - - // Merge a sub-tree to mask. This method adds the field paths represented - // by all leaf nodes descended from "node" to mask. - void MergeToFieldMask(const std::string& prefix, const Node* node, - FieldMask* out); - - // Merge all leaf nodes of a sub-tree to another tree. - void MergeLeafNodesToTree(const std::string& prefix, const Node* node, - FieldMaskTree* out); - - // Merge all fields specified by a sub-tree from one message to another. - void MergeMessage(const Node* node, const Message& source, - const FieldMaskUtil::MergeOptions& options, - Message* destination); - - // Add required field path of the message to this tree based on current tree - // structure. If a message is present in the tree, add the path of its - // required field to the tree. This is to make sure that after trimming a - // message with required fields are set, check IsInitialized() will not fail. - void AddRequiredFieldPath(Node* node, const Descriptor* descriptor); - - // Trims all fields not specified by this sub-tree from the given message. - // Returns true if the message is actually modified - bool TrimMessage(const Node* node, Message* message); - - Node root_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldMaskTree); -}; - -FieldMaskTree::FieldMaskTree() {} - -FieldMaskTree::~FieldMaskTree() {} - -void FieldMaskTree::MergeFromFieldMask(const FieldMask& mask) { - for (int i = 0; i < mask.paths_size(); ++i) { - AddPath(mask.paths(i)); - } -} - -void FieldMaskTree::MergeToFieldMask(FieldMask* mask) { - MergeToFieldMask("", &root_, mask); -} - -void FieldMaskTree::MergeToFieldMask(const std::string& prefix, - const Node* node, FieldMask* out) { - if (node->children.empty()) { - if (prefix.empty()) { - // This is the root node. - return; - } - out->add_paths(prefix); - return; - } - for (std::map<std::string, Node*>::const_iterator it = node->children.begin(); - it != node->children.end(); ++it) { - std::string current_path = - prefix.empty() ? it->first : prefix + "." + it->first; - MergeToFieldMask(current_path, it->second, out); - } -} - -void FieldMaskTree::AddPath(const std::string& path) { - std::vector<std::string> parts = Split(path, "."); - if (parts.empty()) { - return; - } - bool new_branch = false; - Node* node = &root_; - for (const std::string& node_name : parts) { - if (!new_branch && node != &root_ && node->children.empty()) { - // Path matches an existing leaf node. This means the path is already - // covered by this tree (for example, adding "foo.bar.baz" to a tree - // which already contains "foo.bar"). - return; - } - Node*& child = node->children[node_name]; - if (child == NULL) { - new_branch = true; - child = new Node(); - } - node = child; - } - if (!node->children.empty()) { - node->ClearChildren(); - } -} - -void FieldMaskTree::RemovePath(const std::string& path, - const Descriptor* descriptor) { - if (root_.children.empty()) { - // Nothing to be removed from an empty tree. We shortcut it here so an empty - // tree won't be interpreted as a field mask containing all fields by the - // code below. - return; - } - std::vector<std::string> parts = Split(path, "."); - if (parts.empty()) { - return; - } - std::vector<Node*> nodes(parts.size()); - Node* node = &root_; - const Descriptor* current_descriptor = descriptor; - Node* new_branch_node = nullptr; - for (int i = 0; i < parts.size(); ++i) { - nodes[i] = node; - const FieldDescriptor* field_descriptor = - current_descriptor->FindFieldByName(parts[i]); - if (field_descriptor == nullptr || - (field_descriptor->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE && - i != parts.size() - 1)) { - // Invalid path. - if (new_branch_node != nullptr) { - // If add any new nodes, cleanup. - new_branch_node->ClearChildren(); - } - return; - } - - if (node->children.empty()) { - if (new_branch_node == nullptr) { - new_branch_node = node; - } - for (int i = 0; i < current_descriptor->field_count(); ++i) { - node->children[current_descriptor->field(i)->name()] = new Node(); - } - } - if (ContainsKey(node->children, parts[i])) { - node = node->children[parts[i]]; - if (field_descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - current_descriptor = field_descriptor->message_type(); - } - } else { - // Path does not exist. - return; - } - } - // Remove path. - for (int i = parts.size() - 1; i >= 0; i--) { - delete nodes[i]->children[parts[i]]; - nodes[i]->children.erase(parts[i]); - if (!nodes[i]->children.empty()) { - break; - } - } -} - -void FieldMaskTree::IntersectPath(const std::string& path, FieldMaskTree* out) { - std::vector<std::string> parts = Split(path, "."); - if (parts.empty()) { - return; - } - const Node* node = &root_; - for (const std::string& node_name : parts) { - if (node->children.empty()) { - if (node != &root_) { - out->AddPath(path); - } - return; - } - const Node* result = FindPtrOrNull(node->children, node_name); - if (result == NULL) { - // No intersection found. - return; - } - node = result; - } - // Now we found a matching node with the given path. Add all leaf nodes - // to out. - MergeLeafNodesToTree(path, node, out); -} - -void FieldMaskTree::MergeLeafNodesToTree(const std::string& prefix, - const Node* node, FieldMaskTree* out) { - if (node->children.empty()) { - out->AddPath(prefix); - } - for (std::map<std::string, Node*>::const_iterator it = node->children.begin(); - it != node->children.end(); ++it) { - std::string current_path = - prefix.empty() ? it->first : prefix + "." + it->first; - MergeLeafNodesToTree(current_path, it->second, out); - } -} - -void FieldMaskTree::MergeMessage(const Node* node, const Message& source, - const FieldMaskUtil::MergeOptions& options, - Message* destination) { - GOOGLE_DCHECK(!node->children.empty()); - const Reflection* source_reflection = source.GetReflection(); - const Reflection* destination_reflection = destination->GetReflection(); - const Descriptor* descriptor = source.GetDescriptor(); - for (std::map<std::string, Node*>::const_iterator it = node->children.begin(); - it != node->children.end(); ++it) { - const std::string& field_name = it->first; - const Node* child = it->second; - const FieldDescriptor* field = descriptor->FindFieldByName(field_name); - if (field == NULL) { - GOOGLE_LOG(ERROR) << "Cannot find field \"" << field_name << "\" in message " - << descriptor->full_name(); - continue; - } - if (!child->children.empty()) { - // Sub-paths are only allowed for singular message fields. - if (field->is_repeated() || - field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) { - GOOGLE_LOG(ERROR) << "Field \"" << field_name << "\" in message " - << descriptor->full_name() - << " is not a singular message field and cannot " - << "have sub-fields."; - continue; - } - MergeMessage(child, source_reflection->GetMessage(source, field), options, - destination_reflection->MutableMessage(destination, field)); - continue; - } - if (!field->is_repeated()) { - switch (field->cpp_type()) { -#define COPY_VALUE(TYPE, Name) \ - case FieldDescriptor::CPPTYPE_##TYPE: { \ - if (source_reflection->HasField(source, field)) { \ - destination_reflection->Set##Name( \ - destination, field, source_reflection->Get##Name(source, field)); \ - } else { \ - destination_reflection->ClearField(destination, field); \ - } \ - break; \ - } - COPY_VALUE(BOOL, Bool) - COPY_VALUE(INT32, Int32) - COPY_VALUE(INT64, Int64) - COPY_VALUE(UINT32, UInt32) - COPY_VALUE(UINT64, UInt64) - COPY_VALUE(FLOAT, Float) - COPY_VALUE(DOUBLE, Double) - COPY_VALUE(ENUM, Enum) - COPY_VALUE(STRING, String) -#undef COPY_VALUE - case FieldDescriptor::CPPTYPE_MESSAGE: { - if (options.replace_message_fields()) { - destination_reflection->ClearField(destination, field); - } - if (source_reflection->HasField(source, field)) { - destination_reflection->MutableMessage(destination, field) - ->MergeFrom(source_reflection->GetMessage(source, field)); - } - break; - } - } - } else { - if (options.replace_repeated_fields()) { - destination_reflection->ClearField(destination, field); - } - switch (field->cpp_type()) { -#define COPY_REPEATED_VALUE(TYPE, Name) \ - case FieldDescriptor::CPPTYPE_##TYPE: { \ - int size = source_reflection->FieldSize(source, field); \ - for (int i = 0; i < size; ++i) { \ - destination_reflection->Add##Name( \ - destination, field, \ - source_reflection->GetRepeated##Name(source, field, i)); \ - } \ - break; \ - } - COPY_REPEATED_VALUE(BOOL, Bool) - COPY_REPEATED_VALUE(INT32, Int32) - COPY_REPEATED_VALUE(INT64, Int64) - COPY_REPEATED_VALUE(UINT32, UInt32) - COPY_REPEATED_VALUE(UINT64, UInt64) - COPY_REPEATED_VALUE(FLOAT, Float) - COPY_REPEATED_VALUE(DOUBLE, Double) - COPY_REPEATED_VALUE(ENUM, Enum) - COPY_REPEATED_VALUE(STRING, String) -#undef COPY_REPEATED_VALUE - case FieldDescriptor::CPPTYPE_MESSAGE: { - int size = source_reflection->FieldSize(source, field); - for (int i = 0; i < size; ++i) { - destination_reflection->AddMessage(destination, field) - ->MergeFrom( - source_reflection->GetRepeatedMessage(source, field, i)); - } - break; - } - } - } - } -} - -void FieldMaskTree::AddRequiredFieldPath(Node* node, - const Descriptor* descriptor) { - const int32_t field_count = descriptor->field_count(); - for (int index = 0; index < field_count; ++index) { - const FieldDescriptor* field = descriptor->field(index); - if (field->is_required()) { - const std::string& node_name = field->name(); - Node*& child = node->children[node_name]; - if (child == nullptr) { - // Add required field path to the tree - child = new Node(); - } else if (child->children.empty()) { - // If the required field is in the tree and does not have any children, - // do nothing. - continue; - } - // Add required field in the children to the tree if the field is message. - if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - AddRequiredFieldPath(child, field->message_type()); - } - } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - std::map<std::string, Node*>::const_iterator it = - node->children.find(field->name()); - if (it != node->children.end()) { - // Add required fields in the children to the - // tree if the field is a message and present in the tree. - Node* child = it->second; - if (!child->children.empty()) { - AddRequiredFieldPath(child, field->message_type()); - } - } - } - } -} - -bool FieldMaskTree::TrimMessage(const Node* node, Message* message) { - GOOGLE_DCHECK(!node->children.empty()); - const Reflection* reflection = message->GetReflection(); - const Descriptor* descriptor = message->GetDescriptor(); - const int32_t field_count = descriptor->field_count(); - bool modified = false; - for (int index = 0; index < field_count; ++index) { - const FieldDescriptor* field = descriptor->field(index); - std::map<std::string, Node*>::const_iterator it = - node->children.find(field->name()); - if (it == node->children.end()) { - if (field->is_repeated()) { - if (reflection->FieldSize(*message, field) != 0) { - modified = true; - } - } else { - if (reflection->HasField(*message, field)) { - modified = true; - } - } - reflection->ClearField(message, field); - } else { - if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - Node* child = it->second; - if (!child->children.empty() && reflection->HasField(*message, field)) { - bool nestedMessageChanged = - TrimMessage(child, reflection->MutableMessage(message, field)); - modified = nestedMessageChanged || modified; - } - } - } - } - return modified; -} - -} // namespace - -void FieldMaskUtil::ToCanonicalForm(const FieldMask& mask, FieldMask* out) { - FieldMaskTree tree; - tree.MergeFromFieldMask(mask); - out->Clear(); - tree.MergeToFieldMask(out); -} - -void FieldMaskUtil::Union(const FieldMask& mask1, const FieldMask& mask2, - FieldMask* out) { - FieldMaskTree tree; - tree.MergeFromFieldMask(mask1); - tree.MergeFromFieldMask(mask2); - out->Clear(); - tree.MergeToFieldMask(out); -} - -void FieldMaskUtil::Intersect(const FieldMask& mask1, const FieldMask& mask2, - FieldMask* out) { - FieldMaskTree tree, intersection; - tree.MergeFromFieldMask(mask1); - for (int i = 0; i < mask2.paths_size(); ++i) { - tree.IntersectPath(mask2.paths(i), &intersection); - } - out->Clear(); - intersection.MergeToFieldMask(out); -} - -void FieldMaskUtil::Subtract(const Descriptor* descriptor, - const FieldMask& mask1, const FieldMask& mask2, - FieldMask* out) { - if (mask1.paths().empty()) { - out->Clear(); - return; - } - FieldMaskTree tree; - tree.MergeFromFieldMask(mask1); - for (int i = 0; i < mask2.paths_size(); ++i) { - tree.RemovePath(mask2.paths(i), descriptor); - } - out->Clear(); - tree.MergeToFieldMask(out); -} - -bool FieldMaskUtil::IsPathInFieldMask(StringPiece path, - const FieldMask& mask) { - for (int i = 0; i < mask.paths_size(); ++i) { - const std::string& mask_path = mask.paths(i); - if (path == mask_path) { - return true; - } else if (mask_path.length() < path.length()) { - // Also check whether mask.paths(i) is a prefix of path. - if (path.substr(0, mask_path.length() + 1).compare(mask_path + ".") == - 0) { - return true; - } - } - } - return false; -} - -void FieldMaskUtil::MergeMessageTo(const Message& source, const FieldMask& mask, - const MergeOptions& options, - Message* destination) { - GOOGLE_CHECK(source.GetDescriptor() == destination->GetDescriptor()); - // Build a FieldMaskTree and walk through the tree to merge all specified - // fields. - FieldMaskTree tree; - tree.MergeFromFieldMask(mask); - tree.MergeMessage(source, options, destination); -} - -bool FieldMaskUtil::TrimMessage(const FieldMask& mask, Message* message) { - // Build a FieldMaskTree and walk through the tree to merge all specified - // fields. - FieldMaskTree tree; - tree.MergeFromFieldMask(mask); - return tree.TrimMessage(GOOGLE_CHECK_NOTNULL(message)); -} - -bool FieldMaskUtil::TrimMessage(const FieldMask& mask, Message* message, - const TrimOptions& options) { - // Build a FieldMaskTree and walk through the tree to merge all specified - // fields. - FieldMaskTree tree; - tree.MergeFromFieldMask(mask); - // If keep_required_fields is true, implicitly add required fields of - // a message present in the tree to prevent from trimming. - if (options.keep_required_fields()) { - tree.AddRequiredFieldPath(GOOGLE_CHECK_NOTNULL(message->GetDescriptor())); - } - return tree.TrimMessage(GOOGLE_CHECK_NOTNULL(message)); -} - -} // namespace util -} // namespace protobuf -} // namespace google diff --git a/contrib/libs/protobuf_std/src/google/protobuf/util/field_mask_util.h b/contrib/libs/protobuf_std/src/google/protobuf/util/field_mask_util.h deleted file mode 100644 index 84cd1202ef..0000000000 --- a/contrib/libs/protobuf_std/src/google/protobuf/util/field_mask_util.h +++ /dev/null @@ -1,262 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Defines utilities for the FieldMask well known type. - -#ifndef GOOGLE_PROTOBUF_UTIL_FIELD_MASK_UTIL_H__ -#define GOOGLE_PROTOBUF_UTIL_FIELD_MASK_UTIL_H__ - -#include <cstdint> -#include <string> - -#include <google/protobuf/field_mask.pb.h> -#include <google/protobuf/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__ diff --git a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/constants.h b/contrib/libs/protobuf_std/src/google/protobuf/util/internal/constants.h deleted file mode 100644 index 65f1a34024..0000000000 --- a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/constants.h +++ /dev/null @@ -1,101 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_CONSTANTS_H__ -#define GOOGLE_PROTOBUF_UTIL_CONVERTER_CONSTANTS_H__ - -#include <cstdint> - -#include <google/protobuf/stubs/common.h> - -// This file contains constants used by //net/proto2/util/converter. - -namespace google { -namespace protobuf { -namespace util { -namespace converter { -// Prefix for type URLs. -const char kTypeServiceBaseUrl[] = "type.googleapis.com"; - -// Format string for RFC3339 timestamp formatting. -const char kRfc3339TimeFormat[] = "%E4Y-%m-%dT%H:%M:%S"; - -// Same as above, but the year value is not zero-padded i.e. this accepts -// timestamps like "1-01-0001T23:59:59Z" instead of "0001-01-0001T23:59:59Z". -const char kRfc3339TimeFormatNoPadding[] = "%Y-%m-%dT%H:%M:%S"; - -// Minimum seconds allowed in a google.protobuf.Timestamp value. -const int64_t kTimestampMinSeconds = -62135596800LL; - -// Maximum seconds allowed in a google.protobuf.Timestamp value. -const int64_t kTimestampMaxSeconds = 253402300799LL; - -// Minimum seconds allowed in a google.protobuf.Duration value. -const int64_t kDurationMinSeconds = -315576000000LL; - -// Maximum seconds allowed in a google.protobuf.Duration value. -const int64_t kDurationMaxSeconds = 315576000000LL; - -// Nano seconds in a second. -const int32_t kNanosPerSecond = 1000000000; - -// Type url representing NULL values in google.protobuf.Struct type. -const char kStructNullValueTypeUrl[] = - "type.googleapis.com/google.protobuf.NullValue"; - -// Type string for google.protobuf.Struct -const char kStructType[] = "google.protobuf.Struct"; - -// Type string for struct.proto's google.protobuf.Value value type. -const char kStructValueType[] = "google.protobuf.Value"; - -// Type string for struct.proto's google.protobuf.ListValue value type. -const char kStructListValueType[] = "google.protobuf.ListValue"; - -// Type string for google.protobuf.Timestamp -const char kTimestampType[] = "google.protobuf.Timestamp"; - -// Type string for google.protobuf.Duration -const char kDurationType[] = "google.protobuf.Duration"; - -// Type URL for struct value type google.protobuf.Value -const char kStructValueTypeUrl[] = "type.googleapis.com/google.protobuf.Value"; - -// Type string for google.protobuf.Any -const char kAnyType[] = "google.protobuf.Any"; - -// The protobuf option name of jspb.message_id; -const char kOptionJspbMessageId[] = "jspb.message_id"; - -} // namespace converter -} // namespace util -} // namespace protobuf -} // namespace google -#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_CONSTANTS_H__ diff --git a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/datapiece.cc b/contrib/libs/protobuf_std/src/google/protobuf/util/internal/datapiece.cc deleted file mode 100644 index 52c335dd8a..0000000000 --- a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/datapiece.cc +++ /dev/null @@ -1,423 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include <google/protobuf/util/internal/datapiece.h> - -#include <cmath> -#include <cstdint> -#include <limits> - -#include <google/protobuf/struct.pb.h> -#include <google/protobuf/type.pb.h> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/util/internal/utility.h> -#include <google/protobuf/stubs/status.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/stubs/mathutil.h> - -namespace google { -namespace protobuf { -namespace util { -namespace converter { - -using util::Status; - -namespace { - -template <typename To, typename From> -util::StatusOr<To> ValidateNumberConversion(To after, From before) { - if (after == before && - MathUtil::Sign<From>(before) == MathUtil::Sign<To>(after)) { - return after; - } else { - return util::InvalidArgumentError( - std::is_integral<From>::value ? ValueAsString(before) - : std::is_same<From, double>::value ? DoubleAsString(before) - : FloatAsString(before)); - } -} - -// For general conversion between -// int32, int64, uint32, uint64, double and float -// except conversion between double and float. -template <typename To, typename From> -util::StatusOr<To> NumberConvertAndCheck(From before) { - if (std::is_same<From, To>::value) return before; - - To after = static_cast<To>(before); - return ValidateNumberConversion(after, before); -} - -// For conversion to integer types (int32, int64, uint32, uint64) from floating -// point types (double, float) only. -template <typename To, typename From> -util::StatusOr<To> FloatingPointToIntConvertAndCheck(From before) { - if (std::is_same<From, To>::value) return before; - - To after = static_cast<To>(before); - return ValidateNumberConversion(after, before); -} - -// For conversion between double and float only. -util::StatusOr<double> FloatToDouble(float before) { - // Casting float to double should just work as double has more precision - // than float. - return static_cast<double>(before); -} - -util::StatusOr<float> DoubleToFloat(double before) { - if (std::isnan(before)) { - return std::numeric_limits<float>::quiet_NaN(); - } else if (!std::isfinite(before)) { - // Converting a double +inf/-inf to float should just work. - return static_cast<float>(before); - } else if (before > std::numeric_limits<float>::max() || - before < -std::numeric_limits<float>::max()) { - // Double value outside of the range of float. - return util::InvalidArgumentError(DoubleAsString(before)); - } else { - return static_cast<float>(before); - } -} - -} // namespace - -util::StatusOr<int32_t> DataPiece::ToInt32() const { - if (type_ == TYPE_STRING) - return StringToNumber<int32_t>(safe_strto32); - - if (type_ == TYPE_DOUBLE) - return FloatingPointToIntConvertAndCheck<int32_t, double>(double_); - - if (type_ == TYPE_FLOAT) - return FloatingPointToIntConvertAndCheck<int32_t, float>(float_); - - return GenericConvert<int32_t>(); -} - -util::StatusOr<uint32_t> DataPiece::ToUint32() const { - if (type_ == TYPE_STRING) - return StringToNumber<uint32_t>(safe_strtou32); - - if (type_ == TYPE_DOUBLE) - return FloatingPointToIntConvertAndCheck<uint32_t, double>(double_); - - if (type_ == TYPE_FLOAT) - return FloatingPointToIntConvertAndCheck<uint32_t, float>(float_); - - return GenericConvert<uint32_t>(); -} - -util::StatusOr<int64_t> DataPiece::ToInt64() const { - if (type_ == TYPE_STRING) - return StringToNumber<int64_t>(safe_strto64); - - if (type_ == TYPE_DOUBLE) - return FloatingPointToIntConvertAndCheck<int64_t, double>(double_); - - if (type_ == TYPE_FLOAT) - return FloatingPointToIntConvertAndCheck<int64_t, float>(float_); - - return GenericConvert<int64_t>(); -} - -util::StatusOr<uint64_t> DataPiece::ToUint64() const { - if (type_ == TYPE_STRING) - return StringToNumber<uint64_t>(safe_strtou64); - - if (type_ == TYPE_DOUBLE) - return FloatingPointToIntConvertAndCheck<uint64_t, double>(double_); - - if (type_ == TYPE_FLOAT) - return FloatingPointToIntConvertAndCheck<uint64_t, float>(float_); - - return GenericConvert<uint64_t>(); -} - -util::StatusOr<double> DataPiece::ToDouble() const { - if (type_ == TYPE_FLOAT) { - return FloatToDouble(float_); - } - if (type_ == TYPE_STRING) { - if (str_ == "Infinity") return std::numeric_limits<double>::infinity(); - if (str_ == "-Infinity") return -std::numeric_limits<double>::infinity(); - if (str_ == "NaN") return std::numeric_limits<double>::quiet_NaN(); - util::StatusOr<double> value = StringToNumber<double>(safe_strtod); - if (value.ok() && !std::isfinite(value.value())) { - // safe_strtod converts out-of-range values to +inf/-inf, but we want - // to report them as errors. - return util::InvalidArgumentError(StrCat("\"", str_, "\"")); - } else { - return value; - } - } - return GenericConvert<double>(); -} - -util::StatusOr<float> DataPiece::ToFloat() const { - if (type_ == TYPE_DOUBLE) { - return DoubleToFloat(double_); - } - if (type_ == TYPE_STRING) { - if (str_ == "Infinity") return std::numeric_limits<float>::infinity(); - if (str_ == "-Infinity") return -std::numeric_limits<float>::infinity(); - if (str_ == "NaN") return std::numeric_limits<float>::quiet_NaN(); - // SafeStrToFloat() is used instead of safe_strtof() because the later - // does not fail on inputs like SimpleDtoa(DBL_MAX). - return StringToNumber<float>(SafeStrToFloat); - } - return GenericConvert<float>(); -} - -util::StatusOr<bool> DataPiece::ToBool() const { - switch (type_) { - case TYPE_BOOL: - return bool_; - case TYPE_STRING: - return StringToNumber<bool>(safe_strtob); - default: - return util::InvalidArgumentError( - ValueAsStringOrDefault("Wrong type. Cannot convert to Bool.")); - } -} - -util::StatusOr<std::string> DataPiece::ToString() const { - switch (type_) { - case TYPE_STRING: - return std::string(str_); - case TYPE_BYTES: { - std::string base64; - Base64Escape(str_, &base64); - return base64; - } - default: - return util::InvalidArgumentError( - ValueAsStringOrDefault("Cannot convert to string.")); - } -} - -std::string DataPiece::ValueAsStringOrDefault( - StringPiece default_string) const { - switch (type_) { - case TYPE_INT32: - return StrCat(i32_); - case TYPE_INT64: - return StrCat(i64_); - case TYPE_UINT32: - return StrCat(u32_); - case TYPE_UINT64: - return StrCat(u64_); - case TYPE_DOUBLE: - return DoubleAsString(double_); - case TYPE_FLOAT: - return FloatAsString(float_); - case TYPE_BOOL: - return SimpleBtoa(bool_); - case TYPE_STRING: - return StrCat("\"", str_.ToString(), "\""); - case TYPE_BYTES: { - std::string base64; - WebSafeBase64Escape(str_, &base64); - return StrCat("\"", base64, "\""); - } - case TYPE_NULL: - return "null"; - default: - return std::string(default_string); - } -} - -util::StatusOr<std::string> DataPiece::ToBytes() const { - if (type_ == TYPE_BYTES) return str_.ToString(); - if (type_ == TYPE_STRING) { - std::string decoded; - if (!DecodeBase64(str_, &decoded)) { - return util::InvalidArgumentError( - ValueAsStringOrDefault("Invalid data in input.")); - } - return decoded; - } else { - return util::InvalidArgumentError(ValueAsStringOrDefault( - "Wrong type. Only String or Bytes can be converted to Bytes.")); - } -} - -util::StatusOr<int> DataPiece::ToEnum(const google::protobuf::Enum* enum_type, - bool use_lower_camel_for_enums, - bool case_insensitive_enum_parsing, - bool ignore_unknown_enum_values, - bool* is_unknown_enum_value) const { - if (type_ == TYPE_NULL) return google::protobuf::NULL_VALUE; - - if (type_ == TYPE_STRING) { - // First try the given value as a name. - std::string enum_name = std::string(str_); - const google::protobuf::EnumValue* value = - FindEnumValueByNameOrNull(enum_type, enum_name); - if (value != nullptr) return value->number(); - - // Check if int version of enum is sent as string. - util::StatusOr<int32_t> int_value = ToInt32(); - if (int_value.ok()) { - if (const google::protobuf::EnumValue* enum_value = - FindEnumValueByNumberOrNull(enum_type, int_value.value())) { - return enum_value->number(); - } - } - - // Next try a normalized name. - bool should_normalize_enum = - case_insensitive_enum_parsing || use_lower_camel_for_enums; - if (should_normalize_enum) { - for (std::string::iterator it = enum_name.begin(); it != enum_name.end(); - ++it) { - *it = *it == '-' ? '_' : ascii_toupper(*it); - } - value = FindEnumValueByNameOrNull(enum_type, enum_name); - if (value != nullptr) return value->number(); - } - - // If use_lower_camel_for_enums is true try with enum name without - // underscore. This will also accept camel case names as the enum_name has - // been normalized before. - if (use_lower_camel_for_enums) { - value = FindEnumValueByNameWithoutUnderscoreOrNull(enum_type, enum_name); - if (value != nullptr) return value->number(); - } - - // If ignore_unknown_enum_values is true an unknown enum value is ignored. - if (ignore_unknown_enum_values) { - *is_unknown_enum_value = true; - if (enum_type->enumvalue_size() > 0) { - return enum_type->enumvalue(0).number(); - } - } - } else { - // We don't need to check whether the value is actually declared in the - // enum because we preserve unknown enum values as well. - return ToInt32(); - } - return util::InvalidArgumentError( - ValueAsStringOrDefault("Cannot find enum with given value.")); -} - -template <typename To> -util::StatusOr<To> DataPiece::GenericConvert() const { - switch (type_) { - case TYPE_INT32: - return NumberConvertAndCheck<To, int32_t>(i32_); - case TYPE_INT64: - return NumberConvertAndCheck<To, int64_t>(i64_); - case TYPE_UINT32: - return NumberConvertAndCheck<To, uint32_t>(u32_); - case TYPE_UINT64: - return NumberConvertAndCheck<To, uint64_t>(u64_); - case TYPE_DOUBLE: - return NumberConvertAndCheck<To, double>(double_); - case TYPE_FLOAT: - return NumberConvertAndCheck<To, float>(float_); - default: // TYPE_ENUM, TYPE_STRING, TYPE_CORD, TYPE_BOOL - return util::InvalidArgumentError(ValueAsStringOrDefault( - "Wrong type. Bool, Enum, String and Cord not supported in " - "GenericConvert.")); - } -} - -template <typename To> -util::StatusOr<To> DataPiece::StringToNumber(bool (*func)(StringPiece, - To*)) const { - if (str_.size() > 0 && (str_[0] == ' ' || str_[str_.size() - 1] == ' ')) { - return util::InvalidArgumentError(StrCat("\"", str_, "\"")); - } - To result; - if (func(str_, &result)) return result; - return util::InvalidArgumentError( - StrCat("\"", std::string(str_), "\"")); -} - -bool DataPiece::DecodeBase64(StringPiece src, std::string* dest) const { - // Try web-safe decode first, if it fails, try the non-web-safe decode. - if (WebSafeBase64Unescape(src, dest)) { - if (use_strict_base64_decoding_) { - // In strict mode, check if the escaped version gives us the same value as - // unescaped. - std::string encoded; - // WebSafeBase64Escape does no padding by default. - WebSafeBase64Escape(*dest, &encoded); - // Remove trailing padding '=' characters before comparison. - StringPiece src_no_padding = StringPiece(src).substr( - 0, HasSuffixString(src, "=") ? src.find_last_not_of('=') + 1 - : src.length()); - return encoded == src_no_padding; - } - return true; - } - - if (Base64Unescape(src, dest)) { - if (use_strict_base64_decoding_) { - std::string encoded; - Base64Escape(reinterpret_cast<const unsigned char*>(dest->data()), - dest->length(), &encoded, false); - StringPiece src_no_padding = StringPiece(src).substr( - 0, HasSuffixString(src, "=") ? src.find_last_not_of('=') + 1 - : src.length()); - return encoded == src_no_padding; - } - return true; - } - - return false; -} - -void DataPiece::InternalCopy(const DataPiece& other) { - type_ = other.type_; - use_strict_base64_decoding_ = other.use_strict_base64_decoding_; - switch (type_) { - case TYPE_INT32: - case TYPE_INT64: - case TYPE_UINT32: - case TYPE_UINT64: - case TYPE_DOUBLE: - case TYPE_FLOAT: - case TYPE_BOOL: - case TYPE_ENUM: - case TYPE_NULL: - case TYPE_BYTES: - case TYPE_STRING: { - str_ = other.str_; - break; - } - } -} - -} // namespace converter -} // namespace util -} // namespace protobuf -} // namespace google diff --git a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/datapiece.h b/contrib/libs/protobuf_std/src/google/protobuf/util/internal/datapiece.h deleted file mode 100644 index c27ea5cf86..0000000000 --- a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/datapiece.h +++ /dev/null @@ -1,218 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_DATAPIECE_H__ -#define GOOGLE_PROTOBUF_UTIL_CONVERTER_DATAPIECE_H__ - -#include <cstdint> -#include <string> - -#include <google/protobuf/stubs/common.h> -#include <google/protobuf/stubs/logging.h> -#include <google/protobuf/type.pb.h> -#include <google/protobuf/stubs/statusor.h> -#include <google/protobuf/stubs/strutil.h> - -#include <google/protobuf/port_def.inc> - -namespace google { -namespace protobuf { -namespace util { -namespace converter { -class ProtoWriter; - -// Container for a single piece of data together with its data type. -// -// For primitive types (int32, int64, uint32, uint64, double, float, bool), -// the data is stored by value. -// -// For string, a StringPiece is stored. For Cord, a pointer to Cord is stored. -// Just like StringPiece, the DataPiece class does not own the storage for -// the actual string or Cord, so it is the user's responsibility to guarantee -// that the underlying storage is still valid when the DataPiece is accessed. -class PROTOBUF_EXPORT DataPiece { - public: - // Identifies data type of the value. - // These are the types supported by DataPiece. - enum Type { - TYPE_INT32 = 1, - TYPE_INT64 = 2, - TYPE_UINT32 = 3, - TYPE_UINT64 = 4, - TYPE_DOUBLE = 5, - TYPE_FLOAT = 6, - TYPE_BOOL = 7, - TYPE_ENUM = 8, - TYPE_STRING = 9, - TYPE_BYTES = 10, - TYPE_NULL = 11, // explicit NULL type - }; - - // Constructors and Destructor - explicit DataPiece(const int32_t value) - : type_(TYPE_INT32), i32_(value), use_strict_base64_decoding_(false) {} - explicit DataPiece(const int64_t value) - : type_(TYPE_INT64), i64_(value), use_strict_base64_decoding_(false) {} - explicit DataPiece(const uint32_t value) - : type_(TYPE_UINT32), u32_(value), use_strict_base64_decoding_(false) {} - explicit DataPiece(const uint64_t value) - : type_(TYPE_UINT64), u64_(value), use_strict_base64_decoding_(false) {} - explicit DataPiece(const double value) - : type_(TYPE_DOUBLE), - double_(value), - use_strict_base64_decoding_(false) {} - explicit DataPiece(const float value) - : type_(TYPE_FLOAT), float_(value), use_strict_base64_decoding_(false) {} - explicit DataPiece(const bool value) - : type_(TYPE_BOOL), bool_(value), use_strict_base64_decoding_(false) {} - DataPiece(StringPiece value, bool use_strict_base64_decoding) - : type_(TYPE_STRING), - str_(value), - use_strict_base64_decoding_(use_strict_base64_decoding) {} - // Constructor for bytes. The second parameter is not used. - DataPiece(StringPiece value, bool dummy, bool use_strict_base64_decoding) - : type_(TYPE_BYTES), - str_(value), - use_strict_base64_decoding_(use_strict_base64_decoding) {} - - DataPiece(const DataPiece& r) : type_(r.type_) { InternalCopy(r); } - - DataPiece& operator=(const DataPiece& x) { - InternalCopy(x); - return *this; - } - - static DataPiece NullData() { return DataPiece(TYPE_NULL, 0); } - - virtual ~DataPiece() { - } - - // Accessors - Type type() const { return type_; } - - bool use_strict_base64_decoding() { return use_strict_base64_decoding_; } - - StringPiece str() const { - GOOGLE_LOG_IF(DFATAL, type_ != TYPE_STRING) << "Not a string type."; - return str_; - } - - - // Parses, casts or converts the value stored in the DataPiece into an int32. - util::StatusOr<int32_t> ToInt32() const; - - // Parses, casts or converts the value stored in the DataPiece into a uint32. - util::StatusOr<uint32_t> ToUint32() const; - - // Parses, casts or converts the value stored in the DataPiece into an int64. - util::StatusOr<int64_t> ToInt64() const; - - // Parses, casts or converts the value stored in the DataPiece into a uint64. - util::StatusOr<uint64_t> ToUint64() const; - - // Parses, casts or converts the value stored in the DataPiece into a double. - util::StatusOr<double> ToDouble() const; - - // Parses, casts or converts the value stored in the DataPiece into a float. - util::StatusOr<float> ToFloat() const; - - // Parses, casts or converts the value stored in the DataPiece into a bool. - util::StatusOr<bool> ToBool() const; - - // Parses, casts or converts the value stored in the DataPiece into a string. - util::StatusOr<std::string> ToString() const; - - // Tries to convert the value contained in this datapiece to string. If the - // conversion fails, it returns the default_string. - std::string ValueAsStringOrDefault(StringPiece default_string) const; - - util::StatusOr<std::string> ToBytes() const; - - private: - friend class ProtoWriter; - - // Disallow implicit constructor. - DataPiece(); - - // Helper to create NULL or ENUM types. - DataPiece(Type type, int32_t val) - : type_(type), i32_(val), use_strict_base64_decoding_(false) {} - - // Same as the ToEnum() method above but with additional flag to ignore - // unknown enum values. - util::StatusOr<int> ToEnum(const google::protobuf::Enum* enum_type, - bool use_lower_camel_for_enums, - bool case_insensitive_enum_parsing, - bool ignore_unknown_enum_values, - bool* is_unknown_enum_value) const; - - // For numeric conversion between - // int32, int64, uint32, uint64, double, float and bool - template <typename To> - util::StatusOr<To> GenericConvert() const; - - // For conversion from string to - // int32, int64, uint32, uint64, double, float and bool - template <typename To> - util::StatusOr<To> StringToNumber(bool (*func)(StringPiece, To*)) const; - - // Decodes a base64 string. Returns true on success. - bool DecodeBase64(StringPiece src, std::string* dest) const; - - // Helper function to initialize this DataPiece with 'other'. - void InternalCopy(const DataPiece& other); - - // Data type for this piece of data. - Type type_; - - // Stored piece of data. - union { - int32_t i32_; - int64_t i64_; - uint32_t u32_; - uint64_t u64_; - double double_; - float float_; - bool bool_; - StringPiece str_; - }; - - // Uses a stricter version of base64 decoding for byte fields. - bool use_strict_base64_decoding_; -}; - -} // namespace converter -} // namespace util -} // namespace protobuf -} // namespace google - -#include <google/protobuf/port_undef.inc> - -#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_DATAPIECE_H__ diff --git a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/default_value_objectwriter.cc b/contrib/libs/protobuf_std/src/google/protobuf/util/internal/default_value_objectwriter.cc deleted file mode 100644 index c9c691a970..0000000000 --- a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/default_value_objectwriter.cc +++ /dev/null @@ -1,646 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include <google/protobuf/util/internal/default_value_objectwriter.h> - -#include <cstdint> -#include <unordered_map> - -#include <google/protobuf/util/internal/constants.h> -#include <google/protobuf/util/internal/utility.h> -#include <google/protobuf/stubs/map_util.h> - -namespace google { -namespace protobuf { -namespace util { -namespace converter { - -namespace { -// Helper function to convert string value to given data type by calling the -// passed converter function on the DataPiece created from "value" argument. -// If value is empty or if conversion fails, the default_value is returned. -template <typename T> -T ConvertTo(StringPiece value, - util::StatusOr<T> (DataPiece::*converter_fn)() const, - T default_value) { - if (value.empty()) return default_value; - util::StatusOr<T> result = (DataPiece(value, true).*converter_fn)(); - return result.ok() ? result.value() : default_value; -} -} // namespace - -DefaultValueObjectWriter::DefaultValueObjectWriter( - TypeResolver* type_resolver, const google::protobuf::Type& type, - ObjectWriter* ow) - : typeinfo_(TypeInfo::NewTypeInfo(type_resolver)), - own_typeinfo_(true), - type_(type), - current_(nullptr), - root_(nullptr), - suppress_empty_list_(false), - preserve_proto_field_names_(false), - use_ints_for_enums_(false), - ow_(ow) {} - -DefaultValueObjectWriter::~DefaultValueObjectWriter() { - if (own_typeinfo_) { - delete typeinfo_; - } -} - -DefaultValueObjectWriter* DefaultValueObjectWriter::RenderBool( - StringPiece name, bool value) { - if (current_ == nullptr) { - ow_->RenderBool(name, value); - } else { - RenderDataPiece(name, DataPiece(value)); - } - return this; -} - -DefaultValueObjectWriter* DefaultValueObjectWriter::RenderInt32( - StringPiece name, int32_t value) { - if (current_ == nullptr) { - ow_->RenderInt32(name, value); - } else { - RenderDataPiece(name, DataPiece(value)); - } - return this; -} - -DefaultValueObjectWriter* DefaultValueObjectWriter::RenderUint32( - StringPiece name, uint32_t value) { - if (current_ == nullptr) { - ow_->RenderUint32(name, value); - } else { - RenderDataPiece(name, DataPiece(value)); - } - return this; -} - -DefaultValueObjectWriter* DefaultValueObjectWriter::RenderInt64( - StringPiece name, int64_t value) { - if (current_ == nullptr) { - ow_->RenderInt64(name, value); - } else { - RenderDataPiece(name, DataPiece(value)); - } - return this; -} - -DefaultValueObjectWriter* DefaultValueObjectWriter::RenderUint64( - StringPiece name, uint64_t value) { - if (current_ == nullptr) { - ow_->RenderUint64(name, value); - } else { - RenderDataPiece(name, DataPiece(value)); - } - return this; -} - -DefaultValueObjectWriter* DefaultValueObjectWriter::RenderDouble( - StringPiece name, double value) { - if (current_ == nullptr) { - ow_->RenderDouble(name, value); - } else { - RenderDataPiece(name, DataPiece(value)); - } - return this; -} - -DefaultValueObjectWriter* DefaultValueObjectWriter::RenderFloat( - StringPiece name, float value) { - if (current_ == nullptr) { - ow_->RenderBool(name, value); - } else { - RenderDataPiece(name, DataPiece(value)); - } - return this; -} - -DefaultValueObjectWriter* DefaultValueObjectWriter::RenderString( - StringPiece name, StringPiece value) { - if (current_ == nullptr) { - ow_->RenderString(name, value); - } else { - // Since StringPiece is essentially a pointer, takes a copy of "value" to - // avoid ownership issues. - string_values_.emplace_back(new std::string(value)); - RenderDataPiece(name, DataPiece(*string_values_.back(), true)); - } - return this; -} - -DefaultValueObjectWriter* DefaultValueObjectWriter::RenderBytes( - StringPiece name, StringPiece value) { - if (current_ == nullptr) { - ow_->RenderBytes(name, value); - } else { - // Since StringPiece is essentially a pointer, takes a copy of "value" to - // avoid ownership issues. - string_values_.emplace_back(new std::string(value)); - RenderDataPiece(name, DataPiece(*string_values_.back(), false, true)); - } - return this; -} - -DefaultValueObjectWriter* DefaultValueObjectWriter::RenderNull( - StringPiece name) { - if (current_ == nullptr) { - ow_->RenderNull(name); - } else { - RenderDataPiece(name, DataPiece::NullData()); - } - return this; -} - -void DefaultValueObjectWriter::RegisterFieldScrubCallBack( - FieldScrubCallBack field_scrub_callback) { - field_scrub_callback_ = std::move(field_scrub_callback); -} - -DefaultValueObjectWriter::Node* DefaultValueObjectWriter::CreateNewNode( - const std::string& name, const google::protobuf::Type* type, NodeKind kind, - const DataPiece& data, bool is_placeholder, - const std::vector<std::string>& path, bool suppress_empty_list, - bool preserve_proto_field_names, bool use_ints_for_enums, - FieldScrubCallBack field_scrub_callback) { - return new Node(name, type, kind, data, is_placeholder, path, - suppress_empty_list, preserve_proto_field_names, - use_ints_for_enums, std::move(field_scrub_callback)); -} - -DefaultValueObjectWriter::Node::Node( - const std::string& name, const google::protobuf::Type* type, NodeKind kind, - const DataPiece& data, bool is_placeholder, - const std::vector<std::string>& path, bool suppress_empty_list, - bool preserve_proto_field_names, bool use_ints_for_enums, - FieldScrubCallBack field_scrub_callback) - : name_(name), - type_(type), - kind_(kind), - is_any_(false), - data_(data), - is_placeholder_(is_placeholder), - path_(path), - suppress_empty_list_(suppress_empty_list), - preserve_proto_field_names_(preserve_proto_field_names), - use_ints_for_enums_(use_ints_for_enums), - field_scrub_callback_(std::move(field_scrub_callback)) {} - -DefaultValueObjectWriter::Node* DefaultValueObjectWriter::Node::FindChild( - StringPiece name) { - if (name.empty() || kind_ != OBJECT) { - return nullptr; - } - for (Node* child : children_) { - if (child->name() == name) { - return child; - } - } - return nullptr; -} - -void DefaultValueObjectWriter::Node::WriteTo(ObjectWriter* ow) { - if (kind_ == PRIMITIVE) { - ObjectWriter::RenderDataPieceTo(data_, name_, ow); - return; - } - - // Render maps. Empty maps are rendered as "{}". - if (kind_ == MAP) { - ow->StartObject(name_); - WriteChildren(ow); - ow->EndObject(); - return; - } - - // Write out lists. If we didn't have any list in response, write out empty - // list. - if (kind_ == LIST) { - // Suppress empty lists if requested. - if (suppress_empty_list_ && is_placeholder_) return; - - ow->StartList(name_); - WriteChildren(ow); - ow->EndList(); - return; - } - - // If is_placeholder_ = true, we didn't see this node in the response, so - // skip output. - if (is_placeholder_) return; - - ow->StartObject(name_); - WriteChildren(ow); - ow->EndObject(); -} - -void DefaultValueObjectWriter::Node::WriteChildren(ObjectWriter* ow) { - for (Node* child : children_) { - child->WriteTo(ow); - } -} - -const google::protobuf::Type* DefaultValueObjectWriter::Node::GetMapValueType( - const google::protobuf::Type& found_type, const TypeInfo* typeinfo) { - // If this field is a map, we should use the type of its "Value" as - // the type of the child node. - for (int i = 0; i < found_type.fields_size(); ++i) { - const google::protobuf::Field& sub_field = found_type.fields(i); - if (sub_field.number() != 2) { - continue; - } - if (sub_field.kind() != google::protobuf::Field::TYPE_MESSAGE) { - // This map's value type is not a message type. We don't need to - // get the field_type in this case. - break; - } - util::StatusOr<const google::protobuf::Type*> sub_type = - typeinfo->ResolveTypeUrl(sub_field.type_url()); - if (!sub_type.ok()) { - GOOGLE_LOG(WARNING) << "Cannot resolve type '" << sub_field.type_url() << "'."; - } else { - return sub_type.value(); - } - break; - } - return nullptr; -} - -void DefaultValueObjectWriter::Node::PopulateChildren( - const TypeInfo* typeinfo) { - // Ignores well known types that don't require automatically populating their - // primitive children. For type "Any", we only populate its children when the - // "@type" field is set. - // TODO(tsun): remove "kStructValueType" from the list. It's being checked - // now because of a bug in the tool-chain that causes the "oneof_index" - // of kStructValueType to not be set correctly. - if (type_ == nullptr || type_->name() == kAnyType || - type_->name() == kStructType || type_->name() == kTimestampType || - type_->name() == kDurationType || type_->name() == kStructValueType) { - return; - } - std::vector<Node*> new_children; - std::unordered_map<std::string, int> orig_children_map; - - // Creates a map of child nodes to speed up lookup. - for (int i = 0; i < children_.size(); ++i) { - InsertIfNotPresent(&orig_children_map, children_[i]->name_, i); - } - - for (int i = 0; i < type_->fields_size(); ++i) { - const google::protobuf::Field& field = type_->fields(i); - - // This code is checking if the field to be added to the tree should be - // scrubbed or not by calling the field_scrub_callback_ callback function. - std::vector<std::string> path; - if (!path_.empty()) { - path.insert(path.begin(), path_.begin(), path_.end()); - } - path.push_back(field.name()); - if (field_scrub_callback_ && field_scrub_callback_(path, &field)) { - continue; - } - - std::unordered_map<std::string, int>::iterator found = - orig_children_map.find(field.name()); - // If the child field has already been set, we just add it to the new list - // of children. - if (found != orig_children_map.end()) { - new_children.push_back(children_[found->second]); - children_[found->second] = nullptr; - continue; - } - - const google::protobuf::Type* field_type = nullptr; - bool is_map = false; - NodeKind kind = PRIMITIVE; - - if (field.kind() == google::protobuf::Field::TYPE_MESSAGE) { - kind = OBJECT; - util::StatusOr<const google::protobuf::Type*> found_result = - typeinfo->ResolveTypeUrl(field.type_url()); - if (!found_result.ok()) { - // "field" is of an unknown type. - GOOGLE_LOG(WARNING) << "Cannot resolve type '" << field.type_url() << "'."; - } else { - const google::protobuf::Type* found_type = found_result.value(); - is_map = IsMap(field, *found_type); - - if (!is_map) { - field_type = found_type; - } else { - // If this field is a map, we should use the type of its "Value" as - // the type of the child node. - field_type = GetMapValueType(*found_type, typeinfo); - kind = MAP; - } - } - } - - if (!is_map && - field.cardinality() == google::protobuf::Field::CARDINALITY_REPEATED) { - kind = LIST; - } - - // If oneof_index() != 0, the child field is part of a "oneof", which means - // the child field is optional and we shouldn't populate its default - // primitive value. - if (field.oneof_index() != 0 && kind == PRIMITIVE) continue; - - // If the child field is of primitive type, sets its data to the default - // value of its type. - std::unique_ptr<Node> child( - new Node(preserve_proto_field_names_ ? field.name() : field.json_name(), - field_type, kind, - kind == PRIMITIVE ? CreateDefaultDataPieceForField( - field, typeinfo, use_ints_for_enums_) - : DataPiece::NullData(), - true, path, suppress_empty_list_, preserve_proto_field_names_, - use_ints_for_enums_, field_scrub_callback_)); - new_children.push_back(child.release()); - } - // Adds all leftover nodes in children_ to the beginning of new_child. - for (int i = 0; i < children_.size(); ++i) { - if (children_[i] == nullptr) { - continue; - } - new_children.insert(new_children.begin(), children_[i]); - children_[i] = nullptr; - } - children_.swap(new_children); -} - -void DefaultValueObjectWriter::MaybePopulateChildrenOfAny(Node* node) { - // If this is an "Any" node with "@type" already given and no other children - // have been added, populates its children. - if (node != nullptr && node->is_any() && node->type() != nullptr && - node->type()->name() != kAnyType && node->number_of_children() == 1) { - node->PopulateChildren(typeinfo_); - } -} - -DataPiece DefaultValueObjectWriter::FindEnumDefault( - const google::protobuf::Field& field, const TypeInfo* typeinfo, - bool use_ints_for_enums) { - const google::protobuf::Enum* enum_type = - typeinfo->GetEnumByTypeUrl(field.type_url()); - if (!enum_type) { - GOOGLE_LOG(WARNING) << "Could not find enum with type '" << field.type_url() - << "'"; - return DataPiece::NullData(); - } - if (!field.default_value().empty()) { - if (!use_ints_for_enums) { - return DataPiece(field.default_value(), true); - } else { - const std::string& enum_default_value_name = field.default_value(); - for (int enum_index = 0; - enum_index < enum_type->enumvalue_size(); - ++enum_index) { - auto& enum_value = enum_type->enumvalue(enum_index); - if (enum_value.name() == enum_default_value_name) - return DataPiece(enum_value.number()); - } - GOOGLE_LOG(WARNING) << "Could not find enum value '" - << enum_default_value_name - << "' with type '" - << field.type_url() - << "'"; - return DataPiece::NullData(); - } - } - // We treat the first value as the default if none is specified. - return enum_type->enumvalue_size() > 0 - ? (use_ints_for_enums - ? DataPiece(enum_type->enumvalue(0).number()) - : DataPiece(enum_type->enumvalue(0).name(), true)) - : DataPiece::NullData(); -} - -DataPiece DefaultValueObjectWriter::CreateDefaultDataPieceForField( - const google::protobuf::Field& field, const TypeInfo* typeinfo, - bool use_ints_for_enums) { - switch (field.kind()) { - case google::protobuf::Field::TYPE_DOUBLE: { - return DataPiece(ConvertTo<double>( - field.default_value(), &DataPiece::ToDouble, static_cast<double>(0))); - } - case google::protobuf::Field::TYPE_FLOAT: { - return DataPiece(ConvertTo<float>( - field.default_value(), &DataPiece::ToFloat, static_cast<float>(0))); - } - case google::protobuf::Field::TYPE_INT64: - case google::protobuf::Field::TYPE_SINT64: - case google::protobuf::Field::TYPE_SFIXED64: { - return DataPiece(ConvertTo<int64_t>( - field.default_value(), &DataPiece::ToInt64, static_cast<int64_t>(0))); - } - case google::protobuf::Field::TYPE_UINT64: - case google::protobuf::Field::TYPE_FIXED64: { - return DataPiece(ConvertTo<uint64_t>(field.default_value(), - &DataPiece::ToUint64, - static_cast<uint64_t>(0))); - } - case google::protobuf::Field::TYPE_INT32: - case google::protobuf::Field::TYPE_SINT32: - case google::protobuf::Field::TYPE_SFIXED32: { - return DataPiece(ConvertTo<int32_t>( - field.default_value(), &DataPiece::ToInt32, static_cast<int32_t>(0))); - } - case google::protobuf::Field::TYPE_BOOL: { - return DataPiece( - ConvertTo<bool>(field.default_value(), &DataPiece::ToBool, false)); - } - case google::protobuf::Field::TYPE_STRING: { - return DataPiece(field.default_value(), true); - } - case google::protobuf::Field::TYPE_BYTES: { - return DataPiece(field.default_value(), false, true); - } - case google::protobuf::Field::TYPE_UINT32: - case google::protobuf::Field::TYPE_FIXED32: { - return DataPiece(ConvertTo<uint32_t>(field.default_value(), - &DataPiece::ToUint32, - static_cast<uint32_t>(0))); - } - case google::protobuf::Field::TYPE_ENUM: { - return FindEnumDefault(field, typeinfo, use_ints_for_enums); - } - default: { - return DataPiece::NullData(); - } - } -} - -DefaultValueObjectWriter* DefaultValueObjectWriter::StartObject( - StringPiece name) { - if (current_ == nullptr) { - std::vector<std::string> path; - root_.reset(CreateNewNode(std::string(name), &type_, OBJECT, - DataPiece::NullData(), false, path, - suppress_empty_list_, preserve_proto_field_names_, - use_ints_for_enums_, field_scrub_callback_)); - root_->PopulateChildren(typeinfo_); - current_ = root_.get(); - return this; - } - MaybePopulateChildrenOfAny(current_); - Node* child = current_->FindChild(name); - if (current_->kind() == LIST || current_->kind() == MAP || child == nullptr) { - // If current_ is a list or a map node, we should create a new child and use - // the type of current_ as the type of the new child. - std::unique_ptr<Node> node( - CreateNewNode(std::string(name), - ((current_->kind() == LIST || current_->kind() == MAP) - ? current_->type() - : nullptr), - OBJECT, DataPiece::NullData(), false, - child == nullptr ? current_->path() : child->path(), - suppress_empty_list_, preserve_proto_field_names_, - use_ints_for_enums_, field_scrub_callback_)); - child = node.get(); - current_->AddChild(node.release()); - } - - child->set_is_placeholder(false); - if (child->kind() == OBJECT && child->number_of_children() == 0) { - child->PopulateChildren(typeinfo_); - } - - stack_.push(current_); - current_ = child; - return this; -} - -DefaultValueObjectWriter* DefaultValueObjectWriter::EndObject() { - if (stack_.empty()) { - // The root object ends here. Writes out the tree. - WriteRoot(); - return this; - } - current_ = stack_.top(); - stack_.pop(); - return this; -} - -DefaultValueObjectWriter* DefaultValueObjectWriter::StartList( - StringPiece name) { - if (current_ == nullptr) { - std::vector<std::string> path; - root_.reset(CreateNewNode(std::string(name), &type_, LIST, - DataPiece::NullData(), false, path, - suppress_empty_list_, preserve_proto_field_names_, - use_ints_for_enums_, field_scrub_callback_)); - current_ = root_.get(); - return this; - } - MaybePopulateChildrenOfAny(current_); - Node* child = current_->FindChild(name); - if (child == nullptr || child->kind() != LIST) { - std::unique_ptr<Node> node(CreateNewNode( - std::string(name), nullptr, LIST, DataPiece::NullData(), false, - child == nullptr ? current_->path() : child->path(), - suppress_empty_list_, preserve_proto_field_names_, use_ints_for_enums_, - field_scrub_callback_)); - child = node.get(); - current_->AddChild(node.release()); - } - child->set_is_placeholder(false); - - stack_.push(current_); - current_ = child; - return this; -} - -void DefaultValueObjectWriter::WriteRoot() { - root_->WriteTo(ow_); - root_.reset(nullptr); - current_ = nullptr; -} - -DefaultValueObjectWriter* DefaultValueObjectWriter::EndList() { - if (stack_.empty()) { - WriteRoot(); - return this; - } - current_ = stack_.top(); - stack_.pop(); - return this; -} - -void DefaultValueObjectWriter::RenderDataPiece(StringPiece name, - const DataPiece& data) { - MaybePopulateChildrenOfAny(current_); - if (current_->type() != nullptr && current_->type()->name() == kAnyType && - name == "@type") { - util::StatusOr<std::string> data_string = data.ToString(); - if (data_string.ok()) { - const std::string& string_value = data_string.value(); - // If the type of current_ is "Any" and its "@type" field is being set - // here, sets the type of current_ to be the type specified by the - // "@type". - util::StatusOr<const google::protobuf::Type*> found_type = - typeinfo_->ResolveTypeUrl(string_value); - if (!found_type.ok()) { - GOOGLE_LOG(WARNING) << "Failed to resolve type '" << string_value << "'."; - } else { - current_->set_type(found_type.value()); - } - current_->set_is_any(true); - // If the "@type" field is placed after other fields, we should populate - // other children of primitive type now. Otherwise, we should wait until - // the first value field is rendered before we populate the children, - // because the "value" field of a Any message could be omitted. - if (current_->number_of_children() > 1 && current_->type() != nullptr) { - current_->PopulateChildren(typeinfo_); - } - } - } - Node* child = current_->FindChild(name); - if (child == nullptr || child->kind() != PRIMITIVE) { - // No children are found, creates a new child. - std::unique_ptr<Node> node( - CreateNewNode(std::string(name), nullptr, PRIMITIVE, data, false, - child == nullptr ? current_->path() : child->path(), - suppress_empty_list_, preserve_proto_field_names_, - use_ints_for_enums_, field_scrub_callback_)); - current_->AddChild(node.release()); - } else { - child->set_data(data); - child->set_is_placeholder(false); - } -} - -} // namespace converter -} // namespace util -} // namespace protobuf -} // namespace google diff --git a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/default_value_objectwriter.h b/contrib/libs/protobuf_std/src/google/protobuf/util/internal/default_value_objectwriter.h deleted file mode 100644 index 8236f0a4fd..0000000000 --- a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/default_value_objectwriter.h +++ /dev/null @@ -1,332 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_DEFAULT_VALUE_OBJECTWRITER_H__ -#define GOOGLE_PROTOBUF_UTIL_CONVERTER_DEFAULT_VALUE_OBJECTWRITER_H__ - -#include <cstdint> -#include <functional> -#include <memory> -#include <stack> -#include <vector> - -#include <google/protobuf/stubs/common.h> -#include <google/protobuf/util/internal/type_info.h> -#include <google/protobuf/util/internal/datapiece.h> -#include <google/protobuf/util/internal/object_writer.h> -#include <google/protobuf/util/internal/utility.h> -#include <google/protobuf/util/type_resolver.h> -#include <google/protobuf/stubs/strutil.h> - -// Must be included last. -#include <google/protobuf/port_def.inc> - -namespace google { -namespace protobuf { -namespace util { -namespace converter { - -// An ObjectWriter that renders non-repeated primitive fields of proto messages -// with their default values. DefaultValueObjectWriter holds objects, lists and -// fields it receives in a tree structure and writes them out to another -// ObjectWriter when EndObject() is called on the root object. It also writes -// out all non-repeated primitive fields that haven't been explicitly rendered -// with their default values (0 for numbers, "" for strings, etc). -class PROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter { - public: - // A Callback function to check whether a field needs to be scrubbed. - // - // Returns true if the field should not be present in the output. Returns - // false otherwise. - // - // The 'path' parameter is a vector of path to the field from root. For - // example: if a nested field "a.b.c" (b is the parent message field of c and - // a is the parent message field of b), then the vector should contain { "a", - // "b", "c" }. - // - // The Field* should point to the google::protobuf::Field of "c". - typedef std::function<bool( - const std::vector<std::string>& /*path of the field*/, - const google::protobuf::Field* /*field*/)> - FieldScrubCallBack; - - DefaultValueObjectWriter(TypeResolver* type_resolver, - const google::protobuf::Type& type, - ObjectWriter* ow); - - virtual ~DefaultValueObjectWriter(); - - // ObjectWriter methods. - DefaultValueObjectWriter* StartObject(StringPiece name) override; - - DefaultValueObjectWriter* EndObject() override; - - DefaultValueObjectWriter* StartList(StringPiece name) override; - - DefaultValueObjectWriter* EndList() override; - - DefaultValueObjectWriter* RenderBool(StringPiece name, - bool value) override; - - DefaultValueObjectWriter* RenderInt32(StringPiece name, - int32_t value) override; - - DefaultValueObjectWriter* RenderUint32(StringPiece name, - uint32_t value) override; - - DefaultValueObjectWriter* RenderInt64(StringPiece name, - int64_t value) override; - - DefaultValueObjectWriter* RenderUint64(StringPiece name, - uint64_t value) override; - - DefaultValueObjectWriter* RenderDouble(StringPiece name, - double value) override; - - DefaultValueObjectWriter* RenderFloat(StringPiece name, - float value) override; - - DefaultValueObjectWriter* RenderString(StringPiece name, - StringPiece value) override; - DefaultValueObjectWriter* RenderBytes(StringPiece name, - StringPiece value) override; - - DefaultValueObjectWriter* RenderNull(StringPiece name) override; - - // Register the callback for scrubbing of fields. - void RegisterFieldScrubCallBack(FieldScrubCallBack field_scrub_callback); - - // If set to true, empty lists are suppressed from output when default values - // are written. - void set_suppress_empty_list(bool value) { suppress_empty_list_ = value; } - - // If set to true, original proto field names are used - void set_preserve_proto_field_names(bool value) { - preserve_proto_field_names_ = value; - } - - // If set to true, enums are rendered as ints from output when default values - // are written. - void set_print_enums_as_ints(bool value) { use_ints_for_enums_ = value; } - - protected: - enum NodeKind { - PRIMITIVE = 0, - OBJECT = 1, - LIST = 2, - MAP = 3, - }; - - // "Node" represents a node in the tree that holds the input of - // DefaultValueObjectWriter. - class PROTOBUF_EXPORT Node { - public: - Node(const std::string& name, const google::protobuf::Type* type, - NodeKind kind, const DataPiece& data, bool is_placeholder, - const std::vector<std::string>& path, bool suppress_empty_list, - bool preserve_proto_field_names, bool use_ints_for_enums, - FieldScrubCallBack field_scrub_callback); - virtual ~Node() { - for (int i = 0; i < children_.size(); ++i) { - delete children_[i]; - } - } - - // Adds a child to this node. Takes ownership of this child. - void AddChild(Node* child) { children_.push_back(child); } - - // Finds the child given its name. - Node* FindChild(StringPiece name); - - // Populates children of this Node based on its type. If there are already - // children created, they will be merged to the result. Caller should pass - // in TypeInfo for looking up types of the children. - virtual void PopulateChildren(const TypeInfo* typeinfo); - - // If this node is a leaf (has data), writes the current node to the - // ObjectWriter; if not, then recursively writes the children to the - // ObjectWriter. - virtual void WriteTo(ObjectWriter* ow); - - // Accessors - const std::string& name() const { return name_; } - - const std::vector<std::string>& path() const { return path_; } - - const google::protobuf::Type* type() const { return type_; } - - void set_type(const google::protobuf::Type* type) { type_ = type; } - - NodeKind kind() const { return kind_; } - - int number_of_children() const { return children_.size(); } - - void set_data(const DataPiece& data) { data_ = data; } - - bool is_any() const { return is_any_; } - - void set_is_any(bool is_any) { is_any_ = is_any; } - - void set_is_placeholder(bool is_placeholder) { - is_placeholder_ = is_placeholder; - } - - protected: - // Returns the Value Type of a map given the Type of the map entry and a - // TypeInfo instance. - const google::protobuf::Type* GetMapValueType( - const google::protobuf::Type& found_type, const TypeInfo* typeinfo); - - // Calls WriteTo() on every child in children_. - void WriteChildren(ObjectWriter* ow); - - // The name of this node. - std::string name_; - // google::protobuf::Type of this node. Owned by TypeInfo. - const google::protobuf::Type* type_; - // The kind of this node. - NodeKind kind_; - // Whether this is a node for "Any". - bool is_any_; - // The data of this node when it is a leaf node. - DataPiece data_; - // Children of this node. - std::vector<Node*> children_; - // Whether this node is a placeholder for an object or list automatically - // generated when creating the parent node. Should be set to false after - // the parent node's StartObject()/StartList() method is called with this - // node's name. - bool is_placeholder_; - - // Path of the field of this node - std::vector<std::string> path_; - - // Whether to suppress empty list output. - bool suppress_empty_list_; - - // Whether to preserve original proto field names - bool preserve_proto_field_names_; - - // Whether to always print enums as ints - bool use_ints_for_enums_; - - // Function for determining whether a field needs to be scrubbed or not. - FieldScrubCallBack field_scrub_callback_; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Node); - }; - - // Creates a new Node and returns it. Caller owns memory of returned object. - virtual Node* CreateNewNode(const std::string& name, - const google::protobuf::Type* type, NodeKind kind, - const DataPiece& data, bool is_placeholder, - const std::vector<std::string>& path, - bool suppress_empty_list, - bool preserve_proto_field_names, - bool use_ints_for_enums, - FieldScrubCallBack field_scrub_callback); - - // Creates a DataPiece containing the default value of the type of the field. - static DataPiece CreateDefaultDataPieceForField( - const google::protobuf::Field& field, const TypeInfo* typeinfo) { - return CreateDefaultDataPieceForField(field, typeinfo, false); - } - - // Same as the above but with a flag to use ints instead of enum names. - static DataPiece CreateDefaultDataPieceForField( - const google::protobuf::Field& field, const TypeInfo* typeinfo, - bool use_ints_for_enums); - - protected: - // Returns a pointer to current Node in tree. - Node* current() { return current_; } - - private: - // Populates children of "node" if it is an "any" Node and its real type has - // been given. - void MaybePopulateChildrenOfAny(Node* node); - - // Writes the root_ node to ow_ and resets the root_ and current_ pointer to - // nullptr. - void WriteRoot(); - - // Adds or replaces the data_ of a primitive child node. - void RenderDataPiece(StringPiece name, const DataPiece& data); - - // Returns the default enum value as a DataPiece, or the first enum value if - // there is no default. For proto3, where we cannot specify an explicit - // default, a zero value will always be returned. - static DataPiece FindEnumDefault(const google::protobuf::Field& field, - const TypeInfo* typeinfo, - bool use_ints_for_enums); - - // Type information for all the types used in the descriptor. Used to find - // google::protobuf::Type of nested messages/enums. - const TypeInfo* typeinfo_; - // Whether the TypeInfo object is owned by this class. - bool own_typeinfo_; - // google::protobuf::Type of the root message type. - const google::protobuf::Type& type_; - // Holds copies of strings passed to RenderString. - std::vector<std::unique_ptr<std::string>> string_values_; - - // The current Node. Owned by its parents. - Node* current_; - // The root Node. - std::unique_ptr<Node> root_; - // The stack to hold the path of Nodes from current_ to root_; - std::stack<Node*> stack_; - - // Whether to suppress output of empty lists. - bool suppress_empty_list_; - - // Whether to preserve original proto field names - bool preserve_proto_field_names_; - - // Whether to always print enums as ints - bool use_ints_for_enums_; - - // Function for determining whether a field needs to be scrubbed or not. - FieldScrubCallBack field_scrub_callback_; - - ObjectWriter* ow_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DefaultValueObjectWriter); -}; - -} // namespace converter -} // namespace util -} // namespace protobuf -} // namespace google - -#include <google/protobuf/port_undef.inc> - -#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_DEFAULT_VALUE_OBJECTWRITER_H__ diff --git a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/error_listener.cc b/contrib/libs/protobuf_std/src/google/protobuf/util/internal/error_listener.cc deleted file mode 100644 index 538307bae2..0000000000 --- a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/error_listener.cc +++ /dev/null @@ -1,42 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include <google/protobuf/util/internal/error_listener.h> - -namespace google { -namespace protobuf { -namespace util { -namespace converter { - - -} // namespace converter -} // namespace util -} // namespace protobuf -} // namespace google diff --git a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/error_listener.h b/contrib/libs/protobuf_std/src/google/protobuf/util/internal/error_listener.h deleted file mode 100644 index 07cb95701d..0000000000 --- a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/error_listener.h +++ /dev/null @@ -1,109 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_ERROR_LISTENER_H__ -#define GOOGLE_PROTOBUF_UTIL_CONVERTER_ERROR_LISTENER_H__ - -#include <algorithm> -#include <memory> -#include <string> -#include <vector> - -#include <google/protobuf/stubs/callback.h> -#include <google/protobuf/stubs/common.h> -#include <google/protobuf/stubs/logging.h> -#include <google/protobuf/util/internal/location_tracker.h> -#include <google/protobuf/stubs/strutil.h> - -// Must be included last. -#include <google/protobuf/port_def.inc> - -namespace google { -namespace protobuf { -namespace util { -namespace converter { - -// Interface for error listener. -class PROTOBUF_EXPORT ErrorListener { - public: - virtual ~ErrorListener() {} - - // Reports an invalid name at the given location. - virtual void InvalidName(const LocationTrackerInterface& loc, - StringPiece invalid_name, - StringPiece message) = 0; - - // Reports an invalid value for a field. - virtual void InvalidValue(const LocationTrackerInterface& loc, - StringPiece type_name, - StringPiece value) = 0; - - // Reports a missing required field. - virtual void MissingField(const LocationTrackerInterface& loc, - StringPiece missing_name) = 0; - - protected: - ErrorListener() {} - - private: - // Do not add any data members to this class. - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ErrorListener); -}; - -// An error listener that ignores all errors. -class PROTOBUF_EXPORT NoopErrorListener : public ErrorListener { - public: - NoopErrorListener() {} - ~NoopErrorListener() override {} - - void InvalidName(const LocationTrackerInterface& loc, - StringPiece invalid_name, - StringPiece message) override {} - - void InvalidValue(const LocationTrackerInterface& loc, - StringPiece type_name, - StringPiece value) override {} - - void MissingField(const LocationTrackerInterface& loc, - StringPiece missing_name) override {} - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(NoopErrorListener); -}; - - -} // namespace converter -} // namespace util -} // namespace protobuf -} // namespace google - -#include <google/protobuf/port_undef.inc> - -#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_ERROR_LISTENER_H__ diff --git a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/field_mask_utility.cc b/contrib/libs/protobuf_std/src/google/protobuf/util/internal/field_mask_utility.cc deleted file mode 100644 index f211a5402b..0000000000 --- a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/field_mask_utility.cc +++ /dev/null @@ -1,218 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include <google/protobuf/util/internal/field_mask_utility.h> - -#include <google/protobuf/util/internal/utility.h> -#include <google/protobuf/stubs/status.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/stubs/status_macros.h> - -// Must be included last. -#include <google/protobuf/port_def.inc> - -namespace google { -namespace protobuf { -namespace util { -namespace converter { - -namespace { - -// Appends a FieldMask path segment to a prefix. -std::string AppendPathSegmentToPrefix(StringPiece prefix, - StringPiece segment) { - if (prefix.empty()) { - return std::string(segment); - } - if (segment.empty()) { - return std::string(prefix); - } - // If the segment is a map key, appends it to the prefix without the ".". - if (HasPrefixString(segment, "[\"")) { - return StrCat(prefix, segment); - } - return StrCat(prefix, ".", segment); -} - -} // namespace - -std::string ConvertFieldMaskPath(const StringPiece path, - ConverterCallback converter) { - std::string result; - result.reserve(path.size() << 1); - - bool is_quoted = false; - bool is_escaping = false; - int current_segment_start = 0; - - // Loops until 1 passed the end of the input to make handling the last - // segment easier. - for (size_t i = 0; i <= path.size(); ++i) { - // Outputs quoted string as-is. - if (is_quoted) { - if (i == path.size()) { - break; - } - result.push_back(path[i]); - if (is_escaping) { - is_escaping = false; - } else if (path[i] == '\\') { - is_escaping = true; - } else if (path[i] == '\"') { - current_segment_start = i + 1; - is_quoted = false; - } - continue; - } - if (i == path.size() || path[i] == '.' || path[i] == '(' || - path[i] == ')' || path[i] == '\"') { - result += converter( - path.substr(current_segment_start, i - current_segment_start)); - if (i < path.size()) { - result.push_back(path[i]); - } - current_segment_start = i + 1; - } - if (i < path.size() && path[i] == '\"') { - is_quoted = true; - } - } - return result; -} - -util::Status DecodeCompactFieldMaskPaths(StringPiece paths, - PathSinkCallback path_sink) { - std::stack<std::string> prefix; - int length = paths.length(); - int previous_position = 0; - bool in_map_key = false; - bool is_escaping = false; - // Loops until 1 passed the end of the input to make the handle of the last - // segment easier. - for (int i = 0; i <= length; ++i) { - if (i != length) { - // Skips everything in a map key until we hit the end of it, which is - // marked by an un-escaped '"' immediately followed by a ']'. - if (in_map_key) { - if (is_escaping) { - is_escaping = false; - continue; - } - if (paths[i] == '\\') { - is_escaping = true; - continue; - } - if (paths[i] != '\"') { - continue; - } - // Un-escaped '"' must be followed with a ']'. - if (i >= length - 1 || paths[i + 1] != ']') { - return util::InvalidArgumentError(StrCat( - "Invalid FieldMask '", paths, - "'. Map keys should be represented as [\"some_key\"].")); - } - // The end of the map key ("\"]") has been found. - in_map_key = false; - // Skips ']'. - i++; - // Checks whether the key ends at the end of a path segment. - if (i < length - 1 && paths[i + 1] != '.' && paths[i + 1] != ',' && - paths[i + 1] != ')' && paths[i + 1] != '(') { - return util::InvalidArgumentError(StrCat( - "Invalid FieldMask '", paths, - "'. Map keys should be at the end of a path segment.")); - } - is_escaping = false; - continue; - } - - // We are not in a map key, look for the start of one. - if (paths[i] == '[') { - if (i >= length - 1 || paths[i + 1] != '\"') { - return util::InvalidArgumentError(StrCat( - "Invalid FieldMask '", paths, - "'. Map keys should be represented as [\"some_key\"].")); - } - // "[\"" starts a map key. - in_map_key = true; - i++; // Skips the '\"'. - continue; - } - // If the current character is not a special character (',', '(' or ')'), - // continue to the next. - if (paths[i] != ',' && paths[i] != ')' && paths[i] != '(') { - continue; - } - } - // Gets the current segment - sub-string between previous position (after - // '(', ')', ',', or the beginning of the input) and the current position. - StringPiece segment = - paths.substr(previous_position, i - previous_position); - std::string current_prefix = prefix.empty() ? "" : prefix.top(); - - if (i < length && paths[i] == '(') { - // Builds a prefix and save it into the stack. - prefix.push(AppendPathSegmentToPrefix(current_prefix, segment)); - } else if (!segment.empty()) { - // When the current character is ')', ',' or the current position has - // passed the end of the input, builds and outputs a new paths by - // concatenating the last prefix with the current segment. - RETURN_IF_ERROR( - path_sink(AppendPathSegmentToPrefix(current_prefix, segment))); - } - - // Removes the last prefix after seeing a ')'. - if (i < length && paths[i] == ')') { - if (prefix.empty()) { - return util::InvalidArgumentError( - StrCat("Invalid FieldMask '", paths, - "'. Cannot find matching '(' for all ')'.")); - } - prefix.pop(); - } - previous_position = i + 1; - } - if (in_map_key) { - return util::InvalidArgumentError( - StrCat("Invalid FieldMask '", paths, - "'. Cannot find matching ']' for all '['.")); - } - if (!prefix.empty()) { - return util::InvalidArgumentError( - StrCat("Invalid FieldMask '", paths, - "'. Cannot find matching ')' for all '('.")); - } - return util::Status(); -} - -} // namespace converter -} // namespace util -} // namespace protobuf -} // namespace google diff --git a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/field_mask_utility.h b/contrib/libs/protobuf_std/src/google/protobuf/util/internal/field_mask_utility.h deleted file mode 100644 index bc41321220..0000000000 --- a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/field_mask_utility.h +++ /dev/null @@ -1,74 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// FieldMask related utility methods. - -#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_FIELD_MASK_UTILITY_H__ -#define GOOGLE_PROTOBUF_UTIL_CONVERTER_FIELD_MASK_UTILITY_H__ - -#include <functional> -#include <stack> - -#include <google/protobuf/stubs/callback.h> -#include <google/protobuf/stubs/common.h> -#include <google/protobuf/stubs/status.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/stubs/status.h> - -namespace google { -namespace protobuf { -namespace util { -namespace converter { - -typedef std::function<std::string(StringPiece)> ConverterCallback; -typedef std::function<util::Status(StringPiece)> PathSinkCallback; - -// Applies a 'converter' to each segment of a FieldMask path and returns the -// result. Quoted strings in the 'path' are copied to the output as-is without -// converting their content. Escaping is supported within quoted strings. -// For example, "ab\"_c" will be returned as "ab\"_c" without any changes. -std::string ConvertFieldMaskPath(const StringPiece path, - ConverterCallback converter); - -// Decodes a compact list of FieldMasks. For example, "a.b,a.c.d,a.c.e" will be -// decoded into a list of field paths - "a.b", "a.c.d", "a.c.e". And the results -// will be sent to 'path_sink', i.e. 'path_sink' will be called once per -// resulting path. -// Note that we also support Apiary style FieldMask form. The above example in -// the Apiary style will look like "a.b,a.c(d,e)". -util::Status DecodeCompactFieldMaskPaths(StringPiece paths, - PathSinkCallback path_sink); - -} // namespace converter -} // namespace util -} // namespace protobuf -} // namespace google - -#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_FIELD_MASK_UTILITY_H__ diff --git a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/json_escaping.cc b/contrib/libs/protobuf_std/src/google/protobuf/util/internal/json_escaping.cc deleted file mode 100644 index e4fa8cf788..0000000000 --- a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/json_escaping.cc +++ /dev/null @@ -1,372 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include <google/protobuf/util/internal/json_escaping.h> - -#include <cstdint> - -#include <google/protobuf/stubs/logging.h> -#include <google/protobuf/stubs/common.h> - -namespace google { -namespace protobuf { -namespace util { -namespace converter { - -namespace { - -// Array of hex characters for conversion to hex. -static const char kHex[] = "0123456789abcdef"; - -// Characters 0x00 to 0x9f are very commonly used, so we provide a special -// table lookup. -// -// For unicode code point ch < 0xa0: -// kCommonEscapes[ch] is the escaped string of ch, if escaping is needed; -// or an empty string, if escaping is not needed. -static const char kCommonEscapes[160][7] = { - // C0 (ASCII and derivatives) control characters - "\\u0000", "\\u0001", "\\u0002", "\\u0003", // 0x00 - "\\u0004", "\\u0005", "\\u0006", "\\u0007", "\\b", "\\t", "\\n", "\\u000b", - "\\f", "\\r", "\\u000e", "\\u000f", "\\u0010", "\\u0011", "\\u0012", - "\\u0013", // 0x10 - "\\u0014", "\\u0015", "\\u0016", "\\u0017", "\\u0018", "\\u0019", "\\u001a", - "\\u001b", "\\u001c", "\\u001d", "\\u001e", "\\u001f", - // Escaping of " and \ are required by www.json.org string definition. - // Escaping of < and > are required for HTML security. - "", "", "\\\"", "", "", "", "", "", // 0x20 - "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", // 0x30 - "", "", "", "", "\\u003c", "", "\\u003e", "", "", "", "", "", "", "", "", - "", // 0x40 - "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", // 0x50 - "", "", "", "", "\\\\", "", "", "", "", "", "", "", "", "", "", "", // 0x60 - "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", // 0x70 - "", "", "", "", "", "", "", "\\u007f", - // C1 (ISO 8859 and Unicode) extended control characters - "\\u0080", "\\u0081", "\\u0082", "\\u0083", // 0x80 - "\\u0084", "\\u0085", "\\u0086", "\\u0087", "\\u0088", "\\u0089", "\\u008a", - "\\u008b", "\\u008c", "\\u008d", "\\u008e", "\\u008f", "\\u0090", "\\u0091", - "\\u0092", "\\u0093", // 0x90 - "\\u0094", "\\u0095", "\\u0096", "\\u0097", "\\u0098", "\\u0099", "\\u009a", - "\\u009b", "\\u009c", "\\u009d", "\\u009e", "\\u009f"}; - -// Determines if the given char value is a unicode surrogate code unit (either -// high-surrogate or low-surrogate). -inline bool IsSurrogate(uint32_t c) { - // Optimized form of: - // return c >= kMinHighSurrogate && c <= kMaxLowSurrogate; - // (Reduced from 3 ALU instructions to 2 ALU instructions) - return (c & 0xfffff800) == JsonEscaping::kMinHighSurrogate; -} - -// Returns true if the given unicode code point cp is a valid -// unicode code point (i.e. in the range 0 <= cp <= kMaxCodePoint). -inline bool IsValidCodePoint(uint32_t cp) { - return cp <= JsonEscaping::kMaxCodePoint; -} - -// Returns the low surrogate for the given unicode code point. The result is -// meaningless if the given code point is not a supplementary character. -inline uint16_t ToLowSurrogate(uint32_t cp) { - return (cp & - (JsonEscaping::kMaxLowSurrogate - JsonEscaping::kMinLowSurrogate)) + - JsonEscaping::kMinLowSurrogate; -} - -// Returns the high surrogate for the given unicode code point. The result is -// meaningless if the given code point is not a supplementary character. -inline uint16_t ToHighSurrogate(uint32_t cp) { - return (cp >> 10) + (JsonEscaping::kMinHighSurrogate - - (JsonEscaping::kMinSupplementaryCodePoint >> 10)); -} - -// Input str is encoded in UTF-8. A unicode code point could be encoded in -// UTF-8 using anywhere from 1 to 4 characters, and it could span multiple -// reads of the ByteSource. -// -// This function reads the next unicode code point from the input (str) at -// the given position (index), taking into account any left-over partial -// code point from the previous iteration (cp), together with the number -// of characters left to read to complete this code point (num_left). -// -// This function assumes that the input (str) is valid at the given position -// (index). In order words, at least one character could be read successfully. -// -// The code point read (partial or complete) is stored in (cp). Upon return, -// (num_left) stores the number of characters that has yet to be read in -// order to complete the current unicode code point. If the read is complete, -// then (num_left) is 0. Also, (num_read) is the number of characters read. -// -// Returns false if we encounter an invalid UTF-8 string. Returns true -// otherwise, including the case when we reach the end of the input (str) -// before a complete unicode code point is read. -bool ReadCodePoint(StringPiece str, int index, uint32_t* cp, - int* num_left, int* num_read) { - if (*num_left == 0) { - // Last read was complete. Start reading a new unicode code point. - *cp = static_cast<uint8_t>(str[index++]); - *num_read = 1; - // The length of the code point is determined from reading the first byte. - // - // If the first byte is between: - // 0..0x7f: that's the value of the code point. - // 0x80..0xbf: <invalid> - // 0xc0..0xdf: 11-bit code point encoded in 2 bytes. - // bit 10-6, bit 5-0 - // 0xe0..0xef: 16-bit code point encoded in 3 bytes. - // bit 15-12, bit 11-6, bit 5-0 - // 0xf0..0xf7: 21-bit code point encoded in 4 bytes. - // bit 20-18, bit 17-12, bit 11-6, bit 5-0 - // 0xf8..0xff: <invalid> - // - // Meaning of each bit: - // <msb> bit 7: 0 - single byte code point: bits 6-0 are values. - // 1 - multibyte code point - // bit 6: 0 - subsequent bytes of multibyte code point: - // bits 5-0 are values. - // 1 - first byte of multibyte code point - // bit 5: 0 - first byte of 2-byte code point: bits 4-0 are values. - // 1 - first byte of code point with >= 3 bytes. - // bit 4: 0 - first byte of 3-byte code point: bits 3-0 are values. - // 1 - first byte of code point with >= 4 bytes. - // bit 3: 0 - first byte of 4-byte code point: bits 2-0 are values. - // 1 - reserved for future expansion. - if (*cp <= 0x7f) { - return true; - } else if (*cp <= 0xbf) { - return false; - } else if (*cp <= 0xdf) { - *cp &= 0x1f; - *num_left = 1; - } else if (*cp <= 0xef) { - *cp &= 0x0f; - *num_left = 2; - } else if (*cp <= 0xf7) { - *cp &= 0x07; - *num_left = 3; - } else { - return false; - } - } else { - // Last read was partial. Initialize num_read to 0 and continue reading - // the last unicode code point. - *num_read = 0; - } - while (*num_left > 0 && index < str.size()) { - uint32_t ch = static_cast<uint8_t>(str[index++]); - --(*num_left); - ++(*num_read); - *cp = (*cp << 6) | (ch & 0x3f); - if (ch < 0x80 || ch > 0xbf) return false; - } - return *num_left > 0 || (!IsSurrogate(*cp) && IsValidCodePoint(*cp)); -} - -// Stores the 16-bit unicode code point as its hexadecimal digits in buffer -// and returns a StringPiece that points to this buffer. The input buffer needs -// to be at least 6 bytes long. -StringPiece ToHex(uint16_t cp, char* buffer) { - buffer[5] = kHex[cp & 0x0f]; - cp >>= 4; - buffer[4] = kHex[cp & 0x0f]; - cp >>= 4; - buffer[3] = kHex[cp & 0x0f]; - cp >>= 4; - buffer[2] = kHex[cp & 0x0f]; - return StringPiece(buffer, 6); -} - -// Stores the 32-bit unicode code point as its hexadecimal digits in buffer -// and returns a StringPiece that points to this buffer. The input buffer needs -// to be at least 12 bytes long. -StringPiece ToSurrogateHex(uint32_t cp, char* buffer) { - uint16_t low = ToLowSurrogate(cp); - uint16_t high = ToHighSurrogate(cp); - - buffer[11] = kHex[low & 0x0f]; - low >>= 4; - buffer[10] = kHex[low & 0x0f]; - low >>= 4; - buffer[9] = kHex[low & 0x0f]; - low >>= 4; - buffer[8] = kHex[low & 0x0f]; - - buffer[5] = kHex[high & 0x0f]; - high >>= 4; - buffer[4] = kHex[high & 0x0f]; - high >>= 4; - buffer[3] = kHex[high & 0x0f]; - high >>= 4; - buffer[2] = kHex[high & 0x0f]; - - return StringPiece(buffer, 12); -} - -// If the given unicode code point needs escaping, then returns the -// escaped form. The returned StringPiece either points to statically -// pre-allocated char[] or to the given buffer. The input buffer needs -// to be at least 12 bytes long. -// -// If the given unicode code point does not need escaping, an empty -// StringPiece is returned. -StringPiece EscapeCodePoint(uint32_t cp, char* buffer) { - if (cp < 0xa0) return kCommonEscapes[cp]; - switch (cp) { - // These are not required by json spec - // but used to prevent security bugs in javascript. - case 0xfeff: // Zero width no-break space - case 0xfff9: // Interlinear annotation anchor - case 0xfffa: // Interlinear annotation separator - case 0xfffb: // Interlinear annotation terminator - - case 0x00ad: // Soft-hyphen - case 0x06dd: // Arabic end of ayah - case 0x070f: // Syriac abbreviation mark - case 0x17b4: // Khmer vowel inherent Aq - case 0x17b5: // Khmer vowel inherent Aa - return ToHex(cp, buffer); - - default: - if ((cp >= 0x0600 && cp <= 0x0603) || // Arabic signs - (cp >= 0x200b && cp <= 0x200f) || // Zero width etc. - (cp >= 0x2028 && cp <= 0x202e) || // Separators etc. - (cp >= 0x2060 && cp <= 0x2064) || // Invisible etc. - (cp >= 0x206a && cp <= 0x206f)) { // Shaping etc. - return ToHex(cp, buffer); - } - - if (cp == 0x000e0001 || // Language tag - (cp >= 0x0001d173 && cp <= 0x0001d17a) || // Music formatting - (cp >= 0x000e0020 && cp <= 0x000e007f)) { // TAG symbols - return ToSurrogateHex(cp, buffer); - } - } - return StringPiece(); -} - -// Tries to escape the given code point first. If the given code point -// does not need to be escaped, but force_output is true, then render -// the given multi-byte code point in UTF8 in the buffer and returns it. -StringPiece EscapeCodePoint(uint32_t cp, char* buffer, - bool force_output) { - StringPiece sp = EscapeCodePoint(cp, buffer); - if (force_output && sp.empty()) { - buffer[5] = (cp & 0x3f) | 0x80; - cp >>= 6; - if (cp <= 0x1f) { - buffer[4] = cp | 0xc0; - sp = StringPiece(buffer + 4, 2); - return sp; - } - buffer[4] = (cp & 0x3f) | 0x80; - cp >>= 6; - if (cp <= 0x0f) { - buffer[3] = cp | 0xe0; - sp = StringPiece(buffer + 3, 3); - return sp; - } - buffer[3] = (cp & 0x3f) | 0x80; - buffer[2] = ((cp >> 6) & 0x07) | 0xf0; - sp = StringPiece(buffer + 2, 4); - } - return sp; -} - -} // namespace - -void JsonEscaping::Escape(strings::ByteSource* input, - strings::ByteSink* output) { - char buffer[12] = "\\udead\\ubee"; - uint32_t cp = 0; // Current unicode code point. - int num_left = 0; // Num of chars to read to complete the code point. - while (input->Available() > 0) { - StringPiece str = input->Peek(); - StringPiece escaped; - int i = 0; - int num_read; - bool ok; - bool cp_was_split = num_left > 0; - // Loop until we encounter either - // i) a code point that needs to be escaped; or - // ii) a split code point is completely read; or - // iii) a character that is not a valid utf8; or - // iv) end of the StringPiece str is reached. - do { - ok = ReadCodePoint(str, i, &cp, &num_left, &num_read); - if (num_left > 0 || !ok) break; // case iii or iv - escaped = EscapeCodePoint(cp, buffer, cp_was_split); - if (!escaped.empty()) break; // case i or ii - i += num_read; - num_read = 0; - } while (i < str.length()); // case iv - // First copy the un-escaped prefix, if any, to the output ByteSink. - if (i > 0) input->CopyTo(output, i); - if (num_read > 0) input->Skip(num_read); - if (!ok) { - // Case iii: Report error. - // TODO(wpoon): Add error reporting. - num_left = 0; - } else if (num_left == 0 && !escaped.empty()) { - // Case i or ii: Append the escaped code point to the output ByteSink. - output->Append(escaped.data(), escaped.size()); - } - } - if (num_left > 0) { - // Treat as case iii: report error. - // TODO(wpoon): Add error reporting. - } -} - -void JsonEscaping::Escape(StringPiece input, strings::ByteSink* output) { - const size_t len = input.length(); - const char* p = input.data(); - - bool can_skip_escaping = true; - for (int i = 0; i < len; i++) { - char c = p[i]; - if (c < 0x20 || c >= 0x7F || c == '"' || c == '<' || c == '>' || - c == '\\') { - can_skip_escaping = false; - break; - } - } - - if (can_skip_escaping) { - output->Append(input.data(), input.length()); - } else { - strings::ArrayByteSource source(input); - Escape(&source, output); - } -} - -} // namespace converter -} // namespace util -} // namespace protobuf -} // namespace google diff --git a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/json_escaping.h b/contrib/libs/protobuf_std/src/google/protobuf/util/internal/json_escaping.h deleted file mode 100644 index 38cb645ee6..0000000000 --- a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/json_escaping.h +++ /dev/null @@ -1,98 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef GOOGLE_PROTOBUF_UTIL_INTERNAL__JSON_ESCAPING_H__ -#define GOOGLE_PROTOBUF_UTIL_INTERNAL__JSON_ESCAPING_H__ - -#include <cstdint> - -#include <google/protobuf/stubs/common.h> -#include <google/protobuf/stubs/bytestream.h> - -namespace google { -namespace protobuf { -namespace util { -namespace converter { - -class JsonEscaping { - public: - // The minimum value of a unicode high-surrogate code unit in the utf-16 - // encoding. A high-surrogate is also known as a leading-surrogate. - // See http://www.unicode.org/glossary/#high_surrogate_code_unit - static constexpr uint16_t kMinHighSurrogate = 0xd800; - - // The maximum value of a unicide high-surrogate code unit in the utf-16 - // encoding. A high-surrogate is also known as a leading-surrogate. - // See http://www.unicode.org/glossary/#high_surrogate_code_unit - static constexpr uint16_t kMaxHighSurrogate = 0xdbff; - - // The minimum value of a unicode low-surrogate code unit in the utf-16 - // encoding. A low-surrogate is also known as a trailing-surrogate. - // See http://www.unicode.org/glossary/#low_surrogate_code_unit - static constexpr uint16_t kMinLowSurrogate = 0xdc00; - - // The maximum value of a unicode low-surrogate code unit in the utf-16 - // encoding. A low-surrogate is also known as a trailing surrogate. - // See http://www.unicode.org/glossary/#low_surrogate_code_unit - static constexpr uint16_t kMaxLowSurrogate = 0xdfff; - - // The minimum value of a unicode supplementary code point. - // See http://www.unicode.org/glossary/#supplementary_code_point - static constexpr uint32_t kMinSupplementaryCodePoint = 0x010000; - - // The minimum value of a unicode code point. - // See http://www.unicode.org/glossary/#code_point - static constexpr uint32_t kMinCodePoint = 0x000000; - - // The maximum value of a unicode code point. - // See http://www.unicode.org/glossary/#code_point - static constexpr uint32_t kMaxCodePoint = 0x10ffff; - - JsonEscaping() {} - virtual ~JsonEscaping() {} - - // Escape the given ByteSource to the given ByteSink. - static void Escape(strings::ByteSource* input, strings::ByteSink* output); - - // Escape the given ByteSource to the given ByteSink. - // This is optimized for the case where the string is all printable 7-bit - // ASCII and does not contain a few other characters (such as quotes). - static void Escape(StringPiece input, strings::ByteSink* output); - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(JsonEscaping); -}; - -} // namespace converter -} // namespace util -} // namespace protobuf -} // namespace google - -#endif // GOOGLE_PROTOBUF_UTIL_INTERNAL__JSON_ESCAPING_H__ diff --git a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/json_objectwriter.cc b/contrib/libs/protobuf_std/src/google/protobuf/util/internal/json_objectwriter.cc deleted file mode 100644 index c03eb1d210..0000000000 --- a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/json_objectwriter.cc +++ /dev/null @@ -1,190 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include <google/protobuf/util/internal/json_objectwriter.h> - -#include <cmath> -#include <cstdint> -#include <limits> - -#include <google/protobuf/stubs/casts.h> -#include <google/protobuf/stubs/logging.h> -#include <google/protobuf/stubs/common.h> -#include <google/protobuf/util/internal/utility.h> -#include <google/protobuf/util/internal/json_escaping.h> -#include <google/protobuf/stubs/strutil.h> - -namespace google { -namespace protobuf { -namespace util { -namespace converter { - - -JsonObjectWriter::~JsonObjectWriter() { - if (element_ && !element_->is_root()) { - GOOGLE_LOG(WARNING) << "JsonObjectWriter was not fully closed."; - } -} - -JsonObjectWriter* JsonObjectWriter::StartObject(StringPiece name) { - WritePrefix(name); - WriteChar('{'); - PushObject(); - return this; -} - -JsonObjectWriter* JsonObjectWriter::EndObject() { - Pop(); - WriteChar('}'); - if (element() && element()->is_root()) NewLine(); - return this; -} - -JsonObjectWriter* JsonObjectWriter::StartList(StringPiece name) { - WritePrefix(name); - WriteChar('['); - PushArray(); - return this; -} - -JsonObjectWriter* JsonObjectWriter::EndList() { - Pop(); - WriteChar(']'); - if (element()->is_root()) NewLine(); - return this; -} - -JsonObjectWriter* JsonObjectWriter::RenderBool(StringPiece name, - bool value) { - return RenderSimple(name, value ? "true" : "false"); -} - -JsonObjectWriter* JsonObjectWriter::RenderInt32(StringPiece name, - int32_t value) { - return RenderSimple(name, StrCat(value)); -} - -JsonObjectWriter* JsonObjectWriter::RenderUint32(StringPiece name, - uint32_t value) { - return RenderSimple(name, StrCat(value)); -} - -JsonObjectWriter* JsonObjectWriter::RenderInt64(StringPiece name, - int64_t value) { - WritePrefix(name); - WriteChar('"'); - WriteRawString(StrCat(value)); - WriteChar('"'); - return this; -} - -JsonObjectWriter* JsonObjectWriter::RenderUint64(StringPiece name, - uint64_t value) { - WritePrefix(name); - WriteChar('"'); - WriteRawString(StrCat(value)); - WriteChar('"'); - return this; -} - -JsonObjectWriter* JsonObjectWriter::RenderDouble(StringPiece name, - double value) { - if (std::isfinite(value)) { - return RenderSimple(name, SimpleDtoa(value)); - } - - // Render quoted with NaN/Infinity-aware DoubleAsString. - return RenderString(name, DoubleAsString(value)); -} - -JsonObjectWriter* JsonObjectWriter::RenderFloat(StringPiece name, - float value) { - if (std::isfinite(value)) { - return RenderSimple(name, SimpleFtoa(value)); - } - - // Render quoted with NaN/Infinity-aware FloatAsString. - return RenderString(name, FloatAsString(value)); -} - -JsonObjectWriter* JsonObjectWriter::RenderString(StringPiece name, - StringPiece value) { - WritePrefix(name); - WriteChar('"'); - JsonEscaping::Escape(value, &sink_); - WriteChar('"'); - return this; -} - -JsonObjectWriter* JsonObjectWriter::RenderBytes(StringPiece name, - StringPiece value) { - WritePrefix(name); - std::string base64; - - if (use_websafe_base64_for_bytes_) - WebSafeBase64EscapeWithPadding(std::string(value), &base64); - else - Base64Escape(value, &base64); - - WriteChar('"'); - // TODO(wpoon): Consider a ByteSink solution that writes the base64 bytes - // directly to the stream, rather than first putting them - // into a string and then writing them to the stream. - stream_->WriteRaw(base64.data(), base64.size()); - WriteChar('"'); - return this; -} - -JsonObjectWriter* JsonObjectWriter::RenderNull(StringPiece name) { - return RenderSimple(name, "null"); -} - -JsonObjectWriter* JsonObjectWriter::RenderNullAsEmpty(StringPiece name) { - return RenderSimple(name, ""); -} - -void JsonObjectWriter::WritePrefix(StringPiece name) { - bool not_first = !element()->is_first(); - if (not_first) WriteChar(','); - if (not_first || !element()->is_root()) NewLine(); - if (!name.empty() || element()->is_json_object()) { - WriteChar('"'); - if (!name.empty()) { - JsonEscaping::Escape(name, &sink_); - } - WriteRawString("\":"); - if (!indent_string_.empty()) WriteChar(' '); - } -} - -} // namespace converter -} // namespace util -} // namespace protobuf -} // namespace google diff --git a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/json_objectwriter.h b/contrib/libs/protobuf_std/src/google/protobuf/util/internal/json_objectwriter.h deleted file mode 100644 index 2e9c68483d..0000000000 --- a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/json_objectwriter.h +++ /dev/null @@ -1,278 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_JSON_OBJECTWRITER_H__ -#define GOOGLE_PROTOBUF_UTIL_CONVERTER_JSON_OBJECTWRITER_H__ - -#include <cstdint> -#include <memory> -#include <string> - -#include <google/protobuf/io/coded_stream.h> -#include <google/protobuf/util/internal/structured_objectwriter.h> -#include <google/protobuf/stubs/bytestream.h> - -// clang-format off -#include <google/protobuf/port_def.inc> -// clang-format on - -namespace google { -namespace protobuf { -namespace util { -namespace converter { - - -// An ObjectWriter implementation that outputs JSON. This ObjectWriter -// supports writing a compact form or a pretty printed form. -// -// Sample usage: -// string output; -// StringOutputStream* str_stream = new StringOutputStream(&output); -// CodedOutputStream* out_stream = new CodedOutputStream(str_stream); -// JsonObjectWriter* ow = new JsonObjectWriter(" ", out_stream); -// ow->StartObject("") -// ->RenderString("name", "value") -// ->RenderString("emptystring", string()) -// ->StartObject("nested") -// ->RenderInt64("light", 299792458); -// ->RenderDouble("pi", 3.141592653589793); -// ->EndObject() -// ->StartList("empty") -// ->EndList() -// ->EndObject(); -// -// And then the output string would become: -// { -// "name": "value", -// "emptystring": "", -// "nested": { -// "light": "299792458", -// "pi": 3.141592653589793 -// }, -// "empty": [] -// } -// -// JsonObjectWriter does not validate if calls actually result in valid JSON. -// For example, passing an empty name when one would be required won't result -// in an error, just an invalid output. -// -// Note that all int64 and uint64 are rendered as strings instead of numbers. -// This is because JavaScript parses numbers as 64-bit float thus int64 and -// uint64 would lose precision if rendered as numbers. -// -// JsonObjectWriter is thread-unsafe. -class PROTOBUF_EXPORT JsonObjectWriter : public StructuredObjectWriter { - public: - JsonObjectWriter(StringPiece indent_string, io::CodedOutputStream* out) - : element_(new Element(/*parent=*/nullptr, /*is_json_object=*/false)), - stream_(out), - sink_(out), - indent_string_(indent_string), - indent_char_('\0'), - indent_count_(0), - use_websafe_base64_for_bytes_(false) { - // See if we have a trivial sequence of indent characters. - if (!indent_string.empty()) { - indent_char_ = indent_string[0]; - indent_count_ = indent_string.length(); - for (int i = 1; i < indent_string.length(); i++) { - if (indent_char_ != indent_string_[i]) { - indent_char_ = '\0'; - indent_count_ = 0; - break; - } - } - } - } - virtual ~JsonObjectWriter(); - - // ObjectWriter methods. - JsonObjectWriter* StartObject(StringPiece name) override; - JsonObjectWriter* EndObject() override; - JsonObjectWriter* StartList(StringPiece name) override; - JsonObjectWriter* EndList() override; - JsonObjectWriter* RenderBool(StringPiece name, bool value) override; - JsonObjectWriter* RenderInt32(StringPiece name, int32_t value) override; - JsonObjectWriter* RenderUint32(StringPiece name, - uint32_t value) override; - JsonObjectWriter* RenderInt64(StringPiece name, int64_t value) override; - JsonObjectWriter* RenderUint64(StringPiece name, - uint64_t value) override; - JsonObjectWriter* RenderDouble(StringPiece name, double value) override; - JsonObjectWriter* RenderFloat(StringPiece name, float value) override; - JsonObjectWriter* RenderString(StringPiece name, - StringPiece value) override; - JsonObjectWriter* RenderBytes(StringPiece name, StringPiece value) override; - JsonObjectWriter* RenderNull(StringPiece name) override; - virtual JsonObjectWriter* RenderNullAsEmpty(StringPiece name); - - void set_use_websafe_base64_for_bytes(bool value) { - use_websafe_base64_for_bytes_ = value; - } - - protected: - class PROTOBUF_EXPORT Element : public BaseElement { - public: - Element(Element* parent, bool is_json_object) - : BaseElement(parent), - is_first_(true), - is_json_object_(is_json_object) {} - - // Called before each field of the Element is to be processed. - // Returns true if this is the first call (processing the first field). - bool is_first() { - if (is_first_) { - is_first_ = false; - return true; - } - return false; - } - - // Whether we are currently rendering inside a JSON object (i.e., between - // StartObject() and EndObject()). - bool is_json_object() const { return is_json_object_; } - - private: - bool is_first_; - bool is_json_object_; - - GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(Element); - }; - - Element* element() override { return element_.get(); } - - private: - class PROTOBUF_EXPORT ByteSinkWrapper : public strings::ByteSink { - public: - explicit ByteSinkWrapper(io::CodedOutputStream* stream) : stream_(stream) {} - ~ByteSinkWrapper() override {} - - // ByteSink methods. - void Append(const char* bytes, size_t n) override { - stream_->WriteRaw(bytes, n); - } - - private: - io::CodedOutputStream* stream_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ByteSinkWrapper); - }; - - // Renders a simple value as a string. By default all non-string Render - // methods convert their argument to a string and call this method. This - // method can then be used to render the simple value without escaping it. - JsonObjectWriter* RenderSimple(StringPiece name, - StringPiece value) { - WritePrefix(name); - WriteRawString(value); - return this; - } - - // Pushes a new JSON array element to the stack. - void PushArray() { - element_.reset(new Element(element_.release(), /*is_json_object=*/false)); - } - - // Pushes a new JSON object element to the stack. - void PushObject() { - element_.reset(new Element(element_.release(), /*is_json_object=*/true)); - } - - // Pops an element off of the stack and deletes the popped element. - void Pop() { - bool needs_newline = !element_->is_first(); - element_.reset(element_->pop<Element>()); - if (needs_newline) NewLine(); - } - - // If pretty printing is enabled, this will write a newline to the output, - // followed by optional indentation. Otherwise this method is a noop. - void NewLine() { - if (!indent_string_.empty()) { - size_t len = sizeof('\n') + (indent_string_.size() * element()->level()); - - // Take the slow-path if we don't have sufficient characters remaining in - // our buffer or we have a non-trivial indent string which would prevent - // us from using memset. - uint8_t* out = nullptr; - if (indent_count_ > 0) { - out = stream_->GetDirectBufferForNBytesAndAdvance(len); - } - - if (out != nullptr) { - out[0] = '\n'; - memset(&out[1], indent_char_, len - 1); - } else { - // Slow path, no contiguous output buffer available. - WriteChar('\n'); - for (int i = 0; i < element()->level(); i++) { - stream_->WriteRaw(indent_string_.c_str(), indent_string_.length()); - } - } - } - } - - // Writes a prefix. This will write out any pretty printing and - // commas that are required, followed by the name and a ':' if - // the name is not null. - void WritePrefix(StringPiece name); - - // Writes an individual character to the output. - void WriteChar(const char c) { stream_->WriteRaw(&c, sizeof(c)); } - - // Writes a string to the output. - void WriteRawString(StringPiece s) { - stream_->WriteRaw(s.data(), s.length()); - } - - std::unique_ptr<Element> element_; - io::CodedOutputStream* stream_; - ByteSinkWrapper sink_; - const std::string indent_string_; - - // For the common case of indent being a single character repeated. - char indent_char_; - int indent_count_; - - // Whether to use regular or websafe base64 encoding for byte fields. Defaults - // to regular base64 encoding. - bool use_websafe_base64_for_bytes_; - - GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(JsonObjectWriter); -}; - -} // namespace converter -} // namespace util -} // namespace protobuf -} // namespace google - -#include <google/protobuf/port_undef.inc> - -#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_JSON_OBJECTWRITER_H__ diff --git a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/json_stream_parser.cc b/contrib/libs/protobuf_std/src/google/protobuf/util/internal/json_stream_parser.cc deleted file mode 100644 index ff692cdba3..0000000000 --- a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/json_stream_parser.cc +++ /dev/null @@ -1,994 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include <google/protobuf/util/internal/json_stream_parser.h> - -#include <algorithm> -#include <cctype> -#include <cmath> -#include <memory> -#include <stack> -#include <string> - -#include <google/protobuf/stubs/common.h> -#include <google/protobuf/stubs/logging.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/stubs/status.h> -#include <google/protobuf/util/internal/object_writer.h> -#include <google/protobuf/util/internal/json_escaping.h> - - -namespace google { -namespace protobuf { -namespace util { - -namespace converter { - -// Number of digits in an escaped UTF-16 code unit ('\\' 'u' X X X X) -static const int kUnicodeEscapedLength = 6; - -static const int kDefaultMaxRecursionDepth = 100; - -// These cannot be constexpr for portability with VS2015. -static const StringPiece kKeywordTrue = "true"; -static const StringPiece kKeywordFalse = "false"; -static const StringPiece kKeywordNull = "null"; - -inline bool IsLetter(char c) { - return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || (c == '_') || - (c == '$'); -} - -inline bool IsAlphanumeric(char c) { - return IsLetter(c) || ('0' <= c && c <= '9'); -} - -// Indicates a character may not be part of an unquoted key. -inline bool IsKeySeparator(char c) { - return (ascii_isspace(c) || c == '"' || c == '\'' || c == '{' || - c == '}' || c == '[' || c == ']' || c == ':' || c == ','); -} - -inline void ReplaceInvalidCodePoints(StringPiece str, - const std::string& replacement, - std::string* dst) { - while (!str.empty()) { - int n_valid_bytes = internal::UTF8SpnStructurallyValid(str); - StringPiece valid_part = str.substr(0, n_valid_bytes); - StrAppend(dst, valid_part); - - if (n_valid_bytes == str.size()) { - break; - } - - // Append replacement value. - StrAppend(dst, replacement); - - // Move past valid bytes + one invalid byte. - str.remove_prefix(n_valid_bytes + 1); - } -} - -static bool ConsumeKey(StringPiece* input, StringPiece* key) { - if (input->empty() || !IsLetter((*input)[0])) return false; - int len = 1; - for (; len < input->size(); ++len) { - if (!IsAlphanumeric((*input)[len])) { - break; - } - } - *key = StringPiece(input->data(), len); - *input = StringPiece(input->data() + len, input->size() - len); - return true; -} - -// Same as 'ConsumeKey', but allows a widened set of key characters. -static bool ConsumeKeyPermissive(StringPiece* input, - StringPiece* key) { - if (input->empty() || !IsLetter((*input)[0])) return false; - int len = 1; - for (; len < input->size(); ++len) { - if (IsKeySeparator((*input)[len])) { - break; - } - } - *key = StringPiece(input->data(), len); - *input = StringPiece(input->data() + len, input->size() - len); - return true; -} - -static bool MatchKey(StringPiece input) { - return !input.empty() && IsLetter(input[0]); -} - -JsonStreamParser::JsonStreamParser(ObjectWriter* ow) - : ow_(ow), - stack_(), - leftover_(), - json_(), - p_(), - key_(), - key_storage_(), - finishing_(false), - seen_non_whitespace_(false), - allow_no_root_element_(false), - parsed_(), - parsed_storage_(), - string_open_(0), - chunk_storage_(), - coerce_to_utf8_(false), - utf8_replacement_character_(" "), - allow_empty_null_(false), - allow_permissive_key_naming_(false), - loose_float_number_conversion_(false), - recursion_depth_(0), - max_recursion_depth_(kDefaultMaxRecursionDepth) { - // Initialize the stack with a single value to be parsed. - stack_.push(VALUE); -} - -JsonStreamParser::~JsonStreamParser() {} - - -util::Status JsonStreamParser::Parse(StringPiece json) { - StringPiece chunk = json; - // If we have leftovers from a previous chunk, append the new chunk to it - // and create a new StringPiece pointing at the string's data. This could - // be large but we rely on the chunks to be small, assuming they are - // fragments of a Cord. - if (!leftover_.empty()) { - // Don't point chunk to leftover_ because leftover_ will be updated in - // ParseChunk(chunk). - chunk_storage_.swap(leftover_); - StrAppend(&chunk_storage_, json); - chunk = StringPiece(chunk_storage_); - } - - // Find the structurally valid UTF8 prefix and parse only that. - int n = internal::UTF8SpnStructurallyValid(chunk); - if (n > 0) { - util::Status status = ParseChunk(chunk.substr(0, n)); - - // Any leftover characters are stashed in leftover_ for later parsing when - // there is more data available. - StrAppend(&leftover_, chunk.substr(n)); - return status; - } else { - leftover_.assign(chunk.data(), chunk.size()); - return util::Status(); - } -} - -util::Status JsonStreamParser::FinishParse() { - // If we do not expect anything and there is nothing left to parse we're all - // done. - if (stack_.empty() && leftover_.empty()) { - return util::Status(); - } - - // Lifetime needs to last until RunParser returns, so keep this variable - // outside of the coerce_to_utf8 block. - std::unique_ptr<std::string> scratch; - - bool is_valid_utf8 = internal::IsStructurallyValidUTF8(leftover_); - if (coerce_to_utf8_ && !is_valid_utf8) { - scratch.reset(new std::string); - scratch->reserve(leftover_.size() * utf8_replacement_character_.size()); - ReplaceInvalidCodePoints(leftover_, utf8_replacement_character_, - scratch.get()); - p_ = json_ = *scratch; - } else { - p_ = json_ = leftover_; - if (!is_valid_utf8) { - return ReportFailure("Encountered non UTF-8 code points.", - ParseErrorType::NON_UTF_8); - } - } - - // Parse the remainder in finishing mode, which reports errors for things like - // unterminated strings or unknown tokens that would normally be retried. - finishing_ = true; - util::Status result = RunParser(); - if (result.ok()) { - SkipWhitespace(); - if (!p_.empty()) { - result = - ReportFailure("Parsing terminated before end of input.", - ParseErrorType::PARSING_TERMINATED_BEFORE_END_OF_INPUT); - } - } - return result; -} - -util::Status JsonStreamParser::ParseChunk(StringPiece chunk) { - // Do not do any work if the chunk is empty. - if (chunk.empty()) return util::Status(); - - p_ = json_ = chunk; - - finishing_ = false; - util::Status result = RunParser(); - if (!result.ok()) return result; - - SkipWhitespace(); - if (p_.empty()) { - // If we parsed everything we had, clear the leftover. - leftover_.clear(); - } else { - // If we do not expect anything i.e. stack is empty, and we have non-empty - // string left to parse, we report an error. - if (stack_.empty()) { - return ReportFailure( - "Parsing terminated before end of input.", - ParseErrorType::PARSING_TERMINATED_BEFORE_END_OF_INPUT); - } - // If we expect future data i.e. stack is non-empty, and we have some - // unparsed data left, we save it for later parse. - leftover_ = std::string(p_); - } - return util::Status(); -} - -bool JsonStreamParser::IsInputAllWhiteSpaces(TokenType type) { - // Conclude the whole input is full of white spaces by: - // - it is at the finishing stage - // - we have run out of the input data - // - haven't seen non-whitespace char so far - if (finishing_ && p_.empty() && type == UNKNOWN && !seen_non_whitespace_) { - return true; - } - return false; -} - -util::Status JsonStreamParser::RunParser() { - while (!stack_.empty()) { - ParseType type = stack_.top(); - TokenType t = (string_open_ == 0) ? GetNextTokenType() : BEGIN_STRING; - stack_.pop(); - util::Status result; - switch (type) { - case VALUE: - if (allow_no_root_element_ && IsInputAllWhiteSpaces(t)) { - return util::Status(); - } - result = ParseValue(t); - break; - - case OBJ_MID: - result = ParseObjectMid(t); - break; - - case ENTRY: - result = ParseEntry(t); - break; - - case ENTRY_MID: - result = ParseEntryMid(t); - break; - - case ARRAY_VALUE: - result = ParseArrayValue(t); - break; - - case ARRAY_MID: - result = ParseArrayMid(t); - break; - - default: - result = - util::InternalError(StrCat("Unknown parse type: ", type)); - break; - } - if (!result.ok()) { - // If we were cancelled, save our state and try again later. - if (!finishing_ && util::IsCancelled(result)) { - stack_.push(type); - // If we have a key we still need to render, make sure to save off the - // contents in our own storage. - if (!key_.empty() && key_storage_.empty()) { - StrAppend(&key_storage_, key_); - key_ = StringPiece(key_storage_); - } - result = util::Status(); - } - return result; - } - } - return util::Status(); -} - -util::Status JsonStreamParser::ParseValue(TokenType type) { - switch (type) { - case BEGIN_OBJECT: - return HandleBeginObject(); - case BEGIN_ARRAY: - return HandleBeginArray(); - case BEGIN_STRING: - return ParseString(); - case BEGIN_NUMBER: - return ParseNumber(); - case BEGIN_TRUE: - return ParseTrue(); - case BEGIN_FALSE: - return ParseFalse(); - case BEGIN_NULL: - return ParseNull(); - case UNKNOWN: - return ReportUnknown("Expected a value.", ParseErrorType::EXPECTED_VALUE); - default: { - // Special case for having been cut off while parsing, wait for more data. - // This handles things like 'fals' being at the end of the string, we - // don't know if the next char would be e, completing it, or something - // else, making it invalid. - if (!finishing_ && p_.length() < kKeywordFalse.length()) { - return util::CancelledError(""); - } - - if (allow_empty_null_ && IsEmptyNullAllowed(type)) { - return ParseEmptyNull(); - } - return ReportFailure("Unexpected token.", - ParseErrorType::UNEXPECTED_TOKEN); - } - } -} - -util::Status JsonStreamParser::ParseString() { - util::Status result = ParseStringHelper(); - if (result.ok()) { - ow_->RenderString(key_, parsed_); - key_ = StringPiece(); - parsed_ = StringPiece(); - parsed_storage_.clear(); - } - return result; -} - -util::Status JsonStreamParser::ParseStringHelper() { - // If we haven't seen the start quote, grab it and remember it for later. - if (string_open_ == 0) { - string_open_ = *p_.data(); - GOOGLE_DCHECK(string_open_ == '\"' || string_open_ == '\''); - Advance(); - } - // Track where we last copied data from so we can minimize copying. - const char* last = p_.data(); - while (!p_.empty()) { - const char* data = p_.data(); - if (*data == '\\') { - // We're about to handle an escape, copy all bytes from last to data. - if (last < data) { - parsed_storage_.append(last, data - last); - } - // If we ran out of string after the \, cancel or report an error - // depending on if we expect more data later. - if (p_.length() == 1) { - if (!finishing_) { - return util::CancelledError(""); - } - return ReportFailure("Closing quote expected in string.", - ParseErrorType::EXPECTED_CLOSING_QUOTE); - } - // Parse a unicode escape if we found \u in the string. - if (data[1] == 'u') { - util::Status result = ParseUnicodeEscape(); - if (!result.ok()) { - return result; - } - // Move last pointer past the unicode escape and continue. - last = p_.data(); - continue; - } - // Handle the standard set of backslash-escaped characters. - switch (data[1]) { - case 'b': - parsed_storage_.push_back('\b'); - break; - case 'f': - parsed_storage_.push_back('\f'); - break; - case 'n': - parsed_storage_.push_back('\n'); - break; - case 'r': - parsed_storage_.push_back('\r'); - break; - case 't': - parsed_storage_.push_back('\t'); - break; - case 'v': - parsed_storage_.push_back('\v'); - break; - default: - parsed_storage_.push_back(data[1]); - } - // We handled two characters, so advance past them and continue. - p_.remove_prefix(2); - last = p_.data(); - continue; - } - // If we found the closing quote note it, advance past it, and return. - if (*data == string_open_) { - // If we didn't copy anything, reuse the input buffer. - if (parsed_storage_.empty()) { - parsed_ = StringPiece(last, data - last); - } else { - if (last < data) { - parsed_storage_.append(last, data - last); - } - parsed_ = StringPiece(parsed_storage_); - } - // Clear the quote char so next time we try to parse a string we'll - // start fresh. - string_open_ = 0; - Advance(); - return util::Status(); - } - // Normal character, just advance past it. - Advance(); - } - // If we ran out of characters, copy over what we have so far. - if (last < p_.data()) { - parsed_storage_.append(last, p_.data() - last); - } - // If we didn't find the closing quote but we expect more data, cancel for now - if (!finishing_) { - return util::CancelledError(""); - } - // End of string reached without a closing quote, report an error. - string_open_ = 0; - return ReportFailure("Closing quote expected in string.", - ParseErrorType::EXPECTED_CLOSING_QUOTE); -} - -// Converts a unicode escaped character to a decimal value stored in a char32 -// for use in UTF8 encoding utility. We assume that str begins with \uhhhh and -// convert that from the hex number to a decimal value. -// -// There are some security exploits with UTF-8 that we should be careful of: -// - http://www.unicode.org/reports/tr36/#UTF-8_Exploit -// - http://sites/intl-eng/design-guide/core-application -util::Status JsonStreamParser::ParseUnicodeEscape() { - if (p_.length() < kUnicodeEscapedLength) { - if (!finishing_) { - return util::CancelledError(""); - } - return ReportFailure("Illegal hex string.", - ParseErrorType::ILLEGAL_HEX_STRING); - } - GOOGLE_DCHECK_EQ('\\', p_.data()[0]); - GOOGLE_DCHECK_EQ('u', p_.data()[1]); - uint32 code = 0; - for (int i = 2; i < kUnicodeEscapedLength; ++i) { - if (!isxdigit(p_.data()[i])) { - return ReportFailure("Invalid escape sequence.", - ParseErrorType::INVALID_ESCAPE_SEQUENCE); - } - code = (code << 4) + hex_digit_to_int(p_.data()[i]); - } - if (code >= JsonEscaping::kMinHighSurrogate && - code <= JsonEscaping::kMaxHighSurrogate) { - if (p_.length() < 2 * kUnicodeEscapedLength) { - if (!finishing_) { - return util::CancelledError(""); - } - if (!coerce_to_utf8_) { - return ReportFailure("Missing low surrogate.", - ParseErrorType::MISSING_LOW_SURROGATE); - } - } else if (p_.data()[kUnicodeEscapedLength] == '\\' && - p_.data()[kUnicodeEscapedLength + 1] == 'u') { - uint32 low_code = 0; - for (int i = kUnicodeEscapedLength + 2; i < 2 * kUnicodeEscapedLength; - ++i) { - if (!isxdigit(p_.data()[i])) { - return ReportFailure("Invalid escape sequence.", - ParseErrorType::INVALID_ESCAPE_SEQUENCE); - } - low_code = (low_code << 4) + hex_digit_to_int(p_.data()[i]); - } - if (low_code >= JsonEscaping::kMinLowSurrogate && - low_code <= JsonEscaping::kMaxLowSurrogate) { - // Convert UTF-16 surrogate pair to 21-bit Unicode codepoint. - code = (((code & 0x3FF) << 10) | (low_code & 0x3FF)) + - JsonEscaping::kMinSupplementaryCodePoint; - // Advance past the first code unit escape. - p_.remove_prefix(kUnicodeEscapedLength); - } else if (!coerce_to_utf8_) { - return ReportFailure("Invalid low surrogate.", - ParseErrorType::INVALID_LOW_SURROGATE); - } - } else if (!coerce_to_utf8_) { - return ReportFailure("Missing low surrogate.", - ParseErrorType::MISSING_LOW_SURROGATE); - } - } - if (!coerce_to_utf8_ && !IsValidCodePoint(code)) { - return ReportFailure("Invalid unicode code point.", - ParseErrorType::INVALID_UNICODE); - } - char buf[UTFmax]; - int len = EncodeAsUTF8Char(code, buf); - // Advance past the [final] code unit escape. - p_.remove_prefix(kUnicodeEscapedLength); - parsed_storage_.append(buf, len); - return util::Status(); -} - -util::Status JsonStreamParser::ParseNumber() { - NumberResult number; - util::Status result = ParseNumberHelper(&number); - if (result.ok()) { - switch (number.type) { - case NumberResult::DOUBLE: - ow_->RenderDouble(key_, number.double_val); - key_ = StringPiece(); - break; - - case NumberResult::INT: - ow_->RenderInt64(key_, number.int_val); - key_ = StringPiece(); - break; - - case NumberResult::UINT: - ow_->RenderUint64(key_, number.uint_val); - key_ = StringPiece(); - break; - - default: - return ReportFailure("Unable to parse number.", - ParseErrorType::UNABLE_TO_PARSE_NUMBER); - } - } - return result; -} - -util::Status JsonStreamParser::ParseDoubleHelper(const std::string& number, - NumberResult* result) { - if (!safe_strtod(number, &result->double_val)) { - return ReportFailure("Unable to parse number.", - ParseErrorType::UNABLE_TO_PARSE_NUMBER); - } - if (!loose_float_number_conversion_ && !std::isfinite(result->double_val)) { - return ReportFailure("Number exceeds the range of double.", - ParseErrorType::NUMBER_EXCEEDS_RANGE_DOUBLE); - } - result->type = NumberResult::DOUBLE; - return util::Status(); -} - -util::Status JsonStreamParser::ParseNumberHelper(NumberResult* result) { - const char* data = p_.data(); - int length = p_.length(); - - // Look for the first non-numeric character, or the end of the string. - int index = 0; - bool floating = false; - bool negative = data[index] == '-'; - // Find the first character that cannot be part of the number. Along the way - // detect if the number needs to be parsed as a double. - // Note that this restricts numbers to the JSON specification, so for example - // we do not support hex or octal notations. - for (; index < length; ++index) { - char c = data[index]; - if (isdigit(c)) continue; - if (c == '.' || c == 'e' || c == 'E') { - floating = true; - continue; - } - if (c == '+' || c == '-' || c == 'x') continue; - // Not a valid number character, break out. - break; - } - - // If the entire input is a valid number, and we may have more content in the - // future, we abort for now and resume when we know more. - if (index == length && !finishing_) { - return util::CancelledError(""); - } - - // Create a string containing just the number, so we can use safe_strtoX - std::string number = std::string(p_.substr(0, index)); - - // Floating point number, parse as a double. - if (floating) { - util::Status status = ParseDoubleHelper(number, result); - if (status.ok()) { - p_.remove_prefix(index); - } - return status; - } - - // Positive non-floating point number, parse as a uint64. - if (!negative) { - // Octal/Hex numbers are not valid JSON values. - if (number.length() >= 2 && number[0] == '0') { - return ReportFailure( - "Octal/hex numbers are not valid JSON values.", - ParseErrorType::OCTAL_OR_HEX_ARE_NOT_VALID_JSON_VALUES); - } - if (safe_strtou64(number, &result->uint_val)) { - result->type = NumberResult::UINT; - p_.remove_prefix(index); - return util::Status(); - } else { - // If the value is too large, parse it as double. - util::Status status = ParseDoubleHelper(number, result); - if (status.ok()) { - p_.remove_prefix(index); - } - return status; - } - } - - // Octal/Hex numbers are not valid JSON values. - if (number.length() >= 3 && number[1] == '0') { - return ReportFailure( - "Octal/hex numbers are not valid JSON values.", - ParseErrorType::OCTAL_OR_HEX_ARE_NOT_VALID_JSON_VALUES); - } - // Negative non-floating point number, parse as an int64. - if (safe_strto64(number, &result->int_val)) { - result->type = NumberResult::INT; - p_.remove_prefix(index); - return util::Status(); - } else { - // If the value is too large, parse it as double. - util::Status status = ParseDoubleHelper(number, result); - if (status.ok()) { - p_.remove_prefix(index); - } - return status; - } -} - -util::Status JsonStreamParser::HandleBeginObject() { - GOOGLE_DCHECK_EQ('{', *p_.data()); - Advance(); - ow_->StartObject(key_); - auto status = IncrementRecursionDepth(key_); - if (!status.ok()) { - return status; - } - key_ = StringPiece(); - stack_.push(ENTRY); - return util::Status(); -} - -util::Status JsonStreamParser::ParseObjectMid(TokenType type) { - if (type == UNKNOWN) { - return ReportUnknown("Expected , or } after key:value pair.", - ParseErrorType::EXPECTED_COMMA_OR_BRACES); - } - - // Object is complete, advance past the comma and render the EndObject. - if (type == END_OBJECT) { - Advance(); - ow_->EndObject(); - --recursion_depth_; - return util::Status(); - } - // Found a comma, advance past it and get ready for an entry. - if (type == VALUE_SEPARATOR) { - Advance(); - stack_.push(ENTRY); - return util::Status(); - } - // Illegal token after key:value pair. - return ReportFailure("Expected , or } after key:value pair.", - ParseErrorType::EXPECTED_COMMA_OR_BRACES); -} - -util::Status JsonStreamParser::ParseEntry(TokenType type) { - if (type == UNKNOWN) { - return ReportUnknown("Expected an object key or }.", - ParseErrorType::EXPECTED_OBJECT_KEY_OR_BRACES); - } - - // Close the object and return. This allows for trailing commas. - if (type == END_OBJECT) { - ow_->EndObject(); - Advance(); - --recursion_depth_; - return util::Status(); - } - - util::Status result; - if (type == BEGIN_STRING) { - // Key is a string (standard JSON), parse it and store the string. - result = ParseStringHelper(); - if (result.ok()) { - key_storage_.clear(); - if (!parsed_storage_.empty()) { - parsed_storage_.swap(key_storage_); - key_ = StringPiece(key_storage_); - } else { - key_ = parsed_; - } - parsed_ = StringPiece(); - } - } else if (type == BEGIN_KEY) { - // Key is a bare key (back compat), create a StringPiece pointing to it. - result = ParseKey(); - } else if (type == BEGIN_NULL || type == BEGIN_TRUE || type == BEGIN_FALSE) { - // Key may be a bare key that begins with a reserved word. - result = ParseKey(); - if (result.ok() && (key_ == kKeywordNull || key_ == kKeywordTrue || - key_ == kKeywordFalse)) { - result = ReportFailure("Expected an object key or }.", - ParseErrorType::EXPECTED_OBJECT_KEY_OR_BRACES); - } - } else { - // Unknown key type, report an error. - result = ReportFailure("Expected an object key or }.", - ParseErrorType::EXPECTED_OBJECT_KEY_OR_BRACES); - } - // On success we next expect an entry mid ':' then an object mid ',' or '}' - if (result.ok()) { - stack_.push(OBJ_MID); - stack_.push(ENTRY_MID); - } - return result; -} - -util::Status JsonStreamParser::ParseEntryMid(TokenType type) { - if (type == UNKNOWN) { - return ReportUnknown("Expected : between key:value pair.", - ParseErrorType::EXPECTED_COLON); - } - if (type == ENTRY_SEPARATOR) { - Advance(); - stack_.push(VALUE); - return util::Status(); - } - return ReportFailure("Expected : between key:value pair.", - ParseErrorType::EXPECTED_COLON); -} - -util::Status JsonStreamParser::HandleBeginArray() { - GOOGLE_DCHECK_EQ('[', *p_.data()); - Advance(); - ow_->StartList(key_); - key_ = StringPiece(); - stack_.push(ARRAY_VALUE); - return util::Status(); -} - -util::Status JsonStreamParser::ParseArrayValue(TokenType type) { - if (type == UNKNOWN) { - return ReportUnknown("Expected a value or ] within an array.", - ParseErrorType::EXPECTED_VALUE_OR_BRACKET); - } - - if (type == END_ARRAY) { - ow_->EndList(); - Advance(); - return util::Status(); - } - - // The ParseValue call may push something onto the stack so we need to make - // sure an ARRAY_MID is after it, so we push it on now. Also, the parsing of - // empty-null array value is relying on this ARRAY_MID token. - stack_.push(ARRAY_MID); - util::Status result = ParseValue(type); - if (util::IsCancelled(result)) { - // If we were cancelled, pop back off the ARRAY_MID so we don't try to - // push it on again when we try over. - stack_.pop(); - } - return result; -} - -util::Status JsonStreamParser::ParseArrayMid(TokenType type) { - if (type == UNKNOWN) { - return ReportUnknown("Expected , or ] after array value.", - ParseErrorType::EXPECTED_COMMA_OR_BRACKET); - } - - if (type == END_ARRAY) { - ow_->EndList(); - Advance(); - return util::Status(); - } - - // Found a comma, advance past it and expect an array value next. - if (type == VALUE_SEPARATOR) { - Advance(); - stack_.push(ARRAY_VALUE); - return util::Status(); - } - // Illegal token after array value. - return ReportFailure("Expected , or ] after array value.", - ParseErrorType::EXPECTED_COMMA_OR_BRACKET); -} - -util::Status JsonStreamParser::ParseTrue() { - ow_->RenderBool(key_, true); - key_ = StringPiece(); - p_.remove_prefix(kKeywordTrue.length()); - return util::Status(); -} - -util::Status JsonStreamParser::ParseFalse() { - ow_->RenderBool(key_, false); - key_ = StringPiece(); - p_.remove_prefix(kKeywordFalse.length()); - return util::Status(); -} - -util::Status JsonStreamParser::ParseNull() { - ow_->RenderNull(key_); - key_ = StringPiece(); - p_.remove_prefix(kKeywordNull.length()); - return util::Status(); -} - -util::Status JsonStreamParser::ParseEmptyNull() { - ow_->RenderNull(key_); - key_ = StringPiece(); - return util::Status(); -} - -bool JsonStreamParser::IsEmptyNullAllowed(TokenType type) { - if (stack_.empty()) return false; - return (stack_.top() == ARRAY_MID && type == VALUE_SEPARATOR) || - stack_.top() == OBJ_MID; -} - -util::Status JsonStreamParser::ReportFailure(StringPiece message, - ParseErrorType parse_code) { - static const int kContextLength = 20; - const char* p_start = p_.data(); - const char* json_start = json_.data(); - const char* begin = std::max(p_start - kContextLength, json_start); - const char* end = - std::min(p_start + kContextLength, json_start + json_.size()); - StringPiece segment(begin, end - begin); - std::string location(p_start - begin, ' '); - location.push_back('^'); - auto status = util::InvalidArgumentError( - StrCat(message, "\n", segment, "\n", location)); - return status; -} - -util::Status JsonStreamParser::ReportUnknown(StringPiece message, - ParseErrorType parse_code) { - // If we aren't finishing the parse, cancel parsing and try later. - if (!finishing_) { - return util::CancelledError(""); - } - if (p_.empty()) { - return ReportFailure(StrCat("Unexpected end of string. ", message), - parse_code); - } - return ReportFailure(message, parse_code); -} - -util::Status JsonStreamParser::IncrementRecursionDepth( - StringPiece key) const { - if (++recursion_depth_ > max_recursion_depth_) { - return util::InvalidArgumentError(StrCat( - "Message too deep. Max recursion depth reached for key '", key, "'")); - } - return util::Status(); -} - -void JsonStreamParser::SkipWhitespace() { - while (!p_.empty() && ascii_isspace(*p_.data())) { - Advance(); - } - if (!p_.empty() && !ascii_isspace(*p_.data())) { - seen_non_whitespace_ = true; - } -} - -void JsonStreamParser::Advance() { - // Advance by moving one UTF8 character while making sure we don't go beyond - // the length of StringPiece. - p_.remove_prefix(std::min<int>( - p_.length(), UTF8FirstLetterNumBytes(p_.data(), p_.length()))); -} - -util::Status JsonStreamParser::ParseKey() { - StringPiece original = p_; - - if (allow_permissive_key_naming_) { - if (!ConsumeKeyPermissive(&p_, &key_)) { - return ReportFailure("Invalid key or variable name.", - ParseErrorType::INVALID_KEY_OR_VARIABLE_NAME); - } - } else { - if (!ConsumeKey(&p_, &key_)) { - return ReportFailure("Invalid key or variable name.", - ParseErrorType::INVALID_KEY_OR_VARIABLE_NAME); - } - } - - // If we consumed everything but expect more data, reset p_ and cancel since - // we can't know if the key was complete or not. - if (!finishing_ && p_.empty()) { - p_ = original; - return util::CancelledError(""); - } - // Since we aren't using the key storage, clear it out. - key_storage_.clear(); - return util::Status(); -} - -JsonStreamParser::TokenType JsonStreamParser::GetNextTokenType() { - SkipWhitespace(); - - int size = p_.size(); - if (size == 0) { - // If we ran out of data, report unknown and we'll place the previous parse - // type onto the stack and try again when we have more data. - return UNKNOWN; - } - // TODO(sven): Split this method based on context since different contexts - // support different tokens. Would slightly speed up processing? - const char* data = p_.data(); - StringPiece data_view = StringPiece(data, size); - if (*data == '\"' || *data == '\'') return BEGIN_STRING; - if (*data == '-' || ('0' <= *data && *data <= '9')) { - return BEGIN_NUMBER; - } - if (size >= kKeywordTrue.length() && - HasPrefixString(data_view, kKeywordTrue)) { - return BEGIN_TRUE; - } - if (size >= kKeywordFalse.length() && - HasPrefixString(data_view, kKeywordFalse)) { - return BEGIN_FALSE; - } - if (size >= kKeywordNull.length() && - HasPrefixString(data_view, kKeywordNull)) { - return BEGIN_NULL; - } - if (*data == '{') return BEGIN_OBJECT; - if (*data == '}') return END_OBJECT; - if (*data == '[') return BEGIN_ARRAY; - if (*data == ']') return END_ARRAY; - if (*data == ':') return ENTRY_SEPARATOR; - if (*data == ',') return VALUE_SEPARATOR; - if (MatchKey(p_)) { - return BEGIN_KEY; - } - - // We don't know that we necessarily have an invalid token here, just that we - // can't parse what we have so far. So we don't report an error and just - // return UNKNOWN so we can try again later when we have more data, or if we - // finish and we have leftovers. - return UNKNOWN; -} - -} // namespace converter -} // namespace util -} // namespace protobuf -} // namespace google diff --git a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/json_stream_parser.h b/contrib/libs/protobuf_std/src/google/protobuf/util/internal/json_stream_parser.h deleted file mode 100644 index 47dfe82f4a..0000000000 --- a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/json_stream_parser.h +++ /dev/null @@ -1,349 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_JSON_STREAM_PARSER_H__ -#define GOOGLE_PROTOBUF_UTIL_CONVERTER_JSON_STREAM_PARSER_H__ - -#include <cstdint> -#include <stack> -#include <string> - -#include <google/protobuf/stubs/common.h> -#include <google/protobuf/stubs/status.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/stubs/status.h> - -#include <google/protobuf/port_def.inc> - -namespace google { -namespace protobuf { -namespace util { -namespace converter { - - -class ObjectWriter; - -// A JSON parser that can parse a stream of JSON chunks rather than needing the -// entire JSON string up front. It is a modified version of the parser in -// //net/proto/json/json-parser.h that has been changed in the following ways: -// - Changed from recursion to an explicit stack to allow resumption -// - Added support for int64 and uint64 numbers -// - Removed support for octal and decimal escapes -// - Removed support for numeric keys -// - Removed support for functions (javascript) -// - Removed some lax-comma support (but kept trailing comma support) -// - Writes directly to an ObjectWriter rather than using subclassing -// -// Here is an example usage: -// JsonStreamParser parser(ow_.get()); -// util::Status result = parser.Parse(chunk1); -// result.Update(parser.Parse(chunk2)); -// result.Update(parser.FinishParse()); -// GOOGLE_DCHECK(result.ok()) << "Failed to parse JSON"; -// -// This parser is thread-compatible as long as only one thread is calling a -// Parse() method at a time. -class PROTOBUF_EXPORT JsonStreamParser { - public: - // Creates a JsonStreamParser that will write to the given ObjectWriter. - explicit JsonStreamParser(ObjectWriter* ow); - virtual ~JsonStreamParser(); - - // Parses a UTF-8 encoded JSON string from a StringPiece. If the returned - // status is non-ok, the status might contain a payload ParseErrorType with - // type_url kParseErrorTypeUrl and a payload containing string snippet of the - // error with type_url kParseErrorSnippetUrl. - util::Status Parse(StringPiece json); - - - // Finish parsing the JSON string. If the returned status is non-ok, the - // status might contain a payload ParseErrorType with type_url - // kParseErrorTypeUrl and a payload containing string snippet of the error - // with type_url kParseErrorSnippetUrl. - util::Status FinishParse(); - - - // Sets the max recursion depth of JSON message to be deserialized. JSON - // messages over this depth will fail to be deserialized. - // Default value is 100. - void set_max_recursion_depth(int max_depth) { - max_recursion_depth_ = max_depth; - } - - // Denotes the cause of error. - enum ParseErrorType { - UNKNOWN_PARSE_ERROR, - OCTAL_OR_HEX_ARE_NOT_VALID_JSON_VALUES, - EXPECTED_COLON, - EXPECTED_COMMA_OR_BRACKET, - EXPECTED_VALUE, - EXPECTED_COMMA_OR_BRACES, - EXPECTED_OBJECT_KEY_OR_BRACES, - EXPECTED_VALUE_OR_BRACKET, - INVALID_KEY_OR_VARIABLE_NAME, - NON_UTF_8, - PARSING_TERMINATED_BEFORE_END_OF_INPUT, - UNEXPECTED_TOKEN, - EXPECTED_CLOSING_QUOTE, - ILLEGAL_HEX_STRING, - INVALID_ESCAPE_SEQUENCE, - MISSING_LOW_SURROGATE, - INVALID_LOW_SURROGATE, - INVALID_UNICODE, - UNABLE_TO_PARSE_NUMBER, - NUMBER_EXCEEDS_RANGE_DOUBLE - }; - - private: - friend class JsonStreamParserTest; - // Return the current recursion depth. - int recursion_depth() { return recursion_depth_; } - - enum TokenType { - BEGIN_STRING, // " or ' - BEGIN_NUMBER, // - or digit - BEGIN_TRUE, // true - BEGIN_FALSE, // false - BEGIN_NULL, // null - BEGIN_OBJECT, // { - END_OBJECT, // } - BEGIN_ARRAY, // [ - END_ARRAY, // ] - ENTRY_SEPARATOR, // : - VALUE_SEPARATOR, // , - BEGIN_KEY, // letter, _, $ or digit. Must begin with non-digit - UNKNOWN // Unknown token or we ran out of the stream. - }; - - enum ParseType { - VALUE, // Expects a {, [, true, false, null, string or number - OBJ_MID, // Expects a ',' or } - ENTRY, // Expects a key or } - ENTRY_MID, // Expects a : - ARRAY_VALUE, // Expects a value or ] - ARRAY_MID // Expects a ',' or ] - }; - - // Holds the result of parsing a number - struct NumberResult { - enum Type { DOUBLE, INT, UINT }; - Type type; - union { - double double_val; - int64_t int_val; - uint64_t uint_val; - }; - }; - - // Parses a single chunk of JSON, returning an error if the JSON was invalid. - util::Status ParseChunk(StringPiece chunk); - - // Runs the parser based on stack_ and p_, until the stack is empty or p_ runs - // out of data. If we unexpectedly run out of p_ we push the latest back onto - // the stack and return. - util::Status RunParser(); - - // Parses a value from p_ and writes it to ow_. - // A value may be an object, array, true, false, null, string or number. - util::Status ParseValue(TokenType type); - - // Parses a string and writes it out to the ow_. - util::Status ParseString(); - - // Parses a string, storing the result in parsed_. - util::Status ParseStringHelper(); - - // This function parses unicode escape sequences in strings. It returns an - // error when there's a parsing error, either the size is not the expected - // size or a character is not a hex digit. When it returns str will contain - // what has been successfully parsed so far. - util::Status ParseUnicodeEscape(); - - // Expects p_ to point to a JSON number, writes the number to the writer using - // the appropriate Render method based on the type of number. - util::Status ParseNumber(); - - // Parse a number into a NumberResult, reporting an error if no number could - // be parsed. This method will try to parse into a uint64, int64, or double - // based on whether the number was positive or negative or had a decimal - // component. - util::Status ParseNumberHelper(NumberResult* result); - - // Parse a number as double into a NumberResult. - util::Status ParseDoubleHelper(const std::string& number, - NumberResult* result); - - // Handles a { during parsing of a value. - util::Status HandleBeginObject(); - - // Parses from the ENTRY state. - util::Status ParseEntry(TokenType type); - - // Parses from the ENTRY_MID state. - util::Status ParseEntryMid(TokenType type); - - // Parses from the OBJ_MID state. - util::Status ParseObjectMid(TokenType type); - - // Handles a [ during parsing of a value. - util::Status HandleBeginArray(); - - // Parses from the ARRAY_VALUE state. - util::Status ParseArrayValue(TokenType type); - - // Parses from the ARRAY_MID state. - util::Status ParseArrayMid(TokenType type); - - // Expects p_ to point to an unquoted literal - util::Status ParseTrue(); - util::Status ParseFalse(); - util::Status ParseNull(); - util::Status ParseEmptyNull(); - - // Whether an empty-null is allowed in the current state. - bool IsEmptyNullAllowed(TokenType type); - - // Whether the whole input is all whitespaces. - bool IsInputAllWhiteSpaces(TokenType type); - - // Report a failure as a util::Status. - util::Status ReportFailure(StringPiece message, - ParseErrorType parse_code); - - // Report a failure due to an UNKNOWN token type. We check if we hit the - // end of the stream and if we're finishing or not to detect what type of - // status to return in this case. - util::Status ReportUnknown(StringPiece message, - ParseErrorType parse_code); - - // Helper function to check recursion depth and increment it. It will return - // OkStatus() if the current depth is allowed. Otherwise an error is returned. - // key is used for error reporting. - util::Status IncrementRecursionDepth(StringPiece key) const; - - // Advance p_ past all whitespace or until the end of the string. - void SkipWhitespace(); - - // Advance p_ one UTF-8 character - void Advance(); - - // Expects p_ to point to the beginning of a key. - util::Status ParseKey(); - - // Return the type of the next token at p_. - TokenType GetNextTokenType(); - - // The object writer to write parse events to. - ObjectWriter* ow_; - - // The stack of parsing we still need to do. When the stack runs empty we will - // have parsed a single value from the root (e.g. an object or list). - std::stack<ParseType> stack_; - - // Contains any leftover text from a previous chunk that we weren't able to - // fully parse, for example the start of a key or number. - std::string leftover_; - - // The current chunk of JSON being parsed. Primarily used for providing - // context during error reporting. - StringPiece json_; - - // A pointer within the current JSON being parsed, used to track location. - StringPiece p_; - - // Stores the last key read, as we separate parsing of keys and values. - StringPiece key_; - - // Storage for key_ if we need to keep ownership, for example between chunks - // or if the key was unescaped from a JSON string. - std::string key_storage_; - - // True during the FinishParse() call, so we know that any errors are fatal. - // For example an unterminated string will normally result in cancelling and - // trying during the next chunk, but during FinishParse() it is an error. - bool finishing_; - - // Whether non whitespace tokens have been seen during parsing. - // It is used to handle the case of a pure whitespace stream input. - bool seen_non_whitespace_; - - // The JsonStreamParser requires a root element by default and it will raise - // error if the root element is missing. If `allow_no_root_element_` is true, - // the JsonStreamParser can also handle this case. - bool allow_no_root_element_; - - // String we parsed during a call to ParseStringHelper(). - StringPiece parsed_; - - // Storage for the string we parsed. This may be empty if the string was able - // to be parsed directly from the input. - std::string parsed_storage_; - - // The character that opened the string, either ' or ". - // A value of 0 indicates that string parsing is not in process. - char string_open_; - - // Storage for the chunk that are being parsed in ParseChunk(). - std::string chunk_storage_; - - // Whether to allow non UTF-8 encoded input and replace invalid code points. - bool coerce_to_utf8_; - - // Replacement character for invalid UTF-8 code points. - std::string utf8_replacement_character_; - - // Whether allows empty string represented null array value or object entry - // value. - bool allow_empty_null_; - - // Whether unquoted object keys can contain embedded non-alphanumeric - // characters when this is unambiguous for parsing. - bool allow_permissive_key_naming_; - - // Whether allows out-of-range floating point numbers or reject them. - bool loose_float_number_conversion_; - - // Tracks current recursion depth. - mutable int recursion_depth_; - - // Maximum allowed recursion depth. - int max_recursion_depth_; - - GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(JsonStreamParser); -}; - -} // namespace converter -} // namespace util -} // namespace protobuf -} // namespace google - -#include <google/protobuf/port_undef.inc> - -#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_JSON_STREAM_PARSER_H__ diff --git a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/location_tracker.h b/contrib/libs/protobuf_std/src/google/protobuf/util/internal/location_tracker.h deleted file mode 100644 index c29a75a74c..0000000000 --- a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/location_tracker.h +++ /dev/null @@ -1,69 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_LOCATION_TRACKER_H__ -#define GOOGLE_PROTOBUF_UTIL_CONVERTER_LOCATION_TRACKER_H__ - -#include <string> - -#include <google/protobuf/stubs/common.h> - -#include <google/protobuf/port_def.inc> - -namespace google { -namespace protobuf { -namespace util { -namespace converter { - -// LocationTrackerInterface is an interface for classes that track -// the location information for the purpose of error reporting. -class PROTOBUF_EXPORT LocationTrackerInterface { - public: - virtual ~LocationTrackerInterface() {} - - // Returns the object location as human readable string. - virtual std::string ToString() const = 0; - - protected: - LocationTrackerInterface() {} - - private: - // Please do not add any data members to this class. - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(LocationTrackerInterface); -}; - -} // namespace converter -} // namespace util -} // namespace protobuf -} // namespace google - -#include <google/protobuf/port_undef.inc> - -#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_LOCATION_TRACKER_H__ diff --git a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/object_location_tracker.h b/contrib/libs/protobuf_std/src/google/protobuf/util/internal/object_location_tracker.h deleted file mode 100644 index 571279d59b..0000000000 --- a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/object_location_tracker.h +++ /dev/null @@ -1,64 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_OBJECT_LOCATION_TRACKER_H__ -#define GOOGLE_PROTOBUF_UTIL_CONVERTER_OBJECT_LOCATION_TRACKER_H__ - -#include <string> - -#include <google/protobuf/stubs/common.h> -#include <google/protobuf/util/internal/location_tracker.h> - -namespace google { -namespace protobuf { -namespace util { -namespace converter { - -// An empty concrete implementation of LocationTrackerInterface. -class ObjectLocationTracker : public LocationTrackerInterface { - public: - // Creates an empty location tracker. - ObjectLocationTracker() {} - - ~ObjectLocationTracker() override {} - - // Returns empty because nothing is tracked. - std::string ToString() const override { return ""; } - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ObjectLocationTracker); -}; - -} // namespace converter -} // namespace util -} // namespace protobuf -} // namespace google - -#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_OBJECT_LOCATION_TRACKER_H__ diff --git a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/object_source.h b/contrib/libs/protobuf_std/src/google/protobuf/util/internal/object_source.h deleted file mode 100644 index de548c1d0a..0000000000 --- a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/object_source.h +++ /dev/null @@ -1,85 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_OBJECT_SOURCE_H__ -#define GOOGLE_PROTOBUF_UTIL_CONVERTER_OBJECT_SOURCE_H__ - -#include <google/protobuf/stubs/common.h> -#include <google/protobuf/stubs/status.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/stubs/status.h> - -// Must be included last. -#include <google/protobuf/port_def.inc> - -namespace google { -namespace protobuf { -namespace util { -namespace converter { - -class ObjectWriter; - -// An ObjectSource is anything that can write to an ObjectWriter. -// Implementation of this interface typically provide constructors or -// factory methods to create an instance based on some source data, for -// example, a character stream, or protobuf. -// -// Derived classes could be thread-unsafe. -class PROTOBUF_EXPORT ObjectSource { - public: - virtual ~ObjectSource() {} - - // Writes to the ObjectWriter - virtual util::Status WriteTo(ObjectWriter* ow) const { - return NamedWriteTo("", ow); - } - - // Writes to the ObjectWriter with a custom name for the message. - // This is useful when you chain ObjectSource together by embedding one - // within another. - virtual util::Status NamedWriteTo(StringPiece name, - ObjectWriter* ow) const = 0; - - protected: - ObjectSource() {} - - private: - // Do not add any data members to this class. - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ObjectSource); -}; - -} // namespace converter -} // namespace util -} // namespace protobuf -} // namespace google - -#include <google/protobuf/port_undef.inc> - -#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_OBJECT_SOURCE_H__ diff --git a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/object_writer.cc b/contrib/libs/protobuf_std/src/google/protobuf/util/internal/object_writer.cc deleted file mode 100644 index 4dabd378e4..0000000000 --- a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/object_writer.cc +++ /dev/null @@ -1,93 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include <google/protobuf/util/internal/object_writer.h> - -#include <google/protobuf/util/internal/datapiece.h> - -namespace google { -namespace protobuf { -namespace util { -namespace converter { - -// static -void ObjectWriter::RenderDataPieceTo(const DataPiece& data, - StringPiece name, ObjectWriter* ow) { - switch (data.type()) { - case DataPiece::TYPE_INT32: { - ow->RenderInt32(name, data.ToInt32().value()); - break; - } - case DataPiece::TYPE_INT64: { - ow->RenderInt64(name, data.ToInt64().value()); - break; - } - case DataPiece::TYPE_UINT32: { - ow->RenderUint32(name, data.ToUint32().value()); - break; - } - case DataPiece::TYPE_UINT64: { - ow->RenderUint64(name, data.ToUint64().value()); - break; - } - case DataPiece::TYPE_DOUBLE: { - ow->RenderDouble(name, data.ToDouble().value()); - break; - } - case DataPiece::TYPE_FLOAT: { - ow->RenderFloat(name, data.ToFloat().value()); - break; - } - case DataPiece::TYPE_BOOL: { - ow->RenderBool(name, data.ToBool().value()); - break; - } - case DataPiece::TYPE_STRING: { - ow->RenderString(name, data.ToString().value()); - break; - } - case DataPiece::TYPE_BYTES: { - ow->RenderBytes(name, data.ToBytes().value()); - break; - } - case DataPiece::TYPE_NULL: { - ow->RenderNull(name); - break; - } - default: - break; - } -} - - -} // namespace converter -} // namespace util -} // namespace protobuf -} // namespace google diff --git a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/object_writer.h b/contrib/libs/protobuf_std/src/google/protobuf/util/internal/object_writer.h deleted file mode 100644 index 917a28041f..0000000000 --- a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/object_writer.h +++ /dev/null @@ -1,151 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_OBJECT_WRITER_H__ -#define GOOGLE_PROTOBUF_UTIL_CONVERTER_OBJECT_WRITER_H__ - -#include <cstdint> - -#include <google/protobuf/stubs/common.h> -#include <google/protobuf/stubs/strutil.h> - -// Must be included last. -#include <google/protobuf/port_def.inc> - -namespace google { -namespace protobuf { -namespace util { -namespace converter { - - -class DataPiece; - -// An ObjectWriter is an interface for writing a stream of events -// representing objects and collections. Implementation of this -// interface can be used to write an object stream to an in-memory -// structure, protobufs, JSON, XML, or any other output format -// desired. The ObjectSource interface is typically used as the -// source of an object stream. -// -// See JsonObjectWriter for a sample implementation of ObjectWriter -// and its use. -// -// Derived classes could be thread-unsafe. -// -// TODO(xinb): seems like a prime candidate to apply the RAII paradigm -// and get rid the need to call EndXXX(). -class PROTOBUF_EXPORT ObjectWriter { - public: - virtual ~ObjectWriter() {} - - // Starts an object. If the name is empty, the object will not be named. - virtual ObjectWriter* StartObject(StringPiece name) = 0; - - // Ends an object. - virtual ObjectWriter* EndObject() = 0; - - // Starts a list. If the name is empty, the list will not be named. - virtual ObjectWriter* StartList(StringPiece name) = 0; - - // Ends a list. - virtual ObjectWriter* EndList() = 0; - - // Renders a boolean value. - virtual ObjectWriter* RenderBool(StringPiece name, bool value) = 0; - - // Renders an 32-bit integer value. - virtual ObjectWriter* RenderInt32(StringPiece name, int32_t value) = 0; - - // Renders an 32-bit unsigned integer value. - virtual ObjectWriter* RenderUint32(StringPiece name, - uint32_t value) = 0; - - // Renders a 64-bit integer value. - virtual ObjectWriter* RenderInt64(StringPiece name, int64_t value) = 0; - - // Renders an 64-bit unsigned integer value. - virtual ObjectWriter* RenderUint64(StringPiece name, - uint64_t value) = 0; - - - // Renders a double value. - virtual ObjectWriter* RenderDouble(StringPiece name, double value) = 0; - // Renders a float value. - virtual ObjectWriter* RenderFloat(StringPiece name, float value) = 0; - - // Renders a StringPiece value. This is for rendering strings. - virtual ObjectWriter* RenderString(StringPiece name, - StringPiece value) = 0; - - // Renders a bytes value. - virtual ObjectWriter* RenderBytes(StringPiece name, StringPiece value) = 0; - - // Renders a Null value. - virtual ObjectWriter* RenderNull(StringPiece name) = 0; - - - // Renders a DataPiece object to a ObjectWriter. - static void RenderDataPieceTo(const DataPiece& data, StringPiece name, - ObjectWriter* ow); - - - // Indicates whether this ObjectWriter has completed writing the root message, - // usually this means writing of one complete object. Subclasses must override - // this behavior appropriately. - virtual bool done() { return false; } - - void set_use_strict_base64_decoding(bool value) { - use_strict_base64_decoding_ = value; - } - - bool use_strict_base64_decoding() const { - return use_strict_base64_decoding_; - } - - protected: - ObjectWriter() : use_strict_base64_decoding_(true) {} - - private: - // If set to true, we use the stricter version of base64 decoding for byte - // fields by making sure decoded version encodes back to the original string. - bool use_strict_base64_decoding_; - - // Do not add any data members to this class. - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ObjectWriter); -}; - -} // namespace converter -} // namespace util -} // namespace protobuf -} // namespace google - -#include <google/protobuf/port_undef.inc> - -#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_OBJECT_WRITER_H__ diff --git a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/proto_writer.cc b/contrib/libs/protobuf_std/src/google/protobuf/util/internal/proto_writer.cc deleted file mode 100644 index 717cee4c1d..0000000000 --- a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/proto_writer.cc +++ /dev/null @@ -1,825 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include <google/protobuf/util/internal/proto_writer.h> - -#include <cstdint> -#include <functional> -#include <stack> - -#include <google/protobuf/stubs/once.h> -#include <google/protobuf/wire_format_lite.h> -#include <google/protobuf/util/internal/field_mask_utility.h> -#include <google/protobuf/util/internal/object_location_tracker.h> -#include <google/protobuf/util/internal/constants.h> -#include <google/protobuf/util/internal/utility.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/stubs/statusor.h> -#include <google/protobuf/stubs/time.h> -#include <google/protobuf/stubs/map_util.h> - - -#include <google/protobuf/port_def.inc> - -namespace google { -namespace protobuf { -namespace util { -namespace converter { - -using io::CodedOutputStream; -using ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite; - -ProtoWriter::ProtoWriter(TypeResolver* type_resolver, - const google::protobuf::Type& type, - strings::ByteSink* output, ErrorListener* listener) - : master_type_(type), - typeinfo_(TypeInfo::NewTypeInfo(type_resolver)), - own_typeinfo_(true), - done_(false), - ignore_unknown_fields_(false), - ignore_unknown_enum_values_(false), - use_lower_camel_for_enums_(false), - case_insensitive_enum_parsing_(true), - use_json_name_in_missing_fields_(false), - element_(nullptr), - size_insert_(), - output_(output), - buffer_(), - adapter_(&buffer_), - stream_(new CodedOutputStream(&adapter_)), - listener_(listener), - invalid_depth_(0), - tracker_(new ObjectLocationTracker()) {} - -ProtoWriter::ProtoWriter(const TypeInfo* typeinfo, - const google::protobuf::Type& type, - strings::ByteSink* output, ErrorListener* listener) - : master_type_(type), - typeinfo_(typeinfo), - own_typeinfo_(false), - done_(false), - ignore_unknown_fields_(false), - ignore_unknown_enum_values_(false), - use_lower_camel_for_enums_(false), - case_insensitive_enum_parsing_(true), - use_json_name_in_missing_fields_(false), - element_(nullptr), - size_insert_(), - output_(output), - buffer_(), - adapter_(&buffer_), - stream_(new CodedOutputStream(&adapter_)), - listener_(listener), - invalid_depth_(0), - tracker_(new ObjectLocationTracker()) {} - -ProtoWriter::~ProtoWriter() { - if (own_typeinfo_) { - delete typeinfo_; - } - if (element_ == nullptr) return; - // Cleanup explicitly in order to avoid destructor stack overflow when input - // is deeply nested. - // Cast to BaseElement to avoid doing additional checks (like missing fields) - // during pop(). - std::unique_ptr<BaseElement> element( - static_cast<BaseElement*>(element_.get())->pop<BaseElement>()); - while (element != nullptr) { - element.reset(element->pop<BaseElement>()); - } -} - -namespace { - -// Writes an INT32 field, including tag to the stream. -inline util::Status WriteInt32(int field_number, const DataPiece& data, - CodedOutputStream* stream) { - util::StatusOr<int32_t> i32 = data.ToInt32(); - if (i32.ok()) { - WireFormatLite::WriteInt32(field_number, i32.value(), stream); - } - return i32.status(); -} - -// writes an SFIXED32 field, including tag, to the stream. -inline util::Status WriteSFixed32(int field_number, const DataPiece& data, - CodedOutputStream* stream) { - util::StatusOr<int32_t> i32 = data.ToInt32(); - if (i32.ok()) { - WireFormatLite::WriteSFixed32(field_number, i32.value(), stream); - } - return i32.status(); -} - -// Writes an SINT32 field, including tag, to the stream. -inline util::Status WriteSInt32(int field_number, const DataPiece& data, - CodedOutputStream* stream) { - util::StatusOr<int32_t> i32 = data.ToInt32(); - if (i32.ok()) { - WireFormatLite::WriteSInt32(field_number, i32.value(), stream); - } - return i32.status(); -} - -// Writes a FIXED32 field, including tag, to the stream. -inline util::Status WriteFixed32(int field_number, const DataPiece& data, - CodedOutputStream* stream) { - util::StatusOr<uint32_t> u32 = data.ToUint32(); - if (u32.ok()) { - WireFormatLite::WriteFixed32(field_number, u32.value(), stream); - } - return u32.status(); -} - -// Writes a UINT32 field, including tag, to the stream. -inline util::Status WriteUInt32(int field_number, const DataPiece& data, - CodedOutputStream* stream) { - util::StatusOr<uint32_t> u32 = data.ToUint32(); - if (u32.ok()) { - WireFormatLite::WriteUInt32(field_number, u32.value(), stream); - } - return u32.status(); -} - -// Writes an INT64 field, including tag, to the stream. -inline util::Status WriteInt64(int field_number, const DataPiece& data, - CodedOutputStream* stream) { - util::StatusOr<int64_t> i64 = data.ToInt64(); - if (i64.ok()) { - WireFormatLite::WriteInt64(field_number, i64.value(), stream); - } - return i64.status(); -} - -// Writes an SFIXED64 field, including tag, to the stream. -inline util::Status WriteSFixed64(int field_number, const DataPiece& data, - CodedOutputStream* stream) { - util::StatusOr<int64_t> i64 = data.ToInt64(); - if (i64.ok()) { - WireFormatLite::WriteSFixed64(field_number, i64.value(), stream); - } - return i64.status(); -} - -// Writes an SINT64 field, including tag, to the stream. -inline util::Status WriteSInt64(int field_number, const DataPiece& data, - CodedOutputStream* stream) { - util::StatusOr<int64_t> i64 = data.ToInt64(); - if (i64.ok()) { - WireFormatLite::WriteSInt64(field_number, i64.value(), stream); - } - return i64.status(); -} - -// Writes a FIXED64 field, including tag, to the stream. -inline util::Status WriteFixed64(int field_number, const DataPiece& data, - CodedOutputStream* stream) { - util::StatusOr<uint64_t> u64 = data.ToUint64(); - if (u64.ok()) { - WireFormatLite::WriteFixed64(field_number, u64.value(), stream); - } - return u64.status(); -} - -// Writes a UINT64 field, including tag, to the stream. -inline util::Status WriteUInt64(int field_number, const DataPiece& data, - CodedOutputStream* stream) { - util::StatusOr<uint64_t> u64 = data.ToUint64(); - if (u64.ok()) { - WireFormatLite::WriteUInt64(field_number, u64.value(), stream); - } - return u64.status(); -} - -// Writes a DOUBLE field, including tag, to the stream. -inline util::Status WriteDouble(int field_number, const DataPiece& data, - CodedOutputStream* stream) { - util::StatusOr<double> d = data.ToDouble(); - if (d.ok()) { - WireFormatLite::WriteDouble(field_number, d.value(), stream); - } - return d.status(); -} - -// Writes a FLOAT field, including tag, to the stream. -inline util::Status WriteFloat(int field_number, const DataPiece& data, - CodedOutputStream* stream) { - util::StatusOr<float> f = data.ToFloat(); - if (f.ok()) { - WireFormatLite::WriteFloat(field_number, f.value(), stream); - } - return f.status(); -} - -// Writes a BOOL field, including tag, to the stream. -inline util::Status WriteBool(int field_number, const DataPiece& data, - CodedOutputStream* stream) { - util::StatusOr<bool> b = data.ToBool(); - if (b.ok()) { - WireFormatLite::WriteBool(field_number, b.value(), stream); - } - return b.status(); -} - -// Writes a BYTES field, including tag, to the stream. -inline util::Status WriteBytes(int field_number, const DataPiece& data, - CodedOutputStream* stream) { - util::StatusOr<std::string> c = data.ToBytes(); - if (c.ok()) { - WireFormatLite::WriteBytes(field_number, c.value(), stream); - } - return c.status(); -} - -// Writes a STRING field, including tag, to the stream. -inline util::Status WriteString(int field_number, const DataPiece& data, - CodedOutputStream* stream) { - util::StatusOr<std::string> s = data.ToString(); - if (s.ok()) { - WireFormatLite::WriteString(field_number, s.value(), stream); - } - return s.status(); -} - -// Given a google::protobuf::Type, returns the set of all required fields. -std::set<const google::protobuf::Field*> GetRequiredFields( - const google::protobuf::Type& type) { - std::set<const google::protobuf::Field*> required; - for (int i = 0; i < type.fields_size(); i++) { - const google::protobuf::Field& field = type.fields(i); - if (field.cardinality() == google::protobuf::Field::CARDINALITY_REQUIRED) { - required.insert(&field); - } - } - return required; -} - -} // namespace - -ProtoWriter::ProtoElement::ProtoElement(const TypeInfo* typeinfo, - const google::protobuf::Type& type, - ProtoWriter* enclosing) - : BaseElement(nullptr), - ow_(enclosing), - parent_field_(nullptr), - typeinfo_(typeinfo), - proto3_(type.syntax() == google::protobuf::SYNTAX_PROTO3), - type_(type), - size_index_(-1), - array_index_(-1), - // oneof_indices_ values are 1-indexed (0 means not present). - oneof_indices_(type.oneofs_size() + 1) { - if (!proto3_) { - required_fields_ = GetRequiredFields(type_); - } -} - -ProtoWriter::ProtoElement::ProtoElement(ProtoWriter::ProtoElement* parent, - const google::protobuf::Field* field, - const google::protobuf::Type& type, - bool is_list) - : BaseElement(parent), - ow_(this->parent()->ow_), - parent_field_(field), - typeinfo_(this->parent()->typeinfo_), - proto3_(type.syntax() == google::protobuf::SYNTAX_PROTO3), - type_(type), - size_index_(!is_list && - field->kind() == google::protobuf::Field::TYPE_MESSAGE - ? ow_->size_insert_.size() - : -1), - array_index_(is_list ? 0 : -1), - // oneof_indices_ values are 1-indexed (0 means not present). - oneof_indices_(type_.oneofs_size() + 1) { - if (!is_list) { - if (ow_->IsRepeated(*field)) { - // Update array_index_ if it is an explicit list. - if (this->parent()->array_index_ >= 0) this->parent()->array_index_++; - } else if (!proto3_) { - // For required fields tracking. - this->parent()->RegisterField(field); - } - - if (field->kind() == google::protobuf::Field::TYPE_MESSAGE) { - if (!proto3_) { - required_fields_ = GetRequiredFields(type_); - } - int start_pos = ow_->stream_->ByteCount(); - // length of serialized message is the final buffer position minus - // starting buffer position, plus length adjustments for size fields - // of any nested messages. We start with -start_pos here, so we only - // need to add the final buffer position to it at the end. - SizeInfo info = {start_pos, -start_pos}; - ow_->size_insert_.push_back(info); - } - } -} - -ProtoWriter::ProtoElement* ProtoWriter::ProtoElement::pop() { - if (!proto3_) { - // Calls the registered error listener for any required field(s) not yet - // seen. - for (std::set<const google::protobuf::Field*>::iterator it = - required_fields_.begin(); - it != required_fields_.end(); ++it) { - ow_->MissingField(ow_->use_json_name_in_missing_fields_ - ? (*it)->json_name() - : (*it)->name()); - } - } - // Computes the total number of proto bytes used by a message, also adjusts - // the size of all parent messages by the length of this size field. - // If size_index_ < 0, this is not a message, so no size field is added. - if (size_index_ >= 0) { - // Add the final buffer position to compute the total length of this - // serialized message. The stored value (before this addition) already - // contains the total length of the size fields of all nested messages - // minus the initial buffer position. - ow_->size_insert_[size_index_].size += ow_->stream_->ByteCount(); - // Calculate the length required to serialize the size field of the - // message, and propagate this additional size information upward to - // all enclosing messages. - int size = ow_->size_insert_[size_index_].size; - int length = CodedOutputStream::VarintSize32(size); - for (ProtoElement* e = parent(); e != nullptr; e = e->parent()) { - // Only nested messages have size field, lists do not have size field. - if (e->size_index_ >= 0) { - ow_->size_insert_[e->size_index_].size += length; - } - } - } - return BaseElement::pop<ProtoElement>(); -} - -void ProtoWriter::ProtoElement::RegisterField( - const google::protobuf::Field* field) { - if (!required_fields_.empty() && - field->cardinality() == google::protobuf::Field::CARDINALITY_REQUIRED) { - required_fields_.erase(field); - } -} - -std::string ProtoWriter::ProtoElement::ToString() const { - std::string loc = ""; - - // first populate a stack with the nodes since we need to process them - // from root to leaf when generating the string location - const ProtoWriter::ProtoElement* now = this; - std::stack<const ProtoWriter::ProtoElement*> element_stack; - while (now->parent() != nullptr) { - element_stack.push(now); - now = now->parent(); - } - - // now pop each node from the stack and append to the location string - while (!element_stack.empty()) { - now = element_stack.top(); - element_stack.pop(); - - if (!ow_->IsRepeated(*(now->parent_field_)) || - now->parent()->parent_field_ != now->parent_field_) { - std::string name = now->parent_field_->name(); - int i = 0; - while (i < name.size() && - (ascii_isalnum(name[i]) || name[i] == '_')) - ++i; - if (i > 0 && i == name.size()) { // safe field name - if (loc.empty()) { - loc = name; - } else { - StrAppend(&loc, ".", name); - } - } else { - StrAppend(&loc, "[\"", CEscape(name), "\"]"); - } - } - - int array_index_now = now->array_index_; - if (ow_->IsRepeated(*(now->parent_field_)) && array_index_now > 0) { - StrAppend(&loc, "[", array_index_now - 1, "]"); - } - } - - return loc; -} - -bool ProtoWriter::ProtoElement::IsOneofIndexTaken(int32_t index) { - return oneof_indices_[index]; -} - -void ProtoWriter::ProtoElement::TakeOneofIndex(int32_t index) { - oneof_indices_[index] = true; -} - -void ProtoWriter::InvalidName(StringPiece unknown_name, - StringPiece message) { - listener_->InvalidName(location(), unknown_name, message); -} - -void ProtoWriter::InvalidValue(StringPiece type_name, - StringPiece value) { - listener_->InvalidValue(location(), type_name, value); -} - -void ProtoWriter::MissingField(StringPiece missing_name) { - listener_->MissingField(location(), missing_name); -} - -ProtoWriter* ProtoWriter::StartObject( - StringPiece name) { - // Starting the root message. Create the root ProtoElement and return. - if (element_ == nullptr) { - if (!name.empty()) { - InvalidName(name, "Root element should not be named."); - } - element_.reset(new ProtoElement(typeinfo_, master_type_, this)); - return this; - } - - const google::protobuf::Field* field = BeginNamed(name, false); - - if (field == nullptr) return this; - - // Check to see if this field is a oneof and that no oneof in that group has - // already been set. - if (!ValidOneof(*field, name)) { - ++invalid_depth_; - return this; - } - - const google::protobuf::Type* type = LookupType(field); - if (type == nullptr) { - ++invalid_depth_; - InvalidName(name, StrCat("Missing descriptor for field: ", - field->type_url())); - return this; - } - - return StartObjectField(*field, *type); -} - - -ProtoWriter* ProtoWriter::EndObject() { - if (invalid_depth_ > 0) { - --invalid_depth_; - return this; - } - - if (element_ != nullptr) { - element_.reset(element_->pop()); - } - - - // If ending the root element, - // then serialize the full message with calculated sizes. - if (element_ == nullptr) { - WriteRootMessage(); - } - return this; -} - -ProtoWriter* ProtoWriter::StartList( - StringPiece name) { - - const google::protobuf::Field* field = BeginNamed(name, true); - - if (field == nullptr) return this; - - if (!ValidOneof(*field, name)) { - ++invalid_depth_; - return this; - } - - const google::protobuf::Type* type = LookupType(field); - if (type == nullptr) { - ++invalid_depth_; - InvalidName(name, StrCat("Missing descriptor for field: ", - field->type_url())); - return this; - } - - return StartListField(*field, *type); -} - - -ProtoWriter* ProtoWriter::EndList() { - if (invalid_depth_ > 0) { - --invalid_depth_; - } else if (element_ != nullptr) { - element_.reset(element_->pop()); - } - return this; -} - -ProtoWriter* ProtoWriter::RenderDataPiece( - StringPiece name, const DataPiece& data) { - util::Status status; - if (invalid_depth_ > 0) return this; - - const google::protobuf::Field* field = Lookup(name); - - if (field == nullptr) return this; - - if (!ValidOneof(*field, name)) return this; - - const google::protobuf::Type* type = LookupType(field); - if (type == nullptr) { - InvalidName(name, StrCat("Missing descriptor for field: ", - field->type_url())); - return this; - } - - return RenderPrimitiveField(*field, *type, data); -} - -bool ProtoWriter::ValidOneof(const google::protobuf::Field& field, - StringPiece unnormalized_name) { - if (element_ == nullptr) return true; - - if (field.oneof_index() > 0) { - if (element_->IsOneofIndexTaken(field.oneof_index())) { - InvalidValue( - "oneof", - StrCat( - "oneof field '", element_->type().oneofs(field.oneof_index() - 1), - "' is already set. Cannot set '", unnormalized_name, "'")); - return false; - } - element_->TakeOneofIndex(field.oneof_index()); - } - return true; -} - -bool ProtoWriter::IsRepeated(const google::protobuf::Field& field) { - return field.cardinality() == google::protobuf::Field::CARDINALITY_REPEATED; -} - -ProtoWriter* ProtoWriter::StartObjectField(const google::protobuf::Field& field, - const google::protobuf::Type& type) { - WriteTag(field); - element_.reset(new ProtoElement(element_.release(), &field, type, false)); - return this; -} - -ProtoWriter* ProtoWriter::StartListField(const google::protobuf::Field& field, - const google::protobuf::Type& type) { - element_.reset(new ProtoElement(element_.release(), &field, type, true)); - return this; -} - -util::Status ProtoWriter::WriteEnum(int field_number, const DataPiece& data, - const google::protobuf::Enum* enum_type, - CodedOutputStream* stream, - bool use_lower_camel_for_enums, - bool case_insensitive_enum_parsing, - bool ignore_unknown_values) { - bool is_unknown_enum_value = false; - util::StatusOr<int> e = data.ToEnum( - enum_type, use_lower_camel_for_enums, case_insensitive_enum_parsing, - ignore_unknown_values, &is_unknown_enum_value); - if (e.ok() && !is_unknown_enum_value) { - WireFormatLite::WriteEnum(field_number, e.value(), stream); - } - return e.status(); -} - -ProtoWriter* ProtoWriter::RenderPrimitiveField( - const google::protobuf::Field& field, const google::protobuf::Type& type, - const DataPiece& data) { - util::Status status; - - // Pushing a ProtoElement and then pop it off at the end for 2 purposes: - // error location reporting and required field accounting. - // - // For proto3, since there is no required field tracking, we only need to - // push ProtoElement for error cases. - if (!element_->proto3()) { - element_.reset(new ProtoElement(element_.release(), &field, type, false)); - } - - switch (field.kind()) { - case google::protobuf::Field::TYPE_INT32: { - status = WriteInt32(field.number(), data, stream_.get()); - break; - } - case google::protobuf::Field::TYPE_SFIXED32: { - status = WriteSFixed32(field.number(), data, stream_.get()); - break; - } - case google::protobuf::Field::TYPE_SINT32: { - status = WriteSInt32(field.number(), data, stream_.get()); - break; - } - case google::protobuf::Field::TYPE_FIXED32: { - status = WriteFixed32(field.number(), data, stream_.get()); - break; - } - case google::protobuf::Field::TYPE_UINT32: { - status = WriteUInt32(field.number(), data, stream_.get()); - break; - } - case google::protobuf::Field::TYPE_INT64: { - status = WriteInt64(field.number(), data, stream_.get()); - break; - } - case google::protobuf::Field::TYPE_SFIXED64: { - status = WriteSFixed64(field.number(), data, stream_.get()); - break; - } - case google::protobuf::Field::TYPE_SINT64: { - status = WriteSInt64(field.number(), data, stream_.get()); - break; - } - case google::protobuf::Field::TYPE_FIXED64: { - status = WriteFixed64(field.number(), data, stream_.get()); - break; - } - case google::protobuf::Field::TYPE_UINT64: { - status = WriteUInt64(field.number(), data, stream_.get()); - break; - } - case google::protobuf::Field::TYPE_DOUBLE: { - status = WriteDouble(field.number(), data, stream_.get()); - break; - } - case google::protobuf::Field::TYPE_FLOAT: { - status = WriteFloat(field.number(), data, stream_.get()); - break; - } - case google::protobuf::Field::TYPE_BOOL: { - status = WriteBool(field.number(), data, stream_.get()); - break; - } - case google::protobuf::Field::TYPE_BYTES: { - status = WriteBytes(field.number(), data, stream_.get()); - break; - } - case google::protobuf::Field::TYPE_STRING: { - status = WriteString(field.number(), data, stream_.get()); - break; - } - case google::protobuf::Field::TYPE_ENUM: { - status = WriteEnum( - field.number(), data, typeinfo_->GetEnumByTypeUrl(field.type_url()), - stream_.get(), use_lower_camel_for_enums_, - case_insensitive_enum_parsing_, ignore_unknown_enum_values_); - break; - } - default: // TYPE_GROUP, TYPE_MESSAGE, TYPE_UNKNOWN. - status = util::InvalidArgumentError(data.ValueAsStringOrDefault("")); - } - - if (!status.ok()) { - // Push a ProtoElement for location reporting purposes. - if (element_->proto3()) { - element_.reset(new ProtoElement(element_.release(), &field, type, false)); - } - InvalidValue(field.type_url().empty() - ? google::protobuf::Field_Kind_Name(field.kind()) - : field.type_url(), - status.message()); - element_.reset(element()->pop()); - return this; - } - - if (!element_->proto3()) element_.reset(element()->pop()); - - return this; -} - -const google::protobuf::Field* ProtoWriter::BeginNamed(StringPiece name, - bool is_list) { - if (invalid_depth_ > 0) { - ++invalid_depth_; - return nullptr; - } - const google::protobuf::Field* field = Lookup(name); - if (field == nullptr) { - ++invalid_depth_; - // InvalidName() already called in Lookup(). - return nullptr; - } - if (is_list && !IsRepeated(*field)) { - ++invalid_depth_; - InvalidName(name, "Proto field is not repeating, cannot start list."); - return nullptr; - } - return field; -} - -const google::protobuf::Field* ProtoWriter::Lookup( - StringPiece unnormalized_name) { - ProtoElement* e = element(); - if (e == nullptr) { - InvalidName(unnormalized_name, "Root element must be a message."); - return nullptr; - } - if (unnormalized_name.empty()) { - // Objects in repeated field inherit the same field descriptor. - if (e->parent_field() == nullptr) { - InvalidName(unnormalized_name, "Proto fields must have a name."); - } else if (!IsRepeated(*e->parent_field())) { - InvalidName(unnormalized_name, "Proto fields must have a name."); - return nullptr; - } - return e->parent_field(); - } - const google::protobuf::Field* field = - typeinfo_->FindField(&e->type(), unnormalized_name); - if (field == nullptr && !ignore_unknown_fields_) { - InvalidName(unnormalized_name, "Cannot find field."); - } - return field; -} - -const google::protobuf::Type* ProtoWriter::LookupType( - const google::protobuf::Field* field) { - return ((field->kind() == google::protobuf::Field::TYPE_MESSAGE || - field->kind() == google::protobuf::Field::TYPE_GROUP) - ? typeinfo_->GetTypeByTypeUrl(field->type_url()) - : &element_->type()); -} - -void ProtoWriter::WriteRootMessage() { - GOOGLE_DCHECK(!done_); - int curr_pos = 0; - // Calls the destructor of CodedOutputStream to remove any uninitialized - // memory from the Cord before we read it. - stream_.reset(nullptr); - const void* data; - int length; - io::ArrayInputStream input_stream(buffer_.data(), buffer_.size()); - while (input_stream.Next(&data, &length)) { - if (length == 0) continue; - int num_bytes = length; - // Write up to where we need to insert the size field. - // The number of bytes we may write is the smaller of: - // - the current fragment size - // - the distance to the next position where a size field needs to be - // inserted. - if (!size_insert_.empty() && - size_insert_.front().pos - curr_pos < num_bytes) { - num_bytes = size_insert_.front().pos - curr_pos; - } - output_->Append(static_cast<const char*>(data), num_bytes); - if (num_bytes < length) { - input_stream.BackUp(length - num_bytes); - } - curr_pos += num_bytes; - // Insert the size field. - // size_insert_.front(): the next <index, size> pair to be written. - // size_insert_.front().pos: position of the size field. - // size_insert_.front().size: the size (integer) to be inserted. - if (!size_insert_.empty() && curr_pos == size_insert_.front().pos) { - // Varint32 occupies at most 10 bytes. - uint8_t insert_buffer[10]; - uint8_t* insert_buffer_pos = CodedOutputStream::WriteVarint32ToArray( - size_insert_.front().size, insert_buffer); - output_->Append(reinterpret_cast<const char*>(insert_buffer), - insert_buffer_pos - insert_buffer); - size_insert_.pop_front(); - } - } - output_->Flush(); - stream_.reset(new CodedOutputStream(&adapter_)); - done_ = true; -} - -void ProtoWriter::WriteTag(const google::protobuf::Field& field) { - WireFormatLite::WireType wire_type = WireFormatLite::WireTypeForFieldType( - static_cast<WireFormatLite::FieldType>(field.kind())); - stream_->WriteTag(WireFormatLite::MakeTag(field.number(), wire_type)); -} - - -} // namespace converter -} // namespace util -} // namespace protobuf -} // namespace google diff --git a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/proto_writer.h b/contrib/libs/protobuf_std/src/google/protobuf/util/internal/proto_writer.h deleted file mode 100644 index 109c1989b7..0000000000 --- a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/proto_writer.h +++ /dev/null @@ -1,388 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTO_WRITER_H__ -#define GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTO_WRITER_H__ - -#include <cstdint> -#include <deque> -#include <string> -#include <vector> - -#include <google/protobuf/stubs/common.h> -#include <google/protobuf/type.pb.h> -#include <google/protobuf/io/coded_stream.h> -#include <google/protobuf/io/zero_copy_stream_impl.h> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/util/internal/type_info.h> -#include <google/protobuf/util/internal/datapiece.h> -#include <google/protobuf/util/internal/error_listener.h> -#include <google/protobuf/util/internal/structured_objectwriter.h> -#include <google/protobuf/util/type_resolver.h> -#include <google/protobuf/stubs/bytestream.h> -#include <google/protobuf/stubs/status.h> -#include <google/protobuf/stubs/hash.h> -#include <google/protobuf/stubs/status.h> - -// Must be included last. -#include <google/protobuf/port_def.inc> - -namespace google { -namespace protobuf { -namespace util { -namespace converter { - - -class ObjectLocationTracker; - -// An ObjectWriter that can write protobuf bytes directly from writer events. -// This class does not support special types like Struct or Map. However, since -// this class supports raw protobuf, it can be used to provide support for -// special types by inheriting from it or by wrapping it. -// -// It also supports streaming. -class PROTOBUF_EXPORT ProtoWriter : public StructuredObjectWriter { - public: -// Constructor. Does not take ownership of any parameter passed in. - ProtoWriter(TypeResolver* type_resolver, const google::protobuf::Type& type, - strings::ByteSink* output, ErrorListener* listener); - ~ProtoWriter() override; - - // ObjectWriter methods. - ProtoWriter* StartObject(StringPiece name) override; - ProtoWriter* EndObject() override; - ProtoWriter* StartList(StringPiece name) override; - ProtoWriter* EndList() override; - ProtoWriter* RenderBool(StringPiece name, bool value) override { - return RenderDataPiece(name, DataPiece(value)); - } - ProtoWriter* RenderInt32(StringPiece name, int32_t value) override { - return RenderDataPiece(name, DataPiece(value)); - } - ProtoWriter* RenderUint32(StringPiece name, uint32_t value) override { - return RenderDataPiece(name, DataPiece(value)); - } - ProtoWriter* RenderInt64(StringPiece name, int64_t value) override { - return RenderDataPiece(name, DataPiece(value)); - } - ProtoWriter* RenderUint64(StringPiece name, uint64_t value) override { - return RenderDataPiece(name, DataPiece(value)); - } - ProtoWriter* RenderDouble(StringPiece name, double value) override { - return RenderDataPiece(name, DataPiece(value)); - } - ProtoWriter* RenderFloat(StringPiece name, float value) override { - return RenderDataPiece(name, DataPiece(value)); - } - ProtoWriter* RenderString(StringPiece name, - StringPiece value) override { - return RenderDataPiece(name, - DataPiece(value, use_strict_base64_decoding())); - } - - ProtoWriter* RenderBytes(StringPiece name, StringPiece value) override { - return RenderDataPiece( - name, DataPiece(value, false, use_strict_base64_decoding())); - } - - ProtoWriter* RenderNull(StringPiece name) override { - return RenderDataPiece(name, DataPiece::NullData()); - } - - - // Renders a DataPiece 'value' into a field whose wire type is determined - // from the given field 'name'. - virtual ProtoWriter* RenderDataPiece(StringPiece name, - const DataPiece& data); - - - // Returns the location tracker to use for tracking locations for errors. - const LocationTrackerInterface& location() { - return element_ != nullptr ? *element_ : *tracker_; - } - - // When true, we finished writing to output a complete message. - bool done() override { return done_; } - - // Returns the proto stream object. - io::CodedOutputStream* stream() { return stream_.get(); } - - // Getters and mutators of invalid_depth_. - void IncrementInvalidDepth() { ++invalid_depth_; } - void DecrementInvalidDepth() { --invalid_depth_; } - int invalid_depth() { return invalid_depth_; } - - ErrorListener* listener() { return listener_; } - - const TypeInfo* typeinfo() { return typeinfo_; } - - void set_ignore_unknown_fields(bool ignore_unknown_fields) { - ignore_unknown_fields_ = ignore_unknown_fields; - } - - bool ignore_unknown_fields() { return ignore_unknown_fields_; } - - void set_ignore_unknown_enum_values(bool ignore_unknown_enum_values) { - ignore_unknown_enum_values_ = ignore_unknown_enum_values; - } - - void set_use_lower_camel_for_enums(bool use_lower_camel_for_enums) { - use_lower_camel_for_enums_ = use_lower_camel_for_enums; - } - - void set_case_insensitive_enum_parsing(bool case_insensitive_enum_parsing) { - case_insensitive_enum_parsing_ = case_insensitive_enum_parsing; - } - - void set_use_json_name_in_missing_fields( - bool use_json_name_in_missing_fields) { - use_json_name_in_missing_fields_ = use_json_name_in_missing_fields; - } - - protected: - class PROTOBUF_EXPORT ProtoElement : public BaseElement, - public LocationTrackerInterface { - public: - // Constructor for the root element. No parent nor field. - ProtoElement(const TypeInfo* typeinfo, const google::protobuf::Type& type, - ProtoWriter* enclosing); - - // Constructor for a field of an element. - ProtoElement(ProtoElement* parent, const google::protobuf::Field* field, - const google::protobuf::Type& type, bool is_list); - - ~ProtoElement() override {} - - // Called just before the destructor for clean up: - // - reports any missing required fields - // - computes the space needed by the size field, and augment the - // length of all parent messages by this additional space. - // - releases and returns the parent pointer. - ProtoElement* pop(); - - // Accessors - // parent_field() may be nullptr if we are at root. - const google::protobuf::Field* parent_field() const { - return parent_field_; - } - const google::protobuf::Type& type() const { return type_; } - - // Registers field for accounting required fields. - void RegisterField(const google::protobuf::Field* field); - - // To report location on error messages. - std::string ToString() const override; - - ProtoElement* parent() const override { - return static_cast<ProtoElement*>(BaseElement::parent()); - } - - // Returns true if the index is already taken by a preceding oneof input. - bool IsOneofIndexTaken(int32_t index); - - // Marks the oneof 'index' as taken. Future inputs to this oneof will - // generate an error. - void TakeOneofIndex(int32_t index); - - bool proto3() { return proto3_; } - - private: - // Used for access to variables of the enclosing instance of - // ProtoWriter. - ProtoWriter* ow_; - - // Describes the element as a field in the parent message. - // parent_field_ is nullptr if and only if this element is the root element. - const google::protobuf::Field* parent_field_; - - // TypeInfo to lookup types. - const TypeInfo* typeinfo_; - - // Whether the type_ is proto3 or not. - bool proto3_; - - // Additional variables if this element is a message: - // (Root element is always a message). - // type_ : the type of this element. - // required_fields_ : set of required fields. - // size_index_ : index into ProtoWriter::size_insert_ - // for later insertion of serialized message length. - const google::protobuf::Type& type_; - std::set<const google::protobuf::Field*> required_fields_; - const int size_index_; - - // Tracks position in repeated fields, needed for LocationTrackerInterface. - int array_index_; - - // Set of oneof indices already seen for the type_. Used to validate - // incoming messages so no more than one oneof is set. - std::vector<bool> oneof_indices_; - - GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(ProtoElement); - }; - - // Container for inserting 'size' information at the 'pos' position. - struct SizeInfo { - const int pos; - int size; - }; - - ProtoWriter(const TypeInfo* typeinfo, const google::protobuf::Type& type, - strings::ByteSink* output, ErrorListener* listener); - - ProtoElement* element() override { return element_.get(); } - - // Helper methods for calling ErrorListener. See error_listener.h. - void InvalidName(StringPiece unknown_name, StringPiece message); - void InvalidValue(StringPiece type_name, StringPiece value); - void MissingField(StringPiece missing_name); - - // Common code for BeginObject() and BeginList() that does invalid_depth_ - // bookkeeping associated with name lookup. - const google::protobuf::Field* BeginNamed(StringPiece name, - bool is_list); - - // Lookup the field in the current element. Looks in the base descriptor - // and in any extension. This will report an error if the field cannot be - // found when ignore_unknown_names_ is false or if multiple matching - // extensions are found. - const google::protobuf::Field* Lookup(StringPiece name); - - // Lookup the field type in the type descriptor. Returns nullptr if the type - // is not known. - const google::protobuf::Type* LookupType( - const google::protobuf::Field* field); - - // Write serialized output to the final output ByteSink, inserting all - // the size information for nested messages that are missing from the - // intermediate Cord buffer. - void WriteRootMessage(); - - // Helper method to write proto tags based on the given field. - void WriteTag(const google::protobuf::Field& field); - - - // Returns true if the field for type_ can be set as a oneof. If field is not - // a oneof type, this function does nothing and returns true. - // If another field for this oneof is already set, this function returns - // false. It also calls the appropriate error callback. - // unnormalized_name is used for error string. - bool ValidOneof(const google::protobuf::Field& field, - StringPiece unnormalized_name); - - // Returns true if the field is repeated. - bool IsRepeated(const google::protobuf::Field& field); - - // Starts an object given the field and the enclosing type. - ProtoWriter* StartObjectField(const google::protobuf::Field& field, - const google::protobuf::Type& type); - - // Starts a list given the field and the enclosing type. - ProtoWriter* StartListField(const google::protobuf::Field& field, - const google::protobuf::Type& type); - - // Renders a primitive field given the field and the enclosing type. - ProtoWriter* RenderPrimitiveField(const google::protobuf::Field& field, - const google::protobuf::Type& type, - const DataPiece& data); - - private: - // Writes an ENUM field, including tag, to the stream. - static util::Status WriteEnum(int field_number, const DataPiece& data, - const google::protobuf::Enum* enum_type, - io::CodedOutputStream* stream, - bool use_lower_camel_for_enums, - bool case_insensitive_enum_parsing, - bool ignore_unknown_values); - - // Variables for describing the structure of the input tree: - // master_type_: descriptor for the whole protobuf message. - // typeinfo_ : the TypeInfo object to lookup types. - const google::protobuf::Type& master_type_; - const TypeInfo* typeinfo_; - // Whether we own the typeinfo_ object. - bool own_typeinfo_; - - // Indicates whether we finished writing root message completely. - bool done_; - - // If true, don't report unknown field names to the listener. - bool ignore_unknown_fields_; - - // If true, don't report unknown enum values to the listener. - bool ignore_unknown_enum_values_; - - // If true, check if enum name in camel case or without underscore matches the - // field name. - bool use_lower_camel_for_enums_; - - // If true, check if enum name in UPPER_CASE matches the field name. - bool case_insensitive_enum_parsing_; - - // If true, use the json name in missing fields errors. - bool use_json_name_in_missing_fields_; - - // Variable for internal state processing: - // element_ : the current element. - // size_insert_: sizes of nested messages. - // pos - position to insert the size field. - // size - size value to be inserted. - std::unique_ptr<ProtoElement> element_; - std::deque<SizeInfo> size_insert_; - - // Variables for output generation: - // output_ : pointer to an external ByteSink for final user-visible output. - // buffer_ : buffer holding partial message before being ready for output_. - // adapter_ : internal adapter between CodedOutputStream and buffer_. - // stream_ : wrapper for writing tags and other encodings in wire format. - strings::ByteSink* output_; - std::string buffer_; - io::StringOutputStream adapter_; - std::unique_ptr<io::CodedOutputStream> stream_; - - // Variables for error tracking and reporting: - // listener_ : a place to report any errors found. - // invalid_depth_: number of enclosing invalid nested messages. - // tracker_ : the root location tracker interface. - ErrorListener* listener_; - int invalid_depth_; - std::unique_ptr<LocationTrackerInterface> tracker_; - - GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(ProtoWriter); -}; - -} // namespace converter -} // namespace util -} // namespace protobuf -} // namespace google - -#include <google/protobuf/port_undef.inc> - -#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTO_WRITER_H__ diff --git a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/protostream_objectsource.cc b/contrib/libs/protobuf_std/src/google/protobuf/util/internal/protostream_objectsource.cc deleted file mode 100644 index 3a37d9c5e9..0000000000 --- a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/protostream_objectsource.cc +++ /dev/null @@ -1,1112 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include <google/protobuf/util/internal/protostream_objectsource.h> - -#include <cstdint> -#include <unordered_map> -#include <utility> - -#include <google/protobuf/stubs/logging.h> -#include <google/protobuf/stubs/common.h> -#include <google/protobuf/stubs/stringprintf.h> -#include <google/protobuf/io/coded_stream.h> -#include <google/protobuf/io/zero_copy_stream_impl.h> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/stubs/once.h> -#include <google/protobuf/unknown_field_set.h> -#include <google/protobuf/wire_format.h> -#include <google/protobuf/wire_format_lite.h> -#include <google/protobuf/util/internal/field_mask_utility.h> -#include <google/protobuf/util/internal/constants.h> -#include <google/protobuf/util/internal/utility.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/stubs/casts.h> -#include <google/protobuf/stubs/status.h> -#include <google/protobuf/stubs/time.h> -#include <google/protobuf/stubs/map_util.h> -#include <google/protobuf/stubs/status_macros.h> - - -#include <google/protobuf/port_def.inc> - -namespace google { -namespace protobuf { -namespace util { -namespace converter { - -using ::PROTOBUF_NAMESPACE_ID::internal::WireFormat; -using ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite; - -namespace { - -static int kDefaultMaxRecursionDepth = 64; - -// Finds a field with the given number. nullptr if none found. -const google::protobuf::Field* FindFieldByNumber( - const google::protobuf::Type& type, int number); - -// Returns true if the field is packable. -bool IsPackable(const google::protobuf::Field& field); - -// Finds an enum value with the given number. nullptr if none found. -const google::protobuf::EnumValue* FindEnumValueByNumber( - const google::protobuf::Enum& tech_enum, int number); - -// Utility function to format nanos. -const std::string FormatNanos(uint32_t nanos, bool with_trailing_zeros); - -util::StatusOr<std::string> MapKeyDefaultValueAsString( - const google::protobuf::Field& field) { - switch (field.kind()) { - case google::protobuf::Field::TYPE_BOOL: - return std::string("false"); - case google::protobuf::Field::TYPE_INT32: - case google::protobuf::Field::TYPE_INT64: - case google::protobuf::Field::TYPE_UINT32: - case google::protobuf::Field::TYPE_UINT64: - case google::protobuf::Field::TYPE_SINT32: - case google::protobuf::Field::TYPE_SINT64: - case google::protobuf::Field::TYPE_SFIXED32: - case google::protobuf::Field::TYPE_SFIXED64: - case google::protobuf::Field::TYPE_FIXED32: - case google::protobuf::Field::TYPE_FIXED64: - return std::string("0"); - case google::protobuf::Field::TYPE_STRING: - return std::string(); - default: - return util::InternalError("Invalid map key type."); - } -} -} // namespace - - -ProtoStreamObjectSource::ProtoStreamObjectSource( - io::CodedInputStream* stream, TypeResolver* type_resolver, - const google::protobuf::Type& type, const RenderOptions& render_options) - : stream_(stream), - typeinfo_(TypeInfo::NewTypeInfo(type_resolver)), - own_typeinfo_(true), - type_(type), - render_options_(render_options), - recursion_depth_(0), - max_recursion_depth_(kDefaultMaxRecursionDepth) { - GOOGLE_LOG_IF(DFATAL, stream == nullptr) << "Input stream is nullptr."; -} - -ProtoStreamObjectSource::ProtoStreamObjectSource( - io::CodedInputStream* stream, const TypeInfo* typeinfo, - const google::protobuf::Type& type, const RenderOptions& render_options) - : stream_(stream), - typeinfo_(typeinfo), - own_typeinfo_(false), - type_(type), - render_options_(render_options), - recursion_depth_(0), - max_recursion_depth_(kDefaultMaxRecursionDepth) { - GOOGLE_LOG_IF(DFATAL, stream == nullptr) << "Input stream is nullptr."; -} - -ProtoStreamObjectSource::~ProtoStreamObjectSource() { - if (own_typeinfo_) { - delete typeinfo_; - } -} - -util::Status ProtoStreamObjectSource::NamedWriteTo(StringPiece name, - ObjectWriter* ow) const { - return WriteMessage(type_, name, 0, true, ow); -} - -const google::protobuf::Field* ProtoStreamObjectSource::FindAndVerifyField( - const google::protobuf::Type& type, uint32_t tag) const { - // Lookup the new field in the type by tag number. - const google::protobuf::Field* field = FindFieldByNumber(type, tag >> 3); - // Verify if the field corresponds to the wire type in tag. - // If there is any discrepancy, mark the field as not found. - if (field != nullptr) { - WireFormatLite::WireType expected_type = - WireFormatLite::WireTypeForFieldType( - static_cast<WireFormatLite::FieldType>(field->kind())); - WireFormatLite::WireType actual_type = WireFormatLite::GetTagWireType(tag); - if (actual_type != expected_type && - (!IsPackable(*field) || - actual_type != WireFormatLite::WIRETYPE_LENGTH_DELIMITED)) { - field = nullptr; - } - } - return field; -} - -util::Status ProtoStreamObjectSource::WriteMessage( - const google::protobuf::Type& type, StringPiece name, - const uint32_t end_tag, bool include_start_and_end, - ObjectWriter* ow) const { - - const TypeRenderer* type_renderer = FindTypeRenderer(type.name()); - if (type_renderer != nullptr) { - return (*type_renderer)(this, type, name, ow); - } - - const google::protobuf::Field* field = nullptr; - std::string field_name; - // last_tag set to dummy value that is different from tag. - uint32_t tag = stream_->ReadTag(), last_tag = tag + 1; - UnknownFieldSet unknown_fields; - - - if (include_start_and_end) { - ow->StartObject(name); - } - while (tag != end_tag && tag != 0) { - if (tag != last_tag) { // Update field only if tag is changed. - last_tag = tag; - field = FindAndVerifyField(type, tag); - if (field != nullptr) { - if (render_options_.preserve_proto_field_names) { - field_name = field->name(); - } else { - field_name = field->json_name(); - } - } - } - if (field == nullptr) { - // If we didn't find a field, skip this unknown tag. - // TODO(wpoon): Check return boolean value. - WireFormat::SkipField( - stream_, tag, - nullptr); - tag = stream_->ReadTag(); - continue; - } - - if (field->cardinality() == google::protobuf::Field::CARDINALITY_REPEATED) { - if (IsMap(*field)) { - ow->StartObject(field_name); - ASSIGN_OR_RETURN(tag, RenderMap(field, field_name, tag, ow)); - ow->EndObject(); - } else { - ASSIGN_OR_RETURN(tag, RenderList(field, field_name, tag, ow)); - } - } else { - // Render the field. - RETURN_IF_ERROR(RenderField(field, field_name, ow)); - tag = stream_->ReadTag(); - } - } - - - if (include_start_and_end) { - ow->EndObject(); - } - return util::Status(); -} - -util::StatusOr<uint32_t> ProtoStreamObjectSource::RenderList( - const google::protobuf::Field* field, StringPiece name, - uint32_t list_tag, ObjectWriter* ow) const { - uint32_t tag_to_return = 0; - ow->StartList(name); - if (IsPackable(*field) && - list_tag == - WireFormatLite::MakeTag(field->number(), - WireFormatLite::WIRETYPE_LENGTH_DELIMITED)) { - RETURN_IF_ERROR(RenderPacked(field, ow)); - // Since packed fields have a single tag, read another tag from stream to - // return. - tag_to_return = stream_->ReadTag(); - } else { - do { - RETURN_IF_ERROR(RenderField(field, "", ow)); - } while ((tag_to_return = stream_->ReadTag()) == list_tag); - } - ow->EndList(); - return tag_to_return; -} - -util::StatusOr<uint32_t> ProtoStreamObjectSource::RenderMap( - const google::protobuf::Field* field, StringPiece name, - uint32_t list_tag, ObjectWriter* ow) const { - const google::protobuf::Type* field_type = - typeinfo_->GetTypeByTypeUrl(field->type_url()); - uint32_t tag_to_return = 0; - do { - // Render map entry message type. - uint32_t buffer32; - stream_->ReadVarint32(&buffer32); // message length - int old_limit = stream_->PushLimit(buffer32); - std::string map_key; - for (uint32_t tag = stream_->ReadTag(); tag != 0; - tag = stream_->ReadTag()) { - const google::protobuf::Field* field = - FindAndVerifyField(*field_type, tag); - if (field == nullptr) { - WireFormat::SkipField(stream_, tag, nullptr); - continue; - } - // Map field numbers are key = 1 and value = 2 - if (field->number() == 1) { - map_key = ReadFieldValueAsString(*field); - } else if (field->number() == 2) { - if (map_key.empty()) { - // An absent map key is treated as the default. - const google::protobuf::Field* key_field = - FindFieldByNumber(*field_type, 1); - if (key_field == nullptr) { - // The Type info for this map entry is incorrect. It should always - // have a field named "key" and with field number 1. - return util::InternalError("Invalid map entry."); - } - ASSIGN_OR_RETURN(map_key, MapKeyDefaultValueAsString(*key_field)); - } - RETURN_IF_ERROR(RenderField(field, map_key, ow)); - } else { - // The Type info for this map entry is incorrect. It should contain - // exactly two fields with field number 1 and 2. - return util::InternalError("Invalid map entry."); - } - } - stream_->PopLimit(old_limit); - } while ((tag_to_return = stream_->ReadTag()) == list_tag); - return tag_to_return; -} - -util::Status ProtoStreamObjectSource::RenderPacked( - const google::protobuf::Field* field, ObjectWriter* ow) const { - uint32_t length; - stream_->ReadVarint32(&length); - int old_limit = stream_->PushLimit(length); - while (stream_->BytesUntilLimit() > 0) { - RETURN_IF_ERROR(RenderField(field, StringPiece(), ow)); - } - stream_->PopLimit(old_limit); - return util::Status(); -} - -util::Status ProtoStreamObjectSource::RenderTimestamp( - const ProtoStreamObjectSource* os, const google::protobuf::Type& type, - StringPiece field_name, ObjectWriter* ow) { - std::pair<int64_t, int32_t> p = os->ReadSecondsAndNanos(type); - int64_t seconds = p.first; - int32_t nanos = p.second; - if (seconds > kTimestampMaxSeconds || seconds < kTimestampMinSeconds) { - return util::InternalError(StrCat( - "Timestamp seconds exceeds limit for field: ", field_name)); - } - - if (nanos < 0 || nanos >= kNanosPerSecond) { - return util::InternalError( - StrCat("Timestamp nanos exceeds limit for field: ", field_name)); - } - - ow->RenderString(field_name, - ::google::protobuf::internal::FormatTime(seconds, nanos)); - - return util::Status(); -} - -util::Status ProtoStreamObjectSource::RenderDuration( - const ProtoStreamObjectSource* os, const google::protobuf::Type& type, - StringPiece field_name, ObjectWriter* ow) { - std::pair<int64_t, int32_t> p = os->ReadSecondsAndNanos(type); - int64_t seconds = p.first; - int32_t nanos = p.second; - if (seconds > kDurationMaxSeconds || seconds < kDurationMinSeconds) { - return util::InternalError( - StrCat("Duration seconds exceeds limit for field: ", field_name)); - } - - if (nanos <= -kNanosPerSecond || nanos >= kNanosPerSecond) { - return util::InternalError( - StrCat("Duration nanos exceeds limit for field: ", field_name)); - } - - std::string sign = ""; - if (seconds < 0) { - if (nanos > 0) { - return util::InternalError( - StrCat("Duration nanos is non-negative, but seconds is " - "negative for field: ", - field_name)); - } - sign = "-"; - seconds = -seconds; - nanos = -nanos; - } else if (seconds == 0 && nanos < 0) { - sign = "-"; - nanos = -nanos; - } - std::string formatted_duration = StringPrintf( - "%s%lld%ss", sign.c_str(), static_cast<long long>(seconds), // NOLINT - FormatNanos( - nanos, - false - ) - .c_str()); - ow->RenderString(field_name, formatted_duration); - return util::Status(); -} - -util::Status ProtoStreamObjectSource::RenderDouble( - const ProtoStreamObjectSource* os, const google::protobuf::Type& type, - StringPiece field_name, ObjectWriter* ow) { - uint32_t tag = os->stream_->ReadTag(); - uint64_t buffer64 = 0; // default value of Double wrapper value - if (tag != 0) { - os->stream_->ReadLittleEndian64(&buffer64); - os->stream_->ReadTag(); - } - ow->RenderDouble(field_name, bit_cast<double>(buffer64)); - return util::Status(); -} - -util::Status ProtoStreamObjectSource::RenderFloat( - const ProtoStreamObjectSource* os, const google::protobuf::Type& type, - StringPiece field_name, ObjectWriter* ow) { - uint32_t tag = os->stream_->ReadTag(); - uint32_t buffer32 = 0; // default value of Float wrapper value - if (tag != 0) { - os->stream_->ReadLittleEndian32(&buffer32); - os->stream_->ReadTag(); - } - ow->RenderFloat(field_name, bit_cast<float>(buffer32)); - return util::Status(); -} - -util::Status ProtoStreamObjectSource::RenderInt64( - const ProtoStreamObjectSource* os, const google::protobuf::Type& type, - StringPiece field_name, ObjectWriter* ow) { - uint32_t tag = os->stream_->ReadTag(); - uint64_t buffer64 = 0; // default value of Int64 wrapper value - if (tag != 0) { - os->stream_->ReadVarint64(&buffer64); - os->stream_->ReadTag(); - } - ow->RenderInt64(field_name, bit_cast<int64_t>(buffer64)); - return util::Status(); -} - -util::Status ProtoStreamObjectSource::RenderUInt64( - const ProtoStreamObjectSource* os, const google::protobuf::Type& type, - StringPiece field_name, ObjectWriter* ow) { - uint32_t tag = os->stream_->ReadTag(); - uint64_t buffer64 = 0; // default value of UInt64 wrapper value - if (tag != 0) { - os->stream_->ReadVarint64(&buffer64); - os->stream_->ReadTag(); - } - ow->RenderUint64(field_name, bit_cast<uint64_t>(buffer64)); - return util::Status(); -} - -util::Status ProtoStreamObjectSource::RenderInt32( - const ProtoStreamObjectSource* os, const google::protobuf::Type& type, - StringPiece field_name, ObjectWriter* ow) { - uint32_t tag = os->stream_->ReadTag(); - uint32_t buffer32 = 0; // default value of Int32 wrapper value - if (tag != 0) { - os->stream_->ReadVarint32(&buffer32); - os->stream_->ReadTag(); - } - ow->RenderInt32(field_name, bit_cast<int32_t>(buffer32)); - return util::Status(); -} - -util::Status ProtoStreamObjectSource::RenderUInt32( - const ProtoStreamObjectSource* os, const google::protobuf::Type& type, - StringPiece field_name, ObjectWriter* ow) { - uint32_t tag = os->stream_->ReadTag(); - uint32_t buffer32 = 0; // default value of UInt32 wrapper value - if (tag != 0) { - os->stream_->ReadVarint32(&buffer32); - os->stream_->ReadTag(); - } - ow->RenderUint32(field_name, bit_cast<uint32_t>(buffer32)); - return util::Status(); -} - -util::Status ProtoStreamObjectSource::RenderBool( - const ProtoStreamObjectSource* os, const google::protobuf::Type& type, - StringPiece field_name, ObjectWriter* ow) { - uint32_t tag = os->stream_->ReadTag(); - uint64_t buffer64 = 0; // results in 'false' value as default, which is the - // default value of Bool wrapper - if (tag != 0) { - os->stream_->ReadVarint64(&buffer64); - os->stream_->ReadTag(); - } - ow->RenderBool(field_name, buffer64 != 0); - return util::Status(); -} - -util::Status ProtoStreamObjectSource::RenderString( - const ProtoStreamObjectSource* os, const google::protobuf::Type& type, - StringPiece field_name, ObjectWriter* ow) { - uint32_t tag = os->stream_->ReadTag(); - uint32_t buffer32; - std::string str; // default value of empty for String wrapper - if (tag != 0) { - os->stream_->ReadVarint32(&buffer32); // string size. - os->stream_->ReadString(&str, buffer32); - os->stream_->ReadTag(); - } - ow->RenderString(field_name, str); - return util::Status(); -} - -util::Status ProtoStreamObjectSource::RenderBytes( - const ProtoStreamObjectSource* os, const google::protobuf::Type& type, - StringPiece field_name, ObjectWriter* ow) { - uint32_t tag = os->stream_->ReadTag(); - uint32_t buffer32; - std::string str; - if (tag != 0) { - os->stream_->ReadVarint32(&buffer32); - os->stream_->ReadString(&str, buffer32); - os->stream_->ReadTag(); - } - ow->RenderBytes(field_name, str); - return util::Status(); -} - -util::Status ProtoStreamObjectSource::RenderStruct( - const ProtoStreamObjectSource* os, const google::protobuf::Type& type, - StringPiece field_name, ObjectWriter* ow) { - const google::protobuf::Field* field = nullptr; - uint32_t tag = os->stream_->ReadTag(); - ow->StartObject(field_name); - while (tag != 0) { - field = os->FindAndVerifyField(type, tag); - if (field == nullptr) { - WireFormat::SkipField(os->stream_, tag, nullptr); - tag = os->stream_->ReadTag(); - continue; - } - // google.protobuf.Struct has only one field that is a map. Hence we use - // RenderMap to render that field. - if (os->IsMap(*field)) { - ASSIGN_OR_RETURN(tag, os->RenderMap(field, field_name, tag, ow)); - } - } - ow->EndObject(); - return util::Status(); -} - -util::Status ProtoStreamObjectSource::RenderStructValue( - const ProtoStreamObjectSource* os, const google::protobuf::Type& type, - StringPiece field_name, ObjectWriter* ow) { - const google::protobuf::Field* field = nullptr; - for (uint32_t tag = os->stream_->ReadTag(); tag != 0; - tag = os->stream_->ReadTag()) { - field = os->FindAndVerifyField(type, tag); - if (field == nullptr) { - WireFormat::SkipField(os->stream_, tag, nullptr); - continue; - } - RETURN_IF_ERROR(os->RenderField(field, field_name, ow)); - } - return util::Status(); -} - -// TODO(skarvaje): Avoid code duplication of for loops and SkipField logic. -util::Status ProtoStreamObjectSource::RenderStructListValue( - const ProtoStreamObjectSource* os, const google::protobuf::Type& type, - StringPiece field_name, ObjectWriter* ow) { - uint32_t tag = os->stream_->ReadTag(); - - // Render empty list when we find empty ListValue message. - if (tag == 0) { - ow->StartList(field_name); - ow->EndList(); - return util::Status(); - } - - while (tag != 0) { - const google::protobuf::Field* field = os->FindAndVerifyField(type, tag); - if (field == nullptr) { - WireFormat::SkipField(os->stream_, tag, nullptr); - tag = os->stream_->ReadTag(); - continue; - } - ASSIGN_OR_RETURN(tag, os->RenderList(field, field_name, tag, ow)); - } - return util::Status(); -} - -util::Status ProtoStreamObjectSource::RenderAny( - const ProtoStreamObjectSource* os, const google::protobuf::Type& type, - StringPiece field_name, ObjectWriter* ow) { - // An Any is of the form { string type_url = 1; bytes value = 2; } - uint32_t tag; - std::string type_url; - std::string value; - - // First read out the type_url and value from the proto stream - for (tag = os->stream_->ReadTag(); tag != 0; tag = os->stream_->ReadTag()) { - const google::protobuf::Field* field = os->FindAndVerifyField(type, tag); - if (field == nullptr) { - WireFormat::SkipField(os->stream_, tag, nullptr); - continue; - } - // 'type_url' has field number of 1 and 'value' has field number 2 - // //google/protobuf/any.proto - if (field->number() == 1) { - // read type_url - uint32_t type_url_size; - os->stream_->ReadVarint32(&type_url_size); - os->stream_->ReadString(&type_url, type_url_size); - } else if (field->number() == 2) { - // read value - uint32_t value_size; - os->stream_->ReadVarint32(&value_size); - os->stream_->ReadString(&value, value_size); - } - } - - // If there is no value, we don't lookup the type, we just output it (if - // present). If both type and value are empty we output an empty object. - if (value.empty()) { - ow->StartObject(field_name); - if (!type_url.empty()) { - ow->RenderString("@type", type_url); - } - ow->EndObject(); - return util::Status(); - } - - // If there is a value but no type, we cannot render it, so report an error. - if (type_url.empty()) { - // TODO(sven): Add an external message once those are ready. - return util::InternalError("Invalid Any, the type_url is missing."); - } - - util::StatusOr<const google::protobuf::Type*> resolved_type = - os->typeinfo_->ResolveTypeUrl(type_url); - - if (!resolved_type.ok()) { - // Convert into an internal error, since this means the backend gave us - // an invalid response (missing or invalid type information). - return util::InternalError(resolved_type.status().message()); - } - // nested_type cannot be null at this time. - const google::protobuf::Type* nested_type = resolved_type.value(); - - io::ArrayInputStream zero_copy_stream(value.data(), value.size()); - io::CodedInputStream in_stream(&zero_copy_stream); - // We know the type so we can render it. Recursively parse the nested stream - // using a nested ProtoStreamObjectSource using our nested type information. - ProtoStreamObjectSource nested_os(&in_stream, os->typeinfo_, *nested_type, - os->render_options_); - - // We manually call start and end object here so we can inject the @type. - ow->StartObject(field_name); - ow->RenderString("@type", type_url); - util::Status result = - nested_os.WriteMessage(nested_os.type_, "value", 0, false, ow); - ow->EndObject(); - return result; -} - -util::Status ProtoStreamObjectSource::RenderFieldMask( - const ProtoStreamObjectSource* os, const google::protobuf::Type& type, - StringPiece field_name, ObjectWriter* ow) { - std::string combined; - uint32_t buffer32; - uint32_t paths_field_tag = 0; - for (uint32_t tag = os->stream_->ReadTag(); tag != 0; - tag = os->stream_->ReadTag()) { - if (paths_field_tag == 0) { - const google::protobuf::Field* field = os->FindAndVerifyField(type, tag); - if (field != nullptr && field->number() == 1 && - field->name() == "paths") { - paths_field_tag = tag; - } - } - if (paths_field_tag != tag) { - return util::InternalError("Invalid FieldMask, unexpected field."); - } - std::string str; - os->stream_->ReadVarint32(&buffer32); // string size. - os->stream_->ReadString(&str, buffer32); - if (!combined.empty()) { - combined.append(","); - } - combined.append(ConvertFieldMaskPath(str, &ToCamelCase)); - } - ow->RenderString(field_name, combined); - return util::Status(); -} - - -std::unordered_map<std::string, ProtoStreamObjectSource::TypeRenderer>* - ProtoStreamObjectSource::renderers_ = nullptr; -PROTOBUF_NAMESPACE_ID::internal::once_flag source_renderers_init_; - - -void ProtoStreamObjectSource::InitRendererMap() { - renderers_ = new std::unordered_map<std::string, - ProtoStreamObjectSource::TypeRenderer>(); - (*renderers_)["google.protobuf.Timestamp"] = - &ProtoStreamObjectSource::RenderTimestamp; - (*renderers_)["google.protobuf.Duration"] = - &ProtoStreamObjectSource::RenderDuration; - (*renderers_)["google.protobuf.DoubleValue"] = - &ProtoStreamObjectSource::RenderDouble; - (*renderers_)["google.protobuf.FloatValue"] = - &ProtoStreamObjectSource::RenderFloat; - (*renderers_)["google.protobuf.Int64Value"] = - &ProtoStreamObjectSource::RenderInt64; - (*renderers_)["google.protobuf.UInt64Value"] = - &ProtoStreamObjectSource::RenderUInt64; - (*renderers_)["google.protobuf.Int32Value"] = - &ProtoStreamObjectSource::RenderInt32; - (*renderers_)["google.protobuf.UInt32Value"] = - &ProtoStreamObjectSource::RenderUInt32; - (*renderers_)["google.protobuf.BoolValue"] = - &ProtoStreamObjectSource::RenderBool; - (*renderers_)["google.protobuf.StringValue"] = - &ProtoStreamObjectSource::RenderString; - (*renderers_)["google.protobuf.BytesValue"] = - &ProtoStreamObjectSource::RenderBytes; - (*renderers_)["google.protobuf.Any"] = &ProtoStreamObjectSource::RenderAny; - (*renderers_)["google.protobuf.Struct"] = - &ProtoStreamObjectSource::RenderStruct; - (*renderers_)["google.protobuf.Value"] = - &ProtoStreamObjectSource::RenderStructValue; - (*renderers_)["google.protobuf.ListValue"] = - &ProtoStreamObjectSource::RenderStructListValue; - (*renderers_)["google.protobuf.FieldMask"] = - &ProtoStreamObjectSource::RenderFieldMask; - ::google::protobuf::internal::OnShutdown(&DeleteRendererMap); -} - -void ProtoStreamObjectSource::DeleteRendererMap() { - delete ProtoStreamObjectSource::renderers_; - renderers_ = nullptr; -} - -// static -ProtoStreamObjectSource::TypeRenderer* -ProtoStreamObjectSource::FindTypeRenderer(const std::string& type_url) { - PROTOBUF_NAMESPACE_ID::internal::call_once(source_renderers_init_, - InitRendererMap); - return FindOrNull(*renderers_, type_url); -} - -util::Status ProtoStreamObjectSource::RenderField( - const google::protobuf::Field* field, StringPiece field_name, - ObjectWriter* ow) const { - // Short-circuit message types as it tends to call WriteMessage recursively - // and ends up using a lot of stack space. Keep the stack usage of this - // message small in order to preserve stack space and not crash. - if (field->kind() == google::protobuf::Field::TYPE_MESSAGE) { - uint32_t buffer32; - stream_->ReadVarint32(&buffer32); // message length - int old_limit = stream_->PushLimit(buffer32); - // Get the nested message type for this field. - const google::protobuf::Type* type = - typeinfo_->GetTypeByTypeUrl(field->type_url()); - if (type == nullptr) { - return util::InternalError( - StrCat("Invalid configuration. Could not find the type: ", - field->type_url())); - } - - // Short-circuit any special type rendering to save call-stack space. - const TypeRenderer* type_renderer = FindTypeRenderer(type->name()); - - RETURN_IF_ERROR(IncrementRecursionDepth(type->name(), field_name)); - if (type_renderer != nullptr) { - RETURN_IF_ERROR((*type_renderer)(this, *type, field_name, ow)); - } else { - RETURN_IF_ERROR(WriteMessage(*type, field_name, 0, true, ow)); - } - --recursion_depth_; - - if (!stream_->ConsumedEntireMessage()) { - return util::InvalidArgumentError( - "Nested protocol message not parsed in its entirety."); - } - stream_->PopLimit(old_limit); - } else { - // Render all other non-message types. - return RenderNonMessageField(field, field_name, ow); - } - return util::Status(); -} - -util::Status ProtoStreamObjectSource::RenderNonMessageField( - const google::protobuf::Field* field, StringPiece field_name, - ObjectWriter* ow) const { - // Temporary buffers of different types. - uint32_t buffer32 = 0; - uint64_t buffer64 = 0; - std::string strbuffer; - switch (field->kind()) { - case google::protobuf::Field::TYPE_BOOL: { - stream_->ReadVarint64(&buffer64); - ow->RenderBool(field_name, buffer64 != 0); - break; - } - case google::protobuf::Field::TYPE_INT32: { - stream_->ReadVarint32(&buffer32); - ow->RenderInt32(field_name, bit_cast<int32_t>(buffer32)); - break; - } - case google::protobuf::Field::TYPE_INT64: { - stream_->ReadVarint64(&buffer64); - ow->RenderInt64(field_name, bit_cast<int64>(buffer64)); - break; - } - case google::protobuf::Field::TYPE_UINT32: { - stream_->ReadVarint32(&buffer32); - ow->RenderUint32(field_name, bit_cast<uint32_t>(buffer32)); - break; - } - case google::protobuf::Field::TYPE_UINT64: { - stream_->ReadVarint64(&buffer64); - ow->RenderUint64(field_name, bit_cast<uint64>(buffer64)); - break; - } - case google::protobuf::Field::TYPE_SINT32: { - stream_->ReadVarint32(&buffer32); - ow->RenderInt32(field_name, WireFormatLite::ZigZagDecode32(buffer32)); - break; - } - case google::protobuf::Field::TYPE_SINT64: { - stream_->ReadVarint64(&buffer64); - ow->RenderInt64(field_name, WireFormatLite::ZigZagDecode64(buffer64)); - break; - } - case google::protobuf::Field::TYPE_SFIXED32: { - stream_->ReadLittleEndian32(&buffer32); - ow->RenderInt32(field_name, bit_cast<int32_t>(buffer32)); - break; - } - case google::protobuf::Field::TYPE_SFIXED64: { - stream_->ReadLittleEndian64(&buffer64); - ow->RenderInt64(field_name, bit_cast<int64>(buffer64)); - break; - } - case google::protobuf::Field::TYPE_FIXED32: { - stream_->ReadLittleEndian32(&buffer32); - ow->RenderUint32(field_name, bit_cast<uint32_t>(buffer32)); - break; - } - case google::protobuf::Field::TYPE_FIXED64: { - stream_->ReadLittleEndian64(&buffer64); - ow->RenderUint64(field_name, bit_cast<uint64>(buffer64)); - break; - } - case google::protobuf::Field::TYPE_FLOAT: { - stream_->ReadLittleEndian32(&buffer32); - ow->RenderFloat(field_name, bit_cast<float>(buffer32)); - break; - } - case google::protobuf::Field::TYPE_DOUBLE: { - stream_->ReadLittleEndian64(&buffer64); - ow->RenderDouble(field_name, bit_cast<double>(buffer64)); - break; - } - case google::protobuf::Field::TYPE_ENUM: { - stream_->ReadVarint32(&buffer32); - - // If the field represents an explicit NULL value, render null. - if (field->type_url() == kStructNullValueTypeUrl) { - ow->RenderNull(field_name); - break; - } - - // Get the nested enum type for this field. - // TODO(skarvaje): Avoid string manipulation. Find ways to speed this - // up. - const google::protobuf::Enum* en = - typeinfo_->GetEnumByTypeUrl(field->type_url()); - // Lookup the name of the enum, and render that. Unknown enum values - // are printed as integers. - if (en != nullptr) { - const google::protobuf::EnumValue* enum_value = - FindEnumValueByNumber(*en, buffer32); - if (enum_value != nullptr) { - if (render_options_.use_ints_for_enums) { - ow->RenderInt32(field_name, buffer32); - } else if (render_options_.use_lower_camel_for_enums) { - ow->RenderString(field_name, - EnumValueNameToLowerCamelCase(enum_value->name())); - } else { - ow->RenderString(field_name, enum_value->name()); - } - } else { - ow->RenderInt32(field_name, buffer32); - } - } else { - ow->RenderInt32(field_name, buffer32); - } - break; - } - case google::protobuf::Field::TYPE_STRING: { - stream_->ReadVarint32(&buffer32); // string size. - stream_->ReadString(&strbuffer, buffer32); - ow->RenderString(field_name, strbuffer); - break; - } - case google::protobuf::Field::TYPE_BYTES: { - stream_->ReadVarint32(&buffer32); // bytes size. - stream_->ReadString(&strbuffer, buffer32); - ow->RenderBytes(field_name, strbuffer); - break; - } - default: - break; - } - return util::Status(); -} - -// TODO(skarvaje): Fix this to avoid code duplication. -const std::string ProtoStreamObjectSource::ReadFieldValueAsString( - const google::protobuf::Field& field) const { - std::string result; - switch (field.kind()) { - case google::protobuf::Field::TYPE_BOOL: { - uint64_t buffer64; - stream_->ReadVarint64(&buffer64); - result = buffer64 != 0 ? "true" : "false"; - break; - } - case google::protobuf::Field::TYPE_INT32: { - uint32_t buffer32; - stream_->ReadVarint32(&buffer32); - result = StrCat(bit_cast<int32_t>(buffer32)); - break; - } - case google::protobuf::Field::TYPE_INT64: { - uint64_t buffer64; - stream_->ReadVarint64(&buffer64); - result = StrCat(bit_cast<int64_t>(buffer64)); - break; - } - case google::protobuf::Field::TYPE_UINT32: { - uint32_t buffer32; - stream_->ReadVarint32(&buffer32); - result = StrCat(bit_cast<uint32_t>(buffer32)); - break; - } - case google::protobuf::Field::TYPE_UINT64: { - uint64_t buffer64; - stream_->ReadVarint64(&buffer64); - result = StrCat(bit_cast<uint64_t>(buffer64)); - break; - } - case google::protobuf::Field::TYPE_SINT32: { - uint32_t buffer32; - stream_->ReadVarint32(&buffer32); - result = StrCat(WireFormatLite::ZigZagDecode32(buffer32)); - break; - } - case google::protobuf::Field::TYPE_SINT64: { - uint64_t buffer64; - stream_->ReadVarint64(&buffer64); - result = StrCat(WireFormatLite::ZigZagDecode64(buffer64)); - break; - } - case google::protobuf::Field::TYPE_SFIXED32: { - uint32_t buffer32; - stream_->ReadLittleEndian32(&buffer32); - result = StrCat(bit_cast<int32_t>(buffer32)); - break; - } - case google::protobuf::Field::TYPE_SFIXED64: { - uint64_t buffer64; - stream_->ReadLittleEndian64(&buffer64); - result = StrCat(bit_cast<int64_t>(buffer64)); - break; - } - case google::protobuf::Field::TYPE_FIXED32: { - uint32_t buffer32; - stream_->ReadLittleEndian32(&buffer32); - result = StrCat(bit_cast<uint32_t>(buffer32)); - break; - } - case google::protobuf::Field::TYPE_FIXED64: { - uint64_t buffer64; - stream_->ReadLittleEndian64(&buffer64); - result = StrCat(bit_cast<uint64_t>(buffer64)); - break; - } - case google::protobuf::Field::TYPE_FLOAT: { - uint32_t buffer32; - stream_->ReadLittleEndian32(&buffer32); - result = SimpleFtoa(bit_cast<float>(buffer32)); - break; - } - case google::protobuf::Field::TYPE_DOUBLE: { - uint64_t buffer64; - stream_->ReadLittleEndian64(&buffer64); - result = SimpleDtoa(bit_cast<double>(buffer64)); - break; - } - case google::protobuf::Field::TYPE_ENUM: { - uint32_t buffer32; - stream_->ReadVarint32(&buffer32); - // Get the nested enum type for this field. - // TODO(skarvaje): Avoid string manipulation. Find ways to speed this - // up. - const google::protobuf::Enum* en = - typeinfo_->GetEnumByTypeUrl(field.type_url()); - // Lookup the name of the enum, and render that. Skips unknown enums. - if (en != nullptr) { - const google::protobuf::EnumValue* enum_value = - FindEnumValueByNumber(*en, buffer32); - if (enum_value != nullptr) { - result = enum_value->name(); - } - } - break; - } - case google::protobuf::Field::TYPE_STRING: { - uint32_t buffer32; - stream_->ReadVarint32(&buffer32); // string size. - stream_->ReadString(&result, buffer32); - break; - } - case google::protobuf::Field::TYPE_BYTES: { - uint32_t buffer32; - stream_->ReadVarint32(&buffer32); // bytes size. - stream_->ReadString(&result, buffer32); - break; - } - default: - break; - } - return result; -} - -// Field is a map if it is a repeated message and it has an option "map_type". -// TODO(skarvaje): Consider pre-computing the IsMap() into Field directly. -bool ProtoStreamObjectSource::IsMap( - const google::protobuf::Field& field) const { - const google::protobuf::Type* field_type = - typeinfo_->GetTypeByTypeUrl(field.type_url()); - return field.kind() == google::protobuf::Field::TYPE_MESSAGE && - util::converter::IsMap(field, *field_type); -} - -std::pair<int64_t, int32_t> ProtoStreamObjectSource::ReadSecondsAndNanos( - const google::protobuf::Type& type) const { - uint64_t seconds = 0; - uint32_t nanos = 0; - uint32_t tag = 0; - int64_t signed_seconds = 0; - int32_t signed_nanos = 0; - - for (tag = stream_->ReadTag(); tag != 0; tag = stream_->ReadTag()) { - const google::protobuf::Field* field = FindAndVerifyField(type, tag); - if (field == nullptr) { - WireFormat::SkipField(stream_, tag, nullptr); - continue; - } - // 'seconds' has field number of 1 and 'nanos' has field number 2 - // //google/protobuf/timestamp.proto & duration.proto - if (field->number() == 1) { - // read seconds - stream_->ReadVarint64(&seconds); - signed_seconds = bit_cast<int64_t>(seconds); - } else if (field->number() == 2) { - // read nanos - stream_->ReadVarint32(&nanos); - signed_nanos = bit_cast<int32_t>(nanos); - } - } - return std::pair<int64_t, int32_t>(signed_seconds, signed_nanos); -} - -util::Status ProtoStreamObjectSource::IncrementRecursionDepth( - StringPiece type_name, StringPiece field_name) const { - if (++recursion_depth_ > max_recursion_depth_) { - return util::InvalidArgumentError( - StrCat("Message too deep. Max recursion depth reached for type '", - type_name, "', field '", field_name, "'")); - } - return util::Status(); -} - -namespace { -// TODO(skarvaje): Speed this up by not doing a linear scan. -const google::protobuf::Field* FindFieldByNumber( - const google::protobuf::Type& type, int number) { - for (int i = 0; i < type.fields_size(); ++i) { - if (type.fields(i).number() == number) { - return &type.fields(i); - } - } - return nullptr; -} - -// TODO(skarvaje): Replace FieldDescriptor by implementing IsTypePackable() -// using tech Field. -bool IsPackable(const google::protobuf::Field& field) { - return field.cardinality() == google::protobuf::Field::CARDINALITY_REPEATED && - FieldDescriptor::IsTypePackable( - static_cast<FieldDescriptor::Type>(field.kind())); -} - -// TODO(skarvaje): Speed this up by not doing a linear scan. -const google::protobuf::EnumValue* FindEnumValueByNumber( - const google::protobuf::Enum& tech_enum, int number) { - for (int i = 0; i < tech_enum.enumvalue_size(); ++i) { - const google::protobuf::EnumValue& ev = tech_enum.enumvalue(i); - if (ev.number() == number) { - return &ev; - } - } - return nullptr; -} - -// TODO(skarvaje): Look into optimizing this by not doing computation on -// double. -const std::string FormatNanos(uint32_t nanos, bool with_trailing_zeros) { - if (nanos == 0) { - return with_trailing_zeros ? ".000" : ""; - } - - const char* format = (nanos % 1000 != 0) ? "%.9f" - : (nanos % 1000000 != 0) ? "%.6f" - : "%.3f"; - std::string formatted = - StringPrintf(format, static_cast<double>(nanos) / kNanosPerSecond); - // remove the leading 0 before decimal. - return formatted.substr(1); -} -} // namespace - -} // namespace converter -} // namespace util -} // namespace protobuf -} // namespace google diff --git a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/protostream_objectsource.h b/contrib/libs/protobuf_std/src/google/protobuf/util/internal/protostream_objectsource.h deleted file mode 100644 index 60eaf4e1d8..0000000000 --- a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/protostream_objectsource.h +++ /dev/null @@ -1,328 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTOSTREAM_OBJECTSOURCE_H__ -#define GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTOSTREAM_OBJECTSOURCE_H__ - -#include <cstdint> -#include <functional> -#include <string> -#include <unordered_map> - -#include <google/protobuf/stubs/status.h> - -#include <google/protobuf/stubs/common.h> -#include <google/protobuf/type.pb.h> -#include <google/protobuf/util/internal/type_info.h> -#include <google/protobuf/util/internal/object_source.h> -#include <google/protobuf/util/internal/object_writer.h> -#include <google/protobuf/util/type_resolver.h> -#include <google/protobuf/stubs/statusor.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/stubs/hash.h> -#include <google/protobuf/stubs/status.h> - - -#include <google/protobuf/port_def.inc> - -namespace google { -namespace protobuf { -namespace util { -namespace converter { - -class TypeInfo; - -// An ObjectSource that can parse a stream of bytes as a protocol buffer. -// Its WriteTo() method can be given an ObjectWriter. -// This implementation uses a google.protobuf.Type for tag and name lookup. -// The field names are converted into lower camel-case when writing to the -// ObjectWriter. -// -// Sample usage: (suppose input is: string proto) -// ArrayInputStream arr_stream(proto.data(), proto.size()); -// CodedInputStream in_stream(&arr_stream); -// ProtoStreamObjectSource os(&in_stream, /*ServiceTypeInfo*/ typeinfo, -// <your message google::protobuf::Type>); -// -// Status status = os.WriteTo(<some ObjectWriter>); -class PROTOBUF_EXPORT ProtoStreamObjectSource : public ObjectSource { - public: - - struct RenderOptions { - RenderOptions() = default; - RenderOptions(const RenderOptions&) = default; - - // Sets whether or not to use lowerCamelCase casing for enum values. If set - // to false, enum values are output without any case conversions. - // - // For example, if we have an enum: - // enum Type { - // ACTION_AND_ADVENTURE = 1; - // } - // Type type = 20; - // - // And this option is set to true. Then the rendered "type" field will have - // the string "actionAndAdventure". - // { - // ... - // "type": "actionAndAdventure", - // ... - // } - // - // If set to false, the rendered "type" field will have the string - // "ACTION_AND_ADVENTURE". - // { - // ... - // "type": "ACTION_AND_ADVENTURE", - // ... - // } - bool use_lower_camel_for_enums = false; - - // Sets whether to always output enums as ints, by default this is off, and - // enums are rendered as strings. - bool use_ints_for_enums = false; - - // Whether to preserve proto field names - bool preserve_proto_field_names = false; - - }; - - ProtoStreamObjectSource(io::CodedInputStream* stream, - TypeResolver* type_resolver, - const google::protobuf::Type& type) - : ProtoStreamObjectSource(stream, type_resolver, type, RenderOptions()) {} - ProtoStreamObjectSource(io::CodedInputStream* stream, - TypeResolver* type_resolver, - const google::protobuf::Type& type, - const RenderOptions& render_options); - - ~ProtoStreamObjectSource() override; - - util::Status NamedWriteTo(StringPiece name, - ObjectWriter* ow) const override; - - // Sets the max recursion depth of proto message to be deserialized. Proto - // messages over this depth will fail to be deserialized. - // Default value is 64. - void set_max_recursion_depth(int max_depth) { - max_recursion_depth_ = max_depth; - } - - protected: - // Writes a proto2 Message to the ObjectWriter. When the given end_tag is - // found this method will complete, allowing it to be used for parsing both - // nested messages (end with 0) and nested groups (end with group end tag). - // The include_start_and_end parameter allows this method to be called when - // already inside of an object, and skip calling StartObject and EndObject. - virtual util::Status WriteMessage(const google::protobuf::Type& type, - StringPiece name, - const uint32_t end_tag, - bool include_start_and_end, - ObjectWriter* ow) const; - - // Renders a repeating field (packed or unpacked). Returns the next tag after - // reading all sequential repeating elements. The caller should use this tag - // before reading more tags from the stream. - virtual util::StatusOr<uint32_t> RenderList( - const google::protobuf::Field* field, StringPiece name, - uint32_t list_tag, ObjectWriter* ow) const; - - // Looks up a field and verify its consistency with wire type in tag. - const google::protobuf::Field* FindAndVerifyField( - const google::protobuf::Type& type, uint32_t tag) const; - - // Renders a field value to the ObjectWriter. - virtual util::Status RenderField(const google::protobuf::Field* field, - StringPiece field_name, - ObjectWriter* ow) const; - - // Reads field value according to Field spec in 'field' and returns the read - // value as string. This only works for primitive datatypes (no message - // types). - const std::string ReadFieldValueAsString( - const google::protobuf::Field& field) const; - - - // Returns the input stream. - io::CodedInputStream* stream() const { return stream_; } - - private: - ProtoStreamObjectSource(io::CodedInputStream* stream, - const TypeInfo* typeinfo, - const google::protobuf::Type& type, - const RenderOptions& render_options); - // Function that renders a well known type with a modified behavior. - typedef util::Status (*TypeRenderer)(const ProtoStreamObjectSource*, - const google::protobuf::Type&, - StringPiece, ObjectWriter*); - - // TODO(skarvaje): Mark these methods as non-const as they modify internal - // state (stream_). - // - // Renders a NWP map. - // Returns the next tag after reading all map entries. The caller should use - // this tag before reading more tags from the stream. - util::StatusOr<uint32_t> RenderMap(const google::protobuf::Field* field, - StringPiece name, uint32_t list_tag, - ObjectWriter* ow) const; - - // Renders a packed repeating field. A packed field is stored as: - // {tag length item1 item2 item3} instead of the less efficient - // {tag item1 tag item2 tag item3}. - util::Status RenderPacked(const google::protobuf::Field* field, - ObjectWriter* ow) const; - - // Renders a google.protobuf.Timestamp value to ObjectWriter - static util::Status RenderTimestamp(const ProtoStreamObjectSource* os, - const google::protobuf::Type& type, - StringPiece name, ObjectWriter* ow); - - // Renders a google.protobuf.Duration value to ObjectWriter - static util::Status RenderDuration(const ProtoStreamObjectSource* os, - const google::protobuf::Type& type, - StringPiece name, ObjectWriter* ow); - - // Following RenderTYPE functions render well known types in - // google/protobuf/wrappers.proto corresponding to TYPE. - static util::Status RenderDouble(const ProtoStreamObjectSource* os, - const google::protobuf::Type& type, - StringPiece name, ObjectWriter* ow); - static util::Status RenderFloat(const ProtoStreamObjectSource* os, - const google::protobuf::Type& type, - StringPiece name, ObjectWriter* ow); - static util::Status RenderInt64(const ProtoStreamObjectSource* os, - const google::protobuf::Type& type, - StringPiece name, ObjectWriter* ow); - static util::Status RenderUInt64(const ProtoStreamObjectSource* os, - const google::protobuf::Type& type, - StringPiece name, ObjectWriter* ow); - static util::Status RenderInt32(const ProtoStreamObjectSource* os, - const google::protobuf::Type& type, - StringPiece name, ObjectWriter* ow); - static util::Status RenderUInt32(const ProtoStreamObjectSource* os, - const google::protobuf::Type& type, - StringPiece name, ObjectWriter* ow); - static util::Status RenderBool(const ProtoStreamObjectSource* os, - const google::protobuf::Type& type, - StringPiece name, ObjectWriter* ow); - static util::Status RenderString(const ProtoStreamObjectSource* os, - const google::protobuf::Type& type, - StringPiece name, ObjectWriter* ow); - static util::Status RenderBytes(const ProtoStreamObjectSource* os, - const google::protobuf::Type& type, - StringPiece name, ObjectWriter* ow); - - // Renders a google.protobuf.Struct to ObjectWriter. - static util::Status RenderStruct(const ProtoStreamObjectSource* os, - const google::protobuf::Type& type, - StringPiece name, ObjectWriter* ow); - - // Helper to render google.protobuf.Struct's Value fields to ObjectWriter. - static util::Status RenderStructValue(const ProtoStreamObjectSource* os, - const google::protobuf::Type& type, - StringPiece name, - ObjectWriter* ow); - - // Helper to render google.protobuf.Struct's ListValue fields to ObjectWriter. - static util::Status RenderStructListValue(const ProtoStreamObjectSource* os, - const google::protobuf::Type& type, - StringPiece name, - ObjectWriter* ow); - - // Render the "Any" type. - static util::Status RenderAny(const ProtoStreamObjectSource* os, - const google::protobuf::Type& type, - StringPiece name, ObjectWriter* ow); - - // Render the "FieldMask" type. - static util::Status RenderFieldMask(const ProtoStreamObjectSource* os, - const google::protobuf::Type& type, - StringPiece name, ObjectWriter* ow); - - static std::unordered_map<std::string, TypeRenderer>* renderers_; - static void InitRendererMap(); - static void DeleteRendererMap(); - static TypeRenderer* FindTypeRenderer(const std::string& type_url); - - // Same as above but renders all non-message field types. Callers don't call - // this function directly. They just use RenderField. - util::Status RenderNonMessageField(const google::protobuf::Field* field, - StringPiece field_name, - ObjectWriter* ow) const; - - - // Utility function to detect proto maps. The 'field' MUST be repeated. - bool IsMap(const google::protobuf::Field& field) const; - - // Utility to read int64 and int32 values from a message type in stream_. - // Used for reading google.protobuf.Timestamp and Duration messages. - std::pair<int64_t, int32_t> ReadSecondsAndNanos( - const google::protobuf::Type& type) const; - - // Helper function to check recursion depth and increment it. It will return - // OkStatus() if the current depth is allowed. Otherwise an error is returned. - // type_name and field_name are used for error reporting. - util::Status IncrementRecursionDepth(StringPiece type_name, - StringPiece field_name) const; - - // Input stream to read from. Ownership rests with the caller. - mutable io::CodedInputStream* stream_; - - // Type information for all the types used in the descriptor. Used to find - // google::protobuf::Type of nested messages/enums. - const TypeInfo* typeinfo_; - - // Whether this class owns the typeinfo_ object. If true the typeinfo_ object - // should be deleted in the destructor. - bool own_typeinfo_; - - // google::protobuf::Type of the message source. - const google::protobuf::Type& type_; - - - const RenderOptions render_options_; - - // Tracks current recursion depth. - mutable int recursion_depth_; - - // Maximum allowed recursion depth. - int max_recursion_depth_; - - GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(ProtoStreamObjectSource); -}; - -} // namespace converter -} // namespace util -} // namespace protobuf -} // namespace google - -#include <google/protobuf/port_undef.inc> - -#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTOSTREAM_OBJECTSOURCE_H__ diff --git a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/protostream_objectwriter.cc b/contrib/libs/protobuf_std/src/google/protobuf/util/internal/protostream_objectwriter.cc deleted file mode 100644 index ec9a2cedea..0000000000 --- a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/protostream_objectwriter.cc +++ /dev/null @@ -1,1400 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include <google/protobuf/util/internal/protostream_objectwriter.h> - -#include <cstdint> -#include <functional> -#include <stack> -#include <unordered_map> -#include <unordered_set> - -#include <google/protobuf/stubs/once.h> -#include <google/protobuf/wire_format_lite.h> -#include <google/protobuf/util/internal/field_mask_utility.h> -#include <google/protobuf/util/internal/object_location_tracker.h> -#include <google/protobuf/util/internal/constants.h> -#include <google/protobuf/util/internal/utility.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/stubs/status.h> -#include <google/protobuf/stubs/statusor.h> -#include <google/protobuf/stubs/time.h> -#include <google/protobuf/stubs/map_util.h> - - -#include <google/protobuf/port_def.inc> - -namespace google { -namespace protobuf { -namespace util { -namespace converter { - -using ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite; -using std::placeholders::_1; -using util::Status; - - -ProtoStreamObjectWriter::ProtoStreamObjectWriter( - TypeResolver* type_resolver, const google::protobuf::Type& type, - strings::ByteSink* output, ErrorListener* listener, - const ProtoStreamObjectWriter::Options& options) - : ProtoWriter(type_resolver, type, output, listener), - master_type_(type), - current_(nullptr), - options_(options) { - set_ignore_unknown_fields(options_.ignore_unknown_fields); - set_ignore_unknown_enum_values(options_.ignore_unknown_enum_values); - set_use_lower_camel_for_enums(options_.use_lower_camel_for_enums); - set_case_insensitive_enum_parsing(options_.case_insensitive_enum_parsing); - set_use_json_name_in_missing_fields(options.use_json_name_in_missing_fields); -} - -ProtoStreamObjectWriter::ProtoStreamObjectWriter( - const TypeInfo* typeinfo, const google::protobuf::Type& type, - strings::ByteSink* output, ErrorListener* listener, - const ProtoStreamObjectWriter::Options& options) - : ProtoWriter(typeinfo, type, output, listener), - master_type_(type), - current_(nullptr), - options_(options) { - set_ignore_unknown_fields(options_.ignore_unknown_fields); - set_use_lower_camel_for_enums(options.use_lower_camel_for_enums); - set_case_insensitive_enum_parsing(options_.case_insensitive_enum_parsing); - set_use_json_name_in_missing_fields(options.use_json_name_in_missing_fields); -} - -ProtoStreamObjectWriter::ProtoStreamObjectWriter( - const TypeInfo* typeinfo, const google::protobuf::Type& type, - strings::ByteSink* output, ErrorListener* listener) - : ProtoWriter(typeinfo, type, output, listener), - master_type_(type), - current_(nullptr), - options_(ProtoStreamObjectWriter::Options::Defaults()) {} - -ProtoStreamObjectWriter::~ProtoStreamObjectWriter() { - if (current_ == nullptr) return; - // Cleanup explicitly in order to avoid destructor stack overflow when input - // is deeply nested. - // Cast to BaseElement to avoid doing additional checks (like missing fields) - // during pop(). - std::unique_ptr<BaseElement> element( - static_cast<BaseElement*>(current_.get())->pop<BaseElement>()); - while (element != nullptr) { - element.reset(element->pop<BaseElement>()); - } -} - -namespace { -// Utility method to split a string representation of Timestamp or Duration and -// return the parts. -void SplitSecondsAndNanos(StringPiece input, StringPiece* seconds, - StringPiece* nanos) { - size_t idx = input.rfind('.'); - if (idx != std::string::npos) { - *seconds = input.substr(0, idx); - *nanos = input.substr(idx + 1); - } else { - *seconds = input; - *nanos = StringPiece(); - } -} - -Status GetNanosFromStringPiece(StringPiece s_nanos, - const char* parse_failure_message, - const char* exceeded_limit_message, - int32_t* nanos) { - *nanos = 0; - - // Count the number of leading 0s and consume them. - int num_leading_zeros = 0; - while (s_nanos.Consume("0")) { - num_leading_zeros++; - } - int32_t i_nanos = 0; - // 's_nanos' contains fractional seconds -- i.e. 'nanos' is equal to - // "0." + s_nanos.ToString() seconds. An int32 is used for the - // conversion to 'nanos', rather than a double, so that there is no - // loss of precision. - if (!s_nanos.empty() && !safe_strto32(s_nanos, &i_nanos)) { - return util::InvalidArgumentError(parse_failure_message); - } - if (i_nanos > kNanosPerSecond || i_nanos < 0) { - return util::InvalidArgumentError(exceeded_limit_message); - } - // s_nanos should only have digits. No whitespace. - if (s_nanos.find_first_not_of("0123456789") != StringPiece::npos) { - return util::InvalidArgumentError(parse_failure_message); - } - - if (i_nanos > 0) { - // 'scale' is the number of digits to the right of the decimal - // point in "0." + s_nanos.ToString() - int32_t scale = num_leading_zeros + s_nanos.size(); - // 'conversion' converts i_nanos into nanoseconds. - // conversion = kNanosPerSecond / static_cast<int32>(std::pow(10, scale)) - // For efficiency, we precompute the conversion factor. - int32_t conversion = 0; - switch (scale) { - case 1: - conversion = 100000000; - break; - case 2: - conversion = 10000000; - break; - case 3: - conversion = 1000000; - break; - case 4: - conversion = 100000; - break; - case 5: - conversion = 10000; - break; - case 6: - conversion = 1000; - break; - case 7: - conversion = 100; - break; - case 8: - conversion = 10; - break; - case 9: - conversion = 1; - break; - default: - return util::InvalidArgumentError(exceeded_limit_message); - } - *nanos = i_nanos * conversion; - } - - return Status(); -} - -} // namespace - -ProtoStreamObjectWriter::AnyWriter::AnyWriter(ProtoStreamObjectWriter* parent) - : parent_(parent), - ow_(), - invalid_(false), - data_(), - output_(&data_), - depth_(0), - is_well_known_type_(false), - well_known_type_render_(nullptr) {} - -ProtoStreamObjectWriter::AnyWriter::~AnyWriter() {} - -void ProtoStreamObjectWriter::AnyWriter::StartObject(StringPiece name) { - ++depth_; - // If an object writer is absent, that means we have not called StartAny() - // before reaching here, which happens when we have data before the "@type" - // field. - if (ow_ == nullptr) { - // Save data before the "@type" field for later replay. - uninterpreted_events_.push_back(Event(Event::START_OBJECT, name)); - } else if (is_well_known_type_ && depth_ == 1) { - // For well-known types, the only other field besides "@type" should be a - // "value" field. - if (name != "value" && !invalid_) { - parent_->InvalidValue("Any", - "Expect a \"value\" field for well-known types."); - invalid_ = true; - } - ow_->StartObject(""); - } else { - // Forward the call to the child writer if: - // 1. the type is not a well-known type. - // 2. or, we are in a nested Any, Struct, or Value object. - ow_->StartObject(name); - } -} - -bool ProtoStreamObjectWriter::AnyWriter::EndObject() { - --depth_; - if (ow_ == nullptr) { - if (depth_ >= 0) { - // Save data before the "@type" field for later replay. - uninterpreted_events_.push_back(Event(Event::END_OBJECT)); - } - } else if (depth_ >= 0 || !is_well_known_type_) { - // As long as depth_ >= 0, we know we haven't reached the end of Any. - // Propagate these EndObject() calls to the contained ow_. For regular - // message types, we propagate the end of Any as well. - ow_->EndObject(); - } - // A negative depth_ implies that we have reached the end of Any - // object. Now we write out its contents. - if (depth_ < 0) { - WriteAny(); - return false; - } - return true; -} - -void ProtoStreamObjectWriter::AnyWriter::StartList(StringPiece name) { - ++depth_; - if (ow_ == nullptr) { - // Save data before the "@type" field for later replay. - uninterpreted_events_.push_back(Event(Event::START_LIST, name)); - } else if (is_well_known_type_ && depth_ == 1) { - if (name != "value" && !invalid_) { - parent_->InvalidValue("Any", - "Expect a \"value\" field for well-known types."); - invalid_ = true; - } - ow_->StartList(""); - } else { - ow_->StartList(name); - } -} - -void ProtoStreamObjectWriter::AnyWriter::EndList() { - --depth_; - if (depth_ < 0) { - GOOGLE_LOG(DFATAL) << "Mismatched EndList found, should not be possible"; - depth_ = 0; - } - if (ow_ == nullptr) { - // Save data before the "@type" field for later replay. - uninterpreted_events_.push_back(Event(Event::END_LIST)); - } else { - ow_->EndList(); - } -} - -void ProtoStreamObjectWriter::AnyWriter::RenderDataPiece( - StringPiece name, const DataPiece& value) { - // Start an Any only at depth_ 0. Other RenderDataPiece calls with "@type" - // should go to the contained ow_ as they indicate nested Anys. - if (depth_ == 0 && ow_ == nullptr && name == "@type") { - StartAny(value); - } else if (ow_ == nullptr) { - // Save data before the "@type" field. - uninterpreted_events_.push_back(Event(name, value)); - } else if (depth_ == 0 && is_well_known_type_) { - if (name != "value" && !invalid_) { - parent_->InvalidValue("Any", - "Expect a \"value\" field for well-known types."); - invalid_ = true; - } - if (well_known_type_render_ == nullptr) { - // Only Any and Struct don't have a special type render but both of - // them expect a JSON object (i.e., a StartObject() call). - if (value.type() != DataPiece::TYPE_NULL && !invalid_) { - parent_->InvalidValue("Any", "Expect a JSON object."); - invalid_ = true; - } - } else { - ow_->ProtoWriter::StartObject(""); - Status status = (*well_known_type_render_)(ow_.get(), value); - if (!status.ok()) ow_->InvalidValue("Any", status.message()); - ow_->ProtoWriter::EndObject(); - } - } else { - ow_->RenderDataPiece(name, value); - } -} - -void ProtoStreamObjectWriter::AnyWriter::StartAny(const DataPiece& value) { - // Figure out the type url. This is a copy-paste from WriteString but we also - // need the value, so we can't just call through to that. - if (value.type() == DataPiece::TYPE_STRING) { - type_url_ = std::string(value.str()); - } else { - util::StatusOr<std::string> s = value.ToString(); - if (!s.ok()) { - parent_->InvalidValue("String", s.status().message()); - invalid_ = true; - return; - } - type_url_ = s.value(); - } - // Resolve the type url, and report an error if we failed to resolve it. - util::StatusOr<const google::protobuf::Type*> resolved_type = - parent_->typeinfo()->ResolveTypeUrl(type_url_); - if (!resolved_type.ok()) { - parent_->InvalidValue("Any", resolved_type.status().message()); - invalid_ = true; - return; - } - // At this point, type is never null. - const google::protobuf::Type* type = resolved_type.value(); - - well_known_type_render_ = FindTypeRenderer(type_url_); - if (well_known_type_render_ != nullptr || - // Explicitly list Any and Struct here because they don't have a - // custom renderer. - type->name() == kAnyType || type->name() == kStructType) { - is_well_known_type_ = true; - } - - // Create our object writer and initialize it with the first StartObject - // call. - ow_.reset(new ProtoStreamObjectWriter(parent_->typeinfo(), *type, &output_, - parent_->listener(), - parent_->options_)); - - // Don't call StartObject() for well-known types yet. Depending on the - // type of actual data, we may not need to call StartObject(). For - // example: - // { - // "@type": "type.googleapis.com/google.protobuf.Value", - // "value": [1, 2, 3], - // } - // With the above JSON representation, we will only call StartList() on the - // contained ow_. - if (!is_well_known_type_) { - ow_->StartObject(""); - } - - // Now we know the proto type and can interpret all data fields we gathered - // before the "@type" field. - for (int i = 0; i < uninterpreted_events_.size(); ++i) { - uninterpreted_events_[i].Replay(this); - } -} - -void ProtoStreamObjectWriter::AnyWriter::WriteAny() { - if (ow_ == nullptr) { - if (uninterpreted_events_.empty()) { - // We never got any content, so just return immediately, which is - // equivalent to writing an empty Any. - return; - } else { - // There are uninterpreted data, but we never got a "@type" field. - if (!invalid_) { - parent_->InvalidValue("Any", - StrCat("Missing @type for any field in ", - parent_->master_type_.name())); - invalid_ = true; - } - return; - } - } - // Render the type_url and value fields directly to the stream. - // type_url has tag 1 and value has tag 2. - WireFormatLite::WriteString(1, type_url_, parent_->stream()); - if (!data_.empty()) { - WireFormatLite::WriteBytes(2, data_, parent_->stream()); - } -} - -void ProtoStreamObjectWriter::AnyWriter::Event::Replay( - AnyWriter* writer) const { - switch (type_) { - case START_OBJECT: - writer->StartObject(name_); - break; - case END_OBJECT: - writer->EndObject(); - break; - case START_LIST: - writer->StartList(name_); - break; - case END_LIST: - writer->EndList(); - break; - case RENDER_DATA_PIECE: - writer->RenderDataPiece(name_, value_); - break; - } -} - -void ProtoStreamObjectWriter::AnyWriter::Event::DeepCopy() { - // DataPiece only contains a string reference. To make sure the referenced - // string value stays valid, we make a copy of the string value and update - // DataPiece to reference our own copy. - if (value_.type() == DataPiece::TYPE_STRING) { - StrAppend(&value_storage_, value_.str()); - value_ = DataPiece(value_storage_, value_.use_strict_base64_decoding()); - } else if (value_.type() == DataPiece::TYPE_BYTES) { - value_storage_ = value_.ToBytes().value(); - value_ = - DataPiece(value_storage_, true, value_.use_strict_base64_decoding()); - } -} - -ProtoStreamObjectWriter::Item::Item(ProtoStreamObjectWriter* enclosing, - ItemType item_type, bool is_placeholder, - bool is_list) - : BaseElement(nullptr), - ow_(enclosing), - any_(), - item_type_(item_type), - is_placeholder_(is_placeholder), - is_list_(is_list) { - if (item_type_ == ANY) { - any_.reset(new AnyWriter(ow_)); - } - if (item_type == MAP) { - map_keys_.reset(new std::unordered_set<std::string>); - } -} - -ProtoStreamObjectWriter::Item::Item(ProtoStreamObjectWriter::Item* parent, - ItemType item_type, bool is_placeholder, - bool is_list) - : BaseElement(parent), - ow_(this->parent()->ow_), - any_(), - item_type_(item_type), - is_placeholder_(is_placeholder), - is_list_(is_list) { - if (item_type == ANY) { - any_.reset(new AnyWriter(ow_)); - } - if (item_type == MAP) { - map_keys_.reset(new std::unordered_set<std::string>); - } -} - -bool ProtoStreamObjectWriter::Item::InsertMapKeyIfNotPresent( - StringPiece map_key) { - return InsertIfNotPresent(map_keys_.get(), std::string(map_key)); -} - - -ProtoStreamObjectWriter* ProtoStreamObjectWriter::StartObject( - StringPiece name) { - if (invalid_depth() > 0) { - IncrementInvalidDepth(); - return this; - } - - // Starting the root message. Create the root Item and return. - // ANY message type does not need special handling, just set the ItemType - // to ANY. - if (current_ == nullptr) { - ProtoWriter::StartObject(name); - current_.reset(new Item( - this, master_type_.name() == kAnyType ? Item::ANY : Item::MESSAGE, - false, false)); - - // If master type is a special type that needs extra values to be written to - // stream, we write those values. - if (master_type_.name() == kStructType) { - // Struct has a map<string, Value> field called "fields". - // https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/struct.proto - // "fields": [ - Push("fields", Item::MAP, true, true); - return this; - } - - if (master_type_.name() == kStructValueType) { - // We got a StartObject call with google.protobuf.Value field. The only - // object within that type is a struct type. So start a struct. - // - // The struct field in Value type is named "struct_value" - // https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/struct.proto - // Also start the map field "fields" within the struct. - // "struct_value": { - // "fields": [ - Push("struct_value", Item::MESSAGE, true, false); - Push("fields", Item::MAP, true, true); - return this; - } - - if (master_type_.name() == kStructListValueType) { - InvalidValue(kStructListValueType, - "Cannot start root message with ListValue."); - } - - return this; - } - - // Send all ANY events to AnyWriter. - if (current_->IsAny()) { - current_->any()->StartObject(name); - return this; - } - - // If we are within a map, we render name as keys and send StartObject to the - // value field. - if (current_->IsMap()) { - if (!ValidMapKey(name)) { - IncrementInvalidDepth(); - return this; - } - - // Map is a repeated field of message type with a "key" and a "value" field. - // https://developers.google.com/protocol-buffers/docs/proto3?hl=en#maps - // message MapFieldEntry { - // key_type key = 1; - // value_type value = 2; - // } - // - // repeated MapFieldEntry map_field = N; - // - // That means, we render the following element within a list (hence no - // name): - // { "key": "<name>", "value": { - Push("", Item::MESSAGE, false, false); - ProtoWriter::RenderDataPiece("key", - DataPiece(name, use_strict_base64_decoding())); - Push("value", IsAny(*Lookup("value")) ? Item::ANY : Item::MESSAGE, true, - false); - - // Make sure we are valid so far after starting map fields. - if (invalid_depth() > 0) return this; - - // If top of stack is g.p.Struct type, start the struct the map field within - // it. - if (element() != nullptr && IsStruct(*element()->parent_field())) { - // Render "fields": [ - Push("fields", Item::MAP, true, true); - return this; - } - - // If top of stack is g.p.Value type, start the Struct within it. - if (element() != nullptr && IsStructValue(*element()->parent_field())) { - // Render - // "struct_value": { - // "fields": [ - Push("struct_value", Item::MESSAGE, true, false); - Push("fields", Item::MAP, true, true); - } - return this; - } - - const google::protobuf::Field* field = BeginNamed(name, false); - - if (field == nullptr) return this; - - // Legacy JSON map is a list of key value pairs. Starts a map entry object. - if (options_.use_legacy_json_map_format && name.empty()) { - Push(name, IsAny(*field) ? Item::ANY : Item::MESSAGE, false, false); - return this; - } - - if (IsMap(*field)) { - // Begin a map. A map is triggered by a StartObject() call if the current - // field has a map type. - // A map type is always repeated, hence set is_list to true. - // Render - // "<name>": [ - Push(name, Item::MAP, false, true); - return this; - } - - if (options_.disable_implicit_message_list) { - // If the incoming object is repeated, the top-level object on stack should - // be list. Report an error otherwise. - if (IsRepeated(*field) && !current_->is_list()) { - IncrementInvalidDepth(); - - if (!options_.suppress_implicit_message_list_error) { - InvalidValue( - field->name(), - "Starting an object in a repeated field but the parent object " - "is not a list"); - } - return this; - } - } - - if (IsStruct(*field)) { - // Start a struct object. - // Render - // "<name>": { - // "fields": { - Push(name, Item::MESSAGE, false, false); - Push("fields", Item::MAP, true, true); - return this; - } - - if (IsStructValue(*field)) { - // We got a StartObject call with google.protobuf.Value field. The only - // object within that type is a struct type. So start a struct. - // Render - // "<name>": { - // "struct_value": { - // "fields": { - Push(name, Item::MESSAGE, false, false); - Push("struct_value", Item::MESSAGE, true, false); - Push("fields", Item::MAP, true, true); - return this; - } - - if (field->kind() != google::protobuf::Field::TYPE_GROUP && - field->kind() != google::protobuf::Field::TYPE_MESSAGE) { - IncrementInvalidDepth(); - if (!options_.suppress_object_to_scalar_error) { - InvalidValue(field->name(), "Starting an object on a scalar field"); - } - - return this; - } - - // A regular message type. Pass it directly to ProtoWriter. - // Render - // "<name>": { - Push(name, IsAny(*field) ? Item::ANY : Item::MESSAGE, false, false); - return this; -} - -ProtoStreamObjectWriter* ProtoStreamObjectWriter::EndObject() { - if (invalid_depth() > 0) { - DecrementInvalidDepth(); - return this; - } - - if (current_ == nullptr) return this; - - if (current_->IsAny()) { - if (current_->any()->EndObject()) return this; - } - - Pop(); - - return this; -} - - -ProtoStreamObjectWriter* ProtoStreamObjectWriter::StartList( - StringPiece name) { - if (invalid_depth() > 0) { - IncrementInvalidDepth(); - return this; - } - - // Since we cannot have a top-level repeated item in protobuf, the only way - // this is valid is if we start a special type google.protobuf.ListValue or - // google.protobuf.Value. - if (current_ == nullptr) { - if (!name.empty()) { - InvalidName(name, "Root element should not be named."); - IncrementInvalidDepth(); - return this; - } - - // If master type is a special type that needs extra values to be written to - // stream, we write those values. - if (master_type_.name() == kStructValueType) { - // We got a StartList with google.protobuf.Value master type. This means - // we have to start the "list_value" within google.protobuf.Value. - // - // See - // https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/struct.proto - // - // Render - // "<name>": { - // "list_value": { - // "values": [ // Start this list. - ProtoWriter::StartObject(name); - current_.reset(new Item(this, Item::MESSAGE, false, false)); - Push("list_value", Item::MESSAGE, true, false); - Push("values", Item::MESSAGE, true, true); - return this; - } - - if (master_type_.name() == kStructListValueType) { - // We got a StartList with google.protobuf.ListValue master type. This - // means we have to start the "values" within google.protobuf.ListValue. - // - // Render - // "<name>": { - // "values": [ // Start this list. - ProtoWriter::StartObject(name); - current_.reset(new Item(this, Item::MESSAGE, false, false)); - Push("values", Item::MESSAGE, true, true); - return this; - } - - // Send the event to ProtoWriter so proper errors can be reported. - // - // Render a regular list: - // "<name>": [ - ProtoWriter::StartList(name); - current_.reset(new Item(this, Item::MESSAGE, false, true)); - return this; - } - - if (current_->IsAny()) { - current_->any()->StartList(name); - return this; - } - - // If the top of stack is a map, we are starting a list value within a map. - // Since map does not allow repeated values, this can only happen when the map - // value is of a special type that renders a list in JSON. These can be one - // of 3 cases: - // i. We are rendering a list value within google.protobuf.Struct - // ii. We are rendering a list value within google.protobuf.Value - // iii. We are rendering a list value with type google.protobuf.ListValue. - if (current_->IsMap()) { - if (!ValidMapKey(name)) { - IncrementInvalidDepth(); - return this; - } - - // Start the repeated map entry object. - // Render - // { "key": "<name>", "value": { - Push("", Item::MESSAGE, false, false); - ProtoWriter::RenderDataPiece("key", - DataPiece(name, use_strict_base64_decoding())); - Push("value", Item::MESSAGE, true, false); - - // Make sure we are valid after pushing all above items. - if (invalid_depth() > 0) return this; - - // case i and ii above. Start "list_value" field within g.p.Value - if (element() != nullptr && element()->parent_field() != nullptr) { - // Render - // "list_value": { - // "values": [ // Start this list - if (IsStructValue(*element()->parent_field())) { - Push("list_value", Item::MESSAGE, true, false); - Push("values", Item::MESSAGE, true, true); - return this; - } - - // Render - // "values": [ - if (IsStructListValue(*element()->parent_field())) { - // case iii above. Bind directly to g.p.ListValue - Push("values", Item::MESSAGE, true, true); - return this; - } - } - - // Report an error. - InvalidValue("Map", StrCat("Cannot have repeated items ('", name, - "') within a map.")); - return this; - } - - // When name is empty and stack is not empty, we are rendering an item within - // a list. - if (name.empty()) { - if (element() != nullptr && element()->parent_field() != nullptr) { - if (IsStructValue(*element()->parent_field())) { - // Since it is g.p.Value, we bind directly to the list_value. - // Render - // { // g.p.Value item within the list - // "list_value": { - // "values": [ - Push("", Item::MESSAGE, false, false); - Push("list_value", Item::MESSAGE, true, false); - Push("values", Item::MESSAGE, true, true); - return this; - } - - if (IsStructListValue(*element()->parent_field())) { - // Since it is g.p.ListValue, we bind to it directly. - // Render - // { // g.p.ListValue item within the list - // "values": [ - Push("", Item::MESSAGE, false, false); - Push("values", Item::MESSAGE, true, true); - return this; - } - } - - // Pass the event to underlying ProtoWriter. - Push(name, Item::MESSAGE, false, true); - return this; - } - - // name is not empty - const google::protobuf::Field* field = Lookup(name); - - if (field == nullptr) { - IncrementInvalidDepth(); - return this; - } - - if (IsStructValue(*field)) { - // If g.p.Value is repeated, start that list. Otherwise, start the - // "list_value" within it. - if (IsRepeated(*field)) { - // Render it just like a regular repeated field. - // "<name>": [ - Push(name, Item::MESSAGE, false, true); - return this; - } - - // Start the "list_value" field. - // Render - // "<name>": { - // "list_value": { - // "values": [ - Push(name, Item::MESSAGE, false, false); - Push("list_value", Item::MESSAGE, true, false); - Push("values", Item::MESSAGE, true, true); - return this; - } - - if (IsStructListValue(*field)) { - // If g.p.ListValue is repeated, start that list. Otherwise, start the - // "values" within it. - if (IsRepeated(*field)) { - // Render it just like a regular repeated field. - // "<name>": [ - Push(name, Item::MESSAGE, false, true); - return this; - } - - // Start the "values" field within g.p.ListValue. - // Render - // "<name>": { - // "values": [ - Push(name, Item::MESSAGE, false, false); - Push("values", Item::MESSAGE, true, true); - return this; - } - - // If we are here, the field should be repeated. Report an error otherwise. - if (!IsRepeated(*field)) { - IncrementInvalidDepth(); - InvalidName(name, "Proto field is not repeating, cannot start list."); - return this; - } - - if (IsMap(*field)) { - if (options_.use_legacy_json_map_format) { - Push(name, Item::MESSAGE, false, true); - return this; - } - InvalidValue("Map", StrCat("Cannot bind a list to map for field '", - name, "'.")); - IncrementInvalidDepth(); - return this; - } - - // Pass the event to ProtoWriter. - // Render - // "<name>": [ - Push(name, Item::MESSAGE, false, true); - return this; -} - -ProtoStreamObjectWriter* ProtoStreamObjectWriter::EndList() { - if (invalid_depth() > 0) { - DecrementInvalidDepth(); - return this; - } - - if (current_ == nullptr) return this; - - if (current_->IsAny()) { - current_->any()->EndList(); - return this; - } - - Pop(); - return this; -} - -Status ProtoStreamObjectWriter::RenderStructValue(ProtoStreamObjectWriter* ow, - const DataPiece& data) { - std::string struct_field_name; - switch (data.type()) { - case DataPiece::TYPE_INT32: { - if (ow->options_.struct_integers_as_strings) { - util::StatusOr<int32_t> int_value = data.ToInt32(); - if (int_value.ok()) { - ow->ProtoWriter::RenderDataPiece( - "string_value", - DataPiece(SimpleDtoa(int_value.value()), true)); - return Status(); - } - } - struct_field_name = "number_value"; - break; - } - case DataPiece::TYPE_UINT32: { - if (ow->options_.struct_integers_as_strings) { - util::StatusOr<uint32_t> int_value = data.ToUint32(); - if (int_value.ok()) { - ow->ProtoWriter::RenderDataPiece( - "string_value", - DataPiece(SimpleDtoa(int_value.value()), true)); - return Status(); - } - } - struct_field_name = "number_value"; - break; - } - case DataPiece::TYPE_INT64: { - // If the option to treat integers as strings is set, then render them as - // strings. Otherwise, fallback to rendering them as double. - if (ow->options_.struct_integers_as_strings) { - util::StatusOr<int64_t> int_value = data.ToInt64(); - if (int_value.ok()) { - ow->ProtoWriter::RenderDataPiece( - "string_value", DataPiece(StrCat(int_value.value()), true)); - return Status(); - } - } - struct_field_name = "number_value"; - break; - } - case DataPiece::TYPE_UINT64: { - // If the option to treat integers as strings is set, then render them as - // strings. Otherwise, fallback to rendering them as double. - if (ow->options_.struct_integers_as_strings) { - util::StatusOr<uint64_t> int_value = data.ToUint64(); - if (int_value.ok()) { - ow->ProtoWriter::RenderDataPiece( - "string_value", DataPiece(StrCat(int_value.value()), true)); - return Status(); - } - } - struct_field_name = "number_value"; - break; - } - case DataPiece::TYPE_FLOAT: { - if (ow->options_.struct_integers_as_strings) { - util::StatusOr<float> float_value = data.ToFloat(); - if (float_value.ok()) { - ow->ProtoWriter::RenderDataPiece( - "string_value", - DataPiece(SimpleDtoa(float_value.value()), true)); - return Status(); - } - } - struct_field_name = "number_value"; - break; - } - case DataPiece::TYPE_DOUBLE: { - if (ow->options_.struct_integers_as_strings) { - util::StatusOr<double> double_value = data.ToDouble(); - if (double_value.ok()) { - ow->ProtoWriter::RenderDataPiece( - "string_value", - DataPiece(SimpleDtoa(double_value.value()), true)); - return Status(); - } - } - struct_field_name = "number_value"; - break; - } - case DataPiece::TYPE_STRING: { - struct_field_name = "string_value"; - break; - } - case DataPiece::TYPE_BOOL: { - struct_field_name = "bool_value"; - break; - } - case DataPiece::TYPE_NULL: { - struct_field_name = "null_value"; - break; - } - default: { - return util::InvalidArgumentError( - "Invalid struct data type. Only number, string, boolean or null " - "values are supported."); - } - } - ow->ProtoWriter::RenderDataPiece(struct_field_name, data); - return Status(); -} - -Status ProtoStreamObjectWriter::RenderTimestamp(ProtoStreamObjectWriter* ow, - const DataPiece& data) { - if (data.type() == DataPiece::TYPE_NULL) return Status(); - if (data.type() != DataPiece::TYPE_STRING) { - return util::InvalidArgumentError( - StrCat("Invalid data type for timestamp, value is ", - data.ValueAsStringOrDefault(""))); - } - - StringPiece value(data.str()); - - int64 seconds; - int32 nanos; - if (!::google::protobuf::internal::ParseTime(value.ToString(), &seconds, - &nanos)) { - return util::InvalidArgumentError(StrCat("Invalid time format: ", value)); - } - - - ow->ProtoWriter::RenderDataPiece("seconds", DataPiece(seconds)); - ow->ProtoWriter::RenderDataPiece("nanos", DataPiece(nanos)); - return Status(); -} - -static inline util::Status RenderOneFieldPath(ProtoStreamObjectWriter* ow, - StringPiece path) { - ow->ProtoWriter::RenderDataPiece( - "paths", DataPiece(ConvertFieldMaskPath(path, &ToSnakeCase), true)); - return Status(); -} - -Status ProtoStreamObjectWriter::RenderFieldMask(ProtoStreamObjectWriter* ow, - const DataPiece& data) { - if (data.type() == DataPiece::TYPE_NULL) return Status(); - if (data.type() != DataPiece::TYPE_STRING) { - return util::InvalidArgumentError( - StrCat("Invalid data type for field mask, value is ", - data.ValueAsStringOrDefault(""))); - } - - // TODO(tsun): figure out how to do proto descriptor based snake case - // conversions as much as possible. Because ToSnakeCase sometimes returns the - // wrong value. - return DecodeCompactFieldMaskPaths(data.str(), - std::bind(&RenderOneFieldPath, ow, _1)); -} - -Status ProtoStreamObjectWriter::RenderDuration(ProtoStreamObjectWriter* ow, - const DataPiece& data) { - if (data.type() == DataPiece::TYPE_NULL) return Status(); - if (data.type() != DataPiece::TYPE_STRING) { - return util::InvalidArgumentError( - StrCat("Invalid data type for duration, value is ", - data.ValueAsStringOrDefault(""))); - } - - StringPiece value(data.str()); - - if (!HasSuffixString(value, "s")) { - return util::InvalidArgumentError( - "Illegal duration format; duration must end with 's'"); - } - value = value.substr(0, value.size() - 1); - int sign = 1; - if (HasPrefixString(value, "-")) { - sign = -1; - value = value.substr(1); - } - - StringPiece s_secs, s_nanos; - SplitSecondsAndNanos(value, &s_secs, &s_nanos); - uint64_t unsigned_seconds; - if (!safe_strtou64(s_secs, &unsigned_seconds)) { - return util::InvalidArgumentError( - "Invalid duration format, failed to parse seconds"); - } - - int32_t nanos = 0; - Status nanos_status = GetNanosFromStringPiece( - s_nanos, "Invalid duration format, failed to parse nano seconds", - "Duration value exceeds limits", &nanos); - if (!nanos_status.ok()) { - return nanos_status; - } - nanos = sign * nanos; - - int64_t seconds = sign * unsigned_seconds; - if (seconds > kDurationMaxSeconds || seconds < kDurationMinSeconds || - nanos <= -kNanosPerSecond || nanos >= kNanosPerSecond) { - return util::InvalidArgumentError("Duration value exceeds limits"); - } - - ow->ProtoWriter::RenderDataPiece("seconds", DataPiece(seconds)); - ow->ProtoWriter::RenderDataPiece("nanos", DataPiece(nanos)); - return Status(); -} - -Status ProtoStreamObjectWriter::RenderWrapperType(ProtoStreamObjectWriter* ow, - const DataPiece& data) { - if (data.type() == DataPiece::TYPE_NULL) return Status(); - ow->ProtoWriter::RenderDataPiece("value", data); - return Status(); -} - -ProtoStreamObjectWriter* ProtoStreamObjectWriter::RenderDataPiece( - StringPiece name, const DataPiece& data) { - Status status; - if (invalid_depth() > 0) return this; - - if (current_ == nullptr) { - const TypeRenderer* type_renderer = - FindTypeRenderer(GetFullTypeWithUrl(master_type_.name())); - if (type_renderer == nullptr) { - InvalidName(name, "Root element must be a message."); - return this; - } - // Render the special type. - // "<name>": { - // ... Render special type ... - // } - ProtoWriter::StartObject(name); - status = (*type_renderer)(this, data); - if (!status.ok()) { - InvalidValue(master_type_.name(), - StrCat("Field '", name, "', ", status.message())); - } - ProtoWriter::EndObject(); - return this; - } - - if (current_->IsAny()) { - current_->any()->RenderDataPiece(name, data); - return this; - } - - const google::protobuf::Field* field = nullptr; - if (current_->IsMap()) { - if (!ValidMapKey(name)) return this; - - field = Lookup("value"); - if (field == nullptr) { - GOOGLE_LOG(DFATAL) << "Map does not have a value field."; - return this; - } - - if (options_.ignore_null_value_map_entry) { - // If we are rendering explicit null values and the backend proto field is - // not of the google.protobuf.NullType type, interpret null as absence. - if (data.type() == DataPiece::TYPE_NULL && - field->type_url() != kStructNullValueTypeUrl) { - return this; - } - } - - // Render an item in repeated map list. - // { "key": "<name>", "value": - Push("", Item::MESSAGE, false, false); - ProtoWriter::RenderDataPiece("key", - DataPiece(name, use_strict_base64_decoding())); - - const TypeRenderer* type_renderer = FindTypeRenderer(field->type_url()); - if (type_renderer != nullptr) { - // Map's value type is a special type. Render it like a message: - // "value": { - // ... Render special type ... - // } - Push("value", Item::MESSAGE, true, false); - status = (*type_renderer)(this, data); - if (!status.ok()) { - InvalidValue(field->type_url(), - StrCat("Field '", name, "', ", status.message())); - } - Pop(); - return this; - } - - // If we are rendering explicit null values and the backend proto field is - // not of the google.protobuf.NullType type, we do nothing. - if (data.type() == DataPiece::TYPE_NULL && - field->type_url() != kStructNullValueTypeUrl) { - Pop(); - return this; - } - - // Render the map value as a primitive type. - ProtoWriter::RenderDataPiece("value", data); - Pop(); - return this; - } - - field = Lookup(name); - if (field == nullptr) return this; - - // Check if the field is of special type. Render it accordingly if so. - const TypeRenderer* type_renderer = FindTypeRenderer(field->type_url()); - if (type_renderer != nullptr) { - // Pass through null value only for google.protobuf.Value. For other - // types we ignore null value just like for regular field types. - if (data.type() != DataPiece::TYPE_NULL || - field->type_url() == kStructValueTypeUrl) { - Push(name, Item::MESSAGE, false, false); - status = (*type_renderer)(this, data); - if (!status.ok()) { - InvalidValue(field->type_url(), - StrCat("Field '", name, "', ", status.message())); - } - Pop(); - } - return this; - } - - // If we are rendering explicit null values and the backend proto field is - // not of the google.protobuf.NullType type, we do nothing. - if (data.type() == DataPiece::TYPE_NULL && - field->type_url() != kStructNullValueTypeUrl) { - return this; - } - - if (IsRepeated(*field) && !current_->is_list()) { - if (options_.disable_implicit_scalar_list) { - if (!options_.suppress_implicit_scalar_list_error) { - InvalidValue( - field->name(), - "Starting an primitive in a repeated field but the parent field " - "is not a list"); - } - - return this; - } - } - - ProtoWriter::RenderDataPiece(name, data); - return this; -} - -// Map of functions that are responsible for rendering well known type -// represented by the key. -std::unordered_map<std::string, ProtoStreamObjectWriter::TypeRenderer>* - ProtoStreamObjectWriter::renderers_ = nullptr; -PROTOBUF_NAMESPACE_ID::internal::once_flag writer_renderers_init_; - -void ProtoStreamObjectWriter::InitRendererMap() { - renderers_ = new std::unordered_map<std::string, - ProtoStreamObjectWriter::TypeRenderer>(); - (*renderers_)["type.googleapis.com/google.protobuf.Timestamp"] = - &ProtoStreamObjectWriter::RenderTimestamp; - (*renderers_)["type.googleapis.com/google.protobuf.Duration"] = - &ProtoStreamObjectWriter::RenderDuration; - (*renderers_)["type.googleapis.com/google.protobuf.FieldMask"] = - &ProtoStreamObjectWriter::RenderFieldMask; - (*renderers_)["type.googleapis.com/google.protobuf.Double"] = - &ProtoStreamObjectWriter::RenderWrapperType; - (*renderers_)["type.googleapis.com/google.protobuf.Float"] = - &ProtoStreamObjectWriter::RenderWrapperType; - (*renderers_)["type.googleapis.com/google.protobuf.Int64"] = - &ProtoStreamObjectWriter::RenderWrapperType; - (*renderers_)["type.googleapis.com/google.protobuf.UInt64"] = - &ProtoStreamObjectWriter::RenderWrapperType; - (*renderers_)["type.googleapis.com/google.protobuf.Int32"] = - &ProtoStreamObjectWriter::RenderWrapperType; - (*renderers_)["type.googleapis.com/google.protobuf.UInt32"] = - &ProtoStreamObjectWriter::RenderWrapperType; - (*renderers_)["type.googleapis.com/google.protobuf.Bool"] = - &ProtoStreamObjectWriter::RenderWrapperType; - (*renderers_)["type.googleapis.com/google.protobuf.String"] = - &ProtoStreamObjectWriter::RenderWrapperType; - (*renderers_)["type.googleapis.com/google.protobuf.Bytes"] = - &ProtoStreamObjectWriter::RenderWrapperType; - (*renderers_)["type.googleapis.com/google.protobuf.DoubleValue"] = - &ProtoStreamObjectWriter::RenderWrapperType; - (*renderers_)["type.googleapis.com/google.protobuf.FloatValue"] = - &ProtoStreamObjectWriter::RenderWrapperType; - (*renderers_)["type.googleapis.com/google.protobuf.Int64Value"] = - &ProtoStreamObjectWriter::RenderWrapperType; - (*renderers_)["type.googleapis.com/google.protobuf.UInt64Value"] = - &ProtoStreamObjectWriter::RenderWrapperType; - (*renderers_)["type.googleapis.com/google.protobuf.Int32Value"] = - &ProtoStreamObjectWriter::RenderWrapperType; - (*renderers_)["type.googleapis.com/google.protobuf.UInt32Value"] = - &ProtoStreamObjectWriter::RenderWrapperType; - (*renderers_)["type.googleapis.com/google.protobuf.BoolValue"] = - &ProtoStreamObjectWriter::RenderWrapperType; - (*renderers_)["type.googleapis.com/google.protobuf.StringValue"] = - &ProtoStreamObjectWriter::RenderWrapperType; - (*renderers_)["type.googleapis.com/google.protobuf.BytesValue"] = - &ProtoStreamObjectWriter::RenderWrapperType; - (*renderers_)["type.googleapis.com/google.protobuf.Value"] = - &ProtoStreamObjectWriter::RenderStructValue; - ::google::protobuf::internal::OnShutdown(&DeleteRendererMap); -} - -void ProtoStreamObjectWriter::DeleteRendererMap() { - delete ProtoStreamObjectWriter::renderers_; - renderers_ = nullptr; -} - -ProtoStreamObjectWriter::TypeRenderer* -ProtoStreamObjectWriter::FindTypeRenderer(const std::string& type_url) { - PROTOBUF_NAMESPACE_ID::internal::call_once(writer_renderers_init_, - InitRendererMap); - return FindOrNull(*renderers_, type_url); -} - -bool ProtoStreamObjectWriter::ValidMapKey(StringPiece unnormalized_name) { - if (current_ == nullptr) return true; - - if (!current_->InsertMapKeyIfNotPresent(unnormalized_name)) { - listener()->InvalidName( - location(), unnormalized_name, - StrCat("Repeated map key: '", unnormalized_name, - "' is already set.")); - return false; - } - - return true; -} - -void ProtoStreamObjectWriter::Push( - StringPiece name, Item::ItemType item_type, bool is_placeholder, - bool is_list) { - is_list ? ProtoWriter::StartList(name) : ProtoWriter::StartObject(name); - - // invalid_depth == 0 means it is a successful StartObject or StartList. - if (invalid_depth() == 0) - current_.reset( - new Item(current_.release(), item_type, is_placeholder, is_list)); -} - -void ProtoStreamObjectWriter::Pop() { - // Pop all placeholder items sending StartObject or StartList events to - // ProtoWriter according to is_list value. - while (current_ != nullptr && current_->is_placeholder()) { - PopOneElement(); - } - if (current_ != nullptr) { - PopOneElement(); - } -} - -void ProtoStreamObjectWriter::PopOneElement() { - current_->is_list() ? ProtoWriter::EndList() : ProtoWriter::EndObject(); - current_.reset(current_->pop<Item>()); -} - -bool ProtoStreamObjectWriter::IsMap(const google::protobuf::Field& field) { - if (field.type_url().empty() || - field.kind() != google::protobuf::Field::TYPE_MESSAGE || - field.cardinality() != google::protobuf::Field::CARDINALITY_REPEATED) { - return false; - } - const google::protobuf::Type* field_type = - typeinfo()->GetTypeByTypeUrl(field.type_url()); - - return converter::IsMap(field, *field_type); -} - -bool ProtoStreamObjectWriter::IsAny(const google::protobuf::Field& field) { - return GetTypeWithoutUrl(field.type_url()) == kAnyType; -} - -bool ProtoStreamObjectWriter::IsStruct(const google::protobuf::Field& field) { - return GetTypeWithoutUrl(field.type_url()) == kStructType; -} - -bool ProtoStreamObjectWriter::IsStructValue( - const google::protobuf::Field& field) { - return GetTypeWithoutUrl(field.type_url()) == kStructValueType; -} - -bool ProtoStreamObjectWriter::IsStructListValue( - const google::protobuf::Field& field) { - return GetTypeWithoutUrl(field.type_url()) == kStructListValueType; -} - -} // namespace converter -} // namespace util -} // namespace protobuf -} // namespace google diff --git a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/protostream_objectwriter.h b/contrib/libs/protobuf_std/src/google/protobuf/util/internal/protostream_objectwriter.h deleted file mode 100644 index 0befd1c240..0000000000 --- a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/protostream_objectwriter.h +++ /dev/null @@ -1,452 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTOSTREAM_OBJECTWRITER_H__ -#define GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTOSTREAM_OBJECTWRITER_H__ - -#include <deque> -#include <string> -#include <unordered_map> -#include <unordered_set> - -#include <google/protobuf/stubs/common.h> -#include <google/protobuf/type.pb.h> -#include <google/protobuf/io/coded_stream.h> -#include <google/protobuf/io/zero_copy_stream_impl.h> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/util/internal/type_info.h> -#include <google/protobuf/util/internal/datapiece.h> -#include <google/protobuf/util/internal/error_listener.h> -#include <google/protobuf/util/internal/proto_writer.h> -#include <google/protobuf/util/internal/structured_objectwriter.h> -#include <google/protobuf/util/type_resolver.h> -#include <google/protobuf/stubs/bytestream.h> -#include <google/protobuf/stubs/status.h> -#include <google/protobuf/stubs/hash.h> - -#include <google/protobuf/port_def.inc> - -namespace google { -namespace protobuf { -namespace util { -namespace converter { - -class ObjectLocationTracker; - -// An ObjectWriter that can write protobuf bytes directly from writer events. -// This class supports all special types like Struct and Map. It uses -// the ProtoWriter class to write raw proto bytes. -// -// It also supports streaming. -class PROTOBUF_EXPORT ProtoStreamObjectWriter : public ProtoWriter { - public: - // Options that control ProtoStreamObjectWriter class's behavior. - struct Options { - // Treats numeric inputs in google.protobuf.Struct as strings. Normally, - // numeric values are returned in double field "number_value" of - // google.protobuf.Struct. However, this can cause precision loss for - // int64/uint64/double inputs. This option is provided for cases that want - // to preserve number precision. - // - // TODO(skarvaje): Rename to struct_numbers_as_strings as it covers double - // as well. - bool struct_integers_as_strings; - - // Not treat unknown fields as an error. If there is an unknown fields, - // just ignore it and continue to process the rest. Note that this doesn't - // apply to unknown enum values. - bool ignore_unknown_fields; - - // Ignore unknown enum values. - bool ignore_unknown_enum_values; - - // If true, check if enum name in camel case or without underscore matches - // the field name. - bool use_lower_camel_for_enums; - - // If true, check if enum name in UPPER_CASE matches the field name. - bool case_insensitive_enum_parsing; - - // If true, skips rendering the map entry if map value is null unless the - // value type is google.protobuf.NullType. - bool ignore_null_value_map_entry; - - // If true, accepts repeated key/value pair for a map proto field. - bool use_legacy_json_map_format; - - // If true, disable implicitly creating message list. - bool disable_implicit_message_list; - - // If true, suppress the error of implicitly creating message list when it - // is disabled. - bool suppress_implicit_message_list_error; - - // If true, disable implicitly creating scalar list. - bool disable_implicit_scalar_list; - - // If true, suppress the error of implicitly creating scalar list when it - // is disabled. - bool suppress_implicit_scalar_list_error; - - // If true, suppress the error of rendering scalar field if the source is an - // object. - bool suppress_object_to_scalar_error; - - // If true, use the json name in missing fields errors. - bool use_json_name_in_missing_fields; - - Options() - : struct_integers_as_strings(false), - ignore_unknown_fields(false), - ignore_unknown_enum_values(false), - use_lower_camel_for_enums(false), - case_insensitive_enum_parsing(false), - ignore_null_value_map_entry(false), - use_legacy_json_map_format(false), - disable_implicit_message_list(false), - suppress_implicit_message_list_error(false), - disable_implicit_scalar_list(false), - suppress_implicit_scalar_list_error(false), - suppress_object_to_scalar_error(false), - use_json_name_in_missing_fields(false) {} - - // Default instance of Options with all options set to defaults. - static const Options& Defaults() { - static Options defaults; - return defaults; - } - }; - - // Constructor. Does not take ownership of any parameter passed in. - ProtoStreamObjectWriter(TypeResolver* type_resolver, - const google::protobuf::Type& type, - strings::ByteSink* output, ErrorListener* listener, - const ProtoStreamObjectWriter::Options& options = - ProtoStreamObjectWriter::Options::Defaults()); - ~ProtoStreamObjectWriter() override; - - // ObjectWriter methods. - ProtoStreamObjectWriter* StartObject(StringPiece name) override; - ProtoStreamObjectWriter* EndObject() override; - ProtoStreamObjectWriter* StartList(StringPiece name) override; - ProtoStreamObjectWriter* EndList() override; - - // Renders a DataPiece 'value' into a field whose wire type is determined - // from the given field 'name'. - ProtoStreamObjectWriter* RenderDataPiece(StringPiece name, - const DataPiece& data) override; - - protected: - // Function that renders a well known type with modified behavior. - typedef util::Status (*TypeRenderer)(ProtoStreamObjectWriter*, - const DataPiece&); - - // Handles writing Anys out using nested object writers and the like. - class PROTOBUF_EXPORT AnyWriter { - public: - explicit AnyWriter(ProtoStreamObjectWriter* parent); - ~AnyWriter(); - - // Passes a StartObject call through to the Any writer. - void StartObject(StringPiece name); - - // Passes an EndObject call through to the Any. Returns true if the any - // handled the EndObject call, false if the Any is now all done and is no - // longer needed. - bool EndObject(); - - // Passes a StartList call through to the Any writer. - void StartList(StringPiece name); - - // Passes an EndList call through to the Any writer. - void EndList(); - - // Renders a data piece on the any. - void RenderDataPiece(StringPiece name, const DataPiece& value); - - private: - // Before the "@type" field is encountered, we store all incoming data - // into this Event struct and replay them after we get the "@type" field. - class PROTOBUF_EXPORT Event { - public: - enum Type { - START_OBJECT = 0, - END_OBJECT = 1, - START_LIST = 2, - END_LIST = 3, - RENDER_DATA_PIECE = 4, - }; - - // Constructor for END_OBJECT and END_LIST events. - explicit Event(Type type) : type_(type), value_(DataPiece::NullData()) {} - - // Constructor for START_OBJECT and START_LIST events. - explicit Event(Type type, StringPiece name) - : type_(type), name_(name), value_(DataPiece::NullData()) {} - - // Constructor for RENDER_DATA_PIECE events. - explicit Event(StringPiece name, const DataPiece& value) - : type_(RENDER_DATA_PIECE), name_(name), value_(value) { - DeepCopy(); - } - - Event(const Event& other) - : type_(other.type_), name_(other.name_), value_(other.value_) { - DeepCopy(); - } - - Event& operator=(const Event& other) { - type_ = other.type_; - name_ = other.name_; - value_ = other.value_; - DeepCopy(); - return *this; - } - - void Replay(AnyWriter* writer) const; - - private: - void DeepCopy(); - - Type type_; - std::string name_; - DataPiece value_; - std::string value_storage_; - }; - - // Handles starting up the any once we have a type. - void StartAny(const DataPiece& value); - - // Writes the Any out to the parent writer in its serialized form. - void WriteAny(); - - // The parent of this writer, needed for various bits such as type info and - // the listeners. - ProtoStreamObjectWriter* parent_; - - // The nested object writer, used to write events. - std::unique_ptr<ProtoStreamObjectWriter> ow_; - - // The type_url_ that this Any represents. - std::string type_url_; - - // Whether this any is invalid. This allows us to only report an invalid - // Any message a single time rather than every time we get a nested field. - bool invalid_; - - // The output data and wrapping ByteSink. - std::string data_; - strings::StringByteSink output_; - - // The depth within the Any, so we can track when we're done. - int depth_; - - // True if the type is a well-known type. Well-known types in Any - // has a special formatting: - // { - // "@type": "type.googleapis.com/google.protobuf.XXX", - // "value": <JSON representation of the type>, - // } - bool is_well_known_type_; - TypeRenderer* well_known_type_render_; - - // Store data before the "@type" field. - std::vector<Event> uninterpreted_events_; - }; - - // Represents an item in a stack of items used to keep state between - // ObjectWrier events. - class PROTOBUF_EXPORT Item : public BaseElement { - public: - // Indicates the type of item. - enum ItemType { - MESSAGE, // Simple message - MAP, // Proto3 map type - ANY, // Proto3 Any type - }; - - // Constructor for the root item. - Item(ProtoStreamObjectWriter* enclosing, ItemType item_type, - bool is_placeholder, bool is_list); - - // Constructor for a field of a message. - Item(Item* parent, ItemType item_type, bool is_placeholder, bool is_list); - - ~Item() override {} - - // These functions return true if the element type is corresponding to the - // type in function name. - bool IsMap() { return item_type_ == MAP; } - bool IsAny() { return item_type_ == ANY; } - - AnyWriter* any() const { return any_.get(); } - - Item* parent() const override { - return static_cast<Item*>(BaseElement::parent()); - } - - // Inserts map key into hash set if and only if the key did NOT already - // exist in hash set. - // The hash set (map_keys_) is ONLY used to keep track of map keys. - // Return true if insert successfully; returns false if the map key was - // already present. - bool InsertMapKeyIfNotPresent(StringPiece map_key); - - bool is_placeholder() const { return is_placeholder_; } - bool is_list() const { return is_list_; } - - private: - // Used for access to variables of the enclosing instance of - // ProtoStreamObjectWriter. - ProtoStreamObjectWriter* ow_; - - // A writer for Any objects, handles all Any-related nonsense. - std::unique_ptr<AnyWriter> any_; - - // The type of this element, see enum for permissible types. - ItemType item_type_; - - // Set of map keys already seen for the type_. Used to validate incoming - // messages so no map key appears more than once. - std::unique_ptr<std::unordered_set<std::string> > map_keys_; - - // Conveys whether this Item is a placeholder or not. Placeholder items are - // pushed to stack to account for special types. - bool is_placeholder_; - - // Conveys whether this Item is a list or not. This is used to send - // StartList or EndList calls to underlying ObjectWriter. - bool is_list_; - - GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(Item); - }; - - ProtoStreamObjectWriter(const TypeInfo* typeinfo, - const google::protobuf::Type& type, - strings::ByteSink* output, ErrorListener* listener); - - ProtoStreamObjectWriter(const TypeInfo* typeinfo, - const google::protobuf::Type& type, - strings::ByteSink* output, ErrorListener* listener, - const ProtoStreamObjectWriter::Options& options); - - // Returns true if the field is a map. - inline bool IsMap(const google::protobuf::Field& field); - - // Returns true if the field is an any. - inline bool IsAny(const google::protobuf::Field& field); - - // Returns true if the field is google.protobuf.Struct. - inline bool IsStruct(const google::protobuf::Field& field); - - // Returns true if the field is google.protobuf.Value. - inline bool IsStructValue(const google::protobuf::Field& field); - - // Returns true if the field is google.protobuf.ListValue. - inline bool IsStructListValue(const google::protobuf::Field& field); - - // Renders google.protobuf.Value in struct.proto. It picks the right oneof - // type based on value's type. - static util::Status RenderStructValue(ProtoStreamObjectWriter* ow, - const DataPiece& data); - - // Renders google.protobuf.Timestamp value. - static util::Status RenderTimestamp(ProtoStreamObjectWriter* ow, - const DataPiece& data); - - // Renders google.protobuf.FieldMask value. - static util::Status RenderFieldMask(ProtoStreamObjectWriter* ow, - const DataPiece& data); - - // Renders google.protobuf.Duration value. - static util::Status RenderDuration(ProtoStreamObjectWriter* ow, - const DataPiece& data); - - // Renders wrapper message types for primitive types in - // google/protobuf/wrappers.proto. - static util::Status RenderWrapperType(ProtoStreamObjectWriter* ow, - const DataPiece& data); - - static void InitRendererMap(); - static void DeleteRendererMap(); - static TypeRenderer* FindTypeRenderer(const std::string& type_url); - - // Returns true if the map key for type_ is not duplicated key. - // If map key is duplicated key, this function returns false. - // Note that caller should make sure that the current proto element (current_) - // is of element type MAP or STRUCT_MAP. - // It also calls the appropriate error callback and unnormalzied_name is used - // for error string. - bool ValidMapKey(StringPiece unnormalized_name); - - // Pushes an item on to the stack. Also calls either StartObject or StartList - // on the underlying ObjectWriter depending on whether is_list is false or - // not. - // is_placeholder conveys whether the item is a placeholder item or not. - // Placeholder items are pushed when adding auxiliary types' StartObject or - // StartList calls. - void Push(StringPiece name, Item::ItemType item_type, - bool is_placeholder, bool is_list); - - - // Pops items from the stack. All placeholder items are popped until a - // non-placeholder item is found. - void Pop(); - - // Pops one element from the stack. Calls EndObject() or EndList() on the - // underlying ObjectWriter depending on the value of is_list_. - void PopOneElement(); - - private: - // Helper functions to create the map and find functions responsible for - // rendering well known types, keyed by type URL. - static std::unordered_map<std::string, TypeRenderer>* renderers_; - - // Variables for describing the structure of the input tree: - // master_type_: descriptor for the whole protobuf message. - const google::protobuf::Type& master_type_; - - // The current element, variable for internal state processing. - std::unique_ptr<Item> current_; - - // Reference to the options that control this class's behavior. - const ProtoStreamObjectWriter::Options options_; - - GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(ProtoStreamObjectWriter); -}; - -} // namespace converter -} // namespace util -} // namespace protobuf -} // namespace google - -#include <google/protobuf/port_undef.inc> - -#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTOSTREAM_OBJECTWRITER_H__ diff --git a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/structured_objectwriter.h b/contrib/libs/protobuf_std/src/google/protobuf/util/internal/structured_objectwriter.h deleted file mode 100644 index 01cbb9e1ac..0000000000 --- a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/structured_objectwriter.h +++ /dev/null @@ -1,120 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_STRUCTURED_OBJECTWRITER_H__ -#define GOOGLE_PROTOBUF_UTIL_CONVERTER_STRUCTURED_OBJECTWRITER_H__ - -#include <memory> - -#include <google/protobuf/stubs/casts.h> -#include <google/protobuf/stubs/common.h> -#include <google/protobuf/util/internal/object_writer.h> - -#include <google/protobuf/port_def.inc> - -namespace google { -namespace protobuf { -namespace util { -namespace converter { - -// An StructuredObjectWriter is an ObjectWriter for writing -// tree-structured data in a stream of events representing objects -// and collections. Implementation of this interface can be used to -// write an object stream to an in-memory structure, protobufs, -// JSON, XML, or any other output format desired. The ObjectSource -// interface is typically used as the source of an object stream. -// -// See JsonObjectWriter for a sample implementation of -// StructuredObjectWriter and its use. -// -// Derived classes could be thread-unsafe. -class PROTOBUF_EXPORT StructuredObjectWriter : public ObjectWriter { - public: - virtual ~StructuredObjectWriter() {} - - protected: - // A base element class for subclasses to extend, makes tracking state easier. - // - // StructuredObjectWriter behaves as a visitor. BaseElement represents a node - // in the input tree. Implementation of StructuredObjectWriter should also - // extend BaseElement to keep track of the location in the input tree. - class PROTOBUF_EXPORT BaseElement { - public: - // Takes ownership of the parent Element. - explicit BaseElement(BaseElement* parent) - : parent_(parent), - level_(parent == nullptr ? 0 : parent->level() + 1) {} - virtual ~BaseElement() {} - - // Releases ownership of the parent and returns a pointer to it. - template <typename ElementType> - ElementType* pop() { - return down_cast<ElementType*>(parent_.release()); - } - - // Returns true if this element is the root. - bool is_root() const { return parent_ == nullptr; } - - // Returns the number of hops from this element to the root element. - int level() const { return level_; } - - protected: - // Returns pointer to parent element without releasing ownership. - virtual BaseElement* parent() const { return parent_.get(); } - - private: - // Pointer to the parent Element. - std::unique_ptr<BaseElement> parent_; - - // Number of hops to the root Element. - // The root Element has nullptr parent_ and a level_ of 0. - const int level_; - - GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(BaseElement); - }; - - StructuredObjectWriter() {} - - // Returns the current element. Used for indentation and name overrides. - virtual BaseElement* element() = 0; - - private: - // Do not add any data members to this class. - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StructuredObjectWriter); -}; - -} // namespace converter -} // namespace util -} // namespace protobuf -} // namespace google - -#include <google/protobuf/port_undef.inc> - -#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_STRUCTURED_OBJECTWRITER_H__ diff --git a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/type_info.cc b/contrib/libs/protobuf_std/src/google/protobuf/util/internal/type_info.cc deleted file mode 100644 index aaa37d1441..0000000000 --- a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/type_info.cc +++ /dev/null @@ -1,182 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include <google/protobuf/util/internal/type_info.h> - -#include <map> -#include <set> - -#include <google/protobuf/stubs/common.h> -#include <google/protobuf/type.pb.h> -#include <google/protobuf/util/internal/utility.h> -#include <google/protobuf/stubs/status.h> -#include <google/protobuf/stubs/statusor.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/stubs/map_util.h> -#include <google/protobuf/stubs/status.h> - -namespace google { -namespace protobuf { -namespace util { -namespace converter { - -namespace { -// A TypeInfo that looks up information provided by a TypeResolver. -class TypeInfoForTypeResolver : public TypeInfo { - public: - explicit TypeInfoForTypeResolver(TypeResolver* type_resolver) - : type_resolver_(type_resolver) {} - - virtual ~TypeInfoForTypeResolver() { - DeleteCachedTypes(&cached_types_); - DeleteCachedTypes(&cached_enums_); - } - - util::StatusOr<const google::protobuf::Type*> ResolveTypeUrl( - StringPiece type_url) const override { - std::map<StringPiece, StatusOrType>::iterator it = - cached_types_.find(type_url); - if (it != cached_types_.end()) { - return it->second; - } - // Stores the string value so it can be referenced using StringPiece in the - // cached_types_ map. - const std::string& string_type_url = - *string_storage_.insert(std::string(type_url)).first; - std::unique_ptr<google::protobuf::Type> type(new google::protobuf::Type()); - util::Status status = - type_resolver_->ResolveMessageType(string_type_url, type.get()); - StatusOrType result = - status.ok() ? StatusOrType(type.release()) : StatusOrType(status); - cached_types_[string_type_url] = result; - return result; - } - - const google::protobuf::Type* GetTypeByTypeUrl( - StringPiece type_url) const override { - StatusOrType result = ResolveTypeUrl(type_url); - return result.ok() ? result.value() : NULL; - } - - const google::protobuf::Enum* GetEnumByTypeUrl( - StringPiece type_url) const override { - std::map<StringPiece, StatusOrEnum>::iterator it = - cached_enums_.find(type_url); - if (it != cached_enums_.end()) { - return it->second.ok() ? it->second.value() : NULL; - } - // Stores the string value so it can be referenced using StringPiece in the - // cached_enums_ map. - const std::string& string_type_url = - *string_storage_.insert(std::string(type_url)).first; - std::unique_ptr<google::protobuf::Enum> enum_type( - new google::protobuf::Enum()); - util::Status status = - type_resolver_->ResolveEnumType(string_type_url, enum_type.get()); - StatusOrEnum result = - status.ok() ? StatusOrEnum(enum_type.release()) : StatusOrEnum(status); - cached_enums_[string_type_url] = result; - return result.ok() ? result.value() : NULL; - } - - const google::protobuf::Field* FindField( - const google::protobuf::Type* type, - StringPiece camel_case_name) const override { - std::map<const google::protobuf::Type*, CamelCaseNameTable>::const_iterator - it = indexed_types_.find(type); - const CamelCaseNameTable& camel_case_name_table = - (it == indexed_types_.end()) - ? PopulateNameLookupTable(type, &indexed_types_[type]) - : it->second; - StringPiece name = FindWithDefault( - camel_case_name_table, camel_case_name, StringPiece()); - if (name.empty()) { - // Didn't find a mapping. Use whatever provided. - name = camel_case_name; - } - return FindFieldInTypeOrNull(type, name); - } - - private: - typedef util::StatusOr<const google::protobuf::Type*> StatusOrType; - typedef util::StatusOr<const google::protobuf::Enum*> StatusOrEnum; - typedef std::map<StringPiece, StringPiece> CamelCaseNameTable; - - template <typename T> - static void DeleteCachedTypes(std::map<StringPiece, T>* cached_types) { - for (typename std::map<StringPiece, T>::iterator it = - cached_types->begin(); - it != cached_types->end(); ++it) { - if (it->second.ok()) { - delete it->second.value(); - } - } - } - - const CamelCaseNameTable& PopulateNameLookupTable( - const google::protobuf::Type* type, - CamelCaseNameTable* camel_case_name_table) const { - for (int i = 0; i < type->fields_size(); ++i) { - const google::protobuf::Field& field = type->fields(i); - StringPiece name = field.name(); - StringPiece camel_case_name = field.json_name(); - const StringPiece* existing = InsertOrReturnExisting( - camel_case_name_table, camel_case_name, name); - if (existing && *existing != name) { - GOOGLE_LOG(WARNING) << "Field '" << name << "' and '" << *existing - << "' map to the same camel case name '" << camel_case_name - << "'."; - } - } - return *camel_case_name_table; - } - - TypeResolver* type_resolver_; - - // Stores string values that will be referenced by StringPieces in - // cached_types_, cached_enums_. - mutable std::set<std::string> string_storage_; - - mutable std::map<StringPiece, StatusOrType> cached_types_; - mutable std::map<StringPiece, StatusOrEnum> cached_enums_; - - mutable std::map<const google::protobuf::Type*, CamelCaseNameTable> - indexed_types_; -}; -} // namespace - -TypeInfo* TypeInfo::NewTypeInfo(TypeResolver* type_resolver) { - return new TypeInfoForTypeResolver(type_resolver); -} - -} // namespace converter -} // namespace util -} // namespace protobuf -} // namespace google diff --git a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/type_info.h b/contrib/libs/protobuf_std/src/google/protobuf/util/internal/type_info.h deleted file mode 100644 index d8d679e1fe..0000000000 --- a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/type_info.h +++ /dev/null @@ -1,97 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_TYPE_INFO_H__ -#define GOOGLE_PROTOBUF_UTIL_CONVERTER_TYPE_INFO_H__ - -#include <google/protobuf/stubs/common.h> -#include <google/protobuf/type.pb.h> -#include <google/protobuf/util/type_resolver.h> -#include <google/protobuf/stubs/statusor.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/stubs/status.h> - -// Must be included last. -#include <google/protobuf/port_def.inc> - -namespace google { -namespace protobuf { -namespace util { -namespace converter { -// Internal helper class for type resolving. Note that this class is not -// thread-safe and should only be accessed in one thread. -class PROTOBUF_EXPORT TypeInfo { - public: - TypeInfo() {} - virtual ~TypeInfo() {} - - // Resolves a type url into a Type. If the type url is invalid, returns - // INVALID_ARGUMENT error status. If the type url is valid but the - // corresponding type cannot be found, returns a NOT_FOUND error status. - // - // This TypeInfo class retains the ownership of the returned pointer. - virtual util::StatusOr<const google::protobuf::Type*> ResolveTypeUrl( - StringPiece type_url) const = 0; - - // Resolves a type url into a Type. Like ResolveTypeUrl() but returns - // NULL if the type url is invalid or the type cannot be found. - // - // This TypeInfo class retains the ownership of the returned pointer. - virtual const google::protobuf::Type* GetTypeByTypeUrl( - StringPiece type_url) const = 0; - - // Resolves a type url for an enum. Returns NULL if the type url is - // invalid or the type cannot be found. - // - // This TypeInfo class retains the ownership of the returned pointer. - virtual const google::protobuf::Enum* GetEnumByTypeUrl( - StringPiece type_url) const = 0; - - // Looks up a field in the specified type given a CamelCase name. - virtual const google::protobuf::Field* FindField( - const google::protobuf::Type* type, - StringPiece camel_case_name) const = 0; - - // Creates a TypeInfo object that looks up type information from a - // TypeResolver. Caller takes ownership of the returned pointer. - static TypeInfo* NewTypeInfo(TypeResolver* type_resolver); - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TypeInfo); -}; - -} // namespace converter -} // namespace util -} // namespace protobuf -} // namespace google - -#include <google/protobuf/port_undef.inc> - -#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_TYPE_INFO_H__ diff --git a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/type_info_test_helper.cc b/contrib/libs/protobuf_std/src/google/protobuf/util/internal/type_info_test_helper.cc deleted file mode 100644 index e8c3c5a3eb..0000000000 --- a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/type_info_test_helper.cc +++ /dev/null @@ -1,132 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include <google/protobuf/util/internal/type_info_test_helper.h> - -#include <memory> -#include <vector> - -#include <google/protobuf/stubs/logging.h> -#include <google/protobuf/stubs/common.h> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/util/internal/default_value_objectwriter.h> -#include <google/protobuf/util/internal/type_info.h> -#include <google/protobuf/util/internal/constants.h> -#include <google/protobuf/util/internal/protostream_objectsource.h> -#include <google/protobuf/util/internal/protostream_objectwriter.h> -#include <google/protobuf/util/type_resolver.h> -#include <google/protobuf/util/type_resolver_util.h> - -namespace google { -namespace protobuf { -namespace util { -namespace converter { -namespace testing { - - -void TypeInfoTestHelper::ResetTypeInfo( - const std::vector<const Descriptor*>& descriptors) { - switch (type_) { - case USE_TYPE_RESOLVER: { - const DescriptorPool* pool = descriptors[0]->file()->pool(); - for (int i = 1; i < descriptors.size(); ++i) { - GOOGLE_CHECK(pool == descriptors[i]->file()->pool()) - << "Descriptors from different pools are not supported."; - } - type_resolver_.reset( - NewTypeResolverForDescriptorPool(kTypeServiceBaseUrl, pool)); - typeinfo_.reset(TypeInfo::NewTypeInfo(type_resolver_.get())); - return; - } - } - GOOGLE_LOG(FATAL) << "Can not reach here."; -} - -void TypeInfoTestHelper::ResetTypeInfo(const Descriptor* descriptor) { - std::vector<const Descriptor*> descriptors; - descriptors.push_back(descriptor); - ResetTypeInfo(descriptors); -} - -void TypeInfoTestHelper::ResetTypeInfo(const Descriptor* descriptor1, - const Descriptor* descriptor2) { - std::vector<const Descriptor*> descriptors; - descriptors.push_back(descriptor1); - descriptors.push_back(descriptor2); - ResetTypeInfo(descriptors); -} - -TypeInfo* TypeInfoTestHelper::GetTypeInfo() { return typeinfo_.get(); } - -ProtoStreamObjectSource* TypeInfoTestHelper::NewProtoSource( - io::CodedInputStream* coded_input, const std::string& type_url, - ProtoStreamObjectSource::RenderOptions render_options) { - const google::protobuf::Type* type = typeinfo_->GetTypeByTypeUrl(type_url); - switch (type_) { - case USE_TYPE_RESOLVER: { - return new ProtoStreamObjectSource(coded_input, type_resolver_.get(), - *type, render_options); - } - } - GOOGLE_LOG(FATAL) << "Can not reach here."; - return nullptr; -} - -ProtoStreamObjectWriter* TypeInfoTestHelper::NewProtoWriter( - const std::string& type_url, strings::ByteSink* output, - ErrorListener* listener, const ProtoStreamObjectWriter::Options& options) { - const google::protobuf::Type* type = typeinfo_->GetTypeByTypeUrl(type_url); - switch (type_) { - case USE_TYPE_RESOLVER: { - return new ProtoStreamObjectWriter(type_resolver_.get(), *type, output, - listener, options); - } - } - GOOGLE_LOG(FATAL) << "Can not reach here."; - return nullptr; -} - -DefaultValueObjectWriter* TypeInfoTestHelper::NewDefaultValueWriter( - const std::string& type_url, ObjectWriter* writer) { - const google::protobuf::Type* type = typeinfo_->GetTypeByTypeUrl(type_url); - switch (type_) { - case USE_TYPE_RESOLVER: { - return new DefaultValueObjectWriter(type_resolver_.get(), *type, writer); - } - } - GOOGLE_LOG(FATAL) << "Can not reach here."; - return nullptr; -} - -} // namespace testing -} // namespace converter -} // namespace util -} // namespace protobuf -} // namespace google diff --git a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/type_info_test_helper.h b/contrib/libs/protobuf_std/src/google/protobuf/util/internal/type_info_test_helper.h deleted file mode 100644 index c42289e66e..0000000000 --- a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/type_info_test_helper.h +++ /dev/null @@ -1,96 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_TYPE_INFO_TEST_HELPER_H__ -#define GOOGLE_PROTOBUF_UTIL_CONVERTER_TYPE_INFO_TEST_HELPER_H__ - -#include <memory> -#include <vector> - -#include <google/protobuf/io/coded_stream.h> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/util/internal/default_value_objectwriter.h> -#include <google/protobuf/util/internal/type_info.h> -#include <google/protobuf/util/internal/protostream_objectsource.h> -#include <google/protobuf/util/internal/protostream_objectwriter.h> -#include <google/protobuf/util/type_resolver.h> - -namespace google { -namespace protobuf { -namespace util { -namespace converter { -namespace testing { - -enum TypeInfoSource { - USE_TYPE_RESOLVER, -}; - -// In the unit-tests we want to test two scenarios: one with type info from -// ServiceTypeInfo, the other with type info from TypeResolver. This class -// wraps the detail of where the type info is from and provides the same -// interface so the same unit-test code can test both scenarios. -class TypeInfoTestHelper { - public: - explicit TypeInfoTestHelper(TypeInfoSource type) : type_(type) {} - - // Creates a TypeInfo object for the given set of descriptors. - void ResetTypeInfo(const std::vector<const Descriptor*>& descriptors); - - // Convenient overloads. - void ResetTypeInfo(const Descriptor* descriptor); - void ResetTypeInfo(const Descriptor* descriptor1, - const Descriptor* descriptor2); - - // Returns the TypeInfo created after ResetTypeInfo. - TypeInfo* GetTypeInfo(); - - ProtoStreamObjectSource* NewProtoSource( - io::CodedInputStream* coded_input, const std::string& type_url, - ProtoStreamObjectSource::RenderOptions render_options = {}); - - ProtoStreamObjectWriter* NewProtoWriter( - const std::string& type_url, strings::ByteSink* output, - ErrorListener* listener, const ProtoStreamObjectWriter::Options& options); - - DefaultValueObjectWriter* NewDefaultValueWriter(const std::string& type_url, - ObjectWriter* writer); - - private: - TypeInfoSource type_; - std::unique_ptr<TypeInfo> typeinfo_; - std::unique_ptr<TypeResolver> type_resolver_; -}; -} // namespace testing -} // namespace converter -} // namespace util -} // namespace protobuf -} // namespace google - -#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_TYPE_INFO_TEST_HELPER_H__ diff --git a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/utility.cc b/contrib/libs/protobuf_std/src/google/protobuf/util/internal/utility.cc deleted file mode 100644 index 17ff6dd863..0000000000 --- a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/utility.cc +++ /dev/null @@ -1,416 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include <google/protobuf/util/internal/utility.h> - -#include <algorithm> -#include <cmath> -#include <cstdint> -#include <limits> - -#include <google/protobuf/stubs/callback.h> -#include <google/protobuf/stubs/common.h> -#include <google/protobuf/stubs/logging.h> -#include <google/protobuf/wrappers.pb.h> -#include <google/protobuf/descriptor.pb.h> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/util/internal/constants.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/stubs/map_util.h> - -// clang-format off -#include <google/protobuf/port_def.inc> -// clang-format on - -namespace google { -namespace protobuf { -namespace util { -namespace converter { - -bool GetBoolOptionOrDefault( - const RepeatedPtrField<google::protobuf::Option>& options, - StringPiece option_name, bool default_value) { - const google::protobuf::Option* opt = FindOptionOrNull(options, option_name); - if (opt == nullptr) { - return default_value; - } - return GetBoolFromAny(opt->value()); -} - -int64_t GetInt64OptionOrDefault( - const RepeatedPtrField<google::protobuf::Option>& options, - StringPiece option_name, int64_t default_value) { - const google::protobuf::Option* opt = FindOptionOrNull(options, option_name); - if (opt == nullptr) { - return default_value; - } - return GetInt64FromAny(opt->value()); -} - -double GetDoubleOptionOrDefault( - const RepeatedPtrField<google::protobuf::Option>& options, - StringPiece option_name, double default_value) { - const google::protobuf::Option* opt = FindOptionOrNull(options, option_name); - if (opt == nullptr) { - return default_value; - } - return GetDoubleFromAny(opt->value()); -} - -std::string GetStringOptionOrDefault( - const RepeatedPtrField<google::protobuf::Option>& options, - StringPiece option_name, StringPiece default_value) { - const google::protobuf::Option* opt = FindOptionOrNull(options, option_name); - if (opt == nullptr) { - return std::string(default_value); - } - return GetStringFromAny(opt->value()); -} - -template <typename T> -void ParseFromAny(const std::string& data, T* result) { - result->ParseFromString(data); -} - -// Returns a boolean value contained in Any type. -// TODO(skarvaje): Add type checking & error messages here. -bool GetBoolFromAny(const google::protobuf::Any& any) { - google::protobuf::BoolValue b; - ParseFromAny(any.value(), &b); - return b.value(); -} - -int64_t GetInt64FromAny(const google::protobuf::Any& any) { - google::protobuf::Int64Value i; - ParseFromAny(any.value(), &i); - return i.value(); -} - -double GetDoubleFromAny(const google::protobuf::Any& any) { - google::protobuf::DoubleValue i; - ParseFromAny(any.value(), &i); - return i.value(); -} - -std::string GetStringFromAny(const google::protobuf::Any& any) { - google::protobuf::StringValue s; - ParseFromAny(any.value(), &s); - return s.value(); -} - -const StringPiece GetTypeWithoutUrl(StringPiece type_url) { - if (type_url.size() > kTypeUrlSize && type_url[kTypeUrlSize] == '/') { - return type_url.substr(kTypeUrlSize + 1); - } else { - size_t idx = type_url.rfind('/'); - if (idx != type_url.npos) { - type_url.remove_prefix(idx + 1); - } - return type_url; - } -} - -const std::string GetFullTypeWithUrl(StringPiece simple_type) { - return StrCat(kTypeServiceBaseUrl, "/", simple_type); -} - -const google::protobuf::Option* FindOptionOrNull( - const RepeatedPtrField<google::protobuf::Option>& options, - StringPiece option_name) { - for (int i = 0; i < options.size(); ++i) { - const google::protobuf::Option& opt = options.Get(i); - if (opt.name() == option_name) { - return &opt; - } - } - return nullptr; -} - -const google::protobuf::Field* FindFieldInTypeOrNull( - const google::protobuf::Type* type, StringPiece field_name) { - if (type != nullptr) { - for (int i = 0; i < type->fields_size(); ++i) { - const google::protobuf::Field& field = type->fields(i); - if (field.name() == field_name) { - return &field; - } - } - } - return nullptr; -} - -const google::protobuf::Field* FindJsonFieldInTypeOrNull( - const google::protobuf::Type* type, StringPiece json_name) { - if (type != nullptr) { - for (int i = 0; i < type->fields_size(); ++i) { - const google::protobuf::Field& field = type->fields(i); - if (field.json_name() == json_name) { - return &field; - } - } - } - return nullptr; -} - -const google::protobuf::Field* FindFieldInTypeByNumberOrNull( - const google::protobuf::Type* type, int32_t number) { - if (type != nullptr) { - for (int i = 0; i < type->fields_size(); ++i) { - const google::protobuf::Field& field = type->fields(i); - if (field.number() == number) { - return &field; - } - } - } - return nullptr; -} - -const google::protobuf::EnumValue* FindEnumValueByNameOrNull( - const google::protobuf::Enum* enum_type, StringPiece enum_name) { - if (enum_type != nullptr) { - for (int i = 0; i < enum_type->enumvalue_size(); ++i) { - const google::protobuf::EnumValue& enum_value = enum_type->enumvalue(i); - if (enum_value.name() == enum_name) { - return &enum_value; - } - } - } - return nullptr; -} - -const google::protobuf::EnumValue* FindEnumValueByNumberOrNull( - const google::protobuf::Enum* enum_type, int32_t value) { - if (enum_type != nullptr) { - for (int i = 0; i < enum_type->enumvalue_size(); ++i) { - const google::protobuf::EnumValue& enum_value = enum_type->enumvalue(i); - if (enum_value.number() == value) { - return &enum_value; - } - } - } - return nullptr; -} - -const google::protobuf::EnumValue* FindEnumValueByNameWithoutUnderscoreOrNull( - const google::protobuf::Enum* enum_type, StringPiece enum_name) { - if (enum_type != nullptr) { - for (int i = 0; i < enum_type->enumvalue_size(); ++i) { - const google::protobuf::EnumValue& enum_value = enum_type->enumvalue(i); - std::string enum_name_without_underscore = enum_value.name(); - - // Remove underscore from the name. - enum_name_without_underscore.erase( - std::remove(enum_name_without_underscore.begin(), - enum_name_without_underscore.end(), '_'), - enum_name_without_underscore.end()); - // Make the name uppercase. - for (std::string::iterator it = enum_name_without_underscore.begin(); - it != enum_name_without_underscore.end(); ++it) { - *it = ascii_toupper(*it); - } - - if (enum_name_without_underscore == enum_name) { - return &enum_value; - } - } - } - return nullptr; -} - -std::string EnumValueNameToLowerCamelCase(StringPiece input) { - std::string input_string(input); - std::transform(input_string.begin(), input_string.end(), input_string.begin(), - ::tolower); - return ToCamelCase(input_string); -} - -std::string ToCamelCase(StringPiece input) { - bool capitalize_next = false; - bool was_cap = true; - bool is_cap = false; - bool first_word = true; - std::string result; - result.reserve(input.size()); - - for (size_t i = 0; i < input.size(); ++i, was_cap = is_cap) { - is_cap = ascii_isupper(input[i]); - if (input[i] == '_') { - capitalize_next = true; - if (!result.empty()) first_word = false; - continue; - } else if (first_word) { - // Consider when the current character B is capitalized, - // first word ends when: - // 1) following a lowercase: "...aB..." - // 2) followed by a lowercase: "...ABc..." - if (!result.empty() && is_cap && - (!was_cap || - (i + 1 < input.size() && ascii_islower(input[i + 1])))) { - first_word = false; - result.push_back(input[i]); - } else { - result.push_back(ascii_tolower(input[i])); - continue; - } - } else if (capitalize_next) { - capitalize_next = false; - if (ascii_islower(input[i])) { - result.push_back(ascii_toupper(input[i])); - continue; - } else { - result.push_back(input[i]); - continue; - } - } else { - result.push_back(ascii_tolower(input[i])); - } - } - return result; -} - -std::string ToSnakeCase(StringPiece input) { - bool was_not_underscore = false; // Initialize to false for case 1 (below) - bool was_not_cap = false; - std::string result; - result.reserve(input.size() << 1); - - for (size_t i = 0; i < input.size(); ++i) { - if (ascii_isupper(input[i])) { - // Consider when the current character B is capitalized: - // 1) At beginning of input: "B..." => "b..." - // (e.g. "Biscuit" => "biscuit") - // 2) Following a lowercase: "...aB..." => "...a_b..." - // (e.g. "gBike" => "g_bike") - // 3) At the end of input: "...AB" => "...ab" - // (e.g. "GoogleLAB" => "google_lab") - // 4) Followed by a lowercase: "...ABc..." => "...a_bc..." - // (e.g. "GBike" => "g_bike") - if (was_not_underscore && // case 1 out - (was_not_cap || // case 2 in, case 3 out - (i + 1 < input.size() && // case 3 out - ascii_islower(input[i + 1])))) { // case 4 in - // We add an underscore for case 2 and case 4. - result.push_back('_'); - } - result.push_back(ascii_tolower(input[i])); - was_not_underscore = true; - was_not_cap = false; - } else { - result.push_back(input[i]); - was_not_underscore = input[i] != '_'; - was_not_cap = true; - } - } - return result; -} - -std::set<std::string>* well_known_types_ = nullptr; -PROTOBUF_NAMESPACE_ID::internal::once_flag well_known_types_init_; -const char* well_known_types_name_array_[] = { - "google.protobuf.Timestamp", "google.protobuf.Duration", - "google.protobuf.DoubleValue", "google.protobuf.FloatValue", - "google.protobuf.Int64Value", "google.protobuf.UInt64Value", - "google.protobuf.Int32Value", "google.protobuf.UInt32Value", - "google.protobuf.BoolValue", "google.protobuf.StringValue", - "google.protobuf.BytesValue", "google.protobuf.FieldMask"}; - -void DeleteWellKnownTypes() { delete well_known_types_; } - -void InitWellKnownTypes() { - well_known_types_ = new std::set<std::string>; - for (int i = 0; i < GOOGLE_ARRAYSIZE(well_known_types_name_array_); ++i) { - well_known_types_->insert(well_known_types_name_array_[i]); - } - google::protobuf::internal::OnShutdown(&DeleteWellKnownTypes); -} - -bool IsWellKnownType(const std::string& type_name) { - PROTOBUF_NAMESPACE_ID::internal::call_once(well_known_types_init_, - InitWellKnownTypes); - return ContainsKey(*well_known_types_, type_name); -} - -bool IsValidBoolString(StringPiece bool_string) { - return bool_string == "true" || bool_string == "false" || - bool_string == "1" || bool_string == "0"; -} - -bool IsMap(const google::protobuf::Field& field, - const google::protobuf::Type& type) { - return field.cardinality() == google::protobuf::Field::CARDINALITY_REPEATED && - (GetBoolOptionOrDefault(type.options(), "map_entry", false) || - GetBoolOptionOrDefault(type.options(), - "google.protobuf.MessageOptions.map_entry", - false)); -} - -bool IsMessageSetWireFormat(const google::protobuf::Type& type) { - return GetBoolOptionOrDefault(type.options(), "message_set_wire_format", - false) || - GetBoolOptionOrDefault( - type.options(), - "google.protobuf.MessageOptions.message_set_wire_format", false); -} - -std::string DoubleAsString(double value) { - if (value == std::numeric_limits<double>::infinity()) return "Infinity"; - if (value == -std::numeric_limits<double>::infinity()) return "-Infinity"; - if (std::isnan(value)) return "NaN"; - - return SimpleDtoa(value); -} - -std::string FloatAsString(float value) { - if (std::isfinite(value)) return SimpleFtoa(value); - return DoubleAsString(value); -} - -bool SafeStrToFloat(StringPiece str, float* value) { - double double_value; - if (!safe_strtod(str, &double_value)) { - return false; - } - - if (std::isinf(double_value) || std::isnan(double_value)) return false; - - // Fail if the value is not representable in float. - if (double_value > std::numeric_limits<float>::max() || - double_value < -std::numeric_limits<float>::max()) { - return false; - } - - *value = static_cast<float>(double_value); - return true; -} - -} // namespace converter -} // namespace util -} // namespace protobuf -} // namespace google diff --git a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/utility.h b/contrib/libs/protobuf_std/src/google/protobuf/util/internal/utility.h deleted file mode 100644 index b689e8464b..0000000000 --- a/contrib/libs/protobuf_std/src/google/protobuf/util/internal/utility.h +++ /dev/null @@ -1,204 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_UTILITY_H__ -#define GOOGLE_PROTOBUF_UTIL_CONVERTER_UTILITY_H__ - -#include <cstdint> -#include <memory> -#include <string> -#include <utility> - -#include <google/protobuf/stubs/common.h> -#include <google/protobuf/stubs/logging.h> -#include <google/protobuf/any.pb.h> -#include <google/protobuf/type.pb.h> -#include <google/protobuf/repeated_field.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/stubs/statusor.h> -#include <google/protobuf/stubs/status.h> - -// Must be included last. -#include <google/protobuf/port_def.inc> - -namespace google { -namespace protobuf { -namespace util { -namespace converter { - -// Size of "type.googleapis.com" -static const int64_t kTypeUrlSize = 19; - -// Finds the tech option identified by option_name. Parses the boolean value and -// returns it. -// When the option with the given name is not found, default_value is returned. -PROTOBUF_EXPORT bool GetBoolOptionOrDefault( - const RepeatedPtrField<google::protobuf::Option>& options, - StringPiece option_name, bool default_value); - -// Returns int64 option value. If the option isn't found, returns the -// default_value. -PROTOBUF_EXPORT int64_t GetInt64OptionOrDefault( - const RepeatedPtrField<google::protobuf::Option>& options, - StringPiece option_name, int64_t default_value); - -// Returns double option value. If the option isn't found, returns the -// default_value. -PROTOBUF_EXPORT double GetDoubleOptionOrDefault( - const RepeatedPtrField<google::protobuf::Option>& options, - StringPiece option_name, double default_value); - -// Returns string option value. If the option isn't found, returns the -// default_value. -PROTOBUF_EXPORT std::string GetStringOptionOrDefault( - const RepeatedPtrField<google::protobuf::Option>& options, - StringPiece option_name, StringPiece default_value); - -// Returns a boolean value contained in Any type. -// TODO(skarvaje): Make these utilities dealing with Any types more generic, -// add more error checking and move to a more public/shareable location so -// others can use. -PROTOBUF_EXPORT bool GetBoolFromAny(const google::protobuf::Any& any); - -// Returns int64 value contained in Any type. -PROTOBUF_EXPORT int64_t GetInt64FromAny(const google::protobuf::Any& any); - -// Returns double value contained in Any type. -PROTOBUF_EXPORT double GetDoubleFromAny(const google::protobuf::Any& any); - -// Returns string value contained in Any type. -PROTOBUF_EXPORT std::string GetStringFromAny(const google::protobuf::Any& any); - -// Returns the type string without the url prefix. e.g.: If the passed type is -// 'type.googleapis.com/tech.type.Bool', the returned value is 'tech.type.Bool'. -PROTOBUF_EXPORT const StringPiece GetTypeWithoutUrl( - StringPiece type_url); - -// Returns the simple_type with the base type url (kTypeServiceBaseUrl) -// prefixed. -// -// E.g: -// GetFullTypeWithUrl("google.protobuf.Timestamp") returns the string -// "type.googleapis.com/google.protobuf.Timestamp". -PROTOBUF_EXPORT const std::string GetFullTypeWithUrl( - StringPiece simple_type); - -// Finds and returns option identified by name and option_name within the -// provided map. Returns nullptr if none found. -const google::protobuf::Option* FindOptionOrNull( - const RepeatedPtrField<google::protobuf::Option>& options, - StringPiece option_name); - -// Finds and returns the field identified by field_name in the passed tech Type -// object. Returns nullptr if none found. -const google::protobuf::Field* FindFieldInTypeOrNull( - const google::protobuf::Type* type, StringPiece field_name); - -// Similar to FindFieldInTypeOrNull, but this looks up fields with given -// json_name. -const google::protobuf::Field* FindJsonFieldInTypeOrNull( - const google::protobuf::Type* type, StringPiece json_name); - -// Similar to FindFieldInTypeOrNull, but this looks up fields by number. -const google::protobuf::Field* FindFieldInTypeByNumberOrNull( - const google::protobuf::Type* type, int32_t number); - -// Finds and returns the EnumValue identified by enum_name in the passed tech -// Enum object. Returns nullptr if none found. -const google::protobuf::EnumValue* FindEnumValueByNameOrNull( - const google::protobuf::Enum* enum_type, StringPiece enum_name); - -// Finds and returns the EnumValue identified by value in the passed tech -// Enum object. Returns nullptr if none found. -const google::protobuf::EnumValue* FindEnumValueByNumberOrNull( - const google::protobuf::Enum* enum_type, int32_t value); - -// Finds and returns the EnumValue identified by enum_name without underscore in -// the passed tech Enum object. Returns nullptr if none found. -// For Ex. if enum_name is ACTIONANDADVENTURE it can get accepted if -// EnumValue's name is action_and_adventure or ACTION_AND_ADVENTURE. -const google::protobuf::EnumValue* FindEnumValueByNameWithoutUnderscoreOrNull( - const google::protobuf::Enum* enum_type, StringPiece enum_name); - -// Converts input to camel-case and returns it. -PROTOBUF_EXPORT std::string ToCamelCase(const StringPiece input); - -// Converts enum name string to camel-case and returns it. -std::string EnumValueNameToLowerCamelCase(const StringPiece input); - -// Converts input to snake_case and returns it. -PROTOBUF_EXPORT std::string ToSnakeCase(StringPiece input); - -// Returns true if type_name represents a well-known type. -PROTOBUF_EXPORT bool IsWellKnownType(const std::string& type_name); - -// Returns true if 'bool_string' represents a valid boolean value. Only "true", -// "false", "0" and "1" are allowed. -PROTOBUF_EXPORT bool IsValidBoolString(StringPiece bool_string); - -// Returns true if "field" is a protobuf map field based on its type. -PROTOBUF_EXPORT bool IsMap(const google::protobuf::Field& field, - const google::protobuf::Type& type); - -// Returns true if the given type has special MessageSet wire format. -bool IsMessageSetWireFormat(const google::protobuf::Type& type); - -// Infinity/NaN-aware conversion to string. -PROTOBUF_EXPORT std::string DoubleAsString(double value); -PROTOBUF_EXPORT std::string FloatAsString(float value); - -// Convert from int32, int64, uint32, uint64, double or float to string. -template <typename T> -std::string ValueAsString(T value) { - return StrCat(value); -} - -template <> -inline std::string ValueAsString(float value) { - return FloatAsString(value); -} - -template <> -inline std::string ValueAsString(double value) { - return DoubleAsString(value); -} - -// Converts a string to float. Unlike safe_strtof, conversion will fail if the -// value fits into double but not float (e.g., DBL_MAX). -PROTOBUF_EXPORT bool SafeStrToFloat(StringPiece str, float* value); - -} // namespace converter -} // namespace util -} // namespace protobuf -} // namespace google - -#include <google/protobuf/port_undef.inc> - -#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_UTILITY_H__ diff --git a/contrib/libs/protobuf_std/src/google/protobuf/util/json_util.cc b/contrib/libs/protobuf_std/src/google/protobuf/util/json_util.cc deleted file mode 100644 index 3597f9e20b..0000000000 --- a/contrib/libs/protobuf_std/src/google/protobuf/util/json_util.cc +++ /dev/null @@ -1,282 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include <google/protobuf/util/json_util.h> - -#include <google/protobuf/stubs/common.h> -#include <google/protobuf/io/coded_stream.h> -#include <google/protobuf/io/zero_copy_stream.h> -#include <google/protobuf/stubs/once.h> -#include <google/protobuf/util/internal/default_value_objectwriter.h> -#include <google/protobuf/util/internal/error_listener.h> -#include <google/protobuf/util/internal/json_objectwriter.h> -#include <google/protobuf/util/internal/json_stream_parser.h> -#include <google/protobuf/util/internal/protostream_objectsource.h> -#include <google/protobuf/util/internal/protostream_objectwriter.h> -#include <google/protobuf/util/type_resolver.h> -#include <google/protobuf/util/type_resolver_util.h> -#include <google/protobuf/stubs/bytestream.h> -#include <google/protobuf/stubs/status.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/stubs/status_macros.h> - -// clang-format off -#include <google/protobuf/port_def.inc> -// clang-format on - -namespace google { -namespace protobuf { -namespace util { - -namespace internal { -ZeroCopyStreamByteSink::~ZeroCopyStreamByteSink() { - if (buffer_size_ > 0) { - stream_->BackUp(buffer_size_); - } -} - -void ZeroCopyStreamByteSink::Append(const char* bytes, size_t len) { - while (true) { - if (len <= buffer_size_) { - memcpy(buffer_, bytes, len); - buffer_ = static_cast<char*>(buffer_) + len; - buffer_size_ -= len; - return; - } - if (buffer_size_ > 0) { - memcpy(buffer_, bytes, buffer_size_); - bytes += buffer_size_; - len -= buffer_size_; - } - if (!stream_->Next(&buffer_, &buffer_size_)) { - // There isn't a way for ByteSink to report errors. - buffer_size_ = 0; - return; - } - } -} -} // namespace internal - -util::Status BinaryToJsonStream(TypeResolver* resolver, - const std::string& type_url, - io::ZeroCopyInputStream* binary_input, - io::ZeroCopyOutputStream* json_output, - const JsonPrintOptions& options) { - io::CodedInputStream in_stream(binary_input); - google::protobuf::Type type; - RETURN_IF_ERROR(resolver->ResolveMessageType(type_url, &type)); - converter::ProtoStreamObjectSource::RenderOptions render_options; - render_options.use_ints_for_enums = options.always_print_enums_as_ints; - render_options.preserve_proto_field_names = - options.preserve_proto_field_names; - converter::ProtoStreamObjectSource proto_source(&in_stream, resolver, type, - render_options); - io::CodedOutputStream out_stream(json_output); - converter::JsonObjectWriter json_writer(options.add_whitespace ? " " : "", - &out_stream); - if (options.always_print_primitive_fields) { - converter::DefaultValueObjectWriter default_value_writer(resolver, type, - &json_writer); - default_value_writer.set_preserve_proto_field_names( - options.preserve_proto_field_names); - default_value_writer.set_print_enums_as_ints( - options.always_print_enums_as_ints); - return proto_source.WriteTo(&default_value_writer); - } else { - return proto_source.WriteTo(&json_writer); - } -} - -util::Status BinaryToJsonString(TypeResolver* resolver, - const std::string& type_url, - const std::string& binary_input, - std::string* json_output, - const JsonPrintOptions& options) { - io::ArrayInputStream input_stream(binary_input.data(), binary_input.size()); - io::StringOutputStream output_stream(json_output); - return BinaryToJsonStream(resolver, type_url, &input_stream, &output_stream, - options); -} - -namespace { -class StatusErrorListener : public converter::ErrorListener { - public: - StatusErrorListener() {} - ~StatusErrorListener() override {} - - util::Status GetStatus() { return status_; } - - void InvalidName(const converter::LocationTrackerInterface& loc, - StringPiece unknown_name, - StringPiece message) override { - std::string loc_string = GetLocString(loc); - if (!loc_string.empty()) { - loc_string.append(" "); - } - status_ = util::InvalidArgumentError( - StrCat(loc_string, unknown_name, ": ", message)); - } - - void InvalidValue(const converter::LocationTrackerInterface& loc, - StringPiece type_name, - StringPiece value) override { - status_ = util::InvalidArgumentError( - StrCat(GetLocString(loc), ": invalid value ", std::string(value), - " for type ", std::string(type_name))); - } - - void MissingField(const converter::LocationTrackerInterface& loc, - StringPiece missing_name) override { - status_ = util::InvalidArgumentError(StrCat( - GetLocString(loc), ": missing field ", std::string(missing_name))); - } - - private: - util::Status status_; - - std::string GetLocString(const converter::LocationTrackerInterface& loc) { - std::string loc_string = loc.ToString(); - StripWhitespace(&loc_string); - if (!loc_string.empty()) { - loc_string = StrCat("(", loc_string, ")"); - } - return loc_string; - } - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StatusErrorListener); -}; -} // namespace - -util::Status JsonToBinaryStream(TypeResolver* resolver, - const std::string& type_url, - io::ZeroCopyInputStream* json_input, - io::ZeroCopyOutputStream* binary_output, - const JsonParseOptions& options) { - google::protobuf::Type type; - RETURN_IF_ERROR(resolver->ResolveMessageType(type_url, &type)); - internal::ZeroCopyStreamByteSink sink(binary_output); - StatusErrorListener listener; - converter::ProtoStreamObjectWriter::Options proto_writer_options; - proto_writer_options.ignore_unknown_fields = options.ignore_unknown_fields; - proto_writer_options.ignore_unknown_enum_values = - options.ignore_unknown_fields; - proto_writer_options.case_insensitive_enum_parsing = - options.case_insensitive_enum_parsing; - converter::ProtoStreamObjectWriter proto_writer( - resolver, type, &sink, &listener, proto_writer_options); - - converter::JsonStreamParser parser(&proto_writer); - const void* buffer; - int length; - while (json_input->Next(&buffer, &length)) { - if (length == 0) continue; - RETURN_IF_ERROR(parser.Parse( - StringPiece(static_cast<const char*>(buffer), length))); - } - RETURN_IF_ERROR(parser.FinishParse()); - - return listener.GetStatus(); -} - -util::Status JsonToBinaryString(TypeResolver* resolver, - const std::string& type_url, - StringPiece json_input, - std::string* binary_output, - const JsonParseOptions& options) { - io::ArrayInputStream input_stream(json_input.data(), json_input.size()); - io::StringOutputStream output_stream(binary_output); - return JsonToBinaryStream(resolver, type_url, &input_stream, &output_stream, - options); -} - -namespace { -const char* kTypeUrlPrefix = "type.googleapis.com"; -TypeResolver* generated_type_resolver_ = NULL; -PROTOBUF_NAMESPACE_ID::internal::once_flag generated_type_resolver_init_; - -std::string GetTypeUrl(const Message& message) { - return std::string(kTypeUrlPrefix) + "/" + - message.GetDescriptor()->full_name(); -} - -void DeleteGeneratedTypeResolver() { delete generated_type_resolver_; } - -void InitGeneratedTypeResolver() { - generated_type_resolver_ = NewTypeResolverForDescriptorPool( - kTypeUrlPrefix, DescriptorPool::generated_pool()); - ::google::protobuf::internal::OnShutdown(&DeleteGeneratedTypeResolver); -} - -TypeResolver* GetGeneratedTypeResolver() { - PROTOBUF_NAMESPACE_ID::internal::call_once(generated_type_resolver_init_, - InitGeneratedTypeResolver); - return generated_type_resolver_; -} -} // namespace - -util::Status MessageToJsonString(const Message& message, std::string* output, - const JsonOptions& options) { - const DescriptorPool* pool = message.GetDescriptor()->file()->pool(); - TypeResolver* resolver = - pool == DescriptorPool::generated_pool() - ? GetGeneratedTypeResolver() - : NewTypeResolverForDescriptorPool(kTypeUrlPrefix, pool); - util::Status result = - BinaryToJsonString(resolver, GetTypeUrl(message), - message.SerializeAsString(), output, options); - if (pool != DescriptorPool::generated_pool()) { - delete resolver; - } - return result; -} - -util::Status JsonStringToMessage(StringPiece input, Message* message, - const JsonParseOptions& options) { - const DescriptorPool* pool = message->GetDescriptor()->file()->pool(); - TypeResolver* resolver = - pool == DescriptorPool::generated_pool() - ? GetGeneratedTypeResolver() - : NewTypeResolverForDescriptorPool(kTypeUrlPrefix, pool); - std::string binary; - util::Status result = JsonToBinaryString(resolver, GetTypeUrl(*message), - input, &binary, options); - if (result.ok() && !message->ParseFromString(binary)) { - result = util::InvalidArgumentError( - "JSON transcoder produced invalid protobuf output."); - } - if (pool != DescriptorPool::generated_pool()) { - delete resolver; - } - return result; -} - -} // namespace util -} // namespace protobuf -} // namespace google diff --git a/contrib/libs/protobuf_std/src/google/protobuf/util/json_util.h b/contrib/libs/protobuf_std/src/google/protobuf/util/json_util.h deleted file mode 100644 index 73f27837b7..0000000000 --- a/contrib/libs/protobuf_std/src/google/protobuf/util/json_util.h +++ /dev/null @@ -1,204 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// 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__ diff --git a/contrib/libs/protobuf_std/src/google/protobuf/util/message_differencer.cc b/contrib/libs/protobuf_std/src/google/protobuf/util/message_differencer.cc deleted file mode 100644 index 6d7f2f977e..0000000000 --- a/contrib/libs/protobuf_std/src/google/protobuf/util/message_differencer.cc +++ /dev/null @@ -1,2219 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: jschorr@google.com (Joseph Schorr) -// Based on original Protocol Buffers design by -// Sanjay Ghemawat, Jeff Dean, and others. - -#include <google/protobuf/util/message_differencer.h> - -#include <algorithm> -#include <cstddef> -#include <cstdint> -#include <functional> -#include <limits> -#include <memory> -#include <utility> - -#include <google/protobuf/stubs/logging.h> -#include <google/protobuf/stubs/common.h> -#include <google/protobuf/stubs/stringprintf.h> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/io/zero_copy_stream.h> -#include <google/protobuf/io/zero_copy_stream_impl.h> -#include <google/protobuf/descriptor.pb.h> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/dynamic_message.h> -#include <google/protobuf/generated_enum_reflection.h> -#include <google/protobuf/map_field.h> -#include <google/protobuf/message.h> -#include <google/protobuf/text_format.h> -#include <google/protobuf/util/field_comparator.h> -#include <google/protobuf/stubs/strutil.h> - -// Always include as last one, otherwise it can break compilation -#include <google/protobuf/port_def.inc> - -namespace google { -namespace protobuf { - -namespace util { - -// A reporter to report the total number of diffs. -// TODO(ykzhu): we can improve this to take into account the value differencers. -class NumDiffsReporter : public google::protobuf::util::MessageDifferencer::Reporter { - public: - NumDiffsReporter() : num_diffs_(0) {} - - // Returns the total number of diffs. - int32_t GetNumDiffs() const { return num_diffs_; } - void Reset() { num_diffs_ = 0; } - - // Report that a field has been added into Message2. - void ReportAdded( - const google::protobuf::Message& message1, const google::protobuf::Message& message2, - const std::vector<google::protobuf::util::MessageDifferencer::SpecificField>& - field_path) override { - ++num_diffs_; - } - - // Report that a field has been deleted from Message1. - void ReportDeleted( - const google::protobuf::Message& message1, const google::protobuf::Message& message2, - const std::vector<google::protobuf::util::MessageDifferencer::SpecificField>& - field_path) override { - ++num_diffs_; - } - - // Report that the value of a field has been modified. - void ReportModified( - const google::protobuf::Message& message1, const google::protobuf::Message& message2, - const std::vector<google::protobuf::util::MessageDifferencer::SpecificField>& - field_path) override { - ++num_diffs_; - } - - private: - int32_t num_diffs_; -}; - -// When comparing a repeated field as map, MultipleFieldMapKeyComparator can -// be used to specify multiple fields as key for key comparison. -// Two elements of a repeated field will be regarded as having the same key -// iff they have the same value for every specified key field. -// Note that you can also specify only one field as key. -class MessageDifferencer::MultipleFieldsMapKeyComparator - : public MessageDifferencer::MapKeyComparator { - public: - MultipleFieldsMapKeyComparator( - MessageDifferencer* message_differencer, - const std::vector<std::vector<const FieldDescriptor*> >& key_field_paths) - : message_differencer_(message_differencer), - key_field_paths_(key_field_paths) { - GOOGLE_CHECK(!key_field_paths_.empty()); - for (const auto& path : key_field_paths_) { - GOOGLE_CHECK(!path.empty()); - } - } - MultipleFieldsMapKeyComparator(MessageDifferencer* message_differencer, - const FieldDescriptor* key) - : message_differencer_(message_differencer) { - std::vector<const FieldDescriptor*> key_field_path; - key_field_path.push_back(key); - key_field_paths_.push_back(key_field_path); - } - bool IsMatch(const Message& message1, const Message& message2, - const std::vector<SpecificField>& parent_fields) const override { - for (const auto& path : key_field_paths_) { - if (!IsMatchInternal(message1, message2, parent_fields, path, 0)) { - return false; - } - } - return true; - } - - private: - bool IsMatchInternal( - const Message& message1, const Message& message2, - const std::vector<SpecificField>& parent_fields, - const std::vector<const FieldDescriptor*>& key_field_path, - int path_index) const { - const FieldDescriptor* field = key_field_path[path_index]; - std::vector<SpecificField> current_parent_fields(parent_fields); - if (path_index == static_cast<int64_t>(key_field_path.size() - 1)) { - if (field->is_map()) { - return message_differencer_->CompareMapField(message1, message2, field, - ¤t_parent_fields); - } else if (field->is_repeated()) { - return message_differencer_->CompareRepeatedField( - message1, message2, field, ¤t_parent_fields); - } else { - return message_differencer_->CompareFieldValueUsingParentFields( - message1, message2, field, -1, -1, ¤t_parent_fields); - } - } else { - const Reflection* reflection1 = message1.GetReflection(); - const Reflection* reflection2 = message2.GetReflection(); - bool has_field1 = reflection1->HasField(message1, field); - bool has_field2 = reflection2->HasField(message2, field); - if (!has_field1 && !has_field2) { - return true; - } - if (has_field1 != has_field2) { - return false; - } - SpecificField specific_field; - specific_field.field = field; - current_parent_fields.push_back(specific_field); - return IsMatchInternal(reflection1->GetMessage(message1, field), - reflection2->GetMessage(message2, field), - current_parent_fields, key_field_path, - path_index + 1); - } - } - MessageDifferencer* message_differencer_; - std::vector<std::vector<const FieldDescriptor*> > key_field_paths_; - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MultipleFieldsMapKeyComparator); -}; - -// Preserve the order when treating repeated field as SMART_LIST. The current -// implementation is to find the longest matching sequence from the first -// element. The optimal solution requires to use //util/diff/lcs.h, which is -// not open sourced yet. Overwrite this method if you want to have that. -// TODO(ykzhu): change to use LCS once it is open sourced. -void MatchIndicesPostProcessorForSmartList(std::vector<int>* match_list1, - std::vector<int>* match_list2) { - int last_matched_index = -1; - for (size_t i = 0; i < match_list1->size(); ++i) { - if (match_list1->at(i) < 0) { - continue; - } - if (last_matched_index < 0 || match_list1->at(i) > last_matched_index) { - last_matched_index = match_list1->at(i); - } else { - match_list2->at(match_list1->at(i)) = -1; - match_list1->at(i) = -1; - } - } -} - -void AddSpecificIndex( - google::protobuf::util::MessageDifferencer::SpecificField* specific_field, - const Message& message, const FieldDescriptor* field, int index) { - if (field->is_map()) { - const Reflection* reflection = message.GetReflection(); - specific_field->map_entry1 = - &reflection->GetRepeatedMessage(message, field, index); - } - specific_field->index = index; -} - -void AddSpecificNewIndex( - google::protobuf::util::MessageDifferencer::SpecificField* specific_field, - const Message& message, const FieldDescriptor* field, int index) { - if (field->is_map()) { - const Reflection* reflection = message.GetReflection(); - specific_field->map_entry2 = - &reflection->GetRepeatedMessage(message, field, index); - } - specific_field->new_index = index; -} - -MessageDifferencer::MapEntryKeyComparator::MapEntryKeyComparator( - MessageDifferencer* message_differencer) - : message_differencer_(message_differencer) {} - -bool MessageDifferencer::MapEntryKeyComparator::IsMatch( - const Message& message1, const Message& message2, - const std::vector<SpecificField>& parent_fields) const { - // Map entry has its key in the field with tag 1. See the comment for - // map_entry in MessageOptions. - const FieldDescriptor* key = message1.GetDescriptor()->FindFieldByNumber(1); - // If key is not present in message1 and we're doing partial comparison or if - // map key is explicitly ignored treat the field as set instead, - const bool treat_as_set = - (message_differencer_->scope() == PARTIAL && - !message1.GetReflection()->HasField(message1, key)) || - message_differencer_->IsIgnored(message1, message2, key, parent_fields); - - std::vector<SpecificField> current_parent_fields(parent_fields); - if (treat_as_set) { - return message_differencer_->Compare(message1, message2, - ¤t_parent_fields); - } - return message_differencer_->CompareFieldValueUsingParentFields( - message1, message2, key, -1, -1, ¤t_parent_fields); -} - -bool MessageDifferencer::Equals(const Message& message1, - const Message& message2) { - MessageDifferencer differencer; - - return differencer.Compare(message1, message2); -} - -bool MessageDifferencer::Equivalent(const Message& message1, - const Message& message2) { - MessageDifferencer differencer; - differencer.set_message_field_comparison(MessageDifferencer::EQUIVALENT); - - return differencer.Compare(message1, message2); -} - -bool MessageDifferencer::ApproximatelyEquals(const Message& message1, - const Message& message2) { - MessageDifferencer differencer; - differencer.set_float_comparison(MessageDifferencer::APPROXIMATE); - - return differencer.Compare(message1, message2); -} - -bool MessageDifferencer::ApproximatelyEquivalent(const Message& message1, - const Message& message2) { - MessageDifferencer differencer; - differencer.set_message_field_comparison(MessageDifferencer::EQUIVALENT); - differencer.set_float_comparison(MessageDifferencer::APPROXIMATE); - - return differencer.Compare(message1, message2); -} - -// =========================================================================== - -MessageDifferencer::MessageDifferencer() - : reporter_(NULL), - message_field_comparison_(EQUAL), - scope_(FULL), - repeated_field_comparison_(AS_LIST), - map_entry_key_comparator_(this), - report_matches_(false), - report_moves_(true), - report_ignores_(true), - output_string_(nullptr), - match_indices_for_smart_list_callback_( - MatchIndicesPostProcessorForSmartList) {} - -MessageDifferencer::~MessageDifferencer() { - for (MapKeyComparator* comparator : owned_key_comparators_) { - delete comparator; - } - for (IgnoreCriteria* criteria : ignore_criteria_) { - delete criteria; - } -} - -void MessageDifferencer::set_field_comparator(FieldComparator* comparator) { - GOOGLE_CHECK(comparator) << "Field comparator can't be NULL."; - field_comparator_kind_ = kFCBase; - field_comparator_.base = comparator; -} - -#ifdef PROTOBUF_FUTURE_BREAKING_CHANGES -void MessageDifferencer::set_field_comparator( - DefaultFieldComparator* comparator) { - GOOGLE_CHECK(comparator) << "Field comparator can't be NULL."; - field_comparator_kind_ = kFCDefault; - field_comparator_.default_impl = comparator; -} -#endif // PROTOBUF_FUTURE_BREAKING_CHANGES - -void MessageDifferencer::set_message_field_comparison( - MessageFieldComparison comparison) { - message_field_comparison_ = comparison; -} - -void MessageDifferencer::set_scope(Scope scope) { scope_ = scope; } - -MessageDifferencer::Scope MessageDifferencer::scope() { return scope_; } - -void MessageDifferencer::set_float_comparison(FloatComparison comparison) { - default_field_comparator_.set_float_comparison( - comparison == EXACT ? DefaultFieldComparator::EXACT - : DefaultFieldComparator::APPROXIMATE); -} - -void MessageDifferencer::set_repeated_field_comparison( - RepeatedFieldComparison comparison) { - repeated_field_comparison_ = comparison; -} - -MessageDifferencer::RepeatedFieldComparison -MessageDifferencer::repeated_field_comparison() { - return repeated_field_comparison_; -} - -void MessageDifferencer::CheckRepeatedFieldComparisons( - const FieldDescriptor* field, - const RepeatedFieldComparison& new_comparison) { - GOOGLE_CHECK(field->is_repeated()) - << "Field must be repeated: " << field->full_name(); - const MapKeyComparator* key_comparator = GetMapKeyComparator(field); - GOOGLE_CHECK(key_comparator == NULL) - << "Cannot treat this repeated field as both MAP and " << new_comparison - << " for comparison. Field name is: " << field->full_name(); -} - -void MessageDifferencer::TreatAsSet(const FieldDescriptor* field) { - CheckRepeatedFieldComparisons(field, AS_SET); - repeated_field_comparisons_[field] = AS_SET; -} - -void MessageDifferencer::TreatAsSmartSet(const FieldDescriptor* field) { - CheckRepeatedFieldComparisons(field, AS_SMART_SET); - repeated_field_comparisons_[field] = AS_SMART_SET; -} - -void MessageDifferencer::SetMatchIndicesForSmartListCallback( - std::function<void(std::vector<int>*, std::vector<int>*)> callback) { - match_indices_for_smart_list_callback_ = callback; -} - -void MessageDifferencer::TreatAsList(const FieldDescriptor* field) { - CheckRepeatedFieldComparisons(field, AS_LIST); - repeated_field_comparisons_[field] = AS_LIST; -} - -void MessageDifferencer::TreatAsSmartList(const FieldDescriptor* field) { - CheckRepeatedFieldComparisons(field, AS_SMART_LIST); - repeated_field_comparisons_[field] = AS_SMART_LIST; -} - -void MessageDifferencer::TreatAsMap(const FieldDescriptor* field, - const FieldDescriptor* key) { - GOOGLE_CHECK_EQ(FieldDescriptor::CPPTYPE_MESSAGE, field->cpp_type()) - << "Field has to be message type. Field name is: " << field->full_name(); - GOOGLE_CHECK(key->containing_type() == field->message_type()) - << key->full_name() - << " must be a direct subfield within the repeated field " - << field->full_name() << ", not " << key->containing_type()->full_name(); - GOOGLE_CHECK(repeated_field_comparisons_.find(field) == - repeated_field_comparisons_.end()) - << "Cannot treat the same field as both " - << repeated_field_comparisons_[field] - << " and MAP. Field name is: " << field->full_name(); - MapKeyComparator* key_comparator = - new MultipleFieldsMapKeyComparator(this, key); - owned_key_comparators_.push_back(key_comparator); - map_field_key_comparator_[field] = key_comparator; -} - -void MessageDifferencer::TreatAsMapWithMultipleFieldsAsKey( - const FieldDescriptor* field, - const std::vector<const FieldDescriptor*>& key_fields) { - std::vector<std::vector<const FieldDescriptor*> > key_field_paths; - for (const FieldDescriptor* key_filed : key_fields) { - std::vector<const FieldDescriptor*> key_field_path; - key_field_path.push_back(key_filed); - key_field_paths.push_back(key_field_path); - } - TreatAsMapWithMultipleFieldPathsAsKey(field, key_field_paths); -} - -void MessageDifferencer::TreatAsMapWithMultipleFieldPathsAsKey( - const FieldDescriptor* field, - const std::vector<std::vector<const FieldDescriptor*> >& key_field_paths) { - GOOGLE_CHECK(field->is_repeated()) - << "Field must be repeated: " << field->full_name(); - GOOGLE_CHECK_EQ(FieldDescriptor::CPPTYPE_MESSAGE, field->cpp_type()) - << "Field has to be message type. Field name is: " << field->full_name(); - for (const auto& key_field_path : key_field_paths) { - for (size_t j = 0; j < key_field_path.size(); ++j) { - const FieldDescriptor* parent_field = - j == 0 ? field : key_field_path[j - 1]; - const FieldDescriptor* child_field = key_field_path[j]; - GOOGLE_CHECK(child_field->containing_type() == parent_field->message_type()) - << child_field->full_name() - << " must be a direct subfield within the field: " - << parent_field->full_name(); - if (j != 0) { - GOOGLE_CHECK_EQ(FieldDescriptor::CPPTYPE_MESSAGE, parent_field->cpp_type()) - << parent_field->full_name() << " has to be of type message."; - GOOGLE_CHECK(!parent_field->is_repeated()) - << parent_field->full_name() << " cannot be a repeated field."; - } - } - } - GOOGLE_CHECK(repeated_field_comparisons_.find(field) == - repeated_field_comparisons_.end()) - << "Cannot treat the same field as both " - << repeated_field_comparisons_[field] - << " and MAP. Field name is: " << field->full_name(); - MapKeyComparator* key_comparator = - new MultipleFieldsMapKeyComparator(this, key_field_paths); - owned_key_comparators_.push_back(key_comparator); - map_field_key_comparator_[field] = key_comparator; -} - -void MessageDifferencer::TreatAsMapUsingKeyComparator( - const FieldDescriptor* field, const MapKeyComparator* key_comparator) { - GOOGLE_CHECK(field->is_repeated()) - << "Field must be repeated: " << field->full_name(); - GOOGLE_CHECK(repeated_field_comparisons_.find(field) == - repeated_field_comparisons_.end()) - << "Cannot treat the same field as both " - << repeated_field_comparisons_[field] - << " and MAP. Field name is: " << field->full_name(); - map_field_key_comparator_[field] = key_comparator; -} - -void MessageDifferencer::AddIgnoreCriteria(IgnoreCriteria* ignore_criteria) { - ignore_criteria_.push_back(ignore_criteria); -} - -void MessageDifferencer::IgnoreField(const FieldDescriptor* field) { - ignored_fields_.insert(field); -} - -void MessageDifferencer::SetFractionAndMargin(const FieldDescriptor* field, - double fraction, double margin) { - default_field_comparator_.SetFractionAndMargin(field, fraction, margin); -} - -void MessageDifferencer::ReportDifferencesToString(std::string* output) { - GOOGLE_DCHECK(output) << "Specified output string was NULL"; - - output_string_ = output; - output_string_->clear(); -} - -void MessageDifferencer::ReportDifferencesTo(Reporter* reporter) { - // If an output string is set, clear it to prevent - // it superseding the specified reporter. - if (output_string_) { - output_string_ = NULL; - } - - reporter_ = reporter; -} - -bool MessageDifferencer::FieldBefore(const FieldDescriptor* field1, - const FieldDescriptor* field2) { - // Handle sentinel values (i.e. make sure NULLs are always ordered - // at the end of the list). - if (field1 == NULL) { - return false; - } - - if (field2 == NULL) { - return true; - } - - // Always order fields by their tag number - return (field1->number() < field2->number()); -} - -bool MessageDifferencer::Compare(const Message& message1, - const Message& message2) { - std::vector<SpecificField> parent_fields; - - bool result = false; - // Setup the internal reporter if need be. - if (output_string_) { - io::StringOutputStream output_stream(output_string_); - StreamReporter reporter(&output_stream); - reporter.SetMessages(message1, message2); - reporter_ = &reporter; - result = Compare(message1, message2, &parent_fields); - reporter_ = NULL; - } else { - result = Compare(message1, message2, &parent_fields); - } - return result; -} - -bool MessageDifferencer::CompareWithFields( - const Message& message1, const Message& message2, - const std::vector<const FieldDescriptor*>& message1_fields_arg, - const std::vector<const FieldDescriptor*>& message2_fields_arg) { - if (message1.GetDescriptor() != message2.GetDescriptor()) { - GOOGLE_LOG(DFATAL) << "Comparison between two messages with different " - << "descriptors."; - return false; - } - - std::vector<SpecificField> parent_fields; - - bool result = false; - - FieldDescriptorArray message1_fields(message1_fields_arg.size() + 1); - FieldDescriptorArray message2_fields(message2_fields_arg.size() + 1); - - std::copy(message1_fields_arg.cbegin(), message1_fields_arg.cend(), - message1_fields.begin()); - std::copy(message2_fields_arg.cbegin(), message2_fields_arg.cend(), - message2_fields.begin()); - - // Append sentinel values. - message1_fields[message1_fields_arg.size()] = nullptr; - message2_fields[message2_fields_arg.size()] = nullptr; - - std::sort(message1_fields.begin(), message1_fields.end(), FieldBefore); - std::sort(message2_fields.begin(), message2_fields.end(), FieldBefore); - - // Setup the internal reporter if need be. - if (output_string_) { - io::StringOutputStream output_stream(output_string_); - StreamReporter reporter(&output_stream); - reporter_ = &reporter; - result = CompareRequestedFieldsUsingSettings( - message1, message2, message1_fields, message2_fields, &parent_fields); - reporter_ = NULL; - } else { - result = CompareRequestedFieldsUsingSettings( - message1, message2, message1_fields, message2_fields, &parent_fields); - } - - return result; -} - -bool MessageDifferencer::Compare(const Message& message1, - const Message& message2, - std::vector<SpecificField>* parent_fields) { - const Descriptor* descriptor1 = message1.GetDescriptor(); - const Descriptor* descriptor2 = message2.GetDescriptor(); - if (descriptor1 != descriptor2) { - GOOGLE_LOG(DFATAL) << "Comparison between two messages with different " - << "descriptors. " << descriptor1->full_name() << " vs " - << descriptor2->full_name(); - return false; - } - - // Expand google.protobuf.Any payload if possible. - if (descriptor1->full_name() == internal::kAnyFullTypeName) { - std::unique_ptr<Message> data1; - std::unique_ptr<Message> data2; - if (unpack_any_field_.UnpackAny(message1, &data1) && - unpack_any_field_.UnpackAny(message2, &data2)) { - // Avoid DFATAL for different descriptors in google.protobuf.Any payloads. - if (data1->GetDescriptor() != data2->GetDescriptor()) { - return false; - } - return Compare(*data1, *data2, parent_fields); - } - } - const Reflection* reflection1 = message1.GetReflection(); - const Reflection* reflection2 = message2.GetReflection(); - - bool unknown_compare_result = true; - // Ignore unknown fields in EQUIVALENT mode - if (message_field_comparison_ != EQUIVALENT) { - const UnknownFieldSet& unknown_field_set1 = - reflection1->GetUnknownFields(message1); - const UnknownFieldSet& unknown_field_set2 = - reflection2->GetUnknownFields(message2); - if (!CompareUnknownFields(message1, message2, unknown_field_set1, - unknown_field_set2, parent_fields)) { - if (reporter_ == NULL) { - return false; - } - unknown_compare_result = false; - } - } - - FieldDescriptorArray message1_fields = RetrieveFields(message1, true); - FieldDescriptorArray message2_fields = RetrieveFields(message2, false); - - return CompareRequestedFieldsUsingSettings(message1, message2, - message1_fields, message2_fields, - parent_fields) && - unknown_compare_result; -} - -FieldDescriptorArray MessageDifferencer::RetrieveFields(const Message& message, - bool base_message) { - const Descriptor* descriptor = message.GetDescriptor(); - - tmp_message_fields_.clear(); - tmp_message_fields_.reserve(descriptor->field_count() + 1); - - const Reflection* reflection = message.GetReflection(); - if (descriptor->options().map_entry()) { - if (this->scope_ == PARTIAL && base_message) { - reflection->ListFields(message, &tmp_message_fields_); - } else { - // Map entry fields are always considered present. - for (int i = 0; i < descriptor->field_count(); i++) { - tmp_message_fields_.push_back(descriptor->field(i)); - } - } - } else { - reflection->ListFields(message, &tmp_message_fields_); - } - // Add sentinel values to deal with the - // case where the number of the fields in - // each list are different. - tmp_message_fields_.push_back(nullptr); - - FieldDescriptorArray message_fields(tmp_message_fields_.begin(), - tmp_message_fields_.end()); - - return message_fields; -} - -bool MessageDifferencer::CompareRequestedFieldsUsingSettings( - const Message& message1, const Message& message2, - const FieldDescriptorArray& message1_fields, - const FieldDescriptorArray& message2_fields, - std::vector<SpecificField>* parent_fields) { - if (scope_ == FULL) { - if (message_field_comparison_ == EQUIVALENT) { - // We need to merge the field lists of both messages (i.e. - // we are merely checking for a difference in field values, - // rather than the addition or deletion of fields). - FieldDescriptorArray fields_union = - CombineFields(message1_fields, FULL, message2_fields, FULL); - return CompareWithFieldsInternal(message1, message2, fields_union, - fields_union, parent_fields); - } else { - // Simple equality comparison, use the unaltered field lists. - return CompareWithFieldsInternal(message1, message2, message1_fields, - message2_fields, parent_fields); - } - } else { - if (message_field_comparison_ == EQUIVALENT) { - // We use the list of fields for message1 for both messages when - // comparing. This way, extra fields in message2 are ignored, - // and missing fields in message2 use their default value. - return CompareWithFieldsInternal(message1, message2, message1_fields, - message1_fields, parent_fields); - } else { - // We need to consider the full list of fields for message1 - // but only the intersection for message2. This way, any fields - // only present in message2 will be ignored, but any fields only - // present in message1 will be marked as a difference. - FieldDescriptorArray fields_intersection = - CombineFields(message1_fields, PARTIAL, message2_fields, PARTIAL); - return CompareWithFieldsInternal(message1, message2, message1_fields, - fields_intersection, parent_fields); - } - } -} - -FieldDescriptorArray MessageDifferencer::CombineFields( - const FieldDescriptorArray& fields1, Scope fields1_scope, - const FieldDescriptorArray& fields2, Scope fields2_scope) { - size_t index1 = 0; - size_t index2 = 0; - - tmp_message_fields_.clear(); - - while (index1 < fields1.size() && index2 < fields2.size()) { - const FieldDescriptor* field1 = fields1[index1]; - const FieldDescriptor* field2 = fields2[index2]; - - if (FieldBefore(field1, field2)) { - if (fields1_scope == FULL) { - tmp_message_fields_.push_back(fields1[index1]); - } - ++index1; - } else if (FieldBefore(field2, field1)) { - if (fields2_scope == FULL) { - tmp_message_fields_.push_back(fields2[index2]); - } - ++index2; - } else { - tmp_message_fields_.push_back(fields1[index1]); - ++index1; - ++index2; - } - } - - tmp_message_fields_.push_back(nullptr); - - FieldDescriptorArray combined_fields(tmp_message_fields_.begin(), - tmp_message_fields_.end()); - - return combined_fields; -} - -bool MessageDifferencer::CompareWithFieldsInternal( - const Message& message1, const Message& message2, - const FieldDescriptorArray& message1_fields, - const FieldDescriptorArray& message2_fields, - std::vector<SpecificField>* parent_fields) { - bool isDifferent = false; - int field_index1 = 0; - int field_index2 = 0; - - const Reflection* reflection1 = message1.GetReflection(); - const Reflection* reflection2 = message2.GetReflection(); - - while (true) { - const FieldDescriptor* field1 = message1_fields[field_index1]; - const FieldDescriptor* field2 = message2_fields[field_index2]; - - // Once we have reached sentinel values, we are done the comparison. - if (field1 == NULL && field2 == NULL) { - break; - } - - // Check for differences in the field itself. - if (FieldBefore(field1, field2)) { - // Field 1 is not in the field list for message 2. - if (IsIgnored(message1, message2, field1, *parent_fields)) { - // We are ignoring field1. Report the ignore and move on to - // the next field in message1_fields. - if (reporter_ != NULL) { - SpecificField specific_field; - specific_field.field = field1; - parent_fields->push_back(specific_field); - if (report_ignores_) { - reporter_->ReportIgnored(message1, message2, *parent_fields); - } - parent_fields->pop_back(); - } - ++field_index1; - continue; - } - - if (reporter_ != NULL) { - assert(field1 != NULL); - int count = field1->is_repeated() - ? reflection1->FieldSize(message1, field1) - : 1; - - for (int i = 0; i < count; ++i) { - SpecificField specific_field; - specific_field.field = field1; - if (field1->is_repeated()) { - AddSpecificIndex(&specific_field, message1, field1, i); - } else { - specific_field.index = -1; - } - - parent_fields->push_back(specific_field); - reporter_->ReportDeleted(message1, message2, *parent_fields); - parent_fields->pop_back(); - } - - isDifferent = true; - } else { - return false; - } - - ++field_index1; - continue; - } else if (FieldBefore(field2, field1)) { - // Field 2 is not in the field list for message 1. - if (IsIgnored(message1, message2, field2, *parent_fields)) { - // We are ignoring field2. Report the ignore and move on to - // the next field in message2_fields. - if (reporter_ != NULL) { - SpecificField specific_field; - specific_field.field = field2; - parent_fields->push_back(specific_field); - if (report_ignores_) { - reporter_->ReportIgnored(message1, message2, *parent_fields); - } - parent_fields->pop_back(); - } - ++field_index2; - continue; - } - - if (reporter_ != NULL) { - int count = field2->is_repeated() - ? reflection2->FieldSize(message2, field2) - : 1; - - for (int i = 0; i < count; ++i) { - SpecificField specific_field; - specific_field.field = field2; - if (field2->is_repeated()) { - specific_field.index = i; - AddSpecificNewIndex(&specific_field, message2, field2, i); - } else { - specific_field.index = -1; - specific_field.new_index = -1; - } - - parent_fields->push_back(specific_field); - reporter_->ReportAdded(message1, message2, *parent_fields); - parent_fields->pop_back(); - } - - isDifferent = true; - } else { - return false; - } - - ++field_index2; - continue; - } - - // By this point, field1 and field2 are guaranteed to point to the same - // field, so we can now compare the values. - if (IsIgnored(message1, message2, field1, *parent_fields)) { - // Ignore this field. Report and move on. - if (reporter_ != NULL) { - SpecificField specific_field; - specific_field.field = field1; - parent_fields->push_back(specific_field); - if (report_ignores_) { - reporter_->ReportIgnored(message1, message2, *parent_fields); - } - parent_fields->pop_back(); - } - - ++field_index1; - ++field_index2; - continue; - } - - bool fieldDifferent = false; - assert(field1 != NULL); - if (field1->is_map()) { - fieldDifferent = - !CompareMapField(message1, message2, field1, parent_fields); - } else if (field1->is_repeated()) { - fieldDifferent = - !CompareRepeatedField(message1, message2, field1, parent_fields); - } else { - fieldDifferent = !CompareFieldValueUsingParentFields( - message1, message2, field1, -1, -1, parent_fields); - - if (reporter_ != nullptr) { - SpecificField specific_field; - specific_field.field = field1; - parent_fields->push_back(specific_field); - if (fieldDifferent) { - reporter_->ReportModified(message1, message2, *parent_fields); - isDifferent = true; - } else if (report_matches_) { - reporter_->ReportMatched(message1, message2, *parent_fields); - } - parent_fields->pop_back(); - } - } - if (fieldDifferent) { - if (reporter_ == nullptr) return false; - isDifferent = true; - } - // Increment the field indices. - ++field_index1; - ++field_index2; - } - - return !isDifferent; -} - -bool MessageDifferencer::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) { - std::vector<SpecificField> current_parent_fields(parent_fields); - if (repeated_field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) { - return CompareFieldValueUsingParentFields(*message1, *message2, - repeated_field, index1, index2, - ¤t_parent_fields); - } - // Back up the Reporter and output_string_. They will be reset in the - // following code. - Reporter* backup_reporter = reporter_; - std::string* output_string = output_string_; - reporter_ = reporter; - output_string_ = NULL; - bool match; - - if (key_comparator == NULL) { - match = CompareFieldValueUsingParentFields(*message1, *message2, - repeated_field, index1, index2, - ¤t_parent_fields); - } else { - const Reflection* reflection1 = message1->GetReflection(); - const Reflection* reflection2 = message2->GetReflection(); - const Message& m1 = - reflection1->GetRepeatedMessage(*message1, repeated_field, index1); - const Message& m2 = - reflection2->GetRepeatedMessage(*message2, repeated_field, index2); - SpecificField specific_field; - specific_field.field = repeated_field; - if (repeated_field->is_map()) { - specific_field.map_entry1 = &m1; - specific_field.map_entry2 = &m2; - } - specific_field.index = index1; - specific_field.new_index = index2; - current_parent_fields.push_back(specific_field); - match = key_comparator->IsMatch(m1, m2, current_parent_fields); - } - - reporter_ = backup_reporter; - output_string_ = output_string; - return match; -} - -bool MessageDifferencer::CompareMapFieldByMapReflection( - const Message& message1, const Message& message2, - const FieldDescriptor* map_field, std::vector<SpecificField>* parent_fields, - DefaultFieldComparator* comparator) { - GOOGLE_DCHECK_EQ(nullptr, reporter_); - GOOGLE_DCHECK(map_field->is_map()); - GOOGLE_DCHECK(map_field_key_comparator_.find(map_field) == - map_field_key_comparator_.end()); - GOOGLE_DCHECK_EQ(repeated_field_comparison_, AS_LIST); - const Reflection* reflection1 = message1.GetReflection(); - const Reflection* reflection2 = message2.GetReflection(); - const int count1 = reflection1->MapSize(message1, map_field); - const int count2 = reflection2->MapSize(message2, map_field); - const bool treated_as_subset = IsTreatedAsSubset(map_field); - if (count1 != count2 && !treated_as_subset) { - return false; - } - if (count1 > count2) { - return false; - } - - // First pass: check whether the same keys are present. - for (MapIterator it = reflection1->MapBegin(const_cast<Message*>(&message1), - map_field), - it_end = reflection1->MapEnd(const_cast<Message*>(&message1), - map_field); - it != it_end; ++it) { - if (!reflection2->ContainsMapKey(message2, map_field, it.GetKey())) { - return false; - } - } - - // Second pass: compare values for matching keys. - const FieldDescriptor* val_des = map_field->message_type()->map_value(); - switch (val_des->cpp_type()) { -#define HANDLE_TYPE(CPPTYPE, METHOD, COMPAREMETHOD) \ - case FieldDescriptor::CPPTYPE_##CPPTYPE: { \ - for (MapIterator it = reflection1->MapBegin( \ - const_cast<Message*>(&message1), map_field), \ - it_end = reflection1->MapEnd( \ - const_cast<Message*>(&message1), map_field); \ - it != it_end; ++it) { \ - MapValueConstRef value2; \ - reflection2->LookupMapValue(message2, map_field, it.GetKey(), &value2); \ - if (!comparator->Compare##COMPAREMETHOD(*val_des, \ - it.GetValueRef().Get##METHOD(), \ - value2.Get##METHOD())) { \ - return false; \ - } \ - } \ - break; \ - } - HANDLE_TYPE(INT32, Int32Value, Int32); - HANDLE_TYPE(INT64, Int64Value, Int64); - HANDLE_TYPE(UINT32, UInt32Value, UInt32); - HANDLE_TYPE(UINT64, UInt64Value, UInt64); - HANDLE_TYPE(DOUBLE, DoubleValue, Double); - HANDLE_TYPE(FLOAT, FloatValue, Float); - HANDLE_TYPE(BOOL, BoolValue, Bool); - HANDLE_TYPE(STRING, StringValue, String); - HANDLE_TYPE(ENUM, EnumValue, Int32); -#undef HANDLE_TYPE - case FieldDescriptor::CPPTYPE_MESSAGE: { - for (MapIterator it = reflection1->MapBegin( - const_cast<Message*>(&message1), map_field); - it != - reflection1->MapEnd(const_cast<Message*>(&message1), map_field); - ++it) { - if (!reflection2->ContainsMapKey(message2, map_field, it.GetKey())) { - return false; - } - bool compare_result; - MapValueConstRef value2; - reflection2->LookupMapValue(message2, map_field, it.GetKey(), &value2); - // Append currently compared field to the end of parent_fields. - SpecificField specific_value_field; - specific_value_field.field = val_des; - parent_fields->push_back(specific_value_field); - compare_result = Compare(it.GetValueRef().GetMessageValue(), - value2.GetMessageValue(), parent_fields); - parent_fields->pop_back(); - if (!compare_result) { - return false; - } - } - break; - } - } - return true; -} - -bool MessageDifferencer::CompareMapField( - const Message& message1, const Message& message2, - const FieldDescriptor* repeated_field, - std::vector<SpecificField>* parent_fields) { - GOOGLE_DCHECK(repeated_field->is_map()); - - // the input FieldDescriptor is guaranteed to be repeated field. - const Reflection* reflection1 = message1.GetReflection(); - const Reflection* reflection2 = message2.GetReflection(); - - // When both map fields are on map, do not sync to repeated field. - if (reflection1->GetMapData(message1, repeated_field)->IsMapValid() && - reflection2->GetMapData(message2, repeated_field)->IsMapValid() && - // TODO(jieluo): Add support for reporter - reporter_ == nullptr && - // Users didn't set custom map field key comparator - map_field_key_comparator_.find(repeated_field) == - map_field_key_comparator_.end() && - // Users didn't set repeated field comparison - repeated_field_comparison_ == AS_LIST && - // Users didn't set their own FieldComparator implementation - field_comparator_kind_ == kFCDefault) { - const FieldDescriptor* key_des = repeated_field->message_type()->map_key(); - const FieldDescriptor* val_des = - repeated_field->message_type()->map_value(); - std::vector<SpecificField> current_parent_fields(*parent_fields); - SpecificField specific_field; - specific_field.field = repeated_field; - current_parent_fields.push_back(specific_field); - if (!IsIgnored(message1, message2, key_des, current_parent_fields) && - !IsIgnored(message1, message2, val_des, current_parent_fields)) { - return CompareMapFieldByMapReflection(message1, message2, repeated_field, - ¤t_parent_fields, - field_comparator_.default_impl); - } - } - - return CompareRepeatedRep(message1, message2, repeated_field, parent_fields); -} - -bool MessageDifferencer::CompareRepeatedField( - const Message& message1, const Message& message2, - const FieldDescriptor* repeated_field, - std::vector<SpecificField>* parent_fields) { - GOOGLE_DCHECK(!repeated_field->is_map()); - return CompareRepeatedRep(message1, message2, repeated_field, parent_fields); -} - -bool MessageDifferencer::CompareRepeatedRep( - const Message& message1, const Message& message2, - const FieldDescriptor* repeated_field, - std::vector<SpecificField>* parent_fields) { - // the input FieldDescriptor is guaranteed to be repeated field. - GOOGLE_DCHECK(repeated_field->is_repeated()); - const Reflection* reflection1 = message1.GetReflection(); - const Reflection* reflection2 = message2.GetReflection(); - - const int count1 = reflection1->FieldSize(message1, repeated_field); - const int count2 = reflection2->FieldSize(message2, repeated_field); - const bool treated_as_subset = IsTreatedAsSubset(repeated_field); - - // If the field is not treated as subset and no detailed reports is needed, - // we do a quick check on the number of the elements to avoid unnecessary - // comparison. - if (count1 != count2 && reporter_ == NULL && !treated_as_subset) { - return false; - } - // A match can never be found if message1 has more items than message2. - if (count1 > count2 && reporter_ == NULL) { - return false; - } - - // These two list are used for store the index of the correspondent - // element in peer repeated field. - std::vector<int> match_list1; - std::vector<int> match_list2; - - const MapKeyComparator* key_comparator = GetMapKeyComparator(repeated_field); - bool smart_list = IsTreatedAsSmartList(repeated_field); - bool simple_list = key_comparator == nullptr && - !IsTreatedAsSet(repeated_field) && - !IsTreatedAsSmartSet(repeated_field) && !smart_list; - - // For simple lists, we avoid matching repeated field indices, saving the - // memory allocations that would otherwise be needed for match_list1 and - // match_list2. - if (!simple_list) { - // Try to match indices of the repeated fields. Return false if match fails. - if (!MatchRepeatedFieldIndices(message1, message2, repeated_field, - key_comparator, *parent_fields, &match_list1, - &match_list2) && - reporter_ == nullptr) { - return false; - } - } - - bool fieldDifferent = false; - SpecificField specific_field; - specific_field.field = repeated_field; - - // At this point, we have already matched pairs of fields (with the reporting - // to be done later). Now to check if the paired elements are different. - int next_unmatched_index = 0; - for (int i = 0; i < count1; i++) { - if (simple_list && i >= count2) { - break; - } - if (!simple_list && match_list1[i] == -1) { - if (smart_list) { - if (reporter_ == nullptr) return false; - AddSpecificIndex(&specific_field, message1, repeated_field, i); - parent_fields->push_back(specific_field); - reporter_->ReportDeleted(message1, message2, *parent_fields); - parent_fields->pop_back(); - fieldDifferent = true; - // Use -2 to mark this element has been reported. - match_list1[i] = -2; - } - continue; - } - if (smart_list) { - for (int j = next_unmatched_index; j < match_list1[i]; ++j) { - GOOGLE_CHECK_LE(0, j); - if (reporter_ == nullptr) return false; - specific_field.index = j; - AddSpecificNewIndex(&specific_field, message2, repeated_field, j); - parent_fields->push_back(specific_field); - reporter_->ReportAdded(message1, message2, *parent_fields); - parent_fields->pop_back(); - fieldDifferent = true; - // Use -2 to mark this element has been reported. - match_list2[j] = -2; - } - } - AddSpecificIndex(&specific_field, message1, repeated_field, i); - if (simple_list) { - AddSpecificNewIndex(&specific_field, message2, repeated_field, i); - } else { - AddSpecificNewIndex(&specific_field, message2, repeated_field, - match_list1[i]); - next_unmatched_index = match_list1[i] + 1; - } - - const bool result = CompareFieldValueUsingParentFields( - message1, message2, repeated_field, i, specific_field.new_index, - parent_fields); - - // If we have found differences, either report them or terminate if - // no reporter is present. Note that ReportModified, ReportMoved, and - // ReportMatched are all mutually exclusive. - if (!result) { - if (reporter_ == NULL) return false; - parent_fields->push_back(specific_field); - reporter_->ReportModified(message1, message2, *parent_fields); - parent_fields->pop_back(); - fieldDifferent = true; - } else if (reporter_ != NULL && - specific_field.index != specific_field.new_index && - !specific_field.field->is_map() && report_moves_) { - parent_fields->push_back(specific_field); - reporter_->ReportMoved(message1, message2, *parent_fields); - parent_fields->pop_back(); - } else if (report_matches_ && reporter_ != NULL) { - parent_fields->push_back(specific_field); - reporter_->ReportMatched(message1, message2, *parent_fields); - parent_fields->pop_back(); - } - } - - // Report any remaining additions or deletions. - for (int i = 0; i < count2; ++i) { - if (!simple_list && match_list2[i] != -1) continue; - if (simple_list && i < count1) continue; - if (!treated_as_subset) { - fieldDifferent = true; - } - - if (reporter_ == NULL) continue; - specific_field.index = i; - AddSpecificNewIndex(&specific_field, message2, repeated_field, i); - parent_fields->push_back(specific_field); - reporter_->ReportAdded(message1, message2, *parent_fields); - parent_fields->pop_back(); - } - - for (int i = 0; i < count1; ++i) { - if (!simple_list && match_list1[i] != -1) continue; - if (simple_list && i < count2) continue; - assert(reporter_ != NULL); - AddSpecificIndex(&specific_field, message1, repeated_field, i); - parent_fields->push_back(specific_field); - reporter_->ReportDeleted(message1, message2, *parent_fields); - parent_fields->pop_back(); - fieldDifferent = true; - } - return !fieldDifferent; -} - -bool MessageDifferencer::CompareFieldValue(const Message& message1, - const Message& message2, - const FieldDescriptor* field, - int index1, int index2) { - return CompareFieldValueUsingParentFields(message1, message2, field, index1, - index2, NULL); -} - -bool MessageDifferencer::CompareFieldValueUsingParentFields( - const Message& message1, const Message& message2, - const FieldDescriptor* field, int index1, int index2, - std::vector<SpecificField>* parent_fields) { - FieldContext field_context(parent_fields); - FieldComparator::ComparisonResult result = GetFieldComparisonResult( - message1, message2, field, index1, index2, &field_context); - - if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && - result == FieldComparator::RECURSE) { - // Get the nested messages and compare them using one of the Compare - // methods. - const Reflection* reflection1 = message1.GetReflection(); - const Reflection* reflection2 = message2.GetReflection(); - const Message& m1 = - field->is_repeated() - ? reflection1->GetRepeatedMessage(message1, field, index1) - : reflection1->GetMessage(message1, field); - const Message& m2 = - field->is_repeated() - ? reflection2->GetRepeatedMessage(message2, field, index2) - : reflection2->GetMessage(message2, field); - - // parent_fields is used in calls to Reporter methods. - if (parent_fields != NULL) { - // Append currently compared field to the end of parent_fields. - SpecificField specific_field; - specific_field.field = field; - AddSpecificIndex(&specific_field, message1, field, index1); - AddSpecificNewIndex(&specific_field, message2, field, index2); - parent_fields->push_back(specific_field); - const bool compare_result = Compare(m1, m2, parent_fields); - parent_fields->pop_back(); - return compare_result; - } else { - // Recreates parent_fields as if m1 and m2 had no parents. - return Compare(m1, m2); - } - } else { - return (result == FieldComparator::SAME); - } -} - -bool MessageDifferencer::CheckPathChanged( - const std::vector<SpecificField>& field_path) { - for (const SpecificField& specific_field : field_path) { - // Don't check indexes for map entries -- maps are unordered. - if (specific_field.field != nullptr && specific_field.field->is_map()) - continue; - if (specific_field.index != specific_field.new_index) return true; - } - return false; -} - -bool MessageDifferencer::IsTreatedAsSet(const FieldDescriptor* field) { - if (!field->is_repeated()) return false; - if (repeated_field_comparisons_.find(field) != - repeated_field_comparisons_.end()) { - return repeated_field_comparisons_[field] == AS_SET; - } - return GetMapKeyComparator(field) == nullptr && - repeated_field_comparison_ == AS_SET; -} - -bool MessageDifferencer::IsTreatedAsSmartSet(const FieldDescriptor* field) { - if (!field->is_repeated()) return false; - if (repeated_field_comparisons_.find(field) != - repeated_field_comparisons_.end()) { - return repeated_field_comparisons_[field] == AS_SMART_SET; - } - return GetMapKeyComparator(field) == nullptr && - repeated_field_comparison_ == AS_SMART_SET; -} - -bool MessageDifferencer::IsTreatedAsSmartList(const FieldDescriptor* field) { - if (!field->is_repeated()) return false; - if (repeated_field_comparisons_.find(field) != - repeated_field_comparisons_.end()) { - return repeated_field_comparisons_[field] == AS_SMART_LIST; - } - return GetMapKeyComparator(field) == nullptr && - repeated_field_comparison_ == AS_SMART_LIST; -} - -bool MessageDifferencer::IsTreatedAsSubset(const FieldDescriptor* field) { - return scope_ == PARTIAL && - (IsTreatedAsSet(field) || GetMapKeyComparator(field) != NULL); -} - -bool MessageDifferencer::IsIgnored( - const Message& message1, const Message& message2, - const FieldDescriptor* field, - const std::vector<SpecificField>& parent_fields) { - if (ignored_fields_.find(field) != ignored_fields_.end()) { - return true; - } - for (IgnoreCriteria* criteria : ignore_criteria_) { - if (criteria->IsIgnored(message1, message2, field, parent_fields)) { - return true; - } - } - return false; -} - -bool MessageDifferencer::IsUnknownFieldIgnored( - const Message& message1, const Message& message2, - const SpecificField& field, - const std::vector<SpecificField>& parent_fields) { - for (IgnoreCriteria* criteria : ignore_criteria_) { - if (criteria->IsUnknownFieldIgnored(message1, message2, field, - parent_fields)) { - return true; - } - } - return false; -} - -const MessageDifferencer::MapKeyComparator* -MessageDifferencer ::GetMapKeyComparator(const FieldDescriptor* field) const { - if (!field->is_repeated()) return NULL; - FieldKeyComparatorMap::const_iterator it = - map_field_key_comparator_.find(field); - if (it != map_field_key_comparator_.end()) { - return it->second; - } - if (field->is_map()) { - // field cannot already be treated as list or set since TreatAsList() and - // TreatAsSet() call GetMapKeyComparator() and fail if it returns non-NULL. - return &map_entry_key_comparator_; - } - return NULL; -} - -namespace { - -typedef std::pair<int, const UnknownField*> IndexUnknownFieldPair; - -struct UnknownFieldOrdering { - inline bool operator()(const IndexUnknownFieldPair& a, - const IndexUnknownFieldPair& b) const { - if (a.second->number() < b.second->number()) return true; - if (a.second->number() > b.second->number()) return false; - return a.second->type() < b.second->type(); - } -}; - -} // namespace - -bool MessageDifferencer::UnpackAnyField::UnpackAny( - const Message& any, std::unique_ptr<Message>* data) { - const Reflection* reflection = any.GetReflection(); - const FieldDescriptor* type_url_field; - const FieldDescriptor* value_field; - if (!internal::GetAnyFieldDescriptors(any, &type_url_field, &value_field)) { - return false; - } - const std::string& type_url = reflection->GetString(any, type_url_field); - std::string full_type_name; - if (!internal::ParseAnyTypeUrl(type_url, &full_type_name)) { - return false; - } - - const Descriptor* desc = - any.GetDescriptor()->file()->pool()->FindMessageTypeByName( - full_type_name); - if (desc == NULL) { - GOOGLE_LOG(INFO) << "Proto type '" << full_type_name << "' not found"; - return false; - } - - if (dynamic_message_factory_ == NULL) { - dynamic_message_factory_.reset(new DynamicMessageFactory()); - } - data->reset(dynamic_message_factory_->GetPrototype(desc)->New()); - std::string serialized_value = reflection->GetString(any, value_field); - if (!(*data)->ParsePartialFromString(serialized_value)) { - GOOGLE_DLOG(ERROR) << "Failed to parse value for " << full_type_name; - return false; - } - return true; -} - -bool MessageDifferencer::CompareUnknownFields( - const Message& message1, const Message& message2, - const UnknownFieldSet& unknown_field_set1, - const UnknownFieldSet& unknown_field_set2, - std::vector<SpecificField>* parent_field) { - // Ignore unknown fields in EQUIVALENT mode. - if (message_field_comparison_ == EQUIVALENT) return true; - - if (unknown_field_set1.empty() && unknown_field_set2.empty()) { - return true; - } - - bool is_different = false; - - // We first sort the unknown fields by field number and type (in other words, - // in tag order), making sure to preserve ordering of values with the same - // tag. This allows us to report only meaningful differences between the - // two sets -- that is, differing values for the same tag. We use - // IndexUnknownFieldPairs to keep track of the field's original index for - // reporting purposes. - std::vector<IndexUnknownFieldPair> fields1; // unknown_field_set1, sorted - std::vector<IndexUnknownFieldPair> fields2; // unknown_field_set2, sorted - fields1.reserve(unknown_field_set1.field_count()); - fields2.reserve(unknown_field_set2.field_count()); - - for (int i = 0; i < unknown_field_set1.field_count(); i++) { - fields1.push_back(std::make_pair(i, &unknown_field_set1.field(i))); - } - for (int i = 0; i < unknown_field_set2.field_count(); i++) { - fields2.push_back(std::make_pair(i, &unknown_field_set2.field(i))); - } - - UnknownFieldOrdering is_before; - std::stable_sort(fields1.begin(), fields1.end(), is_before); - std::stable_sort(fields2.begin(), fields2.end(), is_before); - - // In order to fill in SpecificField::index, we have to keep track of how - // many values we've seen with the same field number and type. - // current_repeated points at the first field in this range, and - // current_repeated_start{1,2} are the indexes of the first field in the - // range within fields1 and fields2. - const UnknownField* current_repeated = NULL; - int current_repeated_start1 = 0; - int current_repeated_start2 = 0; - - // Now that we have two sorted lists, we can detect fields which appear only - // in one list or the other by traversing them simultaneously. - size_t index1 = 0; - size_t index2 = 0; - while (index1 < fields1.size() || index2 < fields2.size()) { - enum { - ADDITION, - DELETION, - MODIFICATION, - COMPARE_GROUPS, - NO_CHANGE - } change_type; - - // focus_field is the field we're currently reporting on. (In the case - // of a modification, it's the field on the left side.) - const UnknownField* focus_field; - bool match = false; - - if (index2 == fields2.size() || - (index1 < fields1.size() && - is_before(fields1[index1], fields2[index2]))) { - // fields1[index1] is not present in fields2. - change_type = DELETION; - focus_field = fields1[index1].second; - } else if (index1 == fields1.size() || - is_before(fields2[index2], fields1[index1])) { - // fields2[index2] is not present in fields1. - if (scope_ == PARTIAL) { - // Ignore. - ++index2; - continue; - } - change_type = ADDITION; - focus_field = fields2[index2].second; - } else { - // Field type and number are the same. See if the values differ. - change_type = MODIFICATION; - focus_field = fields1[index1].second; - - switch (focus_field->type()) { - case UnknownField::TYPE_VARINT: - match = fields1[index1].second->varint() == - fields2[index2].second->varint(); - break; - case UnknownField::TYPE_FIXED32: - match = fields1[index1].second->fixed32() == - fields2[index2].second->fixed32(); - break; - case UnknownField::TYPE_FIXED64: - match = fields1[index1].second->fixed64() == - fields2[index2].second->fixed64(); - break; - case UnknownField::TYPE_LENGTH_DELIMITED: - match = fields1[index1].second->length_delimited() == - fields2[index2].second->length_delimited(); - break; - case UnknownField::TYPE_GROUP: - // We must deal with this later, after building the SpecificField. - change_type = COMPARE_GROUPS; - break; - } - if (match && change_type != COMPARE_GROUPS) { - change_type = NO_CHANGE; - } - } - - if (current_repeated == NULL || - focus_field->number() != current_repeated->number() || - focus_field->type() != current_repeated->type()) { - // We've started a new repeated field. - current_repeated = focus_field; - current_repeated_start1 = index1; - current_repeated_start2 = index2; - } - - if (change_type == NO_CHANGE && reporter_ == NULL) { - // Fields were already compared and matched and we have no reporter. - ++index1; - ++index2; - continue; - } - - // Build the SpecificField. This is slightly complicated. - SpecificField specific_field; - specific_field.unknown_field_number = focus_field->number(); - specific_field.unknown_field_type = focus_field->type(); - - specific_field.unknown_field_set1 = &unknown_field_set1; - specific_field.unknown_field_set2 = &unknown_field_set2; - - if (change_type != ADDITION) { - specific_field.unknown_field_index1 = fields1[index1].first; - } - if (change_type != DELETION) { - specific_field.unknown_field_index2 = fields2[index2].first; - } - - // Calculate the field index. - if (change_type == ADDITION) { - specific_field.index = index2 - current_repeated_start2; - specific_field.new_index = index2 - current_repeated_start2; - } else { - specific_field.index = index1 - current_repeated_start1; - specific_field.new_index = index2 - current_repeated_start2; - } - - if (IsUnknownFieldIgnored(message1, message2, specific_field, - *parent_field)) { - if (report_ignores_ && reporter_ != NULL) { - parent_field->push_back(specific_field); - reporter_->ReportUnknownFieldIgnored(message1, message2, *parent_field); - parent_field->pop_back(); - } - if (change_type != ADDITION) ++index1; - if (change_type != DELETION) ++index2; - continue; - } - - if (change_type == ADDITION || change_type == DELETION || - change_type == MODIFICATION) { - if (reporter_ == NULL) { - // We found a difference and we have no reporter. - return false; - } - is_different = true; - } - - parent_field->push_back(specific_field); - - switch (change_type) { - case ADDITION: - reporter_->ReportAdded(message1, message2, *parent_field); - ++index2; - break; - case DELETION: - reporter_->ReportDeleted(message1, message2, *parent_field); - ++index1; - break; - case MODIFICATION: - reporter_->ReportModified(message1, message2, *parent_field); - ++index1; - ++index2; - break; - case COMPARE_GROUPS: - if (!CompareUnknownFields( - message1, message2, fields1[index1].second->group(), - fields2[index2].second->group(), parent_field)) { - if (reporter_ == NULL) return false; - is_different = true; - reporter_->ReportModified(message1, message2, *parent_field); - } - ++index1; - ++index2; - break; - case NO_CHANGE: - ++index1; - ++index2; - if (report_matches_) { - reporter_->ReportMatched(message1, message2, *parent_field); - } - } - - parent_field->pop_back(); - } - - return !is_different; -} - -namespace { - -// Find maximum bipartite matching using the argumenting path algorithm. -class MaximumMatcher { - public: - typedef std::function<bool(int, int)> NodeMatchCallback; - // MaximumMatcher takes ownership of the passed in callback and uses it to - // determine whether a node on the left side of the bipartial graph matches - // a node on the right side. count1 is the number of nodes on the left side - // of the graph and count2 to is the number of nodes on the right side. - // Every node is referred to using 0-based indices. - // If a maximum match is found, the result will be stored in match_list1 and - // match_list2. match_list1[i] == j means the i-th node on the left side is - // matched to the j-th node on the right side and match_list2[x] == y means - // the x-th node on the right side is matched to y-th node on the left side. - // match_list1[i] == -1 means the node is not matched. Same with match_list2. - MaximumMatcher(int count1, int count2, NodeMatchCallback callback, - std::vector<int>* match_list1, std::vector<int>* match_list2); - // Find a maximum match and return the number of matched node pairs. - // If early_return is true, this method will return 0 immediately when it - // finds that not all nodes on the left side can be matched. - int FindMaximumMatch(bool early_return); - - private: - // Determines whether the node on the left side of the bipartial graph - // matches the one on the right side. - bool Match(int left, int right); - // Find an argumenting path starting from the node v on the left side. If a - // path can be found, update match_list2_ to reflect the path and return - // true. - bool FindArgumentPathDFS(int v, std::vector<bool>* visited); - - int count1_; - int count2_; - NodeMatchCallback match_callback_; - std::map<std::pair<int, int>, bool> cached_match_results_; - std::vector<int>* match_list1_; - std::vector<int>* match_list2_; - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MaximumMatcher); -}; - -MaximumMatcher::MaximumMatcher(int count1, int count2, - NodeMatchCallback callback, - std::vector<int>* match_list1, - std::vector<int>* match_list2) - : count1_(count1), - count2_(count2), - match_callback_(std::move(callback)), - match_list1_(match_list1), - match_list2_(match_list2) { - match_list1_->assign(count1, -1); - match_list2_->assign(count2, -1); -} - -int MaximumMatcher::FindMaximumMatch(bool early_return) { - int result = 0; - for (int i = 0; i < count1_; ++i) { - std::vector<bool> visited(count1_); - if (FindArgumentPathDFS(i, &visited)) { - ++result; - } else if (early_return) { - return 0; - } - } - // Backfill match_list1_ as we only filled match_list2_ when finding - // argumenting paths. - for (int i = 0; i < count2_; ++i) { - if ((*match_list2_)[i] != -1) { - (*match_list1_)[(*match_list2_)[i]] = i; - } - } - return result; -} - -bool MaximumMatcher::Match(int left, int right) { - std::pair<int, int> p(left, right); - std::map<std::pair<int, int>, bool>::iterator it = - cached_match_results_.find(p); - if (it != cached_match_results_.end()) { - return it->second; - } - cached_match_results_[p] = match_callback_(left, right); - return cached_match_results_[p]; -} - -bool MaximumMatcher::FindArgumentPathDFS(int v, std::vector<bool>* visited) { - (*visited)[v] = true; - // We try to match those un-matched nodes on the right side first. This is - // the step that the naive greedy matching algorithm uses. In the best cases - // where the greedy algorithm can find a maximum matching, we will always - // find a match in this step and the performance will be identical to the - // greedy algorithm. - for (int i = 0; i < count2_; ++i) { - int matched = (*match_list2_)[i]; - if (matched == -1 && Match(v, i)) { - (*match_list2_)[i] = v; - return true; - } - } - // Then we try those already matched nodes and see if we can find an - // alternative match for the node matched to them. - // The greedy algorithm will stop before this and fail to produce the - // correct result. - for (int i = 0; i < count2_; ++i) { - int matched = (*match_list2_)[i]; - if (matched != -1 && Match(v, i)) { - if (!(*visited)[matched] && FindArgumentPathDFS(matched, visited)) { - (*match_list2_)[i] = v; - return true; - } - } - } - return false; -} - -} // namespace - -bool MessageDifferencer::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) { - const int count1 = - message1.GetReflection()->FieldSize(message1, repeated_field); - const int count2 = - message2.GetReflection()->FieldSize(message2, repeated_field); - const bool is_treated_as_smart_set = IsTreatedAsSmartSet(repeated_field); - - match_list1->assign(count1, -1); - match_list2->assign(count2, -1); - // Ensure that we don't report differences during the matching process. Since - // field comparators could potentially use this message differencer object to - // perform further comparisons, turn off reporting here and re-enable it - // before returning. - Reporter* reporter = reporter_; - reporter_ = NULL; - NumDiffsReporter num_diffs_reporter; - std::vector<int32_t> num_diffs_list1; - if (is_treated_as_smart_set) { - num_diffs_list1.assign(count1, std::numeric_limits<int32_t>::max()); - } - - bool success = true; - // Find potential match if this is a special repeated field. - if (scope_ == PARTIAL) { - // When partial matching is enabled, Compare(a, b) && Compare(a, c) - // doesn't necessarily imply Compare(b, c). Therefore a naive greedy - // algorithm will fail to find a maximum matching. - // Here we use the augmenting path algorithm. - auto callback = [&](int i1, int i2) { - return IsMatch(repeated_field, key_comparator, &message1, &message2, - parent_fields, nullptr, i1, i2); - }; - MaximumMatcher matcher(count1, count2, std::move(callback), match_list1, - match_list2); - // If diff info is not needed, we should end the matching process as - // soon as possible if not all items can be matched. - bool early_return = (reporter == nullptr); - int match_count = matcher.FindMaximumMatch(early_return); - if (match_count != count1 && early_return) return false; - success = success && (match_count == count1); - } else { - int start_offset = 0; - // If the two repeated fields are treated as sets, optimize for the case - // where both start with same items stored in the same order. - if (IsTreatedAsSet(repeated_field) || is_treated_as_smart_set || - IsTreatedAsSmartList(repeated_field)) { - start_offset = std::min(count1, count2); - for (int i = 0; i < count1 && i < count2; i++) { - if (IsMatch(repeated_field, key_comparator, &message1, &message2, - parent_fields, nullptr, i, i)) { - match_list1->at(i) = i; - match_list2->at(i) = i; - } else { - start_offset = i; - break; - } - } - } - for (int i = start_offset; i < count1; ++i) { - // Indicates any matched elements for this repeated field. - bool match = false; - int matched_j = -1; - - for (int j = start_offset; j < count2; j++) { - if (match_list2->at(j) != -1) { - if (!is_treated_as_smart_set || num_diffs_list1[i] == 0 || - num_diffs_list1[match_list2->at(j)] == 0) { - continue; - } - } - - if (is_treated_as_smart_set) { - num_diffs_reporter.Reset(); - match = IsMatch(repeated_field, key_comparator, &message1, &message2, - parent_fields, &num_diffs_reporter, i, j); - } else { - match = IsMatch(repeated_field, key_comparator, &message1, &message2, - parent_fields, nullptr, i, j); - } - - if (is_treated_as_smart_set) { - if (match) { - num_diffs_list1[i] = 0; - } else if (repeated_field->cpp_type() == - FieldDescriptor::CPPTYPE_MESSAGE) { - // Replace with the one with fewer diffs. - const int32_t num_diffs = num_diffs_reporter.GetNumDiffs(); - if (num_diffs < num_diffs_list1[i]) { - // If j has been already matched to some element, ensure the - // current num_diffs is smaller. - if (match_list2->at(j) == -1 || - num_diffs < num_diffs_list1[match_list2->at(j)]) { - num_diffs_list1[i] = num_diffs; - match = true; - } - } - } - } - - if (match) { - matched_j = j; - if (!is_treated_as_smart_set || num_diffs_list1[i] == 0) { - break; - } - } - } - - match = (matched_j != -1); - if (match) { - if (is_treated_as_smart_set && match_list2->at(matched_j) != -1) { - // This is to revert the previously matched index in list2. - match_list1->at(match_list2->at(matched_j)) = -1; - match = false; - } - match_list1->at(i) = matched_j; - match_list2->at(matched_j) = i; - } - if (!match && reporter == nullptr) return false; - success = success && match; - } - } - - if (IsTreatedAsSmartList(repeated_field)) { - match_indices_for_smart_list_callback_(match_list1, match_list2); - } - - reporter_ = reporter; - - return success; -} - -FieldComparator::ComparisonResult MessageDifferencer::GetFieldComparisonResult( - const Message& message1, const Message& message2, - const FieldDescriptor* field, int index1, int index2, - const FieldContext* field_context) { - FieldComparator* comparator = field_comparator_kind_ == kFCBase - ? field_comparator_.base - : field_comparator_.default_impl; - return comparator->Compare(message1, message2, field, index1, index2, - field_context); -} - -// =========================================================================== - -MessageDifferencer::Reporter::Reporter() {} -MessageDifferencer::Reporter::~Reporter() {} - -// =========================================================================== - -MessageDifferencer::MapKeyComparator::MapKeyComparator() {} -MessageDifferencer::MapKeyComparator::~MapKeyComparator() {} - -// =========================================================================== - -MessageDifferencer::IgnoreCriteria::IgnoreCriteria() {} -MessageDifferencer::IgnoreCriteria::~IgnoreCriteria() {} - -// =========================================================================== - -// Note that the printer's delimiter is not used, because if we are given a -// printer, we don't know its delimiter. -MessageDifferencer::StreamReporter::StreamReporter( - io::ZeroCopyOutputStream* output) - : printer_(new io::Printer(output, '$')), - delete_printer_(true), - report_modified_aggregates_(false), - message1_(nullptr), - message2_(nullptr) {} - -MessageDifferencer::StreamReporter::StreamReporter(io::Printer* printer) - : printer_(printer), - delete_printer_(false), - report_modified_aggregates_(false), - message1_(nullptr), - message2_(nullptr) {} - -MessageDifferencer::StreamReporter::~StreamReporter() { - if (delete_printer_) delete printer_; -} - -void MessageDifferencer::StreamReporter::PrintPath( - const std::vector<SpecificField>& field_path, bool left_side) { - for (size_t i = 0; i < field_path.size(); ++i) { - SpecificField specific_field = field_path[i]; - - if (specific_field.field != nullptr && - specific_field.field->name() == "value") { - // check to see if this the value label of a map value. If so, skip it - // because it isn't meaningful - if (i > 0 && field_path[i - 1].field->is_map()) { - continue; - } - } - if (i > 0) { - printer_->Print("."); - } - if (specific_field.field != NULL) { - if (specific_field.field->is_extension()) { - printer_->Print("($name$)", "name", specific_field.field->full_name()); - } else { - printer_->PrintRaw(specific_field.field->name()); - } - - if (specific_field.field->is_map()) { - PrintMapKey(left_side, specific_field); - continue; - } - } else { - printer_->PrintRaw(StrCat(specific_field.unknown_field_number)); - } - if (left_side && specific_field.index >= 0) { - printer_->Print("[$name$]", "name", StrCat(specific_field.index)); - } - if (!left_side && specific_field.new_index >= 0) { - printer_->Print("[$name$]", "name", - StrCat(specific_field.new_index)); - } - } -} - - -void MessageDifferencer::StreamReporter::PrintValue( - const Message& message, const std::vector<SpecificField>& field_path, - bool left_side) { - const SpecificField& specific_field = field_path.back(); - const FieldDescriptor* field = specific_field.field; - if (field != NULL) { - std::string output; - int index = left_side ? specific_field.index : specific_field.new_index; - if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - const Reflection* reflection = message.GetReflection(); - const Message& field_message = - field->is_repeated() - ? reflection->GetRepeatedMessage(message, field, index) - : reflection->GetMessage(message, field); - const FieldDescriptor* fd = nullptr; - - if (field->is_map() && message1_ != nullptr && message2_ != nullptr) { - fd = field_message.GetDescriptor()->field(1); - if (fd->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - output = field_message.GetReflection() - ->GetMessage(field_message, fd) - .ShortDebugString(); - } else { - TextFormat::PrintFieldValueToString(field_message, fd, -1, &output); - } - } else { - output = field_message.ShortDebugString(); - } - if (output.empty()) { - printer_->Print("{ }"); - } else { - if ((fd != nullptr) && - (fd->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE)) { - printer_->PrintRaw(output); - } else { - printer_->Print("{ $name$ }", "name", output); - } - } - } else { - TextFormat::PrintFieldValueToString(message, field, index, &output); - printer_->PrintRaw(output); - } - } else { - const UnknownFieldSet* unknown_fields = - (left_side ? specific_field.unknown_field_set1 - : specific_field.unknown_field_set2); - const UnknownField* unknown_field = - &unknown_fields->field(left_side ? specific_field.unknown_field_index1 - : specific_field.unknown_field_index2); - PrintUnknownFieldValue(unknown_field); - } -} - -void MessageDifferencer::StreamReporter::PrintUnknownFieldValue( - const UnknownField* unknown_field) { - GOOGLE_CHECK(unknown_field != NULL) << " Cannot print NULL unknown_field."; - - std::string output; - switch (unknown_field->type()) { - case UnknownField::TYPE_VARINT: - output = StrCat(unknown_field->varint()); - break; - case UnknownField::TYPE_FIXED32: - output = StrCat( - "0x", strings::Hex(unknown_field->fixed32(), strings::ZERO_PAD_8)); - break; - case UnknownField::TYPE_FIXED64: - output = StrCat( - "0x", strings::Hex(unknown_field->fixed64(), strings::ZERO_PAD_16)); - break; - case UnknownField::TYPE_LENGTH_DELIMITED: - output = StringPrintf( - "\"%s\"", CEscape(unknown_field->length_delimited()).c_str()); - break; - case UnknownField::TYPE_GROUP: - // TODO(kenton): Print the contents of the group like we do for - // messages. Requires an equivalent of ShortDebugString() for - // UnknownFieldSet. - output = "{ ... }"; - break; - } - printer_->PrintRaw(output); -} - -void MessageDifferencer::StreamReporter::Print(const std::string& str) { - printer_->Print(str.c_str()); -} - -void MessageDifferencer::StreamReporter::PrintMapKey( - bool left_side, const SpecificField& specific_field) { - if (message1_ == nullptr || message2_ == nullptr) { - GOOGLE_LOG(WARNING) << "PrintPath cannot log map keys; " - "use SetMessages to provide the messages " - "being compared prior to any processing."; - return; - } - - const Message* found_message = - left_side ? specific_field.map_entry1 : specific_field.map_entry2; - std::string key_string = ""; - if (found_message != nullptr) { - // NB: the map key is always the first field - const FieldDescriptor* fd = found_message->GetDescriptor()->field(0); - if (fd->cpp_type() == FieldDescriptor::CPPTYPE_STRING) { - // Not using PrintFieldValueToString for strings to avoid extra - // characters - key_string = found_message->GetReflection()->GetString( - *found_message, found_message->GetDescriptor()->field(0)); - } else { - TextFormat::PrintFieldValueToString(*found_message, fd, -1, &key_string); - } - if (key_string.empty()) { - key_string = "''"; - } - printer_->PrintRaw(StrCat("[", key_string, "]")); - } -} - -void MessageDifferencer::StreamReporter::ReportAdded( - const Message& message1, const Message& message2, - const std::vector<SpecificField>& field_path) { - printer_->Print("added: "); - PrintPath(field_path, false); - printer_->Print(": "); - PrintValue(message2, field_path, false); - printer_->Print("\n"); // Print for newlines. -} - -void MessageDifferencer::StreamReporter::ReportDeleted( - const Message& message1, const Message& message2, - const std::vector<SpecificField>& field_path) { - printer_->Print("deleted: "); - PrintPath(field_path, true); - printer_->Print(": "); - PrintValue(message1, field_path, true); - printer_->Print("\n"); // Print for newlines -} - -void MessageDifferencer::StreamReporter::ReportModified( - const Message& message1, const Message& message2, - const std::vector<SpecificField>& field_path) { - if (!report_modified_aggregates_ && field_path.back().field == NULL) { - if (field_path.back().unknown_field_type == UnknownField::TYPE_GROUP) { - // Any changes to the subfields have already been printed. - return; - } - } else if (!report_modified_aggregates_) { - if (field_path.back().field->cpp_type() == - FieldDescriptor::CPPTYPE_MESSAGE) { - // Any changes to the subfields have already been printed. - return; - } - } - - printer_->Print("modified: "); - PrintPath(field_path, true); - if (CheckPathChanged(field_path)) { - printer_->Print(" -> "); - PrintPath(field_path, false); - } - printer_->Print(": "); - PrintValue(message1, field_path, true); - printer_->Print(" -> "); - PrintValue(message2, field_path, false); - printer_->Print("\n"); // Print for newlines. -} - -void MessageDifferencer::StreamReporter::ReportMoved( - const Message& message1, const Message& message2, - const std::vector<SpecificField>& field_path) { - printer_->Print("moved: "); - PrintPath(field_path, true); - printer_->Print(" -> "); - PrintPath(field_path, false); - printer_->Print(" : "); - PrintValue(message1, field_path, true); - printer_->Print("\n"); // Print for newlines. -} - -void MessageDifferencer::StreamReporter::ReportMatched( - const Message& message1, const Message& message2, - const std::vector<SpecificField>& field_path) { - printer_->Print("matched: "); - PrintPath(field_path, true); - if (CheckPathChanged(field_path)) { - printer_->Print(" -> "); - PrintPath(field_path, false); - } - printer_->Print(" : "); - PrintValue(message1, field_path, true); - printer_->Print("\n"); // Print for newlines. -} - -void MessageDifferencer::StreamReporter::ReportIgnored( - const Message& message1, const Message& message2, - const std::vector<SpecificField>& field_path) { - printer_->Print("ignored: "); - PrintPath(field_path, true); - if (CheckPathChanged(field_path)) { - printer_->Print(" -> "); - PrintPath(field_path, false); - } - printer_->Print("\n"); // Print for newlines. -} - -void MessageDifferencer::StreamReporter::SetMessages(const Message& message1, - const Message& message2) { - message1_ = &message1; - message2_ = &message2; -} - -void MessageDifferencer::StreamReporter::ReportUnknownFieldIgnored( - const Message& message1, const Message& message2, - const std::vector<SpecificField>& field_path) { - printer_->Print("ignored: "); - PrintPath(field_path, true); - if (CheckPathChanged(field_path)) { - printer_->Print(" -> "); - PrintPath(field_path, false); - } - printer_->Print("\n"); // Print for newlines. -} - -MessageDifferencer::MapKeyComparator* -MessageDifferencer::CreateMultipleFieldsMapKeyComparator( - const std::vector<std::vector<const FieldDescriptor*> >& key_field_paths) { - return new MultipleFieldsMapKeyComparator(this, key_field_paths); -} - -} // namespace util -} // namespace protobuf -} // namespace google diff --git a/contrib/libs/protobuf_std/src/google/protobuf/util/message_differencer.h b/contrib/libs/protobuf_std/src/google/protobuf/util/message_differencer.h deleted file mode 100644 index 1ee6a38fc4..0000000000 --- a/contrib/libs/protobuf_std/src/google/protobuf/util/message_differencer.h +++ /dev/null @@ -1,974 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: jschorr@google.com (Joseph Schorr) -// Based on original Protocol Buffers design by -// Sanjay Ghemawat, Jeff Dean, and others. -// -// 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; - - // If "field" is a map field, point to the map entry. - const Message* map_entry1 = nullptr; - const Message* map_entry2 = nullptr; - - // 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); - - private: - // helper function for PrintPath that contains logic for printing maps - void PrintMapKey(bool left_side, const SpecificField& specific_field); - - 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__ diff --git a/contrib/libs/protobuf_std/src/google/protobuf/util/time_util.cc b/contrib/libs/protobuf_std/src/google/protobuf/util/time_util.cc deleted file mode 100644 index 6b9c6654b6..0000000000 --- a/contrib/libs/protobuf_std/src/google/protobuf/util/time_util.cc +++ /dev/null @@ -1,511 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include <google/protobuf/util/time_util.h> - -#include <cstdint> - -#include <google/protobuf/stubs/stringprintf.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/duration.pb.h> -#include <google/protobuf/timestamp.pb.h> -#include <google/protobuf/stubs/int128.h> -#include <google/protobuf/stubs/time.h> - -// Must go after other includes. -#include <google/protobuf/port_def.inc> - -namespace google { -namespace protobuf { -namespace util { - -using google::protobuf::Duration; -using google::protobuf::Timestamp; - -namespace { -static const int kNanosPerSecond = 1000000000; -static const int kMicrosPerSecond = 1000000; -static const int kMillisPerSecond = 1000; -static const int kNanosPerMillisecond = 1000000; -static const int kNanosPerMicrosecond = 1000; -static const int kSecondsPerMinute = 60; // Note that we ignore leap seconds. -static const int kSecondsPerHour = 3600; - -template <typename T> -T CreateNormalized(int64_t seconds, int64_t nanos); - -template <> -Timestamp CreateNormalized(int64_t seconds, int64_t nanos) { - // Make sure nanos is in the range. - if (nanos <= -kNanosPerSecond || nanos >= kNanosPerSecond) { - seconds += nanos / kNanosPerSecond; - nanos = nanos % kNanosPerSecond; - } - // For Timestamp nanos should be in the range [0, 999999999] - if (nanos < 0) { - seconds -= 1; - nanos += kNanosPerSecond; - } - GOOGLE_DCHECK(seconds >= TimeUtil::kTimestampMinSeconds && - seconds <= TimeUtil::kTimestampMaxSeconds); - Timestamp result; - result.set_seconds(seconds); - result.set_nanos(static_cast<int32_t>(nanos)); - return result; -} - -template <> -Duration CreateNormalized(int64_t seconds, int64_t nanos) { - // Make sure nanos is in the range. - if (nanos <= -kNanosPerSecond || nanos >= kNanosPerSecond) { - seconds += nanos / kNanosPerSecond; - nanos = nanos % kNanosPerSecond; - } - // nanos should have the same sign as seconds. - if (seconds < 0 && nanos > 0) { - seconds += 1; - nanos -= kNanosPerSecond; - } else if (seconds > 0 && nanos < 0) { - seconds -= 1; - nanos += kNanosPerSecond; - } - GOOGLE_DCHECK(seconds >= TimeUtil::kDurationMinSeconds && - seconds <= TimeUtil::kDurationMaxSeconds); - Duration result; - result.set_seconds(seconds); - result.set_nanos(static_cast<int32_t>(nanos)); - return result; -} - -// Format nanoseconds with either 3, 6, or 9 digits depending on the required -// precision to represent the exact value. -std::string FormatNanos(int32_t nanos) { - if (nanos % kNanosPerMillisecond == 0) { - return StringPrintf("%03d", nanos / kNanosPerMillisecond); - } else if (nanos % kNanosPerMicrosecond == 0) { - return StringPrintf("%06d", nanos / kNanosPerMicrosecond); - } else { - return StringPrintf("%09d", nanos); - } -} - -std::string FormatTime(int64 seconds, int32 nanos) { - return ::google::protobuf::internal::FormatTime(seconds, nanos); -} - -bool ParseTime(const std::string& value, int64* seconds, int32* nanos) { - return ::google::protobuf::internal::ParseTime(value, seconds, nanos); -} - -void CurrentTime(int64* seconds, int32* nanos) { - return ::google::protobuf::internal::GetCurrentTime(seconds, nanos); -} - -// Truncates the remainder part after division. -int64_t RoundTowardZero(int64_t value, int64_t divider) { - int64_t result = value / divider; - int64_t remainder = value % divider; - // Before C++11, the sign of the remainder is implementation dependent if - // any of the operands is negative. Here we try to enforce C++11's "rounded - // toward zero" semantics. For example, for (-5) / 2 an implementation may - // give -3 as the result with the remainder being 1. This function ensures - // we always return -2 (closer to zero) regardless of the implementation. - if (result < 0 && remainder > 0) { - return result + 1; - } else { - return result; - } -} -} // namespace - -// Actually define these static const integers. Required by C++ standard (but -// some compilers don't like it). -#ifndef _MSC_VER -const int64_t TimeUtil::kTimestampMinSeconds; -const int64_t TimeUtil::kTimestampMaxSeconds; -const int64_t TimeUtil::kDurationMaxSeconds; -const int64_t TimeUtil::kDurationMinSeconds; -#endif // !_MSC_VER - -std::string TimeUtil::ToString(const Timestamp& timestamp) { - return FormatTime(timestamp.seconds(), timestamp.nanos()); -} - -bool TimeUtil::FromString(const std::string& value, Timestamp* timestamp) { - int64_t seconds; - int32_t nanos; - if (!ParseTime(value, &seconds, &nanos)) { - return false; - } - *timestamp = CreateNormalized<Timestamp>(seconds, nanos); - return true; -} - -Timestamp TimeUtil::GetCurrentTime() { - int64_t seconds; - int32_t nanos; - CurrentTime(&seconds, &nanos); - return CreateNormalized<Timestamp>(seconds, nanos); -} - -Timestamp TimeUtil::GetEpoch() { return Timestamp(); } - -std::string TimeUtil::ToString(const Duration& duration) { - std::string result; - int64_t seconds = duration.seconds(); - int32_t nanos = duration.nanos(); - if (seconds < 0 || nanos < 0) { - result += "-"; - seconds = -seconds; - nanos = -nanos; - } - result += StrCat(seconds); - if (nanos != 0) { - result += "." + FormatNanos(nanos); - } - result += "s"; - return result; -} - -static int64_t Pow(int64_t x, int y) { - int64_t result = 1; - for (int i = 0; i < y; ++i) { - result *= x; - } - return result; -} - -bool TimeUtil::FromString(const std::string& value, Duration* duration) { - if (value.length() <= 1 || value[value.length() - 1] != 's') { - return false; - } - bool negative = (value[0] == '-'); - int sign_length = (negative ? 1 : 0); - // Parse the duration value as two integers rather than a float value - // to avoid precision loss. - std::string seconds_part, nanos_part; - size_t pos = value.find_last_of('.'); - if (pos == std::string::npos) { - seconds_part = value.substr(sign_length, value.length() - 1 - sign_length); - nanos_part = "0"; - } else { - seconds_part = value.substr(sign_length, pos - sign_length); - nanos_part = value.substr(pos + 1, value.length() - pos - 2); - } - char* end; - int64_t seconds = strto64(seconds_part.c_str(), &end, 10); - if (end != seconds_part.c_str() + seconds_part.length()) { - return false; - } - int64_t nanos = strto64(nanos_part.c_str(), &end, 10); - if (end != nanos_part.c_str() + nanos_part.length()) { - return false; - } - nanos = nanos * Pow(10, 9 - nanos_part.length()); - if (negative) { - // If a Duration is negative, both seconds and nanos should be negative. - seconds = -seconds; - nanos = -nanos; - } - duration->set_seconds(seconds); - duration->set_nanos(static_cast<int32_t>(nanos)); - return true; -} - -Duration TimeUtil::NanosecondsToDuration(int64_t nanos) { - return CreateNormalized<Duration>(nanos / kNanosPerSecond, - nanos % kNanosPerSecond); -} - -Duration TimeUtil::MicrosecondsToDuration(int64_t micros) { - return CreateNormalized<Duration>( - micros / kMicrosPerSecond, - (micros % kMicrosPerSecond) * kNanosPerMicrosecond); -} - -Duration TimeUtil::MillisecondsToDuration(int64_t millis) { - return CreateNormalized<Duration>( - millis / kMillisPerSecond, - (millis % kMillisPerSecond) * kNanosPerMillisecond); -} - -Duration TimeUtil::SecondsToDuration(int64_t seconds) { - return CreateNormalized<Duration>(seconds, 0); -} - -Duration TimeUtil::MinutesToDuration(int64_t minutes) { - return CreateNormalized<Duration>(minutes * kSecondsPerMinute, 0); -} - -Duration TimeUtil::HoursToDuration(int64_t hours) { - return CreateNormalized<Duration>(hours * kSecondsPerHour, 0); -} - -int64_t TimeUtil::DurationToNanoseconds(const Duration& duration) { - return duration.seconds() * kNanosPerSecond + duration.nanos(); -} - -int64_t TimeUtil::DurationToMicroseconds(const Duration& duration) { - return duration.seconds() * kMicrosPerSecond + - RoundTowardZero(duration.nanos(), kNanosPerMicrosecond); -} - -int64_t TimeUtil::DurationToMilliseconds(const Duration& duration) { - return duration.seconds() * kMillisPerSecond + - RoundTowardZero(duration.nanos(), kNanosPerMillisecond); -} - -int64_t TimeUtil::DurationToSeconds(const Duration& duration) { - return duration.seconds(); -} - -int64_t TimeUtil::DurationToMinutes(const Duration& duration) { - return RoundTowardZero(duration.seconds(), kSecondsPerMinute); -} - -int64_t TimeUtil::DurationToHours(const Duration& duration) { - return RoundTowardZero(duration.seconds(), kSecondsPerHour); -} - -Timestamp TimeUtil::NanosecondsToTimestamp(int64_t nanos) { - return CreateNormalized<Timestamp>(nanos / kNanosPerSecond, - nanos % kNanosPerSecond); -} - -Timestamp TimeUtil::MicrosecondsToTimestamp(int64_t micros) { - return CreateNormalized<Timestamp>( - micros / kMicrosPerSecond, - micros % kMicrosPerSecond * kNanosPerMicrosecond); -} - -Timestamp TimeUtil::MillisecondsToTimestamp(int64_t millis) { - return CreateNormalized<Timestamp>( - millis / kMillisPerSecond, - millis % kMillisPerSecond * kNanosPerMillisecond); -} - -Timestamp TimeUtil::SecondsToTimestamp(int64_t seconds) { - return CreateNormalized<Timestamp>(seconds, 0); -} - -int64_t TimeUtil::TimestampToNanoseconds(const Timestamp& timestamp) { - return timestamp.seconds() * kNanosPerSecond + timestamp.nanos(); -} - -int64_t TimeUtil::TimestampToMicroseconds(const Timestamp& timestamp) { - return timestamp.seconds() * kMicrosPerSecond + - RoundTowardZero(timestamp.nanos(), kNanosPerMicrosecond); -} - -int64_t TimeUtil::TimestampToMilliseconds(const Timestamp& timestamp) { - return timestamp.seconds() * kMillisPerSecond + - RoundTowardZero(timestamp.nanos(), kNanosPerMillisecond); -} - -int64_t TimeUtil::TimestampToSeconds(const Timestamp& timestamp) { - return timestamp.seconds(); -} - -Timestamp TimeUtil::TimeTToTimestamp(time_t value) { - return CreateNormalized<Timestamp>(static_cast<int64_t>(value), 0); -} - -time_t TimeUtil::TimestampToTimeT(const Timestamp& value) { - return static_cast<time_t>(value.seconds()); -} - -Timestamp TimeUtil::TimevalToTimestamp(const timeval& value) { - return CreateNormalized<Timestamp>(value.tv_sec, - value.tv_usec * kNanosPerMicrosecond); -} - -timeval TimeUtil::TimestampToTimeval(const Timestamp& value) { - timeval result; - result.tv_sec = value.seconds(); - result.tv_usec = RoundTowardZero(value.nanos(), kNanosPerMicrosecond); - return result; -} - -Duration TimeUtil::TimevalToDuration(const timeval& value) { - return CreateNormalized<Duration>(value.tv_sec, - value.tv_usec * kNanosPerMicrosecond); -} - -timeval TimeUtil::DurationToTimeval(const Duration& value) { - timeval result; - result.tv_sec = value.seconds(); - result.tv_usec = RoundTowardZero(value.nanos(), kNanosPerMicrosecond); - // timeval.tv_usec's range is [0, 1000000) - if (result.tv_usec < 0) { - result.tv_sec -= 1; - result.tv_usec += kMicrosPerSecond; - } - return result; -} - -} // namespace util -} // namespace protobuf -} // namespace google - -namespace google { -namespace protobuf { -namespace { -using ::PROTOBUF_NAMESPACE_ID::util::CreateNormalized; -using ::PROTOBUF_NAMESPACE_ID::util::kNanosPerSecond; - -// Convert a Duration to uint128. -void ToUint128(const Duration& value, uint128* result, bool* negative) { - if (value.seconds() < 0 || value.nanos() < 0) { - *negative = true; - *result = static_cast<uint64_t>(-value.seconds()); - *result = *result * kNanosPerSecond + static_cast<uint32_t>(-value.nanos()); - } else { - *negative = false; - *result = static_cast<uint64_t>(value.seconds()); - *result = *result * kNanosPerSecond + static_cast<uint32_t>(value.nanos()); - } -} - -void ToDuration(const uint128& value, bool negative, Duration* duration) { - int64_t seconds = - static_cast<int64_t>(Uint128Low64(value / kNanosPerSecond)); - int32_t nanos = - static_cast<int32_t>(Uint128Low64(value % kNanosPerSecond)); - if (negative) { - seconds = -seconds; - nanos = -nanos; - } - duration->set_seconds(seconds); - duration->set_nanos(nanos); -} -} // namespace - -Duration& operator+=(Duration& d1, const Duration& d2) { - d1 = CreateNormalized<Duration>(d1.seconds() + d2.seconds(), - d1.nanos() + d2.nanos()); - return d1; -} - -Duration& operator-=(Duration& d1, const Duration& d2) { // NOLINT - d1 = CreateNormalized<Duration>(d1.seconds() - d2.seconds(), - d1.nanos() - d2.nanos()); - return d1; -} - -Duration& operator*=(Duration& d, int64_t r) { // NOLINT - bool negative; - uint128 value; - ToUint128(d, &value, &negative); - if (r > 0) { - value *= static_cast<uint64_t>(r); - } else { - negative = !negative; - value *= static_cast<uint64_t>(-r); - } - ToDuration(value, negative, &d); - return d; -} - -Duration& operator*=(Duration& d, double r) { // NOLINT - double result = (d.seconds() * 1.0 + 1.0 * d.nanos() / kNanosPerSecond) * r; - int64_t seconds = static_cast<int64_t>(result); - int32_t nanos = static_cast<int32_t>((result - seconds) * kNanosPerSecond); - // Note that we normalize here not just because nanos can have a different - // sign from seconds but also that nanos can be any arbitrary value when - // overflow happens (i.e., the result is a much larger value than what - // int64 can represent). - d = CreateNormalized<Duration>(seconds, nanos); - return d; -} - -Duration& operator/=(Duration& d, int64_t r) { // NOLINT - bool negative; - uint128 value; - ToUint128(d, &value, &negative); - if (r > 0) { - value /= static_cast<uint64_t>(r); - } else { - negative = !negative; - value /= static_cast<uint64_t>(-r); - } - ToDuration(value, negative, &d); - return d; -} - -Duration& operator/=(Duration& d, double r) { // NOLINT - return d *= 1.0 / r; -} - -Duration& operator%=(Duration& d1, const Duration& d2) { // NOLINT - bool negative1, negative2; - uint128 value1, value2; - ToUint128(d1, &value1, &negative1); - ToUint128(d2, &value2, &negative2); - uint128 result = value1 % value2; - // When negative values are involved in division, we round the division - // result towards zero. With this semantics, sign of the remainder is the - // same as the dividend. For example: - // -5 / 10 = 0, -5 % 10 = -5 - // -5 / (-10) = 0, -5 % (-10) = -5 - // 5 / (-10) = 0, 5 % (-10) = 5 - ToDuration(result, negative1, &d1); - return d1; -} - -int64_t operator/(const Duration& d1, const Duration& d2) { - bool negative1, negative2; - uint128 value1, value2; - ToUint128(d1, &value1, &negative1); - ToUint128(d2, &value2, &negative2); - int64_t result = Uint128Low64(value1 / value2); - if (negative1 != negative2) { - result = -result; - } - return result; -} - -Timestamp& operator+=(Timestamp& t, const Duration& d) { // NOLINT - t = CreateNormalized<Timestamp>(t.seconds() + d.seconds(), - t.nanos() + d.nanos()); - return t; -} - -Timestamp& operator-=(Timestamp& t, const Duration& d) { // NOLINT - t = CreateNormalized<Timestamp>(t.seconds() - d.seconds(), - t.nanos() - d.nanos()); - return t; -} - -Duration operator-(const Timestamp& t1, const Timestamp& t2) { - return CreateNormalized<Duration>(t1.seconds() - t2.seconds(), - t1.nanos() - t2.nanos()); -} -} // namespace protobuf -} // namespace google diff --git a/contrib/libs/protobuf_std/src/google/protobuf/util/type_resolver.h b/contrib/libs/protobuf_std/src/google/protobuf/util/type_resolver.h deleted file mode 100644 index 2bda5c883c..0000000000 --- a/contrib/libs/protobuf_std/src/google/protobuf/util/type_resolver.h +++ /dev/null @@ -1,76 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Defines 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__ diff --git a/contrib/libs/protobuf_std/src/google/protobuf/util/type_resolver_util.cc b/contrib/libs/protobuf_std/src/google/protobuf/util/type_resolver_util.cc deleted file mode 100644 index c5d4fdf9dd..0000000000 --- a/contrib/libs/protobuf_std/src/google/protobuf/util/type_resolver_util.cc +++ /dev/null @@ -1,370 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include <google/protobuf/util/type_resolver_util.h> - -#include <google/protobuf/type.pb.h> -#include <google/protobuf/wrappers.pb.h> -#include <google/protobuf/descriptor.pb.h> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/util/internal/utility.h> -#include <google/protobuf/util/type_resolver.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/stubs/status.h> -#include <google/protobuf/stubs/status.h> - -// clang-format off -#include <google/protobuf/port_def.inc> -// clang-format on - -namespace google { -namespace protobuf { -namespace util { -namespace { -using google::protobuf::Any; -using google::protobuf::BoolValue; -using google::protobuf::BytesValue; -using google::protobuf::DoubleValue; -using google::protobuf::Enum; -using google::protobuf::EnumValue; -using google::protobuf::Field; -using google::protobuf::FloatValue; -using google::protobuf::Int32Value; -using google::protobuf::Int64Value; -using google::protobuf::Option; -using google::protobuf::StringValue; -using google::protobuf::Type; -using google::protobuf::UInt32Value; -using google::protobuf::UInt64Value; - -class DescriptorPoolTypeResolver : public TypeResolver { - public: - DescriptorPoolTypeResolver(const std::string& url_prefix, - const DescriptorPool* pool) - : url_prefix_(url_prefix), pool_(pool) {} - - util::Status ResolveMessageType(const std::string& type_url, - Type* type) override { - std::string type_name; - util::Status status = ParseTypeUrl(type_url, &type_name); - if (!status.ok()) { - return status; - } - - const Descriptor* descriptor = pool_->FindMessageTypeByName(type_name); - if (descriptor == NULL) { - return util::NotFoundError("Invalid type URL, unknown type: " + - type_name); - } - ConvertDescriptor(descriptor, type); - return util::Status(); - } - - util::Status ResolveEnumType(const std::string& type_url, - Enum* enum_type) override { - std::string type_name; - util::Status status = ParseTypeUrl(type_url, &type_name); - if (!status.ok()) { - return status; - } - - const EnumDescriptor* descriptor = pool_->FindEnumTypeByName(type_name); - if (descriptor == NULL) { - return util::InvalidArgumentError("Invalid type URL, unknown type: " + - type_name); - } - ConvertEnumDescriptor(descriptor, enum_type); - return util::Status(); - } - - private: - void ConvertDescriptor(const Descriptor* descriptor, Type* type) { - type->Clear(); - type->set_name(descriptor->full_name()); - for (int i = 0; i < descriptor->field_count(); ++i) { - ConvertFieldDescriptor(descriptor->field(i), type->add_fields()); - } - for (int i = 0; i < descriptor->oneof_decl_count(); ++i) { - type->add_oneofs(descriptor->oneof_decl(i)->name()); - } - type->mutable_source_context()->set_file_name(descriptor->file()->name()); - ConvertMessageOptions(descriptor->options(), type->mutable_options()); - } - - void ConvertMessageOptions(const MessageOptions& options, - RepeatedPtrField<Option>* output) { - return ConvertOptionsInternal(options, output); - } - - void ConvertFieldOptions(const FieldOptions& options, - RepeatedPtrField<Option>* output) { - return ConvertOptionsInternal(options, output); - } - - void ConvertEnumOptions(const EnumOptions& options, - RepeatedPtrField<Option>* output) { - return ConvertOptionsInternal(options, output); - } - - void ConvertEnumValueOptions(const EnumValueOptions& options, - RepeatedPtrField<Option>* output) { - return ConvertOptionsInternal(options, output); - } - - // Implementation details for Convert*Options. - void ConvertOptionsInternal(const Message& options, - RepeatedPtrField<Option>* output) { - const Reflection* reflection = options.GetReflection(); - std::vector<const FieldDescriptor*> fields; - reflection->ListFields(options, &fields); - for (const FieldDescriptor* field : fields) { - if (field->is_repeated()) { - const int size = reflection->FieldSize(options, field); - for (int i = 0; i < size; i++) { - ConvertOptionField(reflection, options, field, i, output->Add()); - } - } else { - ConvertOptionField(reflection, options, field, -1, output->Add()); - } - } - } - - static void ConvertOptionField(const Reflection* reflection, - const Message& options, - const FieldDescriptor* field, int index, - Option* out) { - out->set_name(field->is_extension() ? field->full_name() : field->name()); - Any* value = out->mutable_value(); - switch (field->cpp_type()) { - case FieldDescriptor::CPPTYPE_MESSAGE: - value->PackFrom( - field->is_repeated() - ? reflection->GetRepeatedMessage(options, field, index) - : reflection->GetMessage(options, field)); - return; - case FieldDescriptor::CPPTYPE_DOUBLE: - value->PackFrom(WrapValue<DoubleValue>( - field->is_repeated() - ? reflection->GetRepeatedDouble(options, field, index) - : reflection->GetDouble(options, field))); - return; - case FieldDescriptor::CPPTYPE_FLOAT: - value->PackFrom(WrapValue<FloatValue>( - field->is_repeated() - ? reflection->GetRepeatedFloat(options, field, index) - : reflection->GetFloat(options, field))); - return; - case FieldDescriptor::CPPTYPE_INT64: - value->PackFrom(WrapValue<Int64Value>( - field->is_repeated() - ? reflection->GetRepeatedInt64(options, field, index) - : reflection->GetInt64(options, field))); - return; - case FieldDescriptor::CPPTYPE_UINT64: - value->PackFrom(WrapValue<UInt64Value>( - field->is_repeated() - ? reflection->GetRepeatedUInt64(options, field, index) - : reflection->GetUInt64(options, field))); - return; - case FieldDescriptor::CPPTYPE_INT32: - value->PackFrom(WrapValue<Int32Value>( - field->is_repeated() - ? reflection->GetRepeatedInt32(options, field, index) - : reflection->GetInt32(options, field))); - return; - case FieldDescriptor::CPPTYPE_UINT32: - value->PackFrom(WrapValue<UInt32Value>( - field->is_repeated() - ? reflection->GetRepeatedUInt32(options, field, index) - : reflection->GetUInt32(options, field))); - return; - case FieldDescriptor::CPPTYPE_BOOL: - value->PackFrom(WrapValue<BoolValue>( - field->is_repeated() - ? reflection->GetRepeatedBool(options, field, index) - : reflection->GetBool(options, field))); - return; - case FieldDescriptor::CPPTYPE_STRING: { - const std::string& val = - field->is_repeated() - ? reflection->GetRepeatedString(options, field, index) - : reflection->GetString(options, field); - if (field->type() == FieldDescriptor::TYPE_STRING) { - value->PackFrom(WrapValue<StringValue>(val)); - } else { - value->PackFrom(WrapValue<BytesValue>(val)); - } - return; - } - case FieldDescriptor::CPPTYPE_ENUM: { - const EnumValueDescriptor* val = - field->is_repeated() - ? reflection->GetRepeatedEnum(options, field, index) - : reflection->GetEnum(options, field); - value->PackFrom(WrapValue<Int32Value>(val->number())); - return; - } - } - } - - template <typename WrapperT, typename T> - static WrapperT WrapValue(T value) { - WrapperT wrapper; - wrapper.set_value(value); - return wrapper; - } - - void ConvertFieldDescriptor(const FieldDescriptor* descriptor, Field* field) { - field->set_kind(static_cast<Field::Kind>(descriptor->type())); - switch (descriptor->label()) { - case FieldDescriptor::LABEL_OPTIONAL: - field->set_cardinality(Field::CARDINALITY_OPTIONAL); - break; - case FieldDescriptor::LABEL_REPEATED: - field->set_cardinality(Field::CARDINALITY_REPEATED); - break; - case FieldDescriptor::LABEL_REQUIRED: - field->set_cardinality(Field::CARDINALITY_REQUIRED); - break; - } - field->set_number(descriptor->number()); - field->set_name(descriptor->name()); - field->set_json_name(descriptor->json_name()); - if (descriptor->has_default_value()) { - field->set_default_value(DefaultValueAsString(descriptor)); - } - if (descriptor->type() == FieldDescriptor::TYPE_MESSAGE || - descriptor->type() == FieldDescriptor::TYPE_GROUP) { - field->set_type_url(GetTypeUrl(descriptor->message_type())); - } else if (descriptor->type() == FieldDescriptor::TYPE_ENUM) { - field->set_type_url(GetTypeUrl(descriptor->enum_type())); - } - if (descriptor->containing_oneof() != NULL) { - field->set_oneof_index(descriptor->containing_oneof()->index() + 1); - } - if (descriptor->is_packed()) { - field->set_packed(true); - } - - ConvertFieldOptions(descriptor->options(), field->mutable_options()); - } - - void ConvertEnumDescriptor(const EnumDescriptor* descriptor, - Enum* enum_type) { - enum_type->Clear(); - enum_type->set_name(descriptor->full_name()); - enum_type->mutable_source_context()->set_file_name( - descriptor->file()->name()); - for (int i = 0; i < descriptor->value_count(); ++i) { - const EnumValueDescriptor* value_descriptor = descriptor->value(i); - EnumValue* value = enum_type->mutable_enumvalue()->Add(); - value->set_name(value_descriptor->name()); - value->set_number(value_descriptor->number()); - - ConvertEnumValueOptions(value_descriptor->options(), - value->mutable_options()); - } - - ConvertEnumOptions(descriptor->options(), enum_type->mutable_options()); - } - - std::string GetTypeUrl(const Descriptor* descriptor) { - return url_prefix_ + "/" + descriptor->full_name(); - } - - std::string GetTypeUrl(const EnumDescriptor* descriptor) { - return url_prefix_ + "/" + descriptor->full_name(); - } - - util::Status ParseTypeUrl(const std::string& type_url, - std::string* type_name) { - if (type_url.substr(0, url_prefix_.size() + 1) != url_prefix_ + "/") { - return util::InvalidArgumentError( - StrCat("Invalid type URL, type URLs must be of the form '", - url_prefix_, "/<typename>', got: ", type_url)); - } - *type_name = type_url.substr(url_prefix_.size() + 1); - return util::Status(); - } - - std::string DefaultValueAsString(const FieldDescriptor* descriptor) { - switch (descriptor->cpp_type()) { - case FieldDescriptor::CPPTYPE_INT32: - return StrCat(descriptor->default_value_int32()); - break; - case FieldDescriptor::CPPTYPE_INT64: - return StrCat(descriptor->default_value_int64()); - break; - case FieldDescriptor::CPPTYPE_UINT32: - return StrCat(descriptor->default_value_uint32()); - break; - case FieldDescriptor::CPPTYPE_UINT64: - return StrCat(descriptor->default_value_uint64()); - break; - case FieldDescriptor::CPPTYPE_FLOAT: - return SimpleFtoa(descriptor->default_value_float()); - break; - case FieldDescriptor::CPPTYPE_DOUBLE: - return SimpleDtoa(descriptor->default_value_double()); - break; - case FieldDescriptor::CPPTYPE_BOOL: - return descriptor->default_value_bool() ? "true" : "false"; - break; - case FieldDescriptor::CPPTYPE_STRING: - if (descriptor->type() == FieldDescriptor::TYPE_BYTES) { - return CEscape(descriptor->default_value_string()); - } else { - return descriptor->default_value_string(); - } - break; - case FieldDescriptor::CPPTYPE_ENUM: - return descriptor->default_value_enum()->name(); - break; - case FieldDescriptor::CPPTYPE_MESSAGE: - GOOGLE_LOG(DFATAL) << "Messages can't have default values!"; - break; - } - return ""; - } - - std::string url_prefix_; - const DescriptorPool* pool_; -}; - -} // namespace - -TypeResolver* NewTypeResolverForDescriptorPool(const std::string& url_prefix, - const DescriptorPool* pool) { - return new DescriptorPoolTypeResolver(url_prefix, pool); -} - -} // namespace util -} // namespace protobuf -} // namespace google diff --git a/contrib/libs/protobuf_std/src/google/protobuf/util/type_resolver_util.h b/contrib/libs/protobuf_std/src/google/protobuf/util/type_resolver_util.h deleted file mode 100644 index fa912b6041..0000000000 --- a/contrib/libs/protobuf_std/src/google/protobuf/util/type_resolver_util.h +++ /dev/null @@ -1,57 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Defines utilities for the 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__ |