197 lines
6.2 KiB
C++
197 lines
6.2 KiB
C++
|
// 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 <boost/iterator/reverse_iterator.hpp>
|
||
|
|
||
|
#include <string>
|
||
|
#include <algorithm>
|
||
|
|
||
|
|
||
|
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 <charset_t cset, typename Alloc>
|
||
|
class string_adaptor {
|
||
|
|
||
|
typedef charset_traits<cset> traits_t;
|
||
|
typedef typename traits_t::char_t char_t;
|
||
|
typedef typename traits_t::unit_t unit_t;
|
||
|
|
||
|
public:
|
||
|
typedef std::basic_string<unit_t, std::char_traits<unit_t>, 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<cset, typename unit_string_t::const_iterator> const_iterator;
|
||
|
// reverse_iterator ??
|
||
|
typedef boost::reverse_iterator<const_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<n; ++i) {
|
||
|
push_back(c);
|
||
|
}
|
||
|
}
|
||
|
template <typename InputIterator>
|
||
|
string_adaptor& append(InputIterator first, InputIterator last) {
|
||
|
for (; first!=last; ++first) {
|
||
|
push_back(*first);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void push_back(char_t c) {
|
||
|
std::back_insert_iterator<unit_string_t> 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 <typename InputIterator>
|
||
|
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 <charset_t cset, typename Alloc>
|
||
|
bool operator==(const string_adaptor<cset,Alloc>& s1,
|
||
|
const string_adaptor<cset,Alloc>& s2) {
|
||
|
return s1.ustr == s2.ustr;
|
||
|
}
|
||
|
|
||
|
template <charset_t cset, typename Alloc>
|
||
|
bool operator!=(const string_adaptor<cset,Alloc>& s1,
|
||
|
const string_adaptor<cset,Alloc>& s2) {
|
||
|
return s1.ustr != s2.ustr;
|
||
|
}
|
||
|
|
||
|
template <charset_t cset, typename Alloc>
|
||
|
bool operator<(const string_adaptor<cset,Alloc>& s1,
|
||
|
const string_adaptor<cset,Alloc>& s2) {
|
||
|
return s1.compare(s2)<0;
|
||
|
}
|
||
|
|
||
|
template <charset_t cset, typename Alloc>
|
||
|
void swap(string_adaptor<cset,Alloc>& s1,
|
||
|
string_adaptor<cset,Alloc>& s2) {
|
||
|
s1.swap(s2);
|
||
|
}
|
||
|
|
||
|
|
||
|
};
|
||
|
|
||
|
#endif
|