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