Change string management to improve appending performance
This commit is contained in:
parent
a73c9940fe
commit
8a4cae1ccf
@ -48,7 +48,7 @@ namespace raii{
|
||||
|
||||
using string_intermediary<detail::rjp_allocator>::string_intermediary;
|
||||
rjp_string(RJP_value* r):
|
||||
string_intermediary<detail::rjp_allocator>(r ? std::exchange(r->string.value, nullptr) : nullptr, r ? r->string.length : 0){}
|
||||
string_intermediary<detail::rjp_allocator>(r ? std::exchange(r->string.value, nullptr) : nullptr, r ? r->string.length : 0, r ? r->string.length : 0){}
|
||||
using string_intermediary<detail::rjp_allocator>::operator=;
|
||||
rjp_string& operator=(RJP_value* r){
|
||||
if(!r)
|
||||
@ -56,6 +56,7 @@ namespace raii{
|
||||
reset();
|
||||
m_data = std::exchange(r->string.value, nullptr);
|
||||
m_length = r->string.length;
|
||||
m_cap = r->string.length;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
@ -32,15 +32,18 @@ namespace raii{
|
||||
{
|
||||
protected:
|
||||
size_t m_length = 0;
|
||||
size_t m_cap = 0;
|
||||
char* m_data = nullptr;
|
||||
|
||||
protected:
|
||||
constexpr string_base(void) = default;
|
||||
constexpr string_base(size_t len):
|
||||
m_length(len){}
|
||||
m_cap(len){}
|
||||
//Initialize without copying
|
||||
constexpr string_base(char* data, size_t len):
|
||||
m_length(len), m_data(data){}
|
||||
m_cap(len), m_data(data){}
|
||||
constexpr string_base(char* data, size_t len, size_t cap):
|
||||
m_length(len), m_cap(cap), m_data(data){}
|
||||
//Copy ctor (do nothing)
|
||||
string_base(const string_base&){}
|
||||
~string_base(void) = default;
|
||||
@ -51,6 +54,7 @@ namespace raii{
|
||||
|
||||
//Length of string not including null terminator
|
||||
constexpr size_t length(void)const{return m_length;}
|
||||
constexpr size_t capacity(void)const{return m_cap;}
|
||||
//direct access to managed pointer
|
||||
constexpr char* get(void){return m_data;}
|
||||
constexpr const char* get(void)const{return m_data;}
|
||||
@ -75,8 +79,10 @@ namespace raii{
|
||||
string_intermediary(void) = default;
|
||||
string_intermediary(char* data, size_t len);
|
||||
string_intermediary(const char* data, size_t len);
|
||||
string_intermediary(char* data, size_t len, size_t cap);
|
||||
string_intermediary(const char* data);
|
||||
string_intermediary(size_t len);
|
||||
string_intermediary(size_t len, size_t cap);
|
||||
|
||||
//normal copy and move ctors
|
||||
string_intermediary(const string_intermediary& b);
|
||||
@ -184,7 +190,6 @@ namespace raii{
|
||||
{
|
||||
private:
|
||||
Targ& m_targ;
|
||||
size_t m_pos = 0;
|
||||
public:
|
||||
appender(Targ& t);
|
||||
template<class L, class R>
|
||||
|
||||
@ -22,12 +22,16 @@
|
||||
#include <utility> //forward, move, swap, etc
|
||||
#include <cstdlib> //memcpy
|
||||
#include <cstring> //strlen, strcpy
|
||||
#include <algorithm> //max
|
||||
|
||||
namespace raii{
|
||||
template<class Allocator>
|
||||
string_intermediary<Allocator>::string_intermediary(char* data, size_t len):
|
||||
string_base(data, len){}
|
||||
template<class Allocator>
|
||||
string_intermediary<Allocator>::string_intermediary(char* data, size_t len, size_t cap):
|
||||
string_base(data, len, cap){}
|
||||
template<class Allocator>
|
||||
string_intermediary<Allocator>::string_intermediary(const char* data, size_t len):
|
||||
string_base(reinterpret_cast<char*>(len ? Allocator::copy(data, len+1) : nullptr), len)
|
||||
{
|
||||
@ -37,8 +41,10 @@ namespace raii{
|
||||
string_intermediary<Allocator>::string_intermediary(const char* data):
|
||||
string_base(data ? strlen(data) : 0)
|
||||
{
|
||||
if(m_length)
|
||||
m_data = reinterpret_cast<char*>(Allocator::copy(data, m_length+1));
|
||||
if(m_cap){
|
||||
m_data = reinterpret_cast<char*>(Allocator::copy(data, m_cap+1));
|
||||
m_length = m_cap;
|
||||
}
|
||||
}
|
||||
template<class Allocator>
|
||||
string_intermediary<Allocator>::string_intermediary(size_t len):
|
||||
@ -46,18 +52,24 @@ namespace raii{
|
||||
{
|
||||
m_data[len] = 0;
|
||||
}
|
||||
template<class Allocator>
|
||||
string_intermediary<Allocator>::string_intermediary(size_t len, size_t cap):
|
||||
string_base(reinterpret_cast<char*>(len ? Allocator::allocate(len+1) : nullptr), len, cap)
|
||||
{
|
||||
m_data[len] = 0;
|
||||
}
|
||||
|
||||
//normal copy and move ctors
|
||||
template<class Allocator>
|
||||
string_intermediary<Allocator>::string_intermediary(const string_intermediary& b):
|
||||
string_base(reinterpret_cast<char*>(b.m_length ? Allocator::copy(b.m_data, b.m_length+1) : nullptr), b.m_length){}
|
||||
string_base(reinterpret_cast<char*>(b.m_length ? Allocator::copy(b.m_data, b.m_length+1) : nullptr), b.m_length, b.m_cap){}
|
||||
template<class Allocator>
|
||||
string_intermediary<Allocator>::string_intermediary(string_intermediary&& s):
|
||||
string_base(std::exchange(s.m_data, nullptr), s.m_length){}
|
||||
string_base(std::exchange(s.m_data, nullptr), s.m_length, s.m_cap){}
|
||||
|
||||
template<class Allocator>
|
||||
string_intermediary<Allocator>::string_intermediary(const string_base& b):
|
||||
string_base(reinterpret_cast<char*>(b.length() ? Allocator::copy(b.get(), b.length()+1) : nullptr), b.length()){}
|
||||
string_base(reinterpret_cast<char*>(b.length() ? Allocator::copy(b.get(), b.length()+1) : nullptr), b.length(), b.capacity()){}
|
||||
|
||||
//dtor
|
||||
template<class Allocator>
|
||||
@ -67,6 +79,11 @@ namespace raii{
|
||||
|
||||
template<class Allocator>
|
||||
string_intermediary<Allocator>& string_intermediary<Allocator>::operator=(const string_intermediary& s){
|
||||
if(s.m_length < m_length){
|
||||
memcpy(m_data, s.m_data, s.m_length+1);
|
||||
m_length = s.m_length;
|
||||
return *this;
|
||||
}
|
||||
string_intermediary tmp(s);
|
||||
return (*this = std::move(tmp));
|
||||
}
|
||||
@ -74,6 +91,7 @@ namespace raii{
|
||||
string_intermediary<Allocator>& string_intermediary<Allocator>::operator=(string_intermediary&& s){
|
||||
std::swap(m_data, s.m_data);
|
||||
m_length = s.m_length;
|
||||
m_cap = s.m_cap;
|
||||
return *this;
|
||||
}
|
||||
//Copy from c string
|
||||
@ -93,16 +111,18 @@ namespace raii{
|
||||
Allocator::free(m_data);
|
||||
m_data = val;
|
||||
m_length = val ? strlen(val) : 0;
|
||||
m_cap = m_length;
|
||||
}
|
||||
template<class Allocator>
|
||||
void string_intermediary<Allocator>::reset(char* val, size_t len){
|
||||
Allocator::free(m_data);
|
||||
m_data = val;
|
||||
m_length = len;
|
||||
m_cap = len;
|
||||
}
|
||||
template<class Allocator>
|
||||
bool string_intermediary<Allocator>::resize(size_t newsize){
|
||||
if(newsize < m_length)
|
||||
if(newsize < m_cap)
|
||||
return false;
|
||||
string_intermediary tmp(newsize);
|
||||
memcpy(tmp.get(), m_data, m_length);
|
||||
@ -112,23 +132,27 @@ namespace raii{
|
||||
}
|
||||
template<class Allocator>
|
||||
void string_intermediary<Allocator>::append(const char* data, size_t len){
|
||||
string_intermediary tmp(m_length + len);
|
||||
memcpy(tmp.m_data, m_data, m_length);
|
||||
memcpy(tmp.m_data+m_length, data, len);
|
||||
tmp[m_length+len] = 0;
|
||||
*this = std::move(tmp);
|
||||
if(len+m_length <= m_cap){
|
||||
memcpy(m_data+m_length, data, len);
|
||||
m_length += len;
|
||||
m_data[m_length] = 0;
|
||||
}else{
|
||||
string_intermediary tmp(std::max(m_length + len, m_cap*2));
|
||||
memcpy(tmp.m_data, m_data, m_length);
|
||||
memcpy(tmp.m_data+m_length, data, len);
|
||||
tmp.m_length = len+m_length;
|
||||
tmp[m_length+len] = 0;
|
||||
*this = std::move(tmp);
|
||||
}
|
||||
}
|
||||
template<class Allocator>
|
||||
void string_intermediary<Allocator>::append(const char* data){
|
||||
size_t len = strlen(data);
|
||||
resize(m_length+len);
|
||||
memcpy(m_data+m_length, data, len);
|
||||
m_length += len;
|
||||
m_data[m_length] = 0;
|
||||
if(data)
|
||||
append(data, strlen(data));
|
||||
}
|
||||
template<class Allocator>
|
||||
void string_intermediary<Allocator>::append(const string_base& s){
|
||||
append(s.get());
|
||||
append(s.get(), s.length());
|
||||
}
|
||||
|
||||
template<class Allocator>
|
||||
@ -136,15 +160,18 @@ namespace raii{
|
||||
if(!len){
|
||||
Allocator::free(m_data);
|
||||
m_length = 0;
|
||||
m_cap = 0;
|
||||
return *this;
|
||||
}
|
||||
if(len <= m_length){
|
||||
strcpy(m_data, s);
|
||||
}else{
|
||||
Allocator::free(m_data);
|
||||
m_data = reinterpret_cast<char*>(Allocator::copy(s, len+1));
|
||||
m_cap = std::max(len, m_cap*2);
|
||||
m_data = reinterpret_cast<char*>(Allocator::copy(s, m_cap+1));
|
||||
if(!m_data){
|
||||
m_length = 0;
|
||||
m_cap = 0;
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
@ -174,9 +201,8 @@ namespace raii{
|
||||
template<class Left, class Right>
|
||||
template<class Alloc>
|
||||
string_cat_expr<Left,Right>::operator string_intermediary<Alloc>(void){
|
||||
string_intermediary<Alloc> ret(length());
|
||||
for(size_t i = 0;i < length();++i)
|
||||
ret[i] = 'n';
|
||||
size_t len = length();
|
||||
string_intermediary<Alloc> ret(len);
|
||||
detail::appender<string_intermediary<Alloc>> append(ret);
|
||||
append(*this);
|
||||
return ret;
|
||||
@ -193,13 +219,13 @@ namespace raii{
|
||||
|
||||
template<size_t N>
|
||||
constexpr static_string::static_string(const char(&str)[N]):
|
||||
string_base(const_cast<char*>(str), N){}
|
||||
string_base(const_cast<char*>(str), N, N){}
|
||||
constexpr static_string::static_string(const char* str, size_t len):
|
||||
string_base(const_cast<char*>(str), len){}
|
||||
string_base(const_cast<char*>(str), len, len){}
|
||||
constexpr static_string::static_string(const static_string& s):
|
||||
string_base(s.m_data, s.m_length){}
|
||||
string_base(s.m_data, s.m_length, s.m_length){}
|
||||
constexpr static_string::static_string(static_string&& s):
|
||||
string_base(s.m_data, s.m_length){}
|
||||
string_base(s.m_data, s.m_length, s.m_length){}
|
||||
|
||||
namespace detail{
|
||||
template<class Targ>
|
||||
@ -212,8 +238,7 @@ namespace raii{
|
||||
}
|
||||
template<class Targ>
|
||||
void appender<Targ>::operator()(const string_base& str){
|
||||
memcpy(m_targ.get()+m_pos, str.get(), str.length());
|
||||
m_pos += str.length();
|
||||
m_targ.append(str.get(), str.length());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -114,7 +114,8 @@ namespace raii{
|
||||
|
||||
curl_string curler::encode(const char* data, int len){
|
||||
char* tmp = curl_easy_escape(m_curl, data, len);
|
||||
return curl_string(tmp, strlen(tmp));
|
||||
size_t esclen = strlen(tmp);
|
||||
return curl_string(tmp, esclen, esclen);
|
||||
}
|
||||
curl_string curler::decode(const char* data, int* outlen, int len){
|
||||
if(outlen)
|
||||
|
||||
@ -34,7 +34,7 @@ namespace raii{
|
||||
}
|
||||
|
||||
static_string::static_string(const char* c):
|
||||
string_base(const_cast<char*>(c), strlen(c)){}
|
||||
static_string(const_cast<char*>(c), strlen(c)){}
|
||||
static_string& static_string::operator=(const char* c){
|
||||
m_data = const_cast<char*>(c);
|
||||
m_length = strlen(c);
|
||||
|
||||
@ -87,7 +87,7 @@ namespace raii{
|
||||
char* tmp = reinterpret_cast<char*>(string::allocator_type::allocate(len+1));
|
||||
detail::_sanitize_json_copy(tmp, str);
|
||||
tmp[len] = 0;
|
||||
return string(tmp, len);
|
||||
return string(tmp, len, len);
|
||||
}
|
||||
|
||||
|
||||
@ -116,7 +116,7 @@ namespace raii{
|
||||
if(i == 0)
|
||||
return raii::string("0");
|
||||
int place = intlen(i);
|
||||
raii::string ret(place);
|
||||
raii::string ret(place, place);
|
||||
char* buf = ret.get();
|
||||
buf[place] = 0;
|
||||
while(i != 0){
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user