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