| OLD | NEW |
| (Empty) | |
| 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_PROTOSTREAM_OBJECTWRITER_H__ |
| 32 #define GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTOSTREAM_OBJECTWRITER_H__ |
| 33 |
| 34 #include <deque> |
| 35 #include <google/protobuf/stubs/hash.h> |
| 36 #include <string> |
| 37 |
| 38 #include <google/protobuf/stubs/common.h> |
| 39 #include <google/protobuf/io/coded_stream.h> |
| 40 #include <google/protobuf/io/zero_copy_stream_impl.h> |
| 41 #include <google/protobuf/descriptor.h> |
| 42 #include <google/protobuf/util/internal/type_info.h> |
| 43 #include <google/protobuf/util/internal/datapiece.h> |
| 44 #include <google/protobuf/util/internal/error_listener.h> |
| 45 #include <google/protobuf/util/internal/proto_writer.h> |
| 46 #include <google/protobuf/util/internal/structured_objectwriter.h> |
| 47 #include <google/protobuf/util/type_resolver.h> |
| 48 #include <google/protobuf/stubs/bytestream.h> |
| 49 |
| 50 namespace google { |
| 51 namespace protobuf { |
| 52 namespace io { |
| 53 class CodedOutputStream; |
| 54 } // namespace io |
| 55 } // namespace protobuf |
| 56 |
| 57 |
| 58 namespace protobuf { |
| 59 class Type; |
| 60 class Field; |
| 61 } // namespace protobuf |
| 62 |
| 63 |
| 64 namespace protobuf { |
| 65 namespace util { |
| 66 namespace converter { |
| 67 |
| 68 class ObjectLocationTracker; |
| 69 |
| 70 // An ObjectWriter that can write protobuf bytes directly from writer events. |
| 71 // This class supports all special types like Struct and Map. It uses |
| 72 // the ProtoWriter class to write raw proto bytes. |
| 73 // |
| 74 // It also supports streaming. |
| 75 class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public ProtoWriter { |
| 76 public: |
| 77 // Constructor. Does not take ownership of any parameter passed in. |
| 78 ProtoStreamObjectWriter(TypeResolver* type_resolver, |
| 79 const google::protobuf::Type& type, |
| 80 strings::ByteSink* output, ErrorListener* listener); |
| 81 virtual ~ProtoStreamObjectWriter(); |
| 82 |
| 83 // ObjectWriter methods. |
| 84 virtual ProtoStreamObjectWriter* StartObject(StringPiece name); |
| 85 virtual ProtoStreamObjectWriter* EndObject(); |
| 86 virtual ProtoStreamObjectWriter* StartList(StringPiece name); |
| 87 virtual ProtoStreamObjectWriter* EndList(); |
| 88 |
| 89 // Renders a DataPiece 'value' into a field whose wire type is determined |
| 90 // from the given field 'name'. |
| 91 virtual ProtoStreamObjectWriter* RenderDataPiece(StringPiece name, |
| 92 const DataPiece& value); |
| 93 |
| 94 protected: |
| 95 // Function that renders a well known type with modified behavior. |
| 96 typedef util::Status (*TypeRenderer)(ProtoStreamObjectWriter*, |
| 97 const DataPiece&); |
| 98 |
| 99 // Handles writing Anys out using nested object writers and the like. |
| 100 class LIBPROTOBUF_EXPORT AnyWriter { |
| 101 public: |
| 102 explicit AnyWriter(ProtoStreamObjectWriter* parent); |
| 103 ~AnyWriter(); |
| 104 |
| 105 // Passes a StartObject call through to the Any writer. |
| 106 void StartObject(StringPiece name); |
| 107 |
| 108 // Passes an EndObject call through to the Any. Returns true if the any |
| 109 // handled the EndObject call, false if the Any is now all done and is no |
| 110 // longer needed. |
| 111 bool EndObject(); |
| 112 |
| 113 // Passes a StartList call through to the Any writer. |
| 114 void StartList(StringPiece name); |
| 115 |
| 116 // Passes an EndList call through to the Any writer. |
| 117 void EndList(); |
| 118 |
| 119 // Renders a data piece on the any. |
| 120 void RenderDataPiece(StringPiece name, const DataPiece& value); |
| 121 |
| 122 private: |
| 123 // Handles starting up the any once we have a type. |
| 124 void StartAny(const DataPiece& value); |
| 125 |
| 126 // Writes the Any out to the parent writer in its serialized form. |
| 127 void WriteAny(); |
| 128 |
| 129 // The parent of this writer, needed for various bits such as type info and |
| 130 // the listeners. |
| 131 ProtoStreamObjectWriter* parent_; |
| 132 |
| 133 // The nested object writer, used to write events. |
| 134 google::protobuf::scoped_ptr<ProtoStreamObjectWriter> ow_; |
| 135 |
| 136 // The type_url_ that this Any represents. |
| 137 string type_url_; |
| 138 |
| 139 // Whether this any is invalid. This allows us to only report an invalid |
| 140 // Any message a single time rather than every time we get a nested field. |
| 141 bool invalid_; |
| 142 |
| 143 // The output data and wrapping ByteSink. |
| 144 string data_; |
| 145 strings::StringByteSink output_; |
| 146 |
| 147 // The depth within the Any, so we can track when we're done. |
| 148 int depth_; |
| 149 |
| 150 // True if the message type contained in Any has a special "value" message |
| 151 // injected. This is true for well-known message types like Any or Struct. |
| 152 bool has_injected_value_message_; |
| 153 }; |
| 154 |
| 155 // Represents an item in a stack of items used to keep state between |
| 156 // ObjectWrier events. |
| 157 class LIBPROTOBUF_EXPORT Item : public BaseElement { |
| 158 public: |
| 159 // Indicates the type of item. |
| 160 enum ItemType { |
| 161 MESSAGE, // Simple message |
| 162 MAP, // Proto3 map type |
| 163 ANY, // Proto3 Any type |
| 164 }; |
| 165 |
| 166 // Constructor for the root item. |
| 167 Item(ProtoStreamObjectWriter* enclosing, ItemType item_type, |
| 168 bool is_placeholder, bool is_list); |
| 169 |
| 170 // Constructor for a field of a message. |
| 171 Item(Item* parent, ItemType item_type, bool is_placeholder, bool is_list); |
| 172 |
| 173 virtual ~Item() {} |
| 174 |
| 175 // These functions return true if the element type is corresponding to the |
| 176 // type in function name. |
| 177 bool IsMap() { return item_type_ == MAP; } |
| 178 bool IsAny() { return item_type_ == ANY; } |
| 179 |
| 180 AnyWriter* any() const { return any_.get(); } |
| 181 |
| 182 virtual Item* parent() const { |
| 183 return static_cast<Item*>(BaseElement::parent()); |
| 184 } |
| 185 |
| 186 // Inserts map key into hash set if and only if the key did NOT already |
| 187 // exist in hash set. |
| 188 // The hash set (map_keys_) is ONLY used to keep track of map keys. |
| 189 // Return true if insert successfully; returns false if the map key was |
| 190 // already present. |
| 191 bool InsertMapKeyIfNotPresent(StringPiece map_key); |
| 192 |
| 193 bool is_placeholder() const { return is_placeholder_; } |
| 194 bool is_list() const { return is_list_; } |
| 195 |
| 196 private: |
| 197 // Used for access to variables of the enclosing instance of |
| 198 // ProtoStreamObjectWriter. |
| 199 ProtoStreamObjectWriter* ow_; |
| 200 |
| 201 // A writer for Any objects, handles all Any-related nonsense. |
| 202 google::protobuf::scoped_ptr<AnyWriter> any_; |
| 203 |
| 204 // The type of this element, see enum for permissible types. |
| 205 ItemType item_type_; |
| 206 |
| 207 // Set of map keys already seen for the type_. Used to validate incoming |
| 208 // messages so no map key appears more than once. |
| 209 hash_set<string> map_keys_; |
| 210 |
| 211 // Conveys whether this Item is a placeholder or not. Placeholder items are |
| 212 // pushed to stack to account for special types. |
| 213 bool is_placeholder_; |
| 214 |
| 215 // Conveys whether this Item is a list or not. This is used to send |
| 216 // StartList or EndList calls to underlying ObjectWriter. |
| 217 bool is_list_; |
| 218 |
| 219 GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(Item); |
| 220 }; |
| 221 |
| 222 ProtoStreamObjectWriter(const TypeInfo* typeinfo, |
| 223 const google::protobuf::Type& type, |
| 224 strings::ByteSink* output, ErrorListener* listener); |
| 225 |
| 226 // Returns true if the field is a map. |
| 227 bool IsMap(const google::protobuf::Field& field); |
| 228 |
| 229 // Returns true if the field is an any. |
| 230 bool IsAny(const google::protobuf::Field& field); |
| 231 |
| 232 // Returns true if the field is google.protobuf.Struct. |
| 233 bool IsStruct(const google::protobuf::Field& field); |
| 234 |
| 235 // Returns true if the field is google.protobuf.Value. |
| 236 bool IsStructValue(const google::protobuf::Field& field); |
| 237 |
| 238 // Returns true if the field is google.protobuf.ListValue. |
| 239 bool IsStructListValue(const google::protobuf::Field& field); |
| 240 |
| 241 // Renders google.protobuf.Value in struct.proto. It picks the right oneof |
| 242 // type based on value's type. |
| 243 static util::Status RenderStructValue(ProtoStreamObjectWriter* ow, |
| 244 const DataPiece& value); |
| 245 |
| 246 // Renders google.protobuf.Timestamp value. |
| 247 static util::Status RenderTimestamp(ProtoStreamObjectWriter* ow, |
| 248 const DataPiece& value); |
| 249 |
| 250 // Renders google.protobuf.FieldMask value. |
| 251 static util::Status RenderFieldMask(ProtoStreamObjectWriter* ow, |
| 252 const DataPiece& value); |
| 253 |
| 254 // Renders google.protobuf.Duration value. |
| 255 static util::Status RenderDuration(ProtoStreamObjectWriter* ow, |
| 256 const DataPiece& value); |
| 257 |
| 258 // Renders wrapper message types for primitive types in |
| 259 // google/protobuf/wrappers.proto. |
| 260 static util::Status RenderWrapperType(ProtoStreamObjectWriter* ow, |
| 261 const DataPiece& value); |
| 262 |
| 263 static void InitRendererMap(); |
| 264 static void DeleteRendererMap(); |
| 265 static TypeRenderer* FindTypeRenderer(const string& type_url); |
| 266 |
| 267 // Returns true if the map key for type_ is not duplicated key. |
| 268 // If map key is duplicated key, this function returns false. |
| 269 // Note that caller should make sure that the current proto element (current_) |
| 270 // is of element type MAP or STRUCT_MAP. |
| 271 // It also calls the appropriate error callback and unnormalzied_name is used |
| 272 // for error string. |
| 273 bool ValidMapKey(StringPiece unnormalized_name); |
| 274 |
| 275 // Pushes an item on to the stack. Also calls either StartObject or StartList |
| 276 // on the underlying ObjectWriter depending on whether is_list is false or |
| 277 // not. |
| 278 // is_placeholder conveys whether the item is a placeholder item or not. |
| 279 // Placeholder items are pushed when adding auxillary types' StartObject or |
| 280 // StartList calls. |
| 281 void Push(StringPiece name, Item::ItemType item_type, bool is_placeholder, |
| 282 bool is_list); |
| 283 |
| 284 // Pops items from the stack. All placeholder items are popped until a |
| 285 // non-placeholder item is found. |
| 286 void Pop(); |
| 287 |
| 288 // Pops one element from the stack. Calls EndObject() or EndList() on the |
| 289 // underlying ObjectWriter depending on the value of is_list_. |
| 290 void PopOneElement(); |
| 291 |
| 292 private: |
| 293 // Helper functions to create the map and find functions responsible for |
| 294 // rendering well known types, keyed by type URL. |
| 295 static hash_map<string, TypeRenderer>* renderers_; |
| 296 |
| 297 // Variables for describing the structure of the input tree: |
| 298 // master_type_: descriptor for the whole protobuf message. |
| 299 const google::protobuf::Type& master_type_; |
| 300 |
| 301 // The current element, variable for internal state processing. |
| 302 google::protobuf::scoped_ptr<Item> current_; |
| 303 |
| 304 GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(ProtoStreamObjectWriter); |
| 305 }; |
| 306 |
| 307 } // namespace converter |
| 308 } // namespace util |
| 309 } // namespace protobuf |
| 310 |
| 311 } // namespace google |
| 312 #endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTOSTREAM_OBJECTWRITER_H__ |
| OLD | NEW |