1fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Protocol Buffers - Google's data interchange format 2fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Copyright 2008 Google Inc. All rights reserved. 3fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// http://code.google.com/p/protobuf/ 4fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// 5fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Redistribution and use in source and binary forms, with or without 6fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// modification, are permitted provided that the following conditions are 7fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// met: 8fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// 9fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// * Redistributions of source code must retain the above copyright 10fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// notice, this list of conditions and the following disclaimer. 11fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// * Redistributions in binary form must reproduce the above 12fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// copyright notice, this list of conditions and the following disclaimer 13fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// in the documentation and/or other materials provided with the 14fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// distribution. 15fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// * Neither the name of Google Inc. nor the names of its 16fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// contributors may be used to endorse or promote products derived from 17fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// this software without specific prior written permission. 18fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// 19fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 31fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Author: kenton@google.com (Kenton Varda) 32fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Based on original Protocol Buffers design by 33fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Sanjay Ghemawat, Jeff Dean, and others. 34fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 35f03ad1a96ff9a713e26eccebad15c5ecd76ca911Wink Saville#include <istream> 36fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <stack> 37fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <google/protobuf/stubs/hash.h> 38fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 39fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <google/protobuf/message.h> 40fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 41fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <google/protobuf/stubs/common.h> 42fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <google/protobuf/stubs/once.h> 43fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <google/protobuf/io/coded_stream.h> 44fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <google/protobuf/io/zero_copy_stream_impl.h> 45fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <google/protobuf/descriptor.pb.h> 46fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <google/protobuf/descriptor.h> 47fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <google/protobuf/reflection_ops.h> 48fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <google/protobuf/wire_format.h> 49fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <google/protobuf/stubs/strutil.h> 50fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <google/protobuf/stubs/map-util.h> 51fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <google/protobuf/stubs/stl_util-inl.h> 52fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 53fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillenamespace google { 54fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillenamespace protobuf { 55fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 56fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleusing internal::WireFormat; 57fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleusing internal::ReflectionOps; 58fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 59fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleMessage::~Message() {} 60fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 61fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillevoid Message::MergeFrom(const Message& from) { 62fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville const Descriptor* descriptor = GetDescriptor(); 63fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville GOOGLE_CHECK_EQ(from.GetDescriptor(), descriptor) 64fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville << ": Tried to merge from a message with a different type. " 65fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "to: " << descriptor->full_name() << ", " 66fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "from:" << from.GetDescriptor()->full_name(); 67fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville ReflectionOps::Merge(from, this); 68fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 69fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 70fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillevoid Message::CheckTypeAndMergeFrom(const MessageLite& other) { 71fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville MergeFrom(*down_cast<const Message*>(&other)); 72fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 73fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 74fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillevoid Message::CopyFrom(const Message& from) { 75fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville const Descriptor* descriptor = GetDescriptor(); 76fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville GOOGLE_CHECK_EQ(from.GetDescriptor(), descriptor) 77fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville << ": Tried to copy from a message with a different type." 78fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "to: " << descriptor->full_name() << ", " 79fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "from:" << from.GetDescriptor()->full_name(); 80fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville ReflectionOps::Copy(from, this); 81fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 82fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 83fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillestring Message::GetTypeName() const { 84fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return GetDescriptor()->full_name(); 85fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 86fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 87fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillevoid Message::Clear() { 88fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville ReflectionOps::Clear(this); 89fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 90fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 91fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillebool Message::IsInitialized() const { 92fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return ReflectionOps::IsInitialized(*this); 93fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 94fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 95fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillevoid Message::FindInitializationErrors(vector<string>* errors) const { 96fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return ReflectionOps::FindInitializationErrors(*this, "", errors); 97fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 98fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 99fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillestring Message::InitializationErrorString() const { 100fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville vector<string> errors; 101fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville FindInitializationErrors(&errors); 102fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return JoinStrings(errors, ", "); 103fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 104fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 105fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillevoid Message::CheckInitialized() const { 106fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville GOOGLE_CHECK(IsInitialized()) 107fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville << "Message of type \"" << GetDescriptor()->full_name() 108fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville << "\" is missing required fields: " << InitializationErrorString(); 109fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 110fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 111fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillevoid Message::DiscardUnknownFields() { 112fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return ReflectionOps::DiscardUnknownFields(this); 113fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 114fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 115fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillebool Message::MergePartialFromCodedStream(io::CodedInputStream* input) { 116fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return WireFormat::ParseAndMergePartial(input, this); 117fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 118fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 119fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillebool Message::ParseFromFileDescriptor(int file_descriptor) { 120fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville io::FileInputStream input(file_descriptor); 121fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return ParseFromZeroCopyStream(&input) && input.GetErrno() == 0; 122fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 123fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 124fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillebool Message::ParsePartialFromFileDescriptor(int file_descriptor) { 125fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville io::FileInputStream input(file_descriptor); 126fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return ParsePartialFromZeroCopyStream(&input) && input.GetErrno() == 0; 127fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 128fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 129fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillebool Message::ParseFromIstream(istream* input) { 130fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville io::IstreamInputStream zero_copy_input(input); 131fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return ParseFromZeroCopyStream(&zero_copy_input) && input->eof(); 132fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 133fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 134fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillebool Message::ParsePartialFromIstream(istream* input) { 135fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville io::IstreamInputStream zero_copy_input(input); 136fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return ParsePartialFromZeroCopyStream(&zero_copy_input) && input->eof(); 137fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 138fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 139fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 140fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillevoid Message::SerializeWithCachedSizes( 141fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville io::CodedOutputStream* output) const { 142fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville WireFormat::SerializeWithCachedSizes(*this, GetCachedSize(), output); 143fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 144fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 145fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleint Message::ByteSize() const { 146fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville int size = WireFormat::ByteSize(*this); 147fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville SetCachedSize(size); 148fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return size; 149fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 150fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 151fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillevoid Message::SetCachedSize(int size) const { 152fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville GOOGLE_LOG(FATAL) << "Message class \"" << GetDescriptor()->full_name() 153fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville << "\" implements neither SetCachedSize() nor ByteSize(). " 154fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "Must implement one or the other."; 155fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 156fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 157fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleint Message::SpaceUsed() const { 158fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return GetReflection()->SpaceUsed(*this); 159fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 160fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 161fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillebool Message::SerializeToFileDescriptor(int file_descriptor) const { 162fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville io::FileOutputStream output(file_descriptor); 163fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return SerializeToZeroCopyStream(&output); 164fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 165fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 166fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillebool Message::SerializePartialToFileDescriptor(int file_descriptor) const { 167fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville io::FileOutputStream output(file_descriptor); 168fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return SerializePartialToZeroCopyStream(&output); 169fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 170fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 171fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillebool Message::SerializeToOstream(ostream* output) const { 172d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville { 173d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville io::OstreamOutputStream zero_copy_output(output); 174d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (!SerializeToZeroCopyStream(&zero_copy_output)) return false; 175d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 176d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville return output->good(); 177fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 178fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 179fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillebool Message::SerializePartialToOstream(ostream* output) const { 180fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville io::OstreamOutputStream zero_copy_output(output); 181fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return SerializePartialToZeroCopyStream(&zero_copy_output); 182fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 183fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 184fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 185fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleReflection::~Reflection() {} 186fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 187fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// =================================================================== 188fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// MessageFactory 189fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 190fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleMessageFactory::~MessageFactory() {} 191fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 192fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillenamespace { 193fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 194fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleclass GeneratedMessageFactory : public MessageFactory { 195fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public: 196fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville GeneratedMessageFactory(); 197fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville ~GeneratedMessageFactory(); 198fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 199fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville static GeneratedMessageFactory* singleton(); 200fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 201fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville typedef void RegistrationFunc(const string&); 202fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville void RegisterFile(const char* file, RegistrationFunc* registration_func); 203fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville void RegisterType(const Descriptor* descriptor, const Message* prototype); 204fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 205fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // implements MessageFactory --------------------------------------- 206fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville const Message* GetPrototype(const Descriptor* type); 207fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 208fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private: 209fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Only written at static init time, so does not require locking. 210fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville hash_map<const char*, RegistrationFunc*, 211fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville hash<const char*>, streq> file_map_; 212fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 213fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Initialized lazily, so requires locking. 214fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville Mutex mutex_; 215fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville hash_map<const Descriptor*, const Message*> type_map_; 216fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}; 217fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 218fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleGeneratedMessageFactory* generated_message_factory_ = NULL; 219fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleGOOGLE_PROTOBUF_DECLARE_ONCE(generated_message_factory_once_init_); 220fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 221fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillevoid ShutdownGeneratedMessageFactory() { 222fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville delete generated_message_factory_; 223fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 224fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 225fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillevoid InitGeneratedMessageFactory() { 226fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville generated_message_factory_ = new GeneratedMessageFactory; 227fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville internal::OnShutdown(&ShutdownGeneratedMessageFactory); 228fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 229fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 230fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleGeneratedMessageFactory::GeneratedMessageFactory() {} 231fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleGeneratedMessageFactory::~GeneratedMessageFactory() {} 232fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 233fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleGeneratedMessageFactory* GeneratedMessageFactory::singleton() { 234d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville ::google::protobuf::GoogleOnceInit(&generated_message_factory_once_init_, 235fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville &InitGeneratedMessageFactory); 236fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return generated_message_factory_; 237fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 238fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 239fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillevoid GeneratedMessageFactory::RegisterFile( 240fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville const char* file, RegistrationFunc* registration_func) { 241fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (!InsertIfNotPresent(&file_map_, file, registration_func)) { 242fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville GOOGLE_LOG(FATAL) << "File is already registered: " << file; 243fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 244fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 245fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 246fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillevoid GeneratedMessageFactory::RegisterType(const Descriptor* descriptor, 247fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville const Message* prototype) { 248fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville GOOGLE_DCHECK_EQ(descriptor->file()->pool(), DescriptorPool::generated_pool()) 249fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville << "Tried to register a non-generated type with the generated " 250fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "type registry."; 251fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 252fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // This should only be called as a result of calling a file registration 253fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // function during GetPrototype(), in which case we already have locked 254fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // the mutex. 255fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville mutex_.AssertHeld(); 256fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (!InsertIfNotPresent(&type_map_, descriptor, prototype)) { 257fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville GOOGLE_LOG(DFATAL) << "Type is already registered: " << descriptor->full_name(); 258fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 259fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 260fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 261fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleconst Message* GeneratedMessageFactory::GetPrototype(const Descriptor* type) { 262fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville { 263fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville ReaderMutexLock lock(&mutex_); 264fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville const Message* result = FindPtrOrNull(type_map_, type); 265fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (result != NULL) return result; 266fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 267fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 268fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // If the type is not in the generated pool, then we can't possibly handle 269fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // it. 270fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (type->file()->pool() != DescriptorPool::generated_pool()) return NULL; 271fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 272fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Apparently the file hasn't been registered yet. Let's do that now. 273fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville RegistrationFunc* registration_func = 274fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville FindPtrOrNull(file_map_, type->file()->name().c_str()); 275fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (registration_func == NULL) { 276fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville GOOGLE_LOG(DFATAL) << "File appears to be in generated pool but wasn't " 277fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "registered: " << type->file()->name(); 278fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return NULL; 279fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 280fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 281fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville WriterMutexLock lock(&mutex_); 282fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 283fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Check if another thread preempted us. 284fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville const Message* result = FindPtrOrNull(type_map_, type); 285fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (result == NULL) { 286fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Nope. OK, register everything. 287fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville registration_func(type->file()->name()); 288fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Should be here now. 289fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville result = FindPtrOrNull(type_map_, type); 290fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 291fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 292fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (result == NULL) { 293fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville GOOGLE_LOG(DFATAL) << "Type appears to be in generated pool but wasn't " 294fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville << "registered: " << type->full_name(); 295fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 296fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 297fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return result; 298fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 299fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 300fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} // namespace 301fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 302fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleMessageFactory* MessageFactory::generated_factory() { 303fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return GeneratedMessageFactory::singleton(); 304fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 305fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 306fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillevoid MessageFactory::InternalRegisterGeneratedFile( 307fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville const char* filename, void (*register_messages)(const string&)) { 308fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville GeneratedMessageFactory::singleton()->RegisterFile(filename, 309fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville register_messages); 310fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 311fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 312fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillevoid MessageFactory::InternalRegisterGeneratedMessage( 313fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville const Descriptor* descriptor, const Message* prototype) { 314fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville GeneratedMessageFactory::singleton()->RegisterType(descriptor, prototype); 315fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 316fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 317fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 318fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} // namespace protobuf 319fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} // namespace google 320