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/common.h>
     42 #include <google/protobuf/stubs/once.h>
     43 #include <google/protobuf/io/coded_stream.h>
     44 #include <google/protobuf/io/zero_copy_stream_impl.h>
     45 #include <google/protobuf/descriptor.pb.h>
     46 #include <google/protobuf/descriptor.h>
     47 #include <google/protobuf/generated_message_util.h>
     48 #include <google/protobuf/reflection_ops.h>
     49 #include <google/protobuf/wire_format.h>
     50 #include <google/protobuf/stubs/strutil.h>
     51 #include <google/protobuf/stubs/map_util.h>
     52 #include <google/protobuf/stubs/stl_util.h>
     53 
     54 namespace google {
     55 namespace protobuf {
     56 
     57 using internal::WireFormat;
     58 using internal::ReflectionOps;
     59 
     60 Message::~Message() {}
     61 
     62 void Message::MergeFrom(const Message& from) {
     63   const Descriptor* descriptor = GetDescriptor();
     64   GOOGLE_CHECK_EQ(from.GetDescriptor(), descriptor)
     65     << ": Tried to merge from a message with a different type.  "
     66        "to: " << descriptor->full_name() << ", "
     67        "from:" << from.GetDescriptor()->full_name();
     68   ReflectionOps::Merge(from, this);
     69 }
     70 
     71 void Message::CheckTypeAndMergeFrom(const MessageLite& other) {
     72   MergeFrom(*down_cast<const Message*>(&other));
     73 }
     74 
     75 void Message::CopyFrom(const Message& from) {
     76   const Descriptor* descriptor = GetDescriptor();
     77   GOOGLE_CHECK_EQ(from.GetDescriptor(), descriptor)
     78     << ": Tried to copy from a message with a different type. "
     79        "to: " << descriptor->full_name() << ", "
     80        "from:" << from.GetDescriptor()->full_name();
     81   ReflectionOps::Copy(from, this);
     82 }
     83 
     84 string Message::GetTypeName() const {
     85   return GetDescriptor()->full_name();
     86 }
     87 
     88 void Message::Clear() {
     89   ReflectionOps::Clear(this);
     90 }
     91 
     92 bool Message::IsInitialized() const {
     93   return ReflectionOps::IsInitialized(*this);
     94 }
     95 
     96 void Message::FindInitializationErrors(vector<string>* errors) const {
     97   return ReflectionOps::FindInitializationErrors(*this, "", errors);
     98 }
     99 
    100 string Message::InitializationErrorString() const {
    101   vector<string> errors;
    102   FindInitializationErrors(&errors);
    103   return Join(errors, ", ");
    104 }
    105 
    106 void Message::CheckInitialized() const {
    107   GOOGLE_CHECK(IsInitialized())
    108     << "Message of type \"" << GetDescriptor()->full_name()
    109     << "\" is missing required fields: " << InitializationErrorString();
    110 }
    111 
    112 void Message::DiscardUnknownFields() {
    113   return ReflectionOps::DiscardUnknownFields(this);
    114 }
    115 
    116 bool Message::MergePartialFromCodedStream(io::CodedInputStream* input) {
    117   return WireFormat::ParseAndMergePartial(input, this);
    118 }
    119 
    120 bool Message::ParseFromFileDescriptor(int file_descriptor) {
    121   io::FileInputStream input(file_descriptor);
    122   return ParseFromZeroCopyStream(&input) && input.GetErrno() == 0;
    123 }
    124 
    125 bool Message::ParsePartialFromFileDescriptor(int file_descriptor) {
    126   io::FileInputStream input(file_descriptor);
    127   return ParsePartialFromZeroCopyStream(&input) && input.GetErrno() == 0;
    128 }
    129 
    130 bool Message::ParseFromIstream(istream* input) {
    131   io::IstreamInputStream zero_copy_input(input);
    132   return ParseFromZeroCopyStream(&zero_copy_input) && input->eof();
    133 }
    134 
    135 bool Message::ParsePartialFromIstream(istream* input) {
    136   io::IstreamInputStream zero_copy_input(input);
    137   return ParsePartialFromZeroCopyStream(&zero_copy_input) && input->eof();
    138 }
    139 
    140 
    141 void Message::SerializeWithCachedSizes(
    142     io::CodedOutputStream* output) const {
    143   WireFormat::SerializeWithCachedSizes(*this, GetCachedSize(), output);
    144 }
    145 
    146 int Message::ByteSize() const {
    147   int size = WireFormat::ByteSize(*this);
    148   SetCachedSize(size);
    149   return size;
    150 }
    151 
    152 void Message::SetCachedSize(int /* size */) const {
    153   GOOGLE_LOG(FATAL) << "Message class \"" << GetDescriptor()->full_name()
    154              << "\" implements neither SetCachedSize() nor ByteSize().  "
    155                 "Must implement one or the other.";
    156 }
    157 
    158 int Message::SpaceUsed() const {
    159   return GetReflection()->SpaceUsed(*this);
    160 }
    161 
    162 bool Message::SerializeToFileDescriptor(int file_descriptor) const {
    163   io::FileOutputStream output(file_descriptor);
    164   return SerializeToZeroCopyStream(&output);
    165 }
    166 
    167 bool Message::SerializePartialToFileDescriptor(int file_descriptor) const {
    168   io::FileOutputStream output(file_descriptor);
    169   return SerializePartialToZeroCopyStream(&output);
    170 }
    171 
    172 bool Message::SerializeToOstream(ostream* output) const {
    173   {
    174     io::OstreamOutputStream zero_copy_output(output);
    175     if (!SerializeToZeroCopyStream(&zero_copy_output)) return false;
    176   }
    177   return output->good();
    178 }
    179 
    180 bool Message::SerializePartialToOstream(ostream* output) const {
    181   io::OstreamOutputStream zero_copy_output(output);
    182   return SerializePartialToZeroCopyStream(&zero_copy_output);
    183 }
    184 
    185 
    186 // =============================================================================
    187 // Reflection and associated Template Specializations
    188 
    189 Reflection::~Reflection() {}
    190 
    191 #define HANDLE_TYPE(TYPE, CPPTYPE, CTYPE)                             \
    192 template<>                                                            \
    193 const RepeatedField<TYPE>& Reflection::GetRepeatedField<TYPE>(        \
    194     const Message& message, const FieldDescriptor* field) const {     \
    195   return *static_cast<RepeatedField<TYPE>* >(                         \
    196       MutableRawRepeatedField(const_cast<Message*>(&message),         \
    197                           field, CPPTYPE, CTYPE, NULL));              \
    198 }                                                                     \
    199                                                                       \
    200 template<>                                                            \
    201 RepeatedField<TYPE>* Reflection::MutableRepeatedField<TYPE>(          \
    202     Message* message, const FieldDescriptor* field) const {           \
    203   return static_cast<RepeatedField<TYPE>* >(                          \
    204       MutableRawRepeatedField(message, field, CPPTYPE, CTYPE, NULL)); \
    205 }
    206 
    207 HANDLE_TYPE(int32,  FieldDescriptor::CPPTYPE_INT32,  -1);
    208 HANDLE_TYPE(int64,  FieldDescriptor::CPPTYPE_INT64,  -1);
    209 HANDLE_TYPE(uint32, FieldDescriptor::CPPTYPE_UINT32, -1);
    210 HANDLE_TYPE(uint64, FieldDescriptor::CPPTYPE_UINT64, -1);
    211 HANDLE_TYPE(float,  FieldDescriptor::CPPTYPE_FLOAT,  -1);
    212 HANDLE_TYPE(double, FieldDescriptor::CPPTYPE_DOUBLE, -1);
    213 HANDLE_TYPE(bool,   FieldDescriptor::CPPTYPE_BOOL,   -1);
    214 
    215 
    216 #undef HANDLE_TYPE
    217 
    218 void* Reflection::MutableRawRepeatedString(
    219     Message* message, const FieldDescriptor* field, bool is_string) const {
    220   return MutableRawRepeatedField(message, field,
    221       FieldDescriptor::CPPTYPE_STRING, FieldOptions::STRING, NULL);
    222 }
    223 
    224 
    225 // =============================================================================
    226 // MessageFactory
    227 
    228 MessageFactory::~MessageFactory() {}
    229 
    230 namespace {
    231 
    232 class GeneratedMessageFactory : public MessageFactory {
    233  public:
    234   GeneratedMessageFactory();
    235   ~GeneratedMessageFactory();
    236 
    237   static GeneratedMessageFactory* singleton();
    238 
    239   typedef void RegistrationFunc(const string&);
    240   void RegisterFile(const char* file, RegistrationFunc* registration_func);
    241   void RegisterType(const Descriptor* descriptor, const Message* prototype);
    242 
    243   // implements MessageFactory ---------------------------------------
    244   const Message* GetPrototype(const Descriptor* type);
    245 
    246  private:
    247   // Only written at static init time, so does not require locking.
    248   hash_map<const char*, RegistrationFunc*,
    249            hash<const char*>, streq> file_map_;
    250 
    251   // Initialized lazily, so requires locking.
    252   Mutex mutex_;
    253   hash_map<const Descriptor*, const Message*> type_map_;
    254 };
    255 
    256 GeneratedMessageFactory* generated_message_factory_ = NULL;
    257 GOOGLE_PROTOBUF_DECLARE_ONCE(generated_message_factory_once_init_);
    258 
    259 void ShutdownGeneratedMessageFactory() {
    260   delete generated_message_factory_;
    261 }
    262 
    263 void InitGeneratedMessageFactory() {
    264   generated_message_factory_ = new GeneratedMessageFactory;
    265   internal::OnShutdown(&ShutdownGeneratedMessageFactory);
    266 }
    267 
    268 GeneratedMessageFactory::GeneratedMessageFactory() {}
    269 GeneratedMessageFactory::~GeneratedMessageFactory() {}
    270 
    271 GeneratedMessageFactory* GeneratedMessageFactory::singleton() {
    272   ::google::protobuf::GoogleOnceInit(&generated_message_factory_once_init_,
    273                  &InitGeneratedMessageFactory);
    274   return generated_message_factory_;
    275 }
    276 
    277 void GeneratedMessageFactory::RegisterFile(
    278     const char* file, RegistrationFunc* registration_func) {
    279   if (!InsertIfNotPresent(&file_map_, file, registration_func)) {
    280     GOOGLE_LOG(FATAL) << "File is already registered: " << file;
    281   }
    282 }
    283 
    284 void GeneratedMessageFactory::RegisterType(const Descriptor* descriptor,
    285                                            const Message* prototype) {
    286   GOOGLE_DCHECK_EQ(descriptor->file()->pool(), DescriptorPool::generated_pool())
    287     << "Tried to register a non-generated type with the generated "
    288        "type registry.";
    289 
    290   // This should only be called as a result of calling a file registration
    291   // function during GetPrototype(), in which case we already have locked
    292   // the mutex.
    293   mutex_.AssertHeld();
    294   if (!InsertIfNotPresent(&type_map_, descriptor, prototype)) {
    295     GOOGLE_LOG(DFATAL) << "Type is already registered: " << descriptor->full_name();
    296   }
    297 }
    298 
    299 
    300 const Message* GeneratedMessageFactory::GetPrototype(const Descriptor* type) {
    301   {
    302     ReaderMutexLock lock(&mutex_);
    303     const Message* result = FindPtrOrNull(type_map_, type);
    304     if (result != NULL) return result;
    305   }
    306 
    307   // If the type is not in the generated pool, then we can't possibly handle
    308   // it.
    309   if (type->file()->pool() != DescriptorPool::generated_pool()) return NULL;
    310 
    311   // Apparently the file hasn't been registered yet.  Let's do that now.
    312   RegistrationFunc* registration_func =
    313       FindPtrOrNull(file_map_, type->file()->name().c_str());
    314   if (registration_func == NULL) {
    315     GOOGLE_LOG(DFATAL) << "File appears to be in generated pool but wasn't "
    316                    "registered: " << type->file()->name();
    317     return NULL;
    318   }
    319 
    320   WriterMutexLock lock(&mutex_);
    321 
    322   // Check if another thread preempted us.
    323   const Message* result = FindPtrOrNull(type_map_, type);
    324   if (result == NULL) {
    325     // Nope.  OK, register everything.
    326     registration_func(type->file()->name());
    327     // Should be here now.
    328     result = FindPtrOrNull(type_map_, type);
    329   }
    330 
    331   if (result == NULL) {
    332     GOOGLE_LOG(DFATAL) << "Type appears to be in generated pool but wasn't "
    333                 << "registered: " << type->full_name();
    334   }
    335 
    336   return result;
    337 }
    338 
    339 }  // namespace
    340 
    341 MessageFactory* MessageFactory::generated_factory() {
    342   return GeneratedMessageFactory::singleton();
    343 }
    344 
    345 void MessageFactory::InternalRegisterGeneratedFile(
    346     const char* filename, void (*register_messages)(const string&)) {
    347   GeneratedMessageFactory::singleton()->RegisterFile(filename,
    348                                                      register_messages);
    349 }
    350 
    351 void MessageFactory::InternalRegisterGeneratedMessage(
    352     const Descriptor* descriptor, const Message* prototype) {
    353   GeneratedMessageFactory::singleton()->RegisterType(descriptor, prototype);
    354 }
    355 
    356 
    357 }  // namespace protobuf
    358 }  // namespace google
    359