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