aboutsummaryrefslogblamecommitdiff
path: root/src/google/protobuf/generated_message_reflection.h
blob: 579d6abe1ae5a789cf576836e0988645a341e42e (plain) (tree)











































































































































































































































































































                                                                                     
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.
// http://code.google.com/p/protobuf/
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Author: kenton@google.com (Kenton Varda)
//  Based on original Protocol Buffers design by
//  Sanjay Ghemawat, Jeff Dean, and others.
//
// This header is logically internal, but is made public because it is used
// from protocol-compiler-generated code, which may reside in other components.

#ifndef GOOGLE_PROTOBUF_GENERATED_MESSAGE_REFLECTION_H__
#define GOOGLE_PROTOBUF_GENERATED_MESSAGE_REFLECTION_H__

#include <string>
#include <vector>
#include <google/protobuf/message.h>
#include <google/protobuf/unknown_field_set.h>


// Generated code needs this to have been forward-declared.  Easier to do it
// here than to print it inside every .pb.h file.
namespace google {
namespace protobuf { class EnumDescriptor; }

namespace protobuf {
namespace internal {

// Defined in this file.
class GeneratedMessageReflection;

// Defined in other files.
class ExtensionSet;             // extension_set.h

// THIS CLASS IS NOT INTENDED FOR DIRECT USE.  It is intended for use
// by generated code.  This class is just a big hack that reduces code
// size.
//
// A GeneratedMessageReflection is an implementation of Message::Reflection
// which expects all fields to be backed by simple variables located in
// memory.  The locations are given using a base pointer and a set of
// offsets.
//
// It is required that the user represents fields of each type in a standard
// way, so that GeneratedMessageReflection can cast the void* pointer to
// the appropriate type.  For primitive fields and string fields, each field
// should be represented using the obvious C++ primitive type.  Enums and
// Messages are different:
//  - Singular Message fields are stored as a pointer to a Message.  These
//    should start out NULL, except for in the default instance where they
//    should start out pointing to other default instances.
//  - Enum fields are stored as an int.  This int must always contain
//    a valid value, such that EnumDescriptor::FindValueByNumber() would
//    not return NULL.
//  - Repeated fields are stored as RepeatedFields or RepeatedPtrFields
//    of whatever type the individual field would be.  Strings and
//    Messages use RepeatedPtrFields while everything else uses
//    RepeatedFields.
class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Message::Reflection {
 public:
  // Constructs a GeneratedMessageReflection.
  // Parameters:
  //   descriptor:    The descriptor for the message type being implemented.
  //   base:          Pointer to the location where the message object is
  //                  stored.
  //   default_base:  Pointer to the location where the message's default
  //                  instance is stored.  This is only used to obtain
  //                  pointers to default instances of embedded messages,
  //                  which GetMessage() will return if the particular sub-
  //                  message has not been initialized yet.  (Thus, all
  //                  embedded message fields *must* have non-NULL pointers
  //                  in the default instance.)
  //   offsets:       An array of bits giving the byte offsets, relative to
  //                  "base" and "default_base", of each field.  These can
  //                  be computed at compile time using the
  //                  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET() macro, defined
  //                  below.
  //   has_bits:      An array of uint32s of size descriptor->field_count()/32,
  //                  rounded up.  This is a bitfield where each bit indicates
  //                  whether or not the corresponding field of the message
  //                  has been initialized.  The bit for field index i is
  //                  obtained by the expression:
  //                    has_bits[i / 32] & (1 << (i % 32))
  //   extensions:    The ExtensionSet for this message, or NULL if the
  //                  message type has no extension ranges.
  GeneratedMessageReflection(const Descriptor* descriptor,
                             void* base, const void* default_base,
                             const int offsets[], uint32 has_bits[],
                             ExtensionSet* extensions);
  ~GeneratedMessageReflection();

  inline const UnknownFieldSet& unknown_fields() const {
    return unknown_fields_;
  }
  inline UnknownFieldSet* mutable_unknown_fields() {
    return &unknown_fields_;
  }

  // implements Message::Reflection ----------------------------------

  const UnknownFieldSet& GetUnknownFields() const;
  UnknownFieldSet* MutableUnknownFields();

  bool HasField(const FieldDescriptor* field) const;
  int FieldSize(const FieldDescriptor* field) const;
  void ClearField(const FieldDescriptor* field);
  void ListFields(vector<const FieldDescriptor*>* output) const;

