• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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