summaryrefslogtreecommitdiffstats
path: root/src/google/protobuf/io/coded_stream.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/google/protobuf/io/coded_stream.cc')
-rw-r--r--src/google/protobuf/io/coded_stream.cc164
1 files changed, 40 insertions, 124 deletions
diff --git a/src/google/protobuf/io/coded_stream.cc b/src/google/protobuf/io/coded_stream.cc
index 5344975..6a91a13 100644
--- a/src/google/protobuf/io/coded_stream.cc
+++ b/src/google/protobuf/io/coded_stream.cc
@@ -1,6 +1,6 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
-// https://developers.google.com/protocol-buffers/
+// http://code.google.com/p/protobuf/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
@@ -43,7 +43,7 @@
#include <limits.h>
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/stl_util.h>
+#include <google/protobuf/stubs/stl_util-inl.h>
namespace google {
@@ -56,36 +56,10 @@ static const int kMaxVarintBytes = 10;
static const int kMaxVarint32Bytes = 5;
-inline bool NextNonEmpty(ZeroCopyInputStream* input,
- const void** data, int* size) {
- bool success;
- do {
- success = input->Next(data, size);
- } while (success && *size == 0);
- return success;
-}
-
} // namespace
// CodedInputStream ==================================================
-CodedInputStream::~CodedInputStream() {
- if (input_ != NULL) {
- BackUpInputToCurrentPosition();
- }
-
- if (total_bytes_warning_threshold_ == -2) {
- GOOGLE_LOG(WARNING) << "The total number of bytes read was " << total_bytes_read_;
- }
-}
-
-// Static.
-int CodedInputStream::default_recursion_limit_ = 100;
-
-
-void CodedOutputStream::EnableAliasing(bool enabled) {
- aliasing_enabled_ = enabled && output_->AllowsAliasing();
-}
void CodedInputStream::BackUpInputToCurrentPosition() {
int backup_bytes = BufferSize() + buffer_size_after_limit_ + overflow_bytes_;
@@ -115,7 +89,8 @@ inline void CodedInputStream::RecomputeBufferLimits() {
CodedInputStream::Limit CodedInputStream::PushLimit(int byte_limit) {
// Current position relative to the beginning of the stream.
- int current_position = CurrentPosition();
+ int current_position = total_bytes_read_ -
+ (BufferSize() + buffer_size_after_limit_);
Limit old_limit = current_limit_;
@@ -149,9 +124,10 @@ void CodedInputStream::PopLimit(Limit limit) {
legitimate_message_end_ = false;
}
-int CodedInputStream::BytesUntilLimit() const {
+int CodedInputStream::BytesUntilLimit() {
if (current_limit_ == INT_MAX) return -1;
- int current_position = CurrentPosition();
+ int current_position = total_bytes_read_ -
+ (BufferSize() + buffer_size_after_limit_);
return current_limit_ - current_position;
}
@@ -160,22 +136,13 @@ void CodedInputStream::SetTotalBytesLimit(
int total_bytes_limit, int warning_threshold) {
// Make sure the limit isn't already past, since this could confuse other
// code.
- int current_position = CurrentPosition();
+ int current_position = total_bytes_read_ -
+ (BufferSize() + buffer_size_after_limit_);
total_bytes_limit_ = max(current_position, total_bytes_limit);
- if (warning_threshold >= 0) {
- total_bytes_warning_threshold_ = warning_threshold;
- } else {
- // warning_threshold is negative
- total_bytes_warning_threshold_ = -1;
- }
+ total_bytes_warning_threshold_ = warning_threshold;
RecomputeBufferLimits();
}
-int CodedInputStream::BytesUntilTotalBytesLimit() const {
- if (total_bytes_limit_ == INT_MAX) return -1;
- return total_bytes_limit_ - CurrentPosition();
-}
-
void CodedInputStream::PrintTotalBytesLimitError() {
GOOGLE_LOG(ERROR) << "A protocol message was rejected because it was too "
"big (more than " << total_bytes_limit_
@@ -256,14 +223,6 @@ bool CodedInputStream::ReadStringFallback(string* buffer, int size) {
buffer->clear();
}
- int closest_limit = min(current_limit_, total_bytes_limit_);
- if (closest_limit != INT_MAX) {
- int bytes_to_limit = closest_limit - CurrentPosition();
- if (bytes_to_limit > 0 && size > 0 && size <= bytes_to_limit) {
- buffer->reserve(size);
- }
- }
-
int current_buffer_size;
while ((current_buffer_size = BufferSize()) < size) {
// Some STL implementations "helpfully" crash on buffer->append(NULL, 0).
@@ -330,16 +289,11 @@ inline const uint8* ReadVarint32FromArray(const uint8* buffer, uint32* value) {
uint32 b;
uint32 result;
- b = *(ptr++); result = b ; if (!(b & 0x80)) goto done;
- result -= 0x80;
- b = *(ptr++); result += b << 7; if (!(b & 0x80)) goto done;
- result -= 0x80 << 7;
- b = *(ptr++); result += b << 14; if (!(b & 0x80)) goto done;
- result -= 0x80 << 14;
- b = *(ptr++); result += b << 21; if (!(b & 0x80)) goto done;
- result -= 0x80 << 21;
- b = *(ptr++); result += b << 28; if (!(b & 0x80)) goto done;
- // "result -= 0x80 << 28" is irrevelant.
+ b = *(ptr++); result = (b & 0x7F) ; if (!(b & 0x80)) goto done;
+ b = *(ptr++); result |= (b & 0x7F) << 7; if (!(b & 0x80)) goto done;
+ b = *(ptr++); result |= (b & 0x7F) << 14; if (!(b & 0x80)) goto done;
+ b = *(ptr++); result |= (b & 0x7F) << 21; if (!(b & 0x80)) goto done;
+ b = *(ptr++); result |= b << 28; if (!(b & 0x80)) goto done;
// If the input is larger than 32 bits, we still need to read it all
// and discard the high-order bits.
@@ -369,8 +323,8 @@ bool CodedInputStream::ReadVarint32Slow(uint32* value) {
bool CodedInputStream::ReadVarint32Fallback(uint32* value) {
if (BufferSize() >= kMaxVarintBytes ||
- // Optimization: We're also safe if the buffer is non-empty and it ends
- // with a byte that would terminate a varint.
+ // Optimization: If the varint ends at exactly the end of the buffer,
+ // we can detect that and still use the fast path.
(buffer_end_ > buffer_ && !(buffer_end_[-1] & 0x80))) {
const uint8* end = ReadVarint32FromArray(buffer_, value);
if (end == NULL) return false;
@@ -405,17 +359,16 @@ uint32 CodedInputStream::ReadTagSlow() {
// For the slow path, just do a 64-bit read. Try to optimize for one-byte tags
// again, since we have now refreshed the buffer.
- uint64 result = 0;
+ uint64 result;
if (!ReadVarint64(&result)) return 0;
return static_cast<uint32>(result);
}
uint32 CodedInputStream::ReadTagFallback() {
- const int buf_size = BufferSize();
- if (buf_size >= kMaxVarintBytes ||
- // Optimization: We're also safe if the buffer is non-empty and it ends
- // with a byte that would terminate a varint.
- (buf_size > 0 && !(buffer_end_[-1] & 0x80))) {
+ if (BufferSize() >= kMaxVarintBytes ||
+ // Optimization: If the varint ends at exactly the end of the buffer,
+ // we can detect that and still use the fast path.
+ (buffer_end_ > buffer_ && !(buffer_end_[-1] & 0x80))) {
uint32 tag;
const uint8* end = ReadVarint32FromArray(buffer_, &tag);
if (end == NULL) {
@@ -426,9 +379,7 @@ uint32 CodedInputStream::ReadTagFallback() {
} else {
// We are commonly at a limit when attempting to read tags. Try to quickly
// detect this case without making another function call.
- if ((buf_size == 0) &&
- ((buffer_size_after_limit_ > 0) ||
- (total_bytes_read_ == current_limit_)) &&
+ if (buffer_ == buffer_end_ && buffer_size_after_limit_ > 0 &&
// Make sure that the limit we hit is not total_bytes_limit_, since
// in that case we still need to call Refresh() so that it prints an
// error.
@@ -466,8 +417,8 @@ bool CodedInputStream::ReadVarint64Slow(uint64* value) {
bool CodedInputStream::ReadVarint64Fallback(uint64* value) {
if (BufferSize() >= kMaxVarintBytes ||
- // Optimization: We're also safe if the buffer is non-empty and it ends
- // with a byte that would terminate a varint.
+ // Optimization: If the varint ends at exactly the end of the buffer,
+ // we can detect that and still use the fast path.
(buffer_end_ > buffer_ && !(buffer_end_[-1] & 0x80))) {
// Fast path: We have enough bytes left in the buffer to guarantee that
// this read won't cross the end, so we can skip the checks.
@@ -479,30 +430,20 @@ bool CodedInputStream::ReadVarint64Fallback(uint64* value) {
// processors.
uint32 part0 = 0, part1 = 0, part2 = 0;
- b = *(ptr++); part0 = b ; if (!(b & 0x80)) goto done;
- part0 -= 0x80;
- b = *(ptr++); part0 += b << 7; if (!(b & 0x80)) goto done;
- part0 -= 0x80 << 7;
- b = *(ptr++); part0 += b << 14; if (!(b & 0x80)) goto done;
- part0 -= 0x80 << 14;
- b = *(ptr++); part0 += b << 21; if (!(b & 0x80)) goto done;
- part0 -= 0x80 << 21;
- b = *(ptr++); part1 = b ; if (!(b & 0x80)) goto done;
- part1 -= 0x80;
- b = *(ptr++); part1 += b << 7; if (!(b & 0x80)) goto done;
- part1 -= 0x80 << 7;
- b = *(ptr++); part1 += b << 14; if (!(b & 0x80)) goto done;
- part1 -= 0x80 << 14;
- b = *(ptr++); part1 += b << 21; if (!(b & 0x80)) goto done;
- part1 -= 0x80 << 21;
- b = *(ptr++); part2 = b ; if (!(b & 0x80)) goto done;
- part2 -= 0x80;
- b = *(ptr++); part2 += b << 7; if (!(b & 0x80)) goto done;
- // "part2 -= 0x80 << 7" is irrelevant because (0x80 << 7) << 56 is 0.
+ b = *(ptr++); part0 = (b & 0x7F) ; if (!(b & 0x80)) goto done;
+ b = *(ptr++); part0 |= (b & 0x7F) << 7; if (!(b & 0x80)) goto done;
+ b = *(ptr++); part0 |= (b & 0x7F) << 14; if (!(b & 0x80)) goto done;
+ b = *(ptr++); part0 |= (b & 0x7F) << 21; if (!(b & 0x80)) goto done;
+ b = *(ptr++); part1 = (b & 0x7F) ; if (!(b & 0x80)) goto done;
+ b = *(ptr++); part1 |= (b & 0x7F) << 7; if (!(b & 0x80)) goto done;
+ b = *(ptr++); part1 |= (b & 0x7F) << 14; if (!(b & 0x80)) goto done;
+ b = *(ptr++); part1 |= (b & 0x7F) << 21; if (!(b & 0x80)) goto done;
+ b = *(ptr++); part2 = (b & 0x7F) ; if (!(b & 0x80)) goto done;
+ b = *(ptr++); part2 |= (b & 0x7F) << 7; if (!(b & 0x80)) goto done;
// We have overrun the maximum size of a varint (10 bytes). The data
// must be corrupt.
- return false;
+ return NULL;
done:
Advance(ptr - buffer_);
@@ -542,13 +483,13 @@ bool CodedInputStream::Refresh() {
"CodedInputStream::SetTotalBytesLimit() in "
"google/protobuf/io/coded_stream.h.";
- // Don't warn again for this stream, and print total size at the end.
- total_bytes_warning_threshold_ = -2;
+ // Don't warn again for this stream.
+ total_bytes_warning_threshold_ = -1;
}
const void* void_buffer;
int buffer_size;
- if (NextNonEmpty(input_, &void_buffer, &buffer_size)) {
+ if (input_->Next(&void_buffer, &buffer_size)) {
buffer_ = reinterpret_cast<const uint8*>(void_buffer);
buffer_end_ = buffer_ + buffer_size;
GOOGLE_CHECK_GE(buffer_size, 0);
@@ -587,8 +528,7 @@ CodedOutputStream::CodedOutputStream(ZeroCopyOutputStream* output)
buffer_(NULL),
buffer_size_(0),
total_bytes_(0),
- had_error_(false),
- aliasing_enabled_(false) {
+ had_error_(false) {
// Eagerly Refresh() so buffer space is immediately available.
Refresh();
// The Refresh() may have failed. If the client doesn't write any data,
@@ -642,23 +582,6 @@ uint8* CodedOutputStream::WriteRawToArray(
}
-void CodedOutputStream::WriteAliasedRaw(const void* data, int size) {
- if (size < buffer_size_
- ) {
- WriteRaw(data, size);
- } else {
- if (buffer_size_ > 0) {
- output_->BackUp(buffer_size_);
- total_bytes_ -= buffer_size_;
- buffer_ = NULL;
- buffer_size_ = 0;
- }
-
- total_bytes_ += size;
- had_error_ |= !output_->WriteAliasedRaw(data, size);
- }
-}
-
void CodedOutputStream::WriteLittleEndian32(uint32 value) {
uint8 bytes[sizeof(value)];
@@ -902,13 +825,6 @@ int CodedOutputStream::VarintSize64(uint64 value) {
}
}
-uint8* CodedOutputStream::WriteStringWithSizeToArray(const string& str,
- uint8* target) {
- GOOGLE_DCHECK_LE(str.size(), kuint32max);
- target = WriteVarint32ToArray(str.size(), target);
- return WriteStringToArray(str, target);
-}
-
} // namespace io
} // namespace protobuf
} // namespace google