27
Классические строки в C++ Антон Нонко

Антон Нонко, Классические строки в C++

Embed Size (px)

Citation preview

Page 1: Антон Нонко, Классические строки в C++

Классическиестроки в C++

Антон Нонко

Page 2: Антон Нонко, Классические строки в C++

namespace curl {

class easy { CURL* m_curl;

public: easy() : m_curl{curl_easy_init()} { if(!m_curl) throw std::runtime_error{"curl_easy_init failed"}; };

easy(easy const&) = delete; easy& operator = (easy const&) = delete;

~easy() noexcept {curl_easy_cleanup(m_curl);};

void set_url(char const* url) { if(curl_easy_setopt(m_curl, CURLOPT_URL, url) != CURLE_OK) throw std::runtime_error("curl_easy_setopt failed"); };

template<class CharTraits, class Allocator> void set_url(std::basic_string<char, CharTraits, Allocator> const& url) { set_url(url.c_str()); };

void perform() { if(curl_easy_perform(m_curl) != CURLE_OK) throw std::runtime_error{"curl_easy_perform failed"}; };};

};

Page 3: Антон Нонко, Классические строки в C++

namespace curl {

class easy { CURL* m_curl;

public: easy() : m_curl{curl_easy_init()} { if(!m_curl) throw std::runtime_error{"curl_easy_init failed"}; };

easy(easy const&) = delete; easy& operator = (easy const&) = delete;

~easy() noexcept {curl_easy_cleanup(m_curl);};

void set_url(char const* url) { if(curl_easy_setopt(m_curl, CURLOPT_URL, url) != CURLE_OK) throw std::runtime_error("curl_easy_setopt failed"); };

template<class CharTraits, class Allocator> void set_url(std::basic_string<char, CharTraits, Allocator> const& url) { set_url(url.c_str()); };

void perform() { if(curl_easy_perform(m_curl) != CURLE_OK) throw std::runtime_error{"curl_easy_perform failed"}; };};

};

Page 4: Антон Нонко, Классические строки в C++

void set_header(char const* name, char const* value);

Page 5: Антон Нонко, Классические строки в C++

void set_header(char const* name, char const* value);

template<class CT, class A> void set_header( std::basic_string<char, CT, A> const& name, char const* value );

Page 6: Антон Нонко, Классические строки в C++

void set_header(char const* name, char const* value);

template<class CT, class A> void set_header( std::basic_string<char, CT, A> const& name, char const* value );

template<class CT, class A> void set_header( char const* name, std::basic_string<char, CT, A> const& value );

Page 7: Антон Нонко, Классические строки в C++

void set_header(char const* name, char const* value);

template<class CT, class A> void set_header( std::basic_string<char, CT, A> const& name, char const* value );

template<class CT, class A> void set_header( char const* name, std::basic_string<char, CT, A> const& value );

template<class CT1, class A1, class CT2, class A2> void set_header( std::basic_string<char, CT1, A1> const& name, std::basic_string<char, CT2, A2> const& value );

Page 8: Антон Нонко, Классические строки в C++

namespace curl {

class easy { CURL* m_curl;

public: easy() : m_curl{curl_easy_init()} { if(!m_curl) throw std::runtime_error{"curl_easy_init failed"}; };

easy(easy const&) = delete; easy& operator = (easy const&) = delete;

~easy() noexcept {curl_easy_cleanup(m_curl);};

void set_url(char const* url) { if(curl_easy_setopt(m_curl, CURLOPT_URL, url) != CURLE_OK) throw std::runtime_error("curl_easy_setopt failed"); };

template<class CharTraits, class Allocator> void set_url(std::basic_string<char, CharTraits, Allocator> const& url) { set_url(url.c_str()); };

void perform() { if(curl_easy_perform(m_curl) != CURLE_OK) throw std::runtime_error{"curl_easy_perform failed"}; };};

};

Page 9: Антон Нонко, Классические строки в C++

