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