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 <iostream>
36 #include <stack>
37 #include <google/protobuf/stubs/hash.h>
38
39 #include <google/protobuf/message.h>
40
41 #include <google/protobuf/stubs/logging.h>
42 #include <google/protobuf/stubs/common.h>
43 #include <google/protobuf/stubs/mutex.h>
44 #include <google/protobuf/stubs/once.h>
45 #include <google/protobuf/reflection_internal.h>
46 #include <google/protobuf/io/coded_stream.h>
47 #include <google/protobuf/io/zero_copy_stream_impl.h>
48 #include <google/protobuf/descriptor.pb.h>
49 #include <google/protobuf/map_field.h>
50 #include <google/protobuf/descriptor.h>
51 #include <google/protobuf/generated_message_util.h>
52 #include <google/protobuf/reflection_ops.h>
53 #include <google/protobuf/wire_format.h>
54 #include <google/protobuf/stubs/strutil.h>
55 #include <google/protobuf/stubs/map_util.h>
56 #include <google/protobuf/stubs/singleton.h>
57 #include <google/protobuf/stubs/stl_util.h>
58
59 namespace google {
60 namespace protobuf {
61
62 using internal::WireFormat;
63 using internal::ReflectionOps;
64
MergeFrom(const Message & from)65 void Message::MergeFrom(const Message& from) {
66 const Descriptor* descriptor = GetDescriptor();
67 GOOGLE_CHECK_EQ(from.GetDescriptor(), descriptor)
68 << ": Tried to merge from a message with a different type. "
69 "to: " << descriptor->full_name() << ", "
70 "from: " << from.GetDescriptor()->full_name();
71 ReflectionOps::Merge(from, this);
72 }
73
CheckTypeAndMergeFrom(const MessageLite & other)74 void Message::CheckTypeAndMergeFrom(const MessageLite& other) {
75 MergeFrom(*down_cast<const Message*>(&other));
76 }
77
CopyFrom(const Message & from)78 void Message::CopyFrom(const Message& from) {
79 const Descriptor* descriptor = GetDescriptor();
80 GOOGLE_CHECK_EQ(from.GetDescriptor(), descriptor)
81 << ": Tried to copy from a message with a different type. "
82 "to: " << descriptor->full_name() << ", "
83 "from: " << from.GetDescriptor()->full_name();
84 ReflectionOps::Copy(from, this);
85 }
86
GetTypeName() const87 string Message::GetTypeName() const {
88 return GetDescriptor()->full_name();
89 }
90
Clear()91 void Message::Clear() {
92 ReflectionOps::Clear(this);
93 }
94
IsInitialized() const95 bool Message::IsInitialized() const {
96 return ReflectionOps::IsInitialized(*this);
97 }
98
FindInitializationErrors(vector<string> * errors) const99 void Message::FindInitializationErrors(vector<string>* errors) const {
100 return ReflectionOps::FindInitializationErrors(*this, "", errors);
101 }
102
InitializationErrorString() const103 string Message::InitializationErrorString() const {
104 vector<string> errors;
105 FindInitializationErrors(&errors);
106 return Join(errors, ", ");
107 }
108
CheckInitialized() const109 void Message::CheckInitialized() const {
110 GOOGLE_CHECK(IsInitialized())
111 << "Message of type \"" << GetDescriptor()->full_name()
112 << "\" is missing required fields: " << InitializationErrorString();
113 }
114
DiscardUnknownFields()115 void Message::DiscardUnknownFields() {
116 return ReflectionOps::DiscardUnknownFields(this);
117 }
118
MergePartialFromCodedStream(io::CodedInputStream * input)119 bool Message::MergePartialFromCodedStream(io::CodedInputStream* input) {
120 return WireFormat::ParseAndMergePartial(input, this);
121 }
122
ParseFromFileDescriptor(int file_descriptor)123 bool Message::ParseFromFileDescriptor(int file_descriptor) {
124 io::FileInputStream input(file_descriptor);
125 return ParseFromZeroCopyStream(&input) && input.GetErrno() == 0;
126 }
127
ParsePartialFromFileDescriptor(int file_descriptor)128 bool Message::ParsePartialFromFileDescriptor(int file_descriptor) {
129 io::FileInputStream input(file_descriptor);
130 return ParsePartialFromZeroCopyStream(&input) && input.GetErrno() == 0;
131 }
132
ParseFromIstream(istream * input)133 bool Message::ParseFromIstream(istream* input) {
134 io::IstreamInputStream zero_copy_input(input);
135 return ParseFromZeroCopyStream(&zero_copy_input) && input->eof();
136 }
137
ParsePartialFromIstream(istream * input)138 bool Message::ParsePartialFromIstream(istream* input) {
139 io::IstreamInputStream zero_copy_input(input);
140 return ParsePartialFromZeroCopyStream(&zero_copy_input) && input->eof();
141 }
142
143
SerializeWithCachedSizes(io::CodedOutputStream * output) const144 void Message::SerializeWithCachedSizes(
145 io::CodedOutputStream* output) const {
146 WireFormat::SerializeWithCachedSizes(*this, GetCachedSize(), output);
147 }
148
ByteSize() const149 int Message::ByteSize() const {
150 int size = WireFormat::ByteSize(*this);
151 SetCachedSize(size);
152 return size;
153 }
154
SetCachedSize(int) const155 void Message::SetCachedSize(int /* size */) const {
156 GOOGLE_LOG(FATAL) << "Message class \"" << GetDescriptor()->full_name()
157 << "\" implements neither SetCachedSize() nor ByteSize(). "
158 "Must implement one or the other.";
159 }
160
SpaceUsed() const161 int Message::SpaceUsed() const {
162 return GetReflection()->SpaceUsed(*this);
163 }
164
SerializeToFileDescriptor(int file_descriptor) const165 bool Message::SerializeToFileDescriptor(int file_descriptor) const {
166 io::FileOutputStream output(file_descriptor);
167 return SerializeToZeroCopyStream(&output);
168 }
169
SerializePartialToFileDescriptor(int file_descriptor) const170 bool Message::SerializePartialToFileDescriptor(int file_descriptor) const {
171 io::FileOutputStream output(file_descriptor);
172 return SerializePartialToZeroCopyStream(&output);
173 }
174
SerializeToOstream(ostream * output) const175 bool Message::SerializeToOstream(ostream* output) const {
176 {
177 io::OstreamOutputStream zero_copy_output(output);
178 if (!SerializeToZeroCopyStream(&zero_copy_output)) return false;
179 }
180 return output->good();
181 }
182
SerializePartialToOstream(ostream * output) const183 bool Message::SerializePartialToOstream(ostream* output) const {
184 io::OstreamOutputStream zero_copy_output(output);
185 return SerializePartialToZeroCopyStream(&zero_copy_output);
186 }
187
188
189 // =============================================================================
190 // Reflection and associated Template Specializations
191
~Reflection()192 Reflection::~Reflection() {}
193
194 #define HANDLE_TYPE(TYPE, CPPTYPE, CTYPE) \
195 template<> \
196 const RepeatedField<TYPE>& Reflection::GetRepeatedField<TYPE>( \
197 const Message& message, const FieldDescriptor* field) const { \
198 return *static_cast<RepeatedField<TYPE>* >( \
199 MutableRawRepeatedField(const_cast<Message*>(&message), \
200 field, CPPTYPE, CTYPE, NULL)); \
201 } \
202 \
203 template<> \
204 RepeatedField<TYPE>* Reflection::MutableRepeatedField<TYPE>( \
205 Message* message, const FieldDescriptor* field) const { \
206 return static_cast<RepeatedField<TYPE>* >( \
207 MutableRawRepeatedField(message, field, CPPTYPE, CTYPE, NULL)); \
208 }
209
210 HANDLE_TYPE(int32, FieldDescriptor::CPPTYPE_INT32, -1);
211 HANDLE_TYPE(int64, FieldDescriptor::CPPTYPE_INT64, -1);
212 HANDLE_TYPE(uint32, FieldDescriptor::CPPTYPE_UINT32, -1);
213 HANDLE_TYPE(uint64, FieldDescriptor::CPPTYPE_UINT64, -1);
214 HANDLE_TYPE(float, FieldDescriptor::CPPTYPE_FLOAT, -1);
215 HANDLE_TYPE(double, FieldDescriptor::CPPTYPE_DOUBLE, -1);
216 HANDLE_TYPE(bool, FieldDescriptor::CPPTYPE_BOOL, -1);
217
218
219 #undef HANDLE_TYPE
220
MutableRawRepeatedString(Message * message,const FieldDescriptor * field,bool is_string) const221 void* Reflection::MutableRawRepeatedString(
222 Message* message, const FieldDescriptor* field, bool is_string) const {
223 return MutableRawRepeatedField(message, field,
224 FieldDescriptor::CPPTYPE_STRING, FieldOptions::STRING, NULL);
225 }
226
227
228 // Default EnumValue API implementations. Real reflection implementations should
229 // override these. However, there are several legacy implementations that do
230 // not, and cannot easily be changed at the same time as the Reflection API, so
231 // we provide these for now.
232 // TODO: Remove these once all Reflection implementations are updated.
GetEnumValue(const Message & message,const FieldDescriptor * field) const233 int Reflection::GetEnumValue(const Message& message,
234 const FieldDescriptor* field) const {
235 GOOGLE_LOG(FATAL) << "Unimplemented EnumValue API.";
236 return 0;
237 }
SetEnumValue(Message * message,const FieldDescriptor * field,int value) const238 void Reflection::SetEnumValue(Message* message,
239 const FieldDescriptor* field,
240 int value) const {
241 GOOGLE_LOG(FATAL) << "Unimplemented EnumValue API.";
242 }
GetRepeatedEnumValue(const Message & message,const FieldDescriptor * field,int index) const243 int Reflection::GetRepeatedEnumValue(
244 const Message& message,
245 const FieldDescriptor* field, int index) const {
246 GOOGLE_LOG(FATAL) << "Unimplemented EnumValue API.";
247 return 0;
248 }
SetRepeatedEnumValue(Message * message,const FieldDescriptor * field,int index,int value) const249 void Reflection::SetRepeatedEnumValue(Message* message,
250 const FieldDescriptor* field, int index,
251 int value) const {
252 GOOGLE_LOG(FATAL) << "Unimplemented EnumValue API.";
253 }
AddEnumValue(Message * message,const FieldDescriptor * field,int value) const254 void Reflection::AddEnumValue(Message* message,
255 const FieldDescriptor* field,
256 int value) const {
257 GOOGLE_LOG(FATAL) << "Unimplemented EnumValue API.";
258 }
259
MapBegin(Message * message,const FieldDescriptor * field) const260 MapIterator Reflection::MapBegin(
261 Message* message,
262 const FieldDescriptor* field) const {
263 GOOGLE_LOG(FATAL) << "Unimplemented Map Reflection API.";
264 MapIterator iter(message, field);
265 return iter;
266 }
267
MapEnd(Message * message,const FieldDescriptor * field) const268 MapIterator Reflection::MapEnd(
269 Message* message,
270 const FieldDescriptor* field) const {
271 GOOGLE_LOG(FATAL) << "Unimplemented Map Reflection API.";
272 MapIterator iter(message, field);
273 return iter;
274 }
275
276 // =============================================================================
277 // MessageFactory
278
~MessageFactory()279 MessageFactory::~MessageFactory() {}
280
281 namespace {
282
283 class GeneratedMessageFactory : public MessageFactory {
284 public:
285 GeneratedMessageFactory();
286 ~GeneratedMessageFactory();
287
288 static GeneratedMessageFactory* singleton();
289
290 typedef void RegistrationFunc(const string&);
291 void RegisterFile(const char* file, RegistrationFunc* registration_func);
292 void RegisterType(const Descriptor* descriptor, const Message* prototype);
293
294 // implements MessageFactory ---------------------------------------
295 const Message* GetPrototype(const Descriptor* type);
296
297 private:
298 // Only written at static init time, so does not require locking.
299 hash_map<const char*, RegistrationFunc*,
300 hash<const char*>, streq> file_map_;
301
302 // Initialized lazily, so requires locking.
303 Mutex mutex_;
304 hash_map<const Descriptor*, const Message*> type_map_;
305 };
306
307 GeneratedMessageFactory* generated_message_factory_ = NULL;
308 GOOGLE_PROTOBUF_DECLARE_ONCE(generated_message_factory_once_init_);
309
ShutdownGeneratedMessageFactory()310 void ShutdownGeneratedMessageFactory() {
311 delete generated_message_factory_;
312 }
313
InitGeneratedMessageFactory()314 void InitGeneratedMessageFactory() {
315 generated_message_factory_ = new GeneratedMessageFactory;
316 internal::OnShutdown(&ShutdownGeneratedMessageFactory);
317 }
318
GeneratedMessageFactory()319 GeneratedMessageFactory::GeneratedMessageFactory() {}
~GeneratedMessageFactory()320 GeneratedMessageFactory::~GeneratedMessageFactory() {}
321
singleton()322 GeneratedMessageFactory* GeneratedMessageFactory::singleton() {
323 ::google::protobuf::GoogleOnceInit(&generated_message_factory_once_init_,
324 &InitGeneratedMessageFactory);
325 return generated_message_factory_;
326 }
327
RegisterFile(const char * file,RegistrationFunc * registration_func)328 void GeneratedMessageFactory::RegisterFile(
329 const char* file, RegistrationFunc* registration_func) {
330 if (!InsertIfNotPresent(&file_map_, file, registration_func)) {
331 GOOGLE_LOG(FATAL) << "File is already registered: " << file;
332 }
333 }
334
RegisterType(const Descriptor * descriptor,const Message * prototype)335 void GeneratedMessageFactory::RegisterType(const Descriptor* descriptor,
336 const Message* prototype) {
337 GOOGLE_DCHECK_EQ(descriptor->file()->pool(), DescriptorPool::generated_pool())
338 << "Tried to register a non-generated type with the generated "
339 "type registry.";
340
341 // This should only be called as a result of calling a file registration
342 // function during GetPrototype(), in which case we already have locked
343 // the mutex.
344 mutex_.AssertHeld();
345 if (!InsertIfNotPresent(&type_map_, descriptor, prototype)) {
346 GOOGLE_LOG(DFATAL) << "Type is already registered: " << descriptor->full_name();
347 }
348 }
349
350
GetPrototype(const Descriptor * type)351 const Message* GeneratedMessageFactory::GetPrototype(const Descriptor* type) {
352 {
353 ReaderMutexLock lock(&mutex_);
354 const Message* result = FindPtrOrNull(type_map_, type);
355 if (result != NULL) return result;
356 }
357
358 // If the type is not in the generated pool, then we can't possibly handle
359 // it.
360 if (type->file()->pool() != DescriptorPool::generated_pool()) return NULL;
361
362 // Apparently the file hasn't been registered yet. Let's do that now.
363 RegistrationFunc* registration_func =
364 FindPtrOrNull(file_map_, type->file()->name().c_str());
365 if (registration_func == NULL) {
366 GOOGLE_LOG(DFATAL) << "File appears to be in generated pool but wasn't "
367 "registered: " << type->file()->name();
368 return NULL;
369 }
370
371 WriterMutexLock lock(&mutex_);
372
373 // Check if another thread preempted us.
374 const Message* result = FindPtrOrNull(type_map_, type);
375 if (result == NULL) {
376 // Nope. OK, register everything.
377 registration_func(type->file()->name());
378 // Should be here now.
379 result = FindPtrOrNull(type_map_, type);
380 }
381
382 if (result == NULL) {
383 GOOGLE_LOG(DFATAL) << "Type appears to be in generated pool but wasn't "
384 << "registered: " << type->full_name();
385 }
386
387 return result;
388 }
389
390 } // namespace
391
generated_factory()392 MessageFactory* MessageFactory::generated_factory() {
393 return GeneratedMessageFactory::singleton();
394 }
395
InternalRegisterGeneratedFile(const char * filename,void (* register_messages)(const string &))396 void MessageFactory::InternalRegisterGeneratedFile(
397 const char* filename, void (*register_messages)(const string&)) {
398 GeneratedMessageFactory::singleton()->RegisterFile(filename,
399 register_messages);
400 }
401
InternalRegisterGeneratedMessage(const Descriptor * descriptor,const Message * prototype)402 void MessageFactory::InternalRegisterGeneratedMessage(
403 const Descriptor* descriptor, const Message* prototype) {
404 GeneratedMessageFactory::singleton()->RegisterType(descriptor, prototype);
405 }
406
407
GetMessageFactory() const408 MessageFactory* Reflection::GetMessageFactory() const {
409 GOOGLE_LOG(FATAL) << "Not implemented.";
410 return NULL;
411 }
412
RepeatedFieldData(Message * message,const FieldDescriptor * field,FieldDescriptor::CppType cpp_type,const Descriptor * message_type) const413 void* Reflection::RepeatedFieldData(
414 Message* message, const FieldDescriptor* field,
415 FieldDescriptor::CppType cpp_type,
416 const Descriptor* message_type) const {
417 GOOGLE_LOG(FATAL) << "Not implemented.";
418 return NULL;
419 }
420
421 namespace internal {
~RepeatedFieldAccessor()422 RepeatedFieldAccessor::~RepeatedFieldAccessor() {
423 }
424 } // namespace internal
425
RepeatedFieldAccessor(const FieldDescriptor * field) const426 const internal::RepeatedFieldAccessor* Reflection::RepeatedFieldAccessor(
427 const FieldDescriptor* field) const {
428 GOOGLE_CHECK(field->is_repeated());
429 switch (field->cpp_type()) {
430 #define HANDLE_PRIMITIVE_TYPE(TYPE, type) \
431 case FieldDescriptor::CPPTYPE_ ## TYPE: \
432 return internal::Singleton<internal::RepeatedFieldPrimitiveAccessor<type> >::get();
433 HANDLE_PRIMITIVE_TYPE(INT32, int32)
434 HANDLE_PRIMITIVE_TYPE(UINT32, uint32)
435 HANDLE_PRIMITIVE_TYPE(INT64, int64)
436 HANDLE_PRIMITIVE_TYPE(UINT64, uint64)
437 HANDLE_PRIMITIVE_TYPE(FLOAT, float)
438 HANDLE_PRIMITIVE_TYPE(DOUBLE, double)
439 HANDLE_PRIMITIVE_TYPE(BOOL, bool)
440 HANDLE_PRIMITIVE_TYPE(ENUM, int32)
441 #undef HANDLE_PRIMITIVE_TYPE
442 case FieldDescriptor::CPPTYPE_STRING:
443 switch (field->options().ctype()) {
444 default:
445 case FieldOptions::STRING:
446 return internal::Singleton<internal::RepeatedPtrFieldStringAccessor>::get();
447 }
448 break;
449 case FieldDescriptor::CPPTYPE_MESSAGE:
450 if (field->is_map()) {
451 return internal::Singleton<internal::MapFieldAccessor>::get();
452 } else {
453 return internal::Singleton<internal::RepeatedPtrFieldMessageAccessor>::get();
454 }
455 }
456 GOOGLE_LOG(FATAL) << "Should not reach here.";
457 return NULL;
458 }
459
460 namespace internal {
461 namespace {
ShutdownRepeatedFieldAccessor()462 void ShutdownRepeatedFieldAccessor() {
463 internal::Singleton<internal::RepeatedFieldPrimitiveAccessor<int32> >::ShutDown();
464 internal::Singleton<internal::RepeatedFieldPrimitiveAccessor<uint32> >::ShutDown();
465 internal::Singleton<internal::RepeatedFieldPrimitiveAccessor<int64> >::ShutDown();
466 internal::Singleton<internal::RepeatedFieldPrimitiveAccessor<uint64> >::ShutDown();
467 internal::Singleton<internal::RepeatedFieldPrimitiveAccessor<float> >::ShutDown();
468 internal::Singleton<internal::RepeatedFieldPrimitiveAccessor<double> >::ShutDown();
469 internal::Singleton<internal::RepeatedFieldPrimitiveAccessor<bool> >::ShutDown();
470 internal::Singleton<internal::RepeatedPtrFieldStringAccessor>::ShutDown();
471 internal::Singleton<internal::RepeatedPtrFieldMessageAccessor>::ShutDown();
472 internal::Singleton<internal::MapFieldAccessor>::ShutDown();
473 }
474
475 struct ShutdownRepeatedFieldRegister {
ShutdownRepeatedFieldRegistergoogle::protobuf::internal::__anon9dfd28d60211::ShutdownRepeatedFieldRegister476 ShutdownRepeatedFieldRegister() {
477 OnShutdown(&ShutdownRepeatedFieldAccessor);
478 }
479 } shutdown_;
480
481 } // namespace
482 } // namespace internal
483
484 namespace internal {
485 template<>
486 #if defined(_MSC_VER) && (_MSC_VER >= 1900)
487 // Note: force noinline to workaround MSVC 2015 compiler bug, issue #240
488 GOOGLE_ATTRIBUTE_NOINLINE
489 #endif
NewFromPrototype(const Message * prototype,google::protobuf::Arena * arena)490 Message* GenericTypeHandler<Message>::NewFromPrototype(
491 const Message* prototype, google::protobuf::Arena* arena) {
492 return prototype->New(arena);
493 }
494 template<>
495 #if defined(_MSC_VER) && (_MSC_VER >= 1900)
496 // Note: force noinline to workaround MSVC 2015 compiler bug, issue #240
497 GOOGLE_ATTRIBUTE_NOINLINE
498 #endif
GetArena(Message * value)499 google::protobuf::Arena* GenericTypeHandler<Message>::GetArena(
500 Message* value) {
501 return value->GetArena();
502 }
503 template<>
504 #if defined(_MSC_VER) && (_MSC_VER >= 1900)
505 // Note: force noinline to workaround MSVC 2015 compiler bug, issue #240
506 GOOGLE_ATTRIBUTE_NOINLINE
507 #endif
GetMaybeArenaPointer(Message * value)508 void* GenericTypeHandler<Message>::GetMaybeArenaPointer(
509 Message* value) {
510 return value->GetMaybeArenaPointer();
511 }
512 } // namespace internal
513
514 } // namespace protobuf
515 } // namespace google
516