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