BWAPI
Undermind/proxy/cpp/include/google/protobuf/extension_set.h
Go to the documentation of this file.
00001 // Protocol Buffers - Google's data interchange format
00002 // Copyright 2008 Google Inc.  All rights reserved.
00003 // http://code.google.com/p/protobuf/
00004 //
00005 // Redistribution and use in source and binary forms, with or without
00006 // modification, are permitted provided that the following conditions are
00007 // met:
00008 //
00009 //     * Redistributions of source code must retain the above copyright
00010 // notice, this list of conditions and the following disclaimer.
00011 //     * Redistributions in binary form must reproduce the above
00012 // copyright notice, this list of conditions and the following disclaimer
00013 // in the documentation and/or other materials provided with the
00014 // distribution.
00015 //     * Neither the name of Google Inc. nor the names of its
00016 // contributors may be used to endorse or promote products derived from
00017 // this software without specific prior written permission.
00018 //
00019 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00020 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00021 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00022 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
00023 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00024 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00025 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00026 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00027 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00028 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00029 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00030 
00031 // Author: kenton@google.com (Kenton Varda)
00032 //  Based on original Protocol Buffers design by
00033 //  Sanjay Ghemawat, Jeff Dean, and others.
00034 //
00035 // This header is logically internal, but is made public because it is used
00036 // from protocol-compiler-generated code, which may reside in other components.
00037 
00038 #ifndef GOOGLE_PROTOBUF_EXTENSION_SET_H__
00039 #define GOOGLE_PROTOBUF_EXTENSION_SET_H__
00040 
00041 #include <vector>
00042 #include <stack>
00043 #include <map>
00044 #include <utility>
00045 #include <string>
00046 
00047 #include <google/protobuf/stubs/common.h>
00048 
00049 namespace google {
00050 
00051 namespace protobuf {
00052   class Descriptor;                                    // descriptor.h
00053   class FieldDescriptor;                               // descriptor.h
00054   class DescriptorPool;                                // descriptor.h
00055   class MessageLite;                                   // message_lite.h
00056   class Message;                                       // message.h
00057   class MessageFactory;                                // message.h
00058   class UnknownFieldSet;                               // unknown_field_set.h
00059   namespace io {
00060     class CodedInputStream;                              // coded_stream.h
00061     class CodedOutputStream;                             // coded_stream.h
00062   }
00063   namespace internal {
00064     class FieldSkipper;                                  // wire_format_lite.h
00065     class RepeatedPtrFieldBase;                          // repeated_field.h
00066   }
00067   template <typename Element> class RepeatedField;     // repeated_field.h
00068   template <typename Element> class RepeatedPtrField;  // repeated_field.h
00069 }
00070 
00071 namespace protobuf {
00072 namespace internal {
00073 
00074 // Used to store values of type WireFormatLite::FieldType without having to
00075 // #include wire_format_lite.h.  Also, ensures that we use only one byte to
00076 // store these values, which is important to keep the layout of
00077 // ExtensionSet::Extension small.
00078 typedef uint8 FieldType;
00079 
00080 // A function which, given an integer value, returns true if the number
00081 // matches one of the defined values for the corresponding enum type.  This
00082 // is used with RegisterEnumExtension, below.
00083 typedef bool EnumValidityFunc(int number);
00084 
00085 // Version of the above which takes an argument.  This is needed to deal with
00086 // extensions that are not compiled in.
00087 typedef bool EnumValidityFuncWithArg(const void* arg, int number);
00088 
00089 // Information about a registered extension.
00090 struct ExtensionInfo {
00091   inline ExtensionInfo() {}
00092   inline ExtensionInfo(FieldType type, bool is_repeated, bool is_packed)
00093       : type(type), is_repeated(is_repeated), is_packed(is_packed),
00094         descriptor(NULL) {}
00095 
00096   FieldType type;
00097   bool is_repeated;
00098   bool is_packed;
00099 
00100   struct EnumValidityCheck {
00101     EnumValidityFuncWithArg* func;
00102     const void* arg;
00103   };
00104 
00105   union {
00106     EnumValidityCheck enum_validity_check;
00107     const MessageLite* message_prototype;
00108   };
00109 
00110   // The descriptor for this extension, if one exists and is known.  May be
00111   // NULL.  Must not be NULL if the descriptor for the extension does not
00112   // live in the same pool as the descriptor for the containing type.
00113   const FieldDescriptor* descriptor;
00114 };
00115 
00116 // Abstract interface for an object which looks up extension definitions.  Used
00117 // when parsing.
00118 class LIBPROTOBUF_EXPORT ExtensionFinder {
00119  public:
00120   virtual ~ExtensionFinder();
00121 
00122   // Find the extension with the given containing type and number.
00123   virtual bool Find(int number, ExtensionInfo* output) = 0;
00124 };
00125 
00126 // Implementation of ExtensionFinder which finds extensions defined in .proto
00127 // files which have been compiled into the binary.
00128 class LIBPROTOBUF_EXPORT GeneratedExtensionFinder : public ExtensionFinder {
00129  public:
00130   GeneratedExtensionFinder(const MessageLite* containing_type)
00131       : containing_type_(containing_type) {}
00132   virtual ~GeneratedExtensionFinder() {}
00133 
00134   // Returns true and fills in *output if found, otherwise returns false.
00135   virtual bool Find(int number, ExtensionInfo* output);
00136 
00137  private:
00138   const MessageLite* containing_type_;
00139 };
00140 
00141 // Note:  extension_set_heavy.cc defines DescriptorPoolExtensionFinder for
00142 // finding extensions from a DescriptorPool.
00143 
00144 // This is an internal helper class intended for use within the protocol buffer
00145 // library and generated classes.  Clients should not use it directly.  Instead,
00146 // use the generated accessors such as GetExtension() of the class being
00147 // extended.
00148 //
00149 // This class manages extensions for a protocol message object.  The
00150 // message's HasExtension(), GetExtension(), MutableExtension(), and
00151 // ClearExtension() methods are just thin wrappers around the embedded
00152 // ExtensionSet.  When parsing, if a tag number is encountered which is
00153 // inside one of the message type's extension ranges, the tag is passed
00154 // off to the ExtensionSet for parsing.  Etc.
00155 class LIBPROTOBUF_EXPORT ExtensionSet {
00156  public:
00157   ExtensionSet();
00158   ~ExtensionSet();
00159 
00160   // These are called at startup by protocol-compiler-generated code to
00161   // register known extensions.  The registrations are used by ParseField()
00162   // to look up extensions for parsed field numbers.  Note that dynamic parsing
00163   // does not use ParseField(); only protocol-compiler-generated parsing
00164   // methods do.
00165   static void RegisterExtension(const MessageLite* containing_type,
00166                                 int number, FieldType type,
00167                                 bool is_repeated, bool is_packed);
00168   static void RegisterEnumExtension(const MessageLite* containing_type,
00169                                     int number, FieldType type,
00170                                     bool is_repeated, bool is_packed,
00171                                     EnumValidityFunc* is_valid);
00172   static void RegisterMessageExtension(const MessageLite* containing_type,
00173                                        int number, FieldType type,
00174                                        bool is_repeated, bool is_packed,
00175                                        const MessageLite* prototype);
00176 
00177   // =================================================================
00178 
00179   // Add all fields which are currently present to the given vector.  This
00180   // is useful to implement Reflection::ListFields().
00181   void AppendToList(const Descriptor* containing_type,
00182                     const DescriptorPool* pool,
00183                     vector<const FieldDescriptor*>* output) const;
00184 
00185   // =================================================================
00186   // Accessors
00187   //
00188   // Generated message classes include type-safe templated wrappers around
00189   // these methods.  Generally you should use those rather than call these
00190   // directly, unless you are doing low-level memory management.
00191   //
00192   // When calling any of these accessors, the extension number requested
00193   // MUST exist in the DescriptorPool provided to the constructor.  Otheriwse,
00194   // the method will fail an assert.  Normally, though, you would not call
00195   // these directly; you would either call the generated accessors of your
00196   // message class (e.g. GetExtension()) or you would call the accessors
00197   // of the reflection interface.  In both cases, it is impossible to
00198   // trigger this assert failure:  the generated accessors only accept
00199   // linked-in extension types as parameters, while the Reflection interface
00200   // requires you to provide the FieldDescriptor describing the extension.
00201   //
00202   // When calling any of these accessors, a protocol-compiler-generated
00203   // implementation of the extension corresponding to the number MUST
00204   // be linked in, and the FieldDescriptor used to refer to it MUST be
00205   // the one generated by that linked-in code.  Otherwise, the method will
00206   // die on an assert failure.  The message objects returned by the message
00207   // accessors are guaranteed to be of the correct linked-in type.
00208   //
00209   // These methods pretty much match Reflection except that:
00210   // - They're not virtual.
00211   // - They identify fields by number rather than FieldDescriptors.
00212   // - They identify enum values using integers rather than descriptors.
00213   // - Strings provide Mutable() in addition to Set() accessors.
00214 
00215   bool Has(int number) const;
00216   int ExtensionSize(int number) const;   // Size of a repeated extension.
00217   void ClearExtension(int number);
00218 
00219   // singular fields -------------------------------------------------
00220 
00221   int32  GetInt32 (int number, int32  default_value) const;
00222   int64  GetInt64 (int number, int64  default_value) const;
00223   uint32 GetUInt32(int number, uint32 default_value) const;
00224   uint64 GetUInt64(int number, uint64 default_value) const;
00225   float  GetFloat (int number, float  default_value) const;
00226   double GetDouble(int number, double default_value) const;
00227   bool   GetBool  (int number, bool   default_value) const;
00228   int    GetEnum  (int number, int    default_value) const;
00229   const string & GetString (int number, const string&  default_value) const;
00230   const MessageLite& GetMessage(int number,
00231                                 const MessageLite& default_value) const;
00232   const MessageLite& GetMessage(int number, const Descriptor* message_type,
00233                                 MessageFactory* factory) const;
00234 
00235   // |descriptor| may be NULL so long as it is known that the descriptor for
00236   // the extension lives in the same pool as the descriptor for the containing
00237   // type.
00238 #define desc const FieldDescriptor* descriptor  // avoid line wrapping
00239   void SetInt32 (int number, FieldType type, int32  value, desc);
00240   void SetInt64 (int number, FieldType type, int64  value, desc);
00241   void SetUInt32(int number, FieldType type, uint32 value, desc);
00242   void SetUInt64(int number, FieldType type, uint64 value, desc);
00243   void SetFloat (int number, FieldType type, float  value, desc);
00244   void SetDouble(int number, FieldType type, double value, desc);
00245   void SetBool  (int number, FieldType type, bool   value, desc);
00246   void SetEnum  (int number, FieldType type, int    value, desc);
00247   void SetString(int number, FieldType type, const string& value, desc);
00248   string * MutableString (int number, FieldType type, desc);
00249   MessageLite* MutableMessage(int number, FieldType type,
00250                               const MessageLite& prototype, desc);
00251   MessageLite* MutableMessage(const FieldDescriptor* decsriptor,
00252                               MessageFactory* factory);
00253 #undef desc
00254 
00255   // repeated fields -------------------------------------------------
00256 
00257   int32  GetRepeatedInt32 (int number, int index) const;
00258   int64  GetRepeatedInt64 (int number, int index) const;
00259   uint32 GetRepeatedUInt32(int number, int index) const;
00260   uint64 GetRepeatedUInt64(int number, int index) const;
00261   float  GetRepeatedFloat (int number, int index) const;
00262   double GetRepeatedDouble(int number, int index) const;
00263   bool   GetRepeatedBool  (int number, int index) const;
00264   int    GetRepeatedEnum  (int number, int index) const;
00265   const string & GetRepeatedString (int number, int index) const;
00266   const MessageLite& GetRepeatedMessage(int number, int index) const;
00267 
00268   void SetRepeatedInt32 (int number, int index, int32  value);
00269   void SetRepeatedInt64 (int number, int index, int64  value);
00270   void SetRepeatedUInt32(int number, int index, uint32 value);
00271   void SetRepeatedUInt64(int number, int index, uint64 value);
00272   void SetRepeatedFloat (int number, int index, float  value);
00273   void SetRepeatedDouble(int number, int index, double value);
00274   void SetRepeatedBool  (int number, int index, bool   value);
00275   void SetRepeatedEnum  (int number, int index, int    value);
00276   void SetRepeatedString(int number, int index, const string& value);
00277   string * MutableRepeatedString (int number, int index);
00278   MessageLite* MutableRepeatedMessage(int number, int index);
00279 
00280 #define desc const FieldDescriptor* descriptor  // avoid line wrapping
00281   void AddInt32 (int number, FieldType type, bool packed, int32  value, desc);
00282   void AddInt64 (int number, FieldType type, bool packed, int64  value, desc);
00283   void AddUInt32(int number, FieldType type, bool packed, uint32 value, desc);
00284   void AddUInt64(int number, FieldType type, bool packed, uint64 value, desc);
00285   void AddFloat (int number, FieldType type, bool packed, float  value, desc);
00286   void AddDouble(int number, FieldType type, bool packed, double value, desc);
00287   void AddBool  (int number, FieldType type, bool packed, bool   value, desc);
00288   void AddEnum  (int number, FieldType type, bool packed, int    value, desc);
00289   void AddString(int number, FieldType type, const string& value, desc);
00290   string * AddString (int number, FieldType type, desc);
00291   MessageLite* AddMessage(int number, FieldType type,
00292                           const MessageLite& prototype, desc);
00293   MessageLite* AddMessage(const FieldDescriptor* descriptor,
00294                           MessageFactory* factory);
00295 #undef desc
00296 
00297   void RemoveLast(int number);
00298   void SwapElements(int number, int index1, int index2);
00299 
00300   // -----------------------------------------------------------------
00301   // TODO(kenton):  Hardcore memory management accessors
00302 
00303   // =================================================================
00304   // convenience methods for implementing methods of Message
00305   //
00306   // These could all be implemented in terms of the other methods of this
00307   // class, but providing them here helps keep the generated code size down.
00308 
00309   void Clear();
00310   void MergeFrom(const ExtensionSet& other);
00311   void Swap(ExtensionSet* other);
00312   bool IsInitialized() const;
00313 
00314   // Parses a single extension from the input.  The input should start out
00315   // positioned immediately after the tag.  |containing_type| is the default
00316   // instance for the containing message; it is used only to look up the
00317   // extension by number.  See RegisterExtension(), above.  Unlike the other
00318   // methods of ExtensionSet, this only works for generated message types --
00319   // it looks up extensions registered using RegisterExtension().
00320   bool ParseField(uint32 tag, io::CodedInputStream* input,
00321                   ExtensionFinder* extension_finder,
00322                   FieldSkipper* field_skipper);
00323 
00324   // Specific versions for lite or full messages (constructs the appropriate
00325   // FieldSkipper automatically).
00326   bool ParseField(uint32 tag, io::CodedInputStream* input,
00327                   const MessageLite* containing_type);
00328   bool ParseField(uint32 tag, io::CodedInputStream* input,
00329                   const Message* containing_type,
00330                   UnknownFieldSet* unknown_fields);
00331 
00332   // Parse an entire message in MessageSet format.  Such messages have no
00333   // fields, only extensions.
00334   bool ParseMessageSet(io::CodedInputStream* input,
00335                        ExtensionFinder* extension_finder,
00336                        FieldSkipper* field_skipper);
00337 
00338   // Specific versions for lite or full messages (constructs the appropriate
00339   // FieldSkipper automatically).
00340   bool ParseMessageSet(io::CodedInputStream* input,
00341                        const MessageLite* containing_type);
00342   bool ParseMessageSet(io::CodedInputStream* input,
00343                        const Message* containing_type,
00344                        UnknownFieldSet* unknown_fields);
00345 
00346   // Write all extension fields with field numbers in the range
00347   //   [start_field_number, end_field_number)
00348   // to the output stream, using the cached sizes computed when ByteSize() was
00349   // last called.  Note that the range bounds are inclusive-exclusive.
00350   void SerializeWithCachedSizes(int start_field_number,
00351                                 int end_field_number,
00352                                 io::CodedOutputStream* output) const;
00353 
00354   // Same as SerializeWithCachedSizes, but without any bounds checking.
00355   // The caller must ensure that target has sufficient capacity for the
00356   // serialized extensions.
00357   //
00358   // Returns a pointer past the last written byte.
00359   uint8* SerializeWithCachedSizesToArray(int start_field_number,
00360                                          int end_field_number,
00361                                          uint8* target) const;
00362 
00363   // Like above but serializes in MessageSet format.
00364   void SerializeMessageSetWithCachedSizes(io::CodedOutputStream* output) const;
00365   uint8* SerializeMessageSetWithCachedSizesToArray(uint8* target) const;
00366 
00367   // Returns the total serialized size of all the extensions.
00368   int ByteSize() const;
00369 
00370   // Like ByteSize() but uses MessageSet format.
00371   int MessageSetByteSize() const;
00372 
00373   // Returns (an estimate of) the total number of bytes used for storing the
00374   // extensions in memory, excluding sizeof(*this).  If the ExtensionSet is
00375   // for a lite message (and thus possibly contains lite messages), the results
00376   // are undefined (might work, might crash, might corrupt data, might not even
00377   // be linked in).  It's up to the protocol compiler to avoid calling this on
00378   // such ExtensionSets (easy enough since lite messages don't implement
00379   // SpaceUsed()).
00380   int SpaceUsedExcludingSelf() const;
00381 
00382  private:
00383 
00384   struct Extension {
00385     union {
00386       int32        int32_value;
00387       int64        int64_value;
00388       uint32       uint32_value;
00389       uint64       uint64_value;
00390       float        float_value;
00391       double       double_value;
00392       bool         bool_value;
00393       int          enum_value;
00394       string*      string_value;
00395       MessageLite* message_value;
00396 
00397       RepeatedField   <int32      >* repeated_int32_value;
00398       RepeatedField   <int64      >* repeated_int64_value;
00399       RepeatedField   <uint32     >* repeated_uint32_value;
00400       RepeatedField   <uint64     >* repeated_uint64_value;
00401       RepeatedField   <float      >* repeated_float_value;
00402       RepeatedField   <double     >* repeated_double_value;
00403       RepeatedField   <bool       >* repeated_bool_value;
00404       RepeatedField   <int        >* repeated_enum_value;
00405       RepeatedPtrField<string     >* repeated_string_value;
00406       RepeatedPtrField<MessageLite>* repeated_message_value;
00407     };
00408 
00409     FieldType type;
00410     bool is_repeated;
00411 
00412     // For singular types, indicates if the extension is "cleared".  This
00413     // happens when an extension is set and then later cleared by the caller.
00414     // We want to keep the Extension object around for reuse, so instead of
00415     // removing it from the map, we just set is_cleared = true.  This has no
00416     // meaning for repeated types; for those, the size of the RepeatedField
00417     // simply becomes zero when cleared.
00418     bool is_cleared;
00419 
00420     // For repeated types, this indicates if the [packed=true] option is set.
00421     bool is_packed;
00422 
00423     // The descriptor for this extension, if one exists and is known.  May be
00424     // NULL.  Must not be NULL if the descriptor for the extension does not
00425     // live in the same pool as the descriptor for the containing type.
00426     const FieldDescriptor* descriptor;
00427 
00428     // For packed fields, the size of the packed data is recorded here when
00429     // ByteSize() is called then used during serialization.
00430     // TODO(kenton):  Use atomic<int> when C++ supports it.
00431     mutable int cached_size;
00432 
00433     // Some helper methods for operations on a single Extension.
00434     void SerializeFieldWithCachedSizes(
00435         int number,
00436         io::CodedOutputStream* output) const;
00437     uint8* SerializeFieldWithCachedSizesToArray(
00438         int number,
00439         uint8* target) const;
00440     void SerializeMessageSetItemWithCachedSizes(
00441         int number,
00442         io::CodedOutputStream* output) const;
00443     uint8* SerializeMessageSetItemWithCachedSizesToArray(
00444         int number,
00445         uint8* target) const;
00446     int ByteSize(int number) const;
00447     int MessageSetItemByteSize(int number) const;
00448     void Clear();
00449     int GetSize() const;
00450     void Free();
00451     int SpaceUsedExcludingSelf() const;
00452   };
00453 
00454   // Gets the extension with the given number, creating it if it does not
00455   // already exist.  Returns true if the extension did not already exist.
00456   bool MaybeNewExtension(int number, const FieldDescriptor* descriptor,
00457                          Extension** result);
00458 
00459   // Parse a single MessageSet item -- called just after the item group start
00460   // tag has been read.
00461   bool ParseMessageSetItem(io::CodedInputStream* input,
00462                            ExtensionFinder* extension_finder,
00463                            FieldSkipper* field_skipper);
00464 
00465 
00466   // Hack:  RepeatedPtrFieldBase declares ExtensionSet as a friend.  This
00467   //   friendship should automatically extend to ExtensionSet::Extension, but
00468   //   unfortunately some older compilers (e.g. GCC 3.4.4) do not implement this
00469   //   correctly.  So, we must provide helpers for calling methods of that
00470   //   class.
00471 
00472   // Defined in extension_set_heavy.cc.
00473   static inline int RepeatedMessage_SpaceUsedExcludingSelf(
00474       RepeatedPtrFieldBase* field);
00475 
00476   // The Extension struct is small enough to be passed by value, so we use it
00477   // directly as the value type in the map rather than use pointers.  We use
00478   // a map rather than hash_map here because we expect most ExtensionSets will
00479   // only contain a small number of extensions whereas hash_map is optimized
00480   // for 100 elements or more.  Also, we want AppendToList() to order fields
00481   // by field number.
00482   map<int, Extension> extensions_;
00483 
00484   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionSet);
00485 };
00486 
00487 // These are just for convenience...
00488 inline void ExtensionSet::SetString(int number, FieldType type,
00489                                     const string& value,
00490                                     const FieldDescriptor* descriptor) {
00491   MutableString(number, type, descriptor)->assign(value);
00492 }
00493 inline void ExtensionSet::SetRepeatedString(int number, int index,
00494                                             const string& value) {
00495   MutableRepeatedString(number, index)->assign(value);
00496 }
00497 inline void ExtensionSet::AddString(int number, FieldType type,
00498                                     const string& value,
00499                                     const FieldDescriptor* descriptor) {
00500   AddString(number, type, descriptor)->assign(value);
00501 }
00502 
00503 // ===================================================================
00504 // Glue for generated extension accessors
00505 
00506 // -------------------------------------------------------------------
00507 // Template magic
00508 
00509 // First we have a set of classes representing "type traits" for different
00510 // field types.  A type traits class knows how to implement basic accessors
00511 // for extensions of a particular type given an ExtensionSet.  The signature
00512 // for a type traits class looks like this:
00513 //
00514 //   class TypeTraits {
00515 //    public:
00516 //     typedef ? ConstType;
00517 //     typedef ? MutableType;
00518 //
00519 //     static inline ConstType Get(int number, const ExtensionSet& set);
00520 //     static inline void Set(int number, ConstType value, ExtensionSet* set);
00521 //     static inline MutableType Mutable(int number, ExtensionSet* set);
00522 //
00523 //     // Variants for repeated fields.
00524 //     static inline ConstType Get(int number, const ExtensionSet& set,
00525 //                                 int index);
00526 //     static inline void Set(int number, int index,
00527 //                            ConstType value, ExtensionSet* set);
00528 //     static inline MutableType Mutable(int number, int index,
00529 //                                       ExtensionSet* set);
00530 //     static inline void Add(int number, ConstType value, ExtensionSet* set);
00531 //     static inline MutableType Add(int number, ExtensionSet* set);
00532 //   };
00533 //
00534 // Not all of these methods make sense for all field types.  For example, the
00535 // "Mutable" methods only make sense for strings and messages, and the
00536 // repeated methods only make sense for repeated types.  So, each type
00537 // traits class implements only the set of methods from this signature that it
00538 // actually supports.  This will cause a compiler error if the user tries to
00539 // access an extension using a method that doesn't make sense for its type.
00540 // For example, if "foo" is an extension of type "optional int32", then if you
00541 // try to write code like:
00542 //   my_message.MutableExtension(foo)
00543 // you will get a compile error because PrimitiveTypeTraits<int32> does not
00544 // have a "Mutable()" method.
00545 
00546 // -------------------------------------------------------------------
00547 // PrimitiveTypeTraits
00548 
00549 // Since the ExtensionSet has different methods for each primitive type,
00550 // we must explicitly define the methods of the type traits class for each
00551 // known type.
00552 template <typename Type>
00553 class PrimitiveTypeTraits {
00554  public:
00555   typedef Type ConstType;
00556 
00557   static inline ConstType Get(int number, const ExtensionSet& set,
00558                               ConstType default_value);
00559   static inline void Set(int number, FieldType field_type,
00560                          ConstType value, ExtensionSet* set);
00561 };
00562 
00563 template <typename Type>
00564 class RepeatedPrimitiveTypeTraits {
00565  public:
00566   typedef Type ConstType;
00567 
00568   static inline Type Get(int number, const ExtensionSet& set, int index);
00569   static inline void Set(int number, int index, Type value, ExtensionSet* set);
00570   static inline void Add(int number, FieldType field_type,
00571                          bool is_packed, Type value, ExtensionSet* set);
00572 };
00573 
00574 #define PROTOBUF_DEFINE_PRIMITIVE_TYPE(TYPE, METHOD)                       \
00575 template<> inline TYPE PrimitiveTypeTraits<TYPE>::Get(                     \
00576     int number, const ExtensionSet& set, TYPE default_value) {             \
00577   return set.Get##METHOD(number, default_value);                           \
00578 }                                                                          \
00579 template<> inline void PrimitiveTypeTraits<TYPE>::Set(                     \
00580     int number, FieldType field_type, TYPE value, ExtensionSet* set) {     \
00581   set->Set##METHOD(number, field_type, value, NULL);                       \
00582 }                                                                          \
00583                                                                            \
00584 template<> inline TYPE RepeatedPrimitiveTypeTraits<TYPE>::Get(             \
00585     int number, const ExtensionSet& set, int index) {                      \
00586   return set.GetRepeated##METHOD(number, index);                           \
00587 }                                                                          \
00588 template<> inline void RepeatedPrimitiveTypeTraits<TYPE>::Set(             \
00589     int number, int index, TYPE value, ExtensionSet* set) {                \
00590   set->SetRepeated##METHOD(number, index, value);                          \
00591 }                                                                          \
00592 template<> inline void RepeatedPrimitiveTypeTraits<TYPE>::Add(             \
00593     int number, FieldType field_type, bool is_packed,                      \
00594     TYPE value, ExtensionSet* set) {                                       \
00595   set->Add##METHOD(number, field_type, is_packed, value, NULL);            \
00596 }
00597 
00598 PROTOBUF_DEFINE_PRIMITIVE_TYPE( int32,  Int32)
00599 PROTOBUF_DEFINE_PRIMITIVE_TYPE( int64,  Int64)
00600 PROTOBUF_DEFINE_PRIMITIVE_TYPE(uint32, UInt32)
00601 PROTOBUF_DEFINE_PRIMITIVE_TYPE(uint64, UInt64)
00602 PROTOBUF_DEFINE_PRIMITIVE_TYPE( float,  Float)
00603 PROTOBUF_DEFINE_PRIMITIVE_TYPE(double, Double)
00604 PROTOBUF_DEFINE_PRIMITIVE_TYPE(  bool,   Bool)
00605 
00606 #undef PROTOBUF_DEFINE_PRIMITIVE_TYPE
00607 
00608 // -------------------------------------------------------------------
00609 // StringTypeTraits
00610 
00611 // Strings support both Set() and Mutable().
00612 class LIBPROTOBUF_EXPORT StringTypeTraits {
00613  public:
00614   typedef const string& ConstType;
00615   typedef string* MutableType;
00616 
00617   static inline const string& Get(int number, const ExtensionSet& set,
00618                                   ConstType default_value) {
00619     return set.GetString(number, default_value);
00620   }
00621   static inline void Set(int number, FieldType field_type,
00622                          const string& value, ExtensionSet* set) {
00623     set->SetString(number, field_type, value, NULL);
00624   }
00625   static inline string* Mutable(int number, FieldType field_type,
00626                                 ExtensionSet* set) {
00627     return set->MutableString(number, field_type, NULL);
00628   }
00629 };
00630 
00631 class LIBPROTOBUF_EXPORT RepeatedStringTypeTraits {
00632  public:
00633   typedef const string& ConstType;
00634   typedef string* MutableType;
00635 
00636   static inline const string& Get(int number, const ExtensionSet& set,
00637                                   int index) {
00638     return set.GetRepeatedString(number, index);
00639   }
00640   static inline void Set(int number, int index,
00641                          const string& value, ExtensionSet* set) {
00642     set->SetRepeatedString(number, index, value);
00643   }
00644   static inline string* Mutable(int number, int index, ExtensionSet* set) {
00645     return set->MutableRepeatedString(number, index);
00646   }
00647   static inline void Add(int number, FieldType field_type,
00648                          bool /*is_packed*/, const string& value,
00649                          ExtensionSet* set) {
00650     set->AddString(number, field_type, value, NULL);
00651   }
00652   static inline string* Add(int number, FieldType field_type,
00653                             ExtensionSet* set) {
00654     return set->AddString(number, field_type, NULL);
00655   }
00656 };
00657 
00658 // -------------------------------------------------------------------
00659 // EnumTypeTraits
00660 
00661 // ExtensionSet represents enums using integers internally, so we have to
00662 // static_cast around.
00663 template <typename Type, bool IsValid(int)>
00664 class EnumTypeTraits {
00665  public:
00666   typedef Type ConstType;
00667 
00668   static inline ConstType Get(int number, const ExtensionSet& set,
00669                               ConstType default_value) {
00670     return static_cast<Type>(set.GetEnum(number, default_value));
00671   }
00672   static inline void Set(int number, FieldType field_type,
00673                          ConstType value, ExtensionSet* set) {
00674     GOOGLE_DCHECK(IsValid(value));
00675     set->SetEnum(number, field_type, value, NULL);
00676   }
00677 };
00678 
00679 template <typename Type, bool IsValid(int)>
00680 class RepeatedEnumTypeTraits {
00681  public:
00682   typedef Type ConstType;
00683 
00684   static inline ConstType Get(int number, const ExtensionSet& set, int index) {
00685     return static_cast<Type>(set.GetRepeatedEnum(number, index));
00686   }
00687   static inline void Set(int number, int index,
00688                          ConstType value, ExtensionSet* set) {
00689     GOOGLE_DCHECK(IsValid(value));
00690     set->SetRepeatedEnum(number, index, value);
00691   }
00692   static inline void Add(int number, FieldType field_type,
00693                          bool is_packed, ConstType value, ExtensionSet* set) {
00694     GOOGLE_DCHECK(IsValid(value));
00695     set->AddEnum(number, field_type, is_packed, value, NULL);
00696   }
00697 };
00698 
00699 // -------------------------------------------------------------------
00700 // MessageTypeTraits
00701 
00702 // ExtensionSet guarantees that when manipulating extensions with message
00703 // types, the implementation used will be the compiled-in class representing
00704 // that type.  So, we can static_cast down to the exact type we expect.
00705 template <typename Type>
00706 class MessageTypeTraits {
00707  public:
00708   typedef const Type& ConstType;
00709   typedef Type* MutableType;
00710 
00711   static inline ConstType Get(int number, const ExtensionSet& set,
00712                               ConstType default_value) {
00713     return static_cast<const Type&>(
00714         set.GetMessage(number, default_value));
00715   }
00716   static inline MutableType Mutable(int number, FieldType field_type,
00717                                     ExtensionSet* set) {
00718     return static_cast<Type*>(
00719       set->MutableMessage(number, field_type, Type::default_instance(), NULL));
00720   }
00721 };
00722 
00723 template <typename Type>
00724 class RepeatedMessageTypeTraits {
00725  public:
00726   typedef const Type& ConstType;
00727   typedef Type* MutableType;
00728 
00729   static inline ConstType Get(int number, const ExtensionSet& set, int index) {
00730     return static_cast<const Type&>(set.GetRepeatedMessage(number, index));
00731   }
00732   static inline MutableType Mutable(int number, int index, ExtensionSet* set) {
00733     return static_cast<Type*>(set->MutableRepeatedMessage(number, index));
00734   }
00735   static inline MutableType Add(int number, FieldType field_type,
00736                                 ExtensionSet* set) {
00737     return static_cast<Type*>(
00738         set->AddMessage(number, field_type, Type::default_instance(), NULL));
00739   }
00740 };
00741 
00742 // -------------------------------------------------------------------
00743 // ExtensionIdentifier
00744 
00745 // This is the type of actual extension objects.  E.g. if you have:
00746 //   extends Foo with optional int32 bar = 1234;
00747 // then "bar" will be defined in C++ as:
00748 //   ExtensionIdentifier<Foo, PrimitiveTypeTraits<int32>, 1, false> bar(1234);
00749 //
00750 // Note that we could, in theory, supply the field number as a template
00751 // parameter, and thus make an instance of ExtensionIdentifier have no
00752 // actual contents.  However, if we did that, then using at extension
00753 // identifier would not necessarily cause the compiler to output any sort
00754 // of reference to any simple defined in the extension's .pb.o file.  Some
00755 // linkers will actually drop object files that are not explicitly referenced,
00756 // but that would be bad because it would cause this extension to not be
00757 // registered at static initialization, and therefore using it would crash.
00758 
00759 template <typename ExtendeeType, typename TypeTraitsType,
00760           FieldType field_type, bool is_packed>
00761 class ExtensionIdentifier {
00762  public:
00763   typedef TypeTraitsType TypeTraits;
00764   typedef ExtendeeType Extendee;
00765 
00766   ExtensionIdentifier(int number, typename TypeTraits::ConstType default_value)
00767       : number_(number), default_value_(default_value) {}
00768   inline int number() const { return number_; }
00769   typename TypeTraits::ConstType default_value() const {
00770     return default_value_;
00771   }
00772 
00773  private:
00774   const int number_;
00775   typename TypeTraits::ConstType default_value_;
00776 };
00777 
00778 // -------------------------------------------------------------------
00779 // Generated accessors
00780 
00781 // This macro should be expanded in the context of a generated type which
00782 // has extensions.
00783 //
00784 // We use "_proto_TypeTraits" as a type name below because "TypeTraits"
00785 // causes problems if the class has a nested message or enum type with that
00786 // name and "_TypeTraits" is technically reserved for the C++ library since
00787 // it starts with an underscore followed by a capital letter.
00788 #define GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(CLASSNAME)                        \
00789   /* Has, Size, Clear */                                                      \
00790   template <typename _proto_TypeTraits,                                       \
00791             ::google::protobuf::internal::FieldType field_type,                         \
00792             bool is_packed>                                                   \
00793   inline bool HasExtension(                                                   \
00794       const ::google::protobuf::internal::ExtensionIdentifier<                          \
00795         CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id) const {     \
00796     return _extensions_.Has(id.number());                                     \
00797   }                                                                           \
00798                                                                               \
00799   template <typename _proto_TypeTraits,                                       \
00800             ::google::protobuf::internal::FieldType field_type,                         \
00801             bool is_packed>                                                   \
00802   inline void ClearExtension(                                                 \
00803       const ::google::protobuf::internal::ExtensionIdentifier<                          \
00804         CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id) {           \
00805     _extensions_.ClearExtension(id.number());                                 \
00806   }                                                                           \
00807                                                                               \
00808   template <typename _proto_TypeTraits,                                       \
00809             ::google::protobuf::internal::FieldType field_type,                         \
00810             bool is_packed>                                                   \
00811   inline int ExtensionSize(                                                   \
00812       const ::google::protobuf::internal::ExtensionIdentifier<                          \
00813         CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id) const {     \
00814     return _extensions_.ExtensionSize(id.number());                           \
00815   }                                                                           \
00816                                                                               \
00817   /* Singular accessors */                                                    \
00818   template <typename _proto_TypeTraits,                                       \
00819             ::google::protobuf::internal::FieldType field_type,                         \
00820             bool is_packed>                                                   \
00821   inline typename _proto_TypeTraits::ConstType GetExtension(                  \
00822       const ::google::protobuf::internal::ExtensionIdentifier<                          \
00823         CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id) const {     \
00824     return _proto_TypeTraits::Get(id.number(), _extensions_,                  \
00825                                   id.default_value());                        \
00826   }                                                                           \
00827                                                                               \
00828   template <typename _proto_TypeTraits,                                       \
00829             ::google::protobuf::internal::FieldType field_type,                         \
00830             bool is_packed>                                                   \
00831   inline typename _proto_TypeTraits::MutableType MutableExtension(            \
00832       const ::google::protobuf::internal::ExtensionIdentifier<                          \
00833         CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id) {           \
00834     return _proto_TypeTraits::Mutable(id.number(), field_type, &_extensions_);\
00835   }                                                                           \
00836                                                                               \
00837   template <typename _proto_TypeTraits,                                       \
00838             ::google::protobuf::internal::FieldType field_type,                         \
00839             bool is_packed>                                                   \
00840   inline void SetExtension(                                                   \
00841       const ::google::protobuf::internal::ExtensionIdentifier<                          \
00842         CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id,             \
00843       typename _proto_TypeTraits::ConstType value) {                          \
00844     _proto_TypeTraits::Set(id.number(), field_type, value, &_extensions_);    \
00845   }                                                                           \
00846                                                                               \
00847   /* Repeated accessors */                                                    \
00848   template <typename _proto_TypeTraits,                                       \
00849             ::google::protobuf::internal::FieldType field_type,                         \
00850             bool is_packed>                                                   \
00851   inline typename _proto_TypeTraits::ConstType GetExtension(                  \
00852       const ::google::protobuf::internal::ExtensionIdentifier<                          \
00853         CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id,             \
00854       int index) const {                                                      \
00855     return _proto_TypeTraits::Get(id.number(), _extensions_, index);          \
00856   }                                                                           \
00857                                                                               \
00858   template <typename _proto_TypeTraits,                                       \
00859             ::google::protobuf::internal::FieldType field_type,                         \
00860             bool is_packed>                                                   \
00861   inline typename _proto_TypeTraits::MutableType MutableExtension(            \
00862       const ::google::protobuf::internal::ExtensionIdentifier<                          \
00863         CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id,             \
00864       int index) {                                                            \
00865     return _proto_TypeTraits::Mutable(id.number(), index, &_extensions_);     \
00866   }                                                                           \
00867                                                                               \
00868   template <typename _proto_TypeTraits,                                       \
00869             ::google::protobuf::internal::FieldType field_type,                         \
00870             bool is_packed>                                                   \
00871   inline void SetExtension(                                                   \
00872       const ::google::protobuf::internal::ExtensionIdentifier<                          \
00873         CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id,             \
00874       int index, typename _proto_TypeTraits::ConstType value) {               \
00875     _proto_TypeTraits::Set(id.number(), index, value, &_extensions_);         \
00876   }                                                                           \
00877                                                                               \
00878   template <typename _proto_TypeTraits,                                       \
00879             ::google::protobuf::internal::FieldType field_type,                         \
00880             bool is_packed>                                                   \
00881   inline typename _proto_TypeTraits::MutableType AddExtension(                \
00882       const ::google::protobuf::internal::ExtensionIdentifier<                          \
00883         CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id) {           \
00884     return _proto_TypeTraits::Add(id.number(), field_type, &_extensions_);    \
00885   }                                                                           \
00886                                                                               \
00887   template <typename _proto_TypeTraits,                                       \
00888             ::google::protobuf::internal::FieldType field_type,                         \
00889             bool is_packed>                                                   \
00890   inline void AddExtension(                                                   \
00891       const ::google::protobuf::internal::ExtensionIdentifier<                          \
00892         CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id,             \
00893       typename _proto_TypeTraits::ConstType value) {                          \
00894     _proto_TypeTraits::Add(id.number(), field_type, is_packed,                \
00895                            value, &_extensions_);                             \
00896   }
00897 
00898 }  // namespace internal
00899 }  // namespace protobuf
00900 
00901 }  // namespace google
00902 #endif  // GOOGLE_PROTOBUF_EXTENSION_SET_H__
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines