1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // http://code.google.com/p/protobuf/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 // * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 // * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 // * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31 // Author: kenton@google.com (Kenton Varda)
32 // Based on original Protocol Buffers design by
33 // Sanjay Ghemawat, Jeff Dean, and others.
34
35 #include <google/protobuf/reflection_ops.h>
36 #include <google/protobuf/descriptor.h>
37 #include <google/protobuf/unknown_field_set.h>
38 #include <google/protobuf/stubs/strutil.h>
39
40 namespace google {
41 namespace protobuf {
42 namespace internal {
43
Copy(const Message & from,Message * to)44 void ReflectionOps::Copy(const Message& from, Message* to) {
45 if (&from == to) return;
46 Clear(to);
47 Merge(from, to);
48 }
49
Merge(const Message & from,Message * to)50 void ReflectionOps::Merge(const Message& from, Message* to) {
51 GOOGLE_CHECK_NE(&from, to);
52
53 const Descriptor* descriptor = from.GetDescriptor();
54 GOOGLE_CHECK_EQ(to->GetDescriptor(), descriptor)
55 << "Tried to merge messages of different types.";
56
57 const Reflection* from_reflection = from.GetReflection();
58 const Reflection* to_reflection = to->GetReflection();
59
60 vector<const FieldDescriptor*> fields;
61 from_reflection->ListFields(from, &fields);
62 for (int i = 0; i < fields.size(); i++) {
63 const FieldDescriptor* field = fields[i];
64
65 if (field->is_repeated()) {
66 int count = from_reflection->FieldSize(from, field);
67 for (int j = 0; j < count; j++) {
68 switch (field->cpp_type()) {
69 #define HANDLE_TYPE(CPPTYPE, METHOD) \
70 case FieldDescriptor::CPPTYPE_##CPPTYPE: \
71 to_reflection->Add##METHOD(to, field, \
72 from_reflection->GetRepeated##METHOD(from, field, j)); \
73 break;
74
75 HANDLE_TYPE(INT32 , Int32 );
76 HANDLE_TYPE(INT64 , Int64 );
77 HANDLE_TYPE(UINT32, UInt32);
78 HANDLE_TYPE(UINT64, UInt64);
79 HANDLE_TYPE(FLOAT , Float );
80 HANDLE_TYPE(DOUBLE, Double);
81 HANDLE_TYPE(BOOL , Bool );
82 HANDLE_TYPE(STRING, String);
83 HANDLE_TYPE(ENUM , Enum );
84 #undef HANDLE_TYPE
85
86 case FieldDescriptor::CPPTYPE_MESSAGE:
87 to_reflection->AddMessage(to, field)->MergeFrom(
88 from_reflection->GetRepeatedMessage(from, field, j));
89 break;
90 }
91 }
92 } else {
93 switch (field->cpp_type()) {
94 #define HANDLE_TYPE(CPPTYPE, METHOD) \
95 case FieldDescriptor::CPPTYPE_##CPPTYPE: \
96 to_reflection->Set##METHOD(to, field, \
97 from_reflection->Get##METHOD(from, field)); \
98 break;
99
100 HANDLE_TYPE(INT32 , Int32 );
101 HANDLE_TYPE(INT64 , Int64 );
102 HANDLE_TYPE(UINT32, UInt32);
103 HANDLE_TYPE(UINT64, UInt64);
104 HANDLE_TYPE(FLOAT , Float );
105 HANDLE_TYPE(DOUBLE, Double);
106 HANDLE_TYPE(BOOL , Bool );
107 HANDLE_TYPE(STRING, String);
108 HANDLE_TYPE(ENUM , Enum );
109 #undef HANDLE_TYPE
110
111 case FieldDescriptor::CPPTYPE_MESSAGE:
112 to_reflection->MutableMessage(to, field)->MergeFrom(
113 from_reflection->GetMessage(from, field));
114 break;
115 }
116 }
117 }
118
119 to_reflection->MutableUnknownFields(to)->MergeFrom(
120 from_reflection->GetUnknownFields(from));
121 }
122
Clear(Message * message)123 void ReflectionOps::Clear(Message* message) {
124 const Reflection* reflection = message->GetReflection();
125
126 vector<const FieldDescriptor*> fields;
127 reflection->ListFields(*message, &fields);
128 for (int i = 0; i < fields.size(); i++) {
129 reflection->ClearField(message, fields[i]);
130 }
131
132 reflection->MutableUnknownFields(message)->Clear();
133 }
134
IsInitialized(const Message & message)135 bool ReflectionOps::IsInitialized(const Message& message) {
136 const Descriptor* descriptor = message.GetDescriptor();
137 const Reflection* reflection = message.GetReflection();
138
139 // Check required fields of this message.
140 for (int i = 0; i < descriptor->field_count(); i++) {
141 if (descriptor->field(i)->is_required()) {
142 if (!reflection->HasField(message, descriptor->field(i))) {
143 return false;
144 }
145 }
146 }
147
148 // Check that sub-messages are initialized.
149 vector<const FieldDescriptor*> fields;
150 reflection->ListFields(message, &fields);
151 for (int i = 0; i < fields.size(); i++) {
152 const FieldDescriptor* field = fields[i];
153 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
154 if (field->is_repeated()) {
155 int size = reflection->FieldSize(message, field);
156
157 for (int i = 0; i < size; i++) {
158 if (!reflection->GetRepeatedMessage(message, field, i)
159 .IsInitialized()) {
160 return false;
161 }
162 }
163 } else {
164 if (!reflection->GetMessage(message, field).IsInitialized()) {
165 return false;
166 }
167 }
168 }
169 }
170
171 return true;
172 }
173
DiscardUnknownFields(Message * message)174 void ReflectionOps::DiscardUnknownFields(Message* message) {
175 const Reflection* reflection = message->GetReflection();
176
177 reflection->MutableUnknownFields(message)->Clear();
178
179 vector<const FieldDescriptor*> fields;
180 reflection->ListFields(*message, &fields);
181 for (int i = 0; i < fields.size(); i++) {
182 const FieldDescriptor* field = fields[i];
183 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
184 if (field->is_repeated()) {
185 int size = reflection->FieldSize(*message, field);
186 for (int i = 0; i < size; i++) {
187 reflection->MutableRepeatedMessage(message, field, i)
188 ->DiscardUnknownFields();
189 }
190 } else {
191 reflection->MutableMessage(message, field)->DiscardUnknownFields();
192 }
193 }
194 }
195 }
196
SubMessagePrefix(const string & prefix,const FieldDescriptor * field,int index)197 static string SubMessagePrefix(const string& prefix,
198 const FieldDescriptor* field,
199 int index) {
200 string result(prefix);
201 if (field->is_extension()) {
202 result.append("(");
203 result.append(field->full_name());
204 result.append(")");
205 } else {
206 result.append(field->name());
207 }
208 if (index != -1) {
209 result.append("[");
210 result.append(SimpleItoa(index));
211 result.append("]");
212 }
213 result.append(".");
214 return result;
215 }
216
FindInitializationErrors(const Message & message,const string & prefix,vector<string> * errors)217 void ReflectionOps::FindInitializationErrors(
218 const Message& message,
219 const string& prefix,
220 vector<string>* errors) {
221 const Descriptor* descriptor = message.GetDescriptor();
222 const Reflection* reflection = message.GetReflection();
223
224 // Check required fields of this message.
225 for (int i = 0; i < descriptor->field_count(); i++) {
226 if (descriptor->field(i)->is_required()) {
227 if (!reflection->HasField(message, descriptor->field(i))) {
228 errors->push_back(prefix + descriptor->field(i)->name());
229 }
230 }
231 }
232
233 // Check sub-messages.
234 vector<const FieldDescriptor*> fields;
235 reflection->ListFields(message, &fields);
236 for (int i = 0; i < fields.size(); i++) {
237 const FieldDescriptor* field = fields[i];
238 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
239
240 if (field->is_repeated()) {
241 int size = reflection->FieldSize(message, field);
242
243 for (int i = 0; i < size; i++) {
244 const Message& sub_message =
245 reflection->GetRepeatedMessage(message, field, i);
246 FindInitializationErrors(sub_message,
247 SubMessagePrefix(prefix, field, i),
248 errors);
249 }
250 } else {
251 const Message& sub_message = reflection->GetMessage(message, field);
252 FindInitializationErrors(sub_message,
253 SubMessagePrefix(prefix, field, -1),
254 errors);
255 }
256 }
257 }
258 }
259
260 } // namespace internal
261 } // namespace protobuf
262 } // namespace google
263