Created
November 10, 2016 20:16
-
-
Save na-ka-na/07db1eed4f8ba2bda5832c87c9338267 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// A ZeroCopyOutputStream which appends bytes to a string. | |
// It has much a more favorable performance profile than StringOutputStream | |
// outside of Google since STLStringResizeUninitialized() is un-optimized. | |
class LIBPROTOBUF_EXPORT StringOutputStream2 : public ZeroCopyOutputStream { | |
public: | |
explicit StringOutputStream2(); | |
~StringOutputStream2(); | |
// implements ZeroCopyOutputStream --------------------------------- | |
bool Next(void** data, int* size); | |
void BackUp(int count); | |
int64 ByteCount() const; | |
// Returns the bytes written to this stream till now. | |
const string& GetBytes(); | |
// Moves bytes written to this stream to the given target. | |
// It is illegal to use the stream after a call to this function. | |
void moveBytes(string& target) { | |
#ifdef LANG_CXX11 | |
target = std::move(GetBytes()); | |
#else | |
target = GetBytes(); | |
#endif | |
byte_count_ = 0; | |
} | |
private: | |
static const int kMinimumSize = 16; | |
string target_; // bytes are appended to this | |
int64 byte_count_; // number of bytes writtten till now | |
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringOutputStream2); | |
}; | |
// =================================================================== | |
StringOutputStream2::StringOutputStream2() | |
: byte_count_(0) { | |
} | |
StringOutputStream2::~StringOutputStream2() { | |
} | |
bool StringOutputStream2::Next(void** data, int* size) { | |
int old_size = target_.size(); | |
// Grow the string. | |
if (old_size < target_.capacity()) { | |
// Resize the string to match its capacity, since we can get away | |
// without a memory allocation this way. | |
STLStringResizeUninitialized(&target_, target_.capacity()); | |
} else if (byte_count_ == old_size) { | |
// Size has reached capacity, try to double the size. | |
if (old_size > std::numeric_limits<int>::max() / 2) { | |
// Can not double the size otherwise it is going to cause integer | |
// overflow in the expression below: old_size * 2 "; | |
GOOGLE_LOG(ERROR) << "Cannot allocate buffer larger than kint32max for " | |
<< "StringOutputStream2."; | |
return false; | |
} | |
// Double the size, also make sure that the new size is at least | |
// kMinimumSize. | |
STLStringResizeUninitialized( | |
&target_, | |
std::max(old_size * 2, | |
kMinimumSize + 0)); // "+ 0" works around GCC4 weirdness. | |
} | |
int new_size = target_.size(); | |
*data = mutable_string_data(&target_) + byte_count_; | |
*size = new_size - byte_count_; | |
byte_count_ = new_size; | |
return true; | |
} | |
void StringOutputStream2::BackUp(int count) { | |
GOOGLE_CHECK_GE(count, 0); | |
GOOGLE_CHECK_LE(count, byte_count_); | |
byte_count_ -= count; | |
} | |
int64 StringOutputStream2::ByteCount() const { | |
return byte_count_; | |
} | |
const string& StringOutputStream2::GetBytes() { | |
if (target_.size() != byte_count_) { | |
target_.resize(byte_count_); | |
} | |
return target_; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment