1// Protocol Buffers - Google's data interchange format
2// Copyright 2008 Google Inc. All rights reserved.
3// https://developers.google.com/protocol-buffers/
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_GENERATED_MESSAGE_REFLECTION_H__
39#define GOOGLE_PROTOBUF_GENERATED_MESSAGE_REFLECTION_H__
40
41#include <string>
42#include <vector>
43#include <google/protobuf/stubs/casts.h>
44#include <google/protobuf/stubs/common.h>
45// TODO(jasonh): Remove this once the compiler change to directly include this
46// is released to components.
47#include <google/protobuf/descriptor.h>
48#include <google/protobuf/generated_enum_reflection.h>
49#include <google/protobuf/stubs/once.h>
50#include <google/protobuf/port.h>
51#include <google/protobuf/unknown_field_set.h>
52
53
54#include <google/protobuf/port_def.inc>
55
56#ifdef SWIG
57#error "You cannot SWIG proto headers"
58#endif
59
60namespace google {
61namespace protobuf {
62class DescriptorPool;
63class MapKey;
64class MapValueRef;
65class MessageLayoutInspector;
66class Message;
67struct Metadata;
68} // namespace protobuf
69} // namespace google
70
71namespace google {
72namespace protobuf {
73namespace internal {
74class DefaultEmptyOneof;
75// Defined in other files.
76class ExtensionSet; // extension_set.h
77class WeakFieldMap; // weak_field_map.h
78
79// This struct describes the internal layout of the message, hence this is
80// used to act on the message reflectively.
81// default_instance: The default instance of the message. This is only
82// used to obtain pointers to default instances of embedded
83// messages, which GetMessage() will return if the particular
84// sub-message has not been initialized yet. (Thus, all
85// embedded message fields *must* have non-null pointers
86// in the default instance.)
87// offsets: An array of ints giving the byte offsets.
88// For each oneof or weak field, the offset is relative to the
89// default_instance. These can be computed at compile time
90// using the
91// PROTO2_GENERATED_DEFAULT_ONEOF_FIELD_OFFSET()
92// macro. For each none oneof field, the offset is related to
93// the start of the message object. These can be computed at
94// compile time using the
95// PROTO2_GENERATED_MESSAGE_FIELD_OFFSET() macro.
96// Besides offsets for all fields, this array also contains
97// offsets for oneof unions. The offset of the i-th oneof union
98// is offsets[descriptor->field_count() + i].
99// has_bit_indices: Mapping from field indexes to their index in the has
100// bit array.
101// has_bits_offset: Offset in the message of an array of uint32s of size
102// descriptor->field_count()/32, rounded up. This is a
103// bitfield where each bit indicates whether or not the
104// corresponding field of the message has been initialized.
105// The bit for field index i is obtained by the expression:
106// has_bits[i / 32] & (1 << (i % 32))
107// unknown_fields_offset: Offset in the message of the UnknownFieldSet for
108// the message.
109// extensions_offset: Offset in the message of the ExtensionSet for the
110// message, or -1 if the message type has no extension
111// ranges.
112// oneof_case_offset: Offset in the message of an array of uint32s of
113// size descriptor->oneof_decl_count(). Each uint32
114// indicates what field is set for each oneof.
115// object_size: The size of a message object of this type, as measured
116// by sizeof().
117// arena_offset: If a message doesn't have a unknown_field_set that stores
118// the arena, it must have a direct pointer to the arena.
119// weak_field_map_offset: If the message proto has weak fields, this is the
120// offset of _weak_field_map_ in the generated proto. Otherwise
121// -1.
122struct ReflectionSchema {
123 public:
124 // Size of a google::protobuf::Message object of this type.
125 uint32 GetObjectSize() const { return static_cast<uint32>(object_size_); }
126
127 bool InRealOneof(const FieldDescriptor* field) const {
128 return field->containing_oneof() &&
129 !field->containing_oneof()->is_synthetic();
130 }
131
132 // Offset of a non-oneof field. Getting a field offset is slightly more
133 // efficient when we know statically that it is not a oneof field.
134 uint32 GetFieldOffsetNonOneof(const FieldDescriptor* field) const {
135 GOOGLE_DCHECK(!InRealOneof(field));
136 return OffsetValue(v: offsets_[field->index()], type: field->type());
137 }
138
139 // Offset of any field.
140 uint32 GetFieldOffset(const FieldDescriptor* field) const {
141 if (InRealOneof(field)) {
142 size_t offset =
143 static_cast<size_t>(field->containing_type()->field_count() +
144 field->containing_oneof()->index());
145 return OffsetValue(v: offsets_[offset], type: field->type());
146 } else {
147 return GetFieldOffsetNonOneof(field);
148 }
149 }
150
151 bool IsFieldInlined(const FieldDescriptor* field) const {
152 if (InRealOneof(field)) {
153 size_t offset =
154 static_cast<size_t>(field->containing_type()->field_count() +
155 field->containing_oneof()->index());
156 return Inlined(v: offsets_[offset], type: field->type());
157 } else {
158 return Inlined(v: offsets_[field->index()], type: field->type());
159 }
160 }
161
162 uint32 GetOneofCaseOffset(const OneofDescriptor* oneof_descriptor) const {
163 return static_cast<uint32>(oneof_case_offset_) +
164 static_cast<uint32>(static_cast<size_t>(oneof_descriptor->index()) *
165 sizeof(uint32));
166 }
167
168 bool HasHasbits() const { return has_bits_offset_ != -1; }
169
170 // Bit index within the bit array of hasbits. Bit order is low-to-high.
171 uint32 HasBitIndex(const FieldDescriptor* field) const {
172 if (has_bits_offset_ == -1) return static_cast<uint32>(-1);
173 GOOGLE_DCHECK(HasHasbits());
174 return has_bit_indices_[field->index()];
175 }
176
177 // Byte offset of the hasbits array.
178 uint32 HasBitsOffset() const {
179 GOOGLE_DCHECK(HasHasbits());
180 return static_cast<uint32>(has_bits_offset_);
181 }
182
183 // The offset of the InternalMetadataWithArena member.
184 // For Lite this will actually be an InternalMetadataWithArenaLite.
185 // The schema doesn't contain enough information to distinguish between
186 // these two cases.
187 uint32 GetMetadataOffset() const {
188 return static_cast<uint32>(metadata_offset_);
189 }
190
191 // Whether this message has an ExtensionSet.
192 bool HasExtensionSet() const { return extensions_offset_ != -1; }
193
194 // The offset of the ExtensionSet in this message.
195 uint32 GetExtensionSetOffset() const {
196 GOOGLE_DCHECK(HasExtensionSet());
197 return static_cast<uint32>(extensions_offset_);
198 }
199
200 // The off set of WeakFieldMap when the message contains weak fields.
201 // The default is 0 for now.
202 int GetWeakFieldMapOffset() const { return weak_field_map_offset_; }
203
204 bool IsDefaultInstance(const Message& message) const {
205 return &message == default_instance_;
206 }
207
208 // Returns a pointer to the default value for this field. The size and type
209 // of the underlying data depends on the field's type.
210 const void* GetFieldDefault(const FieldDescriptor* field) const {
211 return reinterpret_cast<const uint8*>(default_instance_) +
212 OffsetValue(v: offsets_[field->index()], type: field->type());
213 }
214
215
216 bool HasWeakFields() const { return weak_field_map_offset_ > 0; }
217
218 // These members are intended to be private, but we cannot actually make them
219 // private because this prevents us from using aggregate initialization of
220 // them, ie.
221 //
222 // ReflectionSchema schema = {a, b, c, d, e, ...};
223 // private:
224 const Message* default_instance_;
225 const uint32* offsets_;
226 const uint32* has_bit_indices_;
227 int has_bits_offset_;
228 int metadata_offset_;
229 int extensions_offset_;
230 int oneof_case_offset_;
231 int object_size_;
232 int weak_field_map_offset_;
233
234 // We tag offset values to provide additional data about fields (such as
235 // inlined).
236 static uint32 OffsetValue(uint32 v, FieldDescriptor::Type type) {
237 if (type == FieldDescriptor::TYPE_STRING ||
238 type == FieldDescriptor::TYPE_BYTES) {
239 return v & ~1u;
240 } else {
241 return v;
242 }
243 }
244
245 static bool Inlined(uint32 v, FieldDescriptor::Type type) {
246 if (type == FieldDescriptor::TYPE_STRING ||
247 type == FieldDescriptor::TYPE_BYTES) {
248 return v & 1u;
249 } else {
250 // Non string/byte fields are not inlined.
251 return false;
252 }
253 }
254};
255
256// Structs that the code generator emits directly to describe a message.
257// These should never used directly except to build a ReflectionSchema
258// object.
259//
260// EXPERIMENTAL: these are changing rapidly, and may completely disappear
261// or merge with ReflectionSchema.
262struct MigrationSchema {
263 int32 offsets_index;
264 int32 has_bit_indices_index;
265 int object_size;
266};
267
268struct SCCInfoBase;
269
270struct PROTOBUF_EXPORT DescriptorTable {
271 mutable bool is_initialized;
272 bool is_eager;
273 const char* descriptor;
274 const char* filename;
275 int size; // of serialized descriptor
276 once_flag* once;
277 SCCInfoBase* const* init_default_instances;
278 const DescriptorTable* const* deps;
279 int num_sccs;
280 int num_deps;
281 const MigrationSchema* schemas;
282 const Message* const* default_instances;
283 const uint32* offsets;
284 // update the following descriptor arrays.
285 Metadata* file_level_metadata;
286 int num_messages;
287 const EnumDescriptor** file_level_enum_descriptors;
288 const ServiceDescriptor** file_level_service_descriptors;
289};
290
291// AssignDescriptors() pulls the compiled FileDescriptor from the DescriptorPool
292// and uses it to populate all of the global variables which store pointers to
293// the descriptor objects. It also constructs the reflection objects. It is
294// called the first time anyone calls descriptor() or GetReflection() on one of
295// the types defined in the file. AssignDescriptors() is thread-safe.
296void PROTOBUF_EXPORT AssignDescriptors(const DescriptorTable* table,
297 bool eager = false);
298
299// AddDescriptors() is a file-level procedure which adds the encoded
300// FileDescriptorProto for this .proto file to the global DescriptorPool for
301// generated files (DescriptorPool::generated_pool()). It ordinarily runs at
302// static initialization time, but is not used at all in LITE_RUNTIME mode.
303// AddDescriptors() is *not* thread-safe.
304void PROTOBUF_EXPORT AddDescriptors(const DescriptorTable* table);
305
306// These cannot be in lite so we put them in the reflection.
307PROTOBUF_EXPORT void UnknownFieldSetSerializer(const uint8* base, uint32 offset,
308 uint32 tag, uint32 has_offset,
309 io::CodedOutputStream* output);
310
311} // namespace internal
312} // namespace protobuf
313} // namespace google
314
315#include <google/protobuf/port_undef.inc>
316
317#endif // GOOGLE_PROTOBUF_GENERATED_MESSAGE_REFLECTION_H__
318

source code of include/google/protobuf/generated_message_reflection.h