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