1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // http://code.google.com/p/protobuf/
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
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
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.
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.
31 // Author: kenton@google.com (Kenton Varda)
32 // Based on original Protocol Buffers design by
33 // Sanjay Ghemawat, Jeff Dean, and others.
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>
48 void ReflectionOps::Copy(const Message& from, Message* to) {
49 if (&from == to) return;
54 void ReflectionOps::Merge(const Message& from, Message* to) {
55 GOOGLE_CHECK_NE(&from, to);
57 const Descriptor* descriptor = from.GetDescriptor();
58 GOOGLE_CHECK_EQ(to->GetDescriptor(), descriptor)
59 << "Tried to merge messages of different types.";
61 const Reflection* from_reflection = from.GetReflection();
62 const Reflection* to_reflection = to->GetReflection();
64 vector<const FieldDescriptor*> fields;
65 from_reflection->ListFields(from, &fields);
66 for (int i = 0; i < fields.size(); i++) {
67 const FieldDescriptor* field = fields[i];
69 if (field->is_repeated()) {
70 int count = from_reflection->FieldSize(from, field);
71 for (int j = 0; j < count; j++) {
72 switch (field->cpp_type()) {
73 #define HANDLE_TYPE(CPPTYPE, METHOD) \
74 case FieldDescriptor::CPPTYPE_##CPPTYPE: \
75 to_reflection->Add##METHOD(to, field, \
76 from_reflection->GetRepeated##METHOD(from, field, j)); \
79 HANDLE_TYPE(INT32 , Int32 );
80 HANDLE_TYPE(INT64 , Int64 );
81 HANDLE_TYPE(UINT32, UInt32);
82 HANDLE_TYPE(UINT64, UInt64);
83 HANDLE_TYPE(FLOAT , Float );
84 HANDLE_TYPE(DOUBLE, Double);
85 HANDLE_TYPE(BOOL , Bool );
86 HANDLE_TYPE(STRING, String);
87 HANDLE_TYPE(ENUM , Enum );
90 case FieldDescriptor::CPPTYPE_MESSAGE:
91 to_reflection->AddMessage(to, field)->MergeFrom(
92 from_reflection->GetRepeatedMessage(from, field, j));
97 switch (field->cpp_type()) {
98 #define HANDLE_TYPE(CPPTYPE, METHOD) \
99 case FieldDescriptor::CPPTYPE_##CPPTYPE: \
100 to_reflection->Set##METHOD(to, field, \
101 from_reflection->Get##METHOD(from, field)); \
104 HANDLE_TYPE(INT32 , Int32 );
105 HANDLE_TYPE(INT64 , Int64 );
106 HANDLE_TYPE(UINT32, UInt32);
107 HANDLE_TYPE(UINT64, UInt64);
108 HANDLE_TYPE(FLOAT , Float );
109 HANDLE_TYPE(DOUBLE, Double);
110 HANDLE_TYPE(BOOL , Bool );
111 HANDLE_TYPE(STRING, String);
112 HANDLE_TYPE(ENUM , Enum );
115 case FieldDescriptor::CPPTYPE_MESSAGE:
116 to_reflection->MutableMessage(to, field)->MergeFrom(
117 from_reflection->GetMessage(from, field));
123 to_reflection->MutableUnknownFields(to)->MergeFrom(
124 from_reflection->GetUnknownFields(from));
127 void ReflectionOps::Clear(Message* message) {
128 const Reflection* reflection = message->GetReflection();
130 vector<const FieldDescriptor*> fields;
131 reflection->ListFields(*message, &fields);
132 for (int i = 0; i < fields.size(); i++) {
133 reflection->ClearField(message, fields[i]);
136 reflection->MutableUnknownFields(message)->Clear();
139 bool ReflectionOps::IsInitialized(const Message& message) {
140 const Descriptor* descriptor = message.GetDescriptor();
141 const Reflection* reflection = message.GetReflection();
143 // Check required fields of this message.
144 for (int i = 0; i < descriptor->field_count(); i++) {
145 if (descriptor->field(i)->is_required()) {
146 if (!reflection->HasField(message, descriptor->field(i))) {
152 // Check that sub-messages are initialized.
153 vector<const FieldDescriptor*> fields;
154 reflection->ListFields(message, &fields);
155 for (int i = 0; i < fields.size(); i++) {
156 const FieldDescriptor* field = fields[i];
157 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
159 if (field->is_repeated()) {
160 int size = reflection->FieldSize(message, field);
162 for (int j = 0; j < size; j++) {
163 if (!reflection->GetRepeatedMessage(message, field, j)
169 if (!reflection->GetMessage(message, field).IsInitialized()) {
179 void ReflectionOps::DiscardUnknownFields(Message* message) {
180 const Reflection* reflection = message->GetReflection();
182 reflection->MutableUnknownFields(message)->Clear();
184 vector<const FieldDescriptor*> fields;
185 reflection->ListFields(*message, &fields);
186 for (int i = 0; i < fields.size(); i++) {
187 const FieldDescriptor* field = fields[i];
188 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
189 if (field->is_repeated()) {
190 int size = reflection->FieldSize(*message, field);
191 for (int j = 0; j < size; j++) {
192 reflection->MutableRepeatedMessage(message, field, j)
193 ->DiscardUnknownFields();
196 reflection->MutableMessage(message, field)->DiscardUnknownFields();
202 static string SubMessagePrefix(const string& prefix,
203 const FieldDescriptor* field,
205 string result(prefix);
206 if (field->is_extension()) {
208 result.append(field->full_name());
211 result.append(field->name());
215 result.append(SimpleItoa(index));
222 void ReflectionOps::FindInitializationErrors(
223 const Message& message,
224 const string& prefix,
225 vector<string>* errors) {
226 const Descriptor* descriptor = message.GetDescriptor();
227 const Reflection* reflection = message.GetReflection();
229 // Check required fields of this message.
230 for (int i = 0; i < descriptor->field_count(); i++) {
231 if (descriptor->field(i)->is_required()) {
232 if (!reflection->HasField(message, descriptor->field(i))) {
233 errors->push_back(prefix + descriptor->field(i)->name());
238 // Check sub-messages.
239 vector<const FieldDescriptor*> fields;
240 reflection->ListFields(message, &fields);
241 for (int i = 0; i < fields.size(); i++) {
242 const FieldDescriptor* field = fields[i];
243 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
245 if (field->is_repeated()) {
246 int size = reflection->FieldSize(message, field);
248 for (int j = 0; j < size; j++) {
249 const Message& sub_message =
250 reflection->GetRepeatedMessage(message, field, j);
251 FindInitializationErrors(sub_message,
252 SubMessagePrefix(prefix, field, j),
256 const Message& sub_message = reflection->GetMessage(message, field);
257 FindInitializationErrors(sub_message,
258 SubMessagePrefix(prefix, field, -1),
265 } // namespace internal
266 } // namespace protobuf
267 } // namespace google