diff --git a/tdutils/CMakeLists.txt b/tdutils/CMakeLists.txt index ce58be57d..3af31b35e 100644 --- a/tdutils/CMakeLists.txt +++ b/tdutils/CMakeLists.txt @@ -68,10 +68,12 @@ set(TDUTILS_SOURCE td/utils/HttpUrl.cpp td/utils/JsonBuilder.cpp td/utils/logging.cpp + td/utils/misc.cpp td/utils/MimeType.cpp td/utils/Random.cpp td/utils/StackAllocator.cpp td/utils/Status.cpp + td/utils/StringBuilder.cpp td/utils/Time.cpp td/utils/Timer.cpp td/utils/tl_parsers.cpp @@ -162,10 +164,10 @@ set(TDUTILS_SOURCE td/utils/queue.h td/utils/Random.h td/utils/ScopeGuard.h + td/utils/SharedObjectPool.h td/utils/Slice-decl.h td/utils/Slice.h td/utils/SpinLock.h - td/utils/SharedObjectPool.h td/utils/StackAllocator.h td/utils/Status.h td/utils/Storer.h diff --git a/tdutils/td/utils/StringBuilder.cpp b/tdutils/td/utils/StringBuilder.cpp new file mode 100644 index 000000000..83fcb3c30 --- /dev/null +++ b/tdutils/td/utils/StringBuilder.cpp @@ -0,0 +1,108 @@ +// +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2018 +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +#include "td/utils/StringBuilder.h" + +#include + +namespace td { + +// TODO: optimize +StringBuilder &StringBuilder::operator<<(int x) { + if (unlikely(end_ptr_ < current_ptr_)) { + return on_error(); + } + current_ptr_ += std::snprintf(current_ptr_, reserved_size, "%d", x); + return *this; +} + +StringBuilder &StringBuilder::operator<<(unsigned int x) { + if (unlikely(end_ptr_ < current_ptr_)) { + return on_error(); + } + current_ptr_ += std::snprintf(current_ptr_, reserved_size, "%u", x); + return *this; +} + +StringBuilder &StringBuilder::operator<<(long int x) { + if (unlikely(end_ptr_ < current_ptr_)) { + return on_error(); + } + current_ptr_ += std::snprintf(current_ptr_, reserved_size, "%ld", x); + return *this; +} + +StringBuilder &StringBuilder::operator<<(long unsigned int x) { + if (unlikely(end_ptr_ < current_ptr_)) { + return on_error(); + } + current_ptr_ += std::snprintf(current_ptr_, reserved_size, "%lu", x); + return *this; +} + +StringBuilder &StringBuilder::operator<<(long long int x) { + if (unlikely(end_ptr_ < current_ptr_)) { + return on_error(); + } + current_ptr_ += std::snprintf(current_ptr_, reserved_size, "%lld", x); + return *this; +} + +StringBuilder &StringBuilder::operator<<(long long unsigned int x) { + if (unlikely(end_ptr_ < current_ptr_)) { + return on_error(); + } + current_ptr_ += std::snprintf(current_ptr_, reserved_size, "%llu", x); + return *this; +} + +StringBuilder &StringBuilder::operator<<(double x) { + if (unlikely(end_ptr_ < current_ptr_)) { + return on_error(); + } + auto left = end_ptr_ + reserved_size - current_ptr_; + int len = std::snprintf(current_ptr_, left, "%lf", x); + if (unlikely(len >= left)) { + error_flag_ = true; + current_ptr_ += left - 1; + } else { + current_ptr_ += len; + } + return *this; +} + +StringBuilder &StringBuilder::operator<<(const void *ptr) { + if (unlikely(end_ptr_ < current_ptr_)) { + return on_error(); + } + current_ptr_ += std::snprintf(current_ptr_, reserved_size, "%p", ptr); + return *this; +} + +void StringBuilder::vprintf(const char *fmt, va_list list) { + if (unlikely(end_ptr_ < current_ptr_)) { + on_error(); + return; + } + + auto left = end_ptr_ + reserved_size - current_ptr_; + int len = std::vsnprintf(current_ptr_, left, fmt, list); + if (unlikely(len >= left)) { + error_flag_ = true; + current_ptr_ += left - 1; + } else { + current_ptr_ += len; + } +} + +void StringBuilder::printf(const char *fmt, ...) { + va_list list; + va_start(list, fmt); + vprintf(fmt, list); + va_end(list); +} + +} // namespace td diff --git a/tdutils/td/utils/StringBuilder.h b/tdutils/td/utils/StringBuilder.h index 68b5c3c46..ca4144195 100644 --- a/tdutils/td/utils/StringBuilder.h +++ b/tdutils/td/utils/StringBuilder.h @@ -11,7 +11,6 @@ #include "td/utils/StackAllocator.h" #include -#include #include #include #include @@ -31,6 +30,7 @@ class StringBuilder { current_ptr_ = begin_ptr_; error_flag_ = false; } + MutableCSlice as_cslice() { if (current_ptr_ >= end_ptr_ + reserved_size) { std::abort(); // shouldn't happen @@ -82,101 +82,30 @@ class StringBuilder { return *this << static_cast(c); } - // TODO: optimize - StringBuilder &operator<<(int x) { - if (unlikely(end_ptr_ < current_ptr_)) { - return on_error(); - } - current_ptr_ += std::snprintf(current_ptr_, reserved_size, "%d", x); - return *this; - } + StringBuilder &operator<<(int x); - StringBuilder &operator<<(unsigned int x) { - if (unlikely(end_ptr_ < current_ptr_)) { - return on_error(); - } - current_ptr_ += std::snprintf(current_ptr_, reserved_size, "%u", x); - return *this; - } + StringBuilder &operator<<(unsigned int x); - StringBuilder &operator<<(long int x) { - if (unlikely(end_ptr_ < current_ptr_)) { - return on_error(); - } - current_ptr_ += std::snprintf(current_ptr_, reserved_size, "%ld", x); - return *this; - } + StringBuilder &operator<<(long int x); - StringBuilder &operator<<(long unsigned int x) { - if (unlikely(end_ptr_ < current_ptr_)) { - return on_error(); - } - current_ptr_ += std::snprintf(current_ptr_, reserved_size, "%lu", x); - return *this; - } + StringBuilder &operator<<(long unsigned int x); - StringBuilder &operator<<(long long int x) { - if (unlikely(end_ptr_ < current_ptr_)) { - return on_error(); - } - current_ptr_ += std::snprintf(current_ptr_, reserved_size, "%lld", x); - return *this; - } + StringBuilder &operator<<(long long int x); - StringBuilder &operator<<(long long unsigned int x) { - if (unlikely(end_ptr_ < current_ptr_)) { - return on_error(); - } - current_ptr_ += std::snprintf(current_ptr_, reserved_size, "%llu", x); - return *this; - } + StringBuilder &operator<<(long long unsigned int x); - StringBuilder &operator<<(double x) { - if (unlikely(end_ptr_ < current_ptr_)) { - return on_error(); - } - auto left = end_ptr_ + reserved_size - current_ptr_; - int len = std::snprintf(current_ptr_, left, "%lf", x); - if (unlikely(len >= left)) { - error_flag_ = true; - current_ptr_ += left - 1; - } else { - current_ptr_ += len; - } - return *this; - } + StringBuilder &operator<<(double x); + + StringBuilder &operator<<(const void *ptr); template StringBuilder &operator<<(const T *ptr) { - if (unlikely(end_ptr_ < current_ptr_)) { - return on_error(); - } - current_ptr_ += std::snprintf(current_ptr_, reserved_size, "%p", ptr); - return *this; + return *this << static_cast(ptr); } - void vprintf(const char *fmt, va_list list) { - if (unlikely(end_ptr_ < current_ptr_)) { - on_error(); - return; - } + void vprintf(const char *fmt, va_list list); - auto left = end_ptr_ + reserved_size - current_ptr_; - int len = std::vsnprintf(current_ptr_, left, fmt, list); - if (unlikely(len >= left)) { - error_flag_ = true; - current_ptr_ += left - 1; - } else { - current_ptr_ += len; - } - } - - void printf(const char *fmt, ...) TD_ATTRIBUTE_FORMAT_PRINTF(2, 3) { - va_list list; - va_start(list, fmt); - vprintf(fmt, list); - va_end(list); - } + void printf(const char *fmt, ...) TD_ATTRIBUTE_FORMAT_PRINTF(2, 3); private: char *begin_ptr_; diff --git a/tdutils/td/utils/misc.cpp b/tdutils/td/utils/misc.cpp new file mode 100644 index 000000000..83db9da42 --- /dev/null +++ b/tdutils/td/utils/misc.cpp @@ -0,0 +1,63 @@ +// +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2018 +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +#include "td/utils/misc.h" + +#include +#include + +namespace td { + +char *str_dup(Slice str) { + char *res = static_cast(std::malloc(str.size() + 1)); + if (res == nullptr) { + return nullptr; + } + std::copy(str.begin(), str.end(), res); + res[str.size()] = '\0'; + return res; +} + +string implode(vector v, char delimiter) { + string result; + for (auto &str : v) { + if (!result.empty()) { + result += delimiter; + } + result += str; + } + return result; +} + +string oneline(Slice str) { + string result; + result.reserve(str.size()); + bool after_new_line = true; + for (auto c : str) { + if (c != '\n') { + if (after_new_line) { + if (c == ' ') { + continue; + } + after_new_line = false; + } + result += c; + } else { + after_new_line = true; + result += ' '; + } + } + while (!result.empty() && result.back() == ' ') { + result.pop_back(); + } + return result; +} + +double to_double(CSlice str) { + return std::atof(str.c_str()); +} + +} // namespace td diff --git a/tdutils/td/utils/misc.h b/tdutils/td/utils/misc.h index 47ee51bfc..61003e144 100644 --- a/tdutils/td/utils/misc.h +++ b/tdutils/td/utils/misc.h @@ -12,8 +12,8 @@ #include "td/utils/Status.h" #include "td/utils/StringBuilder.h" +#include #include -#include #include #include #include @@ -23,15 +23,7 @@ namespace td { -inline char *str_dup(Slice str) { - char *res = static_cast(std::malloc(str.size() + 1)); - if (res == nullptr) { - return nullptr; - } - std::copy(str.begin(), str.end(), res); - res[str.size()] = '\0'; - return res; -} +char *str_dup(Slice str); template std::pair split(T s, char delimiter = ' ') { @@ -54,16 +46,7 @@ vector full_split(T s, char delimiter = ' ') { return result; } -inline string implode(vector v, char delimiter = ' ') { - string result; - for (auto &str : v) { - if (!result.empty()) { - result += delimiter; - } - result += str; - } - return result; -} +string implode(vector v, char delimiter = ' '); namespace detail { @@ -209,29 +192,7 @@ T trim(T str) { return T(begin, end); } -inline string oneline(Slice str) { - string result; - result.reserve(str.size()); - bool after_new_line = true; - for (auto c : str) { - if (c != '\n') { - if (after_new_line) { - if (c == ' ') { - continue; - } - after_new_line = false; - } - result += c; - } else { - after_new_line = true; - result += ' '; - } - } - while (!result.empty() && result.back() == ' ') { - result.pop_back(); - } - return result; -} +string oneline(Slice str); template std::enable_if_t::value, T> to_integer(Slice str) { @@ -303,9 +264,7 @@ typename std::enable_if::value, T>::type hex_to_integer(Slic return integer_value; } -inline double to_double(CSlice str) { - return std::atof(str.c_str()); -} +double to_double(CSlice str); template T clamp(T value, T min_value, T max_value) {