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

http://github.com/tomahawk-player/tomahawk · C++ · 334 lines · 225 code · 45 blank · 64 comment · 20 complexity · e4b782047dd8c423ce03abc3b16d425a 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. // Authors: wink@google.com (Wink Saville),
  31. // kenton@google.com (Kenton Varda)
  32. // Based on original Protocol Buffers design by
  33. // Sanjay Ghemawat, Jeff Dean, and others.
  34. #include <google/protobuf/message_lite.h>
  35. #include <string>
  36. #include <google/protobuf/stubs/common.h>
  37. #include <google/protobuf/io/coded_stream.h>
  38. #include <google/protobuf/io/zero_copy_stream_impl.h>
  39. #include <google/protobuf/stubs/stl_util-inl.h>
  40. namespace google {
  41. namespace protobuf {
  42. MessageLite::~MessageLite() {}
  43. string MessageLite::InitializationErrorString() const {
  44. return "(cannot determine missing fields for lite message)";
  45. }
  46. namespace {
  47. // When serializing, we first compute the byte size, then serialize the message.
  48. // If serialization produces a different number of bytes than expected, we
  49. // call this function, which crashes. The problem could be due to a bug in the
  50. // protobuf implementation but is more likely caused by concurrent modification
  51. // of the message. This function attempts to distinguish between the two and
  52. // provide a useful error message.
  53. void ByteSizeConsistencyError(int byte_size_before_serialization,
  54. int byte_size_after_serialization,
  55. int bytes_produced_by_serialization) {
  56. GOOGLE_CHECK_EQ(byte_size_before_serialization, byte_size_after_serialization)
  57. << "Protocol message was modified concurrently during serialization.";
  58. GOOGLE_CHECK_EQ(bytes_produced_by_serialization, byte_size_before_serialization)
  59. << "Byte size calculation and serialization were inconsistent. This "
  60. "may indicate a bug in protocol buffers or it may be caused by "
  61. "concurrent modification of the message.";
  62. GOOGLE_LOG(FATAL) << "This shouldn't be called if all the sizes are equal.";
  63. }
  64. string InitializationErrorMessage(const char* action,
  65. const MessageLite& message) {
  66. // Note: We want to avoid depending on strutil in the lite library, otherwise
  67. // we'd use:
  68. //
  69. // return strings::Substitute(
  70. // "Can't $0 message of type \"$1\" because it is missing required "
  71. // "fields: $2",
  72. // action, message.GetTypeName(),
  73. // message.InitializationErrorString());
  74. string result;
  75. result += "Can't ";
  76. result += action;
  77. result += " message of type \"";
  78. result += message.GetTypeName();
  79. result += "\" because it is missing required fields: ";
  80. result += message.InitializationErrorString();
  81. return result;
  82. }
  83. // Several of the Parse methods below just do one thing and then call another
  84. // method. In a naive implementation, we might have ParseFromString() call
  85. // ParseFromArray() which would call ParseFromZeroCopyStream() which would call
  86. // ParseFromCodedStream() which would call MergeFromCodedStream() which would
  87. // call MergePartialFromCodedStream(). However, when parsing very small
  88. // messages, every function call introduces significant overhead. To avoid
  89. // this without reproducing code, we use these forced-inline helpers.
  90. //
  91. // Note: GCC only allows GOOGLE_ATTRIBUTE_ALWAYS_INLINE on declarations, not
  92. // definitions.
  93. inline bool InlineMergeFromCodedStream(io::CodedInputStream* input,
  94. MessageLite* message)
  95. GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
  96. inline bool InlineParseFromCodedStream(io::CodedInputStream* input,
  97. MessageLite* message)
  98. GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
  99. inline bool InlineParsePartialFromCodedStream(io::CodedInputStream* input,
  100. MessageLite* message)
  101. GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
  102. inline bool InlineParseFromArray(const void* data, int size,
  103. MessageLite* message)
  104. GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
  105. inline bool InlineParsePartialFromArray(const void* data, int size,
  106. MessageLite* message)
  107. GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
  108. bool InlineMergeFromCodedStream(io::CodedInputStream* input,
  109. MessageLite* message) {
  110. if (!message->MergePartialFromCodedStream(input)) return false;
  111. if (!message->IsInitialized()) {
  112. GOOGLE_LOG(ERROR) << InitializationErrorMessage("parse", *message);
  113. return false;
  114. }
  115. return true;
  116. }
  117. bool InlineParseFromCodedStream(io::CodedInputStream* input,
  118. MessageLite* message) {
  119. message->Clear();
  120. return InlineMergeFromCodedStream(input, message);
  121. }
  122. bool InlineParsePartialFromCodedStream(io::CodedInputStream* input,
  123. MessageLite* message) {
  124. message->Clear();
  125. return message->MergePartialFromCodedStream(input);
  126. }
  127. bool InlineParseFromArray(const void* data, int size, MessageLite* message) {
  128. io::CodedInputStream input(reinterpret_cast<const uint8*>(data), size);
  129. return InlineParseFromCodedStream(&input, message) &&
  130. input.ConsumedEntireMessage();
  131. }
  132. bool InlineParsePartialFromArray(const void* data, int size,
  133. MessageLite* message) {
  134. io::CodedInputStream input(reinterpret_cast<const uint8*>(data), size);
  135. return InlineParsePartialFromCodedStream(&input, message) &&
  136. input.ConsumedEntireMessage();
  137. }
  138. } // namespace
  139. bool MessageLite::MergeFromCodedStream(io::CodedInputStream* input) {
  140. return InlineMergeFromCodedStream(input, this);
  141. }
  142. bool MessageLite::ParseFromCodedStream(io::CodedInputStream* input) {
  143. return InlineParseFromCodedStream(input, this);
  144. }
  145. bool MessageLite::ParsePartialFromCodedStream(io::CodedInputStream* input) {
  146. return InlineParsePartialFromCodedStream(input, this);
  147. }
  148. bool MessageLite::ParseFromZeroCopyStream(io::ZeroCopyInputStream* input) {
  149. io::CodedInputStream decoder(input);
  150. return ParseFromCodedStream(&decoder) && decoder.ConsumedEntireMessage();
  151. }
  152. bool MessageLite::ParsePartialFromZeroCopyStream(
  153. io::ZeroCopyInputStream* input) {
  154. io::CodedInputStream decoder(input);
  155. return ParsePartialFromCodedStream(&decoder) &&
  156. decoder.ConsumedEntireMessage();
  157. }
  158. bool MessageLite::ParseFromBoundedZeroCopyStream(
  159. io::ZeroCopyInputStream* input, int size) {
  160. io::CodedInputStream decoder(input);
  161. decoder.PushLimit(size);
  162. return ParseFromCodedStream(&decoder) &&
  163. decoder.ConsumedEntireMessage() &&
  164. decoder.BytesUntilLimit() == 0;
  165. }
  166. bool MessageLite::ParsePartialFromBoundedZeroCopyStream(
  167. io::ZeroCopyInputStream* input, int size) {
  168. io::CodedInputStream decoder(input);
  169. decoder.PushLimit(size);
  170. return ParsePartialFromCodedStream(&decoder) &&
  171. decoder.ConsumedEntireMessage() &&
  172. decoder.BytesUntilLimit() == 0;
  173. }
  174. bool MessageLite::ParseFromString(const string& data) {
  175. return InlineParseFromArray(data.data(), data.size(), this);
  176. }
  177. bool MessageLite::ParsePartialFromString(const string& data) {
  178. return InlineParsePartialFromArray(data.data(), data.size(), this);
  179. }
  180. bool MessageLite::ParseFromArray(const void* data, int size) {
  181. return InlineParseFromArray(data, size, this);
  182. }
  183. bool MessageLite::ParsePartialFromArray(const void* data, int size) {
  184. return InlineParsePartialFromArray(data, size, this);
  185. }
  186. // ===================================================================
  187. uint8* MessageLite::SerializeWithCachedSizesToArray(uint8* target) const {
  188. // We only optimize this when using optimize_for = SPEED. In other cases
  189. // we just use the CodedOutputStream path.
  190. int size = GetCachedSize();
  191. io::ArrayOutputStream out(target, size);
  192. io::CodedOutputStream coded_out(&out);
  193. SerializeWithCachedSizes(&coded_out);
  194. GOOGLE_CHECK(!coded_out.HadError());
  195. return target + size;
  196. }
  197. bool MessageLite::SerializeToCodedStream(io::CodedOutputStream* output) const {
  198. GOOGLE_DCHECK(IsInitialized()) << InitializationErrorMessage("serialize", *this);
  199. return SerializePartialToCodedStream(output);
  200. }
  201. bool MessageLite::SerializePartialToCodedStream(
  202. io::CodedOutputStream* output) const {
  203. const int size = ByteSize(); // Force size to be cached.
  204. uint8* buffer = output->GetDirectBufferForNBytesAndAdvance(size);
  205. if (buffer != NULL) {
  206. uint8* end = SerializeWithCachedSizesToArray(buffer);
  207. if (end - buffer != size) {
  208. ByteSizeConsistencyError(size, ByteSize(), end - buffer);
  209. }
  210. return true;
  211. } else {
  212. int original_byte_count = output->ByteCount();
  213. SerializeWithCachedSizes(output);
  214. if (output->HadError()) {
  215. return false;
  216. }
  217. int final_byte_count = output->ByteCount();
  218. if (final_byte_count - original_byte_count != size) {
  219. ByteSizeConsistencyError(size, ByteSize(),
  220. final_byte_count - original_byte_count);
  221. }
  222. return true;
  223. }
  224. }
  225. bool MessageLite::SerializeToZeroCopyStream(
  226. io::ZeroCopyOutputStream* output) const {
  227. io::CodedOutputStream encoder(output);
  228. return SerializeToCodedStream(&encoder);
  229. }
  230. bool MessageLite::SerializePartialToZeroCopyStream(
  231. io::ZeroCopyOutputStream* output) const {
  232. io::CodedOutputStream encoder(output);
  233. return SerializePartialToCodedStream(&encoder);
  234. }
  235. bool MessageLite::AppendToString(string* output) const {
  236. GOOGLE_DCHECK(IsInitialized()) << InitializationErrorMessage("serialize", *this);
  237. return AppendPartialToString(output);
  238. }
  239. bool MessageLite::AppendPartialToString(string* output) const {
  240. int old_size = output->size();
  241. int byte_size = ByteSize();
  242. STLStringResizeUninitialized(output, old_size + byte_size);
  243. uint8* start = reinterpret_cast<uint8*>(string_as_array(output) + old_size);
  244. uint8* end = SerializeWithCachedSizesToArray(start);
  245. if (end - start != byte_size) {
  246. ByteSizeConsistencyError(byte_size, ByteSize(), end - start);
  247. }
  248. return true;
  249. }
  250. bool MessageLite::SerializeToString(string* output) const {
  251. output->clear();
  252. return AppendToString(output);
  253. }
  254. bool MessageLite::SerializePartialToString(string* output) const {
  255. output->clear();
  256. return AppendPartialToString(output);
  257. }
  258. bool MessageLite::SerializeToArray(void* data, int size) const {
  259. GOOGLE_DCHECK(IsInitialized()) << InitializationErrorMessage("serialize", *this);
  260. return SerializePartialToArray(data, size);
  261. }
  262. bool MessageLite::SerializePartialToArray(void* data, int size) const {
  263. int byte_size = ByteSize();
  264. if (size < byte_size) return false;
  265. uint8* start = reinterpret_cast<uint8*>(data);
  266. uint8* end = SerializeWithCachedSizesToArray(start);
  267. if (end - start != byte_size) {
  268. ByteSizeConsistencyError(byte_size, ByteSize(), end - start);
  269. }
  270. return true;
  271. }
  272. string MessageLite::SerializeAsString() const {
  273. // If the compiler implements the (Named) Return Value Optimization,
  274. // the local variable 'result' will not actually reside on the stack
  275. // of this function, but will be overlaid with the object that the
  276. // caller supplied for the return value to be constructed in.
  277. string output;
  278. if (!AppendToString(&output))
  279. output.clear();
  280. return output;
  281. }
  282. string MessageLite::SerializePartialAsString() const {
  283. string output;
  284. if (!AppendPartialToString(&output))
  285. output.clear();
  286. return output;
  287. }
  288. } // namespace protobuf
  289. } // namespace google