blob: 4629dec2510b1cf80dc57f99c39a653193e50a17 [file] [log] [blame]
Brian Silverman9c614bc2016-02-15 20:20:02 -05001// 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
44namespace google {
45namespace protobuf {
46namespace internal {
47
48void ReflectionOps::Copy(const Message& from, Message* to) {
49 if (&from == to) return;
50 Clear(to);
51 Merge(from, to);
52}
53
54void 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
129void 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
141bool 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
181void 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
204static 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
224void 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