diff options
Diffstat (limited to 'src/google/protobuf/util/internal')
40 files changed, 1030 insertions, 712 deletions
diff --git a/src/google/protobuf/util/internal/constants.h b/src/google/protobuf/util/internal/constants.h index a018a09e..3ace10cf 100644 --- a/src/google/protobuf/util/internal/constants.h +++ b/src/google/protobuf/util/internal/constants.h @@ -96,6 +96,9 @@ const char kAnyType[] = "google.protobuf.Any"; const char kFieldMaskTypeUrl[] = "type.googleapis.com/google.protobuf.FieldMask"; +// The protobuf option name of jspb.message_id; +const char kOptionJspbMessageId[] = "jspb.message_id"; + } // namespace converter } // namespace util } // namespace protobuf diff --git a/src/google/protobuf/util/internal/datapiece.cc b/src/google/protobuf/util/internal/datapiece.cc index 59bc28ae..72b7d17a 100644 --- a/src/google/protobuf/util/internal/datapiece.cc +++ b/src/google/protobuf/util/internal/datapiece.cc @@ -43,8 +43,6 @@ namespace protobuf { namespace util { namespace converter { -using google::protobuf::EnumDescriptor; -using google::protobuf::EnumValueDescriptor; ; ; ; @@ -130,7 +128,8 @@ StatusOr<int32> DataPiece::ToInt32() const { } StatusOr<uint32> DataPiece::ToUint32() const { - if (type_ == TYPE_STRING) return StringToNumber<uint32>(safe_strtou32); + if (type_ == TYPE_STRING) + return StringToNumber<uint32>(safe_strtou32); if (type_ == TYPE_DOUBLE) return FloatingPointToIntConvertAndCheck<uint32, double>(double_); @@ -154,7 +153,8 @@ StatusOr<int64> DataPiece::ToInt64() const { } StatusOr<uint64> DataPiece::ToUint64() const { - if (type_ == TYPE_STRING) return StringToNumber<uint64>(safe_strtou64); + if (type_ == TYPE_STRING) + return StringToNumber<uint64>(safe_strtou64); if (type_ == TYPE_DOUBLE) return FloatingPointToIntConvertAndCheck<uint64, double>(double_); @@ -215,7 +215,7 @@ StatusOr<bool> DataPiece::ToBool() const { StatusOr<string> DataPiece::ToString() const { switch (type_) { case TYPE_STRING: - return str_.ToString(); + return string(str_); case TYPE_BYTES: { string base64; Base64Escape(str_, &base64); @@ -227,7 +227,8 @@ StatusOr<string> DataPiece::ToString() const { } } -string DataPiece::ValueAsStringOrDefault(StringPiece default_string) const { +string DataPiece::ValueAsStringOrDefault( + StringPiece default_string) const { switch (type_) { case TYPE_INT32: return SimpleItoa(i32_); @@ -253,7 +254,7 @@ string DataPiece::ValueAsStringOrDefault(StringPiece default_string) const { case TYPE_NULL: return "null"; default: - return default_string.ToString(); + return string(default_string); } } @@ -273,12 +274,13 @@ StatusOr<string> DataPiece::ToBytes() const { StatusOr<int> DataPiece::ToEnum(const google::protobuf::Enum* enum_type, bool use_lower_camel_for_enums, - bool ignore_unknown_enum_values) const { + 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. - string enum_name = str_.ToString(); + string enum_name = string(str_); const google::protobuf::EnumValue* value = FindEnumValueByNameOrNull(enum_type, enum_name); if (value != nullptr) return value->number(); @@ -307,9 +309,11 @@ StatusOr<int> DataPiece::ToEnum(const google::protobuf::Enum* enum_type, if (value != nullptr) return value->number(); } - // If ignore_unknown_enum_values is true an unknown enum value is treated - // as the default - if (ignore_unknown_enum_values) return enum_type->enumvalue(0).number(); + // If ignore_unknown_enum_values is true an unknown enum value is ignored. + if (ignore_unknown_enum_values) { + *is_unknown_enum_value = true; + 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. @@ -342,13 +346,14 @@ StatusOr<To> DataPiece::GenericConvert() const { } template <typename To> -StatusOr<To> DataPiece::StringToNumber(bool (*func)(StringPiece, To*)) const { +StatusOr<To> DataPiece::StringToNumber(bool (*func)(StringPiece, + To*)) const { if (str_.size() > 0 && (str_[0] == ' ' || str_[str_.size() - 1] == ' ')) { return InvalidArgument(StrCat("\"", str_, "\"")); } To result; if (func(str_, &result)) return result; - return InvalidArgument(StrCat("\"", str_.ToString(), "\"")); + return InvalidArgument(StrCat("\"", string(str_), "\"")); } bool DataPiece::DecodeBase64(StringPiece src, string* dest) const { diff --git a/src/google/protobuf/util/internal/datapiece.h b/src/google/protobuf/util/internal/datapiece.h index 95b133da..556c0ec4 100644 --- a/src/google/protobuf/util/internal/datapiece.h +++ b/src/google/protobuf/util/internal/datapiece.h @@ -37,16 +37,19 @@ #include <google/protobuf/stubs/stringpiece.h> #include <google/protobuf/stubs/statusor.h> +#include <google/protobuf/port_def.inc> namespace google { namespace protobuf { class Enum; } // namespace protobuf +} // namespace google - +namespace google { namespace protobuf { namespace util { namespace converter { +class ProtoWriter; // Container for a single piece of data together with its data type. // @@ -57,7 +60,7 @@ namespace converter { // Just like StringPiece, the DataPiece class does not own the storage for // the actual string or Cord, so it is the user's responsiblity to guarantee // that the underlying storage is still valid when the DataPiece is accessed. -class LIBPROTOBUF_EXPORT DataPiece { +class PROTOBUF_EXPORT DataPiece { public: // Identifies data type of the value. // These are the types supported by DataPiece. @@ -120,7 +123,7 @@ class LIBPROTOBUF_EXPORT DataPiece { bool use_strict_base64_decoding() { return use_strict_base64_decoding_; } StringPiece str() const { - GOOGLE_LOG_IF(DFATAL, type_ != TYPE_STRING) << "Not a string type."; + GOOGLE_LOG_IF(DFATAL, type_ != TYPE_STRING) << "Not a std::string type."; return str_; } @@ -147,13 +150,13 @@ class LIBPROTOBUF_EXPORT DataPiece { util::StatusOr<bool> ToBool() const; // Parses, casts or converts the value stored in the DataPiece into a string. - util::StatusOr<string> ToString() const; + 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. - string ValueAsStringOrDefault(StringPiece default_string) const; + std::string ValueAsStringOrDefault(StringPiece default_string) const; - util::StatusOr<string> ToBytes() const; + util::StatusOr<std::string> ToBytes() const; // Converts a value into protocol buffer enum number. If the value is a // string, first attempts conversion by name, trying names as follows: @@ -164,10 +167,13 @@ class LIBPROTOBUF_EXPORT DataPiece { // If the value is not a string, attempts to convert to a 32-bit integer. // If none of these succeeds, returns a conversion error status. util::StatusOr<int> ToEnum(const google::protobuf::Enum* enum_type, - bool use_lower_camel_for_enums, - bool ignore_unknown_enum_values) const; + bool use_lower_camel_for_enums) const { + return ToEnum(enum_type, use_lower_camel_for_enums, false, nullptr); + } private: + friend class ProtoWriter; + // Disallow implicit constructor. DataPiece(); @@ -175,6 +181,13 @@ class LIBPROTOBUF_EXPORT DataPiece { DataPiece(Type type, int32 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 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> @@ -183,10 +196,11 @@ class LIBPROTOBUF_EXPORT DataPiece { // 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; + util::StatusOr<To> StringToNumber(bool (*func)(StringPiece, + To*)) const; // Decodes a base64 string. Returns true on success. - bool DecodeBase64(StringPiece src, string* dest) const; + bool DecodeBase64(StringPiece src, std::string* dest) const; // Helper function to initialize this DataPiece with 'other'. void InternalCopy(const DataPiece& other); @@ -215,6 +229,8 @@ class LIBPROTOBUF_EXPORT DataPiece { } // namespace converter } // namespace util } // namespace protobuf - } // namespace google + +#include <google/protobuf/port_undef.inc> + #endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_DATAPIECE_H__ diff --git a/src/google/protobuf/util/internal/default_value_objectwriter.cc b/src/google/protobuf/util/internal/default_value_objectwriter.cc index b41feb7a..c1d31012 100644 --- a/src/google/protobuf/util/internal/default_value_objectwriter.cc +++ b/src/google/protobuf/util/internal/default_value_objectwriter.cc @@ -30,7 +30,7 @@ #include <google/protobuf/util/internal/default_value_objectwriter.h> -#include <google/protobuf/stubs/hash.h> +#include <unordered_map> #include <google/protobuf/util/internal/constants.h> #include <google/protobuf/util/internal/utility.h> @@ -48,8 +48,8 @@ namespace { // 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, StatusOr<T> (DataPiece::*converter_fn)() const, - T default_value) { +T ConvertTo(StringPiece value, + StatusOr<T> (DataPiece::*converter_fn)() const, T default_value) { if (value.empty()) return default_value; StatusOr<T> result = (DataPiece(value, true).*converter_fn)(); return result.ok() ? result.ValueOrDie() : default_value; @@ -79,8 +79,8 @@ DefaultValueObjectWriter::~DefaultValueObjectWriter() { } } -DefaultValueObjectWriter* DefaultValueObjectWriter::RenderBool(StringPiece name, - bool value) { +DefaultValueObjectWriter* DefaultValueObjectWriter::RenderBool( + StringPiece name, bool value) { if (current_ == nullptr) { ow_->RenderBool(name, value); } else { @@ -156,7 +156,7 @@ DefaultValueObjectWriter* DefaultValueObjectWriter::RenderString( } else { // Since StringPiece is essentially a pointer, takes a copy of "value" to // avoid ownership issues. - string_values_.push_back(new string(value.ToString())); + string_values_.push_back(new string(value)); RenderDataPiece(name, DataPiece(*string_values_.back(), true)); } return this; @@ -193,42 +193,18 @@ void DefaultValueObjectWriter::RegisterFieldScrubCallBack( DefaultValueObjectWriter::Node* DefaultValueObjectWriter::CreateNewNode( const string& name, const google::protobuf::Type* type, NodeKind kind, const DataPiece& data, bool is_placeholder, const std::vector<string>& path, - bool suppress_empty_list, FieldScrubCallBack* field_scrub_callback) { - return new Node(name, type, kind, data, is_placeholder, path, - suppress_empty_list, field_scrub_callback); -} - -DefaultValueObjectWriter::Node* DefaultValueObjectWriter::CreateNewNode( - const string& name, const google::protobuf::Type* type, NodeKind kind, - const DataPiece& data, bool is_placeholder, const std::vector<string>& path, - bool suppress_empty_list, bool preserve_proto_field_names, bool use_ints_for_enums, - FieldScrubCallBack* field_scrub_callback) { + 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, - field_scrub_callback); + suppress_empty_list, preserve_proto_field_names, + use_ints_for_enums, field_scrub_callback); } DefaultValueObjectWriter::Node::Node( const string& name, const google::protobuf::Type* type, NodeKind kind, const DataPiece& data, bool is_placeholder, const std::vector<string>& path, - bool suppress_empty_list, 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_(false), - use_ints_for_enums_(false), - field_scrub_callback_(field_scrub_callback) {} - -DefaultValueObjectWriter::Node::Node( - const string& name, const google::protobuf::Type* type, NodeKind kind, - const DataPiece& data, bool is_placeholder, const std::vector<string>& path, - bool suppress_empty_list, bool preserve_proto_field_names, bool use_ints_for_enums, - FieldScrubCallBack* field_scrub_callback) + bool suppress_empty_list, bool preserve_proto_field_names, + bool use_ints_for_enums, FieldScrubCallBack* field_scrub_callback) : name_(name), type_(type), kind_(kind), @@ -337,7 +313,7 @@ void DefaultValueObjectWriter::Node::PopulateChildren( return; } std::vector<Node*> new_children; - hash_map<string, int> orig_children_map; + std::unordered_map<string, int> orig_children_map; // Creates a map of child nodes to speed up lookup. for (int i = 0; i < children_.size(); ++i) { @@ -359,7 +335,7 @@ void DefaultValueObjectWriter::Node::PopulateChildren( continue; } - hash_map<string, int>::iterator found = + std::unordered_map<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. @@ -408,13 +384,14 @@ void DefaultValueObjectWriter::Node::PopulateChildren( // 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_)); + 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. @@ -438,7 +415,8 @@ void DefaultValueObjectWriter::MaybePopulateChildrenOfAny(Node* node) { } DataPiece DefaultValueObjectWriter::FindEnumDefault( - const google::protobuf::Field& field, const TypeInfo* typeinfo, bool use_ints_for_enums) { + const google::protobuf::Field& field, const TypeInfo* typeinfo, + bool use_ints_for_enums) { if (!field.default_value().empty()) return DataPiece(field.default_value(), true); @@ -451,12 +429,15 @@ DataPiece DefaultValueObjectWriter::FindEnumDefault( } // 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)) + ? (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) { + const google::protobuf::Field& field, const TypeInfo* typeinfo, + bool use_ints_for_enums) { switch (field.kind()) { case google::protobuf::Field_Kind_TYPE_DOUBLE: { return DataPiece(ConvertTo<double>( @@ -509,10 +490,10 @@ DefaultValueObjectWriter* DefaultValueObjectWriter::StartObject( StringPiece name) { if (current_ == nullptr) { std::vector<string> path; - root_.reset(CreateNewNode(string(name), &type_, OBJECT, - DataPiece::NullData(), false, path, - suppress_empty_list_, preserve_proto_field_names_, use_ints_for_enums_, - field_scrub_callback_.get())); + root_.reset(CreateNewNode( + string(name), &type_, OBJECT, DataPiece::NullData(), false, path, + suppress_empty_list_, preserve_proto_field_names_, use_ints_for_enums_, + field_scrub_callback_.get())); root_->PopulateChildren(typeinfo_); current_ = root_.get(); return this; @@ -529,8 +510,8 @@ DefaultValueObjectWriter* DefaultValueObjectWriter::StartObject( : 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_.get())); + suppress_empty_list_, preserve_proto_field_names_, + use_ints_for_enums_, field_scrub_callback_.get())); child = node.get(); current_->AddChild(node.release()); } @@ -573,8 +554,8 @@ DefaultValueObjectWriter* DefaultValueObjectWriter::StartList( std::unique_ptr<Node> node( CreateNewNode(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_.get())); + suppress_empty_list_, preserve_proto_field_names_, + use_ints_for_enums_, field_scrub_callback_.get())); child = node.get(); current_->AddChild(node.release()); } @@ -635,8 +616,8 @@ void DefaultValueObjectWriter::RenderDataPiece(StringPiece name, std::unique_ptr<Node> node( CreateNewNode(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_.get())); + suppress_empty_list_, preserve_proto_field_names_, + use_ints_for_enums_, field_scrub_callback_.get())); current_->AddChild(node.release()); } else { child->set_data(data); diff --git a/src/google/protobuf/util/internal/default_value_objectwriter.h b/src/google/protobuf/util/internal/default_value_objectwriter.h index 7d245c9c..7a8863ca 100644 --- a/src/google/protobuf/util/internal/default_value_objectwriter.h +++ b/src/google/protobuf/util/internal/default_value_objectwriter.h @@ -44,6 +44,8 @@ #include <google/protobuf/util/type_resolver.h> #include <google/protobuf/stubs/stringpiece.h> +#include <google/protobuf/port_def.inc> + namespace google { namespace protobuf { namespace util { @@ -55,7 +57,7 @@ namespace converter { // 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 LIBPROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter { +class PROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter { public: // A Callback function to check whether a field needs to be scrubbed. // @@ -69,7 +71,7 @@ class LIBPROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter { // // The Field* should point to the google::protobuf::Field of "c". typedef ResultCallback2<bool /*return*/, - const std::vector<string>& /*path of the field*/, + const std::vector<std::string>& /*path of the field*/, const google::protobuf::Field* /*field*/> FieldScrubCallBack; @@ -83,37 +85,41 @@ class LIBPROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter { virtual ~DefaultValueObjectWriter(); // ObjectWriter methods. - virtual DefaultValueObjectWriter* StartObject(StringPiece name) override; + DefaultValueObjectWriter* StartObject(StringPiece name) override; - virtual DefaultValueObjectWriter* EndObject() override; + DefaultValueObjectWriter* EndObject() override; - virtual DefaultValueObjectWriter* StartList(StringPiece name) override; + DefaultValueObjectWriter* StartList(StringPiece name) override; - virtual DefaultValueObjectWriter* EndList() override; + DefaultValueObjectWriter* EndList() override; - virtual DefaultValueObjectWriter* RenderBool(StringPiece name, bool value) override; + DefaultValueObjectWriter* RenderBool(StringPiece name, + bool value) override; - virtual DefaultValueObjectWriter* RenderInt32(StringPiece name, int32 value) override; + DefaultValueObjectWriter* RenderInt32(StringPiece name, + int32 value) override; - virtual DefaultValueObjectWriter* RenderUint32(StringPiece name, + DefaultValueObjectWriter* RenderUint32(StringPiece name, uint32 value) override; - virtual DefaultValueObjectWriter* RenderInt64(StringPiece name, int64 value) override; + DefaultValueObjectWriter* RenderInt64(StringPiece name, + int64 value) override; - virtual DefaultValueObjectWriter* RenderUint64(StringPiece name, + DefaultValueObjectWriter* RenderUint64(StringPiece name, uint64 value) override; - virtual DefaultValueObjectWriter* RenderDouble(StringPiece name, + DefaultValueObjectWriter* RenderDouble(StringPiece name, double value) override; - virtual DefaultValueObjectWriter* RenderFloat(StringPiece name, float value) override; + DefaultValueObjectWriter* RenderFloat(StringPiece name, + float value) override; - virtual DefaultValueObjectWriter* RenderString(StringPiece name, + DefaultValueObjectWriter* RenderString(StringPiece name, StringPiece value) override; - virtual DefaultValueObjectWriter* RenderBytes(StringPiece name, + DefaultValueObjectWriter* RenderBytes(StringPiece name, StringPiece value) override; - virtual DefaultValueObjectWriter* RenderNull(StringPiece name) override; + virtual DefaultValueObjectWriter* RenderNull(StringPiece name); // Register the callback for scrubbing of fields. Owership of // field_scrub_callback pointer is also transferred to this class @@ -130,9 +136,7 @@ class LIBPROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter { // 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; - } + void set_print_enums_as_ints(bool value) { use_ints_for_enums_ = value; } protected: enum NodeKind { @@ -144,15 +148,11 @@ class LIBPROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter { // "Node" represents a node in the tree that holds the input of // DefaultValueObjectWriter. - class LIBPROTOBUF_EXPORT Node { + class PROTOBUF_EXPORT Node { public: - Node(const string& name, const google::protobuf::Type* type, NodeKind kind, - const DataPiece& data, bool is_placeholder, - const std::vector<string>& path, bool suppress_empty_list, - FieldScrubCallBack* field_scrub_callback); - Node(const string& name, const google::protobuf::Type* type, NodeKind kind, + Node(const std::string& name, const google::protobuf::Type* type, NodeKind kind, const DataPiece& data, bool is_placeholder, - const std::vector<string>& path, bool suppress_empty_list, + 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() { @@ -178,9 +178,9 @@ class LIBPROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter { virtual void WriteTo(ObjectWriter* ow); // Accessors - const string& name() const { return name_; } + const std::string& name() const { return name_; } - const std::vector<string>& path() const { return path_; } + const std::vector<std::string>& path() const { return path_; } const google::protobuf::Type* type() const { return type_; } @@ -210,7 +210,7 @@ class LIBPROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter { void WriteChildren(ObjectWriter* ow); // The name of this node. - string name_; + std::string name_; // google::protobuf::Type of this node. Owned by TypeInfo. const google::protobuf::Type* type_; // The kind of this node. @@ -228,7 +228,7 @@ class LIBPROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter { bool is_placeholder_; // Path of the field of this node - std::vector<string> path_; + std::vector<std::string> path_; // Whether to suppress empty list output. bool suppress_empty_list_; @@ -248,18 +248,10 @@ class LIBPROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter { }; // Creates a new Node and returns it. Caller owns memory of returned object. - virtual Node* CreateNewNode(const string& name, - const google::protobuf::Type* type, NodeKind kind, - const DataPiece& data, bool is_placeholder, - const std::vector<string>& path, - bool suppress_empty_list, - FieldScrubCallBack* field_scrub_callback); - - // Creates a new Node and returns it. Caller owns memory of returned object. - virtual Node* CreateNewNode(const string& name, + virtual Node* CreateNewNode(const std::string& name, const google::protobuf::Type* type, NodeKind kind, const DataPiece& data, bool is_placeholder, - const std::vector<string>& path, + const std::vector<std::string>& path, bool suppress_empty_list, bool preserve_proto_field_names, bool use_ints_for_enums, @@ -267,7 +259,14 @@ class LIBPROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter { // Creates a DataPiece containing the default value of the type of the field. static DataPiece CreateDefaultDataPieceForField( - const google::protobuf::Field& field, const TypeInfo* typeinfo, bool use_ints_for_enums); + 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. @@ -300,7 +299,7 @@ class LIBPROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter { // google::protobuf::Type of the root message type. const google::protobuf::Type& type_; // Holds copies of strings passed to RenderString. - std::vector<string*> string_values_; + std::vector<std::string*> string_values_; // The current Node. Owned by its parents. Node* current_; @@ -330,6 +329,8 @@ class LIBPROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter { } // 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/src/google/protobuf/util/internal/error_listener.h b/src/google/protobuf/util/internal/error_listener.h index e3baa224..c2b7560d 100644 --- a/src/google/protobuf/util/internal/error_listener.h +++ b/src/google/protobuf/util/internal/error_listener.h @@ -42,23 +42,27 @@ #include <google/protobuf/util/internal/location_tracker.h> #include <google/protobuf/stubs/stringpiece.h> +#include <google/protobuf/port_def.inc> + namespace google { namespace protobuf { namespace util { namespace converter { // Interface for error listener. -class LIBPROTOBUF_EXPORT ErrorListener { +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; + 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; + StringPiece type_name, + StringPiece value) = 0; // Reports a missing required field. virtual void MissingField(const LocationTrackerInterface& loc, @@ -73,18 +77,20 @@ class LIBPROTOBUF_EXPORT ErrorListener { }; // An error listener that ignores all errors. -class LIBPROTOBUF_EXPORT NoopErrorListener : public ErrorListener { +class PROTOBUF_EXPORT NoopErrorListener : public ErrorListener { public: NoopErrorListener() {} - virtual ~NoopErrorListener() override {} + ~NoopErrorListener() override {} - virtual void InvalidName(const LocationTrackerInterface& loc, - StringPiece invalid_name, StringPiece message) override {} + void InvalidName(const LocationTrackerInterface& loc, + StringPiece invalid_name, + StringPiece message) override {} - virtual void InvalidValue(const LocationTrackerInterface &loc, StringPiece type_name, + void InvalidValue(const LocationTrackerInterface& loc, + StringPiece type_name, StringPiece value) override {} - virtual void MissingField(const LocationTrackerInterface &loc, + void MissingField(const LocationTrackerInterface& loc, StringPiece missing_name) override {} private: @@ -95,6 +101,8 @@ class LIBPROTOBUF_EXPORT NoopErrorListener : public ErrorListener { } // 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/src/google/protobuf/util/internal/expecting_objectwriter.h b/src/google/protobuf/util/internal/expecting_objectwriter.h index ae98ddd8..108a15b9 100644 --- a/src/google/protobuf/util/internal/expecting_objectwriter.h +++ b/src/google/protobuf/util/internal/expecting_objectwriter.h @@ -54,6 +54,7 @@ #include <google/protobuf/util/internal/object_writer.h> #include <gmock/gmock.h> + namespace google { namespace protobuf { namespace util { @@ -81,7 +82,8 @@ class MockObjectWriter : public ObjectWriter { MOCK_METHOD2(RenderUint64, ObjectWriter*(StringPiece, uint64)); MOCK_METHOD2(RenderDouble, ObjectWriter*(StringPiece, double)); MOCK_METHOD2(RenderFloat, ObjectWriter*(StringPiece, float)); - MOCK_METHOD2(RenderString, ObjectWriter*(StringPiece, StringPiece)); + MOCK_METHOD2(RenderString, + ObjectWriter*(StringPiece, StringPiece)); MOCK_METHOD2(RenderBytes, ObjectWriter*(StringPiece, StringPiece)); MOCK_METHOD1(RenderNull, ObjectWriter*(StringPiece)); }; @@ -91,9 +93,8 @@ class ExpectingObjectWriter : public ObjectWriter { explicit ExpectingObjectWriter(MockObjectWriter* mock) : mock_(mock) {} virtual ObjectWriter* StartObject(StringPiece name) { - (name.empty() - ? EXPECT_CALL(*mock_, StartObject(IsEmpty())) - : EXPECT_CALL(*mock_, StartObject(StrEq(name.ToString())))) + (name.empty() ? EXPECT_CALL(*mock_, StartObject(IsEmpty())) + : EXPECT_CALL(*mock_, StartObject(StrEq(std::string(name))))) .WillOnce(Return(mock_)) .RetiresOnSaturation(); return this; @@ -107,9 +108,8 @@ class ExpectingObjectWriter : public ObjectWriter { } virtual ObjectWriter* StartList(StringPiece name) { - (name.empty() - ? EXPECT_CALL(*mock_, StartList(IsEmpty())) - : EXPECT_CALL(*mock_, StartList(StrEq(name.ToString())))) + (name.empty() ? EXPECT_CALL(*mock_, StartList(IsEmpty())) + : EXPECT_CALL(*mock_, StartList(StrEq(std::string(name))))) .WillOnce(Return(mock_)) .RetiresOnSaturation(); return this; @@ -125,8 +125,8 @@ class ExpectingObjectWriter : public ObjectWriter { virtual ObjectWriter* RenderBool(StringPiece name, bool value) { (name.empty() ? EXPECT_CALL(*mock_, RenderBool(IsEmpty(), TypedEq<bool>(value))) - : EXPECT_CALL(*mock_, RenderBool(StrEq(name.ToString()), - TypedEq<bool>(value)))) + : EXPECT_CALL(*mock_, + RenderBool(StrEq(std::string(name)), TypedEq<bool>(value)))) .WillOnce(Return(mock_)) .RetiresOnSaturation(); return this; @@ -135,8 +135,8 @@ class ExpectingObjectWriter : public ObjectWriter { virtual ObjectWriter* RenderInt32(StringPiece name, int32 value) { (name.empty() ? EXPECT_CALL(*mock_, RenderInt32(IsEmpty(), TypedEq<int32>(value))) - : EXPECT_CALL(*mock_, RenderInt32(StrEq(name.ToString()), - TypedEq<int32>(value)))) + : EXPECT_CALL(*mock_, + RenderInt32(StrEq(std::string(name)), TypedEq<int32>(value)))) .WillOnce(Return(mock_)) .RetiresOnSaturation(); return this; @@ -145,7 +145,7 @@ class ExpectingObjectWriter : public ObjectWriter { virtual ObjectWriter* RenderUint32(StringPiece name, uint32 value) { (name.empty() ? EXPECT_CALL(*mock_, RenderUint32(IsEmpty(), TypedEq<uint32>(value))) - : EXPECT_CALL(*mock_, RenderUint32(StrEq(name.ToString()), + : EXPECT_CALL(*mock_, RenderUint32(StrEq(std::string(name)), TypedEq<uint32>(value)))) .WillOnce(Return(mock_)) .RetiresOnSaturation(); @@ -155,8 +155,8 @@ class ExpectingObjectWriter : public ObjectWriter { virtual ObjectWriter* RenderInt64(StringPiece name, int64 value) { (name.empty() ? EXPECT_CALL(*mock_, RenderInt64(IsEmpty(), TypedEq<int64>(value))) - : EXPECT_CALL(*mock_, RenderInt64(StrEq(name.ToString()), - TypedEq<int64>(value)))) + : EXPECT_CALL(*mock_, + RenderInt64(StrEq(std::string(name)), TypedEq<int64>(value)))) .WillOnce(Return(mock_)) .RetiresOnSaturation(); return this; @@ -165,7 +165,7 @@ class ExpectingObjectWriter : public ObjectWriter { virtual ObjectWriter* RenderUint64(StringPiece name, uint64 value) { (name.empty() ? EXPECT_CALL(*mock_, RenderUint64(IsEmpty(), TypedEq<uint64>(value))) - : EXPECT_CALL(*mock_, RenderUint64(StrEq(name.ToString()), + : EXPECT_CALL(*mock_, RenderUint64(StrEq(std::string(name)), TypedEq<uint64>(value)))) .WillOnce(Return(mock_)) .RetiresOnSaturation(); @@ -174,9 +174,9 @@ class ExpectingObjectWriter : public ObjectWriter { virtual ObjectWriter* RenderDouble(StringPiece name, double value) { (name.empty() - ? EXPECT_CALL(*mock_, RenderDouble(IsEmpty(), - NanSensitiveDoubleEq(value))) - : EXPECT_CALL(*mock_, RenderDouble(StrEq(name.ToString()), + ? EXPECT_CALL(*mock_, + RenderDouble(IsEmpty(), NanSensitiveDoubleEq(value))) + : EXPECT_CALL(*mock_, RenderDouble(StrEq(std::string(name)), NanSensitiveDoubleEq(value)))) .WillOnce(Return(mock_)) .RetiresOnSaturation(); @@ -185,21 +185,24 @@ class ExpectingObjectWriter : public ObjectWriter { virtual ObjectWriter* RenderFloat(StringPiece name, float value) { (name.empty() - ? EXPECT_CALL(*mock_, RenderFloat(IsEmpty(), - NanSensitiveFloatEq(value))) - : EXPECT_CALL(*mock_, RenderFloat(StrEq(name.ToString()), + ? EXPECT_CALL(*mock_, + RenderFloat(IsEmpty(), NanSensitiveFloatEq(value))) + : EXPECT_CALL(*mock_, RenderFloat(StrEq(std::string(name)), NanSensitiveFloatEq(value)))) .WillOnce(Return(mock_)) .RetiresOnSaturation(); return this; } - virtual ObjectWriter* RenderString(StringPiece name, StringPiece value) { + virtual ObjectWriter* RenderString(StringPiece name, + StringPiece value) { (name.empty() - ? EXPECT_CALL(*mock_, RenderString(IsEmpty(), - TypedEq<StringPiece>(value.ToString()))) - : EXPECT_CALL(*mock_, RenderString(StrEq(name.ToString()), - TypedEq<StringPiece>(value.ToString())))) + ? EXPECT_CALL(*mock_, + RenderString(IsEmpty(), + TypedEq<StringPiece>(std::string(value)))) + : EXPECT_CALL(*mock_, + RenderString(StrEq(std::string(name)), + TypedEq<StringPiece>(std::string(value))))) .WillOnce(Return(mock_)) .RetiresOnSaturation(); return this; @@ -218,7 +221,7 @@ class ExpectingObjectWriter : public ObjectWriter { virtual ObjectWriter* RenderNull(StringPiece name) { (name.empty() ? EXPECT_CALL(*mock_, RenderNull(IsEmpty())) - : EXPECT_CALL(*mock_, RenderNull(StrEq(name.ToString()))) + : EXPECT_CALL(*mock_, RenderNull(StrEq(std::string(name)))) .WillOnce(Return(mock_)) .RetiresOnSaturation()); return this; @@ -233,6 +236,6 @@ class ExpectingObjectWriter : public ObjectWriter { } // namespace converter } // namespace util } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_EXPECTING_OBJECTWRITER_H__ diff --git a/src/google/protobuf/util/internal/field_mask_utility.cc b/src/google/protobuf/util/internal/field_mask_utility.cc index 778a4510..b0190127 100644 --- a/src/google/protobuf/util/internal/field_mask_utility.cc +++ b/src/google/protobuf/util/internal/field_mask_utility.cc @@ -34,6 +34,8 @@ #include <google/protobuf/stubs/strutil.h> #include <google/protobuf/stubs/status_macros.h> +#include <google/protobuf/port_def.inc> + namespace google { namespace protobuf { namespace util { @@ -46,12 +48,13 @@ inline util::Status CallPathSink(PathSinkCallback path_sink, } // Appends a FieldMask path segment to a prefix. -string AppendPathSegmentToPrefix(StringPiece prefix, StringPiece segment) { +string AppendPathSegmentToPrefix(StringPiece prefix, + StringPiece segment) { if (prefix.empty()) { - return segment.ToString(); + return string(segment); } if (segment.empty()) { - return prefix.ToString(); + return string(prefix); } // If the segment is a map key, appends it to the prefix without the ".". if (StringStartsWith(segment, "[\"")) { @@ -135,8 +138,9 @@ util::Status DecodeCompactFieldMaskPaths(StringPiece paths, if (i >= length - 1 || paths[i + 1] != ']') { return util::Status( util::error::INVALID_ARGUMENT, - StrCat("Invalid FieldMask '", paths, - "'. Map keys should be represented as [\"some_key\"].")); + 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; @@ -147,8 +151,9 @@ util::Status DecodeCompactFieldMaskPaths(StringPiece paths, paths[i + 1] != ')' && paths[i + 1] != '(') { return util::Status( util::error::INVALID_ARGUMENT, - StrCat("Invalid FieldMask '", paths, - "'. Map keys should be at the end of a path segment.")); + StrCat( + "Invalid FieldMask '", paths, + "'. Map keys should be at the end of a path segment.")); } is_escaping = false; continue; @@ -159,8 +164,9 @@ util::Status DecodeCompactFieldMaskPaths(StringPiece paths, if (i >= length - 1 || paths[i + 1] != '\"') { return util::Status( util::error::INVALID_ARGUMENT, - StrCat("Invalid FieldMask '", paths, - "'. Map keys should be represented as [\"some_key\"].")); + StrCat( + "Invalid FieldMask '", paths, + "'. Map keys should be represented as [\"some_key\"].")); } // "[\"" starts a map key. in_map_key = true; @@ -196,21 +202,23 @@ util::Status DecodeCompactFieldMaskPaths(StringPiece paths, return util::Status( util::error::INVALID_ARGUMENT, StrCat("Invalid FieldMask '", paths, - "'. Cannot find matching '(' for all ')'.")); + "'. Cannot find matching '(' for all ')'.")); } prefix.pop(); } previous_position = i + 1; } if (in_map_key) { - return util::Status(util::error::INVALID_ARGUMENT, - StrCat("Invalid FieldMask '", paths, - "'. Cannot find matching ']' for all '['.")); + return util::Status( + util::error::INVALID_ARGUMENT, + StrCat("Invalid FieldMask '", paths, + "'. Cannot find matching ']' for all '['.")); } if (!prefix.empty()) { - return util::Status(util::error::INVALID_ARGUMENT, - StrCat("Invalid FieldMask '", paths, - "'. Cannot find matching ')' for all '('.")); + return util::Status( + util::error::INVALID_ARGUMENT, + StrCat("Invalid FieldMask '", paths, + "'. Cannot find matching ')' for all '('.")); } return util::Status(); } diff --git a/src/google/protobuf/util/internal/field_mask_utility.h b/src/google/protobuf/util/internal/field_mask_utility.h index 59f36f75..97755804 100644 --- a/src/google/protobuf/util/internal/field_mask_utility.h +++ b/src/google/protobuf/util/internal/field_mask_utility.h @@ -45,14 +45,14 @@ namespace protobuf { namespace util { namespace converter { -typedef string (*ConverterCallback)(StringPiece); +typedef std::string (*ConverterCallback)(StringPiece); typedef ResultCallback1<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. -string ConvertFieldMaskPath(const StringPiece path, +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 @@ -67,6 +67,6 @@ util::Status DecodeCompactFieldMaskPaths(StringPiece paths, } // namespace converter } // namespace util } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_FIELD_MASK_UTILITY_H__ diff --git a/src/google/protobuf/util/internal/json_escaping.cc b/src/google/protobuf/util/internal/json_escaping.cc index 06b9a7f2..d1673597 100644 --- a/src/google/protobuf/util/internal/json_escaping.cc +++ b/src/google/protobuf/util/internal/json_escaping.cc @@ -134,8 +134,8 @@ inline uint16 ToHighSurrogate(uint32 cp) { // 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 *cp, int* num_left, int *num_read) { +bool ReadCodePoint(StringPiece str, int index, uint32* 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>(str[index++]); diff --git a/src/google/protobuf/util/internal/json_escaping.h b/src/google/protobuf/util/internal/json_escaping.h index 5495c57f..07042f6f 100644 --- a/src/google/protobuf/util/internal/json_escaping.h +++ b/src/google/protobuf/util/internal/json_escaping.h @@ -86,6 +86,6 @@ class JsonEscaping { } // namespace converter } // namespace util } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_UTIL_INTERNAL__JSON_ESCAPING_H__ diff --git a/src/google/protobuf/util/internal/json_objectwriter.cc b/src/google/protobuf/util/internal/json_objectwriter.cc index a431177a..c2d3292e 100644 --- a/src/google/protobuf/util/internal/json_objectwriter.cc +++ b/src/google/protobuf/util/internal/json_objectwriter.cc @@ -49,7 +49,7 @@ using strings::ArrayByteSource; ; JsonObjectWriter::~JsonObjectWriter() { - if (!element_->is_root()) { + if (element_ && !element_->is_root()) { GOOGLE_LOG(WARNING) << "JsonObjectWriter was not fully closed."; } } @@ -64,7 +64,7 @@ JsonObjectWriter* JsonObjectWriter::StartObject(StringPiece name) { JsonObjectWriter* JsonObjectWriter::EndObject() { Pop(); WriteChar('}'); - if (element()->is_root()) NewLine(); + if (element() && element()->is_root()) NewLine(); return this; } @@ -82,11 +82,13 @@ JsonObjectWriter* JsonObjectWriter::EndList() { return this; } -JsonObjectWriter* JsonObjectWriter::RenderBool(StringPiece name, bool value) { +JsonObjectWriter* JsonObjectWriter::RenderBool(StringPiece name, + bool value) { return RenderSimple(name, value ? "true" : "false"); } -JsonObjectWriter* JsonObjectWriter::RenderInt32(StringPiece name, int32 value) { +JsonObjectWriter* JsonObjectWriter::RenderInt32(StringPiece name, + int32 value) { return RenderSimple(name, SimpleItoa(value)); } @@ -95,7 +97,8 @@ JsonObjectWriter* JsonObjectWriter::RenderUint32(StringPiece name, return RenderSimple(name, SimpleItoa(value)); } -JsonObjectWriter* JsonObjectWriter::RenderInt64(StringPiece name, int64 value) { +JsonObjectWriter* JsonObjectWriter::RenderInt64(StringPiece name, + int64 value) { WritePrefix(name); WriteChar('"'); stream_->WriteString(SimpleItoa(value)); @@ -122,7 +125,8 @@ JsonObjectWriter* JsonObjectWriter::RenderDouble(StringPiece name, return RenderString(name, DoubleAsString(value)); } -JsonObjectWriter* JsonObjectWriter::RenderFloat(StringPiece name, float value) { +JsonObjectWriter* JsonObjectWriter::RenderFloat(StringPiece name, + float value) { if (MathLimits<float>::IsFinite(value)) { return RenderSimple(name, SimpleFtoa(value)); } diff --git a/src/google/protobuf/util/internal/json_objectwriter.h b/src/google/protobuf/util/internal/json_objectwriter.h index 4c25b465..ebfc7fba 100644 --- a/src/google/protobuf/util/internal/json_objectwriter.h +++ b/src/google/protobuf/util/internal/json_objectwriter.h @@ -38,6 +38,8 @@ #include <google/protobuf/util/internal/structured_objectwriter.h> #include <google/protobuf/stubs/bytestream.h> +#include <google/protobuf/port_def.inc> + namespace google { namespace protobuf { namespace util { @@ -82,32 +84,32 @@ namespace converter { // uint64 would lose precision if rendered as numbers. // // JsonObjectWriter is thread-unsafe. -class LIBPROTOBUF_EXPORT JsonObjectWriter : public StructuredObjectWriter { +class PROTOBUF_EXPORT JsonObjectWriter : public StructuredObjectWriter { public: - JsonObjectWriter(StringPiece indent_string, - google::protobuf::io::CodedOutputStream* out) + JsonObjectWriter(StringPiece indent_string, io::CodedOutputStream* out) : element_(new Element(/*parent=*/nullptr, /*is_json_object=*/false)), stream_(out), sink_(out), - indent_string_(indent_string.ToString()), + indent_string_(indent_string), use_websafe_base64_for_bytes_(false) {} virtual ~JsonObjectWriter(); // ObjectWriter methods. - virtual JsonObjectWriter* StartObject(StringPiece name) override; - virtual JsonObjectWriter* EndObject() override; - virtual JsonObjectWriter* StartList(StringPiece name) override; - virtual JsonObjectWriter* EndList() override; - virtual JsonObjectWriter* RenderBool(StringPiece name, bool value) override; - virtual JsonObjectWriter* RenderInt32(StringPiece name, int32 value) override; - virtual JsonObjectWriter* RenderUint32(StringPiece name, uint32 value) override; - virtual JsonObjectWriter* RenderInt64(StringPiece name, int64 value) override; - virtual JsonObjectWriter* RenderUint64(StringPiece name, uint64 value) override; - virtual JsonObjectWriter* RenderDouble(StringPiece name, double value) override; - virtual JsonObjectWriter* RenderFloat(StringPiece name, float value) override; - virtual JsonObjectWriter* RenderString(StringPiece name, StringPiece value) override; - virtual JsonObjectWriter* RenderBytes(StringPiece name, StringPiece value) override; - virtual JsonObjectWriter* RenderNull(StringPiece name) override; + virtual JsonObjectWriter* StartObject(StringPiece name); + virtual JsonObjectWriter* EndObject(); + virtual JsonObjectWriter* StartList(StringPiece name); + virtual JsonObjectWriter* EndList(); + virtual JsonObjectWriter* RenderBool(StringPiece name, bool value); + virtual JsonObjectWriter* RenderInt32(StringPiece name, int32 value); + virtual JsonObjectWriter* RenderUint32(StringPiece name, uint32 value); + virtual JsonObjectWriter* RenderInt64(StringPiece name, int64 value); + virtual JsonObjectWriter* RenderUint64(StringPiece name, uint64 value); + virtual JsonObjectWriter* RenderDouble(StringPiece name, double value); + virtual JsonObjectWriter* RenderFloat(StringPiece name, float value); + virtual JsonObjectWriter* RenderString(StringPiece name, + StringPiece value); + virtual JsonObjectWriter* RenderBytes(StringPiece name, StringPiece value); + virtual JsonObjectWriter* RenderNull(StringPiece name); virtual JsonObjectWriter* RenderNullAsEmpty(StringPiece name); void set_use_websafe_base64_for_bytes(bool value) { @@ -115,7 +117,7 @@ class LIBPROTOBUF_EXPORT JsonObjectWriter : public StructuredObjectWriter { } protected: - class LIBPROTOBUF_EXPORT Element : public BaseElement { + class PROTOBUF_EXPORT Element : public BaseElement { public: Element(Element* parent, bool is_json_object) : BaseElement(parent), @@ -146,10 +148,9 @@ class LIBPROTOBUF_EXPORT JsonObjectWriter : public StructuredObjectWriter { Element* element() override { return element_.get(); } private: - class LIBPROTOBUF_EXPORT ByteSinkWrapper : public strings::ByteSink { + class PROTOBUF_EXPORT ByteSinkWrapper : public strings::ByteSink { public: - explicit ByteSinkWrapper(google::protobuf::io::CodedOutputStream* stream) - : stream_(stream) {} + explicit ByteSinkWrapper(io::CodedOutputStream* stream) : stream_(stream) {} ~ByteSinkWrapper() override {} // ByteSink methods. @@ -158,7 +159,7 @@ class LIBPROTOBUF_EXPORT JsonObjectWriter : public StructuredObjectWriter { } private: - google::protobuf::io::CodedOutputStream* stream_; + io::CodedOutputStream* stream_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ByteSinkWrapper); }; @@ -166,7 +167,7 @@ class LIBPROTOBUF_EXPORT JsonObjectWriter : public StructuredObjectWriter { // 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, const string& value) { + JsonObjectWriter* RenderSimple(StringPiece name, const std::string& value) { WritePrefix(name); stream_->WriteString(value); return this; @@ -209,9 +210,9 @@ class LIBPROTOBUF_EXPORT JsonObjectWriter : public StructuredObjectWriter { void WriteChar(const char c) { stream_->WriteRaw(&c, sizeof(c)); } std::unique_ptr<Element> element_; - google::protobuf::io::CodedOutputStream* stream_; + io::CodedOutputStream* stream_; ByteSinkWrapper sink_; - const string indent_string_; + const std::string indent_string_; // Whether to use regular or websafe base64 encoding for byte fields. Defaults // to regular base64 encoding. @@ -223,6 +224,8 @@ class LIBPROTOBUF_EXPORT JsonObjectWriter : public StructuredObjectWriter { } // 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/src/google/protobuf/util/internal/json_objectwriter_test.cc b/src/google/protobuf/util/internal/json_objectwriter_test.cc index 0dc710c7..63636525 100644 --- a/src/google/protobuf/util/internal/json_objectwriter_test.cc +++ b/src/google/protobuf/util/internal/json_objectwriter_test.cc @@ -39,8 +39,8 @@ namespace protobuf { namespace util { namespace converter { -using google::protobuf::io::CodedOutputStream; -using google::protobuf::io::StringOutputStream; +using io::CodedOutputStream; +using io::StringOutputStream; class JsonObjectWriterTest : public ::testing::Test { protected: diff --git a/src/google/protobuf/util/internal/json_stream_parser.cc b/src/google/protobuf/util/internal/json_stream_parser.cc index 1c63b31d..e272bbd5 100644 --- a/src/google/protobuf/util/internal/json_stream_parser.cc +++ b/src/google/protobuf/util/internal/json_stream_parser.cc @@ -39,9 +39,10 @@ #include <google/protobuf/stubs/logging.h> #include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/strutil.h> + #include <google/protobuf/util/internal/object_writer.h> #include <google/protobuf/util/internal/json_escaping.h> -#include <google/protobuf/stubs/strutil.h> #include <google/protobuf/stubs/mathlimits.h> @@ -63,6 +64,8 @@ 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; + // Length of the true, false, and null literals. static const int true_len = strlen("true"); static const int false_len = strlen("false"); @@ -109,7 +112,9 @@ JsonStreamParser::JsonStreamParser(ObjectWriter* ow) chunk_storage_(), coerce_to_utf8_(false), allow_empty_null_(false), - loose_float_number_conversion_(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); } @@ -201,7 +206,7 @@ util::Status JsonStreamParser::ParseChunk(StringPiece chunk) { } // 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_ = p_.ToString(); + leftover_ = string(p_); } return util::Status(); } @@ -539,7 +544,7 @@ util::Status JsonStreamParser::ParseNumberHelper(NumberResult* result) { } // Create a string containing just the number, so we can use safe_strtoX - string number = p_.substr(0, index).ToString(); + string number = string(p_.substr(0, index)); // Floating point number, parse as a double. if (floating) { @@ -593,6 +598,10 @@ 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(); @@ -607,6 +616,7 @@ util::Status JsonStreamParser::ParseObjectMid(TokenType type) { if (type == END_OBJECT) { Advance(); ow_->EndObject(); + --recursion_depth_; return util::Status(); } // Found a comma, advance past it and get ready for an entry. @@ -628,6 +638,7 @@ util::Status JsonStreamParser::ParseEntry(TokenType type) { if (type == END_OBJECT) { ow_->EndObject(); Advance(); + --recursion_depth_; return util::Status(); } @@ -784,6 +795,17 @@ util::Status JsonStreamParser::ReportUnknown(StringPiece message) { return ReportFailure(message); } +util::Status JsonStreamParser::IncrementRecursionDepth( + StringPiece key) const { + if (++recursion_depth_ > max_recursion_depth_) { + return Status( + util::error::INVALID_ARGUMENT, + 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(); diff --git a/src/google/protobuf/util/internal/json_stream_parser.h b/src/google/protobuf/util/internal/json_stream_parser.h index 31933b67..3526ec57 100644 --- a/src/google/protobuf/util/internal/json_stream_parser.h +++ b/src/google/protobuf/util/internal/json_stream_parser.h @@ -38,11 +38,13 @@ #include <google/protobuf/stubs/stringpiece.h> #include <google/protobuf/stubs/status.h> -namespace google { +#include <google/protobuf/port_def.inc> + namespace util { class Status; } // namespace util +namespace google { namespace protobuf { namespace util { namespace converter { @@ -69,7 +71,7 @@ class ObjectWriter; // // This parser is thread-compatible as long as only one thread is calling a // Parse() method at a time. -class LIBPROTOBUF_EXPORT JsonStreamParser { +class PROTOBUF_EXPORT JsonStreamParser { public: // Creates a JsonStreamParser that will write to the given ObjectWriter. explicit JsonStreamParser(ObjectWriter* ow); @@ -83,7 +85,18 @@ class LIBPROTOBUF_EXPORT JsonStreamParser { 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; + } + private: + friend class JsonStreamParserTest; + // Return the current recursion depth. + const int recursion_depth() { return recursion_depth_; } + enum TokenType { BEGIN_STRING, // " or ' BEGIN_NUMBER, // - or digit @@ -155,7 +168,7 @@ class LIBPROTOBUF_EXPORT JsonStreamParser { util::Status ParseNumberHelper(NumberResult* result); // Parse a number as double into a NumberResult. - util::Status ParseDoubleHelper(const string& number, NumberResult* result); + util::Status ParseDoubleHelper(const std::string& number, NumberResult* result); // Handles a { during parsing of a value. util::Status HandleBeginObject(); @@ -195,6 +208,11 @@ class LIBPROTOBUF_EXPORT JsonStreamParser { // status to return in this case. util::Status ReportUnknown(StringPiece message); + // Helper function to check recursion depth and increment it. It will return + // Status::OK 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(); @@ -216,7 +234,7 @@ class LIBPROTOBUF_EXPORT JsonStreamParser { // 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. - string leftover_; + std::string leftover_; // The current chunk of JSON being parsed. Primarily used for providing // context during error reporting. @@ -230,7 +248,7 @@ class LIBPROTOBUF_EXPORT JsonStreamParser { // Storage for key_ if we need to keep ownership, for example between chunks // or if the key was unescaped from a JSON string. - string key_storage_; + 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 @@ -242,14 +260,14 @@ class LIBPROTOBUF_EXPORT JsonStreamParser { // Storage for the string we parsed. This may be empty if the string was able // to be parsed directly from the input. - string parsed_storage_; + 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(). - string chunk_storage_; + std::string chunk_storage_; // Whether to allow non UTF-8 encoded input and replace invalid code points. bool coerce_to_utf8_; @@ -261,12 +279,20 @@ class LIBPROTOBUF_EXPORT JsonStreamParser { // 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/src/google/protobuf/util/internal/json_stream_parser_test.cc b/src/google/protobuf/util/internal/json_stream_parser_test.cc index a11e9be0..764c9f71 100644 --- a/src/google/protobuf/util/internal/json_stream_parser_test.cc +++ b/src/google/protobuf/util/internal/json_stream_parser_test.cc @@ -37,6 +37,7 @@ #include <google/protobuf/util/internal/object_writer.h> #include <google/protobuf/stubs/strutil.h> #include <gtest/gtest.h> + #include <google/protobuf/stubs/status.h> @@ -88,8 +89,8 @@ class JsonStreamParserTest : public ::testing::Test { JsonStreamParserTest() : mock_(), ow_(&mock_) {} virtual ~JsonStreamParserTest() {} - util::Status RunTest(StringPiece json, int split, bool coerce_utf8 = false, - bool allow_empty_null = false, + util::Status RunTest(StringPiece json, int split, + bool coerce_utf8 = false, bool allow_empty_null = false, bool loose_float_number_conversion = false) { JsonStreamParser parser(&mock_); @@ -117,6 +118,9 @@ class JsonStreamParserTest : public ::testing::Test { result = parser.FinishParse(); } } + if (result.ok()){ + EXPECT_EQ(parser.recursion_depth(), 0); + } return result; } @@ -131,8 +135,9 @@ class JsonStreamParserTest : public ::testing::Test { EXPECT_OK(result); } - void DoErrorTest(StringPiece json, int split, StringPiece error_prefix, - bool coerce_utf8 = false, bool allow_empty_null = false) { + void DoErrorTest(StringPiece json, int split, + StringPiece error_prefix, bool coerce_utf8 = false, + bool allow_empty_null = false) { util::Status result = RunTest(json, split, coerce_utf8, allow_empty_null); EXPECT_EQ(util::error::INVALID_ARGUMENT, result.error_code()); @@ -838,6 +843,49 @@ TEST_F(JsonStreamParserTest, UnknownCharactersInObject) { } } +TEST_F(JsonStreamParserTest, DeepNestJsonNotExceedLimit) { + int count = 99; + string str; + for (int i = 0; i < count; ++i) { + StrAppend(&str, "{'a':"); + } + StrAppend(&str, "{'nest64':'v1', 'nest64': false, 'nest64': ['v2']}"); + for (int i = 0; i < count; ++i) { + StrAppend(&str, "}"); + } + ow_.StartObject(""); + for (int i = 0; i < count; ++i) { + ow_.StartObject("a"); + } + ow_.RenderString("nest64", "v1") + ->RenderBool("nest64", false) + ->StartList("nest64") + ->RenderString("", "v2") + ->EndList(); + for (int i = 0; i < count; ++i) { + ow_.EndObject(); + } + ow_.EndObject(); + DoTest(str, 0); +} + +TEST_F(JsonStreamParserTest, DeepNestJsonExceedLimit) { + int count = 98; + string str; + for (int i = 0; i < count; ++i) { + StrAppend(&str, "{'a':"); + } + // Supports trailing commas. + StrAppend(&str, + "{'nest11' : [{'nest12' : null,},]," + "'nest21' : {'nest22' : {'nest23' : false}}}"); + for (int i = 0; i < count; ++i) { + StrAppend(&str, "}"); + } + DoErrorTest(str, 0, + "Message too deep. Max recursion depth reached for key 'nest22'"); +} + } // namespace converter } // namespace util } // namespace protobuf diff --git a/src/google/protobuf/util/internal/location_tracker.h b/src/google/protobuf/util/internal/location_tracker.h index 0864b057..c29a75a7 100644 --- a/src/google/protobuf/util/internal/location_tracker.h +++ b/src/google/protobuf/util/internal/location_tracker.h @@ -35,6 +35,8 @@ #include <google/protobuf/stubs/common.h> +#include <google/protobuf/port_def.inc> + namespace google { namespace protobuf { namespace util { @@ -42,12 +44,12 @@ namespace converter { // LocationTrackerInterface is an interface for classes that track // the location information for the purpose of error reporting. -class LIBPROTOBUF_EXPORT LocationTrackerInterface { +class PROTOBUF_EXPORT LocationTrackerInterface { public: virtual ~LocationTrackerInterface() {} // Returns the object location as human readable string. - virtual string ToString() const = 0; + virtual std::string ToString() const = 0; protected: LocationTrackerInterface() {} @@ -60,6 +62,8 @@ class LIBPROTOBUF_EXPORT 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/src/google/protobuf/util/internal/mock_error_listener.h b/src/google/protobuf/util/internal/mock_error_listener.h index 591c35db..1f1321f2 100644 --- a/src/google/protobuf/util/internal/mock_error_listener.h +++ b/src/google/protobuf/util/internal/mock_error_listener.h @@ -31,11 +31,11 @@ #ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_MOCK_ERROR_LISTENER_H__ #define GOOGLE_PROTOBUF_UTIL_CONVERTER_MOCK_ERROR_LISTENER_H__ -#include <google/protobuf/stubs/stringpiece.h> #include <google/protobuf/util/internal/error_listener.h> #include <google/protobuf/util/internal/location_tracker.h> #include <gmock/gmock.h> + namespace google { namespace protobuf { namespace util { @@ -46,11 +46,12 @@ class MockErrorListener : public ErrorListener { MockErrorListener() {} virtual ~MockErrorListener() {} - MOCK_METHOD3(InvalidName, void(const LocationTrackerInterface& loc, - StringPiece unknown_name, - StringPiece message)); - MOCK_METHOD3(InvalidValue, void(const LocationTrackerInterface& loc, - StringPiece type_name, StringPiece value)); + MOCK_METHOD3(InvalidName, + void(const LocationTrackerInterface& loc, + StringPiece unknown_name, StringPiece message)); + MOCK_METHOD3(InvalidValue, + void(const LocationTrackerInterface& loc, + StringPiece type_name, StringPiece value)); MOCK_METHOD2(MissingField, void(const LocationTrackerInterface& loc, StringPiece missing_name)); }; @@ -58,6 +59,6 @@ class MockErrorListener : public ErrorListener { } // namespace converter } // namespace util } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_MOCK_ERROR_LISTENER_H__ diff --git a/src/google/protobuf/util/internal/object_location_tracker.h b/src/google/protobuf/util/internal/object_location_tracker.h index f9b90bc4..571279d5 100644 --- a/src/google/protobuf/util/internal/object_location_tracker.h +++ b/src/google/protobuf/util/internal/object_location_tracker.h @@ -50,7 +50,7 @@ class ObjectLocationTracker : public LocationTrackerInterface { ~ObjectLocationTracker() override {} // Returns empty because nothing is tracked. - string ToString() const override { return ""; } + std::string ToString() const override { return ""; } private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ObjectLocationTracker); @@ -59,6 +59,6 @@ class ObjectLocationTracker : public LocationTrackerInterface { } // namespace converter } // namespace util } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_OBJECT_LOCATION_TRACKER_H__ diff --git a/src/google/protobuf/util/internal/object_source.h b/src/google/protobuf/util/internal/object_source.h index 2c31cfb0..c8ee36fb 100644 --- a/src/google/protobuf/util/internal/object_source.h +++ b/src/google/protobuf/util/internal/object_source.h @@ -35,6 +35,8 @@ #include <google/protobuf/stubs/stringpiece.h> #include <google/protobuf/stubs/status.h> +#include <google/protobuf/port_def.inc> + namespace google { namespace protobuf { namespace util { @@ -48,7 +50,7 @@ class ObjectWriter; // example, a character stream, or protobuf. // // Derived classes could be thread-unsafe. -class LIBPROTOBUF_EXPORT ObjectSource { +class PROTOBUF_EXPORT ObjectSource { public: virtual ~ObjectSource() {} @@ -74,6 +76,8 @@ class LIBPROTOBUF_EXPORT 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/src/google/protobuf/util/internal/object_writer.cc b/src/google/protobuf/util/internal/object_writer.cc index 57cc08a1..bb1b3e57 100644 --- a/src/google/protobuf/util/internal/object_writer.cc +++ b/src/google/protobuf/util/internal/object_writer.cc @@ -38,8 +38,8 @@ namespace util { namespace converter { // static -void ObjectWriter::RenderDataPieceTo(const DataPiece& data, StringPiece name, - ObjectWriter* ow) { +void ObjectWriter::RenderDataPieceTo(const DataPiece& data, + StringPiece name, ObjectWriter* ow) { switch (data.type()) { case DataPiece::TYPE_INT32: { ow->RenderInt32(name, data.ToInt32().ValueOrDie()); diff --git a/src/google/protobuf/util/internal/object_writer.h b/src/google/protobuf/util/internal/object_writer.h index 5781aa1e..a4b509da 100644 --- a/src/google/protobuf/util/internal/object_writer.h +++ b/src/google/protobuf/util/internal/object_writer.h @@ -34,6 +34,8 @@ #include <google/protobuf/stubs/common.h> #include <google/protobuf/stubs/stringpiece.h> +#include <google/protobuf/port_def.inc> + namespace google { namespace protobuf { namespace util { @@ -55,7 +57,7 @@ class DataPiece; // // TODO(xinb): seems like a prime candidate to apply the RAII paradigm // and get rid the need to call EndXXX(). -class LIBPROTOBUF_EXPORT ObjectWriter { +class PROTOBUF_EXPORT ObjectWriter { public: virtual ~ObjectWriter() {} @@ -93,7 +95,8 @@ class LIBPROTOBUF_EXPORT ObjectWriter { 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; + virtual ObjectWriter* RenderString(StringPiece name, + StringPiece value) = 0; // Renders a bytes value. virtual ObjectWriter* RenderBytes(StringPiece name, StringPiece value) = 0; @@ -134,6 +137,8 @@ class LIBPROTOBUF_EXPORT 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/src/google/protobuf/util/internal/proto_writer.cc b/src/google/protobuf/util/internal/proto_writer.cc index b7a52db6..56ee774a 100644 --- a/src/google/protobuf/util/internal/proto_writer.cc +++ b/src/google/protobuf/util/internal/proto_writer.cc @@ -45,16 +45,18 @@ #include <google/protobuf/stubs/statusor.h> +#include <google/protobuf/port_def.inc> + namespace google { namespace protobuf { namespace util { namespace converter { -using google::protobuf::internal::WireFormatLite; -using google::protobuf::io::CodedOutputStream; -using util::error::INVALID_ARGUMENT; +using io::CodedOutputStream; +using ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite; using util::Status; using util::StatusOr; +using util::error::INVALID_ARGUMENT; ProtoWriter::ProtoWriter(TypeResolver* type_resolver, @@ -65,6 +67,7 @@ ProtoWriter::ProtoWriter(TypeResolver* type_resolver, own_typeinfo_(true), done_(false), ignore_unknown_fields_(false), + ignore_unknown_enum_values_(false), use_lower_camel_for_enums_(false), element_(nullptr), size_insert_(), @@ -84,6 +87,7 @@ ProtoWriter::ProtoWriter(const TypeInfo* typeinfo, own_typeinfo_(false), done_(false), ignore_unknown_fields_(false), + ignore_unknown_enum_values_(false), use_lower_camel_for_enums_(false), element_(nullptr), size_insert_(), @@ -263,19 +267,6 @@ inline Status WriteString(int field_number, const DataPiece& data, return s.status(); } -// Writes an ENUM field, including tag, to the stream. -inline Status WriteEnum(int field_number, const DataPiece& data, - const google::protobuf::Enum* enum_type, - CodedOutputStream* stream, - bool use_lower_camel_for_enums, - bool ignore_unknown_values) { - StatusOr<int> e = data.ToEnum(enum_type, use_lower_camel_for_enums, ignore_unknown_values); - if (e.ok()) { - WireFormatLite::WriteEnum(field_number, e.ValueOrDie(), stream); - } - return e.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) { @@ -426,11 +417,13 @@ void ProtoWriter::ProtoElement::TakeOneofIndex(int32 index) { oneof_indices_[index] = true; } -void ProtoWriter::InvalidName(StringPiece unknown_name, StringPiece message) { +void ProtoWriter::InvalidName(StringPiece unknown_name, + StringPiece message) { listener_->InvalidName(location(), ToSnakeCase(unknown_name), message); } -void ProtoWriter::InvalidValue(StringPiece type_name, StringPiece value) { +void ProtoWriter::InvalidValue(StringPiece type_name, + StringPiece value) { listener_->InvalidValue(location(), type_name, value); } @@ -462,8 +455,8 @@ ProtoWriter* ProtoWriter::StartObject(StringPiece name) { const google::protobuf::Type* type = LookupType(field); if (type == nullptr) { ++invalid_depth_; - InvalidName(name, - StrCat("Missing descriptor for field: ", field->type_url())); + InvalidName(name, StrCat("Missing descriptor for field: ", + field->type_url())); return this; } @@ -501,8 +494,8 @@ ProtoWriter* ProtoWriter::StartList(StringPiece name) { const google::protobuf::Type* type = LookupType(field); if (type == nullptr) { ++invalid_depth_; - InvalidName(name, - StrCat("Missing descriptor for field: ", field->type_url())); + InvalidName(name, StrCat("Missing descriptor for field: ", + field->type_url())); return this; } @@ -530,8 +523,8 @@ ProtoWriter* ProtoWriter::RenderDataPiece(StringPiece name, const google::protobuf::Type* type = LookupType(field); if (type == nullptr) { - InvalidName(name, - StrCat("Missing descriptor for field: ", field->type_url())); + InvalidName(name, StrCat("Missing descriptor for field: ", + field->type_url())); return this; } @@ -546,9 +539,9 @@ bool ProtoWriter::ValidOneof(const google::protobuf::Field& field, 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, "'")); + StrCat( + "oneof field '", element_->type().oneofs(field.oneof_index() - 1), + "' is already set. Cannot set '", unnormalized_name, "'")); return false; } element_->TakeOneofIndex(field.oneof_index()); @@ -574,6 +567,20 @@ ProtoWriter* ProtoWriter::StartListField(const google::protobuf::Field& field, return this; } +Status ProtoWriter::WriteEnum(int field_number, const DataPiece& data, + const google::protobuf::Enum* enum_type, + CodedOutputStream* stream, + bool use_lower_camel_for_enums, + bool ignore_unknown_values) { + bool is_unknown_enum_value = false; + StatusOr<int> e = data.ToEnum(enum_type, use_lower_camel_for_enums, + ignore_unknown_values, &is_unknown_enum_value); + if (e.ok() && !is_unknown_enum_value) { + WireFormatLite::WriteEnum(field_number, e.ValueOrDie(), stream); + } + return e.status(); +} + ProtoWriter* ProtoWriter::RenderPrimitiveField( const google::protobuf::Field& field, const google::protobuf::Type& type, const DataPiece& data) { @@ -667,7 +674,7 @@ ProtoWriter* ProtoWriter::RenderPrimitiveField( status = WriteEnum(field.number(), data, typeinfo_->GetEnumByTypeUrl(field.type_url()), stream_.get(), use_lower_camel_for_enums_, - ignore_unknown_fields_); + ignore_unknown_enum_values_); break; } default: // TYPE_GROUP or TYPE_MESSAGE @@ -751,7 +758,7 @@ void ProtoWriter::WriteRootMessage() { stream_.reset(nullptr); const void* data; int length; - google::protobuf::io::ArrayInputStream input_stream(buffer_.data(), buffer_.size()); + io::ArrayInputStream input_stream(buffer_.data(), buffer_.size()); while (input_stream.Next(&data, &length)) { if (length == 0) continue; int num_bytes = length; diff --git a/src/google/protobuf/util/internal/proto_writer.h b/src/google/protobuf/util/internal/proto_writer.h index 5bdafcc9..1a8df982 100644 --- a/src/google/protobuf/util/internal/proto_writer.h +++ b/src/google/protobuf/util/internal/proto_writer.h @@ -46,6 +46,9 @@ #include <google/protobuf/util/type_resolver.h> #include <google/protobuf/stubs/bytestream.h> #include <google/protobuf/stubs/hash.h> +#include <google/protobuf/stubs/status.h> + +#include <google/protobuf/port_def.inc> namespace google { namespace protobuf { @@ -53,14 +56,16 @@ namespace io { class CodedOutputStream; } // namespace io } // namespace protobuf +} // namespace google - +namespace google { namespace protobuf { class Type; class Field; } // namespace protobuf +} // namespace google - +namespace google { namespace protobuf { namespace util { namespace converter { @@ -73,12 +78,12 @@ class ObjectLocationTracker; // special types by inheriting from it or by wrapping it. // // It also supports streaming. -class LIBPROTOBUF_EXPORT ProtoWriter : public StructuredObjectWriter { +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); - virtual ~ProtoWriter() override; + ~ProtoWriter() override; // ObjectWriter methods. ProtoWriter* StartObject(StringPiece name) override; @@ -106,7 +111,8 @@ class LIBPROTOBUF_EXPORT ProtoWriter : public StructuredObjectWriter { ProtoWriter* RenderFloat(StringPiece name, float value) override { return RenderDataPiece(name, DataPiece(value)); } - ProtoWriter* RenderString(StringPiece name, StringPiece value) override { + ProtoWriter* RenderString(StringPiece name, + StringPiece value) override { return RenderDataPiece(name, DataPiece(value, use_strict_base64_decoding())); } @@ -133,7 +139,7 @@ class LIBPROTOBUF_EXPORT ProtoWriter : public StructuredObjectWriter { bool done() override { return done_; } // Returns the proto stream object. - google::protobuf::io::CodedOutputStream* stream() { return stream_.get(); } + io::CodedOutputStream* stream() { return stream_.get(); } // Getters and mutators of invalid_depth_. void IncrementInvalidDepth() { ++invalid_depth_; } @@ -148,12 +154,17 @@ class LIBPROTOBUF_EXPORT ProtoWriter : public StructuredObjectWriter { ignore_unknown_fields_ = 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; } protected: - class LIBPROTOBUF_EXPORT ProtoElement : public BaseElement, public LocationTrackerInterface { + 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, @@ -163,7 +174,7 @@ class LIBPROTOBUF_EXPORT ProtoWriter : public StructuredObjectWriter { ProtoElement(ProtoElement* parent, const google::protobuf::Field* field, const google::protobuf::Type& type, bool is_list); - virtual ~ProtoElement() override {} + ~ProtoElement() override {} // Called just before the destructor for clean up: // - reports any missing required fields @@ -183,9 +194,9 @@ class LIBPROTOBUF_EXPORT ProtoWriter : public StructuredObjectWriter { void RegisterField(const google::protobuf::Field* field); // To report location on error messages. - virtual string ToString() const override; + std::string ToString() const override; - virtual ProtoElement* parent() const override { + ProtoElement* parent() const override { return static_cast<ProtoElement*>(BaseElement::parent()); } @@ -251,7 +262,8 @@ class LIBPROTOBUF_EXPORT ProtoWriter : public StructuredObjectWriter { // 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); + 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 @@ -298,6 +310,13 @@ class LIBPROTOBUF_EXPORT ProtoWriter : public StructuredObjectWriter { const DataPiece& value); 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 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. @@ -309,9 +328,12 @@ class LIBPROTOBUF_EXPORT ProtoWriter : public StructuredObjectWriter { // Indicates whether we finished writing root message completely. bool done_; - // If true, don't report unknown field names and enum values to the listener. + // 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_; @@ -330,9 +352,9 @@ class LIBPROTOBUF_EXPORT ProtoWriter : public StructuredObjectWriter { // adapter_ : internal adapter between CodedOutputStream and buffer_. // stream_ : wrapper for writing tags and other encodings in wire format. strings::ByteSink* output_; - string buffer_; - google::protobuf::io::StringOutputStream adapter_; - std::unique_ptr<google::protobuf::io::CodedOutputStream> stream_; + 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. @@ -348,6 +370,8 @@ class LIBPROTOBUF_EXPORT ProtoWriter : public StructuredObjectWriter { } // 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/src/google/protobuf/util/internal/protostream_objectsource.cc b/src/google/protobuf/util/internal/protostream_objectsource.cc index b0d86c17..97a8bb48 100644 --- a/src/google/protobuf/util/internal/protostream_objectsource.cc +++ b/src/google/protobuf/util/internal/protostream_objectsource.cc @@ -30,9 +30,9 @@ #include <google/protobuf/util/internal/protostream_objectsource.h> +#include <unordered_map> #include <utility> -#include <google/protobuf/stubs/casts.h> #include <google/protobuf/stubs/logging.h> #include <google/protobuf/stubs/common.h> #include <google/protobuf/stubs/stringprintf.h> @@ -40,16 +40,22 @@ #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/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/map_util.h> #include <google/protobuf/stubs/status_macros.h> +#include <google/protobuf/port_def.inc> + namespace google { namespace protobuf { namespace util { @@ -60,12 +66,8 @@ using util::error::Code; using util::error::INTERNAL; } namespace converter { - -using google::protobuf::Descriptor; -using google::protobuf::EnumValueDescriptor; -using google::protobuf::FieldDescriptor; -using google::protobuf::internal::WireFormat; -using google::protobuf::internal::WireFormatLite; +using ::PROTOBUF_NAMESPACE_ID::internal::WireFormat; +using ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite; using util::Status; using util::StatusOr; @@ -113,7 +115,7 @@ StatusOr<string> MapKeyDefaultValueAsString( ProtoStreamObjectSource::ProtoStreamObjectSource( - google::protobuf::io::CodedInputStream* stream, TypeResolver* type_resolver, + io::CodedInputStream* stream, TypeResolver* type_resolver, const google::protobuf::Type& type) : stream_(stream), typeinfo_(TypeInfo::NewTypeInfo(type_resolver)), @@ -131,7 +133,7 @@ ProtoStreamObjectSource::ProtoStreamObjectSource( } ProtoStreamObjectSource::ProtoStreamObjectSource( - google::protobuf::io::CodedInputStream* stream, const TypeInfo* typeinfo, + io::CodedInputStream* stream, const TypeInfo* typeinfo, const google::protobuf::Type& type) : stream_(stream), typeinfo_(typeinfo), @@ -194,7 +196,7 @@ Status ProtoStreamObjectSource::WriteMessage(const google::protobuf::Type& type, string field_name; // last_tag set to dummy value that is different from tag. uint32 tag = stream_->ReadTag(), last_tag = tag + 1; - google::protobuf::UnknownFieldSet unknown_fields; + UnknownFieldSet unknown_fields; if (include_start_and_end) { ow->StartObject(name); @@ -246,8 +248,8 @@ Status ProtoStreamObjectSource::WriteMessage(const google::protobuf::Type& type, } StatusOr<uint32> ProtoStreamObjectSource::RenderList( - const google::protobuf::Field* field, StringPiece name, uint32 list_tag, - ObjectWriter* ow) const { + const google::protobuf::Field* field, StringPiece name, + uint32 list_tag, ObjectWriter* ow) const { uint32 tag_to_return = 0; ow->StartList(name); if (IsPackable(*field) && @@ -268,8 +270,8 @@ StatusOr<uint32> ProtoStreamObjectSource::RenderList( } StatusOr<uint32> ProtoStreamObjectSource::RenderMap( - const google::protobuf::Field* field, StringPiece name, uint32 list_tag, - ObjectWriter* ow) const { + const google::protobuf::Field* field, StringPiece name, + uint32 list_tag, ObjectWriter* ow) const { const google::protobuf::Type* field_type = typeinfo_->GetTypeByTypeUrl(field->type_url()); uint32 tag_to_return = 0; @@ -332,9 +334,9 @@ Status ProtoStreamObjectSource::RenderTimestamp( int64 seconds = p.first; int32 nanos = p.second; if (seconds > kTimestampMaxSeconds || seconds < kTimestampMinSeconds) { - return Status( - util::error::INTERNAL, - StrCat("Timestamp seconds exceeds limit for field: ", field_name)); + return Status(util::error::INTERNAL, + StrCat("Timestamp seconds exceeds limit for field: ", + field_name)); } if (nanos < 0 || nanos >= kNanosPerSecond) { @@ -370,10 +372,11 @@ Status ProtoStreamObjectSource::RenderDuration( string sign = ""; if (seconds < 0) { if (nanos > 0) { - return Status(util::error::INTERNAL, - StrCat("Duration nanos is non-negative, but seconds is " - "negative for field: ", - field_name)); + return Status( + util::error::INTERNAL, + StrCat("Duration nanos is non-negative, but seconds is " + "negative for field: ", + field_name)); } sign = "-"; seconds = -seconds; @@ -383,7 +386,7 @@ Status ProtoStreamObjectSource::RenderDuration( nanos = -nanos; } string formatted_duration = StringPrintf( - "%s%lld%ss", sign.c_str(), seconds, + "%s%lld%ss", sign.c_str(), static_cast<long long>(seconds), // NOLINT FormatNanos(nanos, os->add_trailing_zeros_for_timestamp_and_duration_) .c_str()); ow->RenderString(field_name, formatted_duration); @@ -400,7 +403,7 @@ Status ProtoStreamObjectSource::RenderDouble(const ProtoStreamObjectSource* os, os->stream_->ReadLittleEndian64(&buffer64); os->stream_->ReadTag(); } - ow->RenderDouble(field_name, bit_cast<double>(buffer64)); + ow->RenderDouble(field_name, ::google::protobuf::bit_cast<double>(buffer64)); return util::Status(); } @@ -414,7 +417,7 @@ Status ProtoStreamObjectSource::RenderFloat(const ProtoStreamObjectSource* os, os->stream_->ReadLittleEndian32(&buffer32); os->stream_->ReadTag(); } - ow->RenderFloat(field_name, bit_cast<float>(buffer32)); + ow->RenderFloat(field_name, ::google::protobuf::bit_cast<float>(buffer32)); return util::Status(); } @@ -428,7 +431,7 @@ Status ProtoStreamObjectSource::RenderInt64(const ProtoStreamObjectSource* os, os->stream_->ReadVarint64(&buffer64); os->stream_->ReadTag(); } - ow->RenderInt64(field_name, bit_cast<int64>(buffer64)); + ow->RenderInt64(field_name, ::google::protobuf::bit_cast<int64>(buffer64)); return util::Status(); } @@ -442,7 +445,7 @@ Status ProtoStreamObjectSource::RenderUInt64(const ProtoStreamObjectSource* os, os->stream_->ReadVarint64(&buffer64); os->stream_->ReadTag(); } - ow->RenderUint64(field_name, bit_cast<uint64>(buffer64)); + ow->RenderUint64(field_name, ::google::protobuf::bit_cast<uint64>(buffer64)); return util::Status(); } @@ -456,7 +459,7 @@ Status ProtoStreamObjectSource::RenderInt32(const ProtoStreamObjectSource* os, os->stream_->ReadVarint32(&buffer32); os->stream_->ReadTag(); } - ow->RenderInt32(field_name, bit_cast<int32>(buffer32)); + ow->RenderInt32(field_name, ::google::protobuf::bit_cast<int32>(buffer32)); return util::Status(); } @@ -470,7 +473,7 @@ Status ProtoStreamObjectSource::RenderUInt32(const ProtoStreamObjectSource* os, os->stream_->ReadVarint32(&buffer32); os->stream_->ReadTag(); } - ow->RenderUint32(field_name, bit_cast<uint32>(buffer32)); + ow->RenderUint32(field_name, ::google::protobuf::bit_cast<uint32>(buffer32)); return util::Status(); } @@ -642,8 +645,8 @@ Status ProtoStreamObjectSource::RenderAny(const ProtoStreamObjectSource* os, // nested_type cannot be null at this time. const google::protobuf::Type* nested_type = resolved_type.ValueOrDie(); - google::protobuf::io::ArrayInputStream zero_copy_stream(value.data(), value.size()); - google::protobuf::io::CodedInputStream in_stream(&zero_copy_stream); + 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); @@ -696,12 +699,13 @@ Status ProtoStreamObjectSource::RenderFieldMask( } -hash_map<string, ProtoStreamObjectSource::TypeRenderer>* +std::unordered_map<string, ProtoStreamObjectSource::TypeRenderer>* ProtoStreamObjectSource::renderers_ = NULL; -GOOGLE_PROTOBUF_DECLARE_ONCE(source_renderers_init_); +PROTOBUF_NAMESPACE_ID::internal::once_flag source_renderers_init_; void ProtoStreamObjectSource::InitRendererMap() { - renderers_ = new hash_map<string, ProtoStreamObjectSource::TypeRenderer>(); + renderers_ = + new std::unordered_map<string, ProtoStreamObjectSource::TypeRenderer>(); (*renderers_)["google.protobuf.Timestamp"] = &ProtoStreamObjectSource::RenderTimestamp; (*renderers_)["google.protobuf.Duration"] = @@ -744,7 +748,8 @@ void ProtoStreamObjectSource::DeleteRendererMap() { // static ProtoStreamObjectSource::TypeRenderer* ProtoStreamObjectSource::FindTypeRenderer(const string& type_url) { - ::google::protobuf::GoogleOnceInit(&source_renderers_init_, &InitRendererMap); + PROTOBUF_NAMESPACE_ID::internal::call_once(source_renderers_init_, + InitRendererMap); return FindOrNull(*renderers_, type_url); } @@ -762,9 +767,10 @@ Status ProtoStreamObjectSource::RenderField( const google::protobuf::Type* type = typeinfo_->GetTypeByTypeUrl(field->type_url()); if (type == nullptr) { - return Status(util::error::INTERNAL, - StrCat("Invalid configuration. Could not find the type: ", - field->type_url())); + return Status( + util::error::INTERNAL, + StrCat("Invalid configuration. Could not find the type: ", + field->type_url())); } // Short-circuit any special type rendering to save call-stack space. @@ -806,22 +812,22 @@ Status ProtoStreamObjectSource::RenderNonMessageField( } case google::protobuf::Field_Kind_TYPE_INT32: { stream_->ReadVarint32(&buffer32); - ow->RenderInt32(field_name, bit_cast<int32>(buffer32)); + ow->RenderInt32(field_name, ::google::protobuf::bit_cast<int32>(buffer32)); break; } case google::protobuf::Field_Kind_TYPE_INT64: { stream_->ReadVarint64(&buffer64); - ow->RenderInt64(field_name, bit_cast<int64>(buffer64)); + ow->RenderInt64(field_name, ::google::protobuf::bit_cast<int64>(buffer64)); break; } case google::protobuf::Field_Kind_TYPE_UINT32: { stream_->ReadVarint32(&buffer32); - ow->RenderUint32(field_name, bit_cast<uint32>(buffer32)); + ow->RenderUint32(field_name, ::google::protobuf::bit_cast<uint32>(buffer32)); break; } case google::protobuf::Field_Kind_TYPE_UINT64: { stream_->ReadVarint64(&buffer64); - ow->RenderUint64(field_name, bit_cast<uint64>(buffer64)); + ow->RenderUint64(field_name, ::google::protobuf::bit_cast<uint64>(buffer64)); break; } case google::protobuf::Field_Kind_TYPE_SINT32: { @@ -836,32 +842,32 @@ Status ProtoStreamObjectSource::RenderNonMessageField( } case google::protobuf::Field_Kind_TYPE_SFIXED32: { stream_->ReadLittleEndian32(&buffer32); - ow->RenderInt32(field_name, bit_cast<int32>(buffer32)); + ow->RenderInt32(field_name, ::google::protobuf::bit_cast<int32>(buffer32)); break; } case google::protobuf::Field_Kind_TYPE_SFIXED64: { stream_->ReadLittleEndian64(&buffer64); - ow->RenderInt64(field_name, bit_cast<int64>(buffer64)); + ow->RenderInt64(field_name, ::google::protobuf::bit_cast<int64>(buffer64)); break; } case google::protobuf::Field_Kind_TYPE_FIXED32: { stream_->ReadLittleEndian32(&buffer32); - ow->RenderUint32(field_name, bit_cast<uint32>(buffer32)); + ow->RenderUint32(field_name, ::google::protobuf::bit_cast<uint32>(buffer32)); break; } case google::protobuf::Field_Kind_TYPE_FIXED64: { stream_->ReadLittleEndian64(&buffer64); - ow->RenderUint64(field_name, bit_cast<uint64>(buffer64)); + ow->RenderUint64(field_name, ::google::protobuf::bit_cast<uint64>(buffer64)); break; } case google::protobuf::Field_Kind_TYPE_FLOAT: { stream_->ReadLittleEndian32(&buffer32); - ow->RenderFloat(field_name, bit_cast<float>(buffer32)); + ow->RenderFloat(field_name, ::google::protobuf::bit_cast<float>(buffer32)); break; } case google::protobuf::Field_Kind_TYPE_DOUBLE: { stream_->ReadLittleEndian64(&buffer64); - ow->RenderDouble(field_name, bit_cast<double>(buffer64)); + ow->RenderDouble(field_name, ::google::protobuf::bit_cast<double>(buffer64)); break; } case google::protobuf::Field_Kind_TYPE_ENUM: { @@ -932,25 +938,25 @@ const string ProtoStreamObjectSource::ReadFieldValueAsString( case google::protobuf::Field_Kind_TYPE_INT32: { uint32 buffer32; stream_->ReadVarint32(&buffer32); - result = SimpleItoa(bit_cast<int32>(buffer32)); + result = SimpleItoa(::google::protobuf::bit_cast<int32>(buffer32)); break; } case google::protobuf::Field_Kind_TYPE_INT64: { uint64 buffer64; stream_->ReadVarint64(&buffer64); - result = SimpleItoa(bit_cast<int64>(buffer64)); + result = SimpleItoa(::google::protobuf::bit_cast<int64>(buffer64)); break; } case google::protobuf::Field_Kind_TYPE_UINT32: { uint32 buffer32; stream_->ReadVarint32(&buffer32); - result = SimpleItoa(bit_cast<uint32>(buffer32)); + result = SimpleItoa(::google::protobuf::bit_cast<uint32>(buffer32)); break; } case google::protobuf::Field_Kind_TYPE_UINT64: { uint64 buffer64; stream_->ReadVarint64(&buffer64); - result = SimpleItoa(bit_cast<uint64>(buffer64)); + result = SimpleItoa(::google::protobuf::bit_cast<uint64>(buffer64)); break; } case google::protobuf::Field_Kind_TYPE_SINT32: { @@ -968,37 +974,37 @@ const string ProtoStreamObjectSource::ReadFieldValueAsString( case google::protobuf::Field_Kind_TYPE_SFIXED32: { uint32 buffer32; stream_->ReadLittleEndian32(&buffer32); - result = SimpleItoa(bit_cast<int32>(buffer32)); + result = SimpleItoa(::google::protobuf::bit_cast<int32>(buffer32)); break; } case google::protobuf::Field_Kind_TYPE_SFIXED64: { uint64 buffer64; stream_->ReadLittleEndian64(&buffer64); - result = SimpleItoa(bit_cast<int64>(buffer64)); + result = SimpleItoa(::google::protobuf::bit_cast<int64>(buffer64)); break; } case google::protobuf::Field_Kind_TYPE_FIXED32: { uint32 buffer32; stream_->ReadLittleEndian32(&buffer32); - result = SimpleItoa(bit_cast<uint32>(buffer32)); + result = SimpleItoa(::google::protobuf::bit_cast<uint32>(buffer32)); break; } case google::protobuf::Field_Kind_TYPE_FIXED64: { uint64 buffer64; stream_->ReadLittleEndian64(&buffer64); - result = SimpleItoa(bit_cast<uint64>(buffer64)); + result = SimpleItoa(::google::protobuf::bit_cast<uint64>(buffer64)); break; } case google::protobuf::Field_Kind_TYPE_FLOAT: { uint32 buffer32; stream_->ReadLittleEndian32(&buffer32); - result = SimpleFtoa(bit_cast<float>(buffer32)); + result = SimpleFtoa(::google::protobuf::bit_cast<float>(buffer32)); break; } case google::protobuf::Field_Kind_TYPE_DOUBLE: { uint64 buffer64; stream_->ReadLittleEndian64(&buffer64); - result = SimpleDtoa(bit_cast<double>(buffer64)); + result = SimpleDtoa(::google::protobuf::bit_cast<double>(buffer64)); break; } case google::protobuf::Field_Kind_TYPE_ENUM: { @@ -1044,7 +1050,7 @@ bool ProtoStreamObjectSource::IsMap( const google::protobuf::Type* field_type = typeinfo_->GetTypeByTypeUrl(field.type_url()); return field.kind() == google::protobuf::Field_Kind_TYPE_MESSAGE && - google::protobuf::util::converter::IsMap(field, *field_type); + util::converter::IsMap(field, *field_type); } std::pair<int64, int32> ProtoStreamObjectSource::ReadSecondsAndNanos( @@ -1066,11 +1072,11 @@ std::pair<int64, int32> ProtoStreamObjectSource::ReadSecondsAndNanos( if (field->number() == 1) { // read seconds stream_->ReadVarint64(&seconds); - signed_seconds = bit_cast<int64>(seconds); + signed_seconds = ::google::protobuf::bit_cast<int64>(seconds); } else if (field->number() == 2) { // read nanos stream_->ReadVarint32(&nanos); - signed_nanos = bit_cast<int32>(nanos); + signed_nanos = ::google::protobuf::bit_cast<int32>(nanos); } } return std::pair<int64, int32>(signed_seconds, signed_nanos); @@ -1082,7 +1088,7 @@ Status ProtoStreamObjectSource::IncrementRecursionDepth( return Status( util::error::INVALID_ARGUMENT, StrCat("Message too deep. Max recursion depth reached for type '", - type_name, "', field '", field_name, "'")); + type_name, "', field '", field_name, "'")); } return util::Status(); } @@ -1104,8 +1110,8 @@ const google::protobuf::Field* FindFieldByNumber( bool IsPackable(const google::protobuf::Field& field) { return field.cardinality() == google::protobuf::Field_Cardinality_CARDINALITY_REPEATED && - google::protobuf::FieldDescriptor::IsTypePackable( - static_cast<google::protobuf::FieldDescriptor::Type>(field.kind())); + FieldDescriptor::IsTypePackable( + static_cast<FieldDescriptor::Type>(field.kind())); } // TODO(skarvaje): Speed this up by not doing a linear scan. diff --git a/src/google/protobuf/util/internal/protostream_objectsource.h b/src/google/protobuf/util/internal/protostream_objectsource.h index acd081d9..c2549878 100644 --- a/src/google/protobuf/util/internal/protostream_objectsource.h +++ b/src/google/protobuf/util/internal/protostream_objectsource.h @@ -32,8 +32,8 @@ #define GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTOSTREAM_OBJECTSOURCE_H__ #include <functional> -#include <google/protobuf/stubs/hash.h> #include <string> +#include <unordered_map> #include <google/protobuf/stubs/common.h> #include <google/protobuf/type.pb.h> @@ -42,17 +42,20 @@ #include <google/protobuf/util/internal/type_info.h> #include <google/protobuf/util/type_resolver.h> #include <google/protobuf/stubs/stringpiece.h> +#include <google/protobuf/stubs/hash.h> #include <google/protobuf/stubs/status.h> #include <google/protobuf/stubs/statusor.h> +#include <google/protobuf/port_def.inc> namespace google { namespace protobuf { class Field; class Type; } // namespace protobuf +} // namespace google - +namespace google { namespace protobuf { namespace util { namespace converter { @@ -72,15 +75,16 @@ class TypeInfo; // <your message google::protobuf::Type>); // // Status status = os.WriteTo(<some ObjectWriter>); -class LIBPROTOBUF_EXPORT ProtoStreamObjectSource : public ObjectSource { +class PROTOBUF_EXPORT ProtoStreamObjectSource : public ObjectSource { public: - ProtoStreamObjectSource(google::protobuf::io::CodedInputStream* stream, + ProtoStreamObjectSource(io::CodedInputStream* stream, TypeResolver* type_resolver, const google::protobuf::Type& type); - virtual ~ProtoStreamObjectSource() override; + ~ProtoStreamObjectSource() override; - virtual util::Status NamedWriteTo(StringPiece name, ObjectWriter* ow) const override; + util::Status NamedWriteTo(StringPiece name, + ObjectWriter* ow) const override; // Sets whether or not to use lowerCamelCase casing for enum values. If set to // false, enum values are output without any case conversions. @@ -134,7 +138,8 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectSource : public ObjectSource { // 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& descriptor, - StringPiece name, const uint32 end_tag, + StringPiece name, + const uint32 end_tag, bool include_start_and_end, ObjectWriter* ow) const; @@ -142,8 +147,8 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectSource : public ObjectSource { // reading all sequential repeating elements. The caller should use this tag // before reading more tags from the stream. virtual util::StatusOr<uint32> RenderList( - const google::protobuf::Field* field, StringPiece name, uint32 list_tag, - ObjectWriter* ow) const; + const google::protobuf::Field* field, StringPiece name, + uint32 list_tag, ObjectWriter* ow) const; // Looks up a field and verify its consistency with wire type in tag. const google::protobuf::Field* FindAndVerifyField( @@ -151,17 +156,18 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectSource : public ObjectSource { // Renders a field value to the ObjectWriter. util::Status RenderField(const google::protobuf::Field* field, - StringPiece field_name, ObjectWriter* ow) const; + 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 string ReadFieldValueAsString( + const std::string ReadFieldValueAsString( const google::protobuf::Field& field) const; private: - ProtoStreamObjectSource(google::protobuf::io::CodedInputStream* stream, + ProtoStreamObjectSource(io::CodedInputStream* stream, const TypeInfo* typeinfo, const google::protobuf::Type& type); // Function that renders a well known type with a modified behavior. @@ -188,12 +194,14 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectSource : public ObjectSource { // Renders a google.protobuf.Timestamp value to ObjectWriter static util::Status RenderTimestamp(const ProtoStreamObjectSource* os, const google::protobuf::Type& type, - StringPiece name, ObjectWriter* ow); + 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); + StringPiece name, + ObjectWriter* ow); // Following RenderTYPE functions render well known types in // google/protobuf/wrappers.proto corresponding to TYPE. @@ -233,7 +241,8 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectSource : public ObjectSource { // 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); + StringPiece name, + ObjectWriter* ow); // Helper to render google.protobuf.Struct's ListValue fields to ObjectWriter. static util::Status RenderStructListValue( @@ -248,12 +257,13 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectSource : public ObjectSource { // Render the "FieldMask" type. static util::Status RenderFieldMask(const ProtoStreamObjectSource* os, const google::protobuf::Type& type, - StringPiece name, ObjectWriter* ow); + StringPiece name, + ObjectWriter* ow); - static hash_map<string, TypeRenderer>* renderers_; + static std::unordered_map<std::string, TypeRenderer>* renderers_; static void InitRendererMap(); static void DeleteRendererMap(); - static TypeRenderer* FindTypeRenderer(const string& type_url); + 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. @@ -277,7 +287,7 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectSource : public ObjectSource { StringPiece field_name) const; // Input stream to read from. Ownership rests with the caller. - google::protobuf::io::CodedInputStream* stream_; + io::CodedInputStream* stream_; // Type information for all the types used in the descriptor. Used to find // google::protobuf::Type of nested messages/enums. @@ -321,6 +331,8 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectSource : public ObjectSource { } // 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/src/google/protobuf/util/internal/protostream_objectsource_test.cc b/src/google/protobuf/util/internal/protostream_objectsource_test.cc index 4d86b856..5e2f86f4 100644 --- a/src/google/protobuf/util/internal/protostream_objectsource_test.cc +++ b/src/google/protobuf/util/internal/protostream_objectsource_test.cc @@ -33,7 +33,6 @@ #include <memory> #include <sstream> -#include <google/protobuf/stubs/casts.h> #include <google/protobuf/any.pb.h> #include <google/protobuf/io/coded_stream.h> #include <google/protobuf/io/zero_copy_stream_impl_lite.h> @@ -50,6 +49,7 @@ #include <google/protobuf/util/internal/constants.h> #include <google/protobuf/stubs/strutil.h> #include <gtest/gtest.h> +#include <google/protobuf/stubs/casts.h> namespace google { @@ -57,13 +57,6 @@ namespace protobuf { namespace util { namespace converter { -using google::protobuf::Descriptor; -using google::protobuf::DescriptorPool; -using google::protobuf::FileDescriptorProto; -using google::protobuf::Message; -using google::protobuf::io::ArrayInputStream; -using google::protobuf::io::CodedInputStream; -using util::Status; using google::protobuf::testing::AnyM; using google::protobuf::testing::AnyOut; using google::protobuf::testing::Author; @@ -82,7 +75,10 @@ using google::protobuf::testing::Primitive; using google::protobuf::testing::Proto3Message; using google::protobuf::testing::StructType; using google::protobuf::testing::TimestampDuration; +using io::ArrayInputStream; +using io::CodedInputStream; using ::testing::_; +using util::Status; namespace { @@ -124,7 +120,8 @@ class ProtostreamObjectSourceTest helper_.NewProtoSource(&in_stream, GetTypeUrl(descriptor))); if (use_lower_camel_for_enums_) os->set_use_lower_camel_for_enums(true); if (use_ints_for_enums_) os->set_use_ints_for_enums(true); - if (use_preserve_proto_field_names_) os->set_preserve_proto_field_names(true); + if (use_preserve_proto_field_names_) + os->set_preserve_proto_field_names(true); os->set_max_recursion_depth(64); return os->WriteTo(&mock_); } @@ -132,13 +129,13 @@ class ProtostreamObjectSourceTest void PrepareExpectingObjectWriterForRepeatedPrimitive() { ow_.StartObject("") ->StartList("repFix32") - ->RenderUint32("", bit_cast<uint32>(3201)) - ->RenderUint32("", bit_cast<uint32>(0)) - ->RenderUint32("", bit_cast<uint32>(3202)) + ->RenderUint32("", ::google::protobuf::bit_cast<uint32>(3201)) + ->RenderUint32("", ::google::protobuf::bit_cast<uint32>(0)) + ->RenderUint32("", ::google::protobuf::bit_cast<uint32>(3202)) ->EndList() ->StartList("repU32") - ->RenderUint32("", bit_cast<uint32>(3203)) - ->RenderUint32("", bit_cast<uint32>(0)) + ->RenderUint32("", ::google::protobuf::bit_cast<uint32>(3203)) + ->RenderUint32("", ::google::protobuf::bit_cast<uint32>(0)) ->EndList() ->StartList("repI32") ->RenderInt32("", 0) @@ -155,13 +152,13 @@ class ProtostreamObjectSourceTest ->RenderInt32("", 3208) ->EndList() ->StartList("repFix64") - ->RenderUint64("", bit_cast<uint64>(6401LL)) - ->RenderUint64("", bit_cast<uint64>(0LL)) + ->RenderUint64("", ::google::protobuf::bit_cast<uint64>(6401LL)) + ->RenderUint64("", ::google::protobuf::bit_cast<uint64>(0LL)) ->EndList() ->StartList("repU64") - ->RenderUint64("", bit_cast<uint64>(0LL)) - ->RenderUint64("", bit_cast<uint64>(6402LL)) - ->RenderUint64("", bit_cast<uint64>(6403LL)) + ->RenderUint64("", ::google::protobuf::bit_cast<uint64>(0LL)) + ->RenderUint64("", ::google::protobuf::bit_cast<uint64>(6402LL)) + ->RenderUint64("", ::google::protobuf::bit_cast<uint64>(6403LL)) ->EndList() ->StartList("repI64") ->RenderInt64("", 6404L) @@ -323,13 +320,13 @@ TEST_P(ProtostreamObjectSourceTest, Primitives) { primitive.set_bool_(true); ow_.StartObject("") - ->RenderUint32("fix32", bit_cast<uint32>(3201)) - ->RenderUint32("u32", bit_cast<uint32>(3202)) + ->RenderUint32("fix32", ::google::protobuf::bit_cast<uint32>(3201)) + ->RenderUint32("u32", ::google::protobuf::bit_cast<uint32>(3202)) ->RenderInt32("i32", 3203) ->RenderInt32("sf32", 3204) ->RenderInt32("s32", 3205) - ->RenderUint64("fix64", bit_cast<uint64>(6401LL)) - ->RenderUint64("u64", bit_cast<uint64>(6402LL)) + ->RenderUint64("fix64", ::google::protobuf::bit_cast<uint64>(6401LL)) + ->RenderUint64("u64", ::google::protobuf::bit_cast<uint64>(6402LL)) ->RenderInt64("i64", 6403L) ->RenderInt64("sf64", 6404L) ->RenderInt64("s64", 6405L) @@ -746,8 +743,8 @@ TEST_P(ProtostreamObjectSourceMapsTest, MissingKeysTest) { class ProtostreamObjectSourceAnysTest : public ProtostreamObjectSourceTest { protected: ProtostreamObjectSourceAnysTest() { - helper_.ResetTypeInfo(AnyOut::descriptor(), - google::protobuf::Any::descriptor()); + helper_.ResetTypeInfo({AnyOut::descriptor(), Book::descriptor(), + google::protobuf::Any::descriptor()}); } }; diff --git a/src/google/protobuf/util/internal/protostream_objectwriter.cc b/src/google/protobuf/util/internal/protostream_objectwriter.cc index a1a7030a..9c52116e 100644 --- a/src/google/protobuf/util/internal/protostream_objectwriter.cc +++ b/src/google/protobuf/util/internal/protostream_objectwriter.cc @@ -32,28 +32,33 @@ #include <functional> #include <stack> +#include <unordered_map> +#include <unordered_set> -#include <google/protobuf/stubs/once.h> #include <google/protobuf/stubs/time.h> +#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/map_util.h> #include <google/protobuf/stubs/statusor.h> +#include <google/protobuf/port_def.inc> + namespace google { namespace protobuf { namespace util { namespace converter { -using google::protobuf::internal::WireFormatLite; -using util::error::INVALID_ARGUMENT; +using ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite; using util::Status; using util::StatusOr; +using util::error::INVALID_ARGUMENT; ProtoStreamObjectWriter::ProtoStreamObjectWriter( @@ -65,11 +70,24 @@ ProtoStreamObjectWriter::ProtoStreamObjectWriter( 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); } 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); +} + +ProtoStreamObjectWriter::ProtoStreamObjectWriter( + const TypeInfo* typeinfo, const google::protobuf::Type& type, strings::ByteSink* output, ErrorListener* listener) : ProtoWriter(typeinfo, type, output, listener), master_type_(type), @@ -120,7 +138,7 @@ Status GetNanosFromStringPiece(StringPiece s_nanos, // "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.ToString(), &i_nanos)) { + if (!s_nanos.empty() && !safe_strto32(s_nanos, &i_nanos)) { return Status(INVALID_ARGUMENT, parse_failure_message); } if (i_nanos > kNanosPerSecond || i_nanos < 0) { @@ -305,7 +323,7 @@ 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_ = value.str().ToString(); + type_url_ = string(value.str()); } else { StatusOr<string> s = value.ToString(); if (!s.ok()) { @@ -337,7 +355,7 @@ void ProtoStreamObjectWriter::AnyWriter::StartAny(const DataPiece& value) { // Create our object writer and initialize it with the first StartObject // call. ow_.reset(new ProtoStreamObjectWriter(parent_->typeinfo(), *type, &output_, - parent_->listener())); + 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 @@ -368,8 +386,9 @@ void ProtoStreamObjectWriter::AnyWriter::WriteAny() { } 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())); + parent_->InvalidValue("Any", + StrCat("Missing @type for any field in ", + parent_->master_type_.name())); invalid_ = true; } return; @@ -431,7 +450,7 @@ ProtoStreamObjectWriter::Item::Item(ProtoStreamObjectWriter* enclosing, any_.reset(new AnyWriter(ow_)); } if (item_type == MAP) { - map_keys_.reset(new hash_set<string>); + map_keys_.reset(new std::unordered_set<string>); } } @@ -448,13 +467,13 @@ ProtoStreamObjectWriter::Item::Item(ProtoStreamObjectWriter::Item* parent, any_.reset(new AnyWriter(ow_)); } if (item_type == MAP) { - map_keys_.reset(new hash_set<string>); + map_keys_.reset(new std::unordered_set<string>); } } bool ProtoStreamObjectWriter::Item::InsertMapKeyIfNotPresent( StringPiece map_key) { - return InsertIfNotPresent(map_keys_.get(), map_key.ToString()); + return InsertIfNotPresent(map_keys_.get(), string(map_key)); } ProtoStreamObjectWriter* ProtoStreamObjectWriter::StartObject( @@ -477,7 +496,7 @@ ProtoStreamObjectWriter* ProtoStreamObjectWriter::StartObject( // stream, we write those values. if (master_type_.name() == kStructType) { // Struct has a map<string, Value> field called "fields". - // https://github.com/google/protobuf/blob/master/src/google/protobuf/struct.proto + // https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/struct.proto // "fields": [ Push("fields", Item::MAP, true, true); return this; @@ -488,7 +507,7 @@ ProtoStreamObjectWriter* ProtoStreamObjectWriter::StartObject( // 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/google/protobuf/blob/master/src/google/protobuf/struct.proto + // https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/struct.proto // Also start the map field "fields" within the struct. // "struct_value": { // "fields": [ @@ -534,7 +553,8 @@ ProtoStreamObjectWriter* ProtoStreamObjectWriter::StartObject( 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); + 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; @@ -618,7 +638,8 @@ ProtoStreamObjectWriter* ProtoStreamObjectWriter::EndObject() { return this; } -ProtoStreamObjectWriter* ProtoStreamObjectWriter::StartList(StringPiece name) { +ProtoStreamObjectWriter* ProtoStreamObjectWriter::StartList( + StringPiece name) { if (invalid_depth() > 0) { IncrementInvalidDepth(); return this; @@ -641,7 +662,7 @@ ProtoStreamObjectWriter* ProtoStreamObjectWriter::StartList(StringPiece name) { // we have to start the "list_value" within google.protobuf.Value. // // See - // https://github.com/google/protobuf/blob/master/src/google/protobuf/struct.proto + // https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/struct.proto // // Render // "<name>": { @@ -727,7 +748,7 @@ ProtoStreamObjectWriter* ProtoStreamObjectWriter::StartList(StringPiece name) { // Report an error. InvalidValue("Map", StrCat("Cannot have repeated items ('", name, - "') within a map.")); + "') within a map.")); return this; } @@ -818,8 +839,8 @@ ProtoStreamObjectWriter* ProtoStreamObjectWriter::StartList(StringPiece name) { } if (IsMap(*field)) { - InvalidValue("Map", - StrCat("Cannot bind a list to map for field '", name, "'.")); + InvalidValue("Map", StrCat("Cannot bind a list to map for field '", + name, "'.")); IncrementInvalidDepth(); return this; } @@ -924,7 +945,7 @@ Status ProtoStreamObjectWriter::RenderTimestamp(ProtoStreamObjectWriter* ow, if (data.type() != DataPiece::TYPE_STRING) { return Status(INVALID_ARGUMENT, StrCat("Invalid data type for timestamp, value is ", - data.ValueAsStringOrDefault(""))); + data.ValueAsStringOrDefault(""))); } StringPiece value(data.str()); @@ -955,13 +976,13 @@ Status ProtoStreamObjectWriter::RenderFieldMask(ProtoStreamObjectWriter* ow, if (data.type() != DataPiece::TYPE_STRING) { return Status(INVALID_ARGUMENT, StrCat("Invalid data type for field mask, value is ", - data.ValueAsStringOrDefault(""))); + 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. - std::unique_ptr<ResultCallback1<util::Status, StringPiece> > callback( + std::unique_ptr<ResultCallback1<util::Status, StringPiece>> callback( ::google::protobuf::NewPermanentCallback(&RenderOneFieldPath, ow)); return DecodeCompactFieldMaskPaths(data.str(), callback.get()); } @@ -972,7 +993,7 @@ Status ProtoStreamObjectWriter::RenderDuration(ProtoStreamObjectWriter* ow, if (data.type() != DataPiece::TYPE_STRING) { return Status(INVALID_ARGUMENT, StrCat("Invalid data type for duration, value is ", - data.ValueAsStringOrDefault(""))); + data.ValueAsStringOrDefault(""))); } StringPiece value(data.str()); @@ -1042,8 +1063,8 @@ ProtoStreamObjectWriter* ProtoStreamObjectWriter::RenderDataPiece( ProtoWriter::StartObject(name); status = (*type_renderer)(this, data); if (!status.ok()) { - InvalidValue(master_type_.name(), - StrCat("Field '", name, "', ", status.error_message())); + InvalidValue(master_type_.name(), StrCat("Field '", name, "', ", + status.error_message())); } ProtoWriter::EndObject(); return this; @@ -1058,18 +1079,27 @@ ProtoStreamObjectWriter* ProtoStreamObjectWriter::RenderDataPiece( if (current_->IsMap()) { if (!ValidMapKey(name)) 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())); field = Lookup("value"); if (field == nullptr) { - Pop(); 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: @@ -1079,8 +1109,8 @@ ProtoStreamObjectWriter* ProtoStreamObjectWriter::RenderDataPiece( Push("value", Item::MESSAGE, true, false); status = (*type_renderer)(this, data); if (!status.ok()) { - InvalidValue(field->type_url(), - StrCat("Field '", name, "', ", status.error_message())); + InvalidValue(field->type_url(), StrCat("Field '", name, "', ", + status.error_message())); } Pop(); return this; @@ -1113,8 +1143,8 @@ ProtoStreamObjectWriter* ProtoStreamObjectWriter::RenderDataPiece( Push(name, Item::MESSAGE, false, false); status = (*type_renderer)(this, data); if (!status.ok()) { - InvalidValue(field->type_url(), - StrCat("Field '", name, "', ", status.error_message())); + InvalidValue(field->type_url(), StrCat("Field '", name, "', ", + status.error_message())); } Pop(); } @@ -1134,12 +1164,13 @@ ProtoStreamObjectWriter* ProtoStreamObjectWriter::RenderDataPiece( // Map of functions that are responsible for rendering well known type // represented by the key. -hash_map<string, ProtoStreamObjectWriter::TypeRenderer>* +std::unordered_map<string, ProtoStreamObjectWriter::TypeRenderer>* ProtoStreamObjectWriter::renderers_ = NULL; -GOOGLE_PROTOBUF_DECLARE_ONCE(writer_renderers_init_); +PROTOBUF_NAMESPACE_ID::internal::once_flag writer_renderers_init_; void ProtoStreamObjectWriter::InitRendererMap() { - renderers_ = new hash_map<string, ProtoStreamObjectWriter::TypeRenderer>(); + renderers_ = + new std::unordered_map<string, ProtoStreamObjectWriter::TypeRenderer>(); (*renderers_)["type.googleapis.com/google.protobuf.Timestamp"] = &ProtoStreamObjectWriter::RenderTimestamp; (*renderers_)["type.googleapis.com/google.protobuf.Duration"] = @@ -1194,7 +1225,8 @@ void ProtoStreamObjectWriter::DeleteRendererMap() { ProtoStreamObjectWriter::TypeRenderer* ProtoStreamObjectWriter::FindTypeRenderer(const string& type_url) { - ::google::protobuf::GoogleOnceInit(&writer_renderers_init_, &InitRendererMap); + PROTOBUF_NAMESPACE_ID::internal::call_once(writer_renderers_init_, + InitRendererMap); return FindOrNull(*renderers_, type_url); } @@ -1204,14 +1236,16 @@ bool ProtoStreamObjectWriter::ValidMapKey(StringPiece unnormalized_name) { if (!current_->InsertMapKeyIfNotPresent(unnormalized_name)) { listener()->InvalidName( location(), unnormalized_name, - StrCat("Repeated map key: '", unnormalized_name, "' is already set.")); + StrCat("Repeated map key: '", unnormalized_name, + "' is already set.")); return false; } return true; } -void ProtoStreamObjectWriter::Push(StringPiece name, Item::ItemType item_type, +void ProtoStreamObjectWriter::Push(StringPiece name, + Item::ItemType item_type, bool is_placeholder, bool is_list) { is_list ? ProtoWriter::StartList(name) : ProtoWriter::StartObject(name); @@ -1247,7 +1281,7 @@ bool ProtoStreamObjectWriter::IsMap(const google::protobuf::Field& field) { const google::protobuf::Type* field_type = typeinfo()->GetTypeByTypeUrl(field.type_url()); - return google::protobuf::util::converter::IsMap(field, *field_type); + return converter::IsMap(field, *field_type); } bool ProtoStreamObjectWriter::IsAny(const google::protobuf::Field& field) { diff --git a/src/google/protobuf/util/internal/protostream_objectwriter.h b/src/google/protobuf/util/internal/protostream_objectwriter.h index d9bb432e..fe8170d1 100644 --- a/src/google/protobuf/util/internal/protostream_objectwriter.h +++ b/src/google/protobuf/util/internal/protostream_objectwriter.h @@ -32,8 +32,9 @@ #define GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTOSTREAM_OBJECTWRITER_H__ #include <deque> -#include <google/protobuf/stubs/hash.h> #include <string> +#include <unordered_map> +#include <unordered_set> #include <google/protobuf/stubs/common.h> #include <google/protobuf/io/coded_stream.h> @@ -46,6 +47,9 @@ #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/hash.h> + +#include <google/protobuf/port_def.inc> namespace google { namespace protobuf { @@ -53,14 +57,16 @@ namespace io { class CodedOutputStream; } // namespace io } // namespace protobuf +} // namespace google - +namespace google { namespace protobuf { class Type; class Field; } // namespace protobuf +} // namespace google - +namespace google { namespace protobuf { namespace util { namespace converter { @@ -72,7 +78,7 @@ class ObjectLocationTracker; // the ProtoWriter class to write raw proto bytes. // // It also supports streaming. -class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public ProtoWriter { +class PROTOBUF_EXPORT ProtoStreamObjectWriter : public ProtoWriter { public: // Options that control ProtoStreamObjectWriter class's behavior. struct Options { @@ -87,17 +93,27 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public ProtoWriter { 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. + // 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, skips rendering the map entry if map value is null unless the + // value type is google.protobuf.NullType. + bool ignore_null_value_map_entry; + Options() : struct_integers_as_strings(false), ignore_unknown_fields(false), - use_lower_camel_for_enums(false) {} + ignore_unknown_enum_values(false), + use_lower_camel_for_enums(false), + ignore_null_value_map_entry(false) {} // Default instance of Options with all options set to defaults. static const Options& Defaults() { @@ -112,18 +128,18 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public ProtoWriter { strings::ByteSink* output, ErrorListener* listener, const ProtoStreamObjectWriter::Options& options = ProtoStreamObjectWriter::Options::Defaults()); - virtual ~ProtoStreamObjectWriter() override; + ~ProtoStreamObjectWriter() override; // ObjectWriter methods. - virtual ProtoStreamObjectWriter* StartObject(StringPiece name) override; - virtual ProtoStreamObjectWriter* EndObject() override; - virtual ProtoStreamObjectWriter* StartList(StringPiece name) override; - virtual ProtoStreamObjectWriter* EndList() override; + 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'. - virtual ProtoStreamObjectWriter* RenderDataPiece(StringPiece name, - const DataPiece& value) override; + ProtoStreamObjectWriter* RenderDataPiece(StringPiece name, + const DataPiece& data) override; protected: // Function that renders a well known type with modified behavior. @@ -131,7 +147,7 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public ProtoWriter { const DataPiece&); // Handles writing Anys out using nested object writers and the like. - class LIBPROTOBUF_EXPORT AnyWriter { + class PROTOBUF_EXPORT AnyWriter { public: explicit AnyWriter(ProtoStreamObjectWriter* parent); ~AnyWriter(); @@ -156,7 +172,7 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public ProtoWriter { 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 LIBPROTOBUF_EXPORT Event { + class PROTOBUF_EXPORT Event { public: enum Type { START_OBJECT = 0, @@ -171,13 +187,11 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public ProtoWriter { // Constructor for START_OBJECT and START_LIST events. explicit Event(Type type, StringPiece name) - : type_(type), - name_(name.ToString()), - value_(DataPiece::NullData()) {} + : 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.ToString()), value_(value) { + : type_(RENDER_DATA_PIECE), name_(name), value_(value) { DeepCopy(); } @@ -200,9 +214,9 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public ProtoWriter { void DeepCopy(); Type type_; - string name_; + std::string name_; DataPiece value_; - string value_storage_; + std::string value_storage_; }; // Handles starting up the any once we have a type. @@ -219,14 +233,14 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public ProtoWriter { std::unique_ptr<ProtoStreamObjectWriter> ow_; // The type_url_ that this Any represents. - string type_url_; + 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. - string data_; + std::string data_; strings::StringByteSink output_; // The depth within the Any, so we can track when we're done. @@ -247,7 +261,7 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public ProtoWriter { // Represents an item in a stack of items used to keep state between // ObjectWrier events. - class LIBPROTOBUF_EXPORT Item : public BaseElement { + class PROTOBUF_EXPORT Item : public BaseElement { public: // Indicates the type of item. enum ItemType { @@ -263,7 +277,7 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public ProtoWriter { // Constructor for a field of a message. Item(Item* parent, ItemType item_type, bool is_placeholder, bool is_list); - virtual ~Item() override {} + ~Item() override {} // These functions return true if the element type is corresponding to the // type in function name. @@ -272,7 +286,7 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public ProtoWriter { AnyWriter* any() const { return any_.get(); } - virtual Item* parent() const override { + Item* parent() const override { return static_cast<Item*>(BaseElement::parent()); } @@ -299,7 +313,7 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public ProtoWriter { // 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<hash_set<string> > map_keys_; + 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. @@ -316,6 +330,11 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public ProtoWriter { 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); @@ -355,7 +374,7 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public ProtoWriter { static void InitRendererMap(); static void DeleteRendererMap(); - static TypeRenderer* FindTypeRenderer(const string& type_url); + 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. @@ -371,8 +390,8 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public ProtoWriter { // is_placeholder conveys whether the item is a placeholder item or not. // Placeholder items are pushed when adding auxillary types' StartObject or // StartList calls. - void Push(StringPiece name, Item::ItemType item_type, bool is_placeholder, - bool is_list); + 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. @@ -385,7 +404,7 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public ProtoWriter { private: // Helper functions to create the map and find functions responsible for // rendering well known types, keyed by type URL. - static hash_map<string, TypeRenderer>* renderers_; + 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. @@ -403,6 +422,8 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public ProtoWriter { } // 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/src/google/protobuf/util/internal/protostream_objectwriter_test.cc b/src/google/protobuf/util/internal/protostream_objectwriter_test.cc index 9c50e7dd..66a8f003 100644 --- a/src/google/protobuf/util/internal/protostream_objectwriter_test.cc +++ b/src/google/protobuf/util/internal/protostream_objectwriter_test.cc @@ -58,6 +58,7 @@ #include <gtest/gtest.h> + namespace google { namespace protobuf { namespace util { @@ -79,11 +80,6 @@ using google::protobuf::testing::TestJsonName2; using google::protobuf::testing::TimestampDuration; using google::protobuf::testing::ValueWrapper; using google::protobuf::testing::oneofs::OneOfsRequest; -using google::protobuf::Descriptor; -using google::protobuf::DescriptorPool; -using google::protobuf::DynamicMessageFactory; -using google::protobuf::FileDescriptorProto; -using google::protobuf::Message; using strings::GrowingArrayByteSink; using ::testing::_; using ::testing::Args; @@ -274,7 +270,7 @@ TEST_P(ProtoStreamObjectWriterTest, CustomJsonName) { } // Test that two messages can have different fields mapped to the same JSON -// name. See: https://github.com/google/protobuf/issues/1415 +// name. See: https://github.com/protocolbuffers/protobuf/issues/1415 TEST_P(ProtoStreamObjectWriterTest, ConflictingJsonName) { ResetTypeInfo(TestJsonName1::descriptor()); TestJsonName1 message1; @@ -517,8 +513,8 @@ TEST_P(ProtoStreamObjectWriterTest, NaNInputTest) { EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_SFIXED64"), StringPiece("\"NaN\""))) .With(Args<0>(HasObjectLocation("sf64"))); - EXPECT_CALL(listener_, - InvalidValue(_, StringPiece("TYPE_BOOL"), StringPiece("\"NaN\""))) + EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_BOOL"), + StringPiece("\"NaN\""))) .With(Args<0>(HasObjectLocation("bool"))); ow_->StartObject("") @@ -591,9 +587,9 @@ TEST_P(ProtoStreamObjectWriterTest, NonRepeatedExplicitPrimitiveList) { EXPECT_CALL( listener_, - InvalidName( - _, StringPiece("name"), - StringPiece("Proto field is not repeating, cannot start list."))) + InvalidName(_, StringPiece("name"), + StringPiece( + "Proto field is not repeating, cannot start list."))) .With(Args<0>(HasObjectLocation("author"))); ow_->StartObject("") ->StartObject("author") @@ -687,9 +683,9 @@ TEST_P(ProtoStreamObjectWriterTest, NonRepeatedExplicitMessageList) { EXPECT_CALL( listener_, - InvalidName( - _, StringPiece("publisher"), - StringPiece("Proto field is not repeating, cannot start list."))) + InvalidName(_, StringPiece("publisher"), + StringPiece( + "Proto field is not repeating, cannot start list."))) .With(Args<0>(HasObjectLocation(""))); ow_->StartObject("") ->StartObject("author") @@ -925,6 +921,22 @@ TEST_P(ProtoStreamObjectWriterTest, IgnoreUnknownListAtPublisher) { CheckOutput(expected); } +TEST_P(ProtoStreamObjectWriterTest, + IgnoreUnknownFieldsDontIgnoreUnknownEnumValues) { + ResetTypeInfo(Proto3Message::descriptor()); + + Proto3Message expected; + EXPECT_CALL( + listener_, + InvalidValue(_, StringPiece("TYPE_ENUM"), + StringPiece("\"someunknownvalueyouwillneverknow\""))) + .With(Args<0>(HasObjectLocation("enum_value"))); + ow_->StartObject("") + ->RenderString("enumValue", "someunknownvalueyouwillneverknow") + ->EndObject(); + CheckOutput(expected); +} + TEST_P(ProtoStreamObjectWriterTest, AcceptUnknownEnumValue) { ResetTypeInfo(Proto3Message::descriptor()); @@ -1030,9 +1042,10 @@ TEST_P(ProtoStreamObjectWriterTest, RootNamedObject) { Book expected; expected.set_title("Annie"); - EXPECT_CALL(listener_, - InvalidName(_, StringPiece("oops"), - StringPiece("Root element should not be named."))) + EXPECT_CALL( + listener_, + InvalidName(_, StringPiece("oops"), + StringPiece("Root element should not be named."))) .With(Args<0>(HasObjectLocation(""))); ow_->StartObject("oops")->RenderString("title", "Annie")->EndObject(); CheckOutput(expected, 7); @@ -1041,9 +1054,10 @@ TEST_P(ProtoStreamObjectWriterTest, RootNamedObject) { TEST_P(ProtoStreamObjectWriterTest, RootNamedList) { Book empty; - EXPECT_CALL(listener_, - InvalidName(_, StringPiece("oops"), - StringPiece("Root element should not be named."))) + EXPECT_CALL( + listener_, + InvalidName(_, StringPiece("oops"), + StringPiece("Root element should not be named."))) .With(Args<0>(HasObjectLocation(""))); ow_->StartList("oops")->RenderString("", "item")->EndList(); CheckOutput(empty, 0); @@ -1179,10 +1193,10 @@ TEST_P(ProtoStreamObjectWriterTimestampDurationTest, EXPECT_CALL( listener_, - InvalidValue(_, - StringPiece("type.googleapis.com/google.protobuf.Timestamp"), - StringPiece("Field 'ts', Invalid time format: " - "2016-03-07T15:14:23+"))); + InvalidValue( + _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"), + StringPiece("Field 'ts', Invalid time format: " + "2016-03-07T15:14:23+"))); ow_->StartObject("")->RenderString("ts", "2016-03-07T15:14:23+")->EndObject(); CheckOutput(timestamp); @@ -1194,10 +1208,10 @@ TEST_P(ProtoStreamObjectWriterTimestampDurationTest, EXPECT_CALL( listener_, - InvalidValue(_, - StringPiece("type.googleapis.com/google.protobuf.Timestamp"), - StringPiece("Field 'ts', Invalid time format: " - "2016-03-07T15:14:23+08-10"))); + InvalidValue( + _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"), + StringPiece("Field 'ts', Invalid time format: " + "2016-03-07T15:14:23+08-10"))); ow_->StartObject("") ->RenderString("ts", "2016-03-07T15:14:23+08-10") @@ -1211,10 +1225,10 @@ TEST_P(ProtoStreamObjectWriterTimestampDurationTest, EXPECT_CALL( listener_, - InvalidValue(_, - StringPiece("type.googleapis.com/google.protobuf.Timestamp"), - StringPiece("Field 'ts', Invalid time format: " - "2016-03-07T15:14:23+24:10"))); + InvalidValue( + _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"), + StringPiece("Field 'ts', Invalid time format: " + "2016-03-07T15:14:23+24:10"))); ow_->StartObject("") ->RenderString("ts", "2016-03-07T15:14:23+24:10") @@ -1228,10 +1242,10 @@ TEST_P(ProtoStreamObjectWriterTimestampDurationTest, EXPECT_CALL( listener_, - InvalidValue(_, - StringPiece("type.googleapis.com/google.protobuf.Timestamp"), - StringPiece("Field 'ts', Invalid time format: " - "2016-03-07T15:14:23+04:60"))); + InvalidValue( + _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"), + StringPiece("Field 'ts', Invalid time format: " + "2016-03-07T15:14:23+04:60"))); ow_->StartObject("") ->RenderString("ts", "2016-03-07T15:14:23+04:60") @@ -1244,9 +1258,9 @@ TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError1) { EXPECT_CALL( listener_, - InvalidValue(_, - StringPiece("type.googleapis.com/google.protobuf.Timestamp"), - StringPiece("Field 'ts', Invalid time format: "))); + InvalidValue( + _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"), + StringPiece("Field 'ts', Invalid time format: "))); ow_->StartObject("")->RenderString("ts", "")->EndObject(); CheckOutput(timestamp); @@ -1257,9 +1271,9 @@ TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError2) { EXPECT_CALL( listener_, - InvalidValue(_, - StringPiece("type.googleapis.com/google.protobuf.Timestamp"), - StringPiece("Field 'ts', Invalid time format: Z"))); + InvalidValue( + _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"), + StringPiece("Field 'ts', Invalid time format: Z"))); ow_->StartObject("")->RenderString("ts", "Z")->EndObject(); CheckOutput(timestamp); @@ -1270,10 +1284,10 @@ TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError3) { EXPECT_CALL( listener_, - InvalidValue(_, - StringPiece("type.googleapis.com/google.protobuf.Timestamp"), - StringPiece("Field 'ts', Invalid time format: " - "1970-01-01T00:00:00.ABZ"))); + InvalidValue( + _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"), + StringPiece("Field 'ts', Invalid time format: " + "1970-01-01T00:00:00.ABZ"))); ow_->StartObject("") ->RenderString("ts", "1970-01-01T00:00:00.ABZ") @@ -1286,10 +1300,10 @@ TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError4) { EXPECT_CALL( listener_, - InvalidValue(_, - StringPiece("type.googleapis.com/google.protobuf.Timestamp"), - StringPiece("Field 'ts', Invalid time format: " - "-8031-10-18T00:00:00.000Z"))); + InvalidValue( + _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"), + StringPiece("Field 'ts', Invalid time format: " + "-8031-10-18T00:00:00.000Z"))); ow_->StartObject("") ->RenderString("ts", "-8031-10-18T00:00:00.000Z") @@ -1302,10 +1316,10 @@ TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError5) { EXPECT_CALL( listener_, - InvalidValue(_, - StringPiece("type.googleapis.com/google.protobuf.Timestamp"), - StringPiece("Field 'ts', Invalid time format: " - "2015-11-23T03:37:35.033155 Z"))); + InvalidValue( + _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"), + StringPiece("Field 'ts', Invalid time format: " + "2015-11-23T03:37:35.033155 Z"))); ow_->StartObject("") // Whitespace in the Timestamp nanos is not allowed. @@ -1319,10 +1333,10 @@ TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError6) { EXPECT_CALL( listener_, - InvalidValue(_, - StringPiece("type.googleapis.com/google.protobuf.Timestamp"), - StringPiece("Field 'ts', Invalid time format: " - "2015-11-23T03:37:35.033155 1234Z"))); + InvalidValue( + _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"), + StringPiece("Field 'ts', Invalid time format: " + "2015-11-23T03:37:35.033155 1234Z"))); ow_->StartObject("") // Whitespace in the Timestamp nanos is not allowed. @@ -1336,10 +1350,10 @@ TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError7) { EXPECT_CALL( listener_, - InvalidValue(_, - StringPiece("type.googleapis.com/google.protobuf.Timestamp"), - StringPiece("Field 'ts', Invalid time format: " - "2015-11-23T03:37:35.033abc155Z"))); + InvalidValue( + _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"), + StringPiece("Field 'ts', Invalid time format: " + "2015-11-23T03:37:35.033abc155Z"))); ow_->StartObject("") // Non-numeric characters in the Timestamp nanos is not allowed. @@ -1353,10 +1367,10 @@ TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError8) { EXPECT_CALL( listener_, - InvalidValue(_, - StringPiece("type.googleapis.com/google.protobuf.Timestamp"), - StringPiece("Field 'ts', Invalid time format: " - "0-12-31T23:59:59.000Z"))); + InvalidValue( + _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"), + StringPiece("Field 'ts', Invalid time format: " + "0-12-31T23:59:59.000Z"))); ow_->StartObject("") ->RenderString("ts", "0-12-31T23:59:59.000Z") @@ -1381,8 +1395,9 @@ TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidDurationError1) { listener_, InvalidValue( _, StringPiece("type.googleapis.com/google.protobuf.Duration"), - StringPiece("Field 'dur', Illegal duration format; duration must " - "end with 's'"))); + StringPiece( + "Field 'dur', Illegal duration format; duration must " + "end with 's'"))); ow_->StartObject("")->RenderString("dur", "")->EndObject(); CheckOutput(duration); @@ -1395,8 +1410,9 @@ TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidDurationError2) { listener_, InvalidValue( _, StringPiece("type.googleapis.com/google.protobuf.Duration"), - StringPiece("Field 'dur', Invalid duration format, failed to parse " - "seconds"))); + StringPiece( + "Field 'dur', Invalid duration format, failed to parse " + "seconds"))); ow_->StartObject("")->RenderString("dur", "s")->EndObject(); CheckOutput(duration); @@ -1410,7 +1426,7 @@ TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidDurationError3) { InvalidValue( _, StringPiece("type.googleapis.com/google.protobuf.Duration"), StringPiece("Field 'dur', Invalid duration format, failed to " - "parse nano seconds"))); + "parse nano seconds"))); ow_->StartObject("")->RenderString("dur", "123.DEFs")->EndObject(); CheckOutput(duration); @@ -1421,9 +1437,9 @@ TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidDurationError4) { EXPECT_CALL( listener_, - InvalidValue(_, - StringPiece("type.googleapis.com/google.protobuf.Duration"), - StringPiece("Field 'dur', Duration value exceeds limits"))); + InvalidValue( + _, StringPiece("type.googleapis.com/google.protobuf.Duration"), + StringPiece("Field 'dur', Duration value exceeds limits"))); ow_->StartObject("")->RenderString("dur", "315576000002s")->EndObject(); CheckOutput(duration); @@ -1434,9 +1450,9 @@ TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidDurationError5) { EXPECT_CALL( listener_, - InvalidValue(_, - StringPiece("type.googleapis.com/google.protobuf.Duration"), - StringPiece("Field 'dur', Duration value exceeds limits"))); + InvalidValue( + _, StringPiece("type.googleapis.com/google.protobuf.Duration"), + StringPiece("Field 'dur', Duration value exceeds limits"))); ow_->StartObject("")->RenderString("dur", "0.1000000001s")->EndObject(); CheckOutput(duration); @@ -1533,8 +1549,9 @@ TEST_P(ProtoStreamObjectWriterStructTest, StructInvalidInputFailure) { StructType struct_type; EXPECT_CALL( listener_, - InvalidValue(_, StringPiece("type.googleapis.com/google.protobuf.Struct"), - StringPiece("true"))) + InvalidValue( + _, StringPiece("type.googleapis.com/google.protobuf.Struct"), + StringPiece("true"))) .With(Args<0>(HasObjectLocation("object"))); ow_->StartObject("")->RenderBool("object", true)->EndObject(); @@ -1564,10 +1581,10 @@ TEST_P(ProtoStreamObjectWriterStructTest, StructValuePreservesNull) { } TEST_P(ProtoStreamObjectWriterStructTest, SimpleRepeatedStructMapKeyTest) { - EXPECT_CALL( - listener_, - InvalidName(_, StringPiece("gBike"), - StringPiece("Repeated map key: 'gBike' is already set."))); + EXPECT_CALL(listener_, + InvalidName(_, StringPiece("gBike"), + StringPiece( + "Repeated map key: 'gBike' is already set."))); ow_->StartObject("") ->StartObject("object") ->RenderString("gBike", "v1") @@ -1641,8 +1658,12 @@ TEST_P(ProtoStreamObjectWriterStructTest, ValuePreservesNull) { class ProtoStreamObjectWriterMapTest : public BaseProtoStreamObjectWriterTest { protected: - ProtoStreamObjectWriterMapTest() - : BaseProtoStreamObjectWriterTest(MapIn::descriptor()) {} + ProtoStreamObjectWriterMapTest() { + std::vector<const Descriptor*> descriptors; + descriptors.push_back(MapIn::descriptor()); + descriptors.push_back(google::protobuf::DoubleValue::descriptor()); + ResetTypeInfo(descriptors); + } }; INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest, @@ -1654,9 +1675,9 @@ TEST_P(ProtoStreamObjectWriterMapTest, MapShouldNotAcceptList) { MapIn mm; EXPECT_CALL( listener_, - InvalidValue( - _, StringPiece("Map"), - StringPiece("Cannot bind a list to map for field 'map_input'."))); + InvalidValue(_, StringPiece("Map"), + StringPiece( + "Cannot bind a list to map for field 'map_input'."))); ow_->StartObject("") ->StartList("map_input") ->RenderString("a", "b") @@ -1665,6 +1686,36 @@ TEST_P(ProtoStreamObjectWriterMapTest, MapShouldNotAcceptList) { CheckOutput(mm); } +TEST_P(ProtoStreamObjectWriterMapTest, MapAcceptsNullValue) { + // Null should not be a valid map value. + // See http://go/proto3-json-spec#heading=h.r2ddatp7y4vi + // This test is added for backward compatibility. + MapIn mm; + (*mm.mutable_map_input())["a"] = "b"; + (*mm.mutable_map_input())["x"] = ""; + ow_->StartObject("") + ->StartObject("map_input") + ->RenderString("a", "b") + ->RenderNull("x") + ->EndObject() + ->EndObject(); + CheckOutput(mm); +} + +TEST_P(ProtoStreamObjectWriterMapTest, MapShouldIgnoreNullValueEntry) { + options_.ignore_null_value_map_entry = true; + ResetTypeInfo(MapIn::descriptor()); + MapIn mm; + (*mm.mutable_map_input())["a"] = "b"; + ow_->StartObject("") + ->StartObject("map_input") + ->RenderString("a", "b") + ->RenderNull("x") + ->EndObject() + ->EndObject(); + CheckOutput(mm); +} + TEST_P(ProtoStreamObjectWriterMapTest, RepeatedMapKeyTest) { EXPECT_CALL( listener_, @@ -1899,10 +1950,10 @@ TEST_P(ProtoStreamObjectWriterAnyTest, EmptyAnyFromEmptyObject) { TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithoutTypeUrlFails1) { AnyOut any; - EXPECT_CALL(listener_, - InvalidValue(_, StringPiece("Any"), - StringPiece("Missing @type for any field in " - "google.protobuf.testing.AnyOut"))); + EXPECT_CALL(listener_, InvalidValue(_, StringPiece("Any"), + StringPiece( + "Missing @type for any field in " + "google.protobuf.testing.AnyOut"))); ow_->StartObject("") ->StartObject("any") @@ -1916,10 +1967,10 @@ TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithoutTypeUrlFails1) { TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithoutTypeUrlFails2) { AnyOut any; - EXPECT_CALL(listener_, - InvalidValue(_, StringPiece("Any"), - StringPiece("Missing @type for any field in " - "google.protobuf.testing.AnyOut"))); + EXPECT_CALL(listener_, InvalidValue(_, StringPiece("Any"), + StringPiece( + "Missing @type for any field in " + "google.protobuf.testing.AnyOut"))); ow_->StartObject("") ->StartObject("any") @@ -1933,10 +1984,10 @@ TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithoutTypeUrlFails2) { TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithoutTypeUrlFails3) { AnyOut any; - EXPECT_CALL(listener_, - InvalidValue(_, StringPiece("Any"), - StringPiece("Missing @type for any field in " - "google.protobuf.testing.AnyOut"))); + EXPECT_CALL(listener_, InvalidValue(_, StringPiece("Any"), + StringPiece( + "Missing @type for any field in " + "google.protobuf.testing.AnyOut"))); ow_->StartObject("") ->StartObject("any") @@ -1949,12 +2000,13 @@ TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithoutTypeUrlFails3) { TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithInvalidTypeUrlFails) { AnyOut any; - EXPECT_CALL(listener_, - InvalidValue( - _, StringPiece("Any"), - StringPiece("Invalid type URL, type URLs must be of the form " - "'type.googleapis.com/<typename>', got: " - "type.other.com/some.Type"))); + EXPECT_CALL( + listener_, + InvalidValue( + _, StringPiece("Any"), + StringPiece("Invalid type URL, type URLs must be of the form " + "'type.googleapis.com/<typename>', got: " + "type.other.com/some.Type"))); ow_->StartObject("") ->StartObject("any") @@ -1968,10 +2020,10 @@ TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithInvalidTypeUrlFails) { TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithUnknownTypeFails) { AnyOut any; - EXPECT_CALL( - listener_, - InvalidValue(_, StringPiece("Any"), - StringPiece("Invalid type URL, unknown type: some.Type"))); + EXPECT_CALL(listener_, + InvalidValue(_, StringPiece("Any"), + StringPiece( + "Invalid type URL, unknown type: some.Type"))); ow_->StartObject("") ->StartObject("any") ->RenderString("@type", "type.googleapis.com/some.Type") @@ -1986,7 +2038,8 @@ TEST_P(ProtoStreamObjectWriterAnyTest, AnyIncorrectInputTypeFails) { EXPECT_CALL( listener_, - InvalidValue(_, StringPiece("type.googleapis.com/google.protobuf.Any"), + InvalidValue(_, + StringPiece("type.googleapis.com/google.protobuf.Any"), StringPiece("1"))); ow_->StartObject("")->RenderInt32("any", 1)->EndObject(); CheckOutput(any); @@ -2194,8 +2247,9 @@ TEST_P(ProtoStreamObjectWriterAnyTest, AnyWellKnownTypesNoValueFieldForArray) { // } // } TEST_P(ProtoStreamObjectWriterAnyTest, AnyWellKnownTypesExpectObjectForStruct) { - EXPECT_CALL(listener_, InvalidValue(_, StringPiece("Any"), - StringPiece("Expect a JSON object."))); + EXPECT_CALL(listener_, + InvalidValue(_, StringPiece("Any"), + StringPiece("Expect a JSON object."))); AnyOut any; google::protobuf::Any* any_type = any.mutable_any(); any_type->set_type_url("type.googleapis.com/google.protobuf.Struct"); @@ -2218,8 +2272,9 @@ TEST_P(ProtoStreamObjectWriterAnyTest, AnyWellKnownTypesExpectObjectForStruct) { // } // } TEST_P(ProtoStreamObjectWriterAnyTest, AnyWellKnownTypesExpectObjectForAny) { - EXPECT_CALL(listener_, InvalidValue(_, StringPiece("Any"), - StringPiece("Expect a JSON object."))); + EXPECT_CALL(listener_, + InvalidValue(_, StringPiece("Any"), + StringPiece("Expect a JSON object."))); AnyOut any; google::protobuf::Any* any_type = any.mutable_any(); any_type->set_type_url("type.googleapis.com/google.protobuf.Any"); @@ -2480,7 +2535,7 @@ TEST_P(ProtoStreamObjectWriterFieldMaskTest, MoreCloseThanOpenParentheses) { InvalidValue( _, StringPiece("type.googleapis.com/google.protobuf.FieldMask"), StringPiece("Field 'single_mask', Invalid FieldMask 'a(b,c))'. " - "Cannot find matching '(' for all ')'."))); + "Cannot find matching '(' for all ')'."))); ow_->StartObject(""); ow_->RenderString("id", "1"); @@ -2525,9 +2580,10 @@ TEST_P(ProtoStreamObjectWriterFieldMaskTest, listener_, InvalidValue( _, StringPiece("type.googleapis.com/google.protobuf.FieldMask"), - StringPiece("Field 'single_mask', Invalid FieldMask " - "'path.to.map[\"key1\"]a,path.to.map[\"key2\"]'. " - "Map keys should be at the end of a path segment."))); + StringPiece( + "Field 'single_mask', Invalid FieldMask " + "'path.to.map[\"key1\"]a,path.to.map[\"key2\"]'. " + "Map keys should be at the end of a path segment."))); ow_->StartObject(""); ow_->RenderString("single_mask", @@ -2538,11 +2594,11 @@ TEST_P(ProtoStreamObjectWriterFieldMaskTest, TEST_P(ProtoStreamObjectWriterFieldMaskTest, MapKeyMustEnd) { EXPECT_CALL( listener_, - InvalidValue(_, - StringPiece("type.googleapis.com/google.protobuf.FieldMask"), - StringPiece("Field 'single_mask', Invalid FieldMask " - "'path.to.map[\"key1\"'. Map keys should be " - "represented as [\"some_key\"]."))); + InvalidValue( + _, StringPiece("type.googleapis.com/google.protobuf.FieldMask"), + StringPiece("Field 'single_mask', Invalid FieldMask " + "'path.to.map[\"key1\"'. Map keys should be " + "represented as [\"some_key\"]."))); ow_->StartObject(""); ow_->RenderString("single_mask", "path.to.map[\"key1\""); @@ -2552,11 +2608,11 @@ TEST_P(ProtoStreamObjectWriterFieldMaskTest, MapKeyMustEnd) { TEST_P(ProtoStreamObjectWriterFieldMaskTest, MapKeyMustBeEscapedCorrectly) { EXPECT_CALL( listener_, - InvalidValue(_, - StringPiece("type.googleapis.com/google.protobuf.FieldMask"), - StringPiece("Field 'single_mask', Invalid FieldMask " - "'path.to.map[\"ke\"y1\"]'. Map keys should be " - "represented as [\"some_key\"]."))); + InvalidValue( + _, StringPiece("type.googleapis.com/google.protobuf.FieldMask"), + StringPiece("Field 'single_mask', Invalid FieldMask " + "'path.to.map[\"ke\"y1\"]'. Map keys should be " + "represented as [\"some_key\"]."))); ow_->StartObject(""); ow_->RenderString("single_mask", "path.to.map[\"ke\"y1\"]"); @@ -2647,10 +2703,10 @@ TEST_P(ProtoStreamObjectWriterOneOfsTest, TEST_P(ProtoStreamObjectWriterOneOfsTest, MultipleOneofsFailForMessageTypesPrimitiveFirstTest) { // Test for setting primitive oneof field first and then message field. - EXPECT_CALL(listener_, - InvalidValue(_, StringPiece("oneof"), - StringPiece("oneof field 'data' is already set. " - "Cannot set 'messageData'"))); + EXPECT_CALL(listener_, InvalidValue(_, StringPiece("oneof"), + StringPiece( + "oneof field 'data' is already set. " + "Cannot set 'messageData'"))); // JSON: { "strData": "blah", "messageData": { "dataValue": 123 } } ow_->StartObject(""); @@ -2664,10 +2720,10 @@ TEST_P(ProtoStreamObjectWriterOneOfsTest, TEST_P(ProtoStreamObjectWriterOneOfsTest, MultipleOneofsFailForMessageTypesMessageFirstTest) { // Test for setting message oneof field first and then primitive field. - EXPECT_CALL(listener_, - InvalidValue(_, StringPiece("oneof"), - StringPiece("oneof field 'data' is already set. " - "Cannot set 'strData'"))); + EXPECT_CALL(listener_, InvalidValue(_, StringPiece("oneof"), + StringPiece( + "oneof field 'data' is already set. " + "Cannot set 'strData'"))); // JSON: { "messageData": { "dataValue": 123 }, "strData": "blah" } ow_->StartObject(""); @@ -2680,10 +2736,10 @@ TEST_P(ProtoStreamObjectWriterOneOfsTest, TEST_P(ProtoStreamObjectWriterOneOfsTest, MultipleOneofsFailForStructTypesPrimitiveFirstTest) { - EXPECT_CALL(listener_, - InvalidValue(_, StringPiece("oneof"), - StringPiece("oneof field 'data' is already set. " - "Cannot set 'structData'"))); + EXPECT_CALL(listener_, InvalidValue(_, StringPiece("oneof"), + StringPiece( + "oneof field 'data' is already set. " + "Cannot set 'structData'"))); // JSON: { "strData": "blah", "structData": { "a": "b" } } ow_->StartObject(""); @@ -2696,10 +2752,10 @@ TEST_P(ProtoStreamObjectWriterOneOfsTest, TEST_P(ProtoStreamObjectWriterOneOfsTest, MultipleOneofsFailForStructTypesStructFirstTest) { - EXPECT_CALL(listener_, - InvalidValue(_, StringPiece("oneof"), - StringPiece("oneof field 'data' is already set. " - "Cannot set 'strData'"))); + EXPECT_CALL(listener_, InvalidValue(_, StringPiece("oneof"), + StringPiece( + "oneof field 'data' is already set. " + "Cannot set 'strData'"))); // JSON: { "structData": { "a": "b" }, "strData": "blah" } ow_->StartObject(""); @@ -2712,10 +2768,10 @@ TEST_P(ProtoStreamObjectWriterOneOfsTest, TEST_P(ProtoStreamObjectWriterOneOfsTest, MultipleOneofsFailForStructValueTypesTest) { - EXPECT_CALL(listener_, - InvalidValue(_, StringPiece("oneof"), - StringPiece("oneof field 'data' is already set. " - "Cannot set 'valueData'"))); + EXPECT_CALL(listener_, InvalidValue(_, StringPiece("oneof"), + StringPiece( + "oneof field 'data' is already set. " + "Cannot set 'valueData'"))); // JSON: { "messageData": { "dataValue": 123 }, "valueData": { "a": "b" } } ow_->StartObject(""); @@ -2730,10 +2786,10 @@ TEST_P(ProtoStreamObjectWriterOneOfsTest, TEST_P(ProtoStreamObjectWriterOneOfsTest, MultipleOneofsFailForWellKnownTypesPrimitiveFirstTest) { - EXPECT_CALL(listener_, - InvalidValue(_, StringPiece("oneof"), - StringPiece("oneof field 'data' is already set. " - "Cannot set 'tsData'"))); + EXPECT_CALL(listener_, InvalidValue(_, StringPiece("oneof"), + StringPiece( + "oneof field 'data' is already set. " + "Cannot set 'tsData'"))); // JSON: { "intData": 123, "tsData": "1970-01-02T01:00:00.000Z" } ow_->StartObject(""); @@ -2744,10 +2800,10 @@ TEST_P(ProtoStreamObjectWriterOneOfsTest, TEST_P(ProtoStreamObjectWriterOneOfsTest, MultipleOneofsFailForWellKnownTypesWktFirstTest) { - EXPECT_CALL(listener_, - InvalidValue(_, StringPiece("oneof"), - StringPiece("oneof field 'data' is already set. " - "Cannot set 'intData'"))); + EXPECT_CALL(listener_, InvalidValue(_, StringPiece("oneof"), + StringPiece( + "oneof field 'data' is already set. " + "Cannot set 'intData'"))); // JSON: { "tsData": "1970-01-02T01:00:00.000Z", "intData": 123 } ow_->StartObject(""); @@ -2758,10 +2814,10 @@ TEST_P(ProtoStreamObjectWriterOneOfsTest, TEST_P(ProtoStreamObjectWriterOneOfsTest, MultipleOneofsFailForWellKnownTypesAndMessageTest) { - EXPECT_CALL(listener_, - InvalidValue(_, StringPiece("oneof"), - StringPiece("oneof field 'data' is already set. " - "Cannot set 'messageData'"))); + EXPECT_CALL(listener_, InvalidValue(_, StringPiece("oneof"), + StringPiece( + "oneof field 'data' is already set. " + "Cannot set 'messageData'"))); // JSON: { "tsData": "1970-01-02T01:00:00.000Z", // "messageData": { "dataValue": 123 } } @@ -2775,10 +2831,10 @@ TEST_P(ProtoStreamObjectWriterOneOfsTest, TEST_P(ProtoStreamObjectWriterOneOfsTest, MultipleOneofsFailForOneofWithinAnyTest) { - EXPECT_CALL(listener_, - InvalidValue(_, StringPiece("oneof"), - StringPiece("oneof field 'data' is already set. " - "Cannot set 'intData'"))); + EXPECT_CALL(listener_, InvalidValue(_, StringPiece("oneof"), + StringPiece( + "oneof field 'data' is already set. " + "Cannot set 'intData'"))); // JSON: // { "anyData": diff --git a/src/google/protobuf/util/internal/structured_objectwriter.h b/src/google/protobuf/util/internal/structured_objectwriter.h index 8e63222b..bccea718 100644 --- a/src/google/protobuf/util/internal/structured_objectwriter.h +++ b/src/google/protobuf/util/internal/structured_objectwriter.h @@ -37,6 +37,8 @@ #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 { @@ -53,7 +55,7 @@ namespace converter { // StructuredObjectWriter and its use. // // Derived classes could be thread-unsafe. -class LIBPROTOBUF_EXPORT StructuredObjectWriter : public ObjectWriter { +class PROTOBUF_EXPORT StructuredObjectWriter : public ObjectWriter { public: virtual ~StructuredObjectWriter() {} @@ -63,7 +65,7 @@ class LIBPROTOBUF_EXPORT StructuredObjectWriter : public ObjectWriter { // 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 LIBPROTOBUF_EXPORT BaseElement { + class PROTOBUF_EXPORT BaseElement { public: // Takes ownership of the parent Element. explicit BaseElement(BaseElement* parent) @@ -110,6 +112,8 @@ class LIBPROTOBUF_EXPORT StructuredObjectWriter : public ObjectWriter { } // 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/src/google/protobuf/util/internal/testdata/anys.proto b/src/google/protobuf/util/internal/testdata/anys.proto index a9ebca3d..77c1043b 100644 --- a/src/google/protobuf/util/internal/testdata/anys.proto +++ b/src/google/protobuf/util/internal/testdata/anys.proto @@ -57,6 +57,7 @@ message AnyTestCases { AnyWrapper any_with_message_containing_struct = 13; AnyWrapper any_with_message_containing_repeated_message = 14; AnyWrapper recursive_any_with_type_field_at_end = 15; + AnyWrapper repeated_any = 16; google.protobuf.Any top_level_any = 50; google.protobuf.Any top_level_any_with_type_field_at_end = 51; @@ -87,6 +88,7 @@ message Data { map<string, string> map_data = 7; google.protobuf.Struct struct_data = 8; repeated Data repeated_data = 9; + repeated google.protobuf.Any repeated_any = 10; } service AnyTestService { diff --git a/src/google/protobuf/util/internal/testdata/books.proto b/src/google/protobuf/util/internal/testdata/books.proto index 5e08a291..812474bb 100644 --- a/src/google/protobuf/util/internal/testdata/books.proto +++ b/src/google/protobuf/util/internal/testdata/books.proto @@ -196,7 +196,7 @@ message Cyclic { } // Test that two messages can have different fields mapped to the same JSON -// name. See: https://github.com/google/protobuf/issues/1415 +// name. See: https://github.com/protocolbuffers/protobuf/issues/1415 message TestJsonName1 { optional int32 one_value = 1 [json_name = "value"]; } diff --git a/src/google/protobuf/util/internal/type_info.cc b/src/google/protobuf/util/internal/type_info.cc index e32e71d0..60cc3fc0 100644 --- a/src/google/protobuf/util/internal/type_info.cc +++ b/src/google/protobuf/util/internal/type_info.cc @@ -58,7 +58,7 @@ class TypeInfoForTypeResolver : public TypeInfo { DeleteCachedTypes(&cached_enums_); } - virtual util::StatusOr<const google::protobuf::Type*> ResolveTypeUrl( + util::StatusOr<const google::protobuf::Type*> ResolveTypeUrl( StringPiece type_url) const override { std::map<StringPiece, StatusOrType>::iterator it = cached_types_.find(type_url); @@ -68,7 +68,7 @@ class TypeInfoForTypeResolver : public TypeInfo { // Stores the string value so it can be referenced using StringPiece in the // cached_types_ map. const string& string_type_url = - *string_storage_.insert(type_url.ToString()).first; + *string_storage_.insert(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()); @@ -78,13 +78,13 @@ class TypeInfoForTypeResolver : public TypeInfo { return result; } - virtual const google::protobuf::Type* GetTypeByTypeUrl( + const google::protobuf::Type* GetTypeByTypeUrl( StringPiece type_url) const override { StatusOrType result = ResolveTypeUrl(type_url); return result.ok() ? result.ValueOrDie() : NULL; } - virtual const google::protobuf::Enum* GetEnumByTypeUrl( + const google::protobuf::Enum* GetEnumByTypeUrl( StringPiece type_url) const override { std::map<StringPiece, StatusOrEnum>::iterator it = cached_enums_.find(type_url); @@ -94,7 +94,7 @@ class TypeInfoForTypeResolver : public TypeInfo { // Stores the string value so it can be referenced using StringPiece in the // cached_enums_ map. const string& string_type_url = - *string_storage_.insert(type_url.ToString()).first; + *string_storage_.insert(string(type_url)).first; std::unique_ptr<google::protobuf::Enum> enum_type( new google::protobuf::Enum()); util::Status status = @@ -105,8 +105,7 @@ class TypeInfoForTypeResolver : public TypeInfo { return result.ok() ? result.ValueOrDie() : NULL; } - - virtual const google::protobuf::Field* FindField( + 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 @@ -115,8 +114,8 @@ class TypeInfoForTypeResolver : public TypeInfo { (it == indexed_types_.end()) ? PopulateNameLookupTable(type, &indexed_types_[type]) : it->second; - StringPiece name = - FindWithDefault(camel_case_name_table, camel_case_name, StringPiece()); + 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; @@ -131,7 +130,8 @@ class TypeInfoForTypeResolver : public TypeInfo { template <typename T> static void DeleteCachedTypes(std::map<StringPiece, T>* cached_types) { - for (typename std::map<StringPiece, T>::iterator it = cached_types->begin(); + for (typename std::map<StringPiece, T>::iterator it = + cached_types->begin(); it != cached_types->end(); ++it) { if (it->second.ok()) { delete it->second.ValueOrDie(); @@ -146,8 +146,8 @@ class TypeInfoForTypeResolver : public TypeInfo { 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); + 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 diff --git a/src/google/protobuf/util/internal/type_info.h b/src/google/protobuf/util/internal/type_info.h index d8133176..b933b77a 100644 --- a/src/google/protobuf/util/internal/type_info.h +++ b/src/google/protobuf/util/internal/type_info.h @@ -38,13 +38,15 @@ #include <google/protobuf/stubs/status.h> #include <google/protobuf/stubs/statusor.h> +#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 LIBPROTOBUF_EXPORT TypeInfo { +class PROTOBUF_EXPORT TypeInfo { public: TypeInfo() {} virtual ~TypeInfo() {} @@ -87,6 +89,8 @@ class LIBPROTOBUF_EXPORT 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/src/google/protobuf/util/internal/type_info_test_helper.cc b/src/google/protobuf/util/internal/type_info_test_helper.cc index 281a7f58..dfd86fa3 100644 --- a/src/google/protobuf/util/internal/type_info_test_helper.cc +++ b/src/google/protobuf/util/internal/type_info_test_helper.cc @@ -33,6 +33,7 @@ #include <memory> #include <vector> + #include <google/protobuf/stubs/logging.h> #include <google/protobuf/stubs/common.h> #include <google/protobuf/descriptor.h> diff --git a/src/google/protobuf/util/internal/type_info_test_helper.h b/src/google/protobuf/util/internal/type_info_test_helper.h index 5a077e04..3cafbceb 100644 --- a/src/google/protobuf/util/internal/type_info_test_helper.h +++ b/src/google/protobuf/util/internal/type_info_test_helper.h @@ -72,13 +72,13 @@ class TypeInfoTestHelper { TypeInfo* GetTypeInfo(); ProtoStreamObjectSource* NewProtoSource(io::CodedInputStream* coded_input, - const string& type_url); + const std::string& type_url); ProtoStreamObjectWriter* NewProtoWriter( - const string& type_url, strings::ByteSink* output, + const std::string& type_url, strings::ByteSink* output, ErrorListener* listener, const ProtoStreamObjectWriter::Options& options); - DefaultValueObjectWriter* NewDefaultValueWriter(const string& type_url, + DefaultValueObjectWriter* NewDefaultValueWriter(const std::string& type_url, ObjectWriter* writer); private: @@ -90,6 +90,6 @@ class TypeInfoTestHelper { } // namespace converter } // namespace util } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_TYPE_INFO_TEST_HELPER_H__ diff --git a/src/google/protobuf/util/internal/utility.cc b/src/google/protobuf/util/internal/utility.cc index b8d917ce..7c7e3f1c 100644 --- a/src/google/protobuf/util/internal/utility.cc +++ b/src/google/protobuf/util/internal/utility.cc @@ -43,13 +43,15 @@ #include <google/protobuf/stubs/map_util.h> #include <google/protobuf/stubs/mathlimits.h> +#include <google/protobuf/port_def.inc> + namespace google { namespace protobuf { namespace util { namespace converter { bool GetBoolOptionOrDefault( - const google::protobuf::RepeatedPtrField<google::protobuf::Option>& options, + const RepeatedPtrField<google::protobuf::Option>& options, const string& option_name, bool default_value) { const google::protobuf::Option* opt = FindOptionOrNull(options, option_name); if (opt == nullptr) { @@ -59,7 +61,7 @@ bool GetBoolOptionOrDefault( } int64 GetInt64OptionOrDefault( - const google::protobuf::RepeatedPtrField<google::protobuf::Option>& options, + const RepeatedPtrField<google::protobuf::Option>& options, const string& option_name, int64 default_value) { const google::protobuf::Option* opt = FindOptionOrNull(options, option_name); if (opt == nullptr) { @@ -69,7 +71,7 @@ int64 GetInt64OptionOrDefault( } double GetDoubleOptionOrDefault( - const google::protobuf::RepeatedPtrField<google::protobuf::Option>& options, + const RepeatedPtrField<google::protobuf::Option>& options, const string& option_name, double default_value) { const google::protobuf::Option* opt = FindOptionOrNull(options, option_name); if (opt == nullptr) { @@ -79,7 +81,7 @@ double GetDoubleOptionOrDefault( } string GetStringOptionOrDefault( - const google::protobuf::RepeatedPtrField<google::protobuf::Option>& options, + const RepeatedPtrField<google::protobuf::Option>& options, const string& option_name, const string& default_value) { const google::protobuf::Option* opt = FindOptionOrNull(options, option_name); if (opt == nullptr) { @@ -136,7 +138,7 @@ const string GetFullTypeWithUrl(StringPiece simple_type) { } const google::protobuf::Option* FindOptionOrNull( - const google::protobuf::RepeatedPtrField<google::protobuf::Option>& options, + const RepeatedPtrField<google::protobuf::Option>& options, const string& option_name) { for (int i = 0; i < options.size(); ++i) { const google::protobuf::Option& opt = options.Get(i); @@ -325,7 +327,7 @@ string ToSnakeCase(StringPiece input) { } std::set<string>* well_known_types_ = NULL; -GOOGLE_PROTOBUF_DECLARE_ONCE(well_known_types_init_); +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", @@ -345,7 +347,8 @@ void InitWellKnownTypes() { } bool IsWellKnownType(const string& type_name) { - InitWellKnownTypes(); + PROTOBUF_NAMESPACE_ID::internal::call_once(well_known_types_init_, + InitWellKnownTypes); return ContainsKey(*well_known_types_, type_name); } diff --git a/src/google/protobuf/util/internal/utility.h b/src/google/protobuf/util/internal/utility.h index d8e06a97..6fe82959 100644 --- a/src/google/protobuf/util/internal/utility.h +++ b/src/google/protobuf/util/internal/utility.h @@ -44,6 +44,7 @@ #include <google/protobuf/stubs/status.h> #include <google/protobuf/stubs/statusor.h> +#include <google/protobuf/port_def.inc> namespace google { namespace protobuf { @@ -56,8 +57,9 @@ class Type; class Enum; class EnumValue; } // namespace protobuf +} // namespace google - +namespace google { namespace protobuf { namespace util { namespace converter { @@ -68,46 +70,47 @@ static const int64 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. -LIBPROTOBUF_EXPORT bool GetBoolOptionOrDefault( - const google::protobuf::RepeatedPtrField<google::protobuf::Option>& options, - const string& option_name, bool default_value); +PROTOBUF_EXPORT bool GetBoolOptionOrDefault( + const RepeatedPtrField<google::protobuf::Option>& options, + const std::string& option_name, bool default_value); // Returns int64 option value. If the option isn't found, returns the // default_value. -LIBPROTOBUF_EXPORT int64 GetInt64OptionOrDefault( - const google::protobuf::RepeatedPtrField<google::protobuf::Option>& options, - const string& option_name, int64 default_value); +PROTOBUF_EXPORT int64 GetInt64OptionOrDefault( + const RepeatedPtrField<google::protobuf::Option>& options, + const std::string& option_name, int64 default_value); // Returns double option value. If the option isn't found, returns the // default_value. -LIBPROTOBUF_EXPORT double GetDoubleOptionOrDefault( - const google::protobuf::RepeatedPtrField<google::protobuf::Option>& options, - const string& option_name, double default_value); +PROTOBUF_EXPORT double GetDoubleOptionOrDefault( + const RepeatedPtrField<google::protobuf::Option>& options, + const std::string& option_name, double default_value); // Returns string option value. If the option isn't found, returns the // default_value. -LIBPROTOBUF_EXPORT string GetStringOptionOrDefault( - const google::protobuf::RepeatedPtrField<google::protobuf::Option>& options, - const string& option_name, const string& default_value); +PROTOBUF_EXPORT std::string GetStringOptionOrDefault( + const RepeatedPtrField<google::protobuf::Option>& options, + const std::string& option_name, const std::string& 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/sharable location so others // can use. -LIBPROTOBUF_EXPORT bool GetBoolFromAny(const google::protobuf::Any& any); +PROTOBUF_EXPORT bool GetBoolFromAny(const google::protobuf::Any& any); // Returns int64 value contained in Any type. -LIBPROTOBUF_EXPORT int64 GetInt64FromAny(const google::protobuf::Any& any); +PROTOBUF_EXPORT int64 GetInt64FromAny(const google::protobuf::Any& any); // Returns double value contained in Any type. -LIBPROTOBUF_EXPORT double GetDoubleFromAny(const google::protobuf::Any& any); +PROTOBUF_EXPORT double GetDoubleFromAny(const google::protobuf::Any& any); // Returns string value contained in Any type. -LIBPROTOBUF_EXPORT string GetStringFromAny(const google::protobuf::Any& any); +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'. -LIBPROTOBUF_EXPORT const StringPiece GetTypeWithoutUrl(StringPiece type_url); +PROTOBUF_EXPORT const StringPiece GetTypeWithoutUrl( + StringPiece type_url); // Returns the simple_type with the base type url (kTypeServiceBaseUrl) // prefixed. @@ -115,13 +118,13 @@ LIBPROTOBUF_EXPORT const StringPiece GetTypeWithoutUrl(StringPiece type_url); // E.g: // GetFullTypeWithUrl("google.protobuf.Timestamp") returns the string // "type.googleapis.com/google.protobuf.Timestamp". -LIBPROTOBUF_EXPORT const string GetFullTypeWithUrl(StringPiece simple_type); +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 google::protobuf::RepeatedPtrField<google::protobuf::Option>& options, - const string& option_name); + const RepeatedPtrField<google::protobuf::Option>& options, + const std::string& option_name); // Finds and returns the field identified by field_name in the passed tech Type // object. Returns nullptr if none found. @@ -155,51 +158,51 @@ const google::protobuf::EnumValue* FindEnumValueByNameWithoutUnderscoreOrNull( const google::protobuf::Enum* enum_type, StringPiece enum_name); // Converts input to camel-case and returns it. -LIBPROTOBUF_EXPORT string ToCamelCase(const StringPiece input); +PROTOBUF_EXPORT std::string ToCamelCase(const StringPiece input); // Converts enum name string to camel-case and returns it. -string EnumValueNameToLowerCamelCase(const StringPiece input); +std::string EnumValueNameToLowerCamelCase(const StringPiece input); // Converts input to snake_case and returns it. -LIBPROTOBUF_EXPORT string ToSnakeCase(StringPiece input); +PROTOBUF_EXPORT std::string ToSnakeCase(StringPiece input); // Returns true if type_name represents a well-known type. -LIBPROTOBUF_EXPORT bool IsWellKnownType(const string& type_name); +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. -LIBPROTOBUF_EXPORT bool IsValidBoolString(const string& bool_string); +PROTOBUF_EXPORT bool IsValidBoolString(const std::string& bool_string); // Returns true if "field" is a protobuf map field based on its type. -LIBPROTOBUF_EXPORT bool IsMap(const google::protobuf::Field& field, - const google::protobuf::Type& 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. -LIBPROTOBUF_EXPORT string DoubleAsString(double value); -LIBPROTOBUF_EXPORT string FloatAsString(float value); +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> -string ValueAsString(T value) { +std::string ValueAsString(T value) { return SimpleItoa(value); } template <> -inline string ValueAsString(float value) { +inline std::string ValueAsString(float value) { return FloatAsString(value); } template <> -inline string ValueAsString(double value) { +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). -LIBPROTOBUF_EXPORT bool SafeStrToFloat(StringPiece str, float* value); +PROTOBUF_EXPORT bool SafeStrToFloat(StringPiece str, float* value); // Returns whether a StringPiece begins with the provided prefix. bool StringStartsWith(StringPiece text, StringPiece prefix); @@ -209,6 +212,8 @@ bool StringEndsWith(StringPiece text, StringPiece suffix); } // namespace converter } // namespace util } // namespace protobuf - } // namespace google + +#include <google/protobuf/port_undef.inc> + #endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_UTILITY_H__ |