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