LCOV - code coverage report
Current view: top level - third_party/protobuf/src/google/protobuf - message_lite.cc (source / functions) Hit Total Coverage
Test: tmp.zDYK9MVh93 Lines: 56 134 41.8 %
Date: 2015-10-10 Functions: 13 32 40.6 %

          Line data    Source code
       1             : // Protocol Buffers - Google's data interchange format
       2             : // Copyright 2008 Google Inc.  All rights reserved.
       3             : // https://developers.google.com/protocol-buffers/
       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             : // Authors: wink@google.com (Wink Saville),
      32             : //          kenton@google.com (Kenton Varda)
      33             : //  Based on original Protocol Buffers design by
      34             : //  Sanjay Ghemawat, Jeff Dean, and others.
      35             : 
      36             : #include <google/protobuf/message_lite.h>
      37             : #include <google/protobuf/arena.h>
      38             : #include <google/protobuf/repeated_field.h>
      39             : #include <string>
      40             : #include <google/protobuf/stubs/logging.h>
      41             : #include <google/protobuf/stubs/common.h>
      42             : #include <google/protobuf/io/coded_stream.h>
      43             : #include <google/protobuf/io/zero_copy_stream_impl_lite.h>
      44             : #include <google/protobuf/stubs/stl_util.h>
      45             : 
      46             : namespace google {
      47             : namespace protobuf {
      48             : 
      49     7686911 : MessageLite::~MessageLite() {}
      50             : 
      51           0 : string MessageLite::InitializationErrorString() const {
      52           0 :   return "(cannot determine missing fields for lite message)";
      53             : }
      54             : 
      55             : namespace {
      56             : 
      57             : // When serializing, we first compute the byte size, then serialize the message.
      58             : // If serialization produces a different number of bytes than expected, we
      59             : // call this function, which crashes.  The problem could be due to a bug in the
      60             : // protobuf implementation but is more likely caused by concurrent modification
      61             : // of the message.  This function attempts to distinguish between the two and
      62             : // provide a useful error message.
      63           0 : void ByteSizeConsistencyError(int byte_size_before_serialization,
      64             :                               int byte_size_after_serialization,
      65             :                               int bytes_produced_by_serialization) {
      66           0 :   GOOGLE_CHECK_EQ(byte_size_before_serialization, byte_size_after_serialization)
      67           0 :       << "Protocol message was modified concurrently during serialization.";
      68           0 :   GOOGLE_CHECK_EQ(bytes_produced_by_serialization, byte_size_before_serialization)
      69             :       << "Byte size calculation and serialization were inconsistent.  This "
      70             :          "may indicate a bug in protocol buffers or it may be caused by "
      71           0 :          "concurrent modification of the message.";
      72           0 :   GOOGLE_LOG(FATAL) << "This shouldn't be called if all the sizes are equal.";
      73           0 : }
      74             : 
      75           0 : string InitializationErrorMessage(const char* action,
      76             :                                   const MessageLite& message) {
      77             :   // Note:  We want to avoid depending on strutil in the lite library, otherwise
      78             :   //   we'd use:
      79             :   //
      80             :   // return strings::Substitute(
      81             :   //   "Can't $0 message of type \"$1\" because it is missing required "
      82             :   //   "fields: $2",
      83             :   //   action, message.GetTypeName(),
      84             :   //   message.InitializationErrorString());
      85             : 
      86             :   string result;
      87             :   result += "Can't ";
      88             :   result += action;
      89             :   result += " message of type \"";
      90           0 :   result += message.GetTypeName();
      91             :   result += "\" because it is missing required fields: ";
      92           0 :   result += message.InitializationErrorString();
      93           0 :   return result;
      94             : }
      95             : 
      96             : // Several of the Parse methods below just do one thing and then call another
      97             : // method.  In a naive implementation, we might have ParseFromString() call
      98             : // ParseFromArray() which would call ParseFromZeroCopyStream() which would call
      99             : // ParseFromCodedStream() which would call MergeFromCodedStream() which would
     100             : // call MergePartialFromCodedStream().  However, when parsing very small
     101             : // messages, every function call introduces significant overhead.  To avoid
     102             : // this without reproducing code, we use these forced-inline helpers.
     103             : GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool InlineMergeFromCodedStream(
     104             :     io::CodedInputStream* input, MessageLite* message);
     105             : GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool InlineParseFromCodedStream(
     106             :     io::CodedInputStream* input, MessageLite* message);
     107             : GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool InlineParsePartialFromCodedStream(
     108             :     io::CodedInputStream* input, MessageLite* message);
     109             : GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool InlineParseFromArray(
     110             :     const void* data, int size, MessageLite* message);
     111             : GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool InlineParsePartialFromArray(
     112             :     const void* data, int size, MessageLite* message);
     113             : 
     114             : inline bool InlineMergeFromCodedStream(io::CodedInputStream* input,
     115             :                                        MessageLite* message) {
     116     2795551 :   if (!message->MergePartialFromCodedStream(input)) return false;
     117     2795949 :   if (!message->IsInitialized()) {
     118           0 :     GOOGLE_LOG(ERROR) << InitializationErrorMessage("parse", *message);
     119             :     return false;
     120             :   }
     121             :   return true;
     122             : }
     123             : 
     124             : inline bool InlineParseFromCodedStream(io::CodedInputStream* input,
     125             :                                        MessageLite* message) {
     126     2795721 :   message->Clear();
     127             :   return InlineMergeFromCodedStream(input, message);
     128             : }
     129             : 
     130             : inline bool InlineParsePartialFromCodedStream(io::CodedInputStream* input,
     131             :                                               MessageLite* message) {
     132           0 :   message->Clear();
     133           0 :   return message->MergePartialFromCodedStream(input);
     134             : }
     135             : 
     136             : inline bool InlineParseFromArray(
     137             :     const void* data, int size, MessageLite* message) {
     138         830 :   io::CodedInputStream input(reinterpret_cast<const uint8*>(data), size);
     139        1660 :   return InlineParseFromCodedStream(&input, message) &&
     140        1660 :          input.ConsumedEntireMessage();
     141             : }
     142             : 
     143             : inline bool InlineParsePartialFromArray(
     144             :     const void* data, int size, MessageLite* message) {
     145           0 :   io::CodedInputStream input(reinterpret_cast<const uint8*>(data), size);
     146           0 :   return InlineParsePartialFromCodedStream(&input, message) &&
     147           0 :          input.ConsumedEntireMessage();
     148             : }
     149             : 
     150             : }  // namespace
     151             : 
     152             : 
     153           0 : MessageLite* MessageLite::New(::google::protobuf::Arena* arena) const {
     154           0 :   MessageLite* message = New();
     155           0 :   if (arena != NULL) {
     156           0 :     arena->Own(message);
     157             :   }
     158           0 :   return message;
     159             : }
     160             : 
     161           0 : bool MessageLite::MergeFromCodedStream(io::CodedInputStream* input) {
     162           0 :   return InlineMergeFromCodedStream(input, this);
     163             : }
     164             : 
     165     2794891 : bool MessageLite::ParseFromCodedStream(io::CodedInputStream* input) {
     166     2794973 :   return InlineParseFromCodedStream(input, this);
     167             : }
     168             : 
     169           0 : bool MessageLite::ParsePartialFromCodedStream(io::CodedInputStream* input) {
     170           0 :   return InlineParsePartialFromCodedStream(input, this);
     171             : }
     172             : 
     173           8 : bool MessageLite::ParseFromZeroCopyStream(io::ZeroCopyInputStream* input) {
     174           8 :   io::CodedInputStream decoder(input);
     175           8 :   return ParseFromCodedStream(&decoder) && decoder.ConsumedEntireMessage();
     176             : }
     177             : 
     178           0 : bool MessageLite::ParsePartialFromZeroCopyStream(
     179             :     io::ZeroCopyInputStream* input) {
     180           0 :   io::CodedInputStream decoder(input);
     181           0 :   return ParsePartialFromCodedStream(&decoder) &&
     182           0 :          decoder.ConsumedEntireMessage();
     183             : }
     184             : 
     185           0 : bool MessageLite::ParseFromBoundedZeroCopyStream(
     186             :     io::ZeroCopyInputStream* input, int size) {
     187           0 :   io::CodedInputStream decoder(input);
     188           0 :   decoder.PushLimit(size);
     189           0 :   return ParseFromCodedStream(&decoder) &&
     190           0 :          decoder.ConsumedEntireMessage() &&
     191           0 :          decoder.BytesUntilLimit() == 0;
     192             : }
     193             : 
     194           0 : bool MessageLite::ParsePartialFromBoundedZeroCopyStream(
     195             :     io::ZeroCopyInputStream* input, int size) {
     196           0 :   io::CodedInputStream decoder(input);
     197           0 :   decoder.PushLimit(size);
     198           0 :   return ParsePartialFromCodedStream(&decoder) &&
     199           0 :          decoder.ConsumedEntireMessage() &&
     200           0 :          decoder.BytesUntilLimit() == 0;
     201             : }
     202             : 
     203         722 : bool MessageLite::ParseFromString(const string& data) {
     204        1444 :   return InlineParseFromArray(data.data(), data.size(), this);
     205             : }
     206             : 
     207           0 : bool MessageLite::ParsePartialFromString(const string& data) {
     208           0 :   return InlineParsePartialFromArray(data.data(), data.size(), this);
     209             : }
     210             : 
     211         108 : bool MessageLite::ParseFromArray(const void* data, int size) {
     212         108 :   return InlineParseFromArray(data, size, this);
     213             : }
     214             : 
     215           0 : bool MessageLite::ParsePartialFromArray(const void* data, int size) {
     216           0 :   return InlineParsePartialFromArray(data, size, this);
     217             : }
     218             : 
     219             : 
     220             : // ===================================================================
     221             : 
     222           9 : uint8* MessageLite::SerializeWithCachedSizesToArray(uint8* target) const {
     223             :   // We only optimize this when using optimize_for = SPEED.  In other cases
     224             :   // we just use the CodedOutputStream path.
     225           9 :   int size = GetCachedSize();
     226           9 :   io::ArrayOutputStream out(target, size);
     227          18 :   io::CodedOutputStream coded_out(&out);
     228           9 :   SerializeWithCachedSizes(&coded_out);
     229           9 :   GOOGLE_CHECK(!coded_out.HadError());
     230          18 :   return target + size;
     231             : }
     232             : 
     233          24 : bool MessageLite::SerializeToCodedStream(io::CodedOutputStream* output) const {
     234             :   GOOGLE_DCHECK(IsInitialized()) << InitializationErrorMessage("serialize", *this);
     235          24 :   return SerializePartialToCodedStream(output);
     236             : }
     237             : 
     238          24 : bool MessageLite::SerializePartialToCodedStream(
     239          95 :     io::CodedOutputStream* output) const {
     240          24 :   const int size = ByteSize();  // Force size to be cached.
     241          24 :   if (size < 0) {
     242             :     // Messages >2G cannot be serialized due to overflow computing ByteSize.
     243           0 :     GOOGLE_LOG(ERROR) << "Error computing ByteSize (possible overflow?).";
     244           0 :     return false;
     245             :   }
     246             : 
     247          24 :   uint8* buffer = output->GetDirectBufferForNBytesAndAdvance(size);
     248          24 :   if (buffer != NULL) {
     249           5 :     uint8* end = SerializeWithCachedSizesToArray(buffer);
     250           5 :     if (end - buffer != size) {
     251           0 :       ByteSizeConsistencyError(size, ByteSize(), end - buffer);
     252             :     }
     253             :     return true;
     254             :   } else {
     255          57 :     int original_byte_count = output->ByteCount();
     256          19 :     SerializeWithCachedSizes(output);
     257          19 :     if (output->HadError()) {
     258             :       return false;
     259             :     }
     260          57 :     int final_byte_count = output->ByteCount();
     261             : 
     262          19 :     if (final_byte_count - original_byte_count != size) {
     263           0 :       ByteSizeConsistencyError(size, ByteSize(),
     264           0 :                                final_byte_count - original_byte_count);
     265             :     }
     266             : 
     267             :     return true;
     268             :   }
     269             : }
     270             : 
     271          24 : bool MessageLite::SerializeToZeroCopyStream(
     272             :     io::ZeroCopyOutputStream* output) const {
     273          24 :   io::CodedOutputStream encoder(output);
     274          24 :   return SerializeToCodedStream(&encoder);
     275             : }
     276             : 
     277           0 : bool MessageLite::SerializePartialToZeroCopyStream(
     278             :     io::ZeroCopyOutputStream* output) const {
     279           0 :   io::CodedOutputStream encoder(output);
     280           0 :   return SerializePartialToCodedStream(&encoder);
     281             : }
     282             : 
     283         776 : bool MessageLite::AppendToString(string* output) const {
     284             :   GOOGLE_DCHECK(IsInitialized()) << InitializationErrorMessage("serialize", *this);
     285         776 :   return AppendPartialToString(output);
     286             : }
     287             : 
     288         776 : bool MessageLite::AppendPartialToString(string* output) const {
     289         776 :   int old_size = output->size();
     290         776 :   int byte_size = ByteSize();
     291         776 :   if (byte_size < 0) {
     292             :     // Messages >2G cannot be serialized due to overflow computing ByteSize.
     293           0 :     GOOGLE_LOG(ERROR) << "Error computing ByteSize (possible overflow?).";
     294           0 :     return false;
     295             :   }
     296             : 
     297         776 :   STLStringResizeUninitialized(output, old_size + byte_size);
     298             :   uint8* start =
     299         776 :       reinterpret_cast<uint8*>(io::mutable_string_data(output) + old_size);
     300         776 :   uint8* end = SerializeWithCachedSizesToArray(start);
     301         776 :   if (end - start != byte_size) {
     302           0 :     ByteSizeConsistencyError(byte_size, ByteSize(), end - start);
     303             :   }
     304             :   return true;
     305             : }
     306             : 
     307          78 : bool MessageLite::SerializeToString(string* output) const {
     308             :   output->clear();
     309          78 :   return AppendToString(output);
     310             : }
     311             : 
     312           0 : bool MessageLite::SerializePartialToString(string* output) const {
     313             :   output->clear();
     314           0 :   return AppendPartialToString(output);
     315             : }
     316             : 
     317           0 : bool MessageLite::SerializeToArray(void* data, int size) const {
     318             :   GOOGLE_DCHECK(IsInitialized()) << InitializationErrorMessage("serialize", *this);
     319           0 :   return SerializePartialToArray(data, size);
     320             : }
     321             : 
     322           0 : bool MessageLite::SerializePartialToArray(void* data, int size) const {
     323           0 :   int byte_size = ByteSize();
     324           0 :   if (size < byte_size) return false;
     325           0 :   uint8* start = reinterpret_cast<uint8*>(data);
     326           0 :   uint8* end = SerializeWithCachedSizesToArray(start);
     327           0 :   if (end - start != byte_size) {
     328           0 :     ByteSizeConsistencyError(byte_size, ByteSize(), end - start);
     329             :   }
     330             :   return true;
     331             : }
     332             : 
     333         424 : string MessageLite::SerializeAsString() const {
     334             :   // If the compiler implements the (Named) Return Value Optimization,
     335             :   // the local variable 'output' will not actually reside on the stack
     336             :   // of this function, but will be overlaid with the object that the
     337             :   // caller supplied for the return value to be constructed in.
     338             :   string output;
     339         424 :   if (!AppendToString(&output))
     340             :     output.clear();
     341         424 :   return output;
     342             : }
     343             : 
     344           0 : string MessageLite::SerializePartialAsString() const {
     345             :   string output;
     346           0 :   if (!AppendPartialToString(&output))
     347             :     output.clear();
     348           0 :   return output;
     349             : }
     350             : 
     351             : namespace internal {
     352             : template<>
     353           0 : MessageLite* GenericTypeHandler<MessageLite>::NewFromPrototype(
     354             :     const MessageLite* prototype, google::protobuf::Arena* arena) {
     355           0 :   return prototype->New(arena);
     356             : }
     357             : template <>
     358           0 : void GenericTypeHandler<MessageLite>::Merge(const MessageLite& from,
     359             :                                             MessageLite* to) {
     360           0 :   to->CheckTypeAndMergeFrom(from);
     361           0 : }
     362             : }  // namespace internal
     363             : 
     364             : }  // namespace protobuf
     365             : }  // namespace google

Generated by: LCOV version 1.10