1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // http://code.google.com/p/protobuf/
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 // This header is logically internal, but is made public because it is used
36 // from protocol-compiler-generated code, which may reside in other components.
37
38 #ifndef GOOGLE_PROTOBUF_EXTENSION_SET_H__
39 #define GOOGLE_PROTOBUF_EXTENSION_SET_H__
40
41 #include <vector>
42 #include <stack>
43 #include <map>
44 #include <utility>
45 #include <string>
46
47 #include <google/protobuf/stubs/common.h>
48
49 namespace google {
50
51 namespace protobuf {
52 class Descriptor; // descriptor.h
53 class FieldDescriptor; // descriptor.h
54 class DescriptorPool; // descriptor.h
55 class MessageLite; // message_lite.h
56 class Message; // message.h
57 class MessageFactory; // message.h
58 class UnknownFieldSet; // unknown_field_set.h
59 namespace io {
60 class CodedInputStream; // coded_stream.h
61 class CodedOutputStream; // coded_stream.h
62 }
63 namespace internal {
64 class FieldSkipper; // wire_format_lite.h
65 class RepeatedPtrFieldBase; // repeated_field.h
66 }
67 template <typename Element> class RepeatedField; // repeated_field.h
68 template <typename Element> class RepeatedPtrField; // repeated_field.h
69 }
70
71 namespace protobuf {
72 namespace internal {
73
74 // Used to store values of type WireFormatLite::FieldType without having to
75 // #include wire_format_lite.h. Also, ensures that we use only one byte to
76 // store these values, which is important to keep the layout of
77 // ExtensionSet::Extension small.
78 typedef uint8 FieldType;
79
80 // A function which, given an integer value, returns true if the number
81 // matches one of the defined values for the corresponding enum type. This
82 // is used with RegisterEnumExtension, below.
83 typedef bool EnumValidityFunc(int number);
84
85 // Version of the above which takes an argument. This is needed to deal with
86 // extensions that are not compiled in.
87 typedef bool EnumValidityFuncWithArg(const void* arg, int number);
88
89 // Information about a registered extension.
90 struct ExtensionInfo {
ExtensionInfoExtensionInfo91 inline ExtensionInfo() {}
ExtensionInfoExtensionInfo92 inline ExtensionInfo(FieldType type, bool is_repeated, bool is_packed)
93 : type(type), is_repeated(is_repeated), is_packed(is_packed),
94 descriptor(NULL) {}
95
96 FieldType type;
97 bool is_repeated;
98 bool is_packed;
99
100 struct EnumValidityCheck {
101 EnumValidityFuncWithArg* func;
102 const void* arg;
103 };
104
105 union {
106 EnumValidityCheck enum_validity_check;
107 const MessageLite* message_prototype;
108 };
109
110 // The descriptor for this extension, if one exists and is known. May be
111 // NULL. Must not be NULL if the descriptor for the extension does not
112 // live in the same pool as the descriptor for the containing type.
113 const FieldDescriptor* descriptor;
114 };
115
116 // Abstract interface for an object which looks up extension definitions. Used
117 // when parsing.
118 class LIBPROTOBUF_EXPORT ExtensionFinder {
119 public:
120 virtual ~ExtensionFinder();
121
122 // Find the extension with the given containing type and number.
123 virtual bool Find(int number, ExtensionInfo* output) = 0;
124 };
125
126 // Implementation of ExtensionFinder which finds extensions defined in .proto
127 // files which have been compiled into the binary.
128 class LIBPROTOBUF_EXPORT GeneratedExtensionFinder : public ExtensionFinder {
129 public:
GeneratedExtensionFinder(const MessageLite * containing_type)130 GeneratedExtensionFinder(const MessageLite* containing_type)
131 : containing_type_(containing_type) {}
~GeneratedExtensionFinder()132 virtual ~GeneratedExtensionFinder() {}
133
134 // Returns true and fills in *output if found, otherwise returns false.
135 virtual bool Find(int number, ExtensionInfo* output);
136
137 private:
138 const MessageLite* containing_type_;
139 };
140
141 // Note: extension_set_heavy.cc defines DescriptorPoolExtensionFinder for
142 // finding extensions from a DescriptorPool.
143
144 // This is an internal helper class intended for use within the protocol buffer
145 // library and generated classes. Clients should not use it directly. Instead,
146 // use the generated accessors such as GetExtension() of the class being
147 // extended.
148 //
149 // This class manages extensions for a protocol message object. The
150 // message's HasExtension(), GetExtension(), MutableExtension(), and
151 // ClearExtension() methods are just thin wrappers around the embedded
152 // ExtensionSet. When parsing, if a tag number is encountered which is
153 // inside one of the message type's extension ranges, the tag is passed
154 // off to the ExtensionSet for parsing. Etc.
155 class LIBPROTOBUF_EXPORT ExtensionSet {
156 public:
157 ExtensionSet();
158 ~ExtensionSet();
159
160 // These are called at startup by protocol-compiler-generated code to
161 // register known extensions. The registrations are used by ParseField()
162 // to look up extensions for parsed field numbers. Note that dynamic parsing
163 // does not use ParseField(); only protocol-compiler-generated parsing
164 // methods do.
165 static void RegisterExtension(const MessageLite* containing_type,
166 int number, FieldType type,
167 bool is_repeated, bool is_packed);
168 static void RegisterEnumExtension(const MessageLite* containing_type,
169 int number, FieldType type,
170 bool is_repeated, bool is_packed,
171 EnumValidityFunc* is_valid);
172 static void RegisterMessageExtension(const MessageLite* containing_type,
173 int number, FieldType type,
174 bool is_repeated, bool is_packed,
175 const MessageLite* prototype);
176
177 // =================================================================
178
179 // Add all fields which are currently present to the given vector. This
180 // is useful to implement Reflection::ListFields().
181 void AppendToList(const Descriptor* containing_type,
182 const DescriptorPool* pool,
183 vector<const FieldDescriptor*>* output) const;
184
185 // =================================================================
186 // Accessors
187 //
188 // Generated message classes include type-safe templated wrappers around
189 // these methods. Generally you should use those rather than call these
190 // directly, unless you are doing low-level memory management.
191 //
192 // When calling any of these accessors, the extension number requested
193 // MUST exist in the DescriptorPool provided to the constructor. Otheriwse,
194 // the method will fail an assert. Normally, though, you would not call
195 // these directly; you would either call the generated accessors of your
196 // message class (e.g. GetExtension()) or you would call the accessors
197 // of the reflection interface. In both cases, it is impossible to
198 // trigger this assert failure: the generated accessors only accept
199 // linked-in extension types as parameters, while the Reflection interface
200 // requires you to provide the FieldDescriptor describing the extension.
201 //
202 // When calling any of these accessors, a protocol-compiler-generated
203 // implementation of the extension corresponding to the number MUST
204 // be linked in, and the FieldDescriptor used to refer to it MUST be
205 // the one generated by that linked-in code. Otherwise, the method will
206 // die on an assert failure. The message objects returned by the message
207 // accessors are guaranteed to be of the correct linked-in type.
208 //
209 // These methods pretty much match Reflection except that:
210 // - They're not virtual.
211 // - They identify fields by number rather than FieldDescriptors.
212 // - They identify enum values using integers rather than descriptors.
213 // - Strings provide Mutable() in addition to Set() accessors.
214
215 bool Has(int number) const;
216 int ExtensionSize(int number) const; // Size of a repeated extension.
217 void ClearExtension(int number);
218
219 // singular fields -------------------------------------------------
220
221 int32 GetInt32 (int number, int32 default_value) const;
222 int64 GetInt64 (int number, int64 default_value) const;
223 uint32 GetUInt32(int number, uint32 default_value) const;
224 uint64 GetUInt64(int number, uint64 default_value) const;
225 float GetFloat (int number, float default_value) const;
226 double GetDouble(int number, double default_value) const;
227 bool GetBool (int number, bool default_value) const;
228 int GetEnum (int number, int default_value) const;
229 const string & GetString (int number, const string& default_value) const;
230 const MessageLite& GetMessage(int number,
231 const MessageLite& default_value) const;
232 const MessageLite& GetMessage(int number, const Descriptor* message_type,
233 MessageFactory* factory) const;
234
235 // |descriptor| may be NULL so long as it is known that the descriptor for
236 // the extension lives in the same pool as the descriptor for the containing
237 // type.
238 #define desc const FieldDescriptor* descriptor // avoid line wrapping
239 void SetInt32 (int number, FieldType type, int32 value, desc);
240 void SetInt64 (int number, FieldType type, int64 value, desc);
241 void SetUInt32(int number, FieldType type, uint32 value, desc);
242 void SetUInt64(int number, FieldType type, uint64 value, desc);
243 void SetFloat (int number, FieldType type, float value, desc);
244 void SetDouble(int number, FieldType type, double value, desc);
245 void SetBool (int number, FieldType type, bool value, desc);
246 void SetEnum (int number, FieldType type, int value, desc);
247 void SetString(int number, FieldType type, const string& value, desc);
248 string * MutableString (int number, FieldType type, desc);
249 MessageLite* MutableMessage(int number, FieldType type,
250 const MessageLite& prototype, desc);
251 MessageLite* MutableMessage(const FieldDescriptor* decsriptor,
252 MessageFactory* factory);
253 #undef desc
254
255 // repeated fields -------------------------------------------------
256
257 int32 GetRepeatedInt32 (int number, int index) const;
258 int64 GetRepeatedInt64 (int number, int index) const;
259 uint32 GetRepeatedUInt32(int number, int index) const;
260 uint64 GetRepeatedUInt64(int number, int index) const;
261 float GetRepeatedFloat (int number, int index) const;
262 double GetRepeatedDouble(int number, int index) const;
263 bool GetRepeatedBool (int number, int index) const;
264 int GetRepeatedEnum (int number, int index) const;
265 const string & GetRepeatedString (int number, int index) const;
266 const MessageLite& GetRepeatedMessage(int number, int index) const;
267
268 void SetRepeatedInt32 (int number, int index, int32 value);
269 void SetRepeatedInt64 (int number, int index, int64 value);
270 void SetRepeatedUInt32(int number, int index, uint32 value);
271 void SetRepeatedUInt64(int number, int index, uint64 value);
272 void SetRepeatedFloat (int number, int index, float value);
273 void SetRepeatedDouble(int number, int index, double value);
274 void SetRepeatedBool (int number, int index, bool value);
275 void SetRepeatedEnum (int number, int index, int value);
276 void SetRepeatedString(int number, int index, const string& value);
277 string * MutableRepeatedString (int number, int index);
278 MessageLite* MutableRepeatedMessage(int number, int index);
279
280 #define desc const FieldDescriptor* descriptor // avoid line wrapping
281 void AddInt32 (int number, FieldType type, bool packed, int32 value, desc);
282 void AddInt64 (int number, FieldType type, bool packed, int64 value, desc);
283 void AddUInt32(int number, FieldType type, bool packed, uint32 value, desc);
284 void AddUInt64(int number, FieldType type, bool packed, uint64 value, desc);
285 void AddFloat (int number, FieldType type, bool packed, float value, desc);
286 void AddDouble(int number, FieldType type, bool packed, double value, desc);
287 void AddBool (int number, FieldType type, bool packed, bool value, desc);
288 void AddEnum (int number, FieldType type, bool packed, int value, desc);
289 void AddString(int number, FieldType type, const string& value, desc);
290 string * AddString (int number, FieldType type, desc);
291 MessageLite* AddMessage(int number, FieldType type,
292 const MessageLite& prototype, desc);
293 MessageLite* AddMessage(const FieldDescriptor* descriptor,
294 MessageFactory* factory);
295 #undef desc
296
297 void RemoveLast(int number);
298 void SwapElements(int number, int index1, int index2);
299
300 // -----------------------------------------------------------------
301 // TODO(kenton): Hardcore memory management accessors
302
303 // =================================================================
304 // convenience methods for implementing methods of Message
305 //
306 // These could all be implemented in terms of the other methods of this
307 // class, but providing them here helps keep the generated code size down.
308
309 void Clear();
310 void MergeFrom(const ExtensionSet& other);
311 void Swap(ExtensionSet* other);
312 bool IsInitialized() const;
313
314 // Parses a single extension from the input. The input should start out
315 // positioned immediately after the tag. |containing_type| is the default
316 // instance for the containing message; it is used only to look up the
317 // extension by number. See RegisterExtension(), above. Unlike the other
318 // methods of ExtensionSet, this only works for generated message types --
319 // it looks up extensions registered using RegisterExtension().
320 bool ParseField(uint32 tag, io::CodedInputStream* input,
321 ExtensionFinder* extension_finder,
322 FieldSkipper* field_skipper);
323
324 // Specific versions for lite or full messages (constructs the appropriate
325 // FieldSkipper automatically).
326 bool ParseField(uint32 tag, io::CodedInputStream* input,
327 const MessageLite* containing_type);
328 bool ParseField(uint32 tag, io::CodedInputStream* input,
329 const Message* containing_type,
330 UnknownFieldSet* unknown_fields);
331
332 // Parse an entire message in MessageSet format. Such messages have no
333 // fields, only extensions.
334 bool ParseMessageSet(io::CodedInputStream* input,
335 ExtensionFinder* extension_finder,
336 FieldSkipper* field_skipper);
337
338 // Specific versions for lite or full messages (constructs the appropriate
339 // FieldSkipper automatically).
340 bool ParseMessageSet(io::CodedInputStream* input,
341 const MessageLite* containing_type);
342 bool ParseMessageSet(io::CodedInputStream* input,
343 const Message* containing_type,
344 UnknownFieldSet* unknown_fields);
345
346 // Write all extension fields with field numbers in the range
347 // [start_field_number, end_field_number)
348 // to the output stream, using the cached sizes computed when ByteSize() was
349 // last called. Note that the range bounds are inclusive-exclusive.
350 void SerializeWithCachedSizes(int start_field_number,
351 int end_field_number,
352 io::CodedOutputStream* output) const;
353
354 // Same as SerializeWithCachedSizes, but without any bounds checking.
355 // The caller must ensure that target has sufficient capacity for the
356 // serialized extensions.
357 //
358 // Returns a pointer past the last written byte.
359 uint8* SerializeWithCachedSizesToArray(int start_field_number,
360 int end_field_number,
361 uint8* target) const;
362
363 // Like above but serializes in MessageSet format.
364 void SerializeMessageSetWithCachedSizes(io::CodedOutputStream* output) const;
365 uint8* SerializeMessageSetWithCachedSizesToArray(uint8* target) const;
366
367 // Returns the total serialized size of all the extensions.
368 int ByteSize() const;
369
370 // Like ByteSize() but uses MessageSet format.
371 int MessageSetByteSize() const;
372
373 // Returns (an estimate of) the total number of bytes used for storing the
374 // extensions in memory, excluding sizeof(*this). If the ExtensionSet is
375 // for a lite message (and thus possibly contains lite messages), the results
376 // are undefined (might work, might crash, might corrupt data, might not even
377 // be linked in). It's up to the protocol compiler to avoid calling this on
378 // such ExtensionSets (easy enough since lite messages don't implement
379 // SpaceUsed()).
380 int SpaceUsedExcludingSelf() const;
381
382 private:
383
384 struct Extension {
385 union {
386 int32 int32_value;
387 int64 int64_value;
388 uint32 uint32_value;
389 uint64 uint64_value;
390 float float_value;
391 double double_value;
392 bool bool_value;
393 int enum_value;
394 string* string_value;
395 MessageLite* message_value;
396
397 RepeatedField <int32 >* repeated_int32_value;
398 RepeatedField <int64 >* repeated_int64_value;
399 RepeatedField <uint32 >* repeated_uint32_value;
400 RepeatedField <uint64 >* repeated_uint64_value;
401 RepeatedField <float >* repeated_float_value;
402 RepeatedField <double >* repeated_double_value;
403 RepeatedField <bool >* repeated_bool_value;
404 RepeatedField <int >* repeated_enum_value;
405 RepeatedPtrField<string >* repeated_string_value;
406 RepeatedPtrField<MessageLite>* repeated_message_value;
407 };
408
409 FieldType type;
410 bool is_repeated;
411
412 // For singular types, indicates if the extension is "cleared". This
413 // happens when an extension is set and then later cleared by the caller.
414 // We want to keep the Extension object around for reuse, so instead of
415 // removing it from the map, we just set is_cleared = true. This has no
416 // meaning for repeated types; for those, the size of the RepeatedField
417 // simply becomes zero when cleared.
418 bool is_cleared;
419
420 // For repeated types, this indicates if the [packed=true] option is set.
421 bool is_packed;
422
423 // The descriptor for this extension, if one exists and is known. May be
424 // NULL. Must not be NULL if the descriptor for the extension does not
425 // live in the same pool as the descriptor for the containing type.
426 const FieldDescriptor* descriptor;
427
428 // For packed fields, the size of the packed data is recorded here when
429 // ByteSize() is called then used during serialization.
430 // TODO(kenton): Use atomic<int> when C++ supports it.
431 mutable int cached_size;
432
433 // Some helper methods for operations on a single Extension.
434 void SerializeFieldWithCachedSizes(
435 int number,
436 io::CodedOutputStream* output) const;
437 uint8* SerializeFieldWithCachedSizesToArray(
438 int number,
439 uint8* target) const;
440 void SerializeMessageSetItemWithCachedSizes(
441 int number,
442 io::CodedOutputStream* output) const;
443 uint8* SerializeMessageSetItemWithCachedSizesToArray(
444 int number,
445 uint8* target) const;
446 int ByteSize(int number) const;
447 int MessageSetItemByteSize(int number) const;
448 void Clear();
449 int GetSize() const;
450 void Free();
451 int SpaceUsedExcludingSelf() const;
452 };
453
454 // Gets the extension with the given number, creating it if it does not
455 // already exist. Returns true if the extension did not already exist.
456 bool MaybeNewExtension(int number, const FieldDescriptor* descriptor,
457 Extension** result);
458
459 // Parse a single MessageSet item -- called just after the item group start
460 // tag has been read.
461 bool ParseMessageSetItem(io::CodedInputStream* input,
462 ExtensionFinder* extension_finder,
463 FieldSkipper* field_skipper);
464
465
466 // Hack: RepeatedPtrFieldBase declares ExtensionSet as a friend. This
467 // friendship should automatically extend to ExtensionSet::Extension, but
468 // unfortunately some older compilers (e.g. GCC 3.4.4) do not implement this
469 // correctly. So, we must provide helpers for calling methods of that
470 // class.
471
472 // Defined in extension_set_heavy.cc.
473 static inline int RepeatedMessage_SpaceUsedExcludingSelf(
474 RepeatedPtrFieldBase* field);
475
476 // The Extension struct is small enough to be passed by value, so we use it
477 // directly as the value type in the map rather than use pointers. We use
478 // a map rather than hash_map here because we expect most ExtensionSets will
479 // only contain a small number of extensions whereas hash_map is optimized
480 // for 100 elements or more. Also, we want AppendToList() to order fields
481 // by field number.
482 map<int, Extension> extensions_;
483
484 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionSet);
485 };
486
487 // These are just for convenience...
SetString(int number,FieldType type,const string & value,const FieldDescriptor * descriptor)488 inline void ExtensionSet::SetString(int number, FieldType type,
489 const string& value,
490 const FieldDescriptor* descriptor) {
491 MutableString(number, type, descriptor)->assign(value);
492 }
SetRepeatedString(int number,int index,const string & value)493 inline void ExtensionSet::SetRepeatedString(int number, int index,
494 const string& value) {
495 MutableRepeatedString(number, index)->assign(value);
496 }
AddString(int number,FieldType type,const string & value,const FieldDescriptor * descriptor)497 inline void ExtensionSet::AddString(int number, FieldType type,
498 const string& value,
499 const FieldDescriptor* descriptor) {
500 AddString(number, type, descriptor)->assign(value);
501 }
502
503 // ===================================================================
504 // Glue for generated extension accessors
505
506 // -------------------------------------------------------------------
507 // Template magic
508
509 // First we have a set of classes representing "type traits" for different
510 // field types. A type traits class knows how to implement basic accessors
511 // for extensions of a particular type given an ExtensionSet. The signature
512 // for a type traits class looks like this:
513 //
514 // class TypeTraits {
515 // public:
516 // typedef ? ConstType;
517 // typedef ? MutableType;
518 //
519 // static inline ConstType Get(int number, const ExtensionSet& set);
520 // static inline void Set(int number, ConstType value, ExtensionSet* set);
521 // static inline MutableType Mutable(int number, ExtensionSet* set);
522 //
523 // // Variants for repeated fields.
524 // static inline ConstType Get(int number, const ExtensionSet& set,
525 // int index);
526 // static inline void Set(int number, int index,
527 // ConstType value, ExtensionSet* set);
528 // static inline MutableType Mutable(int number, int index,
529 // ExtensionSet* set);
530 // static inline void Add(int number, ConstType value, ExtensionSet* set);
531 // static inline MutableType Add(int number, ExtensionSet* set);
532 // };
533 //
534 // Not all of these methods make sense for all field types. For example, the
535 // "Mutable" methods only make sense for strings and messages, and the
536 // repeated methods only make sense for repeated types. So, each type
537 // traits class implements only the set of methods from this signature that it
538 // actually supports. This will cause a compiler error if the user tries to
539 // access an extension using a method that doesn't make sense for its type.
540 // For example, if "foo" is an extension of type "optional int32", then if you
541 // try to write code like:
542 // my_message.MutableExtension(foo)
543 // you will get a compile error because PrimitiveTypeTraits<int32> does not
544 // have a "Mutable()" method.
545
546 // -------------------------------------------------------------------
547 // PrimitiveTypeTraits
548
549 // Since the ExtensionSet has different methods for each primitive type,
550 // we must explicitly define the methods of the type traits class for each
551 // known type.
552 template <typename Type>
553 class PrimitiveTypeTraits {
554 public:
555 typedef Type ConstType;
556
557 static inline ConstType Get(int number, const ExtensionSet& set,
558 ConstType default_value);
559 static inline void Set(int number, FieldType field_type,
560 ConstType value, ExtensionSet* set);
561 };
562
563 template <typename Type>
564 class RepeatedPrimitiveTypeTraits {
565 public:
566 typedef Type ConstType;
567
568 static inline Type Get(int number, const ExtensionSet& set, int index);
569 static inline void Set(int number, int index, Type value, ExtensionSet* set);
570 static inline void Add(int number, FieldType field_type,
571 bool is_packed, Type value, ExtensionSet* set);
572 };
573
574 #define PROTOBUF_DEFINE_PRIMITIVE_TYPE(TYPE, METHOD) \
575 template<> inline TYPE PrimitiveTypeTraits<TYPE>::Get( \
576 int number, const ExtensionSet& set, TYPE default_value) { \
577 return set.Get##METHOD(number, default_value); \
578 } \
579 template<> inline void PrimitiveTypeTraits<TYPE>::Set( \
580 int number, FieldType field_type, TYPE value, ExtensionSet* set) { \
581 set->Set##METHOD(number, field_type, value, NULL); \
582 } \
583 \
584 template<> inline TYPE RepeatedPrimitiveTypeTraits<TYPE>::Get( \
585 int number, const ExtensionSet& set, int index) { \
586 return set.GetRepeated##METHOD(number, index); \
587 } \
588 template<> inline void RepeatedPrimitiveTypeTraits<TYPE>::Set( \
589 int number, int index, TYPE value, ExtensionSet* set) { \
590 set->SetRepeated##METHOD(number, index, value); \
591 } \
592 template<> inline void RepeatedPrimitiveTypeTraits<TYPE>::Add( \
593 int number, FieldType field_type, bool is_packed, \
594 TYPE value, ExtensionSet* set) { \
595 set->Add##METHOD(number, field_type, is_packed, value, NULL); \
596 }
597
PROTOBUF_DEFINE_PRIMITIVE_TYPE(int32,Int32)598 PROTOBUF_DEFINE_PRIMITIVE_TYPE( int32, Int32)
599 PROTOBUF_DEFINE_PRIMITIVE_TYPE( int64, Int64)
600 PROTOBUF_DEFINE_PRIMITIVE_TYPE(uint32, UInt32)
601 PROTOBUF_DEFINE_PRIMITIVE_TYPE(uint64, UInt64)
602 PROTOBUF_DEFINE_PRIMITIVE_TYPE( float, Float)
603 PROTOBUF_DEFINE_PRIMITIVE_TYPE(double, Double)
604 PROTOBUF_DEFINE_PRIMITIVE_TYPE( bool, Bool)
605
606 #undef PROTOBUF_DEFINE_PRIMITIVE_TYPE
607
608 // -------------------------------------------------------------------
609 // StringTypeTraits
610
611 // Strings support both Set() and Mutable().
612 class LIBPROTOBUF_EXPORT StringTypeTraits {
613 public:
614 typedef const string& ConstType;
615 typedef string* MutableType;
616
617 static inline const string& Get(int number, const ExtensionSet& set,
618 ConstType default_value) {
619 return set.GetString(number, default_value);
620 }
621 static inline void Set(int number, FieldType field_type,
622 const string& value, ExtensionSet* set) {
623 set->SetString(number, field_type, value, NULL);
624 }
625 static inline string* Mutable(int number, FieldType field_type,
626 ExtensionSet* set) {
627 return set->MutableString(number, field_type, NULL);
628 }
629 };
630
631 class LIBPROTOBUF_EXPORT RepeatedStringTypeTraits {
632 public:
633 typedef const string& ConstType;
634 typedef string* MutableType;
635
Get(int number,const ExtensionSet & set,int index)636 static inline const string& Get(int number, const ExtensionSet& set,
637 int index) {
638 return set.GetRepeatedString(number, index);
639 }
Set(int number,int index,const string & value,ExtensionSet * set)640 static inline void Set(int number, int index,
641 const string& value, ExtensionSet* set) {
642 set->SetRepeatedString(number, index, value);
643 }
Mutable(int number,int index,ExtensionSet * set)644 static inline string* Mutable(int number, int index, ExtensionSet* set) {
645 return set->MutableRepeatedString(number, index);
646 }
Add(int number,FieldType field_type,bool,const string & value,ExtensionSet * set)647 static inline void Add(int number, FieldType field_type,
648 bool /*is_packed*/, const string& value,
649 ExtensionSet* set) {
650 set->AddString(number, field_type, value, NULL);
651 }
Add(int number,FieldType field_type,ExtensionSet * set)652 static inline string* Add(int number, FieldType field_type,
653 ExtensionSet* set) {
654 return set->AddString(number, field_type, NULL);
655 }
656 };
657
658 // -------------------------------------------------------------------
659 // EnumTypeTraits
660
661 // ExtensionSet represents enums using integers internally, so we have to
662 // static_cast around.
663 template <typename Type, bool IsValid(int)>
664 class EnumTypeTraits {
665 public:
666 typedef Type ConstType;
667
Get(int number,const ExtensionSet & set,ConstType default_value)668 static inline ConstType Get(int number, const ExtensionSet& set,
669 ConstType default_value) {
670 return static_cast<Type>(set.GetEnum(number, default_value));
671 }
Set(int number,FieldType field_type,ConstType value,ExtensionSet * set)672 static inline void Set(int number, FieldType field_type,
673 ConstType value, ExtensionSet* set) {
674 GOOGLE_DCHECK(IsValid(value));
675 set->SetEnum(number, field_type, value, NULL);
676 }
677 };
678
679 template <typename Type, bool IsValid(int)>
680 class RepeatedEnumTypeTraits {
681 public:
682 typedef Type ConstType;
683
Get(int number,const ExtensionSet & set,int index)684 static inline ConstType Get(int number, const ExtensionSet& set, int index) {
685 return static_cast<Type>(set.GetRepeatedEnum(number, index));
686 }
Set(int number,int index,ConstType value,ExtensionSet * set)687 static inline void Set(int number, int index,
688 ConstType value, ExtensionSet* set) {
689 GOOGLE_DCHECK(IsValid(value));
690 set->SetRepeatedEnum(number, index, value);
691 }
Add(int number,FieldType field_type,bool is_packed,ConstType value,ExtensionSet * set)692 static inline void Add(int number, FieldType field_type,
693 bool is_packed, ConstType value, ExtensionSet* set) {
694 GOOGLE_DCHECK(IsValid(value));
695 set->AddEnum(number, field_type, is_packed, value, NULL);
696 }
697 };
698
699 // -------------------------------------------------------------------
700 // MessageTypeTraits
701
702 // ExtensionSet guarantees that when manipulating extensions with message
703 // types, the implementation used will be the compiled-in class representing
704 // that type. So, we can static_cast down to the exact type we expect.
705 template <typename Type>
706 class MessageTypeTraits {
707 public:
708 typedef const Type& ConstType;
709 typedef Type* MutableType;
710
Get(int number,const ExtensionSet & set,ConstType default_value)711 static inline ConstType Get(int number, const ExtensionSet& set,
712 ConstType default_value) {
713 return static_cast<const Type&>(
714 set.GetMessage(number, default_value));
715 }
Mutable(int number,FieldType field_type,ExtensionSet * set)716 static inline MutableType Mutable(int number, FieldType field_type,
717 ExtensionSet* set) {
718 return static_cast<Type*>(
719 set->MutableMessage(number, field_type, Type::default_instance(), NULL));
720 }
721 };
722
723 template <typename Type>
724 class RepeatedMessageTypeTraits {
725 public:
726 typedef const Type& ConstType;
727 typedef Type* MutableType;
728
Get(int number,const ExtensionSet & set,int index)729 static inline ConstType Get(int number, const ExtensionSet& set, int index) {
730 return static_cast<const Type&>(set.GetRepeatedMessage(number, index));
731 }
Mutable(int number,int index,ExtensionSet * set)732 static inline MutableType Mutable(int number, int index, ExtensionSet* set) {
733 return static_cast<Type*>(set->MutableRepeatedMessage(number, index));
734 }
Add(int number,FieldType field_type,ExtensionSet * set)735 static inline MutableType Add(int number, FieldType field_type,
736 ExtensionSet* set) {
737 return static_cast<Type*>(
738 set->AddMessage(number, field_type, Type::default_instance(), NULL));
739 }
740 };
741
742 // -------------------------------------------------------------------
743 // ExtensionIdentifier
744
745 // This is the type of actual extension objects. E.g. if you have:
746 // extends Foo with optional int32 bar = 1234;
747 // then "bar" will be defined in C++ as:
748 // ExtensionIdentifier<Foo, PrimitiveTypeTraits<int32>, 1, false> bar(1234);
749 //
750 // Note that we could, in theory, supply the field number as a template
751 // parameter, and thus make an instance of ExtensionIdentifier have no
752 // actual contents. However, if we did that, then using at extension
753 // identifier would not necessarily cause the compiler to output any sort
754 // of reference to any simple defined in the extension's .pb.o file. Some
755 // linkers will actually drop object files that are not explicitly referenced,
756 // but that would be bad because it would cause this extension to not be
757 // registered at static initialization, and therefore using it would crash.
758
759 template <typename ExtendeeType, typename TypeTraitsType,
760 FieldType field_type, bool is_packed>
761 class ExtensionIdentifier {
762 public:
763 typedef TypeTraitsType TypeTraits;
764 typedef ExtendeeType Extendee;
765
ExtensionIdentifier(int number,typename TypeTraits::ConstType default_value)766 ExtensionIdentifier(int number, typename TypeTraits::ConstType default_value)
767 : number_(number), default_value_(default_value) {}
number()768 inline int number() const { return number_; }
default_value()769 typename TypeTraits::ConstType default_value() const {
770 return default_value_;
771 }
772
773 private:
774 const int number_;
775 typename TypeTraits::ConstType default_value_;
776 };
777
778 // -------------------------------------------------------------------
779 // Generated accessors
780
781 // This macro should be expanded in the context of a generated type which
782 // has extensions.
783 //
784 // We use "_proto_TypeTraits" as a type name below because "TypeTraits"
785 // causes problems if the class has a nested message or enum type with that
786 // name and "_TypeTraits" is technically reserved for the C++ library since
787 // it starts with an underscore followed by a capital letter.
788 #define GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(CLASSNAME) \
789 /* Has, Size, Clear */ \
790 template <typename _proto_TypeTraits, \
791 ::google::protobuf::internal::FieldType field_type, \
792 bool is_packed> \
793 inline bool HasExtension( \
794 const ::google::protobuf::internal::ExtensionIdentifier< \
795 CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id) const { \
796 return _extensions_.Has(id.number()); \
797 } \
798 \
799 template <typename _proto_TypeTraits, \
800 ::google::protobuf::internal::FieldType field_type, \
801 bool is_packed> \
802 inline void ClearExtension( \
803 const ::google::protobuf::internal::ExtensionIdentifier< \
804 CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id) { \
805 _extensions_.ClearExtension(id.number()); \
806 } \
807 \
808 template <typename _proto_TypeTraits, \
809 ::google::protobuf::internal::FieldType field_type, \
810 bool is_packed> \
811 inline int ExtensionSize( \
812 const ::google::protobuf::internal::ExtensionIdentifier< \
813 CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id) const { \
814 return _extensions_.ExtensionSize(id.number()); \
815 } \
816 \
817 /* Singular accessors */ \
818 template <typename _proto_TypeTraits, \
819 ::google::protobuf::internal::FieldType field_type, \
820 bool is_packed> \
821 inline typename _proto_TypeTraits::ConstType GetExtension( \
822 const ::google::protobuf::internal::ExtensionIdentifier< \
823 CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id) const { \
824 return _proto_TypeTraits::Get(id.number(), _extensions_, \
825 id.default_value()); \
826 } \
827 \
828 template <typename _proto_TypeTraits, \
829 ::google::protobuf::internal::FieldType field_type, \
830 bool is_packed> \
831 inline typename _proto_TypeTraits::MutableType MutableExtension( \
832 const ::google::protobuf::internal::ExtensionIdentifier< \
833 CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id) { \
834 return _proto_TypeTraits::Mutable(id.number(), field_type, &_extensions_);\
835 } \
836 \
837 template <typename _proto_TypeTraits, \
838 ::google::protobuf::internal::FieldType field_type, \
839 bool is_packed> \
840 inline void SetExtension( \
841 const ::google::protobuf::internal::ExtensionIdentifier< \
842 CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id, \
843 typename _proto_TypeTraits::ConstType value) { \
844 _proto_TypeTraits::Set(id.number(), field_type, value, &_extensions_); \
845 } \
846 \
847 /* Repeated accessors */ \
848 template <typename _proto_TypeTraits, \
849 ::google::protobuf::internal::FieldType field_type, \
850 bool is_packed> \
851 inline typename _proto_TypeTraits::ConstType GetExtension( \
852 const ::google::protobuf::internal::ExtensionIdentifier< \
853 CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id, \
854 int index) const { \
855 return _proto_TypeTraits::Get(id.number(), _extensions_, index); \
856 } \
857 \
858 template <typename _proto_TypeTraits, \
859 ::google::protobuf::internal::FieldType field_type, \
860 bool is_packed> \
861 inline typename _proto_TypeTraits::MutableType MutableExtension( \
862 const ::google::protobuf::internal::ExtensionIdentifier< \
863 CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id, \
864 int index) { \
865 return _proto_TypeTraits::Mutable(id.number(), index, &_extensions_); \
866 } \
867 \
868 template <typename _proto_TypeTraits, \
869 ::google::protobuf::internal::FieldType field_type, \
870 bool is_packed> \
871 inline void SetExtension( \
872 const ::google::protobuf::internal::ExtensionIdentifier< \
873 CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id, \
874 int index, typename _proto_TypeTraits::ConstType value) { \
875 _proto_TypeTraits::Set(id.number(), index, value, &_extensions_); \
876 } \
877 \
878 template <typename _proto_TypeTraits, \
879 ::google::protobuf::internal::FieldType field_type, \
880 bool is_packed> \
881 inline typename _proto_TypeTraits::MutableType AddExtension( \
882 const ::google::protobuf::internal::ExtensionIdentifier< \
883 CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id) { \
884 return _proto_TypeTraits::Add(id.number(), field_type, &_extensions_); \
885 } \
886 \
887 template <typename _proto_TypeTraits, \
888 ::google::protobuf::internal::FieldType field_type, \
889 bool is_packed> \
890 inline void AddExtension( \
891 const ::google::protobuf::internal::ExtensionIdentifier< \
892 CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id, \
893 typename _proto_TypeTraits::ConstType value) { \
894 _proto_TypeTraits::Add(id.number(), field_type, is_packed, \
895 value, &_extensions_); \
896 }
897
898 } // namespace internal
899 } // namespace protobuf
900
901 } // namespace google
902 #endif // GOOGLE_PROTOBUF_EXTENSION_SET_H__
903