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/descriptor.h>
50 #include <google/protobuf/generated_message_util.h>
51 #include <google/protobuf/map_field.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(std::vector<string> * errors) const99 void Message::FindInitializationErrors(std::vector<string>* errors) const {
100 return ReflectionOps::FindInitializationErrors(*this, "", errors);
101 }
102
InitializationErrorString() const103 string Message::InitializationErrorString() const {
104 std::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(std::istream * input)133 bool Message::ParseFromIstream(std::istream* input) {
134 io::IstreamInputStream zero_copy_input(input);
135 return ParseFromZeroCopyStream(&zero_copy_input) && input->eof();
136 }
137
ParsePartialFromIstream(std::istream * input)138 bool Message::ParsePartialFromIstream(std::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 const internal::SerializationTable* table =
147 static_cast<const internal::SerializationTable*>(InternalGetTable());
148 if (table == 0) {
149 WireFormat::SerializeWithCachedSizes(*this, GetCachedSize(), output);
150 } else {
151 internal::TableSerialize(*this, table, output);
152 }
153 }
154
ByteSizeLong() const155 size_t Message::ByteSizeLong() const {
156 size_t size = WireFormat::ByteSize(*this);
157 SetCachedSize(internal::ToCachedSize(size));
158 return size;
159 }
160
SetCachedSize(int) const161 void Message::SetCachedSize(int /* size */) const {
162 GOOGLE_LOG(FATAL) << "Message class \"" << GetDescriptor()->full_name()
163 << "\" implements neither SetCachedSize() nor ByteSize(). "
164 "Must implement one or the other.";
165 }
166
SpaceUsedLong() const167 size_t Message::SpaceUsedLong() const {
168 return GetReflection()->SpaceUsedLong(*this);
169 }
170
SerializeToFileDescriptor(int file_descriptor) const171 bool Message::SerializeToFileDescriptor(int file_descriptor) const {
172 io::FileOutputStream output(file_descriptor);
173 return SerializeToZeroCopyStream(&output);
174 }
175
SerializePartialToFileDescriptor(int file_descriptor) const176 bool Message::SerializePartialToFileDescriptor(int file_descriptor) const {
177 io::FileOutputStream output(file_descriptor);
178 return SerializePartialToZeroCopyStream(&output);
179 }
180
SerializeToOstream(std::ostream * output) const181 bool Message::SerializeToOstream(std::ostream* output) const {
182 {
183 io::OstreamOutputStream zero_copy_output(output);
184 if (!SerializeToZeroCopyStream(&zero_copy_output)) return false;
185 }
186 return output->good();
187 }
188
SerializePartialToOstream(std::ostream * output) const189 bool Message::SerializePartialToOstream(std::ostream* output) const {
190 io::OstreamOutputStream zero_copy_output(output);
191 return SerializePartialToZeroCopyStream(&zero_copy_output);
192 }
193
194
195 // =============================================================================
196 // Reflection and associated Template Specializations
197
~Reflection()198 Reflection::~Reflection() {}
199
AddAllocatedMessage(Message *,const FieldDescriptor *,Message *) const200 void Reflection::AddAllocatedMessage(Message* /* message */,
201 const FieldDescriptor* /*field */,
202 Message* /* new_entry */) const {}
203
204 #define HANDLE_TYPE(TYPE, CPPTYPE, CTYPE) \
205 template<> \
206 const RepeatedField<TYPE>& Reflection::GetRepeatedField<TYPE>( \
207 const Message& message, const FieldDescriptor* field) const { \
208 return *static_cast<RepeatedField<TYPE>* >( \
209 MutableRawRepeatedField(const_cast<Message*>(&message), \
210 field, CPPTYPE, CTYPE, NULL)); \
211 } \
212 \
213 template<> \
214 RepeatedField<TYPE>* Reflection::MutableRepeatedField<TYPE>( \
215 Message* message, const FieldDescriptor* field) const { \
216 return static_cast<RepeatedField<TYPE>* >( \
217 MutableRawRepeatedField(message, field, CPPTYPE, CTYPE, NULL)); \
218 }
219
220 HANDLE_TYPE(int32, FieldDescriptor::CPPTYPE_INT32, -1);
221 HANDLE_TYPE(int64, FieldDescriptor::CPPTYPE_INT64, -1);
222 HANDLE_TYPE(uint32, FieldDescriptor::CPPTYPE_UINT32, -1);
223 HANDLE_TYPE(uint64, FieldDescriptor::CPPTYPE_UINT64, -1);
224 HANDLE_TYPE(float, FieldDescriptor::CPPTYPE_FLOAT, -1);
225 HANDLE_TYPE(double, FieldDescriptor::CPPTYPE_DOUBLE, -1);
226 HANDLE_TYPE(bool, FieldDescriptor::CPPTYPE_BOOL, -1);
227
228
229 #undef HANDLE_TYPE
230
MutableRawRepeatedString(Message * message,const FieldDescriptor * field,bool is_string) const231 void* Reflection::MutableRawRepeatedString(
232 Message* message, const FieldDescriptor* field, bool is_string) const {
233 return MutableRawRepeatedField(message, field,
234 FieldDescriptor::CPPTYPE_STRING, FieldOptions::STRING, NULL);
235 }
236
237
MapBegin(Message * message,const FieldDescriptor * field) const238 MapIterator Reflection::MapBegin(
239 Message* message,
240 const FieldDescriptor* field) const {
241 GOOGLE_LOG(FATAL) << "Unimplemented Map Reflection API.";
242 MapIterator iter(message, field);
243 return iter;
244 }
245
MapEnd(Message * message,const FieldDescriptor * field) const246 MapIterator Reflection::MapEnd(
247 Message* message,
248 const FieldDescriptor* field) const {
249 GOOGLE_LOG(FATAL) << "Unimplemented Map Reflection API.";
250 MapIterator iter(message, field);
251 return iter;
252 }
253
254 // =============================================================================
255 // MessageFactory
256
~MessageFactory()257 MessageFactory::~MessageFactory() {}
258
259 namespace {
260
261 class GeneratedMessageFactory : public MessageFactory {
262 public:
263 GeneratedMessageFactory();
264 ~GeneratedMessageFactory();
265
266 static GeneratedMessageFactory* singleton();
267
268 typedef void RegistrationFunc(const string&);
269 void RegisterFile(const char* file, RegistrationFunc* registration_func);
270 void RegisterType(const Descriptor* descriptor, const Message* prototype);
271
272 // implements MessageFactory ---------------------------------------
273 const Message* GetPrototype(const Descriptor* type);
274
275 private:
276 // Only written at static init time, so does not require locking.
277 hash_map<const char*, RegistrationFunc*,
278 hash<const char*>, streq> file_map_;
279
280 Mutex mutex_;
281 // Initialized lazily, so requires locking.
282 hash_map<const Descriptor*, const Message*> type_map_;
283 };
284
285 GeneratedMessageFactory* generated_message_factory_ = NULL;
286 GOOGLE_PROTOBUF_DECLARE_ONCE(generated_message_factory_once_init_);
287
ShutdownGeneratedMessageFactory()288 void ShutdownGeneratedMessageFactory() {
289 delete generated_message_factory_;
290 }
291
InitGeneratedMessageFactory()292 void InitGeneratedMessageFactory() {
293 generated_message_factory_ = new GeneratedMessageFactory;
294 internal::OnShutdown(&ShutdownGeneratedMessageFactory);
295 }
296
GeneratedMessageFactory()297 GeneratedMessageFactory::GeneratedMessageFactory() {}
~GeneratedMessageFactory()298 GeneratedMessageFactory::~GeneratedMessageFactory() {}
299
singleton()300 GeneratedMessageFactory* GeneratedMessageFactory::singleton() {
301 ::google::protobuf::GoogleOnceInit(&generated_message_factory_once_init_,
302 &InitGeneratedMessageFactory);
303 return generated_message_factory_;
304 }
305
RegisterFile(const char * file,RegistrationFunc * registration_func)306 void GeneratedMessageFactory::RegisterFile(
307 const char* file, RegistrationFunc* registration_func) {
308 if (!InsertIfNotPresent(&file_map_, file, registration_func)) {
309 GOOGLE_LOG(FATAL) << "File is already registered: " << file;
310 }
311 }
312
RegisterType(const Descriptor * descriptor,const Message * prototype)313 void GeneratedMessageFactory::RegisterType(const Descriptor* descriptor,
314 const Message* prototype) {
315 GOOGLE_DCHECK_EQ(descriptor->file()->pool(), DescriptorPool::generated_pool())
316 << "Tried to register a non-generated type with the generated "
317 "type registry.";
318
319 // This should only be called as a result of calling a file registration
320 // function during GetPrototype(), in which case we already have locked
321 // the mutex.
322 mutex_.AssertHeld();
323 if (!InsertIfNotPresent(&type_map_, descriptor, prototype)) {
324 GOOGLE_LOG(DFATAL) << "Type is already registered: " << descriptor->full_name();
325 }
326 }
327
328
GetPrototype(const Descriptor * type)329 const Message* GeneratedMessageFactory::GetPrototype(const Descriptor* type) {
330 {
331 ReaderMutexLock lock(&mutex_);
332 const Message* result = FindPtrOrNull(type_map_, type);
333 if (result != NULL) return result;
334 }
335
336 // If the type is not in the generated pool, then we can't possibly handle
337 // it.
338 if (type->file()->pool() != DescriptorPool::generated_pool()) return NULL;
339
340 // Apparently the file hasn't been registered yet. Let's do that now.
341 RegistrationFunc* registration_func =
342 FindPtrOrNull(file_map_, type->file()->name().c_str());
343 if (registration_func == NULL) {
344 GOOGLE_LOG(DFATAL) << "File appears to be in generated pool but wasn't "
345 "registered: " << type->file()->name();
346 return NULL;
347 }
348
349 WriterMutexLock lock(&mutex_);
350
351 // Check if another thread preempted us.
352 const Message* result = FindPtrOrNull(type_map_, type);
353 if (result == NULL) {
354 // Nope. OK, register everything.
355 registration_func(type->file()->name());
356 // Should be here now.
357 result = FindPtrOrNull(type_map_, type);
358 }
359
360 if (result == NULL) {
361 GOOGLE_LOG(DFATAL) << "Type appears to be in generated pool but wasn't "
362 << "registered: " << type->full_name();
363 }
364
365 return result;
366 }
367
368 } // namespace
369
generated_factory()370 MessageFactory* MessageFactory::generated_factory() {
371 return GeneratedMessageFactory::singleton();
372 }
373
InternalRegisterGeneratedFile(const char * filename,void (* register_messages)(const string &))374 void MessageFactory::InternalRegisterGeneratedFile(
375 const char* filename, void (*register_messages)(const string&)) {
376 GeneratedMessageFactory::singleton()->RegisterFile(filename,
377 register_messages);
378 }
379
InternalRegisterGeneratedMessage(const Descriptor * descriptor,const Message * prototype)380 void MessageFactory::InternalRegisterGeneratedMessage(
381 const Descriptor* descriptor, const Message* prototype) {
382 GeneratedMessageFactory::singleton()->RegisterType(descriptor, prototype);
383 }
384
385
GetMessageFactory() const386 MessageFactory* Reflection::GetMessageFactory() const {
387 GOOGLE_LOG(FATAL) << "Not implemented.";
388 return NULL;
389 }
390
RepeatedFieldData(Message * message,const FieldDescriptor * field,FieldDescriptor::CppType cpp_type,const Descriptor * message_type) const391 void* Reflection::RepeatedFieldData(
392 Message* message, const FieldDescriptor* field,
393 FieldDescriptor::CppType cpp_type,
394 const Descriptor* message_type) const {
395 GOOGLE_LOG(FATAL) << "Not implemented.";
396 return NULL;
397 }
398
399 namespace internal {
~RepeatedFieldAccessor()400 RepeatedFieldAccessor::~RepeatedFieldAccessor() {
401 }
402 } // namespace internal
403
RepeatedFieldAccessor(const FieldDescriptor * field) const404 const internal::RepeatedFieldAccessor* Reflection::RepeatedFieldAccessor(
405 const FieldDescriptor* field) const {
406 GOOGLE_CHECK(field->is_repeated());
407 switch (field->cpp_type()) {
408 #define HANDLE_PRIMITIVE_TYPE(TYPE, type) \
409 case FieldDescriptor::CPPTYPE_ ## TYPE: \
410 return internal::Singleton<internal::RepeatedFieldPrimitiveAccessor<type> >::get();
411 HANDLE_PRIMITIVE_TYPE(INT32, int32)
412 HANDLE_PRIMITIVE_TYPE(UINT32, uint32)
413 HANDLE_PRIMITIVE_TYPE(INT64, int64)
414 HANDLE_PRIMITIVE_TYPE(UINT64, uint64)
415 HANDLE_PRIMITIVE_TYPE(FLOAT, float)
416 HANDLE_PRIMITIVE_TYPE(DOUBLE, double)
417 HANDLE_PRIMITIVE_TYPE(BOOL, bool)
418 HANDLE_PRIMITIVE_TYPE(ENUM, int32)
419 #undef HANDLE_PRIMITIVE_TYPE
420 case FieldDescriptor::CPPTYPE_STRING:
421 switch (field->options().ctype()) {
422 default:
423 case FieldOptions::STRING:
424 return internal::Singleton<internal::RepeatedPtrFieldStringAccessor>::get();
425 }
426 break;
427 case FieldDescriptor::CPPTYPE_MESSAGE:
428 if (field->is_map()) {
429 return internal::Singleton<internal::MapFieldAccessor>::get();
430 } else {
431 return internal::Singleton<internal::RepeatedPtrFieldMessageAccessor>::get();
432 }
433 }
434 GOOGLE_LOG(FATAL) << "Should not reach here.";
435 return NULL;
436 }
437
438 namespace internal {
439 namespace {
ShutdownRepeatedFieldAccessor()440 void ShutdownRepeatedFieldAccessor() {
441 internal::Singleton<internal::RepeatedFieldPrimitiveAccessor<int32> >::ShutDown();
442 internal::Singleton<internal::RepeatedFieldPrimitiveAccessor<uint32> >::ShutDown();
443 internal::Singleton<internal::RepeatedFieldPrimitiveAccessor<int64> >::ShutDown();
444 internal::Singleton<internal::RepeatedFieldPrimitiveAccessor<uint64> >::ShutDown();
445 internal::Singleton<internal::RepeatedFieldPrimitiveAccessor<float> >::ShutDown();
446 internal::Singleton<internal::RepeatedFieldPrimitiveAccessor<double> >::ShutDown();
447 internal::Singleton<internal::RepeatedFieldPrimitiveAccessor<bool> >::ShutDown();
448 internal::Singleton<internal::RepeatedPtrFieldStringAccessor>::ShutDown();
449 internal::Singleton<internal::RepeatedPtrFieldMessageAccessor>::ShutDown();
450 internal::Singleton<internal::MapFieldAccessor>::ShutDown();
451 }
452
453 struct ShutdownRepeatedFieldRegister {
ShutdownRepeatedFieldRegistergoogle::protobuf::internal::__anon78df6caa0211::ShutdownRepeatedFieldRegister454 ShutdownRepeatedFieldRegister() {
455 OnShutdown(&ShutdownRepeatedFieldAccessor);
456 }
457 } shutdown_;
458
459 } // namespace
460 } // namespace internal
461
462 namespace internal {
463 template<>
464 #if defined(_MSC_VER) && (_MSC_VER >= 1800)
465 // Note: force noinline to workaround MSVC compiler bug with /Zc:inline, issue #240
466 GOOGLE_ATTRIBUTE_NOINLINE
467 #endif
NewFromPrototype(const Message * prototype,google::protobuf::Arena * arena)468 Message* GenericTypeHandler<Message>::NewFromPrototype(
469 const Message* prototype, google::protobuf::Arena* arena) {
470 return prototype->New(arena);
471 }
472 template<>
473 #if defined(_MSC_VER) && (_MSC_VER >= 1800)
474 // Note: force noinline to workaround MSVC compiler bug with /Zc:inline, issue #240
475 GOOGLE_ATTRIBUTE_NOINLINE
476 #endif
GetArena(Message * value)477 google::protobuf::Arena* GenericTypeHandler<Message>::GetArena(
478 Message* value) {
479 return value->GetArena();
480 }
481 template<>
482 #if defined(_MSC_VER) && (_MSC_VER >= 1800)
483 // Note: force noinline to workaround MSVC compiler bug with /Zc:inline, issue #240
484 GOOGLE_ATTRIBUTE_NOINLINE
485 #endif
GetMaybeArenaPointer(Message * value)486 void* GenericTypeHandler<Message>::GetMaybeArenaPointer(
487 Message* value) {
488 return value->GetMaybeArenaPointer();
489 }
490 } // namespace internal
491
492 } // namespace protobuf
493 } // namespace google
494