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