Line data Source code
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 : // This header defines the RepeatedFieldRef class template used to access
32 : // repeated fields with protobuf reflection API.
33 : #ifndef GOOGLE_PROTOBUF_REFLECTION_H__
34 : #define GOOGLE_PROTOBUF_REFLECTION_H__
35 :
36 : #include <memory>
37 : #ifndef _SHARED_PTR_H
38 : #include <google/protobuf/stubs/shared_ptr.h>
39 : #endif
40 :
41 : #include <google/protobuf/message.h>
42 : #include <google/protobuf/generated_enum_util.h>
43 :
44 : namespace google {
45 : namespace protobuf {
46 : namespace internal {
47 : template<typename T, typename Enable = void>
48 : struct RefTypeTraits;
49 : } // namespace internal
50 :
51 : template<typename T>
52 : RepeatedFieldRef<T> Reflection::GetRepeatedFieldRef(
53 : const Message& message, const FieldDescriptor* field) const {
54 : return RepeatedFieldRef<T>(message, field);
55 : }
56 :
57 : template<typename T>
58 : MutableRepeatedFieldRef<T> Reflection::GetMutableRepeatedFieldRef(
59 : Message* message, const FieldDescriptor* field) const {
60 : return MutableRepeatedFieldRef<T>(message, field);
61 : }
62 :
63 : // RepeatedFieldRef definition for non-message types.
64 : template<typename T>
65 : class RepeatedFieldRef<
66 : T, typename internal::enable_if<!internal::is_base_of<Message, T>::value>::type> {
67 : typedef typename internal::RefTypeTraits<T>::iterator IteratorType;
68 : typedef typename internal::RefTypeTraits<T>::AccessorType AccessorType;
69 :
70 : public:
71 : bool empty() const {
72 : return accessor_->IsEmpty(data_);
73 : }
74 : int size() const {
75 : return accessor_->Size(data_);
76 : }
77 : T Get(int index) const {
78 : return accessor_->template Get<T>(data_, index);
79 : }
80 :
81 : typedef IteratorType iterator;
82 : typedef IteratorType const_iterator;
83 : iterator begin() const {
84 : return iterator(data_, accessor_, true);
85 : }
86 : iterator end() const {
87 : return iterator(data_, accessor_, false);
88 : }
89 :
90 : private:
91 : friend class Reflection;
92 : RepeatedFieldRef(
93 : const Message& message,
94 : const FieldDescriptor* field) {
95 : const Reflection* reflection = message.GetReflection();
96 : data_ = reflection->RepeatedFieldData(
97 : const_cast<Message*>(&message), field,
98 : internal::RefTypeTraits<T>::cpp_type, NULL);
99 : accessor_ = reflection->RepeatedFieldAccessor(field);
100 : }
101 :
102 : const void* data_;
103 : const AccessorType* accessor_;
104 : };
105 :
106 : // MutableRepeatedFieldRef definition for non-message types.
107 : template<typename T>
108 : class MutableRepeatedFieldRef<
109 : T, typename internal::enable_if<!internal::is_base_of<Message, T>::value>::type> {
110 : typedef typename internal::RefTypeTraits<T>::AccessorType AccessorType;
111 :
112 : public:
113 : bool empty() const {
114 : return accessor_->IsEmpty(data_);
115 : }
116 : int size() const {
117 : return accessor_->Size(data_);
118 : }
119 : T Get(int index) const {
120 : return accessor_->template Get<T>(data_, index);
121 : }
122 :
123 : void Set(int index, const T& value) const {
124 : accessor_->template Set<T>(data_, index, value);
125 : }
126 : void Add(const T& value) const {
127 : accessor_->template Add<T>(data_, value);
128 : }
129 : void RemoveLast() const {
130 : accessor_->RemoveLast(data_);
131 : }
132 : void SwapElements(int index1, int index2) const {
133 : accessor_->SwapElements(data_, index1, index2);
134 : }
135 : void Clear() const {
136 : accessor_->Clear(data_);
137 : }
138 :
139 : void Swap(const MutableRepeatedFieldRef& other) const {
140 : accessor_->Swap(data_, other.accessor_, other.data_);
141 : }
142 :
143 : template<typename Container>
144 : void MergeFrom(const Container& container) const {
145 : typedef typename Container::const_iterator Iterator;
146 : for (Iterator it = container.begin(); it != container.end(); ++it) {
147 : Add(*it);
148 : }
149 : }
150 : template<typename Container>
151 : void CopyFrom(const Container& container) const {
152 : Clear();
153 : MergeFrom(container);
154 : }
155 :
156 : private:
157 : friend class Reflection;
158 : MutableRepeatedFieldRef(
159 : Message* message,
160 : const FieldDescriptor* field) {
161 : const Reflection* reflection = message->GetReflection();
162 : data_ = reflection->RepeatedFieldData(
163 : message, field, internal::RefTypeTraits<T>::cpp_type, NULL);
164 : accessor_ = reflection->RepeatedFieldAccessor(field);
165 : }
166 :
167 : void* data_;
168 : const AccessorType* accessor_;
169 : };
170 :
171 : // RepeatedFieldRef definition for message types.
172 : template<typename T>
173 : class RepeatedFieldRef<
174 : T, typename internal::enable_if<internal::is_base_of<Message, T>::value>::type> {
175 : typedef typename internal::RefTypeTraits<T>::iterator IteratorType;
176 : typedef typename internal::RefTypeTraits<T>::AccessorType AccessorType;
177 :
178 : public:
179 : bool empty() const {
180 : return accessor_->IsEmpty(data_);
181 : }
182 : int size() const {
183 : return accessor_->Size(data_);
184 : }
185 : // This method returns a reference to the underlying message object if it
186 : // exists. If a message object doesn't exist (e.g., data stored in serialized
187 : // form), scratch_space will be filled with the data and a reference to it
188 : // will be returned.
189 : //
190 : // Example:
191 : // RepeatedFieldRef<Message> h = ...
192 : // unique_ptr<Message> scratch_space(h.NewMessage());
193 : // const Message& item = h.Get(index, scratch_space.get());
194 : const T& Get(int index, T* scratch_space) const {
195 : return *static_cast<const T*>(accessor_->Get(data_, index, scratch_space));
196 : }
197 : // Create a new message of the same type as the messages stored in this
198 : // repeated field. Caller takes ownership of the returned object.
199 : T* NewMessage() const {
200 : return static_cast<T*>(default_instance_->New());
201 : }
202 :
203 : typedef IteratorType iterator;
204 : typedef IteratorType const_iterator;
205 : iterator begin() const {
206 : return iterator(data_, accessor_, true, NewMessage());
207 : }
208 : iterator end() const {
209 : return iterator(data_, accessor_, false, NewMessage());
210 : }
211 :
212 : private:
213 : friend class Reflection;
214 : RepeatedFieldRef(
215 : const Message& message,
216 : const FieldDescriptor* field) {
217 : const Reflection* reflection = message.GetReflection();
218 : data_ = reflection->RepeatedFieldData(
219 : const_cast<Message*>(&message), field,
220 : internal::RefTypeTraits<T>::cpp_type,
221 : internal::RefTypeTraits<T>::GetMessageFieldDescriptor());
222 : accessor_ = reflection->RepeatedFieldAccessor(field);
223 : default_instance_ =
224 : reflection->GetMessageFactory()->GetPrototype(field->message_type());
225 : }
226 :
227 : const void* data_;
228 : const AccessorType* accessor_;
229 : const Message* default_instance_;
230 : };
231 :
232 : // MutableRepeatedFieldRef definition for message types.
233 : template<typename T>
234 : class MutableRepeatedFieldRef<
235 : T, typename internal::enable_if<internal::is_base_of<Message, T>::value>::type> {
236 : typedef typename internal::RefTypeTraits<T>::AccessorType AccessorType;
237 :
238 : public:
239 : bool empty() const {
240 : return accessor_->IsEmpty(data_);
241 : }
242 : int size() const {
243 : return accessor_->Size(data_);
244 : }
245 : // See comments for RepeatedFieldRef<Message>::Get()
246 : const T& Get(int index, T* scratch_space) const {
247 : return *static_cast<const T*>(accessor_->Get(data_, index, scratch_space));
248 : }
249 : // Create a new message of the same type as the messages stored in this
250 : // repeated field. Caller takes ownership of the returned object.
251 : T* NewMessage() const {
252 : return static_cast<T*>(default_instance_->New());
253 : }
254 :
255 : void Set(int index, const T& value) const {
256 : accessor_->Set(data_, index, &value);
257 : }
258 : void Add(const T& value) const {
259 : accessor_->Add(data_, &value);
260 : }
261 : void RemoveLast() const {
262 : accessor_->RemoveLast(data_);
263 : }
264 : void SwapElements(int index1, int index2) const {
265 : accessor_->SwapElements(data_, index1, index2);
266 : }
267 : void Clear() const {
268 : accessor_->Clear(data_);
269 : }
270 :
271 : void Swap(const MutableRepeatedFieldRef& other) const {
272 : accessor_->Swap(data_, other.accessor_, other.data_);
273 : }
274 :
275 : template<typename Container>
276 : void MergeFrom(const Container& container) const {
277 : typedef typename Container::const_iterator Iterator;
278 : for (Iterator it = container.begin(); it != container.end(); ++it) {
279 : Add(*it);
280 : }
281 : }
282 : template<typename Container>
283 : void CopyFrom(const Container& container) const {
284 : Clear();
285 : MergeFrom(container);
286 : }
287 :
288 : private:
289 : friend class Reflection;
290 : MutableRepeatedFieldRef(
291 : Message* message,
292 : const FieldDescriptor* field) {
293 : const Reflection* reflection = message->GetReflection();
294 : data_ = reflection->RepeatedFieldData(
295 : message, field, internal::RefTypeTraits<T>::cpp_type,
296 : internal::RefTypeTraits<T>::GetMessageFieldDescriptor());
297 : accessor_ = reflection->RepeatedFieldAccessor(field);
298 : default_instance_ =
299 : reflection->GetMessageFactory()->GetPrototype(field->message_type());
300 : }
301 :
302 : void* data_;
303 : const AccessorType* accessor_;
304 : const Message* default_instance_;
305 : };
306 :
307 : namespace internal {
308 : // Interfaces used to implement reflection RepeatedFieldRef API.
309 : // Reflection::GetRepeatedAccessor() should return a pointer to an singleton
310 : // object that implements the below interface.
311 : //
312 : // This interface passes/returns values using void pointers. The actual type
313 : // of the value depends on the field's cpp_type. Following is a mapping from
314 : // cpp_type to the type that should be used in this interface:
315 : //
316 : // field->cpp_type() T Actual type of void*
317 : // CPPTYPE_INT32 int32 int32
318 : // CPPTYPE_UINT32 uint32 uint32
319 : // CPPTYPE_INT64 int64 int64
320 : // CPPTYPE_UINT64 uint64 uint64
321 : // CPPTYPE_DOUBLE double double
322 : // CPPTYPE_FLOAT float float
323 : // CPPTYPE_BOOL bool bool
324 : // CPPTYPE_ENUM generated enum type int32
325 : // CPPTYPE_STRING string string
326 : // CPPTYPE_MESSAGE generated message type google::protobuf::Message
327 : // or google::protobuf::Message
328 : //
329 : // Note that for enums we use int32 in the interface.
330 : //
331 : // You can map from T to the actual type using RefTypeTraits:
332 : // typedef RefTypeTraits<T>::AccessorValueType ActualType;
333 0 : class LIBPROTOBUF_EXPORT RepeatedFieldAccessor {
334 : public:
335 : // Typedefs for clarity.
336 : typedef void Field;
337 : typedef void Value;
338 : typedef void Iterator;
339 :
340 : virtual ~RepeatedFieldAccessor();
341 : virtual bool IsEmpty(const Field* data) const = 0;
342 : virtual int Size(const Field* data) const = 0;
343 : // Depends on the underlying representation of the repeated field, this
344 : // method can return a pointer to the underlying object if such an object
345 : // exists, or fill the data into scratch_space and return scratch_space.
346 : // Callers of this method must ensure scratch_space is a valid pointer
347 : // to a mutable object of the correct type.
348 : virtual const Value* Get(
349 : const Field* data, int index, Value* scratch_space) const = 0;
350 :
351 : virtual void Clear(Field* data) const = 0;
352 : virtual void Set(Field* data, int index, const Value* value) const = 0;
353 : virtual void Add(Field* data, const Value* value) const = 0;
354 : virtual void RemoveLast(Field* data) const = 0;
355 : virtual void SwapElements(Field* data, int index1, int index2) const = 0;
356 : virtual void Swap(Field* data, const RepeatedFieldAccessor* other_mutator,
357 : Field* other_data) const = 0;
358 :
359 : // Create an iterator that points at the begining of the repeated field.
360 : virtual Iterator* BeginIterator(const Field* data) const = 0;
361 : // Create an iterator that points at the end of the repeated field.
362 : virtual Iterator* EndIterator(const Field* data) const = 0;
363 : // Make a copy of an iterator and return the new copy.
364 : virtual Iterator* CopyIterator(const Field* data,
365 : const Iterator* iterator) const = 0;
366 : // Move an iterator to point to the next element.
367 : virtual Iterator* AdvanceIterator(const Field* data,
368 : Iterator* iterator) const = 0;
369 : // Compare whether two iterators point to the same element.
370 : virtual bool EqualsIterator(const Field* data, const Iterator* a,
371 : const Iterator* b) const = 0;
372 : // Delete an iterator created by BeginIterator(), EndIterator() and
373 : // CopyIterator().
374 : virtual void DeleteIterator(const Field* data, Iterator* iterator) const = 0;
375 : // Like Get() but for iterators.
376 : virtual const Value* GetIteratorValue(const Field* data,
377 : const Iterator* iterator,
378 : Value* scratch_space) const = 0;
379 :
380 : // Templated methods that make using this interface easier for non-message
381 : // types.
382 : template<typename T>
383 0 : T Get(const Field* data, int index) const {
384 : typedef typename RefTypeTraits<T>::AccessorValueType ActualType;
385 : ActualType scratch_space;
386 : return static_cast<T>(
387 : *reinterpret_cast<const ActualType*>(
388 0 : Get(data, index, static_cast<Value*>(&scratch_space))));
389 : }
390 :
391 : template<typename T, typename ValueType>
392 : void Set(Field* data, int index, const ValueType& value) const {
393 : typedef typename RefTypeTraits<T>::AccessorValueType ActualType;
394 : // In this RepeatedFieldAccessor interface we pass/return data using
395 : // raw pointers. Type of the data these raw pointers point to should
396 : // be ActualType. Here we have a ValueType object and want a ActualType
397 : // pointer. We can't cast a ValueType pointer to an ActualType pointer
398 : // directly because their type might be different (for enums ValueType
399 : // may be a generated enum type while ActualType is int32). To be safe
400 : // we make a copy to get a temporary ActualType object and use it.
401 : ActualType tmp = static_cast<ActualType>(value);
402 : Set(data, index, static_cast<const Value*>(&tmp));
403 : }
404 :
405 : template<typename T, typename ValueType>
406 0 : void Add(Field* data, const ValueType& value) const {
407 : typedef typename RefTypeTraits<T>::AccessorValueType ActualType;
408 : // In this RepeatedFieldAccessor interface we pass/return data using
409 : // raw pointers. Type of the data these raw pointers point to should
410 : // be ActualType. Here we have a ValueType object and want a ActualType
411 : // pointer. We can't cast a ValueType pointer to an ActualType pointer
412 : // directly because their type might be different (for enums ValueType
413 : // may be a generated enum type while ActualType is int32). To be safe
414 : // we make a copy to get a temporary ActualType object and use it.
415 0 : ActualType tmp = static_cast<ActualType>(value);
416 0 : Add(data, static_cast<const Value*>(&tmp));
417 0 : }
418 : };
419 :
420 : // Implement (Mutable)RepeatedFieldRef::iterator
421 : template<typename T>
422 : class RepeatedFieldRefIterator
423 : : public std::iterator<std::forward_iterator_tag, T> {
424 : typedef typename RefTypeTraits<T>::AccessorValueType AccessorValueType;
425 : typedef typename RefTypeTraits<T>::IteratorValueType IteratorValueType;
426 : typedef typename RefTypeTraits<T>::IteratorPointerType IteratorPointerType;
427 :
428 : public:
429 : // Constructor for non-message fields.
430 : RepeatedFieldRefIterator(const void* data,
431 : const RepeatedFieldAccessor* accessor,
432 : bool begin)
433 : : data_(data), accessor_(accessor),
434 : iterator_(begin ? accessor->BeginIterator(data) :
435 : accessor->EndIterator(data)),
436 : scratch_space_(new AccessorValueType) {
437 : }
438 : // Constructor for message fields.
439 : RepeatedFieldRefIterator(const void* data,
440 : const RepeatedFieldAccessor* accessor,
441 : bool begin,
442 : AccessorValueType* scratch_space)
443 : : data_(data), accessor_(accessor),
444 : iterator_(begin ? accessor->BeginIterator(data) :
445 : accessor->EndIterator(data)),
446 : scratch_space_(scratch_space) {
447 : }
448 : ~RepeatedFieldRefIterator() {
449 : accessor_->DeleteIterator(data_, iterator_);
450 : }
451 : RepeatedFieldRefIterator operator++(int) {
452 : RepeatedFieldRefIterator tmp(*this);
453 : iterator_ = accessor_->AdvanceIterator(data_, iterator_);
454 : return tmp;
455 : }
456 : RepeatedFieldRefIterator& operator++() {
457 : iterator_ = accessor_->AdvanceIterator(data_, iterator_);
458 : return *this;
459 : }
460 : IteratorValueType operator*() const {
461 : return static_cast<IteratorValueType>(
462 : *static_cast<const AccessorValueType*>(
463 : accessor_->GetIteratorValue(
464 : data_, iterator_, scratch_space_.get())));
465 : }
466 : IteratorPointerType operator->() const {
467 : return static_cast<IteratorPointerType>(
468 : accessor_->GetIteratorValue(
469 : data_, iterator_, scratch_space_.get()));
470 : }
471 : bool operator!=(const RepeatedFieldRefIterator& other) const {
472 : assert(data_ == other.data_);
473 : assert(accessor_ == other.accessor_);
474 : return !accessor_->EqualsIterator(data_, iterator_, other.iterator_);
475 : }
476 : bool operator==(const RepeatedFieldRefIterator& other) const {
477 : return !this->operator!=(other);
478 : }
479 :
480 : RepeatedFieldRefIterator(const RepeatedFieldRefIterator& other)
481 : : data_(other.data_), accessor_(other.accessor_),
482 : iterator_(accessor_->CopyIterator(data_, other.iterator_)) {
483 : }
484 : RepeatedFieldRefIterator& operator=(const RepeatedFieldRefIterator& other) {
485 : if (this != &other) {
486 : accessor_->DeleteIterator(data_, iterator_);
487 : data_ = other.data_;
488 : accessor_ = other.accessor_;
489 : iterator_ = accessor_->CopyIterator(data_, other.iterator_);
490 : }
491 : return *this;
492 : }
493 :
494 : protected:
495 : const void* data_;
496 : const RepeatedFieldAccessor* accessor_;
497 : void* iterator_;
498 : google::protobuf::scoped_ptr<AccessorValueType> scratch_space_;
499 : };
500 :
501 : // TypeTraits that maps the type parameter T of RepeatedFieldRef or
502 : // MutableRepeatedFieldRef to corresponding iterator type,
503 : // RepeatedFieldAccessor type, etc.
504 : template<typename T>
505 : struct PrimitiveTraits {
506 : static const bool is_primitive = false;
507 : };
508 : #define DEFINE_PRIMITIVE(TYPE, type) \
509 : template<> struct PrimitiveTraits<type> { \
510 : static const bool is_primitive = true; \
511 : static const FieldDescriptor::CppType cpp_type = \
512 : FieldDescriptor::CPPTYPE_ ## TYPE; \
513 : };
514 : DEFINE_PRIMITIVE(INT32, int32)
515 : DEFINE_PRIMITIVE(UINT32, uint32)
516 : DEFINE_PRIMITIVE(INT64, int64)
517 : DEFINE_PRIMITIVE(UINT64, uint64)
518 : DEFINE_PRIMITIVE(FLOAT, float)
519 : DEFINE_PRIMITIVE(DOUBLE, double)
520 : DEFINE_PRIMITIVE(BOOL, bool)
521 : #undef DEFINE_PRIMITIVE
522 :
523 : template<typename T>
524 : struct RefTypeTraits<
525 : T, typename internal::enable_if<PrimitiveTraits<T>::is_primitive>::type> {
526 : typedef RepeatedFieldRefIterator<T> iterator;
527 : typedef RepeatedFieldAccessor AccessorType;
528 : typedef T AccessorValueType;
529 : typedef T IteratorValueType;
530 : typedef T* IteratorPointerType;
531 : static const FieldDescriptor::CppType cpp_type =
532 : PrimitiveTraits<T>::cpp_type;
533 : static const Descriptor* GetMessageFieldDescriptor() {
534 : return NULL;
535 : }
536 : };
537 :
538 : template<typename T>
539 : struct RefTypeTraits<
540 : T, typename internal::enable_if<is_proto_enum<T>::value>::type> {
541 : typedef RepeatedFieldRefIterator<T> iterator;
542 : typedef RepeatedFieldAccessor AccessorType;
543 : // We use int32 for repeated enums in RepeatedFieldAccessor.
544 : typedef int32 AccessorValueType;
545 : typedef T IteratorValueType;
546 : typedef int32* IteratorPointerType;
547 : static const FieldDescriptor::CppType cpp_type =
548 : FieldDescriptor::CPPTYPE_ENUM;
549 : static const Descriptor* GetMessageFieldDescriptor() {
550 : return NULL;
551 : }
552 : };
553 :
554 : template<typename T>
555 : struct RefTypeTraits<
556 : T, typename internal::enable_if< ::google::protobuf::internal::is_same<string, T>::value>::type> {
557 : typedef RepeatedFieldRefIterator<T> iterator;
558 : typedef RepeatedFieldAccessor AccessorType;
559 : typedef string AccessorValueType;
560 : typedef string IteratorValueType;
561 : typedef string* IteratorPointerType;
562 : static const FieldDescriptor::CppType cpp_type =
563 : FieldDescriptor::CPPTYPE_STRING;
564 : static const Descriptor* GetMessageFieldDescriptor() {
565 : return NULL;
566 : }
567 : };
568 :
569 : template<typename T>
570 : struct MessageDescriptorGetter {
571 : static const Descriptor* get() {
572 : return T::default_instance().GetDescriptor();
573 : }
574 : };
575 : template<>
576 : struct MessageDescriptorGetter<Message> {
577 : static const Descriptor* get() {
578 : return NULL;
579 : }
580 : };
581 :
582 : template<typename T>
583 : struct RefTypeTraits<
584 : T, typename internal::enable_if<internal::is_base_of<Message, T>::value>::type> {
585 : typedef RepeatedFieldRefIterator<T> iterator;
586 : typedef RepeatedFieldAccessor AccessorType;
587 : typedef Message AccessorValueType;
588 : typedef const T& IteratorValueType;
589 : typedef const T* IteratorPointerType;
590 : static const FieldDescriptor::CppType cpp_type =
591 : FieldDescriptor::CPPTYPE_MESSAGE;
592 : static const Descriptor* GetMessageFieldDescriptor() {
593 : return MessageDescriptorGetter<T>::get();
594 : }
595 : };
596 : } // namespace internal
597 : } // namespace protobuf
598 : } // namespace google
599 :
600 : #endif // GOOGLE_PROTOBUF_REFLECTION_H__
|