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