blob: ec17572bbb199df96f970f3a99e0365eef1f6f30 [file] [log] [blame]
temporal40ee5512008-07-10 02:12:20 +00001// Protocol Buffers - Google's data interchange format
2// Copyright 2008 Google Inc.
3// http://code.google.com/p/protobuf/
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16
17// Author: kenton@google.com (Kenton Varda)
18// Based on original Protocol Buffers design by
19// Sanjay Ghemawat, Jeff Dean, and others.
20
21#include <algorithm>
22#include <google/protobuf/generated_message_reflection.h>
23#include <google/protobuf/descriptor.h>
24#include <google/protobuf/descriptor.pb.h>
25#include <google/protobuf/repeated_field.h>
26#include <google/protobuf/extension_set.h>
27#include <google/protobuf/stubs/common.h>
28
29namespace google {
30namespace protobuf {
31namespace internal {
32
33namespace { const string kEmptyString; }
34
35// ===================================================================
36// Helpers for reporting usage errors (e.g. trying to use GetInt32() on
37// a string field).
38
39namespace {
40
41void ReportReflectionUsageError(
42 const Descriptor* descriptor, const FieldDescriptor* field,
43 const char* method, const char* description) {
44 GOOGLE_LOG(FATAL)
45 << "Protocol Buffer reflection usage error:\n"
46 " Method : google::protobuf::Message::Reflection::" << method << "\n"
47 " Message type: " << descriptor->full_name() << "\n"
48 " Field : " << field->full_name() << "\n"
49 " Problem : " << description;
50}
51
52const char* cpptype_names_[FieldDescriptor::MAX_CPPTYPE + 1] = {
53 "INVALID_CPPTYPE",
54 "CPPTYPE_INT32",
55 "CPPTYPE_INT64",
56 "CPPTYPE_UINT32",
57 "CPPTYPE_UINT64",
58 "CPPTYPE_DOUBLE",
59 "CPPTYPE_FLOAT",
60 "CPPTYPE_BOOL",
61 "CPPTYPE_ENUM",
62 "CPPTYPE_STRING",
63 "CPPTYPE_MESSAGE"
64};
65
66static void ReportReflectionUsageTypeError(
67 const Descriptor* descriptor, const FieldDescriptor* field,
68 const char* method,
69 FieldDescriptor::CppType expected_type) {
70 GOOGLE_LOG(FATAL)
71 << "Protocol Buffer reflection usage error:\n"
72 " Method : google::protobuf::Message::Reflection::" << method << "\n"
73 " Message type: " << descriptor->full_name() << "\n"
74 " Field : " << field->full_name() << "\n"
75 " Problem : Field is not the right type for this message:\n"
76 " Expected : " << cpptype_names_[expected_type] << "\n"
77 " Field type: " << cpptype_names_[field->cpp_type()];
78}
79
80static void ReportReflectionUsageEnumTypeError(
81 const Descriptor* descriptor, const FieldDescriptor* field,
82 const char* method, const EnumValueDescriptor* value) {
83 GOOGLE_LOG(FATAL)
84 << "Protocol Buffer reflection usage error:\n"
85 " Method : google::protobuf::Message::Reflection::" << method << "\n"
86 " Message type: " << descriptor->full_name() << "\n"
87 " Field : " << field->full_name() << "\n"
88 " Problem : Enum value did not match field type:\n"
89 " Expected : " << field->enum_type()->full_name() << "\n"
90 " Actual : " << value->full_name();
91}
92
93#define USAGE_CHECK(CONDITION, METHOD, ERROR_DESCRIPTION) \
94 if (!(CONDITION)) \
95 ReportReflectionUsageError(descriptor_, field, #METHOD, ERROR_DESCRIPTION)
96#define USAGE_CHECK_EQ(A, B, METHOD, ERROR_DESCRIPTION) \
97 USAGE_CHECK((A) == (B), METHOD, ERROR_DESCRIPTION)
98#define USAGE_CHECK_NE(A, B, METHOD, ERROR_DESCRIPTION) \
99 USAGE_CHECK((A) != (B), METHOD, ERROR_DESCRIPTION)
100
101#define USAGE_CHECK_TYPE(METHOD, CPPTYPE) \
102 if (field->cpp_type() != FieldDescriptor::CPPTYPE_##CPPTYPE) \
103 ReportReflectionUsageTypeError(descriptor_, field, #METHOD, \
104 FieldDescriptor::CPPTYPE_##CPPTYPE)
105
106#define USAGE_CHECK_ENUM_VALUE(METHOD) \
107 if (value->type() != field->enum_type()) \
108 ReportReflectionUsageEnumTypeError(descriptor_, field, #METHOD, value)
109
110#define USAGE_CHECK_MESSAGE_TYPE(METHOD) \
111 USAGE_CHECK_EQ(field->containing_type(), descriptor_, \
112 METHOD, "Field does not match message type.");
113#define USAGE_CHECK_SINGULAR(METHOD) \
114 USAGE_CHECK_NE(field->label(), FieldDescriptor::LABEL_REPEATED, METHOD, \
115 "Field is repeated; the method requires a singular field.")
116#define USAGE_CHECK_REPEATED(METHOD) \
117 USAGE_CHECK_EQ(field->label(), FieldDescriptor::LABEL_REPEATED, METHOD, \
118 "Field is singular; the method requires a repeated field.")
119
120#define USAGE_CHECK_ALL(METHOD, LABEL, CPPTYPE) \
121 USAGE_CHECK_MESSAGE_TYPE(METHOD); \
122 USAGE_CHECK_##LABEL(METHOD); \
123 USAGE_CHECK_TYPE(METHOD, CPPTYPE)
124
125} // namespace
126
127// ===================================================================
128
129GeneratedMessageReflection::GeneratedMessageReflection(
130 const Descriptor* descriptor,
131 void* base, const void* default_base,
132 const int offsets[], uint32 has_bits[],
133 ExtensionSet* extensions)
134 : descriptor_ (descriptor),
135 base_ (base),
136 default_base_(default_base),
137 offsets_ (offsets),
138 has_bits_ (has_bits),
139 extensions_ (extensions) {
140}
141
142GeneratedMessageReflection::~GeneratedMessageReflection() {}
143
144const UnknownFieldSet& GeneratedMessageReflection::GetUnknownFields() const {
145 return unknown_fields_;
146}
147UnknownFieldSet* GeneratedMessageReflection::MutableUnknownFields() {
148 return &unknown_fields_;
149}
150
151// -------------------------------------------------------------------
152
153bool GeneratedMessageReflection::HasField(const FieldDescriptor* field) const {
154 USAGE_CHECK_MESSAGE_TYPE(HasField);
155 USAGE_CHECK_SINGULAR(HasField);
156
157 if (field->is_extension()) {
158 return extensions_->Has(field->number());
159 } else {
160 return HasBit(field);
161 }
162}
163
164int GeneratedMessageReflection::FieldSize(const FieldDescriptor* field) const {
165 USAGE_CHECK_MESSAGE_TYPE(HasField);
166 USAGE_CHECK_REPEATED(HasField);
167
168 if (field->is_extension()) {
169 return extensions_->ExtensionSize(field->number());
170 } else {
171 return GetRaw<GenericRepeatedField>(field).GenericSize();
172 }
173}
174
175void GeneratedMessageReflection::ClearField(const FieldDescriptor* field) {
176 USAGE_CHECK_MESSAGE_TYPE(ClearField);
177
178 if (field->is_extension()) {
179 extensions_->ClearExtension(field->number());
180 } else if (!field->is_repeated()) {
181 if (HasBit(field)) {
182 ClearBit(field);
183
184 // We need to set the field back to its default value.
185 switch (field->cpp_type()) {
186#define CLEAR_TYPE(CPPTYPE, TYPE) \
187 case FieldDescriptor::CPPTYPE_##CPPTYPE: \
188 *MutableRaw<TYPE>(field) = field->default_value_##TYPE(); \
189 break;
190
191 CLEAR_TYPE(INT32 , int32 );
192 CLEAR_TYPE(INT64 , int64 );
193 CLEAR_TYPE(UINT32, uint32);
194 CLEAR_TYPE(UINT64, uint64);
195 CLEAR_TYPE(FLOAT , float );
196 CLEAR_TYPE(DOUBLE, double);
197 CLEAR_TYPE(BOOL , bool );
198#undef CLEAR_TYPE
199
200 case FieldDescriptor::CPPTYPE_ENUM:
201 *MutableRaw<int>(field) = field->default_value_enum()->number();
202 break;
203
204 case FieldDescriptor::CPPTYPE_STRING: {
205 const string* default_ptr = DefaultRaw<const string*>(field);
206 string** value = MutableRaw<string*>(field);
207 if (*value != default_ptr) {
208 if (field->has_default_value()) {
209 (*value)->assign(field->default_value_string());
210 } else {
211 (*value)->clear();
212 }
213 }
214 break;
215 }
216
217 case FieldDescriptor::CPPTYPE_MESSAGE:
218 (*MutableRaw<Message*>(field))->Clear();
219 break;
220 }
221 }
222 } else {
223 MutableRaw<GenericRepeatedField>(field)->GenericClear();
224 }
225}
226
227namespace {
228// Comparison functor for sorting FieldDescriptors by field number.
229struct FieldNumberSorter {
230 bool operator()(const FieldDescriptor* left,
231 const FieldDescriptor* right) const {
232 return left->number() < right->number();
233 }
234};
235} // namespace
236
237void GeneratedMessageReflection::ListFields(
238 vector<const FieldDescriptor*>* output) const {
239 output->clear();
240
241 // Optimization: The default instance never has any fields set.
242 if (base_ == default_base_) return;
243
244 for (int i = 0; i < descriptor_->field_count(); i++) {
245 const FieldDescriptor* field = descriptor_->field(i);
246 if (field->is_repeated()) {
247 if (GetRaw<GenericRepeatedField>(field).GenericSize() > 0) {
248 output->push_back(field);
249 }
250 } else {
251 if (HasBit(field)) {
252 output->push_back(field);
253 }
254 }
255 }
256
257 if (extensions_ != NULL) {
258 extensions_->AppendToList(output);
259 }
260
261 // ListFields() must sort output by field number.
262 sort(output->begin(), output->end(), FieldNumberSorter());
263}
264
265// -------------------------------------------------------------------
266
267#undef DEFINE_PRIMITIVE_ACCESSORS
268#define DEFINE_PRIMITIVE_ACCESSORS(TYPENAME, TYPE, PASSTYPE, CPPTYPE) \
269 PASSTYPE GeneratedMessageReflection::Get##TYPENAME( \
270 const FieldDescriptor* field) const { \
271 USAGE_CHECK_ALL(Get##TYPENAME, SINGULAR, CPPTYPE); \
272 if (field->is_extension()) { \
273 return extensions_->Get##TYPENAME(field->number()); \
274 } else { \
275 return GetField<TYPE>(field); \
276 } \
277 } \
278 \
279 void GeneratedMessageReflection::Set##TYPENAME( \
280 const FieldDescriptor* field, PASSTYPE value) { \
281 USAGE_CHECK_ALL(Set##TYPENAME, SINGULAR, CPPTYPE); \
282 if (field->is_extension()) { \
283 return extensions_->Set##TYPENAME(field->number(), value); \
284 } else { \
285 SetField<TYPE>(field, value); \
286 } \
287 } \
288 \
289 PASSTYPE GeneratedMessageReflection::GetRepeated##TYPENAME( \
290 const FieldDescriptor* field, int index) const { \
291 USAGE_CHECK_ALL(GetRepeated##TYPENAME, REPEATED, CPPTYPE); \
292 if (field->is_extension()) { \
293 return extensions_->GetRepeated##TYPENAME(field->number(), index); \
294 } else { \
295 return GetRepeatedField<TYPE>(field, index); \
296 } \
297 } \
298 \
299 void GeneratedMessageReflection::SetRepeated##TYPENAME( \
300 const FieldDescriptor* field, int index, PASSTYPE value) { \
301 USAGE_CHECK_ALL(SetRepeated##TYPENAME, REPEATED, CPPTYPE); \
302 if (field->is_extension()) { \
303 extensions_->SetRepeated##TYPENAME(field->number(), index, value); \
304 } else { \
305 SetRepeatedField<TYPE>(field, index, value); \
306 } \
307 } \
308 \
309 void GeneratedMessageReflection::Add##TYPENAME( \
310 const FieldDescriptor* field, PASSTYPE value) { \
311 USAGE_CHECK_ALL(Add##TYPENAME, REPEATED, CPPTYPE); \
312 if (field->is_extension()) { \
313 extensions_->Add##TYPENAME(field->number(), value); \
314 } else { \
315 AddField<TYPE>(field, value); \
316 } \
317 }
318
319DEFINE_PRIMITIVE_ACCESSORS(Int32 , int32 , int32 , INT32 )
320DEFINE_PRIMITIVE_ACCESSORS(Int64 , int64 , int64 , INT64 )
321DEFINE_PRIMITIVE_ACCESSORS(UInt32, uint32, uint32, UINT32)
322DEFINE_PRIMITIVE_ACCESSORS(UInt64, uint64, uint64, UINT64)
323DEFINE_PRIMITIVE_ACCESSORS(Float , float , float , FLOAT )
324DEFINE_PRIMITIVE_ACCESSORS(Double, double, double, DOUBLE)
325DEFINE_PRIMITIVE_ACCESSORS(Bool , bool , bool , BOOL )
326#undef DEFINE_PRIMITIVE_ACCESSORS
327
328// -------------------------------------------------------------------
329
330string GeneratedMessageReflection::GetString(
331 const FieldDescriptor* field) const {
332 USAGE_CHECK_ALL(GetString, SINGULAR, STRING);
333 if (field->is_extension()) {
334 return extensions_->GetString(field->number());
335 } else {
336 return *GetField<const string*>(field);
337 }
338}
339
340const string& GeneratedMessageReflection::GetStringReference(
341 const FieldDescriptor* field, string* scratch) const {
342 USAGE_CHECK_ALL(GetStringReference, SINGULAR, STRING);
343 if (field->is_extension()) {
344 return extensions_->GetString(field->number());
345 } else {
346 return *GetField<const string*>(field);
347 }
348}
349
350
351void GeneratedMessageReflection::SetString(
352 const FieldDescriptor* field, const string& value) {
353 USAGE_CHECK_ALL(SetString, SINGULAR, STRING);
354 if (field->is_extension()) {
355 return extensions_->SetString(field->number(), value);
356 } else {
357 string** ptr = MutableField<string*>(field);
358 if (*ptr == DefaultRaw<const string*>(field)) {
359 *ptr = new string(value);
360 } else {
361 (*ptr)->assign(value);
362 }
363 }
364}
365
366
367string GeneratedMessageReflection::GetRepeatedString(
368 const FieldDescriptor* field, int index) const {
369 USAGE_CHECK_ALL(GetRepeatedString, REPEATED, STRING);
370 if (field->is_extension()) {
371 return extensions_->GetRepeatedString(field->number(), index);
372 } else {
373 return GetRepeatedField<string>(field, index);
374 }
375}
376
377const string& GeneratedMessageReflection::GetRepeatedStringReference(
378 const FieldDescriptor* field, int index, string* scratch) const {
379 USAGE_CHECK_ALL(GetRepeatedStringReference, REPEATED, STRING);
380 if (field->is_extension()) {
381 return extensions_->GetRepeatedString(field->number(), index);
382 } else {
383 return GetRepeatedField<string>(field, index);
384 }
385}
386
387
388void GeneratedMessageReflection::SetRepeatedString(
389 const FieldDescriptor* field, int index, const string& value) {
390 USAGE_CHECK_ALL(SetRepeatedString, REPEATED, STRING);
391 if (field->is_extension()) {
392 extensions_->SetRepeatedString(field->number(), index, value);
393 } else {
394 SetRepeatedField<string>(field, index, value);
395 }
396}
397
398
399void GeneratedMessageReflection::AddString(
400 const FieldDescriptor* field, const string& value) {
401 USAGE_CHECK_ALL(AddString, REPEATED, STRING);
402 if (field->is_extension()) {
403 extensions_->AddString(field->number(), value);
404 } else {
405 AddField<string>(field, value);
406 }
407}
408
409
410// -------------------------------------------------------------------
411
412const EnumValueDescriptor* GeneratedMessageReflection::GetEnum(
413 const FieldDescriptor* field) const {
414 USAGE_CHECK_ALL(GetEnum, SINGULAR, ENUM);
415
416 int value;
417 if (field->is_extension()) {
418 value = extensions_->GetEnum(field->number());
419 } else {
420 value = GetField<int>(field);
421 }
422 const EnumValueDescriptor* result =
423 field->enum_type()->FindValueByNumber(value);
424 GOOGLE_CHECK(result != NULL);
425 return result;
426}
427
428void GeneratedMessageReflection::SetEnum(const FieldDescriptor* field,
429 const EnumValueDescriptor* value) {
430 USAGE_CHECK_ALL(SetEnum, SINGULAR, ENUM);
431 USAGE_CHECK_ENUM_VALUE(SetEnum);
432
433 if (field->is_extension()) {
434 extensions_->SetEnum(field->number(), value->number());
435 } else {
436 SetField<int>(field, value->number());
437 }
438}
439
440const EnumValueDescriptor* GeneratedMessageReflection::GetRepeatedEnum(
441 const FieldDescriptor* field, int index) const {
442 USAGE_CHECK_ALL(GetRepeatedEnum, REPEATED, ENUM);
443
444 int value;
445 if (field->is_extension()) {
446 value = extensions_->GetRepeatedEnum(field->number(), index);
447 } else {
448 value = GetRepeatedField<int>(field, index);
449 }
450 const EnumValueDescriptor* result =
451 field->enum_type()->FindValueByNumber(value);
452 GOOGLE_CHECK(result != NULL);
453 return result;
454}
455
456void GeneratedMessageReflection::SetRepeatedEnum(
457 const FieldDescriptor* field, int index,
458 const EnumValueDescriptor* value) {
459 USAGE_CHECK_ALL(SetRepeatedEnum, REPEATED, ENUM);
460 USAGE_CHECK_ENUM_VALUE(SetRepeatedEnum);
461
462 if (field->is_extension()) {
463 extensions_->SetRepeatedEnum(field->number(), index, value->number());
464 } else {
465 SetRepeatedField<int>(field, index, value->number());
466 }
467}
468
469void GeneratedMessageReflection::AddEnum(const FieldDescriptor* field,
470 const EnumValueDescriptor* value) {
471 USAGE_CHECK_ALL(AddEnum, REPEATED, ENUM);
472 USAGE_CHECK_ENUM_VALUE(AddEnum);
473
474 if (field->is_extension()) {
475 extensions_->AddEnum(field->number(), value->number());
476 } else {
477 AddField<int>(field, value->number());
478 }
479}
480
481// -------------------------------------------------------------------
482
483const Message& GeneratedMessageReflection::GetMessage(
484 const FieldDescriptor* field) const {
485 USAGE_CHECK_ALL(GetMessage, SINGULAR, MESSAGE);
486
487 if (field->is_extension()) {
488 return extensions_->GetMessage(field->number());
489 } else {
490 const Message* result = GetRaw<const Message*>(field);
491 if (result == NULL) {
492 result = DefaultRaw<const Message*>(field);
493 }
494 return *result;
495 }
496}
497
498Message* GeneratedMessageReflection::MutableMessage(
499 const FieldDescriptor* field) {
500 USAGE_CHECK_ALL(MutableMessage, SINGULAR, MESSAGE);
501
502 if (field->is_extension()) {
503 return extensions_->MutableMessage(field->number());
504 } else {
505 Message** result = MutableField<Message*>(field);
506 if (*result == NULL) {
507 const Message* default_message = DefaultRaw<const Message*>(field);
508 *result = default_message->New();
509 (*result)->CopyFrom(*default_message);
510 }
511 return *result;
512 }
513}
514
515const Message& GeneratedMessageReflection::GetRepeatedMessage(
516 const FieldDescriptor* field, int index) const {
517 USAGE_CHECK_ALL(GetRepeatedMessage, REPEATED, MESSAGE);
518
519 if (field->is_extension()) {
520 return extensions_->GetRepeatedMessage(field->number(), index);
521 } else {
522 return GetRepeatedField<Message>(field, index);
523 }
524}
525
526Message* GeneratedMessageReflection::MutableRepeatedMessage(
527 const FieldDescriptor* field, int index) {
528 USAGE_CHECK_ALL(MutableRepeatedMessage, REPEATED, MESSAGE);
529
530 if (field->is_extension()) {
531 return extensions_->MutableRepeatedMessage(field->number(), index);
532 } else {
533 return MutableRepeatedField<Message>(field, index);
534 }
535}
536
537Message* GeneratedMessageReflection::AddMessage(const FieldDescriptor* field) {
538 USAGE_CHECK_ALL(AddMessage, REPEATED, MESSAGE);
539
540 if (field->is_extension()) {
541 return extensions_->AddMessage(field->number());
542 } else {
543 return AddField<Message>(field);
544 }
545}
546
547// -------------------------------------------------------------------
548
549const FieldDescriptor* GeneratedMessageReflection::FindKnownExtensionByName(
550 const string& name) const {
551 if (extensions_ == NULL) return NULL;
552 return extensions_->FindKnownExtensionByName(name);
553}
554
555const FieldDescriptor* GeneratedMessageReflection::FindKnownExtensionByNumber(
556 int number) const {
557 if (extensions_ == NULL) return NULL;
558 return extensions_->FindKnownExtensionByNumber(number);
559}
560
561// ===================================================================
562// Some private helpers.
563
564// These simple template accessors obtain pointers (or references) to
565// the given field.
566template <typename Type>
567inline const Type& GeneratedMessageReflection::GetRaw(
568 const FieldDescriptor* field) const {
569 const void* ptr = reinterpret_cast<const uint8*>(base_) +
570 offsets_[field->index()];
571 return *reinterpret_cast<const Type*>(ptr);
572}
573
574template <typename Type>
575inline Type* GeneratedMessageReflection::MutableRaw(
576 const FieldDescriptor* field) {
577 void* ptr = reinterpret_cast<uint8*>(base_) + offsets_[field->index()];
578 return reinterpret_cast<Type*>(ptr);
579}
580
581template <typename Type>
582inline const Type& GeneratedMessageReflection::DefaultRaw(
583 const FieldDescriptor* field) const {
584 const void* ptr = reinterpret_cast<const uint8*>(default_base_) +
585 offsets_[field->index()];
586 return *reinterpret_cast<const Type*>(ptr);
587}
588
589// Simple accessors for manipulating has_bits_.
590inline bool GeneratedMessageReflection::HasBit(
591 const FieldDescriptor* field) const {
592 return has_bits_[field->index() / 32] & (1 << (field->index() % 32));
593}
594
595inline void GeneratedMessageReflection::SetBit(
596 const FieldDescriptor* field) {
597 has_bits_[field->index() / 32] |= (1 << (field->index() % 32));
598}
599
600inline void GeneratedMessageReflection::ClearBit(
601 const FieldDescriptor* field) {
602 has_bits_[field->index() / 32] &= ~(1 << (field->index() % 32));
603}
604
605// Template implementations of basic accessors. Inline because each
606// template instance is only called from one location. These are
607// used for all types except messages.
608template <typename Type>
609inline const Type& GeneratedMessageReflection::GetField(
610 const FieldDescriptor* field) const {
611 return GetRaw<Type>(field);
612}
613
614template <typename Type>
615inline void GeneratedMessageReflection::SetField(
616 const FieldDescriptor* field, const Type& value) {
617 *MutableRaw<Type>(field) = value;
618 SetBit(field);
619}
620
621template <typename Type>
622inline Type* GeneratedMessageReflection::MutableField(
623 const FieldDescriptor* field) {
624 SetBit(field);
625 return MutableRaw<Type>(field);
626}
627
628template <typename Type>
629inline const Type& GeneratedMessageReflection::GetRepeatedField(
630 const FieldDescriptor* field, int index) const {
631 return *reinterpret_cast<const Type*>(
632 GetRaw<GenericRepeatedField>(field).GenericGet(index));
633}
634
635template <typename Type>
636inline void GeneratedMessageReflection::SetRepeatedField(
637 const FieldDescriptor* field, int index, const Type& value) {
638 GenericRepeatedField* repeated = MutableRaw<GenericRepeatedField>(field);
639 *reinterpret_cast<Type*>(repeated->GenericMutable(index)) = value;
640}
641
642template <typename Type>
643inline Type* GeneratedMessageReflection::MutableRepeatedField(
644 const FieldDescriptor* field, int index) {
645 GenericRepeatedField* repeated = MutableRaw<GenericRepeatedField>(field);
646 return reinterpret_cast<Type*>(repeated->GenericMutable(index));
647}
648
649template <typename Type>
650inline void GeneratedMessageReflection::AddField(
651 const FieldDescriptor* field, const Type& value) {
652 GenericRepeatedField* repeated = MutableRaw<GenericRepeatedField>(field);
653 *reinterpret_cast<Type*>(repeated->GenericAdd()) = value;
654}
655
656template <typename Type>
657inline Type* GeneratedMessageReflection::AddField(
658 const FieldDescriptor* field) {
659 GenericRepeatedField* repeated = MutableRaw<GenericRepeatedField>(field);
660 return reinterpret_cast<Type*>(repeated->GenericAdd());
661}
662
663} // namespace internal
664} // namespace protobuf
665} // namespace google