PageRenderTime 46ms CodeModel.GetById 2ms app.highlight 36ms RepoModel.GetById 1ms app.codeStats 0ms

/thirdparty/breakpad/third_party/protobuf/protobuf/src/google/protobuf/extension_set.h

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