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_REFLECTION_INTERNAL_H__ 32 #define GOOGLE_PROTOBUF_REFLECTION_INTERNAL_H__ 33 34 #include <google/protobuf/map_field.h> 35 #include <google/protobuf/reflection.h> 36 #include <google/protobuf/repeated_field.h> 37 38 namespace google { 39 namespace protobuf { 40 namespace internal { 41 // A base class for RepeatedFieldAccessor implementations that can support 42 // random-access efficiently. All iterator methods delegates the work to 43 // corresponding random-access methods. 44 class RandomAccessRepeatedFieldAccessor : public RepeatedFieldAccessor { 45 public: ~RandomAccessRepeatedFieldAccessor()46 virtual ~RandomAccessRepeatedFieldAccessor() {} 47 BeginIterator(const Field * data)48 virtual Iterator* BeginIterator(const Field* data) const { 49 return PositionToIterator(0); 50 } EndIterator(const Field * data)51 virtual Iterator* EndIterator(const Field* data) const { 52 return PositionToIterator(this->Size(data)); 53 } CopyIterator(const Field * data,const Iterator * iterator)54 virtual Iterator* CopyIterator(const Field* data, 55 const Iterator* iterator) const { 56 return const_cast<Iterator*>(iterator); 57 } AdvanceIterator(const Field * data,Iterator * iterator)58 virtual Iterator* AdvanceIterator(const Field* data, 59 Iterator* iterator) const { 60 return PositionToIterator(IteratorToPosition(iterator) + 1); 61 } EqualsIterator(const Field * data,const Iterator * a,const Iterator * b)62 virtual bool EqualsIterator(const Field* data, 63 const Iterator* a, 64 const Iterator* b) const { 65 return a == b; 66 } DeleteIterator(const Field * data,Iterator * iterator)67 virtual void DeleteIterator(const Field* data, Iterator* iterator) const { 68 } GetIteratorValue(const Field * data,const Iterator * iterator,Value * scratch_space)69 virtual const Value* GetIteratorValue(const Field* data, 70 const Iterator* iterator, 71 Value* scratch_space) const { 72 return Get(data, static_cast<int>(IteratorToPosition(iterator)), 73 scratch_space); 74 } 75 76 private: IteratorToPosition(const Iterator * iterator)77 static intptr_t IteratorToPosition(const Iterator* iterator) { 78 return reinterpret_cast<intptr_t>(iterator); 79 } PositionToIterator(intptr_t position)80 static Iterator* PositionToIterator(intptr_t position) { 81 return reinterpret_cast<Iterator*>(position); 82 } 83 }; 84 85 // Base class for RepeatedFieldAccessor implementations that manipulates 86 // RepeatedField<T>. 87 template<typename T> 88 class RepeatedFieldWrapper : public RandomAccessRepeatedFieldAccessor { 89 public: RepeatedFieldWrapper()90 RepeatedFieldWrapper() {} ~RepeatedFieldWrapper()91 virtual ~RepeatedFieldWrapper() {} IsEmpty(const Field * data)92 virtual bool IsEmpty(const Field* data) const { 93 return GetRepeatedField(data)->empty(); 94 } Size(const Field * data)95 virtual int Size(const Field* data) const { 96 return GetRepeatedField(data)->size(); 97 } Get(const Field * data,int index,Value * scratch_space)98 virtual const Value* Get(const Field* data, int index, 99 Value* scratch_space) const { 100 return ConvertFromT(GetRepeatedField(data)->Get(index), scratch_space); 101 } Clear(Field * data)102 virtual void Clear(Field* data) const { 103 MutableRepeatedField(data)->Clear(); 104 } Set(Field * data,int index,const Value * value)105 virtual void Set(Field* data, int index, const Value* value) const { 106 MutableRepeatedField(data)->Set(index, ConvertToT(value)); 107 } Add(Field * data,const Value * value)108 virtual void Add(Field* data, const Value* value) const { 109 MutableRepeatedField(data)->Add(ConvertToT(value)); 110 } RemoveLast(Field * data)111 virtual void RemoveLast(Field* data) const { 112 MutableRepeatedField(data)->RemoveLast(); 113 } SwapElements(Field * data,int index1,int index2)114 virtual void SwapElements(Field* data, int index1, int index2) const { 115 MutableRepeatedField(data)->SwapElements(index1, index2); 116 } 117 118 protected: 119 typedef RepeatedField<T> RepeatedFieldType; GetRepeatedField(const Field * data)120 static const RepeatedFieldType* GetRepeatedField(const Field* data) { 121 return reinterpret_cast<const RepeatedFieldType*>(data); 122 } MutableRepeatedField(Field * data)123 static RepeatedFieldType* MutableRepeatedField(Field* data) { 124 return reinterpret_cast<RepeatedFieldType*>(data); 125 } 126 127 // Convert an object recevied by this accessor to an object to be stored in 128 // the underlying RepeatedField. 129 virtual T ConvertToT(const Value* value) const = 0; 130 131 // Convert an object stored in RepeatedPtrField to an object that will be 132 // returned by this accessor. If the two objects have the same type (true 133 // for string fields with ctype=STRING), a pointer to the source object can 134 // be returned directly. Otherwise, data should be copied from value to 135 // scratch_space and scratch_space should be returned. 136 virtual const Value* ConvertFromT(const T& value, 137 Value* scratch_space) const = 0; 138 }; 139 140 // Base class for RepeatedFieldAccessor implementations that manipulates 141 // RepeatedPtrField<T>. 142 template<typename T> 143 class RepeatedPtrFieldWrapper : public RandomAccessRepeatedFieldAccessor { 144 public: RepeatedPtrFieldWrapper()145 RepeatedPtrFieldWrapper() {} ~RepeatedPtrFieldWrapper()146 virtual ~RepeatedPtrFieldWrapper() {} IsEmpty(const Field * data)147 virtual bool IsEmpty(const Field* data) const { 148 return GetRepeatedField(data)->empty(); 149 } Size(const Field * data)150 virtual int Size(const Field* data) const { 151 return GetRepeatedField(data)->size(); 152 } Get(const Field * data,int index,Value * scratch_space)153 virtual const Value* Get(const Field* data, int index, 154 Value* scratch_space) const { 155 return ConvertFromT(GetRepeatedField(data)->Get(index), scratch_space); 156 } Clear(Field * data)157 virtual void Clear(Field* data) const { 158 MutableRepeatedField(data)->Clear(); 159 } Set(Field * data,int index,const Value * value)160 virtual void Set(Field* data, int index, const Value* value) const { 161 ConvertToT(value, MutableRepeatedField(data)->Mutable(index)); 162 } Add(Field * data,const Value * value)163 virtual void Add(Field* data, const Value* value) const { 164 T* allocated = New(value); 165 ConvertToT(value, allocated); 166 MutableRepeatedField(data)->AddAllocated(allocated); 167 } RemoveLast(Field * data)168 virtual void RemoveLast(Field* data) const { 169 MutableRepeatedField(data)->RemoveLast(); 170 } SwapElements(Field * data,int index1,int index2)171 virtual void SwapElements(Field* data, int index1, int index2) const { 172 MutableRepeatedField(data)->SwapElements(index1, index2); 173 } 174 175 protected: 176 typedef RepeatedPtrField<T> RepeatedFieldType; GetRepeatedField(const Field * data)177 static const RepeatedFieldType* GetRepeatedField(const Field* data) { 178 return reinterpret_cast<const RepeatedFieldType*>(data); 179 } MutableRepeatedField(Field * data)180 static RepeatedFieldType* MutableRepeatedField(Field* data) { 181 return reinterpret_cast<RepeatedFieldType*>(data); 182 } 183 184 // Create a new T instance. For repeated message fields, T can be specified 185 // as google::protobuf::Message so we can't use "new T()" directly. In that case, value 186 // should be a message of the same type (it's ensured by the caller) and a 187 // new message object will be created using it. 188 virtual T* New(const Value* value) const = 0; 189 190 // Convert an object received by this accessor to an object that will be 191 // stored in the underlying RepeatedPtrField. 192 virtual void ConvertToT(const Value* value, T* result) const = 0; 193 194 // Convert an object stored in RepeatedPtrField to an object that will be 195 // returned by this accessor. If the two objects have the same type (true 196 // for string fields with ctype=STRING), a pointer to the source object can 197 // be returned directly. Otherwise, data should be copied from value to 198 // scratch_space and scratch_space should be returned. 199 virtual const Value* ConvertFromT(const T& value, 200 Value* scratch_space) const = 0; 201 }; 202 203 // An implementation of RandomAccessRepeatedFieldAccessor that manipulates 204 // MapFieldBase. 205 class MapFieldAccessor : public RandomAccessRepeatedFieldAccessor { 206 public: MapFieldAccessor()207 MapFieldAccessor() {} ~MapFieldAccessor()208 virtual ~MapFieldAccessor() {} IsEmpty(const Field * data)209 virtual bool IsEmpty(const Field* data) const { 210 return GetRepeatedField(data)->empty(); 211 } Size(const Field * data)212 virtual int Size(const Field* data) const { 213 return GetRepeatedField(data)->size(); 214 } Get(const Field * data,int index,Value * scratch_space)215 virtual const Value* Get(const Field* data, int index, 216 Value* scratch_space) const { 217 return ConvertFromEntry(GetRepeatedField(data)->Get(index), scratch_space); 218 } Clear(Field * data)219 virtual void Clear(Field* data) const { 220 MutableRepeatedField(data)->Clear(); 221 } Set(Field * data,int index,const Value * value)222 virtual void Set(Field* data, int index, const Value* value) const { 223 ConvertToEntry(value, MutableRepeatedField(data)->Mutable(index)); 224 } Add(Field * data,const Value * value)225 virtual void Add(Field* data, const Value* value) const { 226 Message* allocated = New(value); 227 ConvertToEntry(value, allocated); 228 MutableRepeatedField(data)->AddAllocated(allocated); 229 } RemoveLast(Field * data)230 virtual void RemoveLast(Field* data) const { 231 MutableRepeatedField(data)->RemoveLast(); 232 } SwapElements(Field * data,int index1,int index2)233 virtual void SwapElements(Field* data, int index1, int index2) const { 234 MutableRepeatedField(data)->SwapElements(index1, index2); 235 } Swap(Field * data,const internal::RepeatedFieldAccessor * other_mutator,Field * other_data)236 virtual void Swap( 237 Field* data, 238 const internal::RepeatedFieldAccessor* other_mutator, 239 Field* other_data) const { 240 GOOGLE_CHECK(this == other_mutator); 241 MutableRepeatedField(data)->Swap(MutableRepeatedField(other_data)); 242 } 243 244 protected: 245 typedef RepeatedPtrField<Message> RepeatedFieldType; GetRepeatedField(const Field * data)246 static const RepeatedFieldType* GetRepeatedField(const Field* data) { 247 return reinterpret_cast<const RepeatedFieldType*>( 248 (&reinterpret_cast<const MapFieldBase*>(data)->GetRepeatedField())); 249 } MutableRepeatedField(Field * data)250 static RepeatedFieldType* MutableRepeatedField(Field* data) { 251 return reinterpret_cast<RepeatedFieldType*>( 252 reinterpret_cast<MapFieldBase*>(data)->MutableRepeatedField()); 253 } New(const Value * value)254 virtual Message* New(const Value* value) const { 255 return static_cast<const Message*>(value)->New(); 256 } 257 // Convert an object received by this accessor to an MapEntry message to be 258 // stored in the underlying MapFieldBase. ConvertToEntry(const Value * value,Message * result)259 virtual void ConvertToEntry(const Value* value, Message* result) const { 260 result->CopyFrom(*static_cast<const Message*>(value)); 261 } 262 // Convert a MapEntry message stored in the underlying MapFieldBase to an 263 // object that will be returned by this accessor. ConvertFromEntry(const Message & value,Value * scratch_space)264 virtual const Value* ConvertFromEntry(const Message& value, 265 Value* scratch_space) const { 266 return static_cast<const Value*>(&value); 267 } 268 }; 269 270 // Default implementations of RepeatedFieldAccessor for primitive types. 271 template<typename T> 272 class RepeatedFieldPrimitiveAccessor : public RepeatedFieldWrapper<T> { 273 typedef void Field; 274 typedef void Value; 275 using RepeatedFieldWrapper<T>::MutableRepeatedField; 276 277 public: RepeatedFieldPrimitiveAccessor()278 RepeatedFieldPrimitiveAccessor() {} ~RepeatedFieldPrimitiveAccessor()279 virtual ~RepeatedFieldPrimitiveAccessor() {} Swap(Field * data,const internal::RepeatedFieldAccessor * other_mutator,Field * other_data)280 virtual void Swap( 281 Field* data, 282 const internal::RepeatedFieldAccessor* other_mutator, 283 Field* other_data) const { 284 // Currently RepeatedFieldPrimitiveAccessor is the only implementation of 285 // RepeatedFieldAccessor for primitive types. As we are using singletons 286 // for these accessors, here "other_mutator" must be "this". 287 GOOGLE_CHECK(this == other_mutator); 288 MutableRepeatedField(data)->Swap(MutableRepeatedField(other_data)); 289 } 290 291 protected: ConvertToT(const Value * value)292 virtual T ConvertToT(const Value* value) const { 293 return *static_cast<const T*>(value); 294 } ConvertFromT(const T & value,Value * scratch_space)295 virtual const Value* ConvertFromT(const T& value, 296 Value* scratch_space) const { 297 return static_cast<const Value*>(&value); 298 } 299 }; 300 301 // Default implementation of RepeatedFieldAccessor for string fields with 302 // ctype=STRING. 303 class RepeatedPtrFieldStringAccessor : public RepeatedPtrFieldWrapper<string> { 304 typedef void Field; 305 typedef void Value; 306 using RepeatedFieldAccessor::Add; 307 308 public: RepeatedPtrFieldStringAccessor()309 RepeatedPtrFieldStringAccessor() {} ~RepeatedPtrFieldStringAccessor()310 virtual ~RepeatedPtrFieldStringAccessor() {} Swap(Field * data,const internal::RepeatedFieldAccessor * other_mutator,Field * other_data)311 virtual void Swap( 312 Field* data, 313 const internal::RepeatedFieldAccessor* other_mutator, 314 Field* other_data) const { 315 if (this == other_mutator) { 316 MutableRepeatedField(data)->Swap(MutableRepeatedField(other_data)); 317 } else { 318 RepeatedPtrField<string> tmp; 319 tmp.Swap(MutableRepeatedField(data)); 320 int other_size = other_mutator->Size(other_data); 321 for (int i = 0; i < other_size; ++i) { 322 Add<string>(data, other_mutator->Get<string>(other_data, i)); 323 } 324 int size = Size(data); 325 other_mutator->Clear(other_data); 326 for (int i = 0; i < size; ++i) { 327 other_mutator->Add<string>(other_data, tmp.Get(i)); 328 } 329 } 330 } 331 332 protected: New(const Value *)333 virtual string* New(const Value*) const { 334 return new string(); 335 } ConvertToT(const Value * value,string * result)336 virtual void ConvertToT(const Value* value, string* result) const { 337 *result = *static_cast<const string*>(value); 338 } ConvertFromT(const string & value,Value * scratch_space)339 virtual const Value* ConvertFromT(const string& value, 340 Value* scratch_space) const { 341 return static_cast<const Value*>(&value); 342 } 343 }; 344 345 346 class RepeatedPtrFieldMessageAccessor 347 : public RepeatedPtrFieldWrapper<Message> { 348 typedef void Field; 349 typedef void Value; 350 351 public: RepeatedPtrFieldMessageAccessor()352 RepeatedPtrFieldMessageAccessor() {} ~RepeatedPtrFieldMessageAccessor()353 virtual ~RepeatedPtrFieldMessageAccessor() {} Swap(Field * data,const internal::RepeatedFieldAccessor * other_mutator,Field * other_data)354 virtual void Swap( 355 Field* data, 356 const internal::RepeatedFieldAccessor* other_mutator, 357 Field* other_data) const { 358 GOOGLE_CHECK(this == other_mutator); 359 MutableRepeatedField(data)->Swap(MutableRepeatedField(other_data)); 360 } 361 362 protected: New(const Value * value)363 virtual Message* New(const Value* value) const { 364 return static_cast<const Message*>(value)->New(); 365 } ConvertToT(const Value * value,Message * result)366 virtual void ConvertToT(const Value* value, Message* result) const { 367 result->CopyFrom(*static_cast<const Message*>(value)); 368 } ConvertFromT(const Message & value,Value * scratch_space)369 virtual const Value* ConvertFromT(const Message& value, 370 Value* scratch_space) const { 371 return static_cast<const Value*>(&value); 372 } 373 }; 374 } // namespace internal 375 } // namespace protobuf 376 377 } // namespace google 378 #endif // GOOGLE_PROTOBUF_REFLECTION_INTERNAL_H__ 379