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