/* ==================================================================== * Copyright (c) 2003-2006, Martin Hauner * http://subcommander.tigris.org * * Subcommander is licensed as described in the file doc/COPYING, which * you should have received as part of this distribution. * ==================================================================== */ // sc #include "String.h" #include "utf8.h" // sys #include #include #define max(a, b) (((a) > (b)) ? (a) : (b)) #define min(a, b) (((a) < (b)) ? (a) : (b)) namespace sc { String::String() : _str(0), _chars(0), _bytes(0) { } String::String( const String& src ) : _str(0), _chars(0), _bytes(0) { *this = src; } String::String( const char* str ) : _str(0), _chars(0), _bytes(0) { _copy(str); _bytes = _strbytes(str); _chars = utf8::strlen8(str,_bytes); } String::String( const char* str, Size bytes ) : _str(0), _chars(0), _bytes(0) { _ncopy(str,bytes); _bytes = bytes; _chars = utf8::strlen8(str,bytes); } String::~String() { _free(_str); } String::operator const char*() const { return _str; } void String::operator=( const String& in ) { _ncopy( in._str, in._bytes ); _chars = in._chars; _bytes = in._bytes; } void String::operator=( const char* in ) { _copy(in); _bytes = _strbytes(in); _chars = utf8::strlen8(in,_bytes); } const char* String::getStr() const { return _str; } size_t String::getCharCnt() const { return _chars; } size_t String::getByteCnt() const { return _bytes; } bool String::isEmpty() const { return getCharCnt() == 0; } String& String::operator+=( const String& in ) { _append( in._str ); _chars += in._chars; _bytes += in._bytes; return *this; } String& String::operator+=( const char* in ) { return *this += String(in); } bool String::operator<( const String &src ) const { return _cmp(src._str) < 0; } bool String::operator==( const String &src ) const { return _cmp(src._str) == 0; } bool String::operator!=( const String &src ) const { return _cmp(src._str) != 0; } String String::left( Size chars ) const { char* cur = utf8::next8( _str, min(chars,_chars) ); Size bytes = cur - _str; char* buf = _malloc( bytes+1 ); _strncpy( buf, _str, bytes ); String left( buf, bytes ); // bytes without 0 _free(buf); return left; } String String::right( Size chars ) const { char* cur = utf8::prev8( _str+_bytes, _str, min(chars,_chars) ); Size bytes = _str + _bytes - cur; Size start = _bytes - bytes; return String( _str+start, _bytes-start ); // bytes without 0 } String String::mid( Size first, Size chars ) const { return right( _chars-first ).left(chars); } int String::_cmp( const char* src ) const { if( _bytes == 0 ) { if( _strbytes(src) == 0 ) return 0; else return -1; } else { if( _strbytes(src) == 0 ) return 1; else return strcmp(_str, src); } } void String::_copy( const char *szSrc ) { Size length = _strbytes(szSrc); char* szDest = _malloc( length + 1 /* 0 byte */ ); _strcpy( szDest, szSrc ); _replace( szDest ); } void String::_ncopy( const char *szSrc, Size length ) { char *szDest = _malloc( length + 1 /* 0 byte */ ); _strncpy( szDest, szSrc, length ); _replace( szDest ); } char* String::_strcpy( char *szDest, const char *szSrc ) const { if( szDest == 0 || szSrc == 0 ) { return szDest; } return ::strcpy(szDest,szSrc); } char* String::_strncpy( char *szDest, const char *szSrc, Size length ) const { if( szDest == 0 || szSrc == 0 ) { return szDest; } ::strncpy( szDest, szSrc, length ); szDest[length] = 0; return szDest; } void String::_append( const char *src ) { char* tmp = _malloc( _bytes + _strbytes(src) + 1 ); _strcat( tmp, _str ); _strcat( tmp, src ); _replace( tmp ); } char* String::_strcat( char *dest, const char* src ) const { if( dest == 0 || src == 0 ) { return const_cast(src); } return ::strcat(dest,src); } void String::_replace( const char *szSrc ) { _free( _str ); _str = const_cast(szSrc); } Size String::_strbytes( const char *szIn ) const { if( ! szIn ) { return 0; } return ::strlen(szIn); } char* String::_malloc( Size nbytes ) const { // don't allocate memory for a negative size or // one of 0 or 1 byte, 1 is a "" string if( nbytes <= 1 ) { return 0; } char *ptr = (char*)::malloc( nbytes ); *ptr = 0; return ptr; } void String::_free( char *ptr ) const { if( ptr ) { ::free( ptr ); } } } // namespace #if 0 void CCharString::_init() { _str = 0; if( ! _mem ) { SetDefaultMalloc(); } } void CCharString::_owner( char *szSrc ) { char *buf = 0; if( szSrc && _strlen(szSrc) == 0 ) { _free(szSrc); } else { buf = szSrc; } _replace(buf); } void CCharString::_append( const char *szSrc ) { _str = _realloc( _str, _strlen() + _strlen(szSrc) + 1 ); _strcat( _str, szSrc ); } int CCharString::_cmp( const char* szSrc ) const { if(_strlen() == 0) { if(_strlen(szSrc) == 0) return 0; else return -1; } else { if(_strlen(szSrc) == 0) return 1; else return strcmp(_str, szSrc); } } size_t CCharString::_strlen() const { return _strlen(_str); } size_t CCharString::_strlen( const char *szIn ) const { if( ! szIn ) { return 0; } return ::strlen(szIn); } char *CCharString::_strcpy( char *szDest, const char *szSrc ) const { if( szDest == 0 || szSrc == 0 ) { return szDest; } return ::strcpy(szDest,szSrc); } char *CCharString::_strncpy( char *szDest, const char *szSrc, size_t length ) const { if( szDest == 0 || szSrc == 0 ) { return szDest; } ::strncpy( szDest, szSrc, length ); szDest[length] = 0; return szDest; } char *CCharString::_strcat( char *szDest, const char *szSrc ) const { if( szDest == 0 || szSrc == 0 ) { return szDest; } return ::strcat(szDest,szSrc); } bool CCharString::_iswhite( const char cIn ) const { if( cIn == 0x20 || (cIn >= 0x09 && cIn <= 0x0d) ) { return true; } return false; } #endif /* String dupString( apr_pool_t* pool, const String& src ) { char* dup = apr_pstrmemdup( pool, src.getStr(), src.getBytes() ); return String( dup, src.getBytes() ); } */