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 // Author: kenton@google.com (Kenton Varda) 32 // Based on original Protocol Buffers design by 33 // Sanjay Ghemawat, Jeff Dean, and others. 34 // 35 // Defines an implementation of Message which can emulate types which are not 36 // known at compile-time. 37 38 #ifndef GOOGLE_PROTOBUF_DYNAMIC_MESSAGE_H__ 39 #define GOOGLE_PROTOBUF_DYNAMIC_MESSAGE_H__ 40 41 #include <algorithm> 42 #include <memory> 43 #include <vector> 44 45 #include <google/protobuf/stubs/common.h> 46 #include <google/protobuf/message.h> 47 #include <google/protobuf/stubs/mutex.h> 48 #include <google/protobuf/reflection.h> 49 #include <google/protobuf/repeated_field.h> 50 51 #ifdef SWIG 52 #error "You cannot SWIG proto headers" 53 #endif 54 55 #include <google/protobuf/port_def.inc> 56 57 namespace google { 58 namespace protobuf { 59 60 // Defined in other files. 61 class Descriptor; // descriptor.h 62 class DescriptorPool; // descriptor.h 63 64 // Constructs implementations of Message which can emulate types which are not 65 // known at compile-time. 66 // 67 // Sometimes you want to be able to manipulate protocol types that you don't 68 // know about at compile time. It would be nice to be able to construct 69 // a Message object which implements the message type given by any arbitrary 70 // Descriptor. DynamicMessage provides this. 71 // 72 // As it turns out, a DynamicMessage needs to construct extra 73 // information about its type in order to operate. Most of this information 74 // can be shared between all DynamicMessages of the same type. But, caching 75 // this information in some sort of global map would be a bad idea, since 76 // the cached information for a particular descriptor could outlive the 77 // descriptor itself. To avoid this problem, DynamicMessageFactory 78 // encapsulates this "cache". All DynamicMessages of the same type created 79 // from the same factory will share the same support data. Any Descriptors 80 // used with a particular factory must outlive the factory. 81 class PROTOBUF_EXPORT DynamicMessageFactory : public MessageFactory { 82 public: 83 // Construct a DynamicMessageFactory that will search for extensions in 84 // the DescriptorPool in which the extendee is defined. 85 DynamicMessageFactory(); 86 87 // Construct a DynamicMessageFactory that will search for extensions in 88 // the given DescriptorPool. 89 // 90 // DEPRECATED: Use CodedInputStream::SetExtensionRegistry() to tell the 91 // parser to look for extensions in an alternate pool. However, note that 92 // this is almost never what you want to do. Almost all users should use 93 // the zero-arg constructor. 94 DynamicMessageFactory(const DescriptorPool* pool); 95 96 ~DynamicMessageFactory(); 97 98 // Call this to tell the DynamicMessageFactory that if it is given a 99 // Descriptor d for which: 100 // d->file()->pool() == DescriptorPool::generated_pool(), 101 // then it should delegate to MessageFactory::generated_factory() instead 102 // of constructing a dynamic implementation of the message. In theory there 103 // is no down side to doing this, so it may become the default in the future. SetDelegateToGeneratedFactory(bool enable)104 void SetDelegateToGeneratedFactory(bool enable) { 105 delegate_to_generated_factory_ = enable; 106 } 107 108 // implements MessageFactory --------------------------------------- 109 110 // Given a Descriptor, constructs the default (prototype) Message of that 111 // type. You can then call that message's New() method to construct a 112 // mutable message of that type. 113 // 114 // Calling this method twice with the same Descriptor returns the same 115 // object. The returned object remains property of the factory and will 116 // be destroyed when the factory is destroyed. Also, any objects created 117 // by calling the prototype's New() method share some data with the 118 // prototype, so these must be destroyed before the DynamicMessageFactory 119 // is destroyed. 120 // 121 // The given descriptor must outlive the returned message, and hence must 122 // outlive the DynamicMessageFactory. 123 // 124 // The method is thread-safe. 125 const Message* GetPrototype(const Descriptor* type) override; 126 127 private: 128 const DescriptorPool* pool_; 129 bool delegate_to_generated_factory_; 130 131 // This struct just contains a hash_map. We can't #include <hash_map> from 132 // this header due to hacks needed for hash_map portability in the open source 133 // release. Namely, stubs/hash.h, which defines hash_map portably, is not a 134 // public header (for good reason), but dynamic_message.h is, and public 135 // headers may only #include other public headers. 136 struct PrototypeMap; 137 std::unique_ptr<PrototypeMap> prototypes_; 138 mutable internal::WrappedMutex prototypes_mutex_; 139 140 friend class DynamicMessage; 141 const Message* GetPrototypeNoLock(const Descriptor* type); 142 143 // Construct default oneof instance for reflection usage if oneof 144 // is defined. 145 static void ConstructDefaultOneofInstance(const Descriptor* type, 146 const uint32 offsets[], 147 void* default_oneof_instance); 148 // Delete default oneof instance. Called by ~DynamicMessageFactory. 149 static void DeleteDefaultOneofInstance(const Descriptor* type, 150 const uint32 offsets[], 151 const void* default_oneof_instance); 152 153 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMessageFactory); 154 }; 155 156 // Helper for computing a sorted list of map entries via reflection. 157 class PROTOBUF_EXPORT DynamicMapSorter { 158 public: Sort(const Message & message,int map_size,const Reflection * reflection,const FieldDescriptor * field)159 static std::vector<const Message*> Sort(const Message& message, int map_size, 160 const Reflection* reflection, 161 const FieldDescriptor* field) { 162 std::vector<const Message*> result; 163 result.reserve(map_size); 164 RepeatedFieldRef<Message> map_field = 165 reflection->GetRepeatedFieldRef<Message>(message, field); 166 for (auto it = map_field.begin(); it != map_field.end(); ++it) { 167 result.push_back(&*it); 168 } 169 MapEntryMessageComparator comparator(field->message_type()); 170 std::stable_sort(result.begin(), result.end(), comparator); 171 // Complain if the keys aren't in ascending order. 172 #ifndef NDEBUG 173 for (size_t j = 1; j < static_cast<size_t>(map_size); j++) { 174 if (!comparator(result[j - 1], result[j])) { 175 GOOGLE_LOG(ERROR) << (comparator(result[j], result[j - 1]) 176 ? "internal error in map key sorting" 177 : "map keys are not unique"); 178 } 179 } 180 #endif 181 return result; 182 } 183 184 private: 185 class PROTOBUF_EXPORT MapEntryMessageComparator { 186 public: MapEntryMessageComparator(const Descriptor * descriptor)187 explicit MapEntryMessageComparator(const Descriptor* descriptor) 188 : field_(descriptor->field(0)) {} 189 operator()190 bool operator()(const Message* a, const Message* b) { 191 const Reflection* reflection = a->GetReflection(); 192 switch (field_->cpp_type()) { 193 case FieldDescriptor::CPPTYPE_BOOL: { 194 bool first = reflection->GetBool(*a, field_); 195 bool second = reflection->GetBool(*b, field_); 196 return first < second; 197 } 198 case FieldDescriptor::CPPTYPE_INT32: { 199 int32 first = reflection->GetInt32(*a, field_); 200 int32 second = reflection->GetInt32(*b, field_); 201 return first < second; 202 } 203 case FieldDescriptor::CPPTYPE_INT64: { 204 int64 first = reflection->GetInt64(*a, field_); 205 int64 second = reflection->GetInt64(*b, field_); 206 return first < second; 207 } 208 case FieldDescriptor::CPPTYPE_UINT32: { 209 uint32 first = reflection->GetUInt32(*a, field_); 210 uint32 second = reflection->GetUInt32(*b, field_); 211 return first < second; 212 } 213 case FieldDescriptor::CPPTYPE_UINT64: { 214 uint64 first = reflection->GetUInt64(*a, field_); 215 uint64 second = reflection->GetUInt64(*b, field_); 216 return first < second; 217 } 218 case FieldDescriptor::CPPTYPE_STRING: { 219 std::string first = reflection->GetString(*a, field_); 220 std::string second = reflection->GetString(*b, field_); 221 return first < second; 222 } 223 default: 224 GOOGLE_LOG(DFATAL) << "Invalid key for map field."; 225 return true; 226 } 227 } 228 229 private: 230 const FieldDescriptor* field_; 231 }; 232 }; 233 234 } // namespace protobuf 235 } // namespace google 236 237 #include <google/protobuf/port_undef.inc> 238 239 #endif // GOOGLE_PROTOBUF_DYNAMIC_MESSAGE_H__ 240