diff --git a/src/google/protobuf/util/json_util.cc b/src/google/protobuf/util/json_util.cc index d7ac2dba66..5974cc4aa3 100644 --- a/src/google/protobuf/util/json_util.cc +++ b/src/google/protobuf/util/json_util.cc @@ -49,22 +49,25 @@ namespace protobuf { namespace util { namespace internal { +ZeroCopyStreamByteSink::~ZeroCopyStreamByteSink() { + stream_->BackUp(buffer_size_); +} + void ZeroCopyStreamByteSink::Append(const char* bytes, size_t len) { - while (len > 0) { - void* buffer; - int length; - if (!stream_->Next(&buffer, &length)) { - // There isn't a way for ByteSink to report errors. + while (true) { + if (len <= buffer_size_) { + memcpy(buffer_, bytes, len); + buffer_ = static_cast(buffer_) + len; + buffer_size_ -= len; return; } - if (len < length) { - memcpy(buffer, bytes, len); - stream_->BackUp(length - len); - break; - } else { - memcpy(buffer, bytes, length); - bytes += length; - len -= length; + memcpy(buffer_, bytes, buffer_size_); + bytes += buffer_size_; + len -= buffer_size_; + if (!stream_->Next(&buffer_, &buffer_size_)) { + // There isn't a way for ByteSink to report errors. + buffer_size_ = 0; + return; } } } diff --git a/src/google/protobuf/util/json_util.h b/src/google/protobuf/util/json_util.h index 6d3cee5281..0e45ef810a 100644 --- a/src/google/protobuf/util/json_util.h +++ b/src/google/protobuf/util/json_util.h @@ -172,12 +172,15 @@ namespace internal { class LIBPROTOBUF_EXPORT ZeroCopyStreamByteSink : public strings::ByteSink { public: explicit ZeroCopyStreamByteSink(io::ZeroCopyOutputStream* stream) - : stream_(stream) {} + : stream_(stream), buffer_size_(0) {} + ~ZeroCopyStreamByteSink(); virtual void Append(const char* bytes, size_t len); private: io::ZeroCopyOutputStream* stream_; + void* buffer_; + int buffer_size_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ZeroCopyStreamByteSink); };