// string_adaptor.hh // This file is part of libpbe; see http://anyterm.org/ // (C) 2007-2008 Philip Endecott // Distributed under the Boost Software License, Version 1.0: // // Permission is hereby granted, free of charge, to any person or organization // obtaining a copy of the software and accompanying documentation covered by // this license (the "Software") to use, reproduce, display, distribute, // execute, and transmit the Software, and to prepare derivative works of the // Software, and to permit third-parties to whom the Software is furnished to // do so, all subject to the following: // // The copyright notices in the Software and this entire statement, including // the above license grant, this restriction and the following disclaimer, // must be included in all copies of the Software, in whole or in part, and // all derivative works of the Software, unless such copies or derivative // works are solely in the form of machine-executable object code generated by // a source language processor. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT // SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE // FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. #ifndef libpbe_charset_string_adaptor_hh #define libpbe_charset_string_adaptor_hh #include "charset/charset_t.hh" #include "charset/charset_traits.hh" #include "charset/const_character_iterator.hh" #include #include #include namespace pbe { // String adaptor // -------------- // // This class adapts a std::string containing a sequence of units into a // std::string-like object containing a sequence of characters. It stores // a reference to the underlying unit-string. template class string_adaptor { typedef charset_traits traits_t; typedef typename traits_t::char_t char_t; typedef typename traits_t::unit_t unit_t; public: typedef std::basic_string, Alloc> unit_string_t; private: unit_string_t& ustr; public: string_adaptor(unit_string_t& ustr_): ustr(ustr_) {} unit_string_t& unit_str() { return ustr; } const unit_string_t& unit_str() const { return ustr; } typedef char_t value_type; typedef char_t* pointer; typedef char_t& reference; typedef const char_t& const_reference; typedef size_t size_type; typedef ptrdiff_t difference_type; // ?? static const size_type npos = -1; // iterator ?? typedef const_character_iterator const_iterator; // reverse_iterator ?? typedef boost::reverse_iterator const_reverse_iterator; // begin // end const_iterator begin() const { return const_iterator(ustr.begin()); } const_iterator end() const { return const_iterator(ustr.end()); } // rbegin // rend const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } // size // ?? could do this in O(n) // length size_type max_size() const { return ustr.max_size(); } // ??? size_type capacity() const { return ustr.capacity(); } // ??? bool empty() const { return ustr.empty(); } // operator[] // operator[] const // c_str() ??? // data() ??? string_adaptor& operator=(const string_adaptor& other) { ustr=other.ustr; return *this; } string_adaptor& operator=(char_t c) { clear(); push_back(c); } void reserve(size_t sz) { ustr.reserve(sz); } // *typ_units_per_char void swap(string_adaptor& other) { ustr.swap(other.ustr); } // insert string_adaptor& append(const string_adaptor& s) { ustr.append(s.unit_str()); return *this; } string_adaptor& append(size_type n, char_t c) { for (size_type i=0; i string_adaptor& append(InputIterator first, InputIterator last) { for (; first!=last; ++first) { push_back(*first); } } void push_back(char_t c) { std::back_insert_iterator i(ustr); traits_t::encode(i,c); } string_adaptor& operator+=(const string_adaptor& s) { append(s); } string_adaptor& operator+=(char_t c) { push_back(c); } #if 0 iterator erase(iterator p) { ustr.erase(p.base(), p.base()+traits_t::char_length(p.base())-1); } iterator erase(iterator first, iterator last) { ustr.erase(first.base(), last.base()+traits_t::char_length(last.base())-1); } #endif void clear() { ustr.clear(); } // resize string_adaptor& assign(const string_adaptor& other) { operator=(other); } string_adaptor& assign(size_type n, char_t c) { clear(); append(n,c); } template string_adaptor& assign(InputIterator first, InputIterator last) { clear(); append(first,last); } // replace // copy // find // find variants // substr int compare(const string_adaptor& s) const { // FIXME apparently this is an SGI thing that's not in the standard // return std::lexicographical_compare_3way(s.begin(), s.end(), begin(), end()); } // Note that for UTF8 we can do the comparison directly on the units, which // should be faster. }; template bool operator==(const string_adaptor& s1, const string_adaptor& s2) { return s1.ustr == s2.ustr; } template bool operator!=(const string_adaptor& s1, const string_adaptor& s2) { return s1.ustr != s2.ustr; } template bool operator<(const string_adaptor& s1, const string_adaptor& s2) { return s1.compare(s2)<0; } template void swap(string_adaptor& s1, string_adaptor& s2) { s1.swap(s2); } }; #endif