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