• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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