• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
49 namespace google {
50 namespace protobuf {
51 namespace io {
52 
53 namespace {
54 
55 static const int kMaxVarintBytes = 10;
56 static const int kMaxVarint32Bytes = 5;
57 
58 
NextNonEmpty(ZeroCopyInputStream * input,const void ** data,int * size)59 inline 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 
~CodedInputStream()72 CodedInputStream::~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.
83 int CodedInputStream::default_recursion_limit_ = 100;
84 
85 
BackUpInputToCurrentPosition()86 void 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 
RecomputeBufferLimits()99 inline 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 
PushLimit(int byte_limit)112 CodedInputStream::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 
PopLimit(Limit limit)137 void 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 
BytesUntilLimit() const148 int 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 
SetTotalBytesLimit(int total_bytes_limit,int warning_threshold)155 void 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 
PrintTotalBytesLimitError()170 void 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 
Skip(int count)178 bool 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 
GetDirectBufferPointer(const void ** data,int * size)215 bool 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 
ReadRaw(void * buffer,int size)223 bool 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 
ReadString(string * buffer,int size)240 bool 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 
ReadStringFallback(string * buffer,int size)245 bool 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 
ReadLittleEndian32Fallback(uint32 * value)271 bool 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 
ReadLittleEndian64Fallback(uint64 * value)288 bool 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 
305 namespace {
306 
307 inline const uint8* ReadVarint32FromArray(
308     const uint8* buffer, uint32* value) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
ReadVarint32FromArray(const uint8 * buffer,uint32 * value)309 inline 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 
ReadVarint32Slow(uint32 * value)339 bool 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 
ReadVarint32Fallback(uint32 * value)348 bool 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 
ReadTagSlow()365 uint32 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 
ReadTagFallback()391 uint32 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 
ReadVarint64Slow(uint64 * value)422 bool 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 
ReadVarint64Fallback(uint64 * value)445 bool 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 
Refresh()486 bool 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 
CodedOutputStream(ZeroCopyOutputStream * output)553 CodedOutputStream::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 
~CodedOutputStream()567 CodedOutputStream::~CodedOutputStream() {
568   if (buffer_size_ > 0) {
569     output_->BackUp(buffer_size_);
570   }
571 }
572 
Skip(int count)573 bool 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 
GetDirectBufferPointer(void ** data,int * size)585 bool 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 
WriteRaw(const void * data,int size)593 void 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 
WriteRawToArray(const void * data,int size,uint8 * target)605 uint8* CodedOutputStream::WriteRawToArray(
606     const void* data, int size, uint8* target) {
607   memcpy(target, data, size);
608   return target + size;
609 }
610 
611 
WriteLittleEndian32(uint32 value)612 void 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 
WriteLittleEndian64(uint64 value)627 void 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 
WriteVarint32FallbackToArrayInline(uint32 value,uint8 * target)642 inline 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 
WriteVarint32(uint32 value)672 void 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 
WriteVarint32FallbackToArray(uint32 value,uint8 * target)694 uint8* CodedOutputStream::WriteVarint32FallbackToArray(
695     uint32 value, uint8* target) {
696   return WriteVarint32FallbackToArrayInline(value, target);
697 }
698 
WriteVarint64ToArrayInline(uint64 value,uint8 * target)699 inline 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 
WriteVarint64(uint64 value)771 void 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 
WriteVarint64ToArray(uint64 value,uint8 * target)794 uint8* CodedOutputStream::WriteVarint64ToArray(
795     uint64 value, uint8* target) {
796   return WriteVarint64ToArrayInline(value, target);
797 }
798 
Refresh()799 bool 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 
VarintSize32Fallback(uint32 value)813 int 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 
VarintSize64(uint64 value)827 int 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