1 // Protocol Buffers - Google's data interchange format 2 // Copyright 2008 Google Inc. All rights reserved. 3 // 4 // Use of this source code is governed by a BSD-style 5 // license that can be found in the LICENSE file or at 6 // https://developers.google.com/open-source/licenses/bsd 7 8 // Author: kenton@google.com (Kenton Varda) 9 // Based on original Protocol Buffers design by 10 // Sanjay Ghemawat, Jeff Dean, and others. 11 // 12 // Defines an implementation of Message which can emulate types which are not 13 // known at compile-time. 14 15 #ifndef GOOGLE_PROTOBUF_DYNAMIC_MESSAGE_H__ 16 #define GOOGLE_PROTOBUF_DYNAMIC_MESSAGE_H__ 17 18 #include <algorithm> 19 #include <cstddef> 20 #include <cstdint> 21 #include <string> 22 #include <vector> 23 24 #include "absl/container/flat_hash_map.h" 25 #include "absl/log/absl_log.h" 26 #include "absl/synchronization/mutex.h" 27 #include "google/protobuf/descriptor.h" 28 #include "google/protobuf/message.h" 29 #include "google/protobuf/reflection.h" 30 #include "google/protobuf/repeated_field.h" 31 32 #ifdef SWIG 33 #error "You cannot SWIG proto headers" 34 #endif 35 36 // Must be included last. 37 #include "google/protobuf/port_def.inc" 38 39 namespace google { 40 namespace protobuf { 41 42 // Defined in other files. 43 class Descriptor; // descriptor.h 44 class DescriptorPool; // descriptor.h 45 46 // Constructs implementations of Message which can emulate types which are not 47 // known at compile-time. 48 // 49 // Sometimes you want to be able to manipulate protocol types that you don't 50 // know about at compile time. It would be nice to be able to construct 51 // a Message object which implements the message type given by any arbitrary 52 // Descriptor. DynamicMessage provides this. 53 // 54 // As it turns out, a DynamicMessage needs to construct extra 55 // information about its type in order to operate. Most of this information 56 // can be shared between all DynamicMessages of the same type. But, caching 57 // this information in some sort of global map would be a bad idea, since 58 // the cached information for a particular descriptor could outlive the 59 // descriptor itself. To avoid this problem, DynamicMessageFactory 60 // encapsulates this "cache". All DynamicMessages of the same type created 61 // from the same factory will share the same support data. Any Descriptors 62 // used with a particular factory must outlive the factory. 63 // 64 // The thread safety for this class is subtle, see comments around GetPrototype 65 // for details 66 class PROTOBUF_EXPORT DynamicMessageFactory : public MessageFactory { 67 public: 68 // Construct a DynamicMessageFactory that will search for extensions in 69 // the DescriptorPool in which the extendee is defined. 70 DynamicMessageFactory(); 71 72 // Construct a DynamicMessageFactory that will search for extensions in 73 // the given DescriptorPool. 74 // 75 // DEPRECATED: Use CodedInputStream::SetExtensionRegistry() to tell the 76 // parser to look for extensions in an alternate pool. However, note that 77 // this is almost never what you want to do. Almost all users should use 78 // the zero-arg constructor. 79 #ifndef PROTOBUF_FUTURE_BREAKING_CHANGES 80 explicit 81 #endif 82 DynamicMessageFactory(const DescriptorPool* pool); 83 DynamicMessageFactory(const DynamicMessageFactory&) = delete; 84 DynamicMessageFactory& operator=(const DynamicMessageFactory&) = delete; 85 86 ~DynamicMessageFactory() override; 87 88 // Call this to tell the DynamicMessageFactory that if it is given a 89 // Descriptor d for which: 90 // d->file()->pool() == DescriptorPool::generated_pool(), 91 // then it should delegate to MessageFactory::generated_factory() instead 92 // of constructing a dynamic implementation of the message. In theory there 93 // is no down side to doing this, so it may become the default in the future. SetDelegateToGeneratedFactory(bool enable)94 void SetDelegateToGeneratedFactory(bool enable) { 95 delegate_to_generated_factory_ = enable; 96 } 97 98 // implements MessageFactory --------------------------------------- 99 100 // Given a Descriptor, constructs the default (prototype) Message of that 101 // type. You can then call that message's New() method to construct a 102 // mutable message of that type. 103 // 104 // Calling this method twice with the same Descriptor returns the same 105 // object. The returned object remains property of the factory and will 106 // be destroyed when the factory is destroyed. Also, any objects created 107 // by calling the prototype's New() method share some data with the 108 // prototype, so these must be destroyed before the DynamicMessageFactory 109 // is destroyed. 110 // 111 // The given descriptor must be non-null and outlive the returned message, and 112 // hence must outlive the DynamicMessageFactory. 113 // 114 // The method is thread-safe. 115 const Message* GetPrototype(const Descriptor* type) override; 116 117 private: 118 const DescriptorPool* pool_; 119 bool delegate_to_generated_factory_; 120 121 struct TypeInfo; 122 absl::flat_hash_map<const Descriptor*, const TypeInfo*> prototypes_; 123 mutable absl::Mutex prototypes_mutex_; 124 125 friend class DynamicMessage; 126 const Message* GetPrototypeNoLock(const Descriptor* type); 127 }; 128 129 // Helper for computing a sorted list of map entries via reflection. 130 class PROTOBUF_EXPORT DynamicMapSorter { 131 public: Sort(const Message & message,int map_size,const Reflection * reflection,const FieldDescriptor * field)132 static std::vector<const Message*> Sort(const Message& message, int map_size, 133 const Reflection* reflection, 134 const FieldDescriptor* field) { 135 std::vector<const Message*> result; 136 result.reserve(map_size); 137 RepeatedFieldRef<Message> map_field = 138 reflection->GetRepeatedFieldRef<Message>(message, field); 139 for (auto it = map_field.begin(); it != map_field.end(); ++it) { 140 result.push_back(&*it); 141 } 142 MapEntryMessageComparator comparator(field->message_type()); 143 std::stable_sort(result.begin(), result.end(), comparator); 144 // Complain if the keys aren't in ascending order. 145 #ifndef NDEBUG 146 for (size_t j = 1; j < static_cast<size_t>(map_size); ++j) { 147 if (!comparator(result[j - 1], result[j])) { 148 ABSL_LOG(ERROR) << (comparator(result[j], result[j - 1]) 149 ? "internal error in map key sorting" 150 : "map keys are not unique"); 151 } 152 } 153 #endif 154 return result; 155 } 156 157 private: 158 class PROTOBUF_EXPORT MapEntryMessageComparator { 159 public: MapEntryMessageComparator(const Descriptor * descriptor)160 explicit MapEntryMessageComparator(const Descriptor* descriptor) 161 : field_(descriptor->field(0)) {} 162 operator()163 bool operator()(const Message* a, const Message* b) { 164 const Reflection* reflection = a->GetReflection(); 165 switch (field_->cpp_type()) { 166 case FieldDescriptor::CPPTYPE_BOOL: { 167 bool first = reflection->GetBool(*a, field_); 168 bool second = reflection->GetBool(*b, field_); 169 return first < second; 170 } 171 case FieldDescriptor::CPPTYPE_INT32: { 172 int32_t first = reflection->GetInt32(*a, field_); 173 int32_t second = reflection->GetInt32(*b, field_); 174 return first < second; 175 } 176 case FieldDescriptor::CPPTYPE_INT64: { 177 int64_t first = reflection->GetInt64(*a, field_); 178 int64_t second = reflection->GetInt64(*b, field_); 179 return first < second; 180 } 181 case FieldDescriptor::CPPTYPE_UINT32: { 182 uint32_t first = reflection->GetUInt32(*a, field_); 183 uint32_t second = reflection->GetUInt32(*b, field_); 184 return first < second; 185 } 186 case FieldDescriptor::CPPTYPE_UINT64: { 187 uint64_t first = reflection->GetUInt64(*a, field_); 188 uint64_t second = reflection->GetUInt64(*b, field_); 189 return first < second; 190 } 191 case FieldDescriptor::CPPTYPE_STRING: { 192 std::string first = reflection->GetString(*a, field_); 193 std::string second = reflection->GetString(*b, field_); 194 return first < second; 195 } 196 default: 197 ABSL_DLOG(FATAL) << "Invalid key for map field."; 198 return true; 199 } 200 } 201 202 private: 203 const FieldDescriptor* field_; 204 }; 205 }; 206 207 } // namespace protobuf 208 } // namespace google 209 210 #include "google/protobuf/port_undef.inc" 211 212 #endif // GOOGLE_PROTOBUF_DYNAMIC_MESSAGE_H__ 213