  int32  GetInt32 (const FieldDescriptor* field) const;
  int64  GetInt64 (const FieldDescriptor* field) const;
  uint32 GetUInt32(const FieldDescriptor* field) const;
  uint64 GetUInt64(const FieldDescriptor* field) const;
  float  GetFloat (const FieldDescriptor* field) const;
  double GetDouble(const FieldDescriptor* field) const;
  bool   GetBool  (const FieldDescriptor* field) const;
  string GetString(const FieldDescriptor* field) const;
  const string& GetStringReference(const FieldDescriptor* field,
                                   string* scratch) const;
  const EnumValueDescriptor* GetEnum(const FieldDescriptor* field) const;
  const Message& GetMessage(const FieldDescriptor* field) const;

  void SetInt32 (const FieldDescriptor* field, int32  value);
  void SetInt64 (const FieldDescriptor* field, int64  value);
  void SetUInt32(const FieldDescriptor* field, uint32 value);
  void SetUInt64(const FieldDescriptor* field, uint64 value);
  void SetFloat (const FieldDescriptor* field, float  value);
  void SetDouble(const FieldDescriptor* field, double value);
  void SetBool  (const FieldDescriptor* field, bool   value);
  void SetString(const FieldDescriptor* field,
                 const string& value);
  void SetEnum  (const FieldDescriptor* field,
                 const EnumValueDescriptor* value);
  Message* MutableMessage(const FieldDescriptor* field);

  int32  GetRepeatedInt32 (const FieldDescriptor* field, int index) const;
  int64  GetRepeatedInt64 (const FieldDescriptor* field, int index) const;
  uint32 GetRepeatedUInt32(const FieldDescriptor* field, int index) const;
  uint64 GetRepeatedUInt64(const FieldDescriptor* field, int index) const;
  float  GetRepeatedFloat (const FieldDescriptor* field, int index) const;
  double GetRepeatedDouble(const FieldDescriptor* field, int index) const;
  bool   GetRepeatedBool  (const FieldDescriptor* field, int index) const;
  string GetRepeatedString(const FieldDescriptor* field, int index) const;
  const string& GetRepeatedStringReference(const FieldDescriptor* field,
                                           int index, string* scratch) const;
  const EnumValueDescriptor* GetRepeatedEnum(const FieldDescriptor* field,
                                             int index) const;
  const Message& GetRepeatedMessage(const FieldDescriptor* field,
                                    int index) const;

  // Set the value of a field.
  void SetRepeatedInt32 (const FieldDescriptor* field, int index, int32  value);
  void SetRepeatedInt64 (const FieldDescriptor* field, int index, int64  value);
  void SetRepeatedUInt32(const FieldDescriptor* field, int index, uint32 value);
  void SetRepeatedUInt64(const FieldDescriptor* field, int index, uint64 value);
  void SetRepeatedFloat (const FieldDescriptor* field, int index, float  value);
  void SetRepeatedDouble(const FieldDescriptor* field, int index, double value);
  void SetRepeatedBool  (const FieldDescriptor* field, int index, bool   value);
  void SetRepeatedString(const FieldDescriptor* field, int index,
                         const string& value);
  void SetRepeatedEnum  (const FieldDescriptor* field, int index,
                         const EnumValueDescriptor* value);
  // Get a mutable pointer to a field with a message type.
  Message* MutableRepeatedMessage(const FieldDescriptor* field, int index);

  void AddInt32 (const FieldDescriptor* field, int32  value);
  void AddInt64 (const FieldDescriptor* field, int64  value);
  void AddUInt32(const FieldDescriptor* field, uint32 value);
  void AddUInt64(const FieldDescriptor* field, uint64 value);
  void AddFloat (const FieldDescriptor* field, float  value);
  void AddDouble(const FieldDescriptor* field, double value);
  void AddBool  (const FieldDescriptor* field, bool   value);
  void AddString(const FieldDescriptor* field, const string& value);
  void AddEnum(const FieldDescriptor* field, const EnumValueDescriptor* value);
  Message* AddMessage(const FieldDescriptor* field);

  const FieldDescriptor* FindKnownExtensionByName(const string& name) const;
  const FieldDescriptor* FindKnownExtensionByNumber(int number) const;

 private:
  friend class GeneratedMessage;

  const Descriptor* descriptor_;
  void* base_;
  const void* default_base_;
  const int* offsets_;

