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 <memory> 35 #include <stack> 36 #include <vector> 37 38 #include <google/protobuf/stubs/callback.h> 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/stringpiece.h> 46 47 #include <google/protobuf/port_def.inc> 48 49 namespace google { 50 namespace protobuf { 51 namespace util { 52 namespace converter { 53 54 // An ObjectWriter that renders non-repeated primitive fields of proto messages 55 // with their default values. DefaultValueObjectWriter holds objects, lists and 56 // fields it receives in a tree structure and writes them out to another 57 // ObjectWriter when EndObject() is called on the root object. It also writes 58 // out all non-repeated primitive fields that haven't been explicitly rendered 59 // with their default values (0 for numbers, "" for strings, etc). 60 class PROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter { 61 public: 62 // A Callback function to check whether a field needs to be scrubbed. 63 // 64 // Returns true if the field should not be present in the output. Returns 65 // false otherwise. 66 // 67 // The 'path' parameter is a vector of path to the field from root. For 68 // example: if a nested field "a.b.c" (b is the parent message field of c and 69 // a is the parent message field of b), then the vector should contain { "a", 70 // "b", "c" }. 71 // 72 // The Field* should point to the google::protobuf::Field of "c". 73 typedef ResultCallback2<bool /*return*/, 74 const std::vector<std::string>& /*path of the field*/, 75 const google::protobuf::Field* /*field*/> 76 FieldScrubCallBack; 77 78 // A unique pointer to a DefaultValueObjectWriter::FieldScrubCallBack. 79 typedef std::unique_ptr<FieldScrubCallBack> FieldScrubCallBackPtr; 80 81 DefaultValueObjectWriter(TypeResolver* type_resolver, 82 const google::protobuf::Type& type, 83 ObjectWriter* ow); 84 85 virtual ~DefaultValueObjectWriter(); 86 87 // ObjectWriter methods. 88 DefaultValueObjectWriter* StartObject(StringPiece name) override; 89 90 DefaultValueObjectWriter* EndObject() override; 91 92 DefaultValueObjectWriter* StartList(StringPiece name) override; 93 94 DefaultValueObjectWriter* EndList() override; 95 96 DefaultValueObjectWriter* RenderBool(StringPiece name, 97 bool value) override; 98 99 DefaultValueObjectWriter* RenderInt32(StringPiece name, 100 int32 value) override; 101 102 DefaultValueObjectWriter* RenderUint32(StringPiece name, 103 uint32 value) override; 104 105 DefaultValueObjectWriter* RenderInt64(StringPiece name, 106 int64 value) override; 107 108 DefaultValueObjectWriter* RenderUint64(StringPiece name, 109 uint64 value) override; 110 111 DefaultValueObjectWriter* RenderDouble(StringPiece name, 112 double value) override; 113 114 DefaultValueObjectWriter* RenderFloat(StringPiece name, 115 float value) override; 116 117 DefaultValueObjectWriter* RenderString(StringPiece name, 118 StringPiece value) override; 119 DefaultValueObjectWriter* RenderBytes(StringPiece name, 120 StringPiece value) override; 121 122 virtual DefaultValueObjectWriter* RenderNull(StringPiece name); 123 124 // Register the callback for scrubbing of fields. Owership of 125 // field_scrub_callback pointer is also transferred to this class 126 void RegisterFieldScrubCallBack(FieldScrubCallBackPtr field_scrub_callback); 127 128 // If set to true, empty lists are suppressed from output when default values 129 // are written. set_suppress_empty_list(bool value)130 void set_suppress_empty_list(bool value) { suppress_empty_list_ = value; } 131 132 // If set to true, original proto field names are used set_preserve_proto_field_names(bool value)133 void set_preserve_proto_field_names(bool value) { 134 preserve_proto_field_names_ = value; 135 } 136 137 // If set to true, enums are rendered as ints from output when default values 138 // are written. set_print_enums_as_ints(bool value)139 void set_print_enums_as_ints(bool value) { use_ints_for_enums_ = value; } 140 141 protected: 142 enum NodeKind { 143 PRIMITIVE = 0, 144 OBJECT = 1, 145 LIST = 2, 146 MAP = 3, 147 }; 148 149 // "Node" represents a node in the tree that holds the input of 150 // DefaultValueObjectWriter. 151 class PROTOBUF_EXPORT Node { 152 public: 153 Node(const std::string& name, const google::protobuf::Type* type, 154 NodeKind kind, const DataPiece& data, bool is_placeholder, 155 const std::vector<std::string>& path, bool suppress_empty_list, 156 bool preserve_proto_field_names, bool use_ints_for_enums, 157 FieldScrubCallBack* field_scrub_callback); ~Node()158 virtual ~Node() { 159 for (int i = 0; i < children_.size(); ++i) { 160 delete children_[i]; 161 } 162 } 163 164 // Adds a child to this node. Takes ownership of this child. AddChild(Node * child)165 void AddChild(Node* child) { children_.push_back(child); } 166 167 // Finds the child given its name. 168 Node* FindChild(StringPiece name); 169 170 // Populates children of this Node based on its type. If there are already 171 // children created, they will be merged to the result. Caller should pass 172 // in TypeInfo for looking up types of the children. 173 virtual void PopulateChildren(const TypeInfo* typeinfo); 174 175 // If this node is a leaf (has data), writes the current node to the 176 // ObjectWriter; if not, then recursively writes the children to the 177 // ObjectWriter. 178 virtual void WriteTo(ObjectWriter* ow); 179 180 // Accessors name()181 const std::string& name() const { return name_; } 182 path()183 const std::vector<std::string>& path() const { return path_; } 184 type()185 const google::protobuf::Type* type() const { return type_; } 186 set_type(const google::protobuf::Type * type)187 void set_type(const google::protobuf::Type* type) { type_ = type; } 188 kind()189 NodeKind kind() const { return kind_; } 190 number_of_children()191 int number_of_children() const { return children_.size(); } 192 set_data(const DataPiece & data)193 void set_data(const DataPiece& data) { data_ = data; } 194 is_any()195 bool is_any() const { return is_any_; } 196 set_is_any(bool is_any)197 void set_is_any(bool is_any) { is_any_ = is_any; } 198 set_is_placeholder(bool is_placeholder)199 void set_is_placeholder(bool is_placeholder) { 200 is_placeholder_ = is_placeholder; 201 } 202 203 protected: 204 // Returns the Value Type of a map given the Type of the map entry and a 205 // TypeInfo instance. 206 const google::protobuf::Type* GetMapValueType( 207 const google::protobuf::Type& entry_type, const TypeInfo* typeinfo); 208 209 // Calls WriteTo() on every child in children_. 210 void WriteChildren(ObjectWriter* ow); 211 212 // The name of this node. 213 std::string name_; 214 // google::protobuf::Type of this node. Owned by TypeInfo. 215 const google::protobuf::Type* type_; 216 // The kind of this node. 217 NodeKind kind_; 218 // Whether this is a node for "Any". 219 bool is_any_; 220 // The data of this node when it is a leaf node. 221 DataPiece data_; 222 // Children of this node. 223 std::vector<Node*> children_; 224 // Whether this node is a placeholder for an object or list automatically 225 // generated when creating the parent node. Should be set to false after 226 // the parent node's StartObject()/StartList() method is called with this 227 // node's name. 228 bool is_placeholder_; 229 230 // Path of the field of this node 231 std::vector<std::string> path_; 232 233 // Whether to suppress empty list output. 234 bool suppress_empty_list_; 235 236 // Whether to preserve original proto field names 237 bool preserve_proto_field_names_; 238 239 // Whether to always print enums as ints 240 bool use_ints_for_enums_; 241 242 // Pointer to function for determining whether a field needs to be scrubbed 243 // or not. This callback is owned by the creator of this node. 244 FieldScrubCallBack* field_scrub_callback_; 245 246 private: 247 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Node); 248 }; 249 250 // Creates a new Node and returns it. Caller owns memory of returned object. 251 virtual Node* CreateNewNode(const std::string& name, 252 const google::protobuf::Type* type, NodeKind kind, 253 const DataPiece& data, bool is_placeholder, 254 const std::vector<std::string>& path, 255 bool suppress_empty_list, 256 bool preserve_proto_field_names, 257 bool use_ints_for_enums, 258 FieldScrubCallBack* field_scrub_callback); 259 260 // Creates a DataPiece containing the default value of the type of the field. CreateDefaultDataPieceForField(const google::protobuf::Field & field,const TypeInfo * typeinfo)261 static DataPiece CreateDefaultDataPieceForField( 262 const google::protobuf::Field& field, const TypeInfo* typeinfo) { 263 return CreateDefaultDataPieceForField(field, typeinfo, false); 264 } 265 266 // Same as the above but with a flag to use ints instead of enum names. 267 static DataPiece CreateDefaultDataPieceForField( 268 const google::protobuf::Field& field, const TypeInfo* typeinfo, 269 bool use_ints_for_enums); 270 271 protected: 272 // Returns a pointer to current Node in tree. current()273 Node* current() { return current_; } 274 275 private: 276 // Populates children of "node" if it is an "any" Node and its real type has 277 // been given. 278 void MaybePopulateChildrenOfAny(Node* node); 279 280 // Writes the root_ node to ow_ and resets the root_ and current_ pointer to 281 // nullptr. 282 void WriteRoot(); 283 284 // Adds or replaces the data_ of a primitive child node. 285 void RenderDataPiece(StringPiece name, const DataPiece& data); 286 287 // Returns the default enum value as a DataPiece, or the first enum value if 288 // there is no default. For proto3, where we cannot specify an explicit 289 // default, a zero value will always be returned. 290 static DataPiece FindEnumDefault(const google::protobuf::Field& field, 291 const TypeInfo* typeinfo, 292 bool use_ints_for_enums); 293 294 // Type information for all the types used in the descriptor. Used to find 295 // google::protobuf::Type of nested messages/enums. 296 const TypeInfo* typeinfo_; 297 // Whether the TypeInfo object is owned by this class. 298 bool own_typeinfo_; 299 // google::protobuf::Type of the root message type. 300 const google::protobuf::Type& type_; 301 // Holds copies of strings passed to RenderString. 302 std::vector<std::unique_ptr<std::string>> string_values_; 303 304 // The current Node. Owned by its parents. 305 Node* current_; 306 // The root Node. 307 std::unique_ptr<Node> root_; 308 // The stack to hold the path of Nodes from current_ to root_; 309 std::stack<Node*> stack_; 310 311 // Whether to suppress output of empty lists. 312 bool suppress_empty_list_; 313 314 // Whether to preserve original proto field names 315 bool preserve_proto_field_names_; 316 317 // Whether to always print enums as ints 318 bool use_ints_for_enums_; 319 320 // Unique Pointer to function for determining whether a field needs to be 321 // scrubbed or not. 322 FieldScrubCallBackPtr field_scrub_callback_; 323 324 ObjectWriter* ow_; 325 326 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DefaultValueObjectWriter); 327 }; 328 329 } // namespace converter 330 } // namespace util 331 } // namespace protobuf 332 } // namespace google 333 334 #include <google/protobuf/port_undef.inc> 335 336 #endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_DEFAULT_VALUE_OBJECTWRITER_H__ 337