1 // Protocol Buffers - Google's data interchange format 2 // Copyright 2008 Google Inc. All rights reserved. 3 // http://code.google.com/p/protobuf/ 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 <istream> 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 JoinStrings(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