1 // Protocol Buffers - Google's data interchange format 2 // Copyright 2008 Google Inc. All rights reserved. 3 // https://developers.google.com/protocol-buffers/ 4 // 5 // Redistribution and use in source and binary forms, with or without 6 // modification, are permitted provided that the following conditions are 7 // met: 8 // 9 // * Redistributions of source code must retain the above copyright 10 // notice, this list of conditions and the following disclaimer. 11 // * Redistributions in binary form must reproduce the above 12 // copyright notice, this list of conditions and the following disclaimer 13 // in the documentation and/or other materials provided with the 14 // distribution. 15 // * Neither the name of Google Inc. nor the names of its 16 // contributors may be used to endorse or promote products derived from 17 // this software without specific prior written permission. 18 // 19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 31 #ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_DEFAULT_VALUE_OBJECTWRITER_H__ 32 #define GOOGLE_PROTOBUF_UTIL_CONVERTER_DEFAULT_VALUE_OBJECTWRITER_H__ 33 34 #include <functional> 35 #include <memory> 36 #include <stack> 37 #include <vector> 38 39 #include <google/protobuf/stubs/common.h> 40 #include <google/protobuf/util/internal/type_info.h> 41 #include <google/protobuf/util/internal/datapiece.h> 42 #include <google/protobuf/util/internal/object_writer.h> 43 #include <google/protobuf/util/internal/utility.h> 44 #include <google/protobuf/util/type_resolver.h> 45 #include <google/protobuf/stubs/strutil.h> 46 47 // Must be included last. 48 #include <google/protobuf/port_def.inc> 49 50 namespace google { 51 namespace protobuf { 52 namespace util { 53 namespace converter { 54 55 // An ObjectWriter that renders non-repeated primitive fields of proto messages 56 // with their default values. DefaultValueObjectWriter holds objects, lists and 57 // fields it receives in a tree structure and writes them out to another 58 // ObjectWriter when EndObject() is called on the root object. It also writes 59 // out all non-repeated primitive fields that haven't been explicitly rendered 60 // with their default values (0 for numbers, "" for strings, etc). 61 class PROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter { 62 public: 63 // A Callback function to check whether a field needs to be scrubbed. 64 // 65 // Returns true if the field should not be present in the output. Returns 66 // false otherwise. 67 // 68 // The 'path' parameter is a vector of path to the field from root. For 69 // example: if a nested field "a.b.c" (b is the parent message field of c and 70 // a is the parent message field of b), then the vector should contain { "a", 71 // "b", "c" }. 72 // 73 // The Field* should point to the google::protobuf::Field of "c". 74 typedef std::function<bool( 75 const std::vector<std::string>& /*path of the field*/, 76 const google::protobuf::Field* /*field*/)> 77 FieldScrubCallBack; 78 79 DefaultValueObjectWriter(TypeResolver* type_resolver, 80 const google::protobuf::Type& type, 81 ObjectWriter* ow); 82 83 virtual ~DefaultValueObjectWriter(); 84 85 // ObjectWriter methods. 86 DefaultValueObjectWriter* StartObject(StringPiece name) override; 87 88 DefaultValueObjectWriter* EndObject() override; 89 90 DefaultValueObjectWriter* StartList(StringPiece name) override; 91 92 DefaultValueObjectWriter* EndList() override; 93 94 DefaultValueObjectWriter* RenderBool(StringPiece name, 95 bool value) override; 96 97 DefaultValueObjectWriter* RenderInt32(StringPiece name, 98 int32 value) override; 99 100 DefaultValueObjectWriter* RenderUint32(StringPiece name, 101 uint32 value) override; 102 103 DefaultValueObjectWriter* RenderInt64(StringPiece name, 104 int64 value) override; 105 106 DefaultValueObjectWriter* RenderUint64(StringPiece name, 107 uint64 value) override; 108 109 DefaultValueObjectWriter* RenderDouble(StringPiece name, 110 double value) override; 111 112 DefaultValueObjectWriter* RenderFloat(StringPiece name, 113 float value) override; 114 115 DefaultValueObjectWriter* RenderString(StringPiece name, 116 StringPiece value) override; 117 DefaultValueObjectWriter* RenderBytes(StringPiece name, 118 StringPiece value) override; 119 120 DefaultValueObjectWriter* RenderNull(StringPiece name) override; 121 122 // Register the callback for scrubbing of fields. 123 void RegisterFieldScrubCallBack(FieldScrubCallBack field_scrub_callback); 124 125 // If set to true, empty lists are suppressed from output when default values 126 // are written. set_suppress_empty_list(bool value)127 void set_suppress_empty_list(bool value) { suppress_empty_list_ = value; } 128 129 // If set to true, original proto field names are used set_preserve_proto_field_names(bool value)130 void set_preserve_proto_field_names(bool value) { 131 preserve_proto_field_names_ = value; 132 } 133 134 // If set to true, enums are rendered as ints from output when default values 135 // are written. set_print_enums_as_ints(bool value)136 void set_print_enums_as_ints(bool value) { use_ints_for_enums_ = value; } 137 138 protected: 139 enum NodeKind { 140 PRIMITIVE = 0, 141 OBJECT = 1, 142 LIST = 2, 143 MAP = 3, 144 }; 145 146 // "Node" represents a node in the tree that holds the input of 147 // DefaultValueObjectWriter. 148 class PROTOBUF_EXPORT Node { 149 public: 150 Node(const std::string& name, const google::protobuf::Type* type, 151 NodeKind kind, const DataPiece& data, bool is_placeholder, 152 const std::vector<std::string>& path, bool suppress_empty_list, 153 bool preserve_proto_field_names, bool use_ints_for_enums, 154 FieldScrubCallBack field_scrub_callback); ~Node()155 virtual ~Node() { 156 for (int i = 0; i < children_.size(); ++i) { 157 delete children_[i]; 158 } 159 } 160 161 // Adds a child to this node. Takes ownership of this child. AddChild(Node * child)162 void AddChild(Node* child) { children_.push_back(child); } 163 164 // Finds the child given its name. 165 Node* FindChild(StringPiece name); 166 167 // Populates children of this Node based on its type. If there are already 168 // children created, they will be merged to the result. Caller should pass 169 // in TypeInfo for looking up types of the children. 170 virtual void PopulateChildren(const TypeInfo* typeinfo); 171 172 // If this node is a leaf (has data), writes the current node to the 173 // ObjectWriter; if not, then recursively writes the children to the 174 // ObjectWriter. 175 virtual void WriteTo(ObjectWriter* ow); 176 177 // Accessors name()178 const std::string& name() const { return name_; } 179 path()180 const std::vector<std::string>& path() const { return path_; } 181 type()182 const google::protobuf::Type* type() const { return type_; } 183 set_type(const google::protobuf::Type * type)184 void set_type(const google::protobuf::Type* type) { type_ = type; } 185 kind()186 NodeKind kind() const { return kind_; } 187 number_of_children()188 int number_of_children() const { return children_.size(); } 189 set_data(const DataPiece & data)190 void set_data(const DataPiece& data) { data_ = data; } 191 is_any()192 bool is_any() const { return is_any_; } 193 set_is_any(bool is_any)194 void set_is_any(bool is_any) { is_any_ = is_any; } 195 set_is_placeholder(bool is_placeholder)196 void set_is_placeholder(bool is_placeholder) { 197 is_placeholder_ = is_placeholder; 198 } 199 200 protected: 201 // Returns the Value Type of a map given the Type of the map entry and a 202 // TypeInfo instance. 203 const google::protobuf::Type* GetMapValueType( 204 const google::protobuf::Type& found_type, const TypeInfo* typeinfo); 205 206 // Calls WriteTo() on every child in children_. 207 void WriteChildren(ObjectWriter* ow); 208 209 // The name of this node. 210 std::string name_; 211 // google::protobuf::Type of this node. Owned by TypeInfo. 212 const google::protobuf::Type* type_; 213 // The kind of this node. 214 NodeKind kind_; 215 // Whether this is a node for "Any". 216 bool is_any_; 217 // The data of this node when it is a leaf node. 218 DataPiece data_; 219 // Children of this node. 220 std::vector<Node*> children_; 221 // Whether this node is a placeholder for an object or list automatically 222 // generated when creating the parent node. Should be set to false after 223 // the parent node's StartObject()/StartList() method is called with this 224 // node's name. 225 bool is_placeholder_; 226 227 // Path of the field of this node 228 std::vector<std::string> path_; 229 230 // Whether to suppress empty list output. 231 bool suppress_empty_list_; 232 233 // Whether to preserve original proto field names 234 bool preserve_proto_field_names_; 235 236 // Whether to always print enums as ints 237 bool use_ints_for_enums_; 238 239 // Function for determining whether a field needs to be scrubbed or not. 240 FieldScrubCallBack field_scrub_callback_; 241 242 private: 243 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Node); 244 }; 245 246 // Creates a new Node and returns it. Caller owns memory of returned object. 247 virtual Node* CreateNewNode(const std::string& name, 248 const google::protobuf::Type* type, NodeKind kind, 249 const DataPiece& data, bool is_placeholder, 250 const std::vector<std::string>& path, 251 bool suppress_empty_list, 252 bool preserve_proto_field_names, 253 bool use_ints_for_enums, 254 FieldScrubCallBack field_scrub_callback); 255 256 // Creates a DataPiece containing the default value of the type of the field. CreateDefaultDataPieceForField(const google::protobuf::Field & field,const TypeInfo * typeinfo)257 static DataPiece CreateDefaultDataPieceForField( 258 const google::protobuf::Field& field, const TypeInfo* typeinfo) { 259 return CreateDefaultDataPieceForField(field, typeinfo, false); 260 } 261 262 // Same as the above but with a flag to use ints instead of enum names. 263 static DataPiece CreateDefaultDataPieceForField( 264 const google::protobuf::Field& field, const TypeInfo* typeinfo, 265 bool use_ints_for_enums); 266 267 protected: 268 // Returns a pointer to current Node in tree. current()269 Node* current() { return current_; } 270 271 private: 272 // Populates children of "node" if it is an "any" Node and its real type has 273 // been given. 274 void MaybePopulateChildrenOfAny(Node* node); 275 276 // Writes the root_ node to ow_ and resets the root_ and current_ pointer to 277 // nullptr. 278 void WriteRoot(); 279 280 // Adds or replaces the data_ of a primitive child node. 281 void RenderDataPiece(StringPiece name, const DataPiece& data); 282 283 // Returns the default enum value as a DataPiece, or the first enum value if 284 // there is no default. For proto3, where we cannot specify an explicit 285 // default, a zero value will always be returned. 286 static DataPiece FindEnumDefault(const google::protobuf::Field& field, 287 const TypeInfo* typeinfo, 288 bool use_ints_for_enums); 289 290 // Type information for all the types used in the descriptor. Used to find 291 // google::protobuf::Type of nested messages/enums. 292 const TypeInfo* typeinfo_; 293 // Whether the TypeInfo object is owned by this class. 294 bool own_typeinfo_; 295 // google::protobuf::Type of the root message type. 296 const google::protobuf::Type& type_; 297 // Holds copies of strings passed to RenderString. 298 std::vector<std::unique_ptr<std::string>> string_values_; 299 300 // The current Node. Owned by its parents. 301 Node* current_; 302 // The root Node. 303 std::unique_ptr<Node> root_; 304 // The stack to hold the path of Nodes from current_ to root_; 305 std::stack<Node*> stack_; 306 307 // Whether to suppress output of empty lists. 308 bool suppress_empty_list_; 309 310 // Whether to preserve original proto field names 311 bool preserve_proto_field_names_; 312 313 // Whether to always print enums as ints 314 bool use_ints_for_enums_; 315 316 // Function for determining whether a field needs to be scrubbed or not. 317 FieldScrubCallBack field_scrub_callback_; 318 319 ObjectWriter* ow_; 320 321 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DefaultValueObjectWriter); 322 }; 323 324 } // namespace converter 325 } // namespace util 326 } // namespace protobuf 327 } // namespace google 328 329 #include <google/protobuf/port_undef.inc> 330 331 #endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_DEFAULT_VALUE_OBJECTWRITER_H__ 332