  // TODO(kenton):  These two pointers just point back into the message object.
  //   We could save space by removing them and using offsets instead.
  uint32* has_bits_;
  ExtensionSet* extensions_;

  // We put this directly in the GeneratedMessageReflection because every
  // message class needs it, and if we don't find any unknown fields, it
  // takes up only one pointer of space.
  UnknownFieldSet unknown_fields_;

  template <typename Type>
  inline const Type& GetRaw(const FieldDescriptor* field) const;
  template <typename Type>
  inline Type* MutableRaw(const FieldDescriptor* field);
  template <typename Type>
  inline const Type& DefaultRaw(const FieldDescriptor* field) const;
  inline const Message* GetMessagePrototype(const FieldDescriptor* field) const;

  inline bool HasBit(const FieldDescriptor* field) const;
  inline void SetBit(const FieldDescriptor* field);
  inline void ClearBit(const FieldDescriptor* field);

  template <typename Type>
  inline const Type& GetField(const FieldDescriptor* field) const;
  template <typename Type>
  inline void SetField(const FieldDescriptor* field, const Type& value);
  template <typename Type>
  inline Type* MutableField(const FieldDescriptor* field);
  template <typename Type>
  inline const Type& GetRepeatedField(const FieldDescriptor* field,
                                      int index) const;
  template <typename Type>
  inline void SetRepeatedField(const FieldDescriptor* field, int index,
                               const Type& value);
  template <typename Type>
  inline Type* MutableRepeatedField(const FieldDescriptor* field, int index);
  template <typename Type>
  inline void AddField(const FieldDescriptor* field, const Type& value);
  template <typename Type>
  inline Type* AddField(const FieldDescriptor* field);

  int GetExtensionNumberOrDie(const Descriptor* type) const;

  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GeneratedMessageReflection);
};

// Returns the offset of the given field within the given aggregate type.
// This is equivalent to the ANSI C offsetof() macro.  However, according
// to the C++ standard, offsetof() only works on POD types, and GCC
// enforces this requirement with a warning.  In practice, this rule is
// unnecessarily strict; there is probably no compiler or platform on
// which the offsets of the direct fields of a class are non-constant.
// Fields inherited from superclasses *can* have non-constant offsets,
// but that's not what this macro will be used for.
//
// Note that we calculate relative to the pointer value 16 here since if we
// just use zero, GCC complains about dereferencing a NULL pointer.  We
// choose 16 rather than some other number just in case the compiler would
// be confused by an unaligned pointer.
#define GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(TYPE, FIELD)    \
  (reinterpret_cast<const char*>(                             \
     &reinterpret_cast<const TYPE*>(16)->FIELD) -             \
   reinterpret_cast<const char*>(16))

// There are some places in proto2 where dynamic_cast would be useful as an
// optimization.  For example, take Message::MergeFrom(const Message& other).
// For a given generated message FooMessage, we generate these two methods:
//   void MergeFrom(const FooMessage& other);
//   void MergeFrom(const Message& other);
// The former method can be implemented directly in terms of FooMessage's
// inline accessors, but the latter method must work with the reflection
// interface.  However, if the parameter to the latter method is actually of
// type FooMessage, then we'd like to be able to just call the other method
// as an optimization.  So, we use dynamic_cast to check this.
//
// That said, dynamic_cast requires RTTI, which many people like to disable
// for performance and code size reasons.  When RTTI is not available, we
// still need to produce correct results.  So, in this case we have to fall
// back to using reflection, which is what we would have done anyway if the
// objects were not of the exact same class.
//
// dynamic_cast_if_available() implements this logic.  If RTTI is
// enabled, it does a dynamic_cast.  If RTTI is disabled, it just returns
// NULL.
//
// If you need to compile without RTTI, simply #define GOOGLE_PROTOBUF_NO_RTTI.
// On MSVC, this should be detected automatically.
template<typename To, typename From>
inline To dynamic_cast_if_available(From from) {
#if defined(GOOGLE_PROTOBUF_NO_RTTI) || (defined(_MSC_VER)&&!defined(_CPPRTTI))
  return NULL;
#else
  return dynamic_cast<To>(from);
#endif
}


}  // namespace internal
}  // namespace protobuf

}  // namespace google
#endif  // GOOGLE_PROTOBUF_GENERATED_MESSAGE_REFLECTION_H__