PageRenderTime 110ms CodeModel.GetById 53ms app.highlight 51ms RepoModel.GetById 2ms app.codeStats 0ms

/thirdparty/breakpad/third_party/protobuf/protobuf/src/google/protobuf/message.cc

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