#ifndef __pxx_string_ih__ #define __pxx_string_ih__ #include "pxx_string.hh" #include "pxx_common.ih" #include "pxx_default_allocator.ih" //#include "pxx_stream.ih" #include #include #include #include namespace pxx { template String::String (size_t _length /* = 0 */) : length (_length) { // PMETHOD; size_t n; if ((default_allocator.get_features() & ALLOCATOR_HAS_GET_REAL_SIZE) != 0) { n = default_allocator.get_real_size( sizeof(StringDataInfo) + sizeof(type_t) * (length + 1)); } else { n = exps_of_two[ get_order(sizeof(StringDataInfo) + sizeof(type_t) * (length + 1))]; } datainfo = static_cast(default_allocator.allocate(n)); datainfo->ref_count = 1; datainfo->capacity = (n - sizeof(StringDataInfo)) / sizeof(type_t) - 1; data = reinterpret_cast( ptr_add_offset(datainfo, sizeof(StringDataInfo))); data[length] = 0; } template String::String ( type_t const* _s, const_t _const /* = non_const_data */ ) { // PMETHOD; size_t n = compute_length(_s); new(this) String(_s, n, _const); } template String::String ( type_t const* _s, size_t _len, const_t _const /* = non_const_data */ ) { // PMETHOD; if (_const == non_const_data) { new(this) String(_len); memcpy(data, _s, (_len) * sizeof(type_t)); data[_len] = 0; } else { datainfo = null; length = _len; data = const_cast(_s); if (data[_len] != 0) throw NonTerminated(); } } template String::String (String const& _s) : data (_s.data), datainfo (_s.datainfo), length (_s.length) { // PMETHOD; if (datainfo != null) datainfo->ref_count++; } template String::~String () { // PMETHOD; if (datainfo != null) { if (--(datainfo->ref_count) == 0) default_allocator.deallocate(datainfo); } } template String& String::operator = (String const& _s) { if (this != &_s) { this->~String(); new(this) String(_s); } return self; } template type_t const* String::get_data () const { return data; } template String String::operator + (String const& _s) const { String s(length + _s.length); memcpy(s.data, data, length * sizeof(type_t)); memcpy(s.data + length, _s.data, _s.length * sizeof(type_t)); s.data[s.length] = 0; return s; } #if 0 template String& String::operator << (String const& _s) { expand(_s.length); memcpy(data + length, _s.data, _s.length * sizeof(type_t)); length += _s.length; data[length] = 0; return self; } #endif template String String::head (size_t _len) const { if (_len <= length) { return String(data, _len); } else { throw OutOfRange(); } } template String String::tail (size_t _from) const { if (_from <= length) { return String(data + _from, length - _from); } else { throw OutOfRange(); } } template String String::substring (size_t _from, size_t _len) const { if (_from + _len <= length) { return String(data + _from, _len); } else { throw OutOfRange(); } } template void String::replace (size_t _from, String const& _s) { if (_from <= length) { deconstify(); if (_s.length > length - _from) { expand(_from + _s.length - length); length = _from + _s.length; data[length] = 0; } memcpy(data + _from, _s.data, _s.length * sizeof(type_t)); } else { throw OutOfRange(); } } template void String::expand (size_t _extra) { deconstify(); size_t n; if (datainfo->capacity - length < _extra) { if ((default_allocator.get_features() & ALLOCATOR_HAS_GET_REAL_SIZE) != 0) { n = default_allocator.get_real_size( sizeof(StringDataInfo) + sizeof(type_t) * (length + _extra + 1)); } else { n = exps_of_two[get_order( sizeof(StringDataInfo) + sizeof(type_t) * (length + _extra + 1))]; } datainfo = static_cast( default_allocator.reallocate(datainfo, n)); datainfo->capacity = (n - sizeof(StringDataInfo)) / sizeof(type_t) - 1; data = reinterpret_cast( ptr_add_offset(datainfo, sizeof(StringDataInfo))); } } template type_t const& String::operator [] (size_t _index) const { if (_index < length) { return data[_index]; } else { throw OutOfRange(); } } template type_t& String::operator [] (size_t _index) { if (_index < length) { return data[_index]; } else { throw OutOfRange(); } } template size_t String::get_length () const { return length; } template size_t String::get_capacity () const { if (datainfo != null) return datainfo->capacity; else return length; } template void String::deconstify () { if (datainfo == null || (datainfo != null && datainfo->ref_count > 1)) { type_t* old_data = data; size_t old_length = length; this->~String(); new(this) String(old_data, old_length); } } template size_t String::compute_length (type_t const* _strdata) { size_t len = 0; while (*_strdata++ != 0) len++; return len; } template <> size_t String::compute_length (char const* _strdata) { return strlen(_strdata); } template <> size_t String::compute_length (wchar_t const* _strdata) { return wcslen(_strdata); } #if 0 template Stream& operator << (Stream& _stream, String _s) { type_t const* p = _s.data; type_t const* q = p + _s.length; while (p < q) { _stream << *p++; } return _stream; } #endif } #endif // __pxx_string_ih__