Line data Source code
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 :
48 0 : void ReflectionOps::Copy(const Message& from, Message* to) {
49 0 : if (&from == to) return;
50 0 : Clear(to);
51 0 : Merge(from, to);
52 : }
53 :
54 0 : void ReflectionOps::Merge(const Message& from, Message* to) {
55 0 : GOOGLE_CHECK_NE(&from, to);
56 :
57 0 : const Descriptor* descriptor = from.GetDescriptor();
58 0 : GOOGLE_CHECK_EQ(to->GetDescriptor(), descriptor)
59 0 : << "Tried to merge messages of different types "
60 0 : << "(merge " << descriptor->full_name()
61 0 : << " to " << to->GetDescriptor()->full_name() << ")";
62 :
63 0 : const Reflection* from_reflection = from.GetReflection();
64 0 : const Reflection* to_reflection = to->GetReflection();
65 :
66 : vector<const FieldDescriptor*> fields;
67 0 : from_reflection->ListFields(from, &fields);
68 0 : for (int i = 0; i < fields.size(); i++) {
69 0 : const FieldDescriptor* field = fields[i];
70 :
71 0 : if (field->is_repeated()) {
72 0 : int count = from_reflection->FieldSize(from, field);
73 0 : for (int j = 0; j < count; j++) {
74 0 : 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 0 : HANDLE_TYPE(INT32 , Int32 );
82 0 : HANDLE_TYPE(INT64 , Int64 );
83 0 : HANDLE_TYPE(UINT32, UInt32);
84 0 : HANDLE_TYPE(UINT64, UInt64);
85 0 : HANDLE_TYPE(FLOAT , Float );
86 0 : HANDLE_TYPE(DOUBLE, Double);
87 0 : HANDLE_TYPE(BOOL , Bool );
88 0 : HANDLE_TYPE(STRING, String);
89 0 : HANDLE_TYPE(ENUM , Enum );
90 : #undef HANDLE_TYPE
91 :
92 : case FieldDescriptor::CPPTYPE_MESSAGE:
93 0 : to_reflection->AddMessage(to, field)->MergeFrom(
94 0 : from_reflection->GetRepeatedMessage(from, field, j));
95 : break;
96 : }
97 : }
98 : } else {
99 0 : 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 0 : HANDLE_TYPE(INT32 , Int32 );
107 0 : HANDLE_TYPE(INT64 , Int64 );
108 0 : HANDLE_TYPE(UINT32, UInt32);
109 0 : HANDLE_TYPE(UINT64, UInt64);
110 0 : HANDLE_TYPE(FLOAT , Float );
111 0 : HANDLE_TYPE(DOUBLE, Double);
112 0 : HANDLE_TYPE(BOOL , Bool );
113 0 : HANDLE_TYPE(STRING, String);
114 0 : HANDLE_TYPE(ENUM , Enum );
115 : #undef HANDLE_TYPE
116 :
117 : case FieldDescriptor::CPPTYPE_MESSAGE:
118 0 : to_reflection->MutableMessage(to, field)->MergeFrom(
119 0 : from_reflection->GetMessage(from, field));
120 : break;
121 : }
122 : }
123 : }
124 :
125 0 : to_reflection->MutableUnknownFields(to)->MergeFrom(
126 0 : from_reflection->GetUnknownFields(from));
127 0 : }
128 :
129 9 : void ReflectionOps::Clear(Message* message) {
130 9 : const Reflection* reflection = message->GetReflection();
131 :
132 : vector<const FieldDescriptor*> fields;
133 9 : reflection->ListFields(*message, &fields);
134 9 : for (int i = 0; i < fields.size(); i++) {
135 0 : reflection->ClearField(message, fields[i]);
136 : }
137 :
138 9 : reflection->MutableUnknownFields(message)->Clear();
139 9 : }
140 :
141 14 : bool ReflectionOps::IsInitialized(const Message& message) {
142 156 : const Descriptor* descriptor = message.GetDescriptor();
143 14 : const Reflection* reflection = message.GetReflection();
144 :
145 : // Check required fields of this message.
146 142 : for (int i = 0; i < descriptor->field_count(); i++) {
147 192 : if (descriptor->field(i)->is_required()) {
148 0 : 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 14 : reflection->ListFields(message, &fields);
157 52 : for (int i = 0; i < fields.size(); i++) {
158 38 : const FieldDescriptor* field = fields[i];
159 38 : if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
160 :
161 5 : if (field->is_repeated()) {
162 0 : int size = reflection->FieldSize(message, field);
163 :
164 0 : for (int j = 0; j < size; j++) {
165 0 : if (!reflection->GetRepeatedMessage(message, field, j)
166 0 : .IsInitialized()) {
167 : return false;
168 : }
169 : }
170 : } else {
171 5 : if (!reflection->GetMessage(message, field).IsInitialized()) {
172 : return false;
173 : }
174 : }
175 : }
176 : }
177 :
178 : return true;
179 : }
180 :
181 0 : void ReflectionOps::DiscardUnknownFields(Message* message) {
182 0 : const Reflection* reflection = message->GetReflection();
183 :
184 0 : reflection->MutableUnknownFields(message)->Clear();
185 :
186 : vector<const FieldDescriptor*> fields;
187 0 : reflection->ListFields(*message, &fields);
188 0 : for (int i = 0; i < fields.size(); i++) {
189 0 : const FieldDescriptor* field = fields[i];
190 0 : if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
191 0 : if (field->is_repeated()) {
192 0 : int size = reflection->FieldSize(*message, field);
193 0 : for (int j = 0; j < size; j++) {
194 0 : reflection->MutableRepeatedMessage(message, field, j)
195 0 : ->DiscardUnknownFields();
196 : }
197 : } else {
198 0 : reflection->MutableMessage(message, field)->DiscardUnknownFields();
199 : }
200 : }
201 : }
202 0 : }
203 :
204 0 : static string SubMessagePrefix(const string& prefix,
205 0 : const FieldDescriptor* field,
206 : int index) {
207 0 : string result(prefix);
208 0 : if (field->is_extension()) {
209 0 : result.append("(");
210 0 : result.append(field->full_name());
211 0 : result.append(")");
212 : } else {
213 0 : result.append(field->name());
214 : }
215 0 : if (index != -1) {
216 0 : result.append("[");
217 0 : result.append(SimpleItoa(index));
218 0 : result.append("]");
219 : }
220 0 : result.append(".");
221 0 : return result;
222 : }
223 :
224 0 : void ReflectionOps::FindInitializationErrors(
225 : const Message& message,
226 : const string& prefix,
227 : vector<string>* errors) {
228 0 : const Descriptor* descriptor = message.GetDescriptor();
229 0 : const Reflection* reflection = message.GetReflection();
230 :
231 : // Check required fields of this message.
232 0 : for (int i = 0; i < descriptor->field_count(); i++) {
233 0 : if (descriptor->field(i)->is_required()) {
234 0 : if (!reflection->HasField(message, descriptor->field(i))) {
235 0 : errors->push_back(prefix + descriptor->field(i)->name());
236 : }
237 : }
238 : }
239 :
240 : // Check sub-messages.
241 : vector<const FieldDescriptor*> fields;
242 0 : reflection->ListFields(message, &fields);
243 0 : for (int i = 0; i < fields.size(); i++) {
244 0 : const FieldDescriptor* field = fields[i];
245 0 : if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
246 :
247 0 : if (field->is_repeated()) {
248 0 : int size = reflection->FieldSize(message, field);
249 :
250 0 : for (int j = 0; j < size; j++) {
251 : const Message& sub_message =
252 0 : reflection->GetRepeatedMessage(message, field, j);
253 : FindInitializationErrors(sub_message,
254 : SubMessagePrefix(prefix, field, j),
255 0 : errors);
256 : }
257 : } else {
258 0 : const Message& sub_message = reflection->GetMessage(message, field);
259 : FindInitializationErrors(sub_message,
260 : SubMessagePrefix(prefix, field, -1),
261 0 : errors);
262 : }
263 : }
264 : }
265 0 : }
266 :
267 : } // namespace internal
268 : } // namespace protobuf
269 : } // namespace google
|