PageRenderTime 44ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/src/protobuf/src/google/protobuf/message.cc

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