Index: base/pickle.cc |
diff --git a/base/pickle.cc b/base/pickle.cc |
index 1d06af350fa43c738a44bc4f21887091f1fca8c6..c88503ced08ea79df6c81b8304607cc042391f87 100644 |
--- a/base/pickle.cc |
+++ b/base/pickle.cc |
@@ -153,7 +153,8 @@ bool PickleIterator::ReadBytes(const char** data, int length) { |
Pickle::Pickle() |
: header_(NULL), |
header_size_(sizeof(Header)), |
- capacity_(0) { |
+ capacity_after_header_(0), |
+ write_offset_(0) { |
Resize(kPayloadUnit); |
header_->payload_size = 0; |
} |
@@ -161,7 +162,8 @@ Pickle::Pickle() |
Pickle::Pickle(int header_size) |
: header_(NULL), |
header_size_(AlignInt(header_size, sizeof(uint32))), |
- capacity_(0) { |
+ capacity_after_header_(0), |
+ write_offset_(0) { |
DCHECK_GE(static_cast<size_t>(header_size), sizeof(Header)); |
DCHECK_LE(header_size, kPayloadUnit); |
Resize(kPayloadUnit); |
@@ -171,7 +173,8 @@ Pickle::Pickle(int header_size) |
Pickle::Pickle(const char* data, size_t data_len) |
: header_(reinterpret_cast<Header*>(const_cast<char*>(data))), |
header_size_(0), |
- capacity_(kCapacityReadOnly) { |
+ capacity_after_header_(kCapacityReadOnly), |
+ write_offset_(0) { |
if (data_len >= sizeof(Header)) |
header_size_ = data_len - header_->payload_size; |
@@ -189,15 +192,15 @@ Pickle::Pickle(const char* data, size_t data_len) |
Pickle::Pickle(const Pickle& other) |
: header_(NULL), |
header_size_(other.header_size_), |
- capacity_(0) { |
+ capacity_after_header_(0), |
+ write_offset_(other.write_offset_) { |
size_t payload_size = header_size_ + other.header_->payload_size; |
- bool resized = Resize(payload_size); |
- CHECK(resized); // Realloc failed. |
+ Resize(payload_size); |
memcpy(header_, other.header_, payload_size); |
} |
Pickle::~Pickle() { |
- if (capacity_ != kCapacityReadOnly) |
+ if (capacity_after_header_ != kCapacityReadOnly) |
free(header_); |
} |
@@ -206,19 +209,19 @@ Pickle& Pickle::operator=(const Pickle& other) { |
NOTREACHED(); |
return *this; |
} |
- if (capacity_ == kCapacityReadOnly) { |
+ if (capacity_after_header_ == kCapacityReadOnly) { |
header_ = NULL; |
- capacity_ = 0; |
+ capacity_after_header_ = 0; |
} |
if (header_size_ != other.header_size_) { |
free(header_); |
header_ = NULL; |
header_size_ = other.header_size_; |
} |
- bool resized = Resize(other.header_size_ + other.header_->payload_size); |
- CHECK(resized); // Realloc failed. |
+ Resize(other.header_->payload_size); |
memcpy(header_, other.header_, |
other.header_size_ + other.header_->payload_size); |
+ write_offset_ = other.write_offset_; |
return *this; |
} |
@@ -249,64 +252,31 @@ bool Pickle::WriteData(const char* data, int length) { |
return length >= 0 && WriteInt(length) && WriteBytes(data, length); |
} |
-bool Pickle::WriteBytes(const void* data, int data_len) { |
- DCHECK_NE(kCapacityReadOnly, capacity_) << "oops: pickle is readonly"; |
- |
- char* dest = BeginWrite(data_len); |
- if (!dest) |
- return false; |
- |
- memcpy(dest, data, data_len); |
- |
- EndWrite(dest, data_len); |
+bool Pickle::WriteBytes(const void* data, int length) { |
+ WriteBytesCommon(data, length); |
return true; |
} |
-void Pickle::Reserve(size_t additional_capacity) { |
- // Write at a uint32-aligned offset from the beginning of the header. |
- size_t offset = AlignInt(header_->payload_size, sizeof(uint32)); |
- |
- size_t new_size = offset + additional_capacity; |
- size_t needed_size = header_size_ + new_size; |
- if (needed_size > capacity_) |
- Resize(capacity_ * 2 + needed_size); |
-} |
- |
-char* Pickle::BeginWrite(size_t length) { |
- // Write at a uint32-aligned offset from the beginning of the header. |
- size_t offset = AlignInt(header_->payload_size, sizeof(uint32)); |
- |
- size_t new_size = offset + length; |
- size_t needed_size = header_size_ + new_size; |
- if (needed_size > capacity_ && !Resize(std::max(capacity_ * 2, needed_size))) |
- return NULL; |
- |
+void Pickle::Reserve(size_t length) { |
+ size_t data_len = AlignInt(length, sizeof(uint32)); |
+ DCHECK_GE(data_len, length); |
#ifdef ARCH_CPU_64_BITS |
- DCHECK_LE(length, kuint32max); |
+ DCHECK_LE(data_len, kuint32max); |
#endif |
- |
- header_->payload_size = static_cast<uint32>(new_size); |
- return mutable_payload() + offset; |
-} |
- |
-void Pickle::EndWrite(char* dest, int length) { |
- // Zero-pad to keep tools like valgrind from complaining about uninitialized |
- // memory. |
- if (length % sizeof(uint32)) |
- memset(dest + length, 0, sizeof(uint32) - (length % sizeof(uint32))); |
+ DCHECK_LE(write_offset_, kuint32max - data_len); |
+ size_t new_size = write_offset_ + data_len; |
+ if (new_size > capacity_after_header_) |
+ Resize(capacity_after_header_ * 2 + new_size); |
} |
-bool Pickle::Resize(size_t new_capacity) { |
+void Pickle::Resize(size_t new_capacity) { |
new_capacity = AlignInt(new_capacity, kPayloadUnit); |
- CHECK_NE(capacity_, kCapacityReadOnly); |
- void* p = realloc(header_, new_capacity); |
- if (!p) |
- return false; |
- |
+ CHECK_NE(capacity_after_header_, kCapacityReadOnly); |
+ void* p = realloc(header_, header_size_ + new_capacity); |
+ CHECK(p); |
header_ = reinterpret_cast<Header*>(p); |
- capacity_ = new_capacity; |
- return true; |
+ capacity_after_header_ = new_capacity; |
} |
// static |
@@ -327,3 +297,32 @@ const char* Pickle::FindNext(size_t header_size, |
return (payload_end > end) ? NULL : payload_end; |
} |
+ |
+template <size_t length> void Pickle::WriteBytesStatic(const void* data) { |
+ WriteBytesCommon(data, length); |
+} |
+ |
+template void Pickle::WriteBytesStatic<2>(const void* data); |
+template void Pickle::WriteBytesStatic<4>(const void* data); |
+template void Pickle::WriteBytesStatic<8>(const void* data); |
+ |
+inline void Pickle::WriteBytesCommon(const void* data, size_t length) { |
+ DCHECK_NE(kCapacityReadOnly, capacity_after_header_) |
+ << "oops: pickle is readonly"; |
+ size_t data_len = AlignInt(length, sizeof(uint32)); |
+ DCHECK_GE(data_len, length); |
+#ifdef ARCH_CPU_64_BITS |
+ DCHECK_LE(data_len, kuint32max); |
+#endif |
+ DCHECK_LE(write_offset_, kuint32max - data_len); |
+ size_t new_size = write_offset_ + data_len; |
+ if (new_size > capacity_after_header_) { |
+ Resize(std::max(capacity_after_header_ * 2, new_size)); |
+ } |
+ |
+ char* write = mutable_payload() + write_offset_; |
+ memcpy(write, data, length); |
+ memset(write + length, 0, data_len - length); |
+ header_->payload_size = static_cast<uint32>(write_offset_ + length); |
+ write_offset_ = new_size; |
+} |