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
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
270