- add sources.
[platform/framework/web/crosswalk.git] / src / third_party / protobuf / src / google / protobuf / reflection_ops.cc
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 <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 void ReflectionOps::Copy(const Message& from, Message* to) {
49   if (&from == to) return;
50   Clear(to);
51   Merge(from, to);
52 }
53
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
61   const Reflection* from_reflection = from.GetReflection();
62   const Reflection* to_reflection = to->GetReflection();
63
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];
68
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));     \
77             break;
78
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  );
88 #undef HANDLE_TYPE
89
90           case FieldDescriptor::CPPTYPE_MESSAGE:
91             to_reflection->AddMessage(to, field)->MergeFrom(
92               from_reflection->GetRepeatedMessage(from, field, j));
93             break;
94         }
95       }
96     } else {
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));                     \
102           break;
103
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  );
113 #undef HANDLE_TYPE
114
115         case FieldDescriptor::CPPTYPE_MESSAGE:
116           to_reflection->MutableMessage(to, field)->MergeFrom(
117             from_reflection->GetMessage(from, field));
118           break;
119       }
120     }
121   }
122
123   to_reflection->MutableUnknownFields(to)->MergeFrom(
124     from_reflection->GetUnknownFields(from));
125 }
126
127 void ReflectionOps::Clear(Message* message) {
128   const Reflection* reflection = message->GetReflection();
129
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]);
134   }
135
136   reflection->MutableUnknownFields(message)->Clear();
137 }
138
139 bool ReflectionOps::IsInitialized(const Message& message) {
140   const Descriptor* descriptor = message.GetDescriptor();
141   const Reflection* reflection = message.GetReflection();
142
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))) {
147         return false;
148       }
149     }
150   }
151
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) {
158
159       if (field->is_repeated()) {
160         int size = reflection->FieldSize(message, field);
161
162         for (int j = 0; j < size; j++) {
163           if (!reflection->GetRepeatedMessage(message, field, j)
164                           .IsInitialized()) {
165             return false;
166           }
167         }
168       } else {
169         if (!reflection->GetMessage(message, field).IsInitialized()) {
170           return false;
171         }
172       }
173     }
174   }
175
176   return true;
177 }
178
179 void ReflectionOps::DiscardUnknownFields(Message* message) {
180   const Reflection* reflection = message->GetReflection();
181
182   reflection->MutableUnknownFields(message)->Clear();
183
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();
194         }
195       } else {
196         reflection->MutableMessage(message, field)->DiscardUnknownFields();
197       }
198     }
199   }
200 }
201
202 static string SubMessagePrefix(const string& prefix,
203                                const FieldDescriptor* field,
204                                int index) {
205   string result(prefix);
206   if (field->is_extension()) {
207     result.append("(");
208     result.append(field->full_name());
209     result.append(")");
210   } else {
211     result.append(field->name());
212   }
213   if (index != -1) {
214     result.append("[");
215     result.append(SimpleItoa(index));
216     result.append("]");
217   }
218   result.append(".");
219   return result;
220 }
221
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();
228
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());
234       }
235     }
236   }
237
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) {
244
245       if (field->is_repeated()) {
246         int size = reflection->FieldSize(message, field);
247
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),
253                                    errors);
254         }
255       } else {
256         const Message& sub_message = reflection->GetMessage(message, field);
257         FindInitializationErrors(sub_message,
258                                  SubMessagePrefix(prefix, field, -1),
259                                  errors);
260       }
261     }
262   }
263 }
264
265 }  // namespace internal
266 }  // namespace protobuf
267 }  // namespace google