namespace curl {

class easy { CURL* m_curl;

public: easy() : m_curl{curl_easy_init()} { if(!m_curl) throw std::runtime_error{"curl_easy_init failed"}; };

easy(easy const&) = delete; easy& operator = (easy const&) = delete;

~easy() noexcept {curl_easy_cleanup(m_curl);};

void set_url(boost::string_ref const url) { if(curl_easy_setopt(m_curl, CURLOPT_URL, url.data()) != CURLE_OK) throw std::runtime_error("curl_easy_setopt failed"); };

void perform() { if(curl_easy_perform(m_curl) != CURLE_OK) throw std::runtime_error{"curl_easy_perform failed"}; };};

};

Page 10: Антон Нонко, Классические строки в C++

namespace curl {

class easy { CURL* m_curl;

public: easy() : m_curl{curl_easy_init()} { if(!m_curl) throw std::runtime_error{"curl_easy_init failed"}; };

easy(easy const&) = delete; easy& operator = (easy const&) = delete;

~easy() noexcept {curl_easy_cleanup(m_curl);};

void set_url(boost::string_ref const url) { // O(N) if(curl_easy_setopt(m_curl, CURLOPT_URL, url.data()) != CURLE_OK) throw std::runtime_error("curl_easy_setopt failed"); };

void perform() { if(curl_easy_perform(m_curl) != CURLE_OK) throw std::runtime_error{"curl_easy_perform failed"}; };};

};

Page 11: Антон Нонко, Классические строки в C++

namespace curl {

class easy { CURL* m_curl;

public: easy() : m_curl{curl_easy_init()} { if(!m_curl) throw std::runtime_error{"curl_easy_init failed"}; };

easy(easy const&) = delete; easy& operator = (easy const&) = delete;

~easy() noexcept {curl_easy_cleanup(m_curl);};

void set_url(boost::string_ref const url) { if(curl_easy_setopt(m_curl, CURLOPT_URL, url.data()) != CURLE_OK) throw std::runtime_error("curl_easy_setopt failed"); };

void perform() { if(curl_easy_perform(m_curl) != CURLE_OK) throw std::runtime_error{"curl_easy_perform failed"}; };};

};

Page 12: Антон Нонко, Классические строки в C++

namespace curl {

class easy { CURL* m_curl;

public: easy() : m_curl{curl_easy_init()} { if(!m_curl) throw std::runtime_error{"curl_easy_init failed"}; };

easy(easy const&) = delete; easy& operator = (easy const&) = delete;

~easy() noexcept {curl_easy_cleanup(m_curl);};

void set_url(boost::string_ref const url) { if(curl_easy_setopt(m_curl, CURLOPT_URL, url.to_string().data()) != CURLE_OK) throw std::runtime_error("curl_easy_setopt failed"); };

void perform() { if(curl_easy_perform(m_curl) != CURLE_OK) throw std::runtime_error{"curl_easy_perform failed"}; };};

};

Page 13: Антон Нонко, Классические строки в C++

template< class Char, class CharTraits = std::char_traits<typename std::remove_const<Char>::type>>class basic_c_string { Char* m_chars;

enum{is_const = std::is_const<Char>::value};

public: basic_c_string(Char* chars) : m_chars{chars} {};

template<class Allocator, class = typename std::enable_if<is_const>::type> basic_c_string( std::basic_string< typename CharTraits::char_type, CharTraits, Allocator > const& string ) : m_chars{string.c_str()} {};

Char const* c_str() const {return m_chars;};};

using const_c_string = basic_c_string<const char>;

Page 14: Антон Нонко, Классические строки в C++

namespace curl {

class easy { CURL* m_curl;

public: easy() : m_curl{curl_easy_init()} { if(!m_curl) throw std::runtime_error{"curl_easy_init failed"}; };

easy(easy const&) = delete; easy& operator = (easy const&) = delete;

~easy() noexcept {curl_easy_cleanup(m_curl);};

template<class CharTraits> void set_url(basic_c_string<char, CharTraits> url) { if(curl_easy_setopt(m_curl, CURLOPT_URL, url.c_str()) != CURLE_OK) throw std::runtime_error{"curl_easy_setopt failed"}; };

void perform() { if(curl_easy_perform(m_curl) != CURLE_OK) throw std::runtime_error{"curl_easy_perform failed"}; };};

};

Page 15: Антон Нонко, Классические строки в C++

namespace curl {

class easy { //...

char const* effective_url() const { char* url; if(curl_easy_getinfo(m_curl, CURLINFO_EFFECTIVE_URL, &url) != CURLE_OK) throw std::runtime_error{"curl_easy_getinfo failed"};

return url; };

//...

};

};

Page 16: Антон Нонко, Классические строки в C++

namespace curl {

class easy { //...

char const* effective_url() const { char* url; if(curl_easy_getinfo(m_curl, CURLINFO_EFFECTIVE_URL, &url) != CURLE_OK) throw std::runtime_error{"curl_easy_getinfo failed"};

return url; };

//...

};

};

int main(int argc, char** argv) { if(argc != 2) return EXIT_FAILURE;

auto url = argv[1];

curl::easy easy; easy.set_url(url); easy.perform();

if(easy.effective_url() == url) { std::cout << "no redirect" << std::endl; };};

Page 17: Антон Нонко, Классические строки в C++

namespace curl {

class easy { //...

char const* effective_url() const { char* url; if(curl_easy_getinfo(m_curl, CURLINFO_EFFECTIVE_URL, &url) != CURLE_OK) throw std::runtime_error{"curl_easy_getinfo failed"};

return url; };

//...

};

};

int main(int argc, char** argv) { if(argc != 2) return EXIT_FAILURE;

auto url = argv[1];

curl::easy easy; easy.set_url(url); easy.perform();

if(easy.effective_url() == url) { std::cout << "no redirect" << std::endl; };};

Page 18: Антон Нонко, Классические строки в C++

template< class Char, class CharTraits = std::char_traits<typename std::remove_const<Char>::type>>class basic_c_string { //...

public: int compare(basic_c_string<Char const, CharTraits> that) { auto this_length = CharTraits::length(c_str()); auto that_length = CharTraits::length(that.c_str());

auto result = CharTraits::compare( c_str(), that.c_str(), std::min(this_length, that_length) );

return result ? result : this_length - that_length; };

friend bool operator == ( this_type this_, basic_c_string<Char const, CharTraits> that ) {return !this_.compare(that);};

//...

};

Page 19: Антон Нонко, Классические строки в C++

namespace curl {

class easy { //...

char const* effective_url() const { char* url; if(curl_easy_getinfo(m_curl, CURLINFO_EFFECTIVE_URL, &url) != CURLE_OK) throw std::runtime_error{"curl_easy_getinfo failed"};

return url; };

//...

};

};

int main(int argc, char** argv) { if(argc != 2) return EXIT_FAILURE;

auto url = argv[1];

curl::easy easy; easy.set_url(url); easy.perform();

if(easy.effective_url() == url) { std::cout << "no redirect" << std::endl; };};

Page 20: Антон Нонко, Классические строки в C++

namespace curl {

class easy { //...

const_c_string effective_url() const { char const* url; if(curl_easy_getinfo(m_curl, CURLINFO_EFFECTIVE_URL, &url) != CURLE_OK) throw std::runtime_error{"curl_easy_getinfo failed"};

return {url}; };

//...

};

};

int main(int argc, char** argv) { if(argc != 2) return EXIT_FAILURE;

auto url = argv[1];

curl::easy easy; easy.set_url(url); easy.perform();

if(easy.effective_url() == url) { std::cout << "no redirect" << std::endl; };};

Page 21: Антон Нонко, Классические строки в C++

namespace curl {

class easy { //...

std::string escape(const_c_string string) { char* escaped = curl_easy_escape(m_curl, string.c_str(), 0); if(!escaped) throw std::runtime_error{"curl_easy_escape_failed"}; try { std::string result = escaped; curl_free(escaped); return result; } catch(...) { curl_free(escaped); throw; }; };

std::string unescape(const_c_string string);

//...

};

};

Page 22: Антон Нонко, Классические строки в C++

namespace curl {

class easy { //...

struct deleter { void operator () (void* p) noexcept {if(p) curl_free(p);}; };

std::string escape(const_c_string string) { std::unique_ptr<char, deleter> escaped{curl_easy_escape(m_curl, string.c_str(), 0)};

if(!escaped) throw std::runtime_error{"curl_easy_escape_failed"}; return {escaped.get()}; };

std::string unescape(const_c_string string);

//...

};

};

Page 23: Антон Нонко, Классические строки в C++

template< class Char, class CharTraits = std::char_traits<typename std::remove_const<Char>::type>, class Storage = Char*>class basic_c_string { Storage m_chars;

enum{is_const = std::is_const<Char>::value}; enum{is_raw = std::is_pointer<Storage>::value};

public: basic_c_string(Char* chars) : m_chars{chars} {};

template< class Allocator, class = typename std::enable_if<is_const && is_raw>::type > basic_c_string( std::basic_string< typename CharTraits::char_type, CharTraits, Allocator > const& string ) : m_chars{string.c_str()} {};

private: template<class C> static C const* get(C* s) {return s;}; template<class C> static C const* get(C const* s) {return s;}; template<class S> static Char const* get(S const& s) {return s.get();};

public: Char const* c_str() const {return get(m_chars);}; //...};

Page 24: Антон Нонко, Классические строки в C++

namespace curl {

class easy { //...

using unique_c_string = basic_c_string<char, std::char_traits<char>, std::unique_ptr<char, deleter>>;

unique_c_string escape(const_c_string string) { char* escaped = curl_easy_escape(m_curl, string.c_str(), 0);

if(!escaped) throw std::runtime_error{"curl_easy_escape_failed"};

return escaped; };

//...

};

};

Page 25: Антон Нонко, Классические строки в C++

template<class Derived, class Char, class CharTraits>class c_string_facade { typedef c_string_facade<Derived, Char, CharTraits> this_type;

public: Char const* c_str() const {return static_cast<Derived const*>(this)->data();};

int compare(basic_c_string<Char const, CharTraits> that) { auto this_length = CharTraits::length(c_str()); auto that_length = CharTraits::length(that.c_str());

auto result = CharTraits::compare( c_str(), that.c_str(), std::min(this_length, that_length) );

return result ? result : this_length - that_length; };

friend bool operator == ( this_type this_, basic_c_string<Char const, CharTraits> that ) { return !this_.compare(that); };

//... };

Page 26: Антон Нонко, Классические строки в C++

template< class Char, class CharTraits = std::char_traits<typename std::remove_const<Char>::type>>class basic_c_string : public c_string_facade<basic_c_string<Char, CharTraits>, Char, CharTraits>{ Char* m_chars; Char* data(); Char const* data() const;

public: basic_c_string(Char* chars); template< class Allocator, class = typename std::enable_if<std::is_const<Char>::value>::type > basic_c_string( std::basic_string< typename CharTraits::char_type, CharTraits, Allocator > const& string );};

Page 27: Антон Нонко, Классические строки в C++

template<class Char, class CharTraits = std::char_traits<Char>>class basic_unique_c_string : public c_string_facade< basic_unique_c_string<Char, CharTraits>, Char, CharTraits >{ std::unique_ptr<Char> m_chars; //...};

template<class Char, class CharTraits = std::char_traits<Char>>class basic_shared_c_string : public c_string_facade< basic_unique_c_string<Char, CharTraits>, Char, CharTraits >{ std::shared_ptr<Char> m_chars; //...};