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/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 54namespace google { 55namespace protobuf { 56 57using internal::WireFormat; 58using internal::ReflectionOps; 59 60Message::~Message() {} 61 62void 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 71void Message::CheckTypeAndMergeFrom(const MessageLite& other) { 72 MergeFrom(*down_cast<const Message*>(&other)); 73} 74 75void 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 84string Message::GetTypeName() const { 85 return GetDescriptor()->full_name(); 86} 87 88void Message::Clear() { 89 ReflectionOps::Clear(this); 90} 91 92bool Message::IsInitialized() const { 93 return ReflectionOps::IsInitialized(*this); 94} 95 96void Message::FindInitializationErrors(vector<string>* errors) const { 97 return ReflectionOps::FindInitializationErrors(*this, "", errors); 98} 99 100string Message::InitializationErrorString() const { 101 vector<string> errors; 102 FindInitializationErrors(&errors); 103 return Join(errors, ", "); 104} 105 106void Message::CheckInitialized() const { 107 GOOGLE_CHECK(IsInitialized()) 108 << "Message of type \"" << GetDescriptor()->full_name() 109 << "\" is missing required fields: " << InitializationErrorString(); 110} 111 112void Message::DiscardUnknownFields() { 113 return ReflectionOps::DiscardUnknownFields(this); 114} 115 116bool Message::MergePartialFromCodedStream(io::CodedInputStream* input) { 117 return WireFormat::ParseAndMergePartial(input, this); 118} 119 120bool Message::ParseFromFileDescriptor(int file_descriptor) { 121 io::FileInputStream input(file_descriptor); 122 return ParseFromZeroCopyStream(&input) && input.GetErrno() == 0; 123} 124 125bool Message::ParsePartialFromFileDescriptor(int file_descriptor) { 126 io::FileInputStream input(file_descriptor); 127 return ParsePartialFromZeroCopyStream(&input) && input.GetErrno() == 0; 128} 129 130bool Message::ParseFromIstream(istream* input) { 131 io::IstreamInputStream zero_copy_input(input); 132 return ParseFromZeroCopyStream(&zero_copy_input) && input->eof(); 133} 134 135bool Message::ParsePartialFromIstream(istream* input) { 136 io::IstreamInputStream zero_copy_input(input); 137 return ParsePartialFromZeroCopyStream(&zero_copy_input) && input->eof(); 138} 139 140 141void Message::SerializeWithCachedSizes( 142 io::CodedOutputStream* output) const { 143 WireFormat::SerializeWithCachedSizes(*this, GetCachedSize(), output); 144} 145 146int Message::ByteSize() const { 147 int size = WireFormat::ByteSize(*this); 148 SetCachedSize(size); 149 return size; 150} 151 152void 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 158int Message::SpaceUsed() const { 159 return GetReflection()->SpaceUsed(*this); 160} 161 162bool Message::SerializeToFileDescriptor(int file_descriptor) const { 163 io::FileOutputStream output(file_descriptor); 164 return SerializeToZeroCopyStream(&output); 165} 166 167bool Message::SerializePartialToFileDescriptor(int file_descriptor) const { 168 io::FileOutputStream output(file_descriptor); 169 return SerializePartialToZeroCopyStream(&output); 170} 171 172bool 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 180bool 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 189Reflection::~Reflection() {} 190 191#define HANDLE_TYPE(TYPE, CPPTYPE, CTYPE) \ 192template<> \ 193const 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 \ 200template<> \ 201RepeatedField<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 207HANDLE_TYPE(int32, FieldDescriptor::CPPTYPE_INT32, -1); 208HANDLE_TYPE(int64, FieldDescriptor::CPPTYPE_INT64, -1); 209HANDLE_TYPE(uint32, FieldDescriptor::CPPTYPE_UINT32, -1); 210HANDLE_TYPE(uint64, FieldDescriptor::CPPTYPE_UINT64, -1); 211HANDLE_TYPE(float, FieldDescriptor::CPPTYPE_FLOAT, -1); 212HANDLE_TYPE(double, FieldDescriptor::CPPTYPE_DOUBLE, -1); 213HANDLE_TYPE(bool, FieldDescriptor::CPPTYPE_BOOL, -1); 214 215 216#undef HANDLE_TYPE 217 218void* 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 228MessageFactory::~MessageFactory() {} 229 230namespace { 231 232class 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 256GeneratedMessageFactory* generated_message_factory_ = NULL; 257GOOGLE_PROTOBUF_DECLARE_ONCE(generated_message_factory_once_init_); 258 259void ShutdownGeneratedMessageFactory() { 260 delete generated_message_factory_; 261} 262 263void InitGeneratedMessageFactory() { 264 generated_message_factory_ = new GeneratedMessageFactory; 265 internal::OnShutdown(&ShutdownGeneratedMessageFactory); 266} 267 268GeneratedMessageFactory::GeneratedMessageFactory() {} 269GeneratedMessageFactory::~GeneratedMessageFactory() {} 270 271GeneratedMessageFactory* GeneratedMessageFactory::singleton() { 272 ::google::protobuf::GoogleOnceInit(&generated_message_factory_once_init_, 273 &InitGeneratedMessageFactory); 274 return generated_message_factory_; 275} 276 277void 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 284void 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 300const 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 341MessageFactory* MessageFactory::generated_factory() { 342 return GeneratedMessageFactory::singleton(); 343} 344 345void MessageFactory::InternalRegisterGeneratedFile( 346 const char* filename, void (*register_messages)(const string&)) { 347 GeneratedMessageFactory::singleton()->RegisterFile(filename, 348 register_messages); 349} 350 351void 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