1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // https://developers.google.com/protocol-buffers/
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 <string>
36 #include <vector>
37
38 #include <google/protobuf/reflection_ops.h>
39 #include <google/protobuf/descriptor.h>
40 #include <google/protobuf/descriptor.pb.h>
41 #include <google/protobuf/unknown_field_set.h>
42 #include <google/protobuf/stubs/strutil.h>
43
44 namespace google {
45 namespace protobuf {
46 namespace internal {
47
Copy(const Message & from,Message * to)48 void ReflectionOps::Copy(const Message& from, Message* to) {
49 if (&from == to) return;
50 Clear(to);
51 Merge(from, to);
52 }
53
Merge(const Message & from,Message * to)54 void ReflectionOps::Merge(const Message& from, Message* to) {
55 GOOGLE_CHECK_NE(&from, to);
56
57 const Descriptor* descriptor = from.GetDescriptor();
58 GOOGLE_CHECK_EQ(to->GetDescriptor(), descriptor)
59 << "Tried to merge messages of different types "
60 << "(merge " << descriptor->full_name()
61 << " to " << to->GetDescriptor()->full_name() << ")";
62
63 const Reflection* from_reflection = from.GetReflection();
64 const Reflection* to_reflection = to->GetReflection();
65
66 vector<const FieldDescriptor*> fields;
67 from_reflection->ListFields(from, &fields);
68 for (int i = 0; i < fields.size(); i++) {
69 const FieldDescriptor* field = fields[i];
70
71 if (field->is_repeated()) {
72 int count = from_reflection->FieldSize(from, field);
73 for (int j = 0; j < count; j++) {
74 switch (field->cpp_type()) {
75 #define HANDLE_TYPE(CPPTYPE, METHOD) \
76 case FieldDescriptor::CPPTYPE_##CPPTYPE: \
77 to_reflection->Add##METHOD(to, field, \
78 from_reflection->GetRepeated##METHOD(from, field, j)); \
79 break;
80
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
91
92 case FieldDescriptor::CPPTYPE_MESSAGE:
93 to_reflection->AddMessage(to, field)->MergeFrom(
94 from_reflection->GetRepeatedMessage(from, field, j));
95 break;
96 }
97 }
98 } else {
99 switch (field->cpp_type()) {
100 #define HANDLE_TYPE(CPPTYPE, METHOD) \
101 case FieldDescriptor::CPPTYPE_##CPPTYPE: \
102 to_reflection->Set##METHOD(to, field, \
103 from_reflection->Get##METHOD(from, field)); \
104 break;
105
106 HANDLE_TYPE(INT32 , Int32 );
107 HANDLE_TYPE(INT64 , Int64 );
108 HANDLE_TYPE(UINT32, UInt32);
109 HANDLE_TYPE(UINT64, UInt64);
110 HANDLE_TYPE(FLOAT , Float );
111 HANDLE_TYPE(DOUBLE, Double);
112 HANDLE_TYPE(BOOL , Bool );
113 HANDLE_TYPE(STRING, String);
114 HANDLE_TYPE(ENUM , Enum );
115 #undef HANDLE_TYPE
116
117 case FieldDescriptor::CPPTYPE_MESSAGE:
118 to_reflection->MutableMessage(to, field)->MergeFrom(
119 from_reflection->GetMessage(from, field));
120 break;
121 }
122 }
123 }
124
125 to_reflection->MutableUnknownFields(to)->MergeFrom(
126 from_reflection->GetUnknownFields(from));
127 }
128
Clear(Message * message)129 void ReflectionOps::Clear(Message* message) {
130 const Reflection* reflection = message->GetReflection();
131
132 vector<const FieldDescriptor*> fields;
133 reflection->ListFields(*message, &fields);
134 for (int i = 0; i < fields.size(); i++) {
135 reflection->ClearField(message, fields[i]);
136 }
137
138 reflection->MutableUnknownFields(message)->Clear();
139 }
140
IsInitialized(const Message & message)141 bool ReflectionOps::IsInitialized(const Message& message) {
142 const Descriptor* descriptor = message.GetDescriptor();
143 const Reflection* reflection = message.GetReflection();
144
145 // Check required fields of this message.
146 for (int i = 0; i < descriptor->field_count(); i++) {
147 if (descriptor->field(i)->is_required()) {
148 if (!reflection->HasField(message, descriptor->field(i))) {
149 return false;
150 }
151 }
152 }
153
154 // Check that sub-messages are initialized.
155 vector<const FieldDescriptor*> fields;
156 reflection->ListFields(message, &fields);
157 for (int i = 0; i < fields.size(); i++) {
158 const FieldDescriptor* field = fields[i];
159 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
160
161 if (field->is_repeated()) {
162 int size = reflection->FieldSize(message, field);
163
164 for (int j = 0; j < size; j++) {
165 if (!reflection->GetRepeatedMessage(message, field, j)
166 .IsInitialized()) {
167 return false;
168 }
169 }
170 } else {
171 if (!reflection->GetMessage(message, field).IsInitialized()) {
172 return false;
173 }
174 }
175 }
176 }
177
178 return true;
179 }
180
DiscardUnknownFields(Message * message)181 void ReflectionOps::DiscardUnknownFields(Message* message) {
182 const Reflection* reflection = message->GetReflection();
183
184 reflection->MutableUnknownFields(message)->Clear();
185
186 vector<const FieldDescriptor*> fields;
187 reflection->ListFields(*message, &fields);
188 for (int i = 0; i < fields.size(); i++) {
189 const FieldDescriptor* field = fields[i];
190 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
191 if (field->is_repeated()) {
192 int size = reflection->FieldSize(*message, field);
193 for (int j = 0; j < size; j++) {
194 reflection->MutableRepeatedMessage(message, field, j)
195 ->DiscardUnknownFields();
196 }
197 } else {
198 reflection->MutableMessage(message, field)->DiscardUnknownFields();
199 }
200 }
201 }
202 }
203
SubMessagePrefix(const string & prefix,const FieldDescriptor * field,int index)204 static string SubMessagePrefix(const string& prefix,
205 const FieldDescriptor* field,
206 int index) {
207 string result(prefix);
208 if (field->is_extension()) {
209 result.append("(");
210 result.append(field->full_name());
211 result.append(")");
212 } else {
213 result.append(field->name());
214 }
215 if (index != -1) {
216 result.append("[");
217 result.append(SimpleItoa(index));
218 result.append("]");
219 }
220 result.append(".");
221 return result;
222 }
223
FindInitializationErrors(const Message & message,const string & prefix,vector<string> * errors)224 void ReflectionOps::FindInitializationErrors(
225 const Message& message,
226 const string& prefix,
227 vector<string>* errors) {
228 const Descriptor* descriptor = message.GetDescriptor();
229 const Reflection* reflection = message.GetReflection();
230
231 // Check required fields of this message.
232 for (int i = 0; i < descriptor->field_count(); i++) {
233 if (descriptor->field(i)->is_required()) {
234 if (!reflection->HasField(message, descriptor->field(i))) {
235 errors->push_back(prefix + descriptor->field(i)->name());
236 }
237 }
238 }
239
240 // Check sub-messages.
241 vector<const FieldDescriptor*> fields;
242 reflection->ListFields(message, &fields);
243 for (int i = 0; i < fields.size(); i++) {
244 const FieldDescriptor* field = fields[i];
245 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
246
247 if (field->is_repeated()) {
248 int size = reflection->FieldSize(message, field);
249
250 for (int j = 0; j < size; j++) {
251 const Message& sub_message =
252 reflection->GetRepeatedMessage(message, field, j);
253 FindInitializationErrors(sub_message,
254 SubMessagePrefix(prefix, field, j),
255 errors);
256 }
257 } else {
258 const Message& sub_message = reflection->GetMessage(message, field);
259 FindInitializationErrors(sub_message,
260 SubMessagePrefix(prefix, field, -1),
261 errors);
262 }
263 }
264 }
265 }
266
267 } // namespace internal
268 } // namespace protobuf
269 } // namespace google
270