#pragma once #ifndef _SHARED_STRING_H_INCLUDED_ #define _SHARED_STRING_H_INCLUDED_ /** * basic_shared_string * * Copyright (c) 2015 Scott Schanel http://github.com/sschanel/shared_string * * License: MIT License * * Uses std::shared_ptr internally to keep memory allocation to a minimum. * This is a boost-less implementation that does not use boost::flyweights. * That means that if you try hard enough you can outsmart it and do * things very ineffeciently. * * But! If you embrace it, you get all the same methods that basic_string * has (as of C++11), and you get a true shared string and it's thread-safe. * Missing methods from basic_string: reserve(), capacity(), shrink_to_fit(). * append(), assign(), insert(), erase(), replace(), push_front(), push_back(), * all methods that return a non-const iterator. Almost all of the implemented * methods are thin wrappers around the shared string. * * If you need those methods, make a copy of the internal string by calling * str() and work on that temporary string. * * You still get operator=(). And clear(). * * * */ #include #include #include template , class Allocator = std::allocator < CharT > > class basic_shared_string { public: typedef std::basic_string string_type; typedef typename string_type::const_iterator const_iterator; typedef typename string_type::const_reverse_iterator const_reverse_iterator; typedef typename string_type::size_type size_type; private: std::shared_ptr string_; void replace_contents(string_type&& newString) { string_ = std::make_shared(std::move(newString)); } public: static const size_type npos = (size_t)-1; const string_type& str() const { static const string_type empty; if (string_.get() != nullptr) { return *(string_.get()); } return empty; } operator const string_type&() { return str(); } basic_shared_string() { } basic_shared_string(const CharT * s) { replace_contents(string_type(s)); } basic_shared_string(const string_type& s) { replace_contents(string_type(s)); } basic_shared_string(string_type&& s) { replace_contents(std::move(s)); } basic_shared_string(const basic_shared_string& s) { string_ = s.string_; } void clear() { string_ = nullptr; } basic_shared_string& operator=(const basic_shared_string& s) { string_ = s.string_; return *this; } basic_shared_string& operator=(const string_type& str) { replace_contents(string_type(str)); return *this; } basic_shared_string& operator=(string_type&& str) { replace_contents(std::move(str)); return *this; } basic_shared_string& operator=(const CharT* s) { replace_contents(string_type(s)); return *this; } basic_shared_string& operator=(CharT ch) { replace_contents(string_type(ch)); return *this; } basic_shared_string& operator=(std::initializer_list ilist) { replace_contents(string_type(ilist)); return *this; } void swap(basic_shared_string& rhs) { this->string_.swap(rhs.string_); } CharT at(size_type pos) const { return str().at(pos); } CharT operator[](size_type pos) const { return str()[pos]; } CharT front() const { return str().front(); } CharT back() const { return str().back(); } const CharT * c_str() const { return str().c_str(); } const_iterator begin() const { return str().begin(); } const_iterator cbegin() const { return str().cbegin(); } const_iterator end() const { return str().end(); } const_iterator cend() const { return str().end(); } const_reverse_iterator rbegin() const { return str().rbegin(); } const_reverse_iterator crbegin() const { return str().crbegin(); } const_reverse_iterator rend() const { return str().rend(); } const_reverse_iterator crend() const { return str().crend(); } bool empty() const { return str().empty(); } size_t size() const { return str().size(); } size_t length() const { return str().length(); } size_t max_size() const { return str().max_size(); } size_t capacity() const { return str().capacity(); } int compare(const string_type& rhs) const { return str().compare(rhs); } int compare(const basic_shared_string& rhs) const { return str().compare(rhs.str()); } int compare(size_type pos1, size_type count1, const string_type& str) const { return str().compare(pos1, count1, str); } int compare(const CharT* s) const { return str().compare(s); } int compare(size_type pos1, size_type count1, const CharT* s) const { return str().compare(pos1, count1, s); } int compare( size_type pos1, size_type count1, const CharT* s, size_type count2) const { return str().compare(pos1, count1, s, count2); } basic_shared_string substr( size_type pos = 0, size_type count = npos) const { if (pos == 0) { if (count == npos) { return *this; } else if (count >= str().size()) { return *this; } } return basic_shared_string(str().substr(pos, count)); } size_type copy( CharT* dest, size_type count, size_type pos = 0) const { return str().copy(dest, count, pos); } size_type find(const string_type& str, size_type pos = 0) const { return str().find(str, pos); } size_type find(const CharT* s, size_type pos, size_type count) const { return str().find(s, pos, count); } size_type find(const CharT* s, size_type pos = 0) const { return str().find(s, pos); } size_type find(CharT ch, size_type pos = 0) const { return str().find(ch, pos); } size_type rfind(const string_type& str, size_type pos = npos) const { return str().rfind(str, pos); } size_type rfind(const CharT* s, size_type pos, size_type count) const { return str().rfind(s, pos, count); } size_type rfind(const CharT* s, size_type pos = npos) const { return str().rfind(s, pos); } size_type rfind(CharT ch, size_type pos = npos) const { return str().rfind(ch, pos); } size_type find_first_of(const string_type& str, size_type pos = 0) const { return str().find_first_of(str, pos); } size_type find_first_of(const CharT* s, size_type pos, size_type count) const { return str().find_first_of(s, pos, count); } size_type find_first_of(const CharT* s, size_type pos = 0) const { return str().find_first_of(s, pos); } size_type find_first_of(CharT ch, size_type pos = 0) const { return str().find_first_of(ch, pos); } size_type find_first_not_of(const string_type& str, size_type pos = 0) const { return str().find_first_not_of(str, pos); } size_type find_first_not_of(const CharT* s, size_type pos, size_type count) const { return str().find_first_not_of(s, pos, count); } size_type find_first_not_of(const CharT* s, size_type pos = 0) const { return str().find_first_not_of(s, pos); } size_type find_first_not_of(CharT ch, size_type pos = 0) const { return str().find_first_not_of(ch, pos); } size_type find_last_of(const string_type& str, size_type pos = npos) const { return str().find_last_of(str, pos); } size_type find_last_of(const CharT* s, size_type pos, size_type count) const { return str().find_last_of(s, pos, count); } size_type find_last_of(const CharT* s, size_type pos = npos) const { return str().find_last_of(s, pos); } size_type find_last_of(CharT ch, size_type pos = npos) const { return str().find_last_of(ch, pos); } size_type find_last_not_of(const string_type& str, size_type pos = npos) const { return str().find_last_not_of(str, pos); } size_type find_last_not_of(const CharT* s, size_type pos, size_type count) const { return str().find_last_not_of(s, pos, count); } size_type find_last_not_of(const CharT* s, size_type pos = npos) const { return str().find_last_not_of(s, pos); } size_type find_last_not_of(CharT ch, size_type pos = npos) const { return str().find_last_not_of(ch, pos); } }; template< class CharT, class Traits, class Alloc > bool operator==( const basic_shared_string& lhs, const basic_shared_string& rhs) { return lhs.str() == rhs.str(); } template< class CharT, class Traits, class Alloc > bool operator!=( const basic_shared_string& lhs, const basic_shared_string& rhs) { return lhs.str() != rhs.str(); } template< class CharT, class Traits, class Alloc > bool operator<( const basic_shared_string& lhs, const basic_shared_string& rhs) { return lhs.str() < rhs.str(); } template< class CharT, class Traits, class Alloc > bool operator<=( const basic_shared_string& lhs, const basic_shared_string& rhs) { return lhs.str() <= rhs.str(); } template< class CharT, class Traits, class Alloc > bool operator>( const basic_shared_string& lhs, const basic_shared_string& rhs) { return lhs.str() > rhs.str(); } template< class CharT, class Traits, class Alloc > bool operator>=( const basic_shared_string& lhs, const basic_shared_string& rhs) { return lhs.str() >= rhs.str(); } template< class CharT, class Traits, class Alloc > bool operator==( const CharT* lhs, const basic_shared_string& rhs) { return operator==(lhs, rhs.str()); } template< class CharT, class Traits, class Alloc > bool operator==( const basic_shared_string& lhs, const CharT* rhs) { return operator==(lhs.str(), rhs); } template< class CharT, class Traits, class Alloc > bool operator!=(const CharT* lhs, const basic_shared_string& rhs) { return operator!=(lhs, rhs.str()); } template< class CharT, class Traits, class Alloc > bool operator!=(const basic_shared_string& lhs, const CharT* rhs) { return operator!=(lhs.str(), rhs); } template< class CharT, class Traits, class Alloc > bool operator<(const CharT* lhs, const basic_shared_string& rhs) { return operator<(lhs, rhs.str()); } template< class CharT, class Traits, class Alloc > bool operator<(const basic_shared_string& lhs, const CharT* rhs) { return operator<(lhs.str(), rhs); } template< class CharT, class Traits, class Alloc > bool operator<=(const CharT* lhs, const basic_shared_string& rhs) { return operator<=(lhs, rhs.str()); } template< class CharT, class Traits, class Alloc > bool operator<=(const basic_shared_string& lhs, const CharT* rhs) { return operator<=(lhs.str(), rhs); } template< class CharT, class Traits, class Alloc > bool operator>(const CharT* lhs, const basic_shared_string& rhs) { return operator>(lhs, rhs.str()); } template< class CharT, class Traits, class Alloc > bool operator>(const basic_shared_string& lhs, const CharT* rhs) { return operator>(lhs.str(), rhs); } template< class CharT, class Traits, class Alloc > bool operator>=(const CharT* lhs, const basic_shared_string& rhs) { return operator>=(lhs, rhs.str()); } template< class CharT, class Traits, class Alloc > bool operator>=(const basic_shared_string& lhs, const CharT* rhs) { return operator>=(lhs.str(), rhs); } template std::basic_ostream& operator<<( std::basic_ostream& os, const basic_shared_string& str) { return operator<<(os, str.str()); } template std::basic_istream& operator>>( std::basic_istream& is, basic_shared_string& str) { std::basic_string temp; operator>>(is, temp); str = temp; return is; } template< class CharT, class Traits, class Alloc > basic_shared_string operator+( const basic_shared_string& lhs, const basic_shared_string& rhs) { return basic_shared_string(operator+(lhs.str(), rhs.str())); } template< class CharT, class Traits, class Alloc > basic_shared_string operator+( const basic_shared_string& lhs, const std::basic_string& rhs) { return basic_shared_string(operator+(lhs.str(), rhs)); } template< class CharT, class Traits, class Alloc > basic_shared_string operator+( const std::basic_string& lhs, const basic_shared_string& rhs) { return basic_shared_string(operator+(lhs, rhs.str())); } template< class CharT, class Traits, class Alloc > basic_shared_string operator+( const CharT* lhs, const basic_shared_string& rhs) { return basic_shared_string(operator+(lhs, rhs.str())); } template< class CharT, class Traits, class Alloc > basic_shared_string operator+( CharT lhs, const basic_shared_string& rhs) { return basic_shared_string(operator+(lhs, rhs.str())); } template< class CharT, class Traits, class Alloc > basic_shared_string operator+( const basic_shared_string& lhs, const CharT* rhs) { return basic_shared_string(operator+(lhs.str(), rhs)); } template basic_shared_string operator+( const basic_shared_string& lhs, CharT rhs) { return basic_shared_string(operator+(lhs.str(), rhs)); } namespace std { template int stoi(const basic_shared_string& str, std::size_t* pos = 0, int base = 10) { return stoi(str.str(), pos, base); } template long stol(const basic_shared_string& str, std::size_t* pos = 0, int base = 10) { return stol(str.str(), pos, base); } template long long stoll(const basic_shared_string& str, std::size_t* pos = 0, int base = 10) { return stoll(str.str(), pos, base); } template unsigned long stoul(const basic_shared_string& str, std::size_t* pos = 0, int base = 10) { return stoul(str.str(), pos, base); } template unsigned long long stoull(const basic_shared_string& str, std::size_t* pos = 0, int base = 10) { return stoull(str.str(), pos, base); } template float stof(const basic_shared_string& str, std::size_t* pos = 0) { return stof(str.str(), pos); } template double stod(const basic_shared_string& str, std::size_t* pos = 0) { return stod(str.str(), pos); } template double stold(const basic_shared_string& str, std::size_t* pos = 0) { return stold(str.str(), pos); } template struct hash < basic_shared_string > { size_t operator()(const basic_shared_string& key) { return hash()(key.str()); } }; } typedef basic_shared_string shared_string; typedef basic_shared_string shared_wstring; #endif // _STRING_REF_H_INCLUDED_