1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.
3 // http://code.google.com/p/protobuf/
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
9 // http://www.apache.org/licenses/LICENSE-2.0
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.
17 // Author: kenton@google.com (Kenton Varda)
18 // Based on original Protocol Buffers design by
19 // Sanjay Ghemawat, Jeff Dean, and others.
21 #include <google/protobuf/reflection_ops.h>
22 #include <google/protobuf/descriptor.h>
23 #include <google/protobuf/unknown_field_set.h>
24 #include <google/protobuf/stubs/strutil.h>
30 void ReflectionOps::Copy(const Descriptor
* descriptor
,
31 const Message::Reflection
& from
,
32 Message::Reflection
* to
) {
33 if (&from
== to
) return;
34 Clear(descriptor
, to
);
35 Merge(descriptor
, from
, to
);
38 void ReflectionOps::Merge(const Descriptor
* descriptor
,
39 const Message::Reflection
& from
,
40 Message::Reflection
* to
) {
41 GOOGLE_CHECK_NE(&from
, to
);
42 vector
<const FieldDescriptor
*> fields
;
43 from
.ListFields(&fields
);
44 for (int i
= 0; i
< fields
.size(); i
++) {
45 const FieldDescriptor
* field
= fields
[i
];
47 if (field
->is_repeated()) {
48 int count
= from
.FieldSize(field
);
49 for (int j
= 0; j
< count
; j
++) {
50 switch (field
->cpp_type()) {
51 #define HANDLE_TYPE(CPPTYPE, METHOD) \
52 case FieldDescriptor::CPPTYPE_##CPPTYPE: \
53 to->Add##METHOD(field, \
54 from.GetRepeated##METHOD(field, j)); \
57 HANDLE_TYPE(INT32
, Int32
);
58 HANDLE_TYPE(INT64
, Int64
);
59 HANDLE_TYPE(UINT32
, UInt32
);
60 HANDLE_TYPE(UINT64
, UInt64
);
61 HANDLE_TYPE(FLOAT
, Float
);
62 HANDLE_TYPE(DOUBLE
, Double
);
63 HANDLE_TYPE(BOOL
, Bool
);
64 HANDLE_TYPE(STRING
, String
);
65 HANDLE_TYPE(ENUM
, Enum
);
68 case FieldDescriptor::CPPTYPE_MESSAGE
:
69 to
->AddMessage(field
)->MergeFrom(
70 from
.GetRepeatedMessage(field
, j
));
74 } else if (from
.HasField(field
)) {
75 switch (field
->cpp_type()) {
76 #define HANDLE_TYPE(CPPTYPE, METHOD) \
77 case FieldDescriptor::CPPTYPE_##CPPTYPE: \
78 to->Set##METHOD(field, from.Get##METHOD(field)); \
81 HANDLE_TYPE(INT32
, Int32
);
82 HANDLE_TYPE(INT64
, Int64
);
83 HANDLE_TYPE(UINT32
, UInt32
);
84 HANDLE_TYPE(UINT64
, UInt64
);
85 HANDLE_TYPE(FLOAT
, Float
);
86 HANDLE_TYPE(DOUBLE
, Double
);
87 HANDLE_TYPE(BOOL
, Bool
);
88 HANDLE_TYPE(STRING
, String
);
89 HANDLE_TYPE(ENUM
, Enum
);
92 case FieldDescriptor::CPPTYPE_MESSAGE
:
93 to
->MutableMessage(field
)->MergeFrom(
94 from
.GetMessage(field
));
100 to
->MutableUnknownFields()->MergeFrom(from
.GetUnknownFields());
103 void ReflectionOps::Clear(const Descriptor
* descriptor
,
104 Message::Reflection
* reflection
) {
105 vector
<const FieldDescriptor
*> fields
;
106 reflection
->ListFields(&fields
);
107 for (int i
= 0; i
< fields
.size(); i
++) {
108 reflection
->ClearField(fields
[i
]);
111 reflection
->MutableUnknownFields()->Clear();
114 bool ReflectionOps::IsInitialized(const Descriptor
* descriptor
,
115 const Message::Reflection
& reflection
) {
116 // Check required fields of this message.
117 for (int i
= 0; i
< descriptor
->field_count(); i
++) {
118 if (descriptor
->field(i
)->is_required()) {
119 if (!reflection
.HasField(descriptor
->field(i
))) {
125 // Check that sub-messages are initialized.
126 vector
<const FieldDescriptor
*> fields
;
127 reflection
.ListFields(&fields
);
128 for (int i
= 0; i
< fields
.size(); i
++) {
129 const FieldDescriptor
* field
= fields
[i
];
130 if (field
->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE
) {
131 if (field
->is_repeated()) {
132 int size
= reflection
.FieldSize(field
);
134 for (int i
= 0; i
< size
; i
++) {
135 if (!reflection
.GetRepeatedMessage(field
, i
).IsInitialized()) {
140 if (reflection
.HasField(field
) &&
141 !reflection
.GetMessage(field
).IsInitialized()) {
151 void ReflectionOps::DiscardUnknownFields(
152 const Descriptor
* descriptor
,
153 Message::Reflection
* reflection
) {
154 reflection
->MutableUnknownFields()->Clear();
156 vector
<const FieldDescriptor
*> fields
;
157 reflection
->ListFields(&fields
);
158 for (int i
= 0; i
< fields
.size(); i
++) {
159 const FieldDescriptor
* field
= fields
[i
];
160 if (field
->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE
) {
161 if (field
->is_repeated()) {
162 int size
= reflection
->FieldSize(field
);
163 for (int i
= 0; i
< size
; i
++) {
164 reflection
->MutableRepeatedMessage(field
, i
)->DiscardUnknownFields();
167 if (reflection
->HasField(field
)) {
168 reflection
->MutableMessage(field
)->DiscardUnknownFields();
175 static string
SubMessagePrefix(const string
& prefix
,
176 const FieldDescriptor
* field
,
178 string
result(prefix
);
179 if (field
->is_extension()) {
181 result
.append(field
->full_name());
184 result
.append(field
->name());
188 result
.append(SimpleItoa(index
));
195 void ReflectionOps::FindInitializationErrors(
196 const Descriptor
* descriptor
,
197 const Message::Reflection
& reflection
,
198 const string
& prefix
,
199 vector
<string
>* errors
) {
200 // Check required fields of this message.
201 for (int i
= 0; i
< descriptor
->field_count(); i
++) {
202 if (descriptor
->field(i
)->is_required()) {
203 if (!reflection
.HasField(descriptor
->field(i
))) {
204 errors
->push_back(prefix
+ descriptor
->field(i
)->name());
209 // Check sub-messages.
210 vector
<const FieldDescriptor
*> fields
;
211 reflection
.ListFields(&fields
);
212 for (int i
= 0; i
< fields
.size(); i
++) {
213 const FieldDescriptor
* field
= fields
[i
];
214 if (field
->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE
) {
216 if (field
->is_repeated()) {
217 int size
= reflection
.FieldSize(field
);
219 for (int i
= 0; i
< size
; i
++) {
220 const Message
& sub_message
= reflection
.GetRepeatedMessage(field
, i
);
221 FindInitializationErrors(field
->message_type(),
222 *sub_message
.GetReflection(),
223 SubMessagePrefix(prefix
, field
, i
),
227 if (reflection
.HasField(field
)) {
228 const Message
& sub_message
= reflection
.GetMessage(field
);
229 FindInitializationErrors(field
->message_type(),
230 *sub_message
.GetReflection(),
231 SubMessagePrefix(prefix
, field
, -1),
239 } // namespace internal
240 } // namespace protobuf
241 } // namespace google