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