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