• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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