blob: a0dd75c65b58a6429f4784219bebbac383cb7b03 [file] [log] [blame]
temporal40ee5512008-07-10 02:12:20 +00001// Protocol Buffers - Google's data interchange format
kenton@google.com24bf56f2008-09-24 20:31:01 +00002// Copyright 2008 Google Inc. All rights reserved.
temporal40ee5512008-07-10 02:12:20 +00003// http://code.google.com/p/protobuf/
4//
kenton@google.com24bf56f2008-09-24 20:31:01 +00005// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are
7// met:
temporal40ee5512008-07-10 02:12:20 +00008//
kenton@google.com24bf56f2008-09-24 20:31:01 +00009// * 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.
temporal40ee5512008-07-10 02:12:20 +000018//
kenton@google.com24bf56f2008-09-24 20:31:01 +000019// 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.
temporal40ee5512008-07-10 02:12:20 +000030
31// Author: kenton@google.com (Kenton Varda)
32// Based on original Protocol Buffers design by
33// Sanjay Ghemawat, Jeff Dean, and others.
34
35#include <algorithm>
36#include <google/protobuf/generated_message_reflection.h>
37#include <google/protobuf/descriptor.h>
38#include <google/protobuf/descriptor.pb.h>
39#include <google/protobuf/repeated_field.h>
40#include <google/protobuf/extension_set.h>
kenton@google.com80b1d622009-07-29 01:13:20 +000041#include <google/protobuf/generated_message_util.h>
temporal40ee5512008-07-10 02:12:20 +000042#include <google/protobuf/stubs/common.h>
43
44namespace google {
45namespace protobuf {
46namespace internal {
47
kenton@google.com26bd9ee2008-11-21 00:06:27 +000048int StringSpaceUsedExcludingSelf(const string& str) {
49 const void* start = &str;
50 const void* end = &str + 1;
51
52 if (start <= str.data() && str.data() <= end) {
53 // The string's data is stored inside the string object itself.
54 return 0;
55 } else {
56 return str.capacity();
57 }
58}
59
kenton@google.comd37d46d2009-04-25 02:53:47 +000060bool ParseNamedEnum(const EnumDescriptor* descriptor,
61 const string& name,
62 int* value) {
63 const EnumValueDescriptor* d = descriptor->FindValueByName(name);
64 if (d == NULL) return false;
65 *value = d->number();
66 return true;
67}
68
69const string& NameOfEnum(const EnumDescriptor* descriptor, int value) {
kenton@google.comd37d46d2009-04-25 02:53:47 +000070 const EnumValueDescriptor* d = descriptor->FindValueByNumber(value);
71 return (d == NULL ? kEmptyString : d->name());
72}
73
temporal40ee5512008-07-10 02:12:20 +000074// ===================================================================
75// Helpers for reporting usage errors (e.g. trying to use GetInt32() on
76// a string field).
77
78namespace {
79
80void ReportReflectionUsageError(
81 const Descriptor* descriptor, const FieldDescriptor* field,
82 const char* method, const char* description) {
83 GOOGLE_LOG(FATAL)
84 << "Protocol Buffer reflection usage error:\n"
temporal779f61c2008-08-13 03:15:00 +000085 " Method : google::protobuf::Reflection::" << method << "\n"
temporal40ee5512008-07-10 02:12:20 +000086 " Message type: " << descriptor->full_name() << "\n"
87 " Field : " << field->full_name() << "\n"
88 " Problem : " << description;
89}
90
91const char* cpptype_names_[FieldDescriptor::MAX_CPPTYPE + 1] = {
92 "INVALID_CPPTYPE",
93 "CPPTYPE_INT32",
94 "CPPTYPE_INT64",
95 "CPPTYPE_UINT32",
96 "CPPTYPE_UINT64",
97 "CPPTYPE_DOUBLE",
98 "CPPTYPE_FLOAT",
99 "CPPTYPE_BOOL",
100 "CPPTYPE_ENUM",
101 "CPPTYPE_STRING",
102 "CPPTYPE_MESSAGE"
103};
104
105static void ReportReflectionUsageTypeError(
106 const Descriptor* descriptor, const FieldDescriptor* field,
107 const char* method,
108 FieldDescriptor::CppType expected_type) {
109 GOOGLE_LOG(FATAL)
110 << "Protocol Buffer reflection usage error:\n"
temporal779f61c2008-08-13 03:15:00 +0000111 " Method : google::protobuf::Reflection::" << method << "\n"
temporal40ee5512008-07-10 02:12:20 +0000112 " Message type: " << descriptor->full_name() << "\n"
113 " Field : " << field->full_name() << "\n"
114 " Problem : Field is not the right type for this message:\n"
115 " Expected : " << cpptype_names_[expected_type] << "\n"
116 " Field type: " << cpptype_names_[field->cpp_type()];
117}
118
119static void ReportReflectionUsageEnumTypeError(
120 const Descriptor* descriptor, const FieldDescriptor* field,
121 const char* method, const EnumValueDescriptor* value) {
122 GOOGLE_LOG(FATAL)
123 << "Protocol Buffer reflection usage error:\n"
temporal779f61c2008-08-13 03:15:00 +0000124 " Method : google::protobuf::Reflection::" << method << "\n"
temporal40ee5512008-07-10 02:12:20 +0000125 " Message type: " << descriptor->full_name() << "\n"
126 " Field : " << field->full_name() << "\n"
127 " Problem : Enum value did not match field type:\n"
128 " Expected : " << field->enum_type()->full_name() << "\n"
129 " Actual : " << value->full_name();
130}
131
132#define USAGE_CHECK(CONDITION, METHOD, ERROR_DESCRIPTION) \
133 if (!(CONDITION)) \
134 ReportReflectionUsageError(descriptor_, field, #METHOD, ERROR_DESCRIPTION)
135#define USAGE_CHECK_EQ(A, B, METHOD, ERROR_DESCRIPTION) \
136 USAGE_CHECK((A) == (B), METHOD, ERROR_DESCRIPTION)
137#define USAGE_CHECK_NE(A, B, METHOD, ERROR_DESCRIPTION) \
138 USAGE_CHECK((A) != (B), METHOD, ERROR_DESCRIPTION)
139
140#define USAGE_CHECK_TYPE(METHOD, CPPTYPE) \
141 if (field->cpp_type() != FieldDescriptor::CPPTYPE_##CPPTYPE) \
142 ReportReflectionUsageTypeError(descriptor_, field, #METHOD, \
143 FieldDescriptor::CPPTYPE_##CPPTYPE)
144
145#define USAGE_CHECK_ENUM_VALUE(METHOD) \
146 if (value->type() != field->enum_type()) \
147 ReportReflectionUsageEnumTypeError(descriptor_, field, #METHOD, value)
148
149#define USAGE_CHECK_MESSAGE_TYPE(METHOD) \
150 USAGE_CHECK_EQ(field->containing_type(), descriptor_, \
151 METHOD, "Field does not match message type.");
152#define USAGE_CHECK_SINGULAR(METHOD) \
153 USAGE_CHECK_NE(field->label(), FieldDescriptor::LABEL_REPEATED, METHOD, \
154 "Field is repeated; the method requires a singular field.")
155#define USAGE_CHECK_REPEATED(METHOD) \
156 USAGE_CHECK_EQ(field->label(), FieldDescriptor::LABEL_REPEATED, METHOD, \
157 "Field is singular; the method requires a repeated field.")
158
159#define USAGE_CHECK_ALL(METHOD, LABEL, CPPTYPE) \
160 USAGE_CHECK_MESSAGE_TYPE(METHOD); \
161 USAGE_CHECK_##LABEL(METHOD); \
162 USAGE_CHECK_TYPE(METHOD, CPPTYPE)
163
164} // namespace
165
166// ===================================================================
167
168GeneratedMessageReflection::GeneratedMessageReflection(
169 const Descriptor* descriptor,
temporal779f61c2008-08-13 03:15:00 +0000170 const Message* default_instance,
171 const int offsets[],
172 int has_bits_offset,
173 int unknown_fields_offset,
174 int extensions_offset,
kenton@google.com26bd9ee2008-11-21 00:06:27 +0000175 const DescriptorPool* descriptor_pool,
kenton@google.comd37d46d2009-04-25 02:53:47 +0000176 MessageFactory* factory,
kenton@google.com26bd9ee2008-11-21 00:06:27 +0000177 int object_size)
temporal779f61c2008-08-13 03:15:00 +0000178 : descriptor_ (descriptor),
179 default_instance_ (default_instance),
180 offsets_ (offsets),
181 has_bits_offset_ (has_bits_offset),
182 unknown_fields_offset_(unknown_fields_offset),
183 extensions_offset_(extensions_offset),
kenton@google.com26bd9ee2008-11-21 00:06:27 +0000184 object_size_ (object_size),
temporal779f61c2008-08-13 03:15:00 +0000185 descriptor_pool_ ((descriptor_pool == NULL) ?
186 DescriptorPool::generated_pool() :
kenton@google.comd37d46d2009-04-25 02:53:47 +0000187 descriptor_pool),
188 message_factory_ (factory) {
temporal40ee5512008-07-10 02:12:20 +0000189}
190
191GeneratedMessageReflection::~GeneratedMessageReflection() {}
192
temporal779f61c2008-08-13 03:15:00 +0000193const UnknownFieldSet& GeneratedMessageReflection::GetUnknownFields(
194 const Message& message) const {
195 const void* ptr = reinterpret_cast<const uint8*>(&message) +
196 unknown_fields_offset_;
197 return *reinterpret_cast<const UnknownFieldSet*>(ptr);
temporal40ee5512008-07-10 02:12:20 +0000198}
temporal779f61c2008-08-13 03:15:00 +0000199UnknownFieldSet* GeneratedMessageReflection::MutableUnknownFields(
200 Message* message) const {
201 void* ptr = reinterpret_cast<uint8*>(message) + unknown_fields_offset_;
202 return reinterpret_cast<UnknownFieldSet*>(ptr);
temporal40ee5512008-07-10 02:12:20 +0000203}
204
kenton@google.com26bd9ee2008-11-21 00:06:27 +0000205int GeneratedMessageReflection::SpaceUsed(const Message& message) const {
206 // object_size_ already includes the in-memory representation of each field
207 // in the message, so we only need to account for additional memory used by
208 // the fields.
209 int total_size = object_size_;
210
211 total_size += GetUnknownFields(message).SpaceUsedExcludingSelf();
212
213 if (extensions_offset_ != -1) {
214 total_size += GetExtensionSet(message).SpaceUsedExcludingSelf();
215 }
216
217 for (int i = 0; i < descriptor_->field_count(); i++) {
218 const FieldDescriptor* field = descriptor_->field(i);
219
220 if (field->is_repeated()) {
kenton@google.com80b1d622009-07-29 01:13:20 +0000221 switch (field->cpp_type()) {
222#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \
223 case FieldDescriptor::CPPTYPE_##UPPERCASE : \
224 total_size += GetRaw<RepeatedField<LOWERCASE> >(message, field) \
225 .SpaceUsedExcludingSelf(); \
226 break
227
228 HANDLE_TYPE( INT32, int32);
229 HANDLE_TYPE( INT64, int64);
230 HANDLE_TYPE(UINT32, uint32);
231 HANDLE_TYPE(UINT64, uint64);
232 HANDLE_TYPE(DOUBLE, double);
233 HANDLE_TYPE( FLOAT, float);
234 HANDLE_TYPE( BOOL, bool);
235 HANDLE_TYPE( ENUM, int);
236#undef HANDLE_TYPE
237
238 case FieldDescriptor::CPPTYPE_STRING:
kenton@google.comfccb1462009-12-18 02:11:36 +0000239 switch (field->options().ctype()) {
240 default: // TODO(kenton): Support other string reps.
241 case FieldOptions::STRING:
242 total_size += GetRaw<RepeatedPtrField<string> >(message, field)
243 .SpaceUsedExcludingSelf();
244 break;
245 }
kenton@google.com80b1d622009-07-29 01:13:20 +0000246 break;
247
248 case FieldDescriptor::CPPTYPE_MESSAGE:
249 // We don't know which subclass of RepeatedPtrFieldBase the type is,
250 // so we use RepeatedPtrFieldBase directly.
251 total_size +=
252 GetRaw<RepeatedPtrFieldBase>(message, field)
253 .SpaceUsedExcludingSelf<GenericTypeHandler<Message> >();
254 break;
255 }
kenton@google.com26bd9ee2008-11-21 00:06:27 +0000256 } else {
257 switch (field->cpp_type()) {
258 case FieldDescriptor::CPPTYPE_INT32 :
259 case FieldDescriptor::CPPTYPE_INT64 :
260 case FieldDescriptor::CPPTYPE_UINT32:
261 case FieldDescriptor::CPPTYPE_UINT64:
262 case FieldDescriptor::CPPTYPE_DOUBLE:
263 case FieldDescriptor::CPPTYPE_FLOAT :
264 case FieldDescriptor::CPPTYPE_BOOL :
265 case FieldDescriptor::CPPTYPE_ENUM :
266 // Field is inline, so we've already counted it.
267 break;
268
269 case FieldDescriptor::CPPTYPE_STRING: {
kenton@google.comfccb1462009-12-18 02:11:36 +0000270 switch (field->options().ctype()) {
271 default: // TODO(kenton): Support other string reps.
272 case FieldOptions::STRING: {
273 const string* ptr = GetField<const string*>(message, field);
kenton@google.com26bd9ee2008-11-21 00:06:27 +0000274
kenton@google.comfccb1462009-12-18 02:11:36 +0000275 // Initially, the string points to the default value stored in
276 // the prototype. Only count the string if it has been changed
277 // from the default value.
278 const string* default_ptr = DefaultRaw<const string*>(field);
kenton@google.com26bd9ee2008-11-21 00:06:27 +0000279
kenton@google.comfccb1462009-12-18 02:11:36 +0000280 if (ptr != default_ptr) {
281 // string fields are represented by just a pointer, so also
282 // include sizeof(string) as well.
283 total_size += sizeof(*ptr) + StringSpaceUsedExcludingSelf(*ptr);
284 }
285 break;
kenton@google.com26bd9ee2008-11-21 00:06:27 +0000286 }
kenton@google.comfccb1462009-12-18 02:11:36 +0000287 }
kenton@google.com26bd9ee2008-11-21 00:06:27 +0000288 break;
289 }
290
291 case FieldDescriptor::CPPTYPE_MESSAGE:
292 if (&message == default_instance_) {
293 // For singular fields, the prototype just stores a pointer to the
294 // external type's prototype, so there is no extra memory usage.
295 } else {
296 const Message* sub_message = GetRaw<const Message*>(message, field);
297 if (sub_message != NULL) {
298 total_size += sub_message->SpaceUsed();
299 }
300 }
301 break;
302 }
303 }
304 }
305
306 return total_size;
307}
308
kenton@google.comceb561d2009-06-25 19:05:36 +0000309void GeneratedMessageReflection::Swap(
310 Message* message1,
311 Message* message2) const {
312 if (message1 == message2) return;
313
kenton@google.com80b1d622009-07-29 01:13:20 +0000314 // TODO(kenton): Other Reflection methods should probably check this too.
kenton@google.comceb561d2009-06-25 19:05:36 +0000315 GOOGLE_CHECK_EQ(message1->GetReflection(), this)
kenton@google.com80b1d622009-07-29 01:13:20 +0000316 << "First argument to Swap() (of type \""
317 << message1->GetDescriptor()->full_name()
318 << "\") is not compatible with this reflection object (which is for type \""
319 << descriptor_->full_name()
320 << "\"). Note that the exact same class is required; not just the same "
321 "descriptor.";
kenton@google.comceb561d2009-06-25 19:05:36 +0000322 GOOGLE_CHECK_EQ(message2->GetReflection(), this)
kenton@google.com80b1d622009-07-29 01:13:20 +0000323 << "Second argument to Swap() (of type \""
324 << message1->GetDescriptor()->full_name()
325 << "\") is not compatible with this reflection object (which is for type \""
326 << descriptor_->full_name()
327 << "\"). Note that the exact same class is required; not just the same "
328 "descriptor.";
kenton@google.comceb561d2009-06-25 19:05:36 +0000329
330 uint32* has_bits1 = MutableHasBits(message1);
331 uint32* has_bits2 = MutableHasBits(message2);
332 int has_bits_size = (descriptor_->field_count() + 31) / 32;
333
334 for (int i = 0; i < has_bits_size; i++) {
kenton@google.com7fb9ae92009-09-02 02:42:56 +0000335 std::swap(has_bits1[i], has_bits2[i]);
kenton@google.comceb561d2009-06-25 19:05:36 +0000336 }
337
338 for (int i = 0; i < descriptor_->field_count(); i++) {
339 const FieldDescriptor* field = descriptor_->field(i);
340 if (field->is_repeated()) {
kenton@google.com80b1d622009-07-29 01:13:20 +0000341 switch (field->cpp_type()) {
342#define SWAP_ARRAYS(CPPTYPE, TYPE) \
343 case FieldDescriptor::CPPTYPE_##CPPTYPE: \
344 MutableRaw<RepeatedField<TYPE> >(message1, field)->Swap( \
345 MutableRaw<RepeatedField<TYPE> >(message2, field)); \
346 break;
347
348 SWAP_ARRAYS(INT32 , int32 );
349 SWAP_ARRAYS(INT64 , int64 );
350 SWAP_ARRAYS(UINT32, uint32);
351 SWAP_ARRAYS(UINT64, uint64);
352 SWAP_ARRAYS(FLOAT , float );
353 SWAP_ARRAYS(DOUBLE, double);
354 SWAP_ARRAYS(BOOL , bool );
355 SWAP_ARRAYS(ENUM , int );
356#undef SWAP_ARRAYS
357
358 case FieldDescriptor::CPPTYPE_STRING:
359 case FieldDescriptor::CPPTYPE_MESSAGE:
360 MutableRaw<RepeatedPtrFieldBase>(message1, field)->Swap(
361 MutableRaw<RepeatedPtrFieldBase>(message2, field));
362 break;
363
364 default:
365 GOOGLE_LOG(FATAL) << "Unimplemented type: " << field->cpp_type();
366 }
kenton@google.comceb561d2009-06-25 19:05:36 +0000367 } else {
368 switch (field->cpp_type()) {
369#define SWAP_VALUES(CPPTYPE, TYPE) \
370 case FieldDescriptor::CPPTYPE_##CPPTYPE: \
kenton@google.com7fb9ae92009-09-02 02:42:56 +0000371 std::swap(*MutableRaw<TYPE>(message1, field), \
372 *MutableRaw<TYPE>(message2, field)); \
kenton@google.comceb561d2009-06-25 19:05:36 +0000373 break;
kenton@google.com80b1d622009-07-29 01:13:20 +0000374
kenton@google.comceb561d2009-06-25 19:05:36 +0000375 SWAP_VALUES(INT32 , int32 );
376 SWAP_VALUES(INT64 , int64 );
377 SWAP_VALUES(UINT32, uint32);
378 SWAP_VALUES(UINT64, uint64);
379 SWAP_VALUES(FLOAT , float );
380 SWAP_VALUES(DOUBLE, double);
381 SWAP_VALUES(BOOL , bool );
kenton@google.com80b1d622009-07-29 01:13:20 +0000382 SWAP_VALUES(ENUM , int );
kenton@google.comceb561d2009-06-25 19:05:36 +0000383 SWAP_VALUES(MESSAGE, Message*);
kenton@google.com80b1d622009-07-29 01:13:20 +0000384#undef SWAP_VALUES
385
386 case FieldDescriptor::CPPTYPE_STRING:
kenton@google.comfccb1462009-12-18 02:11:36 +0000387 switch (field->options().ctype()) {
388 default: // TODO(kenton): Support other string reps.
389 case FieldOptions::STRING:
390 std::swap(*MutableRaw<string*>(message1, field),
391 *MutableRaw<string*>(message2, field));
392 break;
393 }
kenton@google.com80b1d622009-07-29 01:13:20 +0000394 break;
395
kenton@google.comceb561d2009-06-25 19:05:36 +0000396 default:
397 GOOGLE_LOG(FATAL) << "Unimplemented type: " << field->cpp_type();
398 }
399 }
400 }
401
402 if (extensions_offset_ != -1) {
403 MutableExtensionSet(message1)->Swap(MutableExtensionSet(message2));
404 }
405
406 MutableUnknownFields(message1)->Swap(MutableUnknownFields(message2));
407}
408
temporal40ee5512008-07-10 02:12:20 +0000409// -------------------------------------------------------------------
410
temporal779f61c2008-08-13 03:15:00 +0000411bool GeneratedMessageReflection::HasField(const Message& message,
412 const FieldDescriptor* field) const {
temporal40ee5512008-07-10 02:12:20 +0000413 USAGE_CHECK_MESSAGE_TYPE(HasField);
414 USAGE_CHECK_SINGULAR(HasField);
415
416 if (field->is_extension()) {
temporal779f61c2008-08-13 03:15:00 +0000417 return GetExtensionSet(message).Has(field->number());
temporal40ee5512008-07-10 02:12:20 +0000418 } else {
temporal779f61c2008-08-13 03:15:00 +0000419 return HasBit(message, field);
temporal40ee5512008-07-10 02:12:20 +0000420 }
421}
422
temporal779f61c2008-08-13 03:15:00 +0000423int GeneratedMessageReflection::FieldSize(const Message& message,
424 const FieldDescriptor* field) const {
kenton@google.comceb561d2009-06-25 19:05:36 +0000425 USAGE_CHECK_MESSAGE_TYPE(FieldSize);
426 USAGE_CHECK_REPEATED(FieldSize);
temporal40ee5512008-07-10 02:12:20 +0000427
428 if (field->is_extension()) {
temporal779f61c2008-08-13 03:15:00 +0000429 return GetExtensionSet(message).ExtensionSize(field->number());
temporal40ee5512008-07-10 02:12:20 +0000430 } else {
kenton@google.com80b1d622009-07-29 01:13:20 +0000431 switch (field->cpp_type()) {
432#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \
433 case FieldDescriptor::CPPTYPE_##UPPERCASE : \
434 return GetRaw<RepeatedField<LOWERCASE> >(message, field).size()
435
436 HANDLE_TYPE( INT32, int32);
437 HANDLE_TYPE( INT64, int64);
438 HANDLE_TYPE(UINT32, uint32);
439 HANDLE_TYPE(UINT64, uint64);
440 HANDLE_TYPE(DOUBLE, double);
441 HANDLE_TYPE( FLOAT, float);
442 HANDLE_TYPE( BOOL, bool);
443 HANDLE_TYPE( ENUM, int);
444#undef HANDLE_TYPE
445
446 case FieldDescriptor::CPPTYPE_STRING:
447 case FieldDescriptor::CPPTYPE_MESSAGE:
448 return GetRaw<RepeatedPtrFieldBase>(message, field).size();
449 }
450
451 GOOGLE_LOG(FATAL) << "Can't get here.";
452 return 0;
temporal40ee5512008-07-10 02:12:20 +0000453 }
454}
455
temporal779f61c2008-08-13 03:15:00 +0000456void GeneratedMessageReflection::ClearField(
457 Message* message, const FieldDescriptor* field) const {
temporal40ee5512008-07-10 02:12:20 +0000458 USAGE_CHECK_MESSAGE_TYPE(ClearField);
459
460 if (field->is_extension()) {
temporal779f61c2008-08-13 03:15:00 +0000461 MutableExtensionSet(message)->ClearExtension(field->number());
temporal40ee5512008-07-10 02:12:20 +0000462 } else if (!field->is_repeated()) {
temporal779f61c2008-08-13 03:15:00 +0000463 if (HasBit(*message, field)) {
464 ClearBit(message, field);
temporal40ee5512008-07-10 02:12:20 +0000465
466 // We need to set the field back to its default value.
467 switch (field->cpp_type()) {
468#define CLEAR_TYPE(CPPTYPE, TYPE) \
469 case FieldDescriptor::CPPTYPE_##CPPTYPE: \
temporal779f61c2008-08-13 03:15:00 +0000470 *MutableRaw<TYPE>(message, field) = \
471 field->default_value_##TYPE(); \
temporal40ee5512008-07-10 02:12:20 +0000472 break;
473
474 CLEAR_TYPE(INT32 , int32 );
475 CLEAR_TYPE(INT64 , int64 );
476 CLEAR_TYPE(UINT32, uint32);
477 CLEAR_TYPE(UINT64, uint64);
478 CLEAR_TYPE(FLOAT , float );
479 CLEAR_TYPE(DOUBLE, double);
480 CLEAR_TYPE(BOOL , bool );
481#undef CLEAR_TYPE
482
483 case FieldDescriptor::CPPTYPE_ENUM:
temporal779f61c2008-08-13 03:15:00 +0000484 *MutableRaw<int>(message, field) =
485 field->default_value_enum()->number();
temporal40ee5512008-07-10 02:12:20 +0000486 break;
487
488 case FieldDescriptor::CPPTYPE_STRING: {
kenton@google.comfccb1462009-12-18 02:11:36 +0000489 switch (field->options().ctype()) {
490 default: // TODO(kenton): Support other string reps.
491 case FieldOptions::STRING:
492 const string* default_ptr = DefaultRaw<const string*>(field);
493 string** value = MutableRaw<string*>(message, field);
494 if (*value != default_ptr) {
495 if (field->has_default_value()) {
496 (*value)->assign(field->default_value_string());
497 } else {
498 (*value)->clear();
499 }
temporal40ee5512008-07-10 02:12:20 +0000500 }
kenton@google.comfccb1462009-12-18 02:11:36 +0000501 break;
502 }
temporal40ee5512008-07-10 02:12:20 +0000503 break;
504 }
505
506 case FieldDescriptor::CPPTYPE_MESSAGE:
temporal779f61c2008-08-13 03:15:00 +0000507 (*MutableRaw<Message*>(message, field))->Clear();
temporal40ee5512008-07-10 02:12:20 +0000508 break;
509 }
510 }
511 } else {
kenton@google.com80b1d622009-07-29 01:13:20 +0000512 switch (field->cpp_type()) {
513#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \
514 case FieldDescriptor::CPPTYPE_##UPPERCASE : \
515 MutableRaw<RepeatedField<LOWERCASE> >(message, field)->Clear(); \
516 break
517
518 HANDLE_TYPE( INT32, int32);
519 HANDLE_TYPE( INT64, int64);
520 HANDLE_TYPE(UINT32, uint32);
521 HANDLE_TYPE(UINT64, uint64);
522 HANDLE_TYPE(DOUBLE, double);
523 HANDLE_TYPE( FLOAT, float);
524 HANDLE_TYPE( BOOL, bool);
525 HANDLE_TYPE( ENUM, int);
526#undef HANDLE_TYPE
527
528 case FieldDescriptor::CPPTYPE_STRING: {
kenton@google.comfccb1462009-12-18 02:11:36 +0000529 switch (field->options().ctype()) {
530 default: // TODO(kenton): Support other string reps.
531 case FieldOptions::STRING:
532 MutableRaw<RepeatedPtrField<string> >(message, field)->Clear();
533 break;
534 }
kenton@google.com80b1d622009-07-29 01:13:20 +0000535 break;
536 }
537
538 case FieldDescriptor::CPPTYPE_MESSAGE: {
539 // We don't know which subclass of RepeatedPtrFieldBase the type is,
540 // so we use RepeatedPtrFieldBase directly.
541 MutableRaw<RepeatedPtrFieldBase>(message, field)
542 ->Clear<GenericTypeHandler<Message> >();
543 break;
544 }
545 }
temporal40ee5512008-07-10 02:12:20 +0000546 }
547}
548
kenton@google.comceb561d2009-06-25 19:05:36 +0000549void GeneratedMessageReflection::RemoveLast(
550 Message* message,
551 const FieldDescriptor* field) const {
552 USAGE_CHECK_MESSAGE_TYPE(RemoveLast);
553 USAGE_CHECK_REPEATED(RemoveLast);
554
555 if (field->is_extension()) {
556 MutableExtensionSet(message)->RemoveLast(field->number());
557 } else {
kenton@google.com80b1d622009-07-29 01:13:20 +0000558 switch (field->cpp_type()) {
559#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \
560 case FieldDescriptor::CPPTYPE_##UPPERCASE : \
561 MutableRaw<RepeatedField<LOWERCASE> >(message, field)->RemoveLast(); \
562 break
563
564 HANDLE_TYPE( INT32, int32);
565 HANDLE_TYPE( INT64, int64);
566 HANDLE_TYPE(UINT32, uint32);
567 HANDLE_TYPE(UINT64, uint64);
568 HANDLE_TYPE(DOUBLE, double);
569 HANDLE_TYPE( FLOAT, float);
570 HANDLE_TYPE( BOOL, bool);
571 HANDLE_TYPE( ENUM, int);
572#undef HANDLE_TYPE
573
574 case FieldDescriptor::CPPTYPE_STRING:
kenton@google.comfccb1462009-12-18 02:11:36 +0000575 switch (field->options().ctype()) {
576 default: // TODO(kenton): Support other string reps.
577 case FieldOptions::STRING:
578 MutableRaw<RepeatedPtrField<string> >(message, field)->RemoveLast();
579 break;
580 }
kenton@google.com80b1d622009-07-29 01:13:20 +0000581 break;
582
583 case FieldDescriptor::CPPTYPE_MESSAGE:
584 MutableRaw<RepeatedPtrFieldBase>(message, field)
585 ->RemoveLast<GenericTypeHandler<Message> >();
586 break;
587 }
kenton@google.comceb561d2009-06-25 19:05:36 +0000588 }
589}
590
591void GeneratedMessageReflection::SwapElements(
592 Message* message,
593 const FieldDescriptor* field,
594 int index1,
595 int index2) const {
596 USAGE_CHECK_MESSAGE_TYPE(Swap);
597 USAGE_CHECK_REPEATED(Swap);
598
599 if (field->is_extension()) {
kenton@google.com80b1d622009-07-29 01:13:20 +0000600 MutableExtensionSet(message)->SwapElements(field->number(), index1, index2);
kenton@google.comceb561d2009-06-25 19:05:36 +0000601 } else {
kenton@google.com80b1d622009-07-29 01:13:20 +0000602 switch (field->cpp_type()) {
603#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \
604 case FieldDescriptor::CPPTYPE_##UPPERCASE : \
605 MutableRaw<RepeatedField<LOWERCASE> >(message, field) \
606 ->SwapElements(index1, index2); \
607 break
608
609 HANDLE_TYPE( INT32, int32);
610 HANDLE_TYPE( INT64, int64);
611 HANDLE_TYPE(UINT32, uint32);
612 HANDLE_TYPE(UINT64, uint64);
613 HANDLE_TYPE(DOUBLE, double);
614 HANDLE_TYPE( FLOAT, float);
615 HANDLE_TYPE( BOOL, bool);
616 HANDLE_TYPE( ENUM, int);
617#undef HANDLE_TYPE
618
619 case FieldDescriptor::CPPTYPE_STRING:
620 case FieldDescriptor::CPPTYPE_MESSAGE:
621 MutableRaw<RepeatedPtrFieldBase>(message, field)
622 ->SwapElements(index1, index2);
623 break;
624 }
kenton@google.comceb561d2009-06-25 19:05:36 +0000625 }
626}
627
temporal40ee5512008-07-10 02:12:20 +0000628namespace {
629// Comparison functor for sorting FieldDescriptors by field number.
630struct FieldNumberSorter {
631 bool operator()(const FieldDescriptor* left,
632 const FieldDescriptor* right) const {
633 return left->number() < right->number();
634 }
635};
636} // namespace
637
638void GeneratedMessageReflection::ListFields(
temporal779f61c2008-08-13 03:15:00 +0000639 const Message& message,
temporal40ee5512008-07-10 02:12:20 +0000640 vector<const FieldDescriptor*>* output) const {
641 output->clear();
642
643 // Optimization: The default instance never has any fields set.
temporal779f61c2008-08-13 03:15:00 +0000644 if (&message == default_instance_) return;
temporal40ee5512008-07-10 02:12:20 +0000645
646 for (int i = 0; i < descriptor_->field_count(); i++) {
647 const FieldDescriptor* field = descriptor_->field(i);
648 if (field->is_repeated()) {
kenton@google.com80b1d622009-07-29 01:13:20 +0000649 if (FieldSize(message, field) > 0) {
temporal40ee5512008-07-10 02:12:20 +0000650 output->push_back(field);
651 }
652 } else {
temporal779f61c2008-08-13 03:15:00 +0000653 if (HasBit(message, field)) {
temporal40ee5512008-07-10 02:12:20 +0000654 output->push_back(field);
655 }
656 }
657 }
658
temporal779f61c2008-08-13 03:15:00 +0000659 if (extensions_offset_ != -1) {
kenton@google.comd37d46d2009-04-25 02:53:47 +0000660 GetExtensionSet(message).AppendToList(descriptor_, descriptor_pool_,
661 output);
temporal40ee5512008-07-10 02:12:20 +0000662 }
663
664 // ListFields() must sort output by field number.
665 sort(output->begin(), output->end(), FieldNumberSorter());
666}
667
668// -------------------------------------------------------------------
669
670#undef DEFINE_PRIMITIVE_ACCESSORS
671#define DEFINE_PRIMITIVE_ACCESSORS(TYPENAME, TYPE, PASSTYPE, CPPTYPE) \
672 PASSTYPE GeneratedMessageReflection::Get##TYPENAME( \
temporal779f61c2008-08-13 03:15:00 +0000673 const Message& message, const FieldDescriptor* field) const { \
temporal40ee5512008-07-10 02:12:20 +0000674 USAGE_CHECK_ALL(Get##TYPENAME, SINGULAR, CPPTYPE); \
675 if (field->is_extension()) { \
kenton@google.comd37d46d2009-04-25 02:53:47 +0000676 return GetExtensionSet(message).Get##TYPENAME( \
677 field->number(), field->default_value_##PASSTYPE()); \
temporal40ee5512008-07-10 02:12:20 +0000678 } else { \
temporal779f61c2008-08-13 03:15:00 +0000679 return GetField<TYPE>(message, field); \
temporal40ee5512008-07-10 02:12:20 +0000680 } \
681 } \
682 \
683 void GeneratedMessageReflection::Set##TYPENAME( \
temporal779f61c2008-08-13 03:15:00 +0000684 Message* message, const FieldDescriptor* field, \
685 PASSTYPE value) const { \
temporal40ee5512008-07-10 02:12:20 +0000686 USAGE_CHECK_ALL(Set##TYPENAME, SINGULAR, CPPTYPE); \
687 if (field->is_extension()) { \
temporal779f61c2008-08-13 03:15:00 +0000688 return MutableExtensionSet(message)->Set##TYPENAME( \
kenton@google.comfccb1462009-12-18 02:11:36 +0000689 field->number(), field->type(), value, field); \
temporal40ee5512008-07-10 02:12:20 +0000690 } else { \
temporal779f61c2008-08-13 03:15:00 +0000691 SetField<TYPE>(message, field, value); \
temporal40ee5512008-07-10 02:12:20 +0000692 } \
693 } \
694 \
695 PASSTYPE GeneratedMessageReflection::GetRepeated##TYPENAME( \
temporal779f61c2008-08-13 03:15:00 +0000696 const Message& message, \
temporal40ee5512008-07-10 02:12:20 +0000697 const FieldDescriptor* field, int index) const { \
698 USAGE_CHECK_ALL(GetRepeated##TYPENAME, REPEATED, CPPTYPE); \
699 if (field->is_extension()) { \
temporal779f61c2008-08-13 03:15:00 +0000700 return GetExtensionSet(message).GetRepeated##TYPENAME( \
701 field->number(), index); \
temporal40ee5512008-07-10 02:12:20 +0000702 } else { \
temporal779f61c2008-08-13 03:15:00 +0000703 return GetRepeatedField<TYPE>(message, field, index); \
temporal40ee5512008-07-10 02:12:20 +0000704 } \
705 } \
706 \
707 void GeneratedMessageReflection::SetRepeated##TYPENAME( \
temporal779f61c2008-08-13 03:15:00 +0000708 Message* message, const FieldDescriptor* field, \
709 int index, PASSTYPE value) const { \
temporal40ee5512008-07-10 02:12:20 +0000710 USAGE_CHECK_ALL(SetRepeated##TYPENAME, REPEATED, CPPTYPE); \
711 if (field->is_extension()) { \
temporal779f61c2008-08-13 03:15:00 +0000712 MutableExtensionSet(message)->SetRepeated##TYPENAME( \
713 field->number(), index, value); \
temporal40ee5512008-07-10 02:12:20 +0000714 } else { \
temporal779f61c2008-08-13 03:15:00 +0000715 SetRepeatedField<TYPE>(message, field, index, value); \
temporal40ee5512008-07-10 02:12:20 +0000716 } \
717 } \
718 \
719 void GeneratedMessageReflection::Add##TYPENAME( \
temporal779f61c2008-08-13 03:15:00 +0000720 Message* message, const FieldDescriptor* field, \
721 PASSTYPE value) const { \
temporal40ee5512008-07-10 02:12:20 +0000722 USAGE_CHECK_ALL(Add##TYPENAME, REPEATED, CPPTYPE); \
723 if (field->is_extension()) { \
kenton@google.comd37d46d2009-04-25 02:53:47 +0000724 MutableExtensionSet(message)->Add##TYPENAME( \
kenton@google.comfccb1462009-12-18 02:11:36 +0000725 field->number(), field->type(), field->options().packed(), value, \
726 field); \
temporal40ee5512008-07-10 02:12:20 +0000727 } else { \
temporal779f61c2008-08-13 03:15:00 +0000728 AddField<TYPE>(message, field, value); \
temporal40ee5512008-07-10 02:12:20 +0000729 } \
730 }
731
732DEFINE_PRIMITIVE_ACCESSORS(Int32 , int32 , int32 , INT32 )
733DEFINE_PRIMITIVE_ACCESSORS(Int64 , int64 , int64 , INT64 )
734DEFINE_PRIMITIVE_ACCESSORS(UInt32, uint32, uint32, UINT32)
735DEFINE_PRIMITIVE_ACCESSORS(UInt64, uint64, uint64, UINT64)
736DEFINE_PRIMITIVE_ACCESSORS(Float , float , float , FLOAT )
737DEFINE_PRIMITIVE_ACCESSORS(Double, double, double, DOUBLE)
738DEFINE_PRIMITIVE_ACCESSORS(Bool , bool , bool , BOOL )
739#undef DEFINE_PRIMITIVE_ACCESSORS
740
741// -------------------------------------------------------------------
742
743string GeneratedMessageReflection::GetString(
temporal779f61c2008-08-13 03:15:00 +0000744 const Message& message, const FieldDescriptor* field) const {
temporal40ee5512008-07-10 02:12:20 +0000745 USAGE_CHECK_ALL(GetString, SINGULAR, STRING);
746 if (field->is_extension()) {
kenton@google.comd37d46d2009-04-25 02:53:47 +0000747 return GetExtensionSet(message).GetString(field->number(),
748 field->default_value_string());
temporal40ee5512008-07-10 02:12:20 +0000749 } else {
kenton@google.comfccb1462009-12-18 02:11:36 +0000750 switch (field->options().ctype()) {
751 default: // TODO(kenton): Support other string reps.
752 case FieldOptions::STRING:
753 return *GetField<const string*>(message, field);
754 }
755
756 GOOGLE_LOG(FATAL) << "Can't get here.";
757 return kEmptyString; // Make compiler happy.
temporal40ee5512008-07-10 02:12:20 +0000758 }
759}
760
761const string& GeneratedMessageReflection::GetStringReference(
temporal779f61c2008-08-13 03:15:00 +0000762 const Message& message,
temporal40ee5512008-07-10 02:12:20 +0000763 const FieldDescriptor* field, string* scratch) const {
764 USAGE_CHECK_ALL(GetStringReference, SINGULAR, STRING);
765 if (field->is_extension()) {
kenton@google.comd37d46d2009-04-25 02:53:47 +0000766 return GetExtensionSet(message).GetString(field->number(),
767 field->default_value_string());
temporal40ee5512008-07-10 02:12:20 +0000768 } else {
kenton@google.comfccb1462009-12-18 02:11:36 +0000769 switch (field->options().ctype()) {
770 default: // TODO(kenton): Support other string reps.
771 case FieldOptions::STRING:
772 return *GetField<const string*>(message, field);
773 }
774
775 GOOGLE_LOG(FATAL) << "Can't get here.";
776 return kEmptyString; // Make compiler happy.
temporal40ee5512008-07-10 02:12:20 +0000777 }
778}
779
780
781void GeneratedMessageReflection::SetString(
temporal779f61c2008-08-13 03:15:00 +0000782 Message* message, const FieldDescriptor* field,
783 const string& value) const {
temporal40ee5512008-07-10 02:12:20 +0000784 USAGE_CHECK_ALL(SetString, SINGULAR, STRING);
785 if (field->is_extension()) {
kenton@google.comd37d46d2009-04-25 02:53:47 +0000786 return MutableExtensionSet(message)->SetString(field->number(),
kenton@google.comfccb1462009-12-18 02:11:36 +0000787 field->type(), value, field);
temporal40ee5512008-07-10 02:12:20 +0000788 } else {
kenton@google.comfccb1462009-12-18 02:11:36 +0000789 switch (field->options().ctype()) {
790 default: // TODO(kenton): Support other string reps.
791 case FieldOptions::STRING: {
792 string** ptr = MutableField<string*>(message, field);
793 if (*ptr == DefaultRaw<const string*>(field)) {
794 *ptr = new string(value);
795 } else {
796 (*ptr)->assign(value);
797 }
798 break;
799 }
temporal40ee5512008-07-10 02:12:20 +0000800 }
801 }
802}
803
804
805string GeneratedMessageReflection::GetRepeatedString(
temporal779f61c2008-08-13 03:15:00 +0000806 const Message& message, const FieldDescriptor* field, int index) const {
temporal40ee5512008-07-10 02:12:20 +0000807 USAGE_CHECK_ALL(GetRepeatedString, REPEATED, STRING);
808 if (field->is_extension()) {
temporal779f61c2008-08-13 03:15:00 +0000809 return GetExtensionSet(message).GetRepeatedString(field->number(), index);
temporal40ee5512008-07-10 02:12:20 +0000810 } else {
kenton@google.comfccb1462009-12-18 02:11:36 +0000811 switch (field->options().ctype()) {
812 default: // TODO(kenton): Support other string reps.
813 case FieldOptions::STRING:
814 return GetRepeatedPtrField<string>(message, field, index);
815 }
816
817 GOOGLE_LOG(FATAL) << "Can't get here.";
818 return kEmptyString; // Make compiler happy.
temporal40ee5512008-07-10 02:12:20 +0000819 }
820}
821
822const string& GeneratedMessageReflection::GetRepeatedStringReference(
temporal779f61c2008-08-13 03:15:00 +0000823 const Message& message, const FieldDescriptor* field,
824 int index, string* scratch) const {
temporal40ee5512008-07-10 02:12:20 +0000825 USAGE_CHECK_ALL(GetRepeatedStringReference, REPEATED, STRING);
826 if (field->is_extension()) {
temporal779f61c2008-08-13 03:15:00 +0000827 return GetExtensionSet(message).GetRepeatedString(field->number(), index);
temporal40ee5512008-07-10 02:12:20 +0000828 } else {
kenton@google.comfccb1462009-12-18 02:11:36 +0000829 switch (field->options().ctype()) {
830 default: // TODO(kenton): Support other string reps.
831 case FieldOptions::STRING:
832 return GetRepeatedPtrField<string>(message, field, index);
833 }
834
835 GOOGLE_LOG(FATAL) << "Can't get here.";
836 return kEmptyString; // Make compiler happy.
temporal40ee5512008-07-10 02:12:20 +0000837 }
838}
839
840
841void GeneratedMessageReflection::SetRepeatedString(
temporal779f61c2008-08-13 03:15:00 +0000842 Message* message, const FieldDescriptor* field,
843 int index, const string& value) const {
temporal40ee5512008-07-10 02:12:20 +0000844 USAGE_CHECK_ALL(SetRepeatedString, REPEATED, STRING);
845 if (field->is_extension()) {
temporal779f61c2008-08-13 03:15:00 +0000846 MutableExtensionSet(message)->SetRepeatedString(
847 field->number(), index, value);
temporal40ee5512008-07-10 02:12:20 +0000848 } else {
kenton@google.comfccb1462009-12-18 02:11:36 +0000849 switch (field->options().ctype()) {
850 default: // TODO(kenton): Support other string reps.
851 case FieldOptions::STRING:
852 *MutableRepeatedField<string>(message, field, index) = value;
853 break;
854 }
temporal40ee5512008-07-10 02:12:20 +0000855 }
856}
857
858
859void GeneratedMessageReflection::AddString(
temporal779f61c2008-08-13 03:15:00 +0000860 Message* message, const FieldDescriptor* field,
861 const string& value) const {
temporal40ee5512008-07-10 02:12:20 +0000862 USAGE_CHECK_ALL(AddString, REPEATED, STRING);
863 if (field->is_extension()) {
kenton@google.comd37d46d2009-04-25 02:53:47 +0000864 MutableExtensionSet(message)->AddString(field->number(),
kenton@google.comfccb1462009-12-18 02:11:36 +0000865 field->type(), value, field);
temporal40ee5512008-07-10 02:12:20 +0000866 } else {
kenton@google.comfccb1462009-12-18 02:11:36 +0000867 switch (field->options().ctype()) {
868 default: // TODO(kenton): Support other string reps.
869 case FieldOptions::STRING:
870 *AddField<string>(message, field) = value;
871 break;
872 }
temporal40ee5512008-07-10 02:12:20 +0000873 }
874}
875
876
877// -------------------------------------------------------------------
878
879const EnumValueDescriptor* GeneratedMessageReflection::GetEnum(
temporal779f61c2008-08-13 03:15:00 +0000880 const Message& message, const FieldDescriptor* field) const {
temporal40ee5512008-07-10 02:12:20 +0000881 USAGE_CHECK_ALL(GetEnum, SINGULAR, ENUM);
882
883 int value;
884 if (field->is_extension()) {
kenton@google.comd37d46d2009-04-25 02:53:47 +0000885 value = GetExtensionSet(message).GetEnum(
886 field->number(), field->default_value_enum()->number());
temporal40ee5512008-07-10 02:12:20 +0000887 } else {
temporal779f61c2008-08-13 03:15:00 +0000888 value = GetField<int>(message, field);
temporal40ee5512008-07-10 02:12:20 +0000889 }
890 const EnumValueDescriptor* result =
891 field->enum_type()->FindValueByNumber(value);
892 GOOGLE_CHECK(result != NULL);
893 return result;
894}
895
temporal779f61c2008-08-13 03:15:00 +0000896void GeneratedMessageReflection::SetEnum(
897 Message* message, const FieldDescriptor* field,
898 const EnumValueDescriptor* value) const {
temporal40ee5512008-07-10 02:12:20 +0000899 USAGE_CHECK_ALL(SetEnum, SINGULAR, ENUM);
900 USAGE_CHECK_ENUM_VALUE(SetEnum);
901
902 if (field->is_extension()) {
kenton@google.comd37d46d2009-04-25 02:53:47 +0000903 MutableExtensionSet(message)->SetEnum(field->number(), field->type(),
kenton@google.comfccb1462009-12-18 02:11:36 +0000904 value->number(), field);
temporal40ee5512008-07-10 02:12:20 +0000905 } else {
temporal779f61c2008-08-13 03:15:00 +0000906 SetField<int>(message, field, value->number());
temporal40ee5512008-07-10 02:12:20 +0000907 }
908}
909
910const EnumValueDescriptor* GeneratedMessageReflection::GetRepeatedEnum(
temporal779f61c2008-08-13 03:15:00 +0000911 const Message& message, const FieldDescriptor* field, int index) const {
temporal40ee5512008-07-10 02:12:20 +0000912 USAGE_CHECK_ALL(GetRepeatedEnum, REPEATED, ENUM);
913
914 int value;
915 if (field->is_extension()) {
temporal779f61c2008-08-13 03:15:00 +0000916 value = GetExtensionSet(message).GetRepeatedEnum(field->number(), index);
temporal40ee5512008-07-10 02:12:20 +0000917 } else {
temporal779f61c2008-08-13 03:15:00 +0000918 value = GetRepeatedField<int>(message, field, index);
temporal40ee5512008-07-10 02:12:20 +0000919 }
920 const EnumValueDescriptor* result =
921 field->enum_type()->FindValueByNumber(value);
922 GOOGLE_CHECK(result != NULL);
923 return result;
924}
925
926void GeneratedMessageReflection::SetRepeatedEnum(
temporal779f61c2008-08-13 03:15:00 +0000927 Message* message,
temporal40ee5512008-07-10 02:12:20 +0000928 const FieldDescriptor* field, int index,
temporal779f61c2008-08-13 03:15:00 +0000929 const EnumValueDescriptor* value) const {
temporal40ee5512008-07-10 02:12:20 +0000930 USAGE_CHECK_ALL(SetRepeatedEnum, REPEATED, ENUM);
931 USAGE_CHECK_ENUM_VALUE(SetRepeatedEnum);
932
933 if (field->is_extension()) {
temporal779f61c2008-08-13 03:15:00 +0000934 MutableExtensionSet(message)->SetRepeatedEnum(
935 field->number(), index, value->number());
temporal40ee5512008-07-10 02:12:20 +0000936 } else {
temporal779f61c2008-08-13 03:15:00 +0000937 SetRepeatedField<int>(message, field, index, value->number());
temporal40ee5512008-07-10 02:12:20 +0000938 }
939}
940
temporal779f61c2008-08-13 03:15:00 +0000941void GeneratedMessageReflection::AddEnum(
942 Message* message, const FieldDescriptor* field,
943 const EnumValueDescriptor* value) const {
temporal40ee5512008-07-10 02:12:20 +0000944 USAGE_CHECK_ALL(AddEnum, REPEATED, ENUM);
945 USAGE_CHECK_ENUM_VALUE(AddEnum);
946
947 if (field->is_extension()) {
kenton@google.comd37d46d2009-04-25 02:53:47 +0000948 MutableExtensionSet(message)->AddEnum(field->number(), field->type(),
949 field->options().packed(),
kenton@google.comfccb1462009-12-18 02:11:36 +0000950 value->number(), field);
temporal40ee5512008-07-10 02:12:20 +0000951 } else {
temporal779f61c2008-08-13 03:15:00 +0000952 AddField<int>(message, field, value->number());
temporal40ee5512008-07-10 02:12:20 +0000953 }
954}
955
956// -------------------------------------------------------------------
957
958const Message& GeneratedMessageReflection::GetMessage(
kenton@google.comfccb1462009-12-18 02:11:36 +0000959 const Message& message, const FieldDescriptor* field,
960 MessageFactory* factory) const {
temporal40ee5512008-07-10 02:12:20 +0000961 USAGE_CHECK_ALL(GetMessage, SINGULAR, MESSAGE);
962
963 if (field->is_extension()) {
kenton@google.com80b1d622009-07-29 01:13:20 +0000964 return static_cast<const Message&>(
kenton@google.comfccb1462009-12-18 02:11:36 +0000965 GetExtensionSet(message).GetMessage(
966 field->number(), field->message_type(),
967 factory == NULL ? message_factory_ : factory));
temporal40ee5512008-07-10 02:12:20 +0000968 } else {
temporal779f61c2008-08-13 03:15:00 +0000969 const Message* result = GetRaw<const Message*>(message, field);
temporal40ee5512008-07-10 02:12:20 +0000970 if (result == NULL) {
971 result = DefaultRaw<const Message*>(field);
972 }
973 return *result;
974 }
975}
976
977Message* GeneratedMessageReflection::MutableMessage(
kenton@google.comfccb1462009-12-18 02:11:36 +0000978 Message* message, const FieldDescriptor* field,
979 MessageFactory* factory) const {
temporal40ee5512008-07-10 02:12:20 +0000980 USAGE_CHECK_ALL(MutableMessage, SINGULAR, MESSAGE);
981
982 if (field->is_extension()) {
kenton@google.com80b1d622009-07-29 01:13:20 +0000983 return static_cast<Message*>(
kenton@google.comfccb1462009-12-18 02:11:36 +0000984 MutableExtensionSet(message)->MutableMessage(field,
985 factory == NULL ? message_factory_ : factory));
temporal40ee5512008-07-10 02:12:20 +0000986 } else {
temporal779f61c2008-08-13 03:15:00 +0000987 Message** result = MutableField<Message*>(message, field);
temporal40ee5512008-07-10 02:12:20 +0000988 if (*result == NULL) {
989 const Message* default_message = DefaultRaw<const Message*>(field);
990 *result = default_message->New();
temporal40ee5512008-07-10 02:12:20 +0000991 }
992 return *result;
993 }
994}
995
996const Message& GeneratedMessageReflection::GetRepeatedMessage(
temporal779f61c2008-08-13 03:15:00 +0000997 const Message& message, const FieldDescriptor* field, int index) const {
temporal40ee5512008-07-10 02:12:20 +0000998 USAGE_CHECK_ALL(GetRepeatedMessage, REPEATED, MESSAGE);
999
1000 if (field->is_extension()) {
kenton@google.com80b1d622009-07-29 01:13:20 +00001001 return static_cast<const Message&>(
1002 GetExtensionSet(message).GetRepeatedMessage(field->number(), index));
temporal40ee5512008-07-10 02:12:20 +00001003 } else {
kenton@google.com80b1d622009-07-29 01:13:20 +00001004 return GetRaw<RepeatedPtrFieldBase>(message, field)
1005 .Get<GenericTypeHandler<Message> >(index);
temporal40ee5512008-07-10 02:12:20 +00001006 }
1007}
1008
1009Message* GeneratedMessageReflection::MutableRepeatedMessage(
temporal779f61c2008-08-13 03:15:00 +00001010 Message* message, const FieldDescriptor* field, int index) const {
temporal40ee5512008-07-10 02:12:20 +00001011 USAGE_CHECK_ALL(MutableRepeatedMessage, REPEATED, MESSAGE);
1012
1013 if (field->is_extension()) {
kenton@google.com80b1d622009-07-29 01:13:20 +00001014 return static_cast<Message*>(
1015 MutableExtensionSet(message)->MutableRepeatedMessage(
1016 field->number(), index));
temporal40ee5512008-07-10 02:12:20 +00001017 } else {
kenton@google.com80b1d622009-07-29 01:13:20 +00001018 return MutableRaw<RepeatedPtrFieldBase>(message, field)
1019 ->Mutable<GenericTypeHandler<Message> >(index);
temporal40ee5512008-07-10 02:12:20 +00001020 }
1021}
1022
temporal779f61c2008-08-13 03:15:00 +00001023Message* GeneratedMessageReflection::AddMessage(
kenton@google.comfccb1462009-12-18 02:11:36 +00001024 Message* message, const FieldDescriptor* field,
1025 MessageFactory* factory) const {
temporal40ee5512008-07-10 02:12:20 +00001026 USAGE_CHECK_ALL(AddMessage, REPEATED, MESSAGE);
1027
kenton@google.comfccb1462009-12-18 02:11:36 +00001028 if (factory == NULL) factory = message_factory_;
1029
temporal40ee5512008-07-10 02:12:20 +00001030 if (field->is_extension()) {
kenton@google.com80b1d622009-07-29 01:13:20 +00001031 return static_cast<Message*>(
kenton@google.comfccb1462009-12-18 02:11:36 +00001032 MutableExtensionSet(message)->AddMessage(field, factory));
temporal40ee5512008-07-10 02:12:20 +00001033 } else {
kenton@google.com80b1d622009-07-29 01:13:20 +00001034 // We can't use AddField<Message>() because RepeatedPtrFieldBase doesn't
1035 // know how to allocate one.
1036 RepeatedPtrFieldBase* repeated =
1037 MutableRaw<RepeatedPtrFieldBase>(message, field);
1038 Message* result = repeated->AddFromCleared<GenericTypeHandler<Message> >();
1039 if (result == NULL) {
1040 // We must allocate a new object.
1041 const Message* prototype;
1042 if (repeated->size() == 0) {
kenton@google.comfccb1462009-12-18 02:11:36 +00001043 prototype = factory->GetPrototype(field->message_type());
kenton@google.com80b1d622009-07-29 01:13:20 +00001044 } else {
1045 prototype = &repeated->Get<GenericTypeHandler<Message> >(0);
1046 }
1047 result = prototype->New();
1048 repeated->AddAllocated<GenericTypeHandler<Message> >(result);
1049 }
1050 return result;
temporal40ee5512008-07-10 02:12:20 +00001051 }
1052}
1053
1054// -------------------------------------------------------------------
1055
1056const FieldDescriptor* GeneratedMessageReflection::FindKnownExtensionByName(
1057 const string& name) const {
temporal779f61c2008-08-13 03:15:00 +00001058 if (extensions_offset_ == -1) return NULL;
1059
1060 const FieldDescriptor* result = descriptor_pool_->FindExtensionByName(name);
1061 if (result != NULL && result->containing_type() == descriptor_) {
1062 return result;
1063 }
1064
1065 if (descriptor_->options().message_set_wire_format()) {
1066 // MessageSet extensions may be identified by type name.
1067 const Descriptor* type = descriptor_pool_->FindMessageTypeByName(name);
1068 if (type != NULL) {
1069 // Look for a matching extension in the foreign type's scope.
1070 for (int i = 0; i < type->extension_count(); i++) {
1071 const FieldDescriptor* extension = type->extension(i);
1072 if (extension->containing_type() == descriptor_ &&
1073 extension->type() == FieldDescriptor::TYPE_MESSAGE &&
1074 extension->is_optional() &&
1075 extension->message_type() == type) {
1076 // Found it.
1077 return extension;
1078 }
1079 }
1080 }
1081 }
1082
1083 return NULL;
temporal40ee5512008-07-10 02:12:20 +00001084}
1085
1086const FieldDescriptor* GeneratedMessageReflection::FindKnownExtensionByNumber(
1087 int number) const {
temporal779f61c2008-08-13 03:15:00 +00001088 if (extensions_offset_ == -1) return NULL;
1089 return descriptor_pool_->FindExtensionByNumber(descriptor_, number);
temporal40ee5512008-07-10 02:12:20 +00001090}
1091
1092// ===================================================================
1093// Some private helpers.
1094
1095// These simple template accessors obtain pointers (or references) to
1096// the given field.
1097template <typename Type>
1098inline const Type& GeneratedMessageReflection::GetRaw(
temporal779f61c2008-08-13 03:15:00 +00001099 const Message& message, const FieldDescriptor* field) const {
1100 const void* ptr = reinterpret_cast<const uint8*>(&message) +
temporal40ee5512008-07-10 02:12:20 +00001101 offsets_[field->index()];
1102 return *reinterpret_cast<const Type*>(ptr);
1103}
1104
1105template <typename Type>
1106inline Type* GeneratedMessageReflection::MutableRaw(
temporal779f61c2008-08-13 03:15:00 +00001107 Message* message, const FieldDescriptor* field) const {
1108 void* ptr = reinterpret_cast<uint8*>(message) + offsets_[field->index()];
temporal40ee5512008-07-10 02:12:20 +00001109 return reinterpret_cast<Type*>(ptr);
1110}
1111
1112template <typename Type>
1113inline const Type& GeneratedMessageReflection::DefaultRaw(
1114 const FieldDescriptor* field) const {
temporal779f61c2008-08-13 03:15:00 +00001115 const void* ptr = reinterpret_cast<const uint8*>(default_instance_) +
temporal40ee5512008-07-10 02:12:20 +00001116 offsets_[field->index()];
1117 return *reinterpret_cast<const Type*>(ptr);
1118}
1119
temporal779f61c2008-08-13 03:15:00 +00001120inline const uint32* GeneratedMessageReflection::GetHasBits(
1121 const Message& message) const {
1122 const void* ptr = reinterpret_cast<const uint8*>(&message) + has_bits_offset_;
1123 return reinterpret_cast<const uint32*>(ptr);
1124}
1125inline uint32* GeneratedMessageReflection::MutableHasBits(
1126 Message* message) const {
1127 void* ptr = reinterpret_cast<uint8*>(message) + has_bits_offset_;
1128 return reinterpret_cast<uint32*>(ptr);
1129}
1130
1131inline const ExtensionSet& GeneratedMessageReflection::GetExtensionSet(
1132 const Message& message) const {
1133 GOOGLE_DCHECK_NE(extensions_offset_, -1);
1134 const void* ptr = reinterpret_cast<const uint8*>(&message) +
1135 extensions_offset_;
1136 return *reinterpret_cast<const ExtensionSet*>(ptr);
1137}
1138inline ExtensionSet* GeneratedMessageReflection::MutableExtensionSet(
1139 Message* message) const {
1140 GOOGLE_DCHECK_NE(extensions_offset_, -1);
1141 void* ptr = reinterpret_cast<uint8*>(message) + extensions_offset_;
1142 return reinterpret_cast<ExtensionSet*>(ptr);
1143}
1144
temporal40ee5512008-07-10 02:12:20 +00001145// Simple accessors for manipulating has_bits_.
1146inline bool GeneratedMessageReflection::HasBit(
temporal779f61c2008-08-13 03:15:00 +00001147 const Message& message, const FieldDescriptor* field) const {
1148 return GetHasBits(message)[field->index() / 32] &
1149 (1 << (field->index() % 32));
temporal40ee5512008-07-10 02:12:20 +00001150}
1151
1152inline void GeneratedMessageReflection::SetBit(
temporal779f61c2008-08-13 03:15:00 +00001153 Message* message, const FieldDescriptor* field) const {
1154 MutableHasBits(message)[field->index() / 32] |= (1 << (field->index() % 32));
temporal40ee5512008-07-10 02:12:20 +00001155}
1156
1157inline void GeneratedMessageReflection::ClearBit(
temporal779f61c2008-08-13 03:15:00 +00001158 Message* message, const FieldDescriptor* field) const {
1159 MutableHasBits(message)[field->index() / 32] &= ~(1 << (field->index() % 32));
temporal40ee5512008-07-10 02:12:20 +00001160}
1161
1162// Template implementations of basic accessors. Inline because each
1163// template instance is only called from one location. These are
1164// used for all types except messages.
1165template <typename Type>
1166inline const Type& GeneratedMessageReflection::GetField(
temporal779f61c2008-08-13 03:15:00 +00001167 const Message& message, const FieldDescriptor* field) const {
1168 return GetRaw<Type>(message, field);
temporal40ee5512008-07-10 02:12:20 +00001169}
1170
1171template <typename Type>
1172inline void GeneratedMessageReflection::SetField(
temporal779f61c2008-08-13 03:15:00 +00001173 Message* message, const FieldDescriptor* field, const Type& value) const {
1174 *MutableRaw<Type>(message, field) = value;
1175 SetBit(message, field);
temporal40ee5512008-07-10 02:12:20 +00001176}
1177
1178template <typename Type>
1179inline Type* GeneratedMessageReflection::MutableField(
temporal779f61c2008-08-13 03:15:00 +00001180 Message* message, const FieldDescriptor* field) const {
1181 SetBit(message, field);
1182 return MutableRaw<Type>(message, field);
temporal40ee5512008-07-10 02:12:20 +00001183}
1184
1185template <typename Type>
kenton@google.comfccb1462009-12-18 02:11:36 +00001186inline const Type& GeneratedMessageReflection::GetRepeatedField(
temporal779f61c2008-08-13 03:15:00 +00001187 const Message& message, const FieldDescriptor* field, int index) const {
kenton@google.com80b1d622009-07-29 01:13:20 +00001188 return GetRaw<RepeatedField<Type> >(message, field).Get(index);
1189}
1190
1191template <typename Type>
1192inline const Type& GeneratedMessageReflection::GetRepeatedPtrField(
1193 const Message& message, const FieldDescriptor* field, int index) const {
1194 return GetRaw<RepeatedPtrField<Type> >(message, field).Get(index);
temporal40ee5512008-07-10 02:12:20 +00001195}
1196
1197template <typename Type>
1198inline void GeneratedMessageReflection::SetRepeatedField(
temporal779f61c2008-08-13 03:15:00 +00001199 Message* message, const FieldDescriptor* field,
kenton@google.com80b1d622009-07-29 01:13:20 +00001200 int index, Type value) const {
1201 MutableRaw<RepeatedField<Type> >(message, field)->Set(index, value);
temporal40ee5512008-07-10 02:12:20 +00001202}
1203
1204template <typename Type>
1205inline Type* GeneratedMessageReflection::MutableRepeatedField(
temporal779f61c2008-08-13 03:15:00 +00001206 Message* message, const FieldDescriptor* field, int index) const {
kenton@google.com80b1d622009-07-29 01:13:20 +00001207 RepeatedPtrField<Type>* repeated =
1208 MutableRaw<RepeatedPtrField<Type> >(message, field);
1209 return repeated->Mutable(index);
temporal40ee5512008-07-10 02:12:20 +00001210}
1211
1212template <typename Type>
1213inline void GeneratedMessageReflection::AddField(
kenton@google.comfccb1462009-12-18 02:11:36 +00001214 Message* message, const FieldDescriptor* field, const Type& value) const {
kenton@google.com80b1d622009-07-29 01:13:20 +00001215 MutableRaw<RepeatedField<Type> >(message, field)->Add(value);
temporal40ee5512008-07-10 02:12:20 +00001216}
1217
1218template <typename Type>
1219inline Type* GeneratedMessageReflection::AddField(
temporal779f61c2008-08-13 03:15:00 +00001220 Message* message, const FieldDescriptor* field) const {
kenton@google.com80b1d622009-07-29 01:13:20 +00001221 RepeatedPtrField<Type>* repeated =
1222 MutableRaw<RepeatedPtrField<Type> >(message, field);
1223 return repeated->Add();
temporal40ee5512008-07-10 02:12:20 +00001224}
1225
temporal40ee5512008-07-10 02:12:20 +00001226} // namespace internal
1227} // namespace protobuf
1228} // namespace google