StringBuilder fixes.
GitOrigin-RevId: 1836df5f6931ca94e96e7281eeb1090163d8648f
This commit is contained in:
parent
a91db513eb
commit
bc88b8e951
@ -187,7 +187,7 @@ void UpdatesManager::fill_gap(void *td, const char *source) {
|
|||||||
|
|
||||||
string UpdatesManager::get_state() const {
|
string UpdatesManager::get_state() const {
|
||||||
char buff[1024];
|
char buff[1024];
|
||||||
StringBuilder sb({buff, sizeof(buff)});
|
StringBuilder sb(MutableSlice{buff, sizeof(buff)});
|
||||||
sb << "UpdatesManager is in state ";
|
sb << "UpdatesManager is in state ";
|
||||||
switch (state_.type) {
|
switch (state_.type) {
|
||||||
case State::Type::General:
|
case State::Type::General:
|
||||||
|
@ -16,26 +16,26 @@ namespace td {
|
|||||||
class HttpHeaderCreator {
|
class HttpHeaderCreator {
|
||||||
public:
|
public:
|
||||||
static constexpr size_t MAX_HEADER = 4096;
|
static constexpr size_t MAX_HEADER = 4096;
|
||||||
HttpHeaderCreator() : sb_({header_, MAX_HEADER}) {
|
HttpHeaderCreator() : sb_(MutableSlice{header_, MAX_HEADER}) {
|
||||||
}
|
}
|
||||||
void init_ok() {
|
void init_ok() {
|
||||||
sb_ = StringBuilder({header_, MAX_HEADER});
|
sb_ = StringBuilder(MutableSlice{header_, MAX_HEADER});
|
||||||
sb_ << "HTTP/1.1 200 OK\r\n";
|
sb_ << "HTTP/1.1 200 OK\r\n";
|
||||||
}
|
}
|
||||||
void init_get(Slice url) {
|
void init_get(Slice url) {
|
||||||
sb_ = StringBuilder({header_, MAX_HEADER});
|
sb_ = StringBuilder(MutableSlice{header_, MAX_HEADER});
|
||||||
sb_ << "GET " << url << " HTTP/1.1\r\n";
|
sb_ << "GET " << url << " HTTP/1.1\r\n";
|
||||||
}
|
}
|
||||||
void init_post(Slice url) {
|
void init_post(Slice url) {
|
||||||
sb_ = StringBuilder({header_, MAX_HEADER});
|
sb_ = StringBuilder(MutableSlice{header_, MAX_HEADER});
|
||||||
sb_ << "POST " << url << " HTTP/1.1\r\n";
|
sb_ << "POST " << url << " HTTP/1.1\r\n";
|
||||||
}
|
}
|
||||||
void init_error(int code, Slice reason) {
|
void init_error(int code, Slice reason) {
|
||||||
sb_ = StringBuilder({header_, MAX_HEADER});
|
sb_ = StringBuilder(MutableSlice{header_, MAX_HEADER});
|
||||||
sb_ << "HTTP/1.1 " << code << " " << reason << "\r\n";
|
sb_ << "HTTP/1.1 " << code << " " << reason << "\r\n";
|
||||||
}
|
}
|
||||||
void init_status_line(int http_status_code) {
|
void init_status_line(int http_status_code) {
|
||||||
sb_ = StringBuilder({header_, MAX_HEADER});
|
sb_ = StringBuilder(MutableSlice{header_, MAX_HEADER});
|
||||||
sb_ << "HTTP/1.1 " << http_status_code << " " << get_status_line(http_status_code) << "\r\n";
|
sb_ << "HTTP/1.1 " << http_status_code << " " << get_status_line(http_status_code) << "\r\n";
|
||||||
}
|
}
|
||||||
void add_header(Slice key, Slice value) {
|
void add_header(Slice key, Slice value) {
|
||||||
|
@ -58,7 +58,7 @@ class OptionsParser {
|
|||||||
return -1;
|
return -1;
|
||||||
#else
|
#else
|
||||||
char buff[1024];
|
char buff[1024];
|
||||||
StringBuilder sb({buff, sizeof(buff)});
|
StringBuilder sb(MutableSlice{buff, sizeof(buff)});
|
||||||
for (auto &opt : options_) {
|
for (auto &opt : options_) {
|
||||||
CHECK(opt.type != Option::OptionalArg);
|
CHECK(opt.type != Option::OptionalArg);
|
||||||
sb << opt.short_key;
|
sb << opt.short_key;
|
||||||
|
@ -65,10 +65,16 @@ bool StringBuilder::reserve_inner(size_t size) {
|
|||||||
if (!use_buffer_) {
|
if (!use_buffer_) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//TODO: check size_t oveflow
|
|
||||||
size_t old_data_size = current_ptr_ - begin_ptr_;
|
size_t old_data_size = current_ptr_ - begin_ptr_;
|
||||||
|
if (size >= std::numeric_limits<size_t>::max() - reserved_size - old_data_size - 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
size_t need_data_size = old_data_size + size;
|
size_t need_data_size = old_data_size + size;
|
||||||
size_t old_buffer_size = end_ptr_ - begin_ptr_;
|
size_t old_buffer_size = end_ptr_ - begin_ptr_;
|
||||||
|
if (old_buffer_size >= (std::numeric_limits<size_t>::max() - reserved_size) / 2 - 2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
size_t new_buffer_size = (old_buffer_size + 1) * 2;
|
size_t new_buffer_size = (old_buffer_size + 1) * 2;
|
||||||
if (new_buffer_size < need_data_size) {
|
if (new_buffer_size < need_data_size) {
|
||||||
new_buffer_size = need_data_size;
|
new_buffer_size = need_data_size;
|
||||||
@ -77,13 +83,14 @@ bool StringBuilder::reserve_inner(size_t size) {
|
|||||||
new_buffer_size = 100;
|
new_buffer_size = 100;
|
||||||
}
|
}
|
||||||
new_buffer_size += reserved_size;
|
new_buffer_size += reserved_size;
|
||||||
auto new_buffer_ = std::make_unique<char[]>(new_buffer_size);
|
auto new_buffer = std::make_unique<char[]>(new_buffer_size);
|
||||||
std::memcpy(new_buffer_.get(), begin_ptr_, old_data_size);
|
std::memcpy(new_buffer.get(), begin_ptr_, old_data_size);
|
||||||
buffer_ = std::move(new_buffer_);
|
buffer_ = std::move(new_buffer);
|
||||||
begin_ptr_ = buffer_.get();
|
begin_ptr_ = buffer_.get();
|
||||||
current_ptr_ = begin_ptr_ + old_data_size;
|
current_ptr_ = begin_ptr_ + old_data_size;
|
||||||
end_ptr_ = begin_ptr_ + new_buffer_size - reserved_size;
|
end_ptr_ = begin_ptr_ + new_buffer_size - reserved_size;
|
||||||
CHECK(end_ptr_ > begin_ptr_);
|
CHECK(end_ptr_ > current_ptr_);
|
||||||
|
CHECK(static_cast<size_t>(end_ptr_ - current_ptr_) >= size);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,7 +143,7 @@ StringBuilder &StringBuilder::operator<<(long long unsigned int x) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StringBuilder &StringBuilder::operator<<(FixedDouble x) {
|
StringBuilder &StringBuilder::operator<<(FixedDouble x) {
|
||||||
if (unlikely(!reserve())) {
|
if (unlikely(!reserve(std::numeric_limits<double>::max_exponent10 + x.precision + 4))) {
|
||||||
return on_error();
|
return on_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,16 +19,15 @@ namespace td {
|
|||||||
class StringBuilder {
|
class StringBuilder {
|
||||||
public:
|
public:
|
||||||
explicit StringBuilder(MutableSlice slice, bool use_buffer = false)
|
explicit StringBuilder(MutableSlice slice, bool use_buffer = false)
|
||||||
: begin_ptr_(slice.begin())
|
: begin_ptr_(slice.begin()), current_ptr_(begin_ptr_), use_buffer_(use_buffer) {
|
||||||
, current_ptr_(begin_ptr_)
|
|
||||||
, end_ptr_(slice.end() - reserved_size)
|
|
||||||
, use_buffer_(use_buffer) {
|
|
||||||
if (slice.size() <= reserved_size) {
|
if (slice.size() <= reserved_size) {
|
||||||
auto buffer_size = reserved_size + 100;
|
auto buffer_size = reserved_size + 100;
|
||||||
buffer_ = std::make_unique<char[]>(buffer_size);
|
buffer_ = std::make_unique<char[]>(buffer_size);
|
||||||
begin_ptr_ = buffer_.get();
|
begin_ptr_ = buffer_.get();
|
||||||
current_ptr_ = begin_ptr_;
|
current_ptr_ = begin_ptr_;
|
||||||
end_ptr_ = begin_ptr_ + buffer_size - reserved_size;
|
end_ptr_ = begin_ptr_ + buffer_size - reserved_size;
|
||||||
|
} else {
|
||||||
|
end_ptr_ = slice.end() - reserved_size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ static void decode_encode(string str, string result = "") {
|
|||||||
|
|
||||||
TEST(JSON, array) {
|
TEST(JSON, array) {
|
||||||
char tmp[1000];
|
char tmp[1000];
|
||||||
StringBuilder sb({tmp, sizeof(tmp)});
|
StringBuilder sb(MutableSlice{tmp, sizeof(tmp)});
|
||||||
JsonBuilder jb(std::move(sb));
|
JsonBuilder jb(std::move(sb));
|
||||||
jb.enter_value().enter_array() << "Hello" << -123;
|
jb.enter_value().enter_array() << "Hello" << -123;
|
||||||
ASSERT_EQ(jb.string_builder().is_error(), false);
|
ASSERT_EQ(jb.string_builder().is_error(), false);
|
||||||
@ -44,7 +44,7 @@ TEST(JSON, array) {
|
|||||||
}
|
}
|
||||||
TEST(JSON, object) {
|
TEST(JSON, object) {
|
||||||
char tmp[1000];
|
char tmp[1000];
|
||||||
StringBuilder sb({tmp, sizeof(tmp)});
|
StringBuilder sb(MutableSlice{tmp, sizeof(tmp)});
|
||||||
JsonBuilder jb(std::move(sb));
|
JsonBuilder jb(std::move(sb));
|
||||||
auto c = jb.enter_object();
|
auto c = jb.enter_object();
|
||||||
c << std::tie("key", "value");
|
c << std::tie("key", "value");
|
||||||
@ -58,7 +58,7 @@ TEST(JSON, object) {
|
|||||||
|
|
||||||
TEST(JSON, nested) {
|
TEST(JSON, nested) {
|
||||||
char tmp[1000];
|
char tmp[1000];
|
||||||
StringBuilder sb({tmp, sizeof(tmp)});
|
StringBuilder sb(MutableSlice{tmp, sizeof(tmp)});
|
||||||
JsonBuilder jb(std::move(sb));
|
JsonBuilder jb(std::move(sb));
|
||||||
{
|
{
|
||||||
auto a = jb.enter_array();
|
auto a = jb.enter_array();
|
||||||
|
@ -494,12 +494,12 @@ TEST(Misc, full_split) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST(Misc, StringBuilder) {
|
TEST(Misc, StringBuilder) {
|
||||||
auto small = std::string{"abcdefghij"};
|
auto small_str = std::string{"abcdefghij"};
|
||||||
auto big = std::string(1000, 'a');
|
auto big_str = std::string(1000, 'a');
|
||||||
using V = std::vector<std::string>;
|
using V = std::vector<std::string>;
|
||||||
for (auto use_buf : {false, true}) {
|
for (auto use_buf : {false, true}) {
|
||||||
for (size_t initial_buffer_size : {0, 1, 5, 10, 100, 1000, 2000}) {
|
for (size_t initial_buffer_size : {0, 1, 5, 10, 100, 1000, 2000}) {
|
||||||
for (auto test : {V{small}, {small, big, big, small}, {big, small, big}}) {
|
for (auto test : {V{small_str}, V{small_str, big_str, big_str, small_str}, V{big_str, small_str, big_str}}) {
|
||||||
std::string buf(initial_buffer_size, '\0');
|
std::string buf(initial_buffer_size, '\0');
|
||||||
td::StringBuilder sb(buf, use_buf);
|
td::StringBuilder sb(buf, use_buf);
|
||||||
std::string res;
|
std::string res;
|
||||||
|
Loading…
Reference in New Issue
Block a user