pandorafms/extras/anytermd/libpbe/include/charset/string_adaptor.hh

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