Home | History | Annotate | Download | only in io
      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 (at) google.com (Kenton Varda)
     32 //  Based on original Protocol Buffers design by
     33 //  Sanjay Ghemawat, Jeff Dean, and others.
     34 //
     35 // This implementation is heavily optimized to make reads and writes
     36 // of small values (especially varints) as fast as possible.  In
     37 // particular, we optimize for the common case that a read or a write
     38 // will not cross the end of the buffer, since we can avoid a lot
     39 // of branching in this case.
     40 
     41 #include <google/protobuf/io/coded_stream_inl.h>
     42 #include <algorithm>
     43 #include <limits.h>
     44 #include <google/protobuf/io/zero_copy_stream.h>
     45 #include <google/protobuf/stubs/common.h>
     46 #include <google/protobuf/stubs/stl_util.h>
     47 
     48 
     49 namespace google {
     50 namespace protobuf {
     51 namespace io {
     52 
     53 namespace {
     54 
     55 static const int kMaxVarintBytes = 10;
     56 static const int kMaxVarint32Bytes = 5;
     57 
     58 
     59 inline bool NextNonEmpty(ZeroCopyInputStream* input,
     60                          const void** data, int* size) {
     61   bool success;
     62   do {
     63     success = input->Next(data, size);
     64   } while (success && *size == 0);
     65   return success;
     66 }
     67 
     68 }  // namespace
     69 
     70 // CodedInputStream ==================================================
     71 
     72 CodedInputStream::~CodedInputStream() {
     73   if (input_ != NULL) {
     74     BackUpInputToCurrentPosition();
     75   }
     76 
     77   if (total_bytes_warning_threshold_ == -2) {
     78     GOOGLE_LOG(WARNING) << "The total number of bytes read was " << total_bytes_read_;
     79   }
     80 }
     81 
     82 // Static.
     83 int CodedInputStream::default_recursion_limit_ = 100;
     84 
     85 
     86 void CodedInputStream::BackUpInputToCurrentPosition() {
     87   int backup_bytes = BufferSize() + buffer_size_after_limit_ + overflow_bytes_;
     88   if (backup_bytes > 0) {
     89     input_->BackUp(backup_bytes);
     90 
     91     // total_bytes_read_ doesn't include overflow_bytes_.
     92     total_bytes_read_ -= BufferSize() + buffer_size_after_limit_;
     93     buffer_end_ = buffer_;
     94     buffer_size_after_limit_ = 0;
     95     overflow_bytes_ = 0;
     96   }
     97 }
     98 
     99 inline void CodedInputStream::RecomputeBufferLimits() {
    100   buffer_end_ += buffer_size_after_limit_;
    101   int closest_limit = min(current_limit_, total_bytes_limit_);
    102   if (closest_limit < total_bytes_read_) {
    103     // The limit position is in the current buffer.  We must adjust
    104     // the buffer size accordingly.
    105     buffer_size_after_limit_ = total_bytes_read_ - closest_limit;
    106     buffer_end_ -= buffer_size_after_limit_;
    107   } else {
    108     buffer_size_after_limit_ = 0;
    109   }
    110 }
    111 
    112 CodedInputStream::Limit CodedInputStream::PushLimit(int byte_limit) {
    113   // Current position relative to the beginning of the stream.
    114   int current_position = CurrentPosition();
    115 
    116   Limit old_limit = current_limit_;
    117 
    118   // security: byte_limit is possibly evil, so check for negative values
    119   // and overflow.
    120   if (byte_limit >= 0 &&
    121       byte_limit <= INT_MAX - current_position) {
    122     current_limit_ = current_position + byte_limit;
    123   } else {
    124     // Negative or overflow.
    125     current_limit_ = INT_MAX;
    126   }
    127 
    128   // We need to enforce all limits, not just the new one, so if the previous
    129   // limit was before the new requested limit, we continue to enforce the
    130   // previous limit.
    131   current_limit_ = min(current_limit_, old_limit);
    132 
    133   RecomputeBufferLimits();
    134   return old_limit;
    135 }
    136 
    137 void CodedInputStream::PopLimit(Limit limit) {
    138   // The limit passed in is actually the *old* limit, which we returned from
    139   // PushLimit().
    140   current_limit_ = limit;
    141   RecomputeBufferLimits();
    142 
    143   // We may no longer be at a legitimate message end.  ReadTag() needs to be
    144   // called again to find out.
    145   legitimate_message_end_ = false;
    146 }
    147 
    148 int CodedInputStream::BytesUntilLimit() const {
    149   if (current_limit_ == INT_MAX) return -1;
    150   int current_position = CurrentPosition();
    151 
    152   return current_limit_ - current_position;
    153 }
    154 
    155 void CodedInputStream::SetTotalBytesLimit(
    156     int total_bytes_limit, int warning_threshold) {
    157   // Make sure the limit isn't already past, since this could confuse other
    158   // code.
    159   int current_position = CurrentPosition();
    160   total_bytes_limit_ = max(current_position, total_bytes_limit);
    161   if (warning_threshold >= 0) {
    162     total_bytes_warning_threshold_ = warning_threshold;
    163   } else {
    164     // warning_threshold is negative
    165     total_bytes_warning_threshold_ = -1;
    166   }
    167   RecomputeBufferLimits();
    168 }
    169 
    170 void CodedInputStream::PrintTotalBytesLimitError() {
    171   GOOGLE_LOG(ERROR) << "A protocol message was rejected because it was too "
    172                 "big (more than " << total_bytes_limit_
    173              << " bytes).  To increase the limit (or to disable these "
    174                 "warnings), see CodedInputStream::SetTotalBytesLimit() "
    175                 "in google/protobuf/io/coded_stream.h.";
    176 }
    177 
    178 bool CodedInputStream::Skip(int count) {
    179   if (count < 0) return false;  // security: count is often user-supplied
    180 
    181   const int original_buffer_size = BufferSize();
    182 
    183   if (count <= original_buffer_size) {
    184     // Just skipping within the current buffer.  Easy.
    185     Advance(count);
    186     return true;
    187   }
    188 
    189   if (buffer_size_after_limit_ > 0) {
    190     // We hit a limit inside this buffer.  Advance to the limit and fail.
    191     Advance(original_buffer_size);
    192     return false;
    193   }
    194 
    195   count -= original_buffer_size;
    196   buffer_ = NULL;
    197   buffer_end_ = buffer_;
    198 
    199   // Make sure this skip doesn't try to skip past the current limit.
    200   int closest_limit = min(current_limit_, total_bytes_limit_);
    201   int bytes_until_limit = closest_limit - total_bytes_read_;
    202   if (bytes_until_limit < count) {
    203     // We hit the limit.  Skip up to it then fail.
    204     if (bytes_until_limit > 0) {
    205       total_bytes_read_ = closest_limit;
    206       input_->Skip(bytes_until_limit);
    207     }
    208     return false;
    209   }
    210 
    211   total_bytes_read_ += count;
    212   return input_->Skip(count);
    213 }
    214 
    215 bool CodedInputStream::GetDirectBufferPointer(const void** data, int* size) {
    216   if (BufferSize() == 0 && !Refresh()) return false;
    217 
    218   *data = buffer_;
    219   *size = BufferSize();
    220   return true;
    221 }
    222 
    223 bool CodedInputStream::ReadRaw(void* buffer, int size) {
    224   int current_buffer_size;
    225   while ((current_buffer_size = BufferSize()) < size) {
    226     // Reading past end of buffer.  Copy what we have, then refresh.
    227     memcpy(buffer, buffer_, current_buffer_size);
    228     buffer = reinterpret_cast<uint8*>(buffer) + current_buffer_size;
    229     size -= current_buffer_size;
    230     Advance(current_buffer_size);
    231     if (!Refresh()) return false;
    232   }
    233 
    234   memcpy(buffer, buffer_, size);
    235   Advance(size);
    236 
    237   return true;
    238 }
    239 
    240 bool CodedInputStream::ReadString(string* buffer, int size) {
    241   if (size < 0) return false;  // security: size is often user-supplied
    242   return InternalReadStringInline(buffer, size);
    243 }
    244 
    245 bool CodedInputStream::ReadStringFallback(string* buffer, int size) {
    246   if (!buffer->empty()) {
    247     buffer->clear();
    248   }
    249 
    250   int current_buffer_size;
    251   while ((current_buffer_size = BufferSize()) < size) {
    252     // Some STL implementations "helpfully" crash on buffer->append(NULL, 0).
    253     if (current_buffer_size != 0) {
    254       // Note:  string1.append(string2) is O(string2.size()) (as opposed to
    255       //   O(string1.size() + string2.size()), which would be bad).
    256       buffer->append(reinterpret_cast<const char*>(buffer_),
    257                      current_buffer_size);
    258     }
    259     size -= current_buffer_size;
    260     Advance(current_buffer_size);
    261     if (!Refresh()) return false;
    262   }
    263 
    264   buffer->append(reinterpret_cast<const char*>(buffer_), size);
    265   Advance(size);
    266 
    267   return true;
    268 }
    269 
    270 
    271 bool CodedInputStream::ReadLittleEndian32Fallback(uint32* value) {
    272   uint8 bytes[sizeof(*value)];
    273 
    274   const uint8* ptr;
    275   if (BufferSize() >= sizeof(*value)) {
    276     // Fast path:  Enough bytes in the buffer to read directly.
    277     ptr = buffer_;
    278     Advance(sizeof(*value));
    279   } else {
    280     // Slow path:  Had to read past the end of the buffer.
    281     if (!ReadRaw(bytes, sizeof(*value))) return false;
    282     ptr = bytes;
    283   }
    284   ReadLittleEndian32FromArray(ptr, value);
    285   return true;
    286 }
    287 
    288 bool CodedInputStream::ReadLittleEndian64Fallback(uint64* value) {
    289   uint8 bytes[sizeof(*value)];
    290 
    291   const uint8* ptr;
    292   if (BufferSize() >= sizeof(*value)) {
    293     // Fast path:  Enough bytes in the buffer to read directly.
    294     ptr = buffer_;
    295     Advance(sizeof(*value));
    296   } else {
    297     // Slow path:  Had to read past the end of the buffer.
    298     if (!ReadRaw(bytes, sizeof(*value))) return false;
    299     ptr = bytes;
    300   }
    301   ReadLittleEndian64FromArray(ptr, value);
    302   return true;
    303 }
    304 
    305 namespace {
    306 
    307 inline const uint8* ReadVarint32FromArray(
    308     const uint8* buffer, uint32* value) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
    309 inline const uint8* ReadVarint32FromArray(const uint8* buffer, uint32* value) {
    310   // Fast path:  We have enough bytes left in the buffer to guarantee that
    311   // this read won't cross the end, so we can skip the checks.
    312   const uint8* ptr = buffer;
    313   uint32 b;
    314   uint32 result;
    315 
    316   b = *(ptr++); result  = (b & 0x7F)      ; if (!(b & 0x80)) goto done;
    317   b = *(ptr++); result |= (b & 0x7F) <<  7; if (!(b & 0x80)) goto done;
    318   b = *(ptr++); result |= (b & 0x7F) << 14; if (!(b & 0x80)) goto done;
    319   b = *(ptr++); result |= (b & 0x7F) << 21; if (!(b & 0x80)) goto done;
    320   b = *(ptr++); result |=  b         << 28; if (!(b & 0x80)) goto done;
    321 
    322   // If the input is larger than 32 bits, we still need to read it all
    323   // and discard the high-order bits.
    324   for (int i = 0; i < kMaxVarintBytes - kMaxVarint32Bytes; i++) {
    325     b = *(ptr++); if (!(b & 0x80)) goto done;
    326   }
    327 
    328   // We have overrun the maximum size of a varint (10 bytes).  Assume
    329   // the data is corrupt.
    330   return NULL;
    331 
    332  done:
    333   *value = result;
    334   return ptr;
    335 }
    336 
    337 }  // namespace
    338 
    339 bool CodedInputStream::ReadVarint32Slow(uint32* value) {
    340   uint64 result;
    341   // Directly invoke ReadVarint64Fallback, since we already tried to optimize
    342   // for one-byte varints.
    343   if (!ReadVarint64Fallback(&result)) return false;
    344   *value = (uint32)result;
    345   return true;
    346 }
    347 
    348 bool CodedInputStream::ReadVarint32Fallback(uint32* value) {
    349   if (BufferSize() >= kMaxVarintBytes ||
    350       // Optimization:  If the varint ends at exactly the end of the buffer,
    351       // we can detect that and still use the fast path.
    352       (buffer_end_ > buffer_ && !(buffer_end_[-1] & 0x80))) {
    353     const uint8* end = ReadVarint32FromArray(buffer_, value);
    354     if (end == NULL) return false;
    355     buffer_ = end;
    356     return true;
    357   } else {
    358     // Really slow case: we will incur the cost of an extra function call here,
    359     // but moving this out of line reduces the size of this function, which
    360     // improves the common case. In micro benchmarks, this is worth about 10-15%
    361     return ReadVarint32Slow(value);
    362   }
    363 }
    364 
    365 uint32 CodedInputStream::ReadTagSlow() {
    366   if (buffer_ == buffer_end_) {
    367     // Call refresh.
    368     if (!Refresh()) {
    369       // Refresh failed.  Make sure that it failed due to EOF, not because
    370       // we hit total_bytes_limit_, which, unlike normal limits, is not a
    371       // valid place to end a message.
    372       int current_position = total_bytes_read_ - buffer_size_after_limit_;
    373       if (current_position >= total_bytes_limit_) {
    374         // Hit total_bytes_limit_.  But if we also hit the normal limit,
    375         // we're still OK.
    376         legitimate_message_end_ = current_limit_ == total_bytes_limit_;
    377       } else {
    378         legitimate_message_end_ = true;
    379       }
    380       return 0;
    381     }
    382   }
    383 
    384   // For the slow path, just do a 64-bit read. Try to optimize for one-byte tags
    385   // again, since we have now refreshed the buffer.
    386   uint64 result = 0;
    387   if (!ReadVarint64(&result)) return 0;
    388   return static_cast<uint32>(result);
    389 }
    390 
    391 uint32 CodedInputStream::ReadTagFallback() {
    392   const int buf_size = BufferSize();
    393   if (buf_size >= kMaxVarintBytes ||
    394       // Optimization:  If the varint ends at exactly the end of the buffer,
    395       // we can detect that and still use the fast path.
    396       (buf_size > 0 && !(buffer_end_[-1] & 0x80))) {
    397     uint32 tag;
    398     const uint8* end = ReadVarint32FromArray(buffer_, &tag);
    399     if (end == NULL) {
    400       return 0;
    401     }
    402     buffer_ = end;
    403     return tag;
    404   } else {
    405     // We are commonly at a limit when attempting to read tags. Try to quickly
    406     // detect this case without making another function call.
    407     if ((buf_size == 0) &&
    408         ((buffer_size_after_limit_ > 0) ||
    409          (total_bytes_read_ == current_limit_)) &&
    410         // Make sure that the limit we hit is not total_bytes_limit_, since
    411         // in that case we still need to call Refresh() so that it prints an
    412         // error.
    413         total_bytes_read_ - buffer_size_after_limit_ < total_bytes_limit_) {
    414       // We hit a byte limit.
    415       legitimate_message_end_ = true;
    416       return 0;
    417     }
    418     return ReadTagSlow();
    419   }
    420 }
    421 
    422 bool CodedInputStream::ReadVarint64Slow(uint64* value) {
    423   // Slow path:  This read might cross the end of the buffer, so we
    424   // need to check and refresh the buffer if and when it does.
    425 
    426   uint64 result = 0;
    427   int count = 0;
    428   uint32 b;
    429 
    430   do {
    431     if (count == kMaxVarintBytes) return false;
    432     while (buffer_ == buffer_end_) {
    433       if (!Refresh()) return false;
    434     }
    435     b = *buffer_;
    436     result |= static_cast<uint64>(b & 0x7F) << (7 * count);
    437     Advance(1);
    438     ++count;
    439   } while (b & 0x80);
    440 
    441   *value = result;
    442   return true;
    443 }
    444 
    445 bool CodedInputStream::ReadVarint64Fallback(uint64* value) {
    446   if (BufferSize() >= kMaxVarintBytes ||
    447       // Optimization:  If the varint ends at exactly the end of the buffer,
    448       // we can detect that and still use the fast path.
    449       (buffer_end_ > buffer_ && !(buffer_end_[-1] & 0x80))) {
    450     // Fast path:  We have enough bytes left in the buffer to guarantee that
    451     // this read won't cross the end, so we can skip the checks.
    452 
    453     const uint8* ptr = buffer_;
    454     uint32 b;
    455 
    456     // Splitting into 32-bit pieces gives better performance on 32-bit
    457     // processors.
    458     uint32 part0 = 0, part1 = 0, part2 = 0;
    459 
    460     b = *(ptr++); part0  = (b & 0x7F)      ; if (!(b & 0x80)) goto done;
    461     b = *(ptr++); part0 |= (b & 0x7F) <<  7; if (!(b & 0x80)) goto done;
    462     b = *(ptr++); part0 |= (b & 0x7F) << 14; if (!(b & 0x80)) goto done;
    463     b = *(ptr++); part0 |= (b & 0x7F) << 21; if (!(b & 0x80)) goto done;
    464     b = *(ptr++); part1  = (b & 0x7F)      ; if (!(b & 0x80)) goto done;
    465     b = *(ptr++); part1 |= (b & 0x7F) <<  7; if (!(b & 0x80)) goto done;
    466     b = *(ptr++); part1 |= (b & 0x7F) << 14; if (!(b & 0x80)) goto done;
    467     b = *(ptr++); part1 |= (b & 0x7F) << 21; if (!(b & 0x80)) goto done;
    468     b = *(ptr++); part2  = (b & 0x7F)      ; if (!(b & 0x80)) goto done;
    469     b = *(ptr++); part2 |= (b & 0x7F) <<  7; if (!(b & 0x80)) goto done;
    470 
    471     // We have overrun the maximum size of a varint (10 bytes).  The data
    472     // must be corrupt.
    473     return false;
    474 
    475    done:
    476     Advance(ptr - buffer_);
    477     *value = (static_cast<uint64>(part0)      ) |
    478              (static_cast<uint64>(part1) << 28) |
    479              (static_cast<uint64>(part2) << 56);
    480     return true;
    481   } else {
    482     return ReadVarint64Slow(value);
    483   }
    484 }
    485 
    486 bool CodedInputStream::Refresh() {
    487   GOOGLE_DCHECK_EQ(0, BufferSize());
    488 
    489   if (buffer_size_after_limit_ > 0 || overflow_bytes_ > 0 ||
    490       total_bytes_read_ == current_limit_) {
    491     // We've hit a limit.  Stop.
    492     int current_position = total_bytes_read_ - buffer_size_after_limit_;
    493 
    494     if (current_position >= total_bytes_limit_ &&
    495         total_bytes_limit_ != current_limit_) {
    496       // Hit total_bytes_limit_.
    497       PrintTotalBytesLimitError();
    498     }
    499 
    500     return false;
    501   }
    502 
    503   if (total_bytes_warning_threshold_ >= 0 &&
    504       total_bytes_read_ >= total_bytes_warning_threshold_) {
    505       GOOGLE_LOG(WARNING) << "Reading dangerously large protocol message.  If the "
    506                       "message turns out to be larger than "
    507                    << total_bytes_limit_ << " bytes, parsing will be halted "
    508                       "for security reasons.  To increase the limit (or to "
    509                       "disable these warnings), see "
    510                       "CodedInputStream::SetTotalBytesLimit() in "
    511                       "google/protobuf/io/coded_stream.h.";
    512 
    513     // Don't warn again for this stream, and print total size at the end.
    514     total_bytes_warning_threshold_ = -2;
    515   }
    516 
    517   const void* void_buffer;
    518   int buffer_size;
    519   if (NextNonEmpty(input_, &void_buffer, &buffer_size)) {
    520     buffer_ = reinterpret_cast<const uint8*>(void_buffer);
    521     buffer_end_ = buffer_ + buffer_size;
    522     GOOGLE_CHECK_GE(buffer_size, 0);
    523 
    524     if (total_bytes_read_ <= INT_MAX - buffer_size) {
    525       total_bytes_read_ += buffer_size;
    526     } else {
    527       // Overflow.  Reset buffer_end_ to not include the bytes beyond INT_MAX.
    528       // We can't get that far anyway, because total_bytes_limit_ is guaranteed
    529       // to be less than it.  We need to keep track of the number of bytes
    530       // we discarded, though, so that we can call input_->BackUp() to back
    531       // up over them on destruction.
    532 
    533       // The following line is equivalent to:
    534       //   overflow_bytes_ = total_bytes_read_ + buffer_size - INT_MAX;
    535       // except that it avoids overflows.  Signed integer overflow has
    536       // undefined results according to the C standard.
    537       overflow_bytes_ = total_bytes_read_ - (INT_MAX - buffer_size);
    538       buffer_end_ -= overflow_bytes_;
    539       total_bytes_read_ = INT_MAX;
    540     }
    541 
    542     RecomputeBufferLimits();
    543     return true;
    544   } else {
    545     buffer_ = NULL;
    546     buffer_end_ = NULL;
    547     return false;
    548   }
    549 }
    550 
    551 // CodedOutputStream =================================================
    552 
    553 CodedOutputStream::CodedOutputStream(ZeroCopyOutputStream* output)
    554   : output_(output),
    555     buffer_(NULL),
    556     buffer_size_(0),
    557     total_bytes_(0),
    558     had_error_(false) {
    559   // Eagerly Refresh() so buffer space is immediately available.
    560   Refresh();
    561   // The Refresh() may have failed. If the client doesn't write any data,
    562   // though, don't consider this an error. If the client does write data, then
    563   // another Refresh() will be attempted and it will set the error once again.
    564   had_error_ = false;
    565 }
    566 
    567 CodedOutputStream::~CodedOutputStream() {
    568   if (buffer_size_ > 0) {
    569     output_->BackUp(buffer_size_);
    570   }
    571 }
    572 
    573 bool CodedOutputStream::Skip(int count) {
    574   if (count < 0) return false;
    575 
    576   while (count > buffer_size_) {
    577     count -= buffer_size_;
    578     if (!Refresh()) return false;
    579   }
    580 
    581   Advance(count);
    582   return true;
    583 }
    584 
    585 bool CodedOutputStream::GetDirectBufferPointer(void** data, int* size) {
    586   if (buffer_size_ == 0 && !Refresh()) return false;
    587 
    588   *data = buffer_;
    589   *size = buffer_size_;
    590   return true;
    591 }
    592 
    593 void CodedOutputStream::WriteRaw(const void* data, int size) {
    594   while (buffer_size_ < size) {
    595     memcpy(buffer_, data, buffer_size_);
    596     size -= buffer_size_;
    597     data = reinterpret_cast<const uint8*>(data) + buffer_size_;
    598     if (!Refresh()) return;
    599   }
    600 
    601   memcpy(buffer_, data, size);
    602   Advance(size);
    603 }
    604 
    605 uint8* CodedOutputStream::WriteRawToArray(
    606     const void* data, int size, uint8* target) {
    607   memcpy(target, data, size);
    608   return target + size;
    609 }
    610 
    611 
    612 void CodedOutputStream::WriteLittleEndian32(uint32 value) {
    613   uint8 bytes[sizeof(value)];
    614 
    615   bool use_fast = buffer_size_ >= sizeof(value);
    616   uint8* ptr = use_fast ? buffer_ : bytes;
    617 
    618   WriteLittleEndian32ToArray(value, ptr);
    619 
    620   if (use_fast) {
    621     Advance(sizeof(value));
    622   } else {
    623     WriteRaw(bytes, sizeof(value));
    624   }
    625 }
    626 
    627 void CodedOutputStream::WriteLittleEndian64(uint64 value) {
    628   uint8 bytes[sizeof(value)];
    629 
    630   bool use_fast = buffer_size_ >= sizeof(value);
    631   uint8* ptr = use_fast ? buffer_ : bytes;
    632 
    633   WriteLittleEndian64ToArray(value, ptr);
    634 
    635   if (use_fast) {
    636     Advance(sizeof(value));
    637   } else {
    638     WriteRaw(bytes, sizeof(value));
    639   }
    640 }
    641 
    642 inline uint8* CodedOutputStream::WriteVarint32FallbackToArrayInline(
    643     uint32 value, uint8* target) {
    644   target[0] = static_cast<uint8>(value | 0x80);
    645   if (value >= (1 << 7)) {
    646     target[1] = static_cast<uint8>((value >>  7) | 0x80);
    647     if (value >= (1 << 14)) {
    648       target[2] = static_cast<uint8>((value >> 14) | 0x80);
    649       if (value >= (1 << 21)) {
    650         target[3] = static_cast<uint8>((value >> 21) | 0x80);
    651         if (value >= (1 << 28)) {
    652           target[4] = static_cast<uint8>(value >> 28);
    653           return target + 5;
    654         } else {
    655           target[3] &= 0x7F;
    656           return target + 4;
    657         }
    658       } else {
    659         target[2] &= 0x7F;
    660         return target + 3;
    661       }
    662     } else {
    663       target[1] &= 0x7F;
    664       return target + 2;
    665     }
    666   } else {
    667     target[0] &= 0x7F;
    668     return target + 1;
    669   }
    670 }
    671 
    672 void CodedOutputStream::WriteVarint32(uint32 value) {
    673   if (buffer_size_ >= kMaxVarint32Bytes) {
    674     // Fast path:  We have enough bytes left in the buffer to guarantee that
    675     // this write won't cross the end, so we can skip the checks.
    676     uint8* target = buffer_;
    677     uint8* end = WriteVarint32FallbackToArrayInline(value, target);
    678     int size = end - target;
    679     Advance(size);
    680   } else {
    681     // Slow path:  This write might cross the end of the buffer, so we
    682     // compose the bytes first then use WriteRaw().
    683     uint8 bytes[kMaxVarint32Bytes];
    684     int size = 0;
    685     while (value > 0x7F) {
    686       bytes[size++] = (static_cast<uint8>(value) & 0x7F) | 0x80;
    687       value >>= 7;
    688     }
    689     bytes[size++] = static_cast<uint8>(value) & 0x7F;
    690     WriteRaw(bytes, size);
    691   }
    692 }
    693 
    694 uint8* CodedOutputStream::WriteVarint32FallbackToArray(
    695     uint32 value, uint8* target) {
    696   return WriteVarint32FallbackToArrayInline(value, target);
    697 }
    698 
    699 inline uint8* CodedOutputStream::WriteVarint64ToArrayInline(
    700     uint64 value, uint8* target) {
    701   // Splitting into 32-bit pieces gives better performance on 32-bit
    702   // processors.
    703   uint32 part0 = static_cast<uint32>(value      );
    704   uint32 part1 = static_cast<uint32>(value >> 28);
    705   uint32 part2 = static_cast<uint32>(value >> 56);
    706 
    707   int size;
    708 
    709   // Here we can't really optimize for small numbers, since the value is
    710   // split into three parts.  Cheking for numbers < 128, for instance,
    711   // would require three comparisons, since you'd have to make sure part1
    712   // and part2 are zero.  However, if the caller is using 64-bit integers,
    713   // it is likely that they expect the numbers to often be very large, so
    714   // we probably don't want to optimize for small numbers anyway.  Thus,
    715   // we end up with a hardcoded binary search tree...
    716   if (part2 == 0) {
    717     if (part1 == 0) {
    718       if (part0 < (1 << 14)) {
    719         if (part0 < (1 << 7)) {
    720           size = 1; goto size1;
    721         } else {
    722           size = 2; goto size2;
    723         }
    724       } else {
    725         if (part0 < (1 << 21)) {
    726           size = 3; goto size3;
    727         } else {
    728           size = 4; goto size4;
    729         }
    730       }
    731     } else {
    732       if (part1 < (1 << 14)) {
    733         if (part1 < (1 << 7)) {
    734           size = 5; goto size5;
    735         } else {
    736           size = 6; goto size6;
    737         }
    738       } else {
    739         if (part1 < (1 << 21)) {
    740           size = 7; goto size7;
    741         } else {
    742           size = 8; goto size8;
    743         }
    744       }
    745     }
    746   } else {
    747     if (part2 < (1 << 7)) {
    748       size = 9; goto size9;
    749     } else {
    750       size = 10; goto size10;
    751     }
    752   }
    753 
    754   GOOGLE_LOG(FATAL) << "Can't get here.";
    755 
    756   size10: target[9] = static_cast<uint8>((part2 >>  7) | 0x80);
    757   size9 : target[8] = static_cast<uint8>((part2      ) | 0x80);
    758   size8 : target[7] = static_cast<uint8>((part1 >> 21) | 0x80);
    759   size7 : target[6] = static_cast<uint8>((part1 >> 14) | 0x80);
    760   size6 : target[5] = static_cast<uint8>((part1 >>  7) | 0x80);
    761   size5 : target[4] = static_cast<uint8>((part1      ) | 0x80);
    762   size4 : target[3] = static_cast<uint8>((part0 >> 21) | 0x80);
    763   size3 : target[2] = static_cast<uint8>((part0 >> 14) | 0x80);
    764   size2 : target[1] = static_cast<uint8>((part0 >>  7) | 0x80);
    765   size1 : target[0] = static_cast<uint8>((part0      ) | 0x80);
    766 
    767   target[size-1] &= 0x7F;
    768   return target + size;
    769 }
    770 
    771 void CodedOutputStream::WriteVarint64(uint64 value) {
    772   if (buffer_size_ >= kMaxVarintBytes) {
    773     // Fast path:  We have enough bytes left in the buffer to guarantee that
    774     // this write won't cross the end, so we can skip the checks.
    775     uint8* target = buffer_;
    776 
    777     uint8* end = WriteVarint64ToArrayInline(value, target);
    778     int size = end - target;
    779     Advance(size);
    780   } else {
    781     // Slow path:  This write might cross the end of the buffer, so we
    782     // compose the bytes first then use WriteRaw().
    783     uint8 bytes[kMaxVarintBytes];
    784     int size = 0;
    785     while (value > 0x7F) {
    786       bytes[size++] = (static_cast<uint8>(value) & 0x7F) | 0x80;
    787       value >>= 7;
    788     }
    789     bytes[size++] = static_cast<uint8>(value) & 0x7F;
    790     WriteRaw(bytes, size);
    791   }
    792 }
    793 
    794 uint8* CodedOutputStream::WriteVarint64ToArray(
    795     uint64 value, uint8* target) {
    796   return WriteVarint64ToArrayInline(value, target);
    797 }
    798 
    799 bool CodedOutputStream::Refresh() {
    800   void* void_buffer;
    801   if (output_->Next(&void_buffer, &buffer_size_)) {
    802     buffer_ = reinterpret_cast<uint8*>(void_buffer);
    803     total_bytes_ += buffer_size_;
    804     return true;
    805   } else {
    806     buffer_ = NULL;
    807     buffer_size_ = 0;
    808     had_error_ = true;
    809     return false;
    810   }
    811 }
    812 
    813 int CodedOutputStream::VarintSize32Fallback(uint32 value) {
    814   if (value < (1 << 7)) {
    815     return 1;
    816   } else if (value < (1 << 14)) {
    817     return 2;
    818   } else if (value < (1 << 21)) {
    819     return 3;
    820   } else if (value < (1 << 28)) {
    821     return 4;
    822   } else {
    823     return 5;
    824   }
    825 }
    826 
    827 int CodedOutputStream::VarintSize64(uint64 value) {
    828   if (value < (1ull << 35)) {
    829     if (value < (1ull << 7)) {
    830       return 1;
    831     } else if (value < (1ull << 14)) {
    832       return 2;
    833     } else if (value < (1ull << 21)) {
    834       return 3;
    835     } else if (value < (1ull << 28)) {
    836       return 4;
    837     } else {
    838       return 5;
    839     }
    840   } else {
    841     if (value < (1ull << 42)) {
    842       return 6;
    843     } else if (value < (1ull << 49)) {
    844       return 7;
    845     } else if (value < (1ull << 56)) {
    846       return 8;
    847     } else if (value < (1ull << 63)) {
    848       return 9;
    849     } else {
    850       return 10;
    851     }
    852   }
    853 }
    854 
    855 }  // namespace io
    856 }  // namespace protobuf
    857 }  // namespace google
    858