Initial import of v2.0.0beta
[protobuf.git] / src / google / protobuf / reflection_ops.cc
blob2b263298c7675ff6927184cb547ed55bd62699b9
1 // 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
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>
26 namespace google {
27 namespace protobuf {
28 namespace internal {
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)); \
55 break;
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 );
66 #undef HANDLE_TYPE
68 case FieldDescriptor::CPPTYPE_MESSAGE:
69 to->AddMessage(field)->MergeFrom(
70 from.GetRepeatedMessage(field, j));
71 break;
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)); \
79 break;
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 );
90 #undef HANDLE_TYPE
92 case FieldDescriptor::CPPTYPE_MESSAGE:
93 to->MutableMessage(field)->MergeFrom(
94 from.GetMessage(field));
95 break;
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))) {
120 return false;
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()) {
136 return false;
139 } else {
140 if (reflection.HasField(field) &&
141 !reflection.GetMessage(field).IsInitialized()) {
142 return false;
148 return true;
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();
166 } else {
167 if (reflection->HasField(field)) {
168 reflection->MutableMessage(field)->DiscardUnknownFields();
175 static string SubMessagePrefix(const string& prefix,
176 const FieldDescriptor* field,
177 int index) {
178 string result(prefix);
179 if (field->is_extension()) {
180 result.append("(");
181 result.append(field->full_name());
182 result.append(")");
183 } else {
184 result.append(field->name());
186 if (index != -1) {
187 result.append("[");
188 result.append(SimpleItoa(index));
189 result.append("]");
191 result.append(".");
192 return result;
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),
224 errors);
226 } else {
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),
232 errors);
239 } // namespace internal
240 } // namespace protobuf
241 } // namespace google