Implemented raii::binary to a usable level and polished the raii::string family a bit better.
This commit is contained in:
parent
57ed5d979f
commit
60b380f14e
@ -22,6 +22,7 @@
|
|||||||
#include "raii/curler.hpp"
|
#include "raii/curler.hpp"
|
||||||
#include "raii/string.hpp"
|
#include "raii/string.hpp"
|
||||||
#include "raii/rjp_string.hpp"
|
#include "raii/rjp_string.hpp"
|
||||||
|
#include "raii/binary.hpp"
|
||||||
#include "matrix/session_info.hpp"
|
#include "matrix/session_info.hpp"
|
||||||
#include <memory> //shared_ptr
|
#include <memory> //shared_ptr
|
||||||
|
|
||||||
@ -66,10 +67,12 @@ namespace matrix{
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
void _set_curl_useragent(const raii::string_base& useragent);
|
void _set_curl_useragent(const raii::string_base& useragent);
|
||||||
static size_t _post_reply_curl_callback(char* ptr, size_t size, size_t nmemb, void* userdata);
|
|
||||||
raii::string _get_curl(const raii::string_base& url)const;
|
raii::string _get_curl(const raii::string_base& url)const;
|
||||||
|
raii::binary _get_curl_binary(const raii::string_base& url)const;
|
||||||
raii::string _post_curl(const raii::string_base& postdata, const raii::string_base& url, const raii::curl_llist& header)const;
|
raii::string _post_curl(const raii::string_base& postdata, const raii::string_base& url, const raii::curl_llist& header)const;
|
||||||
|
raii::binary _post_curl_binary(const raii::string_base& postdata, const raii::string_base& url, const raii::curl_llist& header)const;
|
||||||
raii::string _put_curl(const raii::string_base& postdata, const raii::string_base& url, const raii::curl_llist& header)const;
|
raii::string _put_curl(const raii::string_base& postdata, const raii::string_base& url, const raii::curl_llist& header)const;
|
||||||
|
raii::binary _put_curl_binary(const raii::string_base& postdata, const raii::string_base& url, const raii::curl_llist& header)const;
|
||||||
raii::rjp_string _post_and_find(const raii::string_base& data, const raii::string_base& url, const raii::curl_llist& header, const raii::string_base& target)const;
|
raii::rjp_string _post_and_find(const raii::string_base& data, const raii::string_base& url, const raii::curl_llist& header, const raii::string_base& target)const;
|
||||||
raii::rjp_string _get_and_find(const raii::string_base& url, const raii::string_base& search)const;
|
raii::rjp_string _get_and_find(const raii::string_base& url, const raii::string_base& search)const;
|
||||||
raii::rjp_string _curl_reply_search(const raii::string_base& reply, const raii::string_base& search)const;
|
raii::rjp_string _curl_reply_search(const raii::string_base& reply, const raii::string_base& search)const;
|
||||||
|
|||||||
@ -21,12 +21,13 @@
|
|||||||
|
|
||||||
#include "raii/rjp_string.hpp"
|
#include "raii/rjp_string.hpp"
|
||||||
#include "raii/string.hpp"
|
#include "raii/string.hpp"
|
||||||
|
#include "raii/binary.hpp"
|
||||||
#include <cstdlib> //size_t
|
#include <cstdlib> //size_t
|
||||||
|
|
||||||
namespace matrix{
|
namespace matrix{
|
||||||
|
|
||||||
struct file_details{
|
struct file_details{
|
||||||
raii::string data;
|
raii::binary data;
|
||||||
raii::string name;
|
raii::string name;
|
||||||
};
|
};
|
||||||
struct image_details : public file_details{
|
struct image_details : public file_details{
|
||||||
|
|||||||
@ -4,29 +4,13 @@
|
|||||||
#include <cstdlib> //size_t
|
#include <cstdlib> //size_t
|
||||||
#include <utility> //move
|
#include <utility> //move
|
||||||
#include <cstring> //memcpy
|
#include <cstring> //memcpy
|
||||||
|
#include <algorithm> //max
|
||||||
|
#include <type_traits>
|
||||||
#include <new>
|
#include <new>
|
||||||
|
#include "raii/default_allocator.hpp"
|
||||||
|
|
||||||
namespace raii{
|
namespace raii{
|
||||||
|
|
||||||
namespace detail{
|
|
||||||
|
|
||||||
template<size_t Alignment>
|
|
||||||
struct default_binary_allocator{
|
|
||||||
static void free(void* data){
|
|
||||||
::operator delete(data);
|
|
||||||
}
|
|
||||||
static void* allocate(size_t size){
|
|
||||||
return ::operator new(size, std::align_val_t(Alignment));
|
|
||||||
}
|
|
||||||
static void* copy(const void* c, size_t size){
|
|
||||||
char* tmp = reinterpret_cast<char*>(allocate(size));
|
|
||||||
memcpy(tmp, c, size);
|
|
||||||
return tmp;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class binary_base
|
class binary_base
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
@ -34,19 +18,19 @@ namespace raii{
|
|||||||
size_t m_size = 0;
|
size_t m_size = 0;
|
||||||
size_t m_cap = 0;
|
size_t m_cap = 0;
|
||||||
public:
|
public:
|
||||||
|
protected:
|
||||||
constexpr binary_base(void) = default;
|
constexpr binary_base(void) = default;
|
||||||
constexpr binary_base(char* data, size_t size):
|
constexpr binary_base(char* data, size_t size):
|
||||||
m_data(data), m_size(size){}
|
m_data(data), m_size(size){}
|
||||||
protected:
|
|
||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
binary_base(const binary_base& b):
|
binary_base(const binary_base& b):
|
||||||
m_data(Allocator::copy(b.m_data, b.m_cap)),
|
m_data(Allocator::copy(b.m_data, b.m_cap)),
|
||||||
m_size(b.m_size),
|
m_size(b.m_size),
|
||||||
m_cap(b.m_cap){}
|
m_cap(b.m_cap){}
|
||||||
binary_base(binary_base&&);
|
binary_base(binary_base&&);
|
||||||
public:
|
|
||||||
~binary_base(void) = default;
|
~binary_base(void) = default;
|
||||||
|
|
||||||
|
public:
|
||||||
char* release(void);
|
char* release(void);
|
||||||
|
|
||||||
constexpr size_t size(void)const{return m_size;}
|
constexpr size_t size(void)const{return m_size;}
|
||||||
@ -59,30 +43,32 @@ namespace raii{
|
|||||||
const char& operator[](size_t i)const;
|
const char& operator[](size_t i)const;
|
||||||
|
|
||||||
};
|
};
|
||||||
template<class Allocator = detail::default_binary_allocator<0>>
|
template<class Allocator = detail::default_allocator<>>
|
||||||
class binary : public binary_base
|
class binary_data : public binary_base
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
constexpr binary(void) = default;
|
using allocator_type = Allocator;
|
||||||
binary(char* data, size_t size):
|
public:
|
||||||
binary_base(Allocator::copy(data, size), size){}
|
constexpr binary_data(void) = default;
|
||||||
binary(size_t size):
|
binary_data(char* data, size_t size):
|
||||||
binary_base(Allocator::allocate(size), size){}
|
binary_base(reinterpret_cast<char*>(Allocator::copy(data, size)), size){}
|
||||||
binary(const binary& b):
|
binary_data(size_t size):
|
||||||
|
binary_base(reinterpret_cast<char*>(Allocator::allocate(size)), size){}
|
||||||
|
binary_data(const binary_data& b):
|
||||||
binary_base(b)
|
binary_base(b)
|
||||||
{
|
{
|
||||||
m_data = Allocator::copy(b.m_data, b.m_cap);
|
m_data = Allocator::copy(b.m_data, b.m_cap);
|
||||||
}
|
}
|
||||||
binary(binary&& b):
|
binary_data(binary_data&& b):
|
||||||
binary_base(std::move(b)){}
|
binary_base(std::move(b)){}
|
||||||
~binary(void){
|
~binary_data(void){
|
||||||
Allocator::free(m_data);
|
Allocator::free(m_data);
|
||||||
}
|
}
|
||||||
binary& operator=(const binary& b){
|
binary_data& operator=(const binary_data& b){
|
||||||
binary tmp(b);
|
binary_data tmp(b);
|
||||||
return (*this = std::move(tmp));
|
return (*this = std::move(tmp));
|
||||||
}
|
}
|
||||||
binary& operator=(binary&& b){
|
binary_data& operator=(binary_data&& b){
|
||||||
m_size = b.m_size;
|
m_size = b.m_size;
|
||||||
m_cap = b.m_cap;
|
m_cap = b.m_cap;
|
||||||
std::swap(m_data, b.m_data);
|
std::swap(m_data, b.m_data);
|
||||||
@ -102,15 +88,59 @@ namespace raii{
|
|||||||
bool resize(size_t newsize){
|
bool resize(size_t newsize){
|
||||||
if(newsize < m_cap)
|
if(newsize < m_cap)
|
||||||
return false;
|
return false;
|
||||||
binary tmp(newsize);
|
binary_data tmp(newsize);
|
||||||
if(!tmp)
|
if(!tmp)
|
||||||
return false;
|
return false;
|
||||||
memcpy(tmp.m_data, m_data, m_size);
|
memcpy(tmp.m_data, m_data, m_size);
|
||||||
*this = std::move(tmp);
|
std::swap(m_data, tmp.m_data);
|
||||||
|
m_cap = tmp.m_cap;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
void append(const char* data, size_t len){
|
||||||
|
if(m_size + len > m_cap)
|
||||||
|
resize(std::max(m_cap*2, m_size+len));
|
||||||
|
memcpy(m_data+m_size, data, len);
|
||||||
|
m_size += len;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
using binary = binary_data<>;
|
||||||
|
|
||||||
|
namespace detail{
|
||||||
|
std::true_type is_binary_type_helper(binary_base);
|
||||||
|
std::false_type is_binary_type_helper(...);
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
struct is_binary_type{
|
||||||
|
constexpr static bool value = std::is_same<decltype(is_binary_type_helper(std::declval<typename std::decay<T>::type>())),std::true_type>::value;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class Left, class Right, typename std::enable_if<raii::detail::is_binary_type<Left>::value && raii::detail::is_binary_type<Right>::value,void>::type* = nullptr>
|
||||||
|
bool operator==(Left&& l, Right&& r){
|
||||||
|
return l && r && l.size() == r.size() && l.capacity() == r.capacity() && !memcmp(l.get(), r.get(), l.size());
|
||||||
|
}
|
||||||
|
template<class Left, class Right, typename std::enable_if<raii::detail::is_binary_type<Left>::value && raii::detail::is_binary_type<Right>::value,void>::type* = nullptr>
|
||||||
|
bool operator!=(Left&& l, Right&& r){
|
||||||
|
return !(std::forward<Left>(l) == std::forward<Right>(r));
|
||||||
|
}
|
||||||
|
template<class All, class Alr>
|
||||||
|
auto operator+(const raii::binary_data<All>& l, const raii::binary_data<Alr>& r){
|
||||||
|
raii::binary_data<All> retval(l.size() + r.size());
|
||||||
|
memcpy(retval.get(), l.get(), l.size());
|
||||||
|
memcpy(retval.get()+l.size(), r.get(), r.size());
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
template<class All, class Alr>
|
||||||
|
decltype(auto) operator+=(raii::binary_data<All>& l, const raii::binary_data<Alr>& r){
|
||||||
|
l.resize(l.size() + r.size());
|
||||||
|
memcpy(l.get()+l.size(), r.get(), r.size());
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef RAII_STRING_BASE_HPP
|
||||||
|
#include "raii/binary_string_conv.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
53
include/raii/binary_string_conv.hpp
Normal file
53
include/raii/binary_string_conv.hpp
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
#ifndef RAII_BINARY_STRING_CONV_HPP
|
||||||
|
#define RAII_BINARY_STRING_CONV_HPP
|
||||||
|
|
||||||
|
#include "raii/string.hpp"
|
||||||
|
#include "raii/binary.hpp"
|
||||||
|
|
||||||
|
namespace raii{
|
||||||
|
template<class Al, class Str = raii::string, typename std::enable_if<raii::detail::is_concrete_string<Str>::value,void>::type* = nullptr>
|
||||||
|
auto binary_to_string(const binary_data<Al>& b){
|
||||||
|
Str s(b.size()+1);
|
||||||
|
memcpy(s.get(), b.get(), b.size());
|
||||||
|
s[b.size()] = 0;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
template<class Al, class Str = raii::string, typename std::enable_if<raii::detail::is_concrete_string<Str>::value && std::is_same<typename std::decay<Al>::type,typename Str::allocator_type>::value,void>::type* = nullptr>
|
||||||
|
auto binary_to_string(binary_data<Al>&& b){
|
||||||
|
Str s;
|
||||||
|
s.reset(b.get(), b.size());
|
||||||
|
b.release();
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
template<class Bin = raii::binary, typename std::enable_if<raii::detail::is_binary_type<Bin>::value,void>::type* = nullptr>
|
||||||
|
auto string_to_binary(const string_base& s){
|
||||||
|
Bin b(s.length()+1);
|
||||||
|
b.append(s.get(), s.length()+1);
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
template<class Al, class Bin = raii::binary, typename std::enable_if<raii::detail::is_binary_type<Bin>::value && std::is_same<typename std::decay<Al>::type,typename Bin::allocator_type>::value,void>::type* = nullptr>
|
||||||
|
auto string_to_binary(string_intermediary<Al>&& s){
|
||||||
|
Bin b;
|
||||||
|
b.reset(s.get(), s.length()+1);
|
||||||
|
s.release();
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
template<class L, class R, typename std::enable_if<raii::detail::is_binary_type<L>::value && raii::detail::is_concrete_string<R>::value,void>::type* = nullptr>
|
||||||
|
decltype(auto) operator+=(L& l, R&& r){
|
||||||
|
l.append(r.get(), r.length()+1);
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
template<class L, class R, typename std::enable_if<raii::detail::is_binary_type<L>::value && raii::detail::is_string<R>::value && !raii::detail::is_concrete_string<R>::value,void>::type* = nullptr>
|
||||||
|
decltype(auto) operator+=(L& l, R&& r){
|
||||||
|
raii::string concrete = r;
|
||||||
|
return (l = concrete);
|
||||||
|
}
|
||||||
|
template<class L, class R, typename std::enable_if<raii::detail::is_concrete_string<L>::value && raii::detail::is_binary_type<R>::value,void>::type* = nullptr>
|
||||||
|
decltype(auto) operator+=(L& l, R&& r){
|
||||||
|
l.resize(l.length(), r.size() + 1);
|
||||||
|
memcpy(l.get()+l.length()+1, r.get(), r.size());
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
30
include/raii/default_allocator.hpp
Normal file
30
include/raii/default_allocator.hpp
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#ifndef RAII_DEFAULT_ALLOCATOR_HPP
|
||||||
|
#define RAII_DEFAULT_ALLOCATOR_HPP
|
||||||
|
|
||||||
|
#include <cstdlib> //size_t
|
||||||
|
#include <cstring> //memcpy
|
||||||
|
#include <new>
|
||||||
|
|
||||||
|
namespace raii{
|
||||||
|
|
||||||
|
namespace detail{
|
||||||
|
|
||||||
|
template<size_t Alignment = __STDCPP_DEFAULT_NEW_ALIGNMENT__>
|
||||||
|
struct default_allocator
|
||||||
|
{
|
||||||
|
static void free(void* data){
|
||||||
|
::operator delete(data, std::align_val_t{Alignment});
|
||||||
|
}
|
||||||
|
static void* allocate(size_t size){
|
||||||
|
return ::operator new(size, std::align_val_t{Alignment});
|
||||||
|
}
|
||||||
|
static void* copy(const void* c, size_t size){
|
||||||
|
char* tmp = reinterpret_cast<char*>(allocate(size));
|
||||||
|
memcpy(tmp, c, size);
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -51,11 +51,6 @@ namespace raii{
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
static_string& operator=(static_string&&) = delete;
|
static_string& operator=(static_string&&) = delete;
|
||||||
|
|
||||||
private:
|
|
||||||
char* _allocate(size_t)const override final{return nullptr;}
|
|
||||||
void _free(char*)const override final{}
|
|
||||||
char* _copy(const char*,size_t)const override final{return nullptr;}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -20,35 +20,12 @@
|
|||||||
#define RAII_STRING_HPP
|
#define RAII_STRING_HPP
|
||||||
|
|
||||||
#include "raii/string_base.hpp"
|
#include "raii/string_base.hpp"
|
||||||
|
#include "raii/default_allocator.hpp"
|
||||||
#include <new> //operator new/delete
|
|
||||||
#include <cstring> //memcpy
|
|
||||||
|
|
||||||
namespace raii{
|
namespace raii{
|
||||||
|
|
||||||
namespace detail{
|
|
||||||
|
|
||||||
class default_allocator
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static void free(void* data){
|
|
||||||
::operator delete(data);
|
|
||||||
}
|
|
||||||
static void* allocate(size_t size){
|
|
||||||
return ::operator new(size);
|
|
||||||
}
|
|
||||||
static void* copy(const void* c, size_t size){
|
|
||||||
char* tmp = reinterpret_cast<char*>(allocate(size));
|
|
||||||
memcpy(tmp, c, size-1);
|
|
||||||
tmp[size-1] = 0;
|
|
||||||
return tmp;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//new allocated string
|
//new allocated string
|
||||||
using string = string_intermediary<detail::default_allocator>;
|
using string = string_intermediary<detail::default_allocator<>>;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -64,72 +64,31 @@ namespace raii{
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
constexpr string_base(void) = default;
|
constexpr string_base(void) = default;
|
||||||
|
constexpr string_base(size_t len):
|
||||||
|
m_length(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_length(len), m_data(data){}
|
||||||
//Allocate without assigning
|
|
||||||
string_base(size_t len);
|
|
||||||
//Copy ctor (do nothing)
|
//Copy ctor (do nothing)
|
||||||
string_base(const string_base&){}
|
string_base(const string_base&){}
|
||||||
|
~string_base(void) = default;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual ~string_base(void) = default;
|
|
||||||
|
|
||||||
public:
|
|
||||||
//Copy from c string
|
|
||||||
string_base& operator=(const char* c);
|
|
||||||
//Copy from other string_base
|
|
||||||
string_base& operator=(const string_base& s);
|
|
||||||
//Move from other string base
|
|
||||||
template<class T, typename std::enable_if<detail::is_string<T>::value && !detail::is_concrete_string<T>::value,void>::type* = nullptr>
|
|
||||||
string_base& operator=(T&& t){
|
|
||||||
size_t len = t.length();
|
|
||||||
char* tmp;
|
|
||||||
if(len > m_length){
|
|
||||||
tmp = _allocate(len+1);
|
|
||||||
_assign(tmp, t.get(), 0);
|
|
||||||
_free(m_data);
|
|
||||||
}else{
|
|
||||||
tmp = m_data;
|
|
||||||
_assign(tmp, t.get(), 0);
|
|
||||||
}
|
|
||||||
m_data = tmp;
|
|
||||||
m_data[len] = 0;
|
|
||||||
m_length = len;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
//Replace managed pointer. Frees existing value
|
|
||||||
void reset(char* val = nullptr);
|
|
||||||
//Stop managing stored pointer. Does not free.
|
//Stop managing stored pointer. Does not free.
|
||||||
char* release(void);
|
char* release(void);
|
||||||
bool resize(size_t newsize);
|
|
||||||
|
|
||||||
//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;}
|
||||||
//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;}
|
||||||
operator char*(void);
|
constexpr operator char*(void){return m_data;}
|
||||||
operator const char*(void)const;
|
constexpr operator const char*(void)const{return m_data;}
|
||||||
//true if m_data is not null
|
//true if m_data is not null
|
||||||
operator bool(void)const;
|
constexpr operator bool(void)const{return m_data;}
|
||||||
|
|
||||||
char& operator[](size_t i);
|
char& operator[](size_t i);
|
||||||
const char& operator[](size_t i)const;
|
const char& operator[](size_t i)const;
|
||||||
|
|
||||||
protected:
|
|
||||||
string_base& _copy_string(const char* s, size_t len);
|
|
||||||
template<class Tup, size_t I = 0>
|
|
||||||
static void _assign(char* dest, Tup&& t, size_t offset){
|
|
||||||
memcpy(dest+offset, std::get<I>(t), std::get<I+1>(t));
|
|
||||||
if constexpr(I+2 < std::tuple_size<Tup>::value){
|
|
||||||
_assign<Tup,I+2>(dest, std::forward<Tup>(t), offset+std::get<I+1>(t));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
virtual char* _allocate(size_t)const = 0;
|
|
||||||
virtual void _free(char*)const = 0;
|
|
||||||
virtual char* _copy(const char*, size_t)const = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -181,14 +140,43 @@ namespace raii{
|
|||||||
Allocator::free(m_data);
|
Allocator::free(m_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
string_intermediary& operator=(const string_intermediary&) = default;
|
string_intermediary& operator=(const string_intermediary& s){
|
||||||
|
string_intermediary tmp(s);
|
||||||
|
std::swap(m_data, tmp.m_data);
|
||||||
|
m_length = tmp.m_length;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
string_intermediary& operator=(string_intermediary&& s){
|
string_intermediary& 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;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
using string_base::operator=;
|
//Copy from c string
|
||||||
|
string_intermediary& operator=(const char* c){
|
||||||
|
return _copy_string(c, strlen(c));
|
||||||
|
}
|
||||||
|
//Copy from other string_base
|
||||||
|
string_intermediary& operator=(const string_base& s){
|
||||||
|
return _copy_string(s.get(), s.length());
|
||||||
|
}
|
||||||
|
//Move from other string base
|
||||||
|
template<class T, typename std::enable_if<detail::is_string<T>::value && !detail::is_concrete_string<T>::value,void>::type* = nullptr>
|
||||||
|
string_base& operator=(T&& t){
|
||||||
|
size_t len = t.length();
|
||||||
|
char* tmp;
|
||||||
|
if(len > m_length){
|
||||||
|
tmp = reinterpret_cast<char*>(Allocator::allocate(len+1));
|
||||||
|
_assign(tmp, t.get(), 0);
|
||||||
|
Allocator::free(m_data);
|
||||||
|
}else{
|
||||||
|
tmp = m_data;
|
||||||
|
_assign(tmp, t.get(), 0);
|
||||||
|
}
|
||||||
|
m_data = tmp;
|
||||||
|
m_data[len] = 0;
|
||||||
|
m_length = len;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
string_intermediary operator+(const string_base& s)const{
|
string_intermediary operator+(const string_base& s)const{
|
||||||
string_intermediary tmp(reinterpret_cast<char*>(Allocator::allocate(m_length + s.length() + 1)), m_length+s.length());
|
string_intermediary tmp(reinterpret_cast<char*>(Allocator::allocate(m_length + s.length() + 1)), m_length+s.length());
|
||||||
@ -205,15 +193,67 @@ namespace raii{
|
|||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//Replace managed pointer. Frees existing value
|
||||||
|
void reset(char* val = nullptr){
|
||||||
|
Allocator::free(m_data);
|
||||||
|
m_data = val;
|
||||||
|
m_length = val ? strlen(val) : 0;
|
||||||
|
}
|
||||||
|
void reset(char* val, size_t len){
|
||||||
|
Allocator::free(m_data);
|
||||||
|
m_data = val;
|
||||||
|
m_length = len;
|
||||||
|
}
|
||||||
|
bool resize(size_t newsize){
|
||||||
|
if(newsize < m_length)
|
||||||
|
return false;
|
||||||
|
string_intermediary tmp(newsize);
|
||||||
|
memcpy(tmp.get(), m_data, m_length);
|
||||||
|
tmp[m_length] = 0;
|
||||||
|
*this = std::move(tmp);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
void 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);
|
||||||
|
}
|
||||||
|
void append(const char* data){
|
||||||
|
*this += data;
|
||||||
|
}
|
||||||
|
void append(const string_expr& s){
|
||||||
|
*this += s;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
char* _allocate(size_t len)const override final{
|
string_intermediary& _copy_string(const char* s, size_t len){
|
||||||
return reinterpret_cast<char*>(Allocator::allocate(len));
|
if(!len){
|
||||||
|
Allocator::free(m_data);
|
||||||
|
m_length = 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));
|
||||||
|
if(!m_data){
|
||||||
|
m_length = 0;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_length = len;
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
void _free(char* ptr)const override final{
|
template<class Tup, size_t I = 0>
|
||||||
Allocator::free(ptr);
|
static void _assign(char* dest, Tup&& t, size_t offset){
|
||||||
}
|
memcpy(dest+offset, std::get<I>(t), std::get<I+1>(t));
|
||||||
char* _copy(const char* ptr, size_t len)const override final{
|
if constexpr(I+2 < std::tuple_size<Tup>::value){
|
||||||
return reinterpret_cast<char*>(Allocator::copy(ptr, len));
|
_assign<Tup,I+2>(dest, std::forward<Tup>(t), offset+std::get<I+1>(t));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -338,4 +378,8 @@ decltype(auto) operator+=(Left& l, const char* r){
|
|||||||
return l = (l + r);
|
return l = (l + r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef RAII_BINARY_HPP
|
||||||
|
#include "raii/binary_string_conv.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -136,7 +136,7 @@ namespace matrix{
|
|||||||
}
|
}
|
||||||
m_curl.setopt(CURLOPT_HEADERFUNCTION, _thumbnail_header_callback);
|
m_curl.setopt(CURLOPT_HEADERFUNCTION, _thumbnail_header_callback);
|
||||||
m_curl.setopt(CURLOPT_HEADERDATA, &reply_header);
|
m_curl.setopt(CURLOPT_HEADERDATA, &reply_header);
|
||||||
i.data = _get_curl(m_ses->urls.file_thumbnail(m_ses->homeserver, info.fileurl, info.thumb_width, info.thumb_height, "crop"_ss));
|
i.data = _get_curl_binary(m_ses->urls.file_thumbnail(m_ses->homeserver, info.fileurl, info.thumb_width, info.thumb_height, "crop"_ss));
|
||||||
m_curl.setopt(CURLOPT_HEADERFUNCTION, NULL);
|
m_curl.setopt(CURLOPT_HEADERFUNCTION, NULL);
|
||||||
m_curl.setopt(CURLOPT_HEADERDATA, NULL);
|
m_curl.setopt(CURLOPT_HEADERDATA, NULL);
|
||||||
if(!i.data){
|
if(!i.data){
|
||||||
@ -175,10 +175,17 @@ namespace matrix{
|
|||||||
return to_copy;
|
return to_copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static size_t _post_reply_curl_callback(char* ptr, size_t size, size_t nmemb, void* userdata){
|
||||||
|
raii::string* data = reinterpret_cast<raii::string*>(userdata);
|
||||||
|
size_t oldlen = data->length();
|
||||||
|
data->resize(data->length() + (size*nmemb));
|
||||||
|
memcpy(data->get()+oldlen, ptr, size*nmemb);
|
||||||
|
return size*nmemb;
|
||||||
|
}
|
||||||
file_info client::_upload_file(const file_details& file, const raii::curl_llist& header)const{
|
file_info client::_upload_file(const file_details& file, const raii::curl_llist& header)const{
|
||||||
raii::string fileurl;
|
raii::string fileurl;
|
||||||
file_info retval = {};
|
file_info retval = {};
|
||||||
internal_upload_data upload_data = {file.data.get(), file.data.length()};
|
internal_upload_data upload_data = {file.data.get(), file.data.size()};
|
||||||
m_curl.postreq();
|
m_curl.postreq();
|
||||||
m_curl.setopt(CURLOPT_POSTFIELDS, NULL);
|
m_curl.setopt(CURLOPT_POSTFIELDS, NULL);
|
||||||
m_curl.setopt(CURLOPT_READFUNCTION, _upload_file_read_callback);
|
m_curl.setopt(CURLOPT_READFUNCTION, _upload_file_read_callback);
|
||||||
@ -206,7 +213,7 @@ namespace matrix{
|
|||||||
return {};
|
return {};
|
||||||
retval.fileurl = res.value;
|
retval.fileurl = res.value;
|
||||||
retval.filename = file.name;
|
retval.filename = file.name;
|
||||||
retval.filesize = file.data.length();
|
retval.filesize = file.data.size();
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -47,18 +47,24 @@ namespace matrix{
|
|||||||
void connection::_set_curl_useragent(const raii::string_base& useragent){
|
void connection::_set_curl_useragent(const raii::string_base& useragent){
|
||||||
m_curl.setuseragent(useragent);
|
m_curl.setuseragent(useragent);
|
||||||
}
|
}
|
||||||
size_t connection::_post_reply_curl_callback(char* ptr, size_t size, size_t nmemb, void* userdata){
|
static size_t _post_reply_curl_callback(char* ptr, size_t size, size_t nmemb, void* userdata){
|
||||||
raii::string* data = reinterpret_cast<raii::string*>(userdata);
|
raii::string* data = reinterpret_cast<raii::string*>(userdata);
|
||||||
size_t oldlen = data->length();
|
data->append(ptr, size*nmemb);
|
||||||
data->resize(data->length() + (size*nmemb));
|
|
||||||
memcpy(data->get()+oldlen, ptr, size*nmemb);
|
|
||||||
return size*nmemb;
|
return size*nmemb;
|
||||||
}
|
}
|
||||||
|
static size_t _binary_reply_curl_callback(char* ptr, size_t size, size_t nmemb, void* userdata){
|
||||||
|
raii::binary* data = reinterpret_cast<raii::binary*>(userdata);
|
||||||
|
data->append(ptr, size*nmemb);
|
||||||
|
return size*nmemb;
|
||||||
|
}
|
||||||
|
static void _get_curl_setup(const raii::string_base& url, raii::curler& curl){
|
||||||
|
curl.getreq();
|
||||||
|
curl.seturl(url);
|
||||||
|
curl.setheader(raii::curl_llist{});
|
||||||
|
}
|
||||||
raii::string connection::_get_curl(const raii::string_base& url)const{
|
raii::string connection::_get_curl(const raii::string_base& url)const{
|
||||||
raii::string reply;
|
raii::string reply;
|
||||||
m_curl.getreq();
|
_get_curl_setup(url, m_curl);
|
||||||
m_curl.seturl(url);
|
|
||||||
m_curl.setheader(raii::curl_llist{});
|
|
||||||
m_curl.setopt(CURLOPT_WRITEFUNCTION, _post_reply_curl_callback);
|
m_curl.setopt(CURLOPT_WRITEFUNCTION, _post_reply_curl_callback);
|
||||||
m_curl.setopt(CURLOPT_WRITEDATA, &reply);
|
m_curl.setopt(CURLOPT_WRITEDATA, &reply);
|
||||||
CURLcode res = m_curl.perform();
|
CURLcode res = m_curl.perform();
|
||||||
@ -66,13 +72,25 @@ namespace matrix{
|
|||||||
return {};
|
return {};
|
||||||
return reply;
|
return reply;
|
||||||
}
|
}
|
||||||
|
raii::binary connection::_get_curl_binary(const raii::string_base& url)const{
|
||||||
|
raii::binary reply;
|
||||||
|
_get_curl_setup(url, m_curl);
|
||||||
|
m_curl.setopt(CURLOPT_WRITEFUNCTION, _binary_reply_curl_callback);
|
||||||
|
m_curl.setopt(CURLOPT_WRITEDATA, &reply);
|
||||||
|
CURLcode res = m_curl.perform();
|
||||||
|
if(res != CURLE_OK)
|
||||||
|
return {};
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
static void _post_curl_setup(const raii::string_base& postdata, const raii::string_base& url, const raii::curl_llist& header, raii::curler& curl){
|
||||||
|
curl.postreq();
|
||||||
|
curl.setpostdata(postdata.get(), postdata.length());
|
||||||
|
curl.seturl(url);
|
||||||
|
curl.setheader(header);
|
||||||
|
}
|
||||||
raii::string connection::_post_curl(const raii::string_base& postdata, const raii::string_base& url, const raii::curl_llist& header)const{
|
raii::string connection::_post_curl(const raii::string_base& postdata, const raii::string_base& url, const raii::curl_llist& header)const{
|
||||||
raii::string reply;
|
raii::string reply;
|
||||||
m_curl.postreq();
|
_post_curl_setup(postdata, url, header, m_curl);
|
||||||
m_curl.setopt(CURLOPT_POSTFIELDS, postdata.get());
|
|
||||||
m_curl.setopt(CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t)postdata.length());
|
|
||||||
m_curl.seturl(url);
|
|
||||||
m_curl.setheader(header);
|
|
||||||
m_curl.setopt(CURLOPT_WRITEFUNCTION, _post_reply_curl_callback);
|
m_curl.setopt(CURLOPT_WRITEFUNCTION, _post_reply_curl_callback);
|
||||||
m_curl.setopt(CURLOPT_WRITEDATA, &reply);
|
m_curl.setopt(CURLOPT_WRITEDATA, &reply);
|
||||||
CURLcode res = m_curl.perform();
|
CURLcode res = m_curl.perform();
|
||||||
@ -80,6 +98,16 @@ namespace matrix{
|
|||||||
return {};
|
return {};
|
||||||
return reply;
|
return reply;
|
||||||
}
|
}
|
||||||
|
raii::binary connection::_post_curl_binary(const raii::string_base& postdata, const raii::string_base& url, const raii::curl_llist& header)const{
|
||||||
|
raii::binary reply;
|
||||||
|
_post_curl_setup(postdata, url, header, m_curl);
|
||||||
|
m_curl.setopt(CURLOPT_WRITEFUNCTION, _binary_reply_curl_callback);
|
||||||
|
m_curl.setopt(CURLOPT_WRITEDATA, &reply);
|
||||||
|
CURLcode res = m_curl.perform();
|
||||||
|
if(res != CURLE_OK)
|
||||||
|
return {};
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
struct put_data{
|
struct put_data{
|
||||||
const char* data;
|
const char* data;
|
||||||
size_t len;
|
size_t len;
|
||||||
@ -93,19 +121,35 @@ namespace matrix{
|
|||||||
src->data += to_copy;
|
src->data += to_copy;
|
||||||
return to_copy;
|
return to_copy;
|
||||||
}
|
}
|
||||||
|
static void _put_curl_setup(put_data& data, const raii::string_base& url, const raii::curl_llist& header, raii::curler& curl){
|
||||||
|
curl.putreq();
|
||||||
|
curl.setopt(CURLOPT_POSTFIELDS, data.data);
|
||||||
|
curl.setopt(CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t)data.len);
|
||||||
|
curl.seturl(url);
|
||||||
|
curl.setheader(header);
|
||||||
|
curl.setopt(CURLOPT_READFUNCTION, _put_read_curl_callback);
|
||||||
|
curl.setopt(CURLOPT_READDATA, &data);
|
||||||
|
curl.setopt(CURLOPT_INFILESIZE, (curl_off_t)data.len);
|
||||||
|
}
|
||||||
raii::string connection::_put_curl(const raii::string_base& putdata, const raii::string_base& url, const raii::curl_llist& header)const{
|
raii::string connection::_put_curl(const raii::string_base& putdata, const raii::string_base& url, const raii::curl_llist& header)const{
|
||||||
raii::string reply;
|
raii::string reply;
|
||||||
put_data data{putdata.get(), putdata.length()};
|
put_data data{putdata.get(), putdata.length()};
|
||||||
m_curl.putreq();
|
|
||||||
m_curl.setopt(CURLOPT_POSTFIELDS, putdata.get());
|
|
||||||
m_curl.setopt(CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t)putdata.length());
|
|
||||||
m_curl.seturl(url);
|
|
||||||
m_curl.setheader(header);
|
|
||||||
m_curl.setopt(CURLOPT_WRITEFUNCTION, _post_reply_curl_callback);
|
m_curl.setopt(CURLOPT_WRITEFUNCTION, _post_reply_curl_callback);
|
||||||
m_curl.setopt(CURLOPT_WRITEDATA, &reply);
|
m_curl.setopt(CURLOPT_WRITEDATA, &reply);
|
||||||
m_curl.setopt(CURLOPT_READFUNCTION, _put_read_curl_callback);
|
_put_curl_setup(data, url, header, m_curl);
|
||||||
m_curl.setopt(CURLOPT_READDATA, &data);
|
CURLcode res = m_curl.perform();
|
||||||
m_curl.setopt(CURLOPT_INFILESIZE, (curl_off_t)data.len);
|
m_curl.setopt(CURLOPT_READDATA, NULL);
|
||||||
|
m_curl.setopt(CURLOPT_READFUNCTION, NULL);
|
||||||
|
if(res != CURLE_OK)
|
||||||
|
return {};
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
raii::binary connection::_put_curl_binary(const raii::string_base& putdata, const raii::string_base& url, const raii::curl_llist& header)const{
|
||||||
|
raii::binary reply;
|
||||||
|
put_data data{putdata.get(), putdata.length()};
|
||||||
|
m_curl.setopt(CURLOPT_WRITEFUNCTION, _binary_reply_curl_callback);
|
||||||
|
m_curl.setopt(CURLOPT_WRITEDATA, &reply);
|
||||||
|
_put_curl_setup(data, url, header, m_curl);
|
||||||
CURLcode res = m_curl.perform();
|
CURLcode res = m_curl.perform();
|
||||||
m_curl.setopt(CURLOPT_READDATA, NULL);
|
m_curl.setopt(CURLOPT_READDATA, NULL);
|
||||||
m_curl.setopt(CURLOPT_READFUNCTION, NULL);
|
m_curl.setopt(CURLOPT_READFUNCTION, NULL);
|
||||||
|
|||||||
@ -113,21 +113,8 @@ namespace matrix{
|
|||||||
_do_login(a.name, a.pass);
|
_do_login(a.name, a.pass);
|
||||||
}
|
}
|
||||||
raii::string session::_request_access_token(const raii::string_base& name, const raii::string_base& pass, const raii::string_base& loginurl)const{
|
raii::string session::_request_access_token(const raii::string_base& name, const raii::string_base& pass, const raii::string_base& loginurl)const{
|
||||||
CURLcode result;
|
|
||||||
raii::string postdata("{\"type\":\"m.login.password\", \"user\":\"" + raii::json_escape(name) + "\", \"password\":\"" + raii::json_escape(pass) + "\"}");
|
raii::string postdata("{\"type\":\"m.login.password\", \"user\":\"" + raii::json_escape(name) + "\", \"password\":\"" + raii::json_escape(pass) + "\"}");
|
||||||
raii::string reply;
|
raii::string reply = _post_curl(postdata, loginurl, raii::curl_llist{});
|
||||||
|
|
||||||
m_curl.seturl(loginurl);
|
|
||||||
m_curl.setpostdata(postdata);
|
|
||||||
m_curl.postreq();
|
|
||||||
m_curl.setopt(CURLOPT_WRITEFUNCTION, client::_post_reply_curl_callback);
|
|
||||||
m_curl.setopt(CURLOPT_WRITEDATA, &reply);
|
|
||||||
|
|
||||||
result = m_curl.perform();
|
|
||||||
|
|
||||||
if(result != CURLE_OK)
|
|
||||||
return {};
|
|
||||||
|
|
||||||
return reply;
|
return reply;
|
||||||
}
|
}
|
||||||
raii::rjp_string session::_get_userid(void){
|
raii::rjp_string session::_get_userid(void){
|
||||||
|
|||||||
@ -28,8 +28,7 @@ namespace raii{
|
|||||||
}
|
}
|
||||||
void* rjp_allocator::copy(const void* data, size_t len){
|
void* rjp_allocator::copy(const void* data, size_t len){
|
||||||
char* tmp = reinterpret_cast<char*>(allocate(len));
|
char* tmp = reinterpret_cast<char*>(allocate(len));
|
||||||
memcpy(tmp, data, len-1);
|
memcpy(tmp, data, len);
|
||||||
tmp[len-1] = 0;
|
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,70 +24,14 @@
|
|||||||
#include <cstring> //strcpy, strlen
|
#include <cstring> //strcpy, strlen
|
||||||
|
|
||||||
namespace raii{
|
namespace raii{
|
||||||
string_base::string_base(size_t len):
|
|
||||||
m_length(len),
|
|
||||||
m_data(nullptr){}
|
|
||||||
string_base& string_base::operator=(const char* c){
|
|
||||||
return _copy_string(c, strlen(c));
|
|
||||||
}
|
|
||||||
string_base& string_base::operator=(const string_base& s){
|
|
||||||
return _copy_string(s.m_data, s.m_length);
|
|
||||||
}
|
|
||||||
void string_base::reset(char* val){
|
|
||||||
_free(m_data);
|
|
||||||
m_data = val;
|
|
||||||
m_length = val ? strlen(val) : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
string_base::operator bool(void)const{
|
|
||||||
return m_data;
|
|
||||||
}
|
|
||||||
string_base::operator char*(void){
|
|
||||||
return m_data;
|
|
||||||
}
|
|
||||||
string_base::operator const char*(void)const{
|
|
||||||
return m_data;
|
|
||||||
}
|
|
||||||
char* string_base::release(void){
|
char* string_base::release(void){
|
||||||
return std::exchange(m_data, nullptr);
|
return std::exchange(m_data, nullptr);
|
||||||
}
|
}
|
||||||
bool string_base::resize(size_t newsize){
|
|
||||||
if(newsize < m_length)
|
|
||||||
return false;
|
|
||||||
char* newbuf = static_cast<char*>(_allocate(newsize+1));
|
|
||||||
if(!newbuf) return false;
|
|
||||||
memset(newbuf, 0, newsize+1);
|
|
||||||
memcpy(newbuf, m_data, m_length);
|
|
||||||
newbuf[m_length] = 0;
|
|
||||||
m_length = newsize;
|
|
||||||
_free(m_data);
|
|
||||||
m_data = newbuf;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
char& string_base::operator[](size_t i){
|
char& string_base::operator[](size_t i){
|
||||||
return m_data[i];
|
return m_data[i];
|
||||||
}
|
}
|
||||||
const char& string_base::operator[](size_t i)const{
|
const char& string_base::operator[](size_t i)const{
|
||||||
return m_data[i];
|
return m_data[i];
|
||||||
}
|
}
|
||||||
string_base& string_base::_copy_string(const char* s, size_t len){
|
|
||||||
if(!len){
|
|
||||||
_free(m_data);
|
|
||||||
m_length = 0;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
if(len <= m_length){
|
|
||||||
strcpy(m_data, s);
|
|
||||||
}else{
|
|
||||||
_free(m_data);
|
|
||||||
m_data = _copy(s, len+1);
|
|
||||||
if(!m_data){
|
|
||||||
m_length = 0;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m_length = len;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user