aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/google/protobuf/generated_message_reflection.h
blob: 579d6abe1ae5a789cf576836e0988645a341e42e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
// 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__