coded_stream.cc revision fbaaef999ba563838ebd00874ed8a1c01fbf286d
16f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// Protocol Buffers - Google's data interchange format 26f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// Copyright 2008 Google Inc. All rights reserved. 36f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// http://code.google.com/p/protobuf/ 46f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// 56f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// Redistribution and use in source and binary forms, with or without 66f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// modification, are permitted provided that the following conditions are 76f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// met: 86f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// 96f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// * Redistributions of source code must retain the above copyright 106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// notice, this list of conditions and the following disclaimer. 116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// * Redistributions in binary form must reproduce the above 126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// copyright notice, this list of conditions and the following disclaimer 136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// in the documentation and/or other materials provided with the 146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// distribution. 156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// * Neither the name of Google Inc. nor the names of its 166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// contributors may be used to endorse or promote products derived from 176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// this software without specific prior written permission. 186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// 196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// Author: kenton@google.com (Kenton Varda) 326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// Based on original Protocol Buffers design by 336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// Sanjay Ghemawat, Jeff Dean, and others. 346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// 356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// This implementation is heavily optimized to make reads and writes 366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// of small values (especially varints) as fast as possible. In 376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// particular, we optimize for the common case that a read or a write 386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// will not cross the end of the buffer, since we can avoid a lot 396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// of branching in this case. 406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include <stack> 426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include <limits.h> 436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include <google/protobuf/io/coded_stream.h> 446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include <google/protobuf/io/zero_copy_stream.h> 456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include <google/protobuf/stubs/common.h> 466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include <google/protobuf/stubs/stl_util-inl.h> 476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgnamespace google { 506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgnamespace protobuf { 516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgnamespace io { 526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgnamespace { 546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const int kDefaultTotalBytesLimit = 64 << 20; // 64MB 566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const int kDefaultTotalBytesWarningThreshold = 32 << 20; // 32MB 586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const int kDefaultRecursionLimit = 64; 596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const int kMaxVarintBytes = 10; 616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const int kMaxVarint32Bytes = 5; 626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org} // namespace 656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// CodedInputStream ================================================== 676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgCodedInputStream::CodedInputStream(ZeroCopyInputStream* input) 696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org : input_(input), 706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org buffer_(NULL), 716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org buffer_size_(0), 726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org total_bytes_read_(0), 736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org overflow_bytes_(0), 746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org last_tag_(0), 756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org legitimate_message_end_(false), 766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org aliasing_enabled_(false), 776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org current_limit_(INT_MAX), 786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org buffer_size_after_limit_(0), 796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org total_bytes_limit_(kDefaultTotalBytesLimit), 806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org total_bytes_warning_threshold_(kDefaultTotalBytesWarningThreshold), 816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org recursion_depth_(0), 826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org recursion_limit_(kDefaultRecursionLimit) { 836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org // Eagerly Refresh() so buffer space is immediately available. 846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org Refresh(); 856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org} 866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgCodedInputStream::CodedInputStream(const uint8* buffer, int size) 886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org : input_(NULL), 896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org buffer_(buffer), 906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org buffer_size_(size), 916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org total_bytes_read_(size), 926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org overflow_bytes_(0), 936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org last_tag_(0), 946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org legitimate_message_end_(false), 956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org aliasing_enabled_(false), 966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org current_limit_(size), 976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org buffer_size_after_limit_(0), 986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org total_bytes_limit_(kDefaultTotalBytesLimit), 996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org total_bytes_warning_threshold_(kDefaultTotalBytesWarningThreshold), 1006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org recursion_depth_(0), 1016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org recursion_limit_(kDefaultRecursionLimit) { 1026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org // Note that setting current_limit_ == size is important to prevent some 1036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org // code paths from trying to access input_ and segfaulting. 1046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org} 1056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 1066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgCodedInputStream::~CodedInputStream() { 1076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org if (input_ != NULL) { 1086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org BackUpInputToCurrentPosition(); 1096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } 1106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org} 1116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 1126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 1136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgvoid CodedInputStream::BackUpInputToCurrentPosition() { 1146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org int backup_bytes = buffer_size_ + buffer_size_after_limit_ + overflow_bytes_; 1156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org if (backup_bytes > 0) { 1166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org input_->BackUp(backup_bytes); 1176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 1186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org // total_bytes_read_ doesn't include overflow_bytes_. 1196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org total_bytes_read_ -= buffer_size_ + buffer_size_after_limit_; 1206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org buffer_size_ = 0; 1216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org buffer_size_after_limit_ = 0; 1226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org overflow_bytes_ = 0; 1236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } 1246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org} 1256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 1266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orginline void CodedInputStream::RecomputeBufferLimits() { 1276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org buffer_size_ += buffer_size_after_limit_; 1286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org int closest_limit = min(current_limit_, total_bytes_limit_); 1296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org if (closest_limit < total_bytes_read_) { 1306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org // The limit position is in the current buffer. We must adjust 1316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org // the buffer size accordingly. 1326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org buffer_size_after_limit_ = total_bytes_read_ - closest_limit; 1336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org buffer_size_ -= buffer_size_after_limit_; 1346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } else { 1356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org buffer_size_after_limit_ = 0; 1366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } 1376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org} 1386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 1396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgCodedInputStream::Limit CodedInputStream::PushLimit(int byte_limit) { 1406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org // Current position relative to the beginning of the stream. 1416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org int current_position = total_bytes_read_ - 1426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org (buffer_size_ + buffer_size_after_limit_); 1436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 1446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org Limit old_limit = current_limit_; 1456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 1466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org // security: byte_limit is possibly evil, so check for negative values 1476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org // and overflow. 1486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org if (byte_limit >= 0 && 1496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org byte_limit <= INT_MAX - current_position) { 1506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org current_limit_ = current_position + byte_limit; 1516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } else { 1526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org // Negative or overflow. 1536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org current_limit_ = INT_MAX; 1546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } 1556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 1566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org // We need to enforce all limits, not just the new one, so if the previous 1576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org // limit was before the new requested limit, we continue to enforce the 1586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org // previous limit. 1596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org current_limit_ = min(current_limit_, old_limit); 1606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 1616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org RecomputeBufferLimits(); 1626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org return old_limit; 1636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org} 1646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 1656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgvoid CodedInputStream::PopLimit(Limit limit) { 1666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org // The limit passed in is actually the *old* limit, which we returned from 1676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org // PushLimit(). 1686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org current_limit_ = limit; 1696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org RecomputeBufferLimits(); 1706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 1716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org // We may no longer be at a legitimate message end. ReadTag() needs to be 1726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org // called again to find out. 1736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org legitimate_message_end_ = false; 1746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org} 1756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 1766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgint CodedInputStream::BytesUntilLimit() { 1776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org if (current_limit_ == INT_MAX) return -1; 1786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org int current_position = total_bytes_read_ - 1796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org (buffer_size_ + buffer_size_after_limit_); 1806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 1816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org return current_limit_ - current_position; 1826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org} 1836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 1846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgvoid CodedInputStream::SetTotalBytesLimit( 1856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org int total_bytes_limit, int warning_threshold) { 1866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org // Make sure the limit isn't already past, since this could confuse other 1876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org // code. 1886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org int current_position = total_bytes_read_ - 1896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org (buffer_size_ + buffer_size_after_limit_); 1906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org total_bytes_limit_ = max(current_position, total_bytes_limit); 1916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org total_bytes_warning_threshold_ = warning_threshold; 1926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org RecomputeBufferLimits(); 1936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org} 1946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 1956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgvoid CodedInputStream::PrintTotalBytesLimitError() { 1966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org GOOGLE_LOG(ERROR) << "A protocol message was rejected because it was too " 1976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org "big (more than " << total_bytes_limit_ 1986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org << " bytes). To increase the limit (or to disable these " 1996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org "warnings), see CodedInputStream::SetTotalBytesLimit() " 2006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org "in google/protobuf/io/coded_stream.h."; 2016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org} 2026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 2036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgbool CodedInputStream::Skip(int count) { 2046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org if (count < 0) return false; // security: count is often user-supplied 2056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 2066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org if (count <= buffer_size_) { 2076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org // Just skipping within the current buffer. Easy. 2086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org Advance(count); 2096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org return true; 210 } 211 212 if (buffer_size_after_limit_ > 0) { 213 // We hit a limit inside this buffer. Advance to the limit and fail. 214 Advance(buffer_size_); 215 return false; 216 } 217 218 count -= buffer_size_; 219 buffer_ = NULL; 220 buffer_size_ = 0; 221 222 // Make sure this skip doesn't try to skip past the current limit. 223 int closest_limit = min(current_limit_, total_bytes_limit_); 224 int bytes_until_limit = closest_limit - total_bytes_read_; 225 if (bytes_until_limit < count) { 226 // We hit the limit. Skip up to it then fail. 227 if (bytes_until_limit > 0) { 228 total_bytes_read_ = closest_limit; 229 input_->Skip(bytes_until_limit); 230 } 231 return false; 232 } 233 234 total_bytes_read_ += count; 235 return input_->Skip(count); 236} 237 238bool CodedInputStream::GetDirectBufferPointer(const void** data, int* size) { 239 if (buffer_size_ == 0 && !Refresh()) return false; 240 241 *data = buffer_; 242 *size = buffer_size_; 243 return true; 244} 245 246bool CodedInputStream::ReadRaw(void* buffer, int size) { 247 while (buffer_size_ < size) { 248 // Reading past end of buffer. Copy what we have, then refresh. 249 memcpy(buffer, buffer_, buffer_size_); 250 buffer = reinterpret_cast<uint8*>(buffer) + buffer_size_; 251 size -= buffer_size_; 252 Advance(buffer_size_); 253 if (!Refresh()) return false; 254 } 255 256 memcpy(buffer, buffer_, size); 257 Advance(size); 258 259 return true; 260} 261 262bool CodedInputStream::ReadString(string* buffer, int size) { 263 if (size < 0) return false; // security: size is often user-supplied 264 265 if (!buffer->empty()) { 266 buffer->clear(); 267 } 268 269 if (size < buffer_size_) { 270 STLStringResizeUninitialized(buffer, size); 271 memcpy((uint8*)buffer->data(), buffer_, size); 272 Advance(size); 273 return true; 274 } 275 276 while (buffer_size_ < size) { 277 // Some STL implementations "helpfully" crash on buffer->append(NULL, 0). 278 if (buffer_size_ != 0) { 279 // Note: string1.append(string2) is O(string2.size()) (as opposed to 280 // O(string1.size() + string2.size()), which would be bad). 281 buffer->append(reinterpret_cast<const char*>(buffer_), buffer_size_); 282 } 283 size -= buffer_size_; 284 Advance(buffer_size_); 285 if (!Refresh()) return false; 286 } 287 288 buffer->append(reinterpret_cast<const char*>(buffer_), size); 289 Advance(size); 290 291 return true; 292} 293 294 295bool CodedInputStream::ReadLittleEndian32(uint32* value) { 296 uint8 bytes[sizeof(*value)]; 297 298 const uint8* ptr; 299 if (buffer_size_ >= sizeof(*value)) { 300 // Fast path: Enough bytes in the buffer to read directly. 301 ptr = buffer_; 302 Advance(sizeof(*value)); 303 } else { 304 // Slow path: Had to read past the end of the buffer. 305 if (!ReadRaw(bytes, sizeof(*value))) return false; 306 ptr = bytes; 307 } 308 309 *value = (static_cast<uint32>(ptr[0]) ) | 310 (static_cast<uint32>(ptr[1]) << 8) | 311 (static_cast<uint32>(ptr[2]) << 16) | 312 (static_cast<uint32>(ptr[3]) << 24); 313 return true; 314} 315 316bool CodedInputStream::ReadLittleEndian64(uint64* value) { 317 uint8 bytes[sizeof(*value)]; 318 319 const uint8* ptr; 320 if (buffer_size_ >= sizeof(*value)) { 321 // Fast path: Enough bytes in the buffer to read directly. 322 ptr = buffer_; 323 Advance(sizeof(*value)); 324 } else { 325 // Slow path: Had to read past the end of the buffer. 326 if (!ReadRaw(bytes, sizeof(*value))) return false; 327 ptr = bytes; 328 } 329 330 uint32 part0 = (static_cast<uint32>(ptr[0]) ) | 331 (static_cast<uint32>(ptr[1]) << 8) | 332 (static_cast<uint32>(ptr[2]) << 16) | 333 (static_cast<uint32>(ptr[3]) << 24); 334 uint32 part1 = (static_cast<uint32>(ptr[4]) ) | 335 (static_cast<uint32>(ptr[5]) << 8) | 336 (static_cast<uint32>(ptr[6]) << 16) | 337 (static_cast<uint32>(ptr[7]) << 24); 338 *value = static_cast<uint64>(part0) | 339 (static_cast<uint64>(part1) << 32); 340 return true; 341} 342 343bool CodedInputStream::ReadVarint32Fallback(uint32* value) { 344 if (buffer_size_ >= kMaxVarintBytes || 345 // Optimization: If the varint ends at exactly the end of the buffer, 346 // we can detect that and still use the fast path. 347 (buffer_size_ != 0 && !(buffer_[buffer_size_-1] & 0x80))) { 348 // Fast path: We have enough bytes left in the buffer to guarantee that 349 // this read won't cross the end, so we can skip the checks. 350 const uint8* ptr = buffer_; 351 uint32 b; 352 uint32 result; 353 354 b = *(ptr++); result = (b & 0x7F) ; if (!(b & 0x80)) goto done; 355 b = *(ptr++); result |= (b & 0x7F) << 7; if (!(b & 0x80)) goto done; 356 b = *(ptr++); result |= (b & 0x7F) << 14; if (!(b & 0x80)) goto done; 357 b = *(ptr++); result |= (b & 0x7F) << 21; if (!(b & 0x80)) goto done; 358 b = *(ptr++); result |= b << 28; if (!(b & 0x80)) goto done; 359 360 // If the input is larger than 32 bits, we still need to read it all 361 // and discard the high-order bits. 362 for (int i = 0; i < kMaxVarintBytes - kMaxVarint32Bytes; i++) { 363 b = *(ptr++); if (!(b & 0x80)) goto done; 364 } 365 366 // We have overrun the maximum size of a varint (10 bytes). Assume 367 // the data is corrupt. 368 return false; 369 370 done: 371 Advance(ptr - buffer_); 372 *value = result; 373 return true; 374 375 } else { 376 // Optimization: If we're at a limit, detect that quickly. (This is 377 // common when reading tags.) 378 while (buffer_size_ == 0) { 379 // Detect cases where we definitely hit a byte limit without calling 380 // Refresh(). 381 if (// If we hit a limit, buffer_size_after_limit_ will be non-zero. 382 buffer_size_after_limit_ > 0 && 383 // Make sure that the limit we hit is not total_bytes_limit_, since 384 // in that case we still need to call Refresh() so that it prints an 385 // error. 386 total_bytes_read_ - buffer_size_after_limit_ < total_bytes_limit_) { 387 // We hit a byte limit. 388 legitimate_message_end_ = true; 389 return false; 390 } 391 392 // Call refresh. 393 if (!Refresh()) { 394 // Refresh failed. Make sure that it failed due to EOF, not because 395 // we hit total_bytes_limit_, which, unlike normal limits, is not a 396 // valid place to end a message. 397 int current_position = total_bytes_read_ - buffer_size_after_limit_; 398 if (current_position >= total_bytes_limit_) { 399 // Hit total_bytes_limit_. But if we also hit the normal limit, 400 // we're still OK. 401 legitimate_message_end_ = current_limit_ == total_bytes_limit_; 402 } else { 403 legitimate_message_end_ = true; 404 } 405 return false; 406 } 407 } 408 409 // Slow path: Just do a 64-bit read. 410 uint64 result; 411 if (!ReadVarint64(&result)) return false; 412 *value = (uint32)result; 413 return true; 414 } 415} 416 417bool CodedInputStream::ReadVarint64(uint64* value) { 418 if (buffer_size_ >= kMaxVarintBytes || 419 // Optimization: If the varint ends at exactly the end of the buffer, 420 // we can detect that and still use the fast path. 421 (buffer_size_ != 0 && !(buffer_[buffer_size_-1] & 0x80))) { 422 // Fast path: We have enough bytes left in the buffer to guarantee that 423 // this read won't cross the end, so we can skip the checks. 424 425 const uint8* ptr = buffer_; 426 uint32 b; 427 428 // Splitting into 32-bit pieces gives better performance on 32-bit 429 // processors. 430 uint32 part0 = 0, part1 = 0, part2 = 0; 431 432 b = *(ptr++); part0 = (b & 0x7F) ; if (!(b & 0x80)) goto done; 433 b = *(ptr++); part0 |= (b & 0x7F) << 7; if (!(b & 0x80)) goto done; 434 b = *(ptr++); part0 |= (b & 0x7F) << 14; if (!(b & 0x80)) goto done; 435 b = *(ptr++); part0 |= (b & 0x7F) << 21; if (!(b & 0x80)) goto done; 436 b = *(ptr++); part1 = (b & 0x7F) ; if (!(b & 0x80)) goto done; 437 b = *(ptr++); part1 |= (b & 0x7F) << 7; if (!(b & 0x80)) goto done; 438 b = *(ptr++); part1 |= (b & 0x7F) << 14; if (!(b & 0x80)) goto done; 439 b = *(ptr++); part1 |= (b & 0x7F) << 21; if (!(b & 0x80)) goto done; 440 b = *(ptr++); part2 = (b & 0x7F) ; if (!(b & 0x80)) goto done; 441 b = *(ptr++); part2 |= (b & 0x7F) << 7; if (!(b & 0x80)) goto done; 442 443 // We have overrun the maximum size of a varint (10 bytes). The data 444 // must be corrupt. 445 return false; 446 447 done: 448 Advance(ptr - buffer_); 449 *value = (static_cast<uint64>(part0) ) | 450 (static_cast<uint64>(part1) << 28) | 451 (static_cast<uint64>(part2) << 56); 452 return true; 453 454 } else { 455 // Slow path: This read might cross the end of the buffer, so we 456 // need to check and refresh the buffer if and when it does. 457 458 uint64 result = 0; 459 int count = 0; 460 uint32 b; 461 462 do { 463 if (count == kMaxVarintBytes) return false; 464 while (buffer_size_ == 0) { 465 if (!Refresh()) return false; 466 } 467 b = *buffer_; 468 result |= static_cast<uint64>(b & 0x7F) << (7 * count); 469 Advance(1); 470 ++count; 471 } while(b & 0x80); 472 473 *value = result; 474 return true; 475 } 476} 477 478bool CodedInputStream::Refresh() { 479 GOOGLE_DCHECK_EQ(buffer_size_, 0); 480 481 if (buffer_size_after_limit_ > 0 || overflow_bytes_ > 0 || 482 total_bytes_read_ == current_limit_) { 483 // We've hit a limit. Stop. 484 int current_position = total_bytes_read_ - buffer_size_after_limit_; 485 486 if (current_position >= total_bytes_limit_ && 487 total_bytes_limit_ != current_limit_) { 488 // Hit total_bytes_limit_. 489 PrintTotalBytesLimitError(); 490 } 491 492 return false; 493 } 494 495 if (total_bytes_warning_threshold_ >= 0 && 496 total_bytes_read_ >= total_bytes_warning_threshold_) { 497 GOOGLE_LOG(WARNING) << "Reading dangerously large protocol message. If the " 498 "message turns out to be larger than " 499 << total_bytes_limit_ << " bytes, parsing will be halted " 500 "for security reasons. To increase the limit (or to " 501 "disable these warnings), see " 502 "CodedInputStream::SetTotalBytesLimit() in " 503 "google/protobuf/io/coded_stream.h."; 504 505 // Don't warn again for this stream. 506 total_bytes_warning_threshold_ = -1; 507 } 508 509 const void* void_buffer; 510 if (input_->Next(&void_buffer, &buffer_size_)) { 511 buffer_ = reinterpret_cast<const uint8*>(void_buffer); 512 GOOGLE_CHECK_GE(buffer_size_, 0); 513 514 if (total_bytes_read_ <= INT_MAX - buffer_size_) { 515 total_bytes_read_ += buffer_size_; 516 } else { 517 // Overflow. Reset buffer_size_ to not include the bytes beyond INT_MAX. 518 // We can't get that far anyway, because total_bytes_limit_ is guaranteed 519 // to be less than it. We need to keep track of the number of bytes 520 // we discarded, though, so that we can call input_->BackUp() to back 521 // up over them on destruction. 522 523 // The following line is equivalent to: 524 // overflow_bytes_ = total_bytes_read_ + buffer_size_ - INT_MAX; 525 // except that it avoids overflows. Signed integer overflow has 526 // undefined results according to the C standard. 527 overflow_bytes_ = total_bytes_read_ - (INT_MAX - buffer_size_); 528 buffer_size_ -= overflow_bytes_; 529 total_bytes_read_ = INT_MAX; 530 } 531 532 RecomputeBufferLimits(); 533 return true; 534 } else { 535 buffer_ = NULL; 536 buffer_size_ = 0; 537 return false; 538 } 539} 540 541// CodedOutputStream ================================================= 542 543CodedOutputStream::CodedOutputStream(ZeroCopyOutputStream* output) 544 : output_(output), 545 buffer_(NULL), 546 buffer_size_(0), 547 total_bytes_(0), 548 had_error_(false) { 549 // Eagerly Refresh() so buffer space is immediately available. 550 Refresh(); 551 // The Refresh() may have failed. If the client doesn't write any data, 552 // though, don't consider this an error. If the client does write data, then 553 // another Refresh() will be attempted and it will set the error once again. 554 had_error_ = false; 555} 556 557CodedOutputStream::~CodedOutputStream() { 558 if (buffer_size_ > 0) { 559 output_->BackUp(buffer_size_); 560 } 561} 562 563bool CodedOutputStream::Skip(int count) { 564 if (count < 0) return false; 565 566 while (count > buffer_size_) { 567 count -= buffer_size_; 568 if (!Refresh()) return false; 569 } 570 571 Advance(count); 572 return true; 573} 574 575bool CodedOutputStream::GetDirectBufferPointer(void** data, int* size) { 576 if (buffer_size_ == 0 && !Refresh()) return false; 577 578 *data = buffer_; 579 *size = buffer_size_; 580 return true; 581} 582 583void CodedOutputStream::WriteRaw(const void* data, int size) { 584 while (buffer_size_ < size) { 585 memcpy(buffer_, data, buffer_size_); 586 size -= buffer_size_; 587 data = reinterpret_cast<const uint8*>(data) + buffer_size_; 588 if (!Refresh()) return; 589 } 590 591 memcpy(buffer_, data, size); 592 Advance(size); 593} 594 595uint8* CodedOutputStream::WriteRawToArray( 596 const void* data, int size, uint8* target) { 597 memcpy(target, data, size); 598 return target + size; 599} 600 601 602void CodedOutputStream::WriteLittleEndian32(uint32 value) { 603 uint8 bytes[sizeof(value)]; 604 605 bool use_fast = buffer_size_ >= sizeof(value); 606 uint8* ptr = use_fast ? buffer_ : bytes; 607 608 WriteLittleEndian32ToArray(value, ptr); 609 610 if (use_fast) { 611 Advance(sizeof(value)); 612 } else { 613 WriteRaw(bytes, sizeof(value)); 614 } 615} 616 617void CodedOutputStream::WriteLittleEndian64(uint64 value) { 618 uint8 bytes[sizeof(value)]; 619 620 bool use_fast = buffer_size_ >= sizeof(value); 621 uint8* ptr = use_fast ? buffer_ : bytes; 622 623 WriteLittleEndian64ToArray(value, ptr); 624 625 if (use_fast) { 626 Advance(sizeof(value)); 627 } else { 628 WriteRaw(bytes, sizeof(value)); 629 } 630} 631 632inline uint8* CodedOutputStream::WriteVarint32FallbackToArrayInline( 633 uint32 value, uint8* target) { 634 target[0] = static_cast<uint8>(value | 0x80); 635 if (value >= (1 << 7)) { 636 target[1] = static_cast<uint8>((value >> 7) | 0x80); 637 if (value >= (1 << 14)) { 638 target[2] = static_cast<uint8>((value >> 14) | 0x80); 639 if (value >= (1 << 21)) { 640 target[3] = static_cast<uint8>((value >> 21) | 0x80); 641 if (value >= (1 << 28)) { 642 target[4] = static_cast<uint8>(value >> 28); 643 return target + 5; 644 } else { 645 target[3] &= 0x7F; 646 return target + 4; 647 } 648 } else { 649 target[2] &= 0x7F; 650 return target + 3; 651 } 652 } else { 653 target[1] &= 0x7F; 654 return target + 2; 655 } 656 } else { 657 target[0] &= 0x7F; 658 return target + 1; 659 } 660} 661 662void CodedOutputStream::WriteVarint32(uint32 value) { 663 if (buffer_size_ >= kMaxVarint32Bytes) { 664 // Fast path: We have enough bytes left in the buffer to guarantee that 665 // this write won't cross the end, so we can skip the checks. 666 uint8* target = buffer_; 667 uint8* end = WriteVarint32FallbackToArrayInline(value, target); 668 int size = end - target; 669 Advance(size); 670 } else { 671 // Slow path: This write might cross the end of the buffer, so we 672 // compose the bytes first then use WriteRaw(). 673 uint8 bytes[kMaxVarint32Bytes]; 674 int size = 0; 675 while (value > 0x7F) { 676 bytes[size++] = (static_cast<uint8>(value) & 0x7F) | 0x80; 677 value >>= 7; 678 } 679 bytes[size++] = static_cast<uint8>(value) & 0x7F; 680 WriteRaw(bytes, size); 681 } 682} 683 684uint8* CodedOutputStream::WriteVarint32FallbackToArray( 685 uint32 value, uint8* target) { 686 return WriteVarint32FallbackToArrayInline(value, target); 687} 688 689inline uint8* CodedOutputStream::WriteVarint64ToArrayInline( 690 uint64 value, uint8* target) { 691 // Splitting into 32-bit pieces gives better performance on 32-bit 692 // processors. 693 uint32 part0 = static_cast<uint32>(value ); 694 uint32 part1 = static_cast<uint32>(value >> 28); 695 uint32 part2 = static_cast<uint32>(value >> 56); 696 697 int size; 698 699 // Here we can't really optimize for small numbers, since the value is 700 // split into three parts. Cheking for numbers < 128, for instance, 701 // would require three comparisons, since you'd have to make sure part1 702 // and part2 are zero. However, if the caller is using 64-bit integers, 703 // it is likely that they expect the numbers to often be very large, so 704 // we probably don't want to optimize for small numbers anyway. Thus, 705 // we end up with a hardcoded binary search tree... 706 if (part2 == 0) { 707 if (part1 == 0) { 708 if (part0 < (1 << 14)) { 709 if (part0 < (1 << 7)) { 710 size = 1; goto size1; 711 } else { 712 size = 2; goto size2; 713 } 714 } else { 715 if (part0 < (1 << 21)) { 716 size = 3; goto size3; 717 } else { 718 size = 4; goto size4; 719 } 720 } 721 } else { 722 if (part1 < (1 << 14)) { 723 if (part1 < (1 << 7)) { 724 size = 5; goto size5; 725 } else { 726 size = 6; goto size6; 727 } 728 } else { 729 if (part1 < (1 << 21)) { 730 size = 7; goto size7; 731 } else { 732 size = 8; goto size8; 733 } 734 } 735 } 736 } else { 737 if (part2 < (1 << 7)) { 738 size = 9; goto size9; 739 } else { 740 size = 10; goto size10; 741 } 742 } 743 744 GOOGLE_LOG(FATAL) << "Can't get here."; 745 746 size10: target[9] = static_cast<uint8>((part2 >> 7) | 0x80); 747 size9 : target[8] = static_cast<uint8>((part2 ) | 0x80); 748 size8 : target[7] = static_cast<uint8>((part1 >> 21) | 0x80); 749 size7 : target[6] = static_cast<uint8>((part1 >> 14) | 0x80); 750 size6 : target[5] = static_cast<uint8>((part1 >> 7) | 0x80); 751 size5 : target[4] = static_cast<uint8>((part1 ) | 0x80); 752 size4 : target[3] = static_cast<uint8>((part0 >> 21) | 0x80); 753 size3 : target[2] = static_cast<uint8>((part0 >> 14) | 0x80); 754 size2 : target[1] = static_cast<uint8>((part0 >> 7) | 0x80); 755 size1 : target[0] = static_cast<uint8>((part0 ) | 0x80); 756 757 target[size-1] &= 0x7F; 758 return target + size; 759} 760 761void CodedOutputStream::WriteVarint64(uint64 value) { 762 if (buffer_size_ >= kMaxVarintBytes) { 763 // Fast path: We have enough bytes left in the buffer to guarantee that 764 // this write won't cross the end, so we can skip the checks. 765 uint8* target = buffer_; 766 767 uint8* end = WriteVarint64ToArrayInline(value, target); 768 int size = end - target; 769 Advance(size); 770 } else { 771 // Slow path: This write might cross the end of the buffer, so we 772 // compose the bytes first then use WriteRaw(). 773 uint8 bytes[kMaxVarintBytes]; 774 int size = 0; 775 while (value > 0x7F) { 776 bytes[size++] = (static_cast<uint8>(value) & 0x7F) | 0x80; 777 value >>= 7; 778 } 779 bytes[size++] = static_cast<uint8>(value) & 0x7F; 780 WriteRaw(bytes, size); 781 } 782} 783 784uint8* CodedOutputStream::WriteVarint64ToArray( 785 uint64 value, uint8* target) { 786 return WriteVarint64ToArrayInline(value, target); 787} 788 789bool CodedOutputStream::Refresh() { 790 void* void_buffer; 791 if (output_->Next(&void_buffer, &buffer_size_)) { 792 buffer_ = reinterpret_cast<uint8*>(void_buffer); 793 total_bytes_ += buffer_size_; 794 return true; 795 } else { 796 buffer_ = NULL; 797 buffer_size_ = 0; 798 had_error_ = true; 799 return false; 800 } 801} 802 803int CodedOutputStream::VarintSize32Fallback(uint32 value) { 804 if (value < (1 << 7)) { 805 return 1; 806 } else if (value < (1 << 14)) { 807 return 2; 808 } else if (value < (1 << 21)) { 809 return 3; 810 } else if (value < (1 << 28)) { 811 return 4; 812 } else { 813 return 5; 814 } 815} 816 817int CodedOutputStream::VarintSize64(uint64 value) { 818 if (value < (1ull << 35)) { 819 if (value < (1ull << 7)) { 820 return 1; 821 } else if (value < (1ull << 14)) { 822 return 2; 823 } else if (value < (1ull << 21)) { 824 return 3; 825 } else if (value < (1ull << 28)) { 826 return 4; 827 } else { 828 return 5; 829 } 830 } else { 831 if (value < (1ull << 42)) { 832 return 6; 833 } else if (value < (1ull << 49)) { 834 return 7; 835 } else if (value < (1ull << 56)) { 836 return 8; 837 } else if (value < (1ull << 63)) { 838 return 9; 839 } else { 840 return 10; 841 } 842 } 843} 844 845} // namespace io 846} // namespace protobuf 847} // namespace google 848