📄 brewstring_ads.h
字号:
/*
* Copyright (C) 2003 Radu Braniste (rbraniste@epicad.com)
* All Rights Reserved
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name of the Author nor the names of its contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef __BrewString
#define __BrewString
#include "platformSpecific.h"
#define length_ pData_->length
#define capacity_ pData_->capacity
#define buffer_ pData_->buffer
template <typename T>
bool isspace(T c){ return (c == ' '); }
template <typename T >
class BrewString
{
public:
template <class U>
BrewString( const U& rhs , UINT sz = 0): pData_(0)
{
CopyCtorImpl(rhs, sz);
}
BrewString( const T* rhs , UINT sz = 0): pData_(0)
{
CopyCtorImpl(rhs, sz);
}
BrewString( const BrewString<T> &rhs ): pData_(0)
{
CopyCtorImpl(rhs, 0);
}
template < class U, class V>
BrewString (const U& lhs, UINT lnl, const V& rhs, UINT lnr): pData_(0)
{
ensureCapacity(lnr + lnl );
MEMCPY( buffer_, getBuf(lhs) , lnl );
MEMCPY( buffer_+lnl, getBuf(rhs) , lnr );
buffer_[length_=capacity_] = 0;
}
BrewString( ) : pData_(0)
{
}
~BrewString()
{
FREE(pData_);
}
const BrewString<T> &
operator=( const BrewString &rhs )
{
if ( this == &rhs )
return *this;
return opEqImpl(rhs);
}
const BrewString<T> &
operator=( const T* rhs )
{
return opEqImpl(rhs);
}
template <class U>
const BrewString<T> &
operator+=( const U& rhs )
{
UINT ln = getLen(rhs);
UINT newLen = increaseBuffer(ln);
cat(getBuf(rhs), ln);
length_ = newLen;
return *this;
}
const BrewString<T> &
operator+=( const T* rhs )
{
UINT ln = getLen(rhs);
UINT newLen = increaseBuffer(ln);
cat(getBuf(rhs), ln);
length_ = newLen;
return *this;
}
template <class U>
bool equals( const U& rhs ) const
{
return ( bufferImpl() && lengthImpl() == getLen(rhs) && STRCMP( buffer_, getBuf(rhs) ) == 0 );
}
template <class U>
bool startsWith( const U &rhs, UINT offset = 0 ) const
{
UINT ln = getLen(rhs);
if ( lengthImpl()< ln + offset || ln == 0)
return false;
return STRNCMP( &buffer_[offset], getBuf(rhs), ln ) == 0;
}
template <class U>
bool endsWith( const U& rhs ) const
{
UINT ln = getLen(rhs);
if ( lengthImpl() < ln || ln == 0)
return false;
return STRCMP( &buffer_[ length_ - ln], getBuf(rhs) ) == 0;
}
template <class U>
int indexOf( const U &rhs, UINT fromIndex = 0 ) const
{
if (lengthImpl() < (getLen(rhs) + fromIndex))
return -1;
const T *temp = STRSTR( &buffer_[ fromIndex ], getBuf(rhs) );
return ( temp ) ? temp - buffer_ : -1;
}
int indexOf( const T rhs, UINT fromIndex = 0 ) const
{
if (lengthImpl()< fromIndex)
return -1;
const T *temp = STRCHR( &buffer_[ fromIndex ], rhs );
return ( temp ) ? temp - buffer_ : -1;
}
template <class U>
int lastIndexOf( const U &rhs ) const
{
return lastIndexOf( rhs, lengthImpl() - getLen(rhs) );
}
template <class U>
int lastIndexOf( const U &rhs, UINT fromIndex ) const
{
UINT ln = getLen(rhs);
if ( ln == 0 || fromIndex + ln>= lengthImpl() )
return -1;
T temp = getBuf(rhs)[ 0 ];
for ( int i = fromIndex; i >= 0; i-- )
{
if ( buffer_[ i ] == temp && (!STRNCMP(getBuf(rhs), &buffer_[i], ln)) )
return i;
}
return -1;
}
template <class U, class V>
const BrewString<T>&
replace( const U& match, const V& replacement )
{
UINT ln = getLen(match);
if (ln == 0 || ln > lengthImpl())
return *this;
BrewString newString;
int loc , oldLoc = 0;
bool isReplaceable = false;
while ( (loc = indexOf( match, oldLoc )) != -1 )
{
if (!isReplaceable )
{
isReplaceable = true;
newString.ensureCapacity(length_);
}
newString += substring( oldLoc, loc );
newString += replacement;
oldLoc = loc + ln;
}
if (isReplaceable)
{
newString += substring( oldLoc );
return opEqImpl(newString);
}
return *this;
}
const BrewString<T>&
replace( T findChar, T replaceChar )
{
if (pData_ && buffer_)
{
T* temp = buffer_;
while( (temp = STRCHR( temp, findChar )) )
*temp = replaceChar;
}
return *this;
}
const BrewString<T>
substring( UINT left ) const
{
return substring( left, lengthImpl() );
}
const BrewString<T>
substring( UINT left, UINT right ) const
{
if ( ( left >= right ) || ( right > lengthImpl()) )
{
return BrewString();
}
return BrewString ( buffer_ + left, right - left );
}
const BrewString<T>& partialString( UINT right )
{
if ( right >= lengthImpl() )
{
return *this;
}
length_ = right;
buffer_[length_] = 0;
return *this;
}
const BrewString<T>& partialString( UINT left, UINT right )
{
if ( ( left > right ) || ( right > lengthImpl() ) )
{
return *this;
}
length_ = right - left;
T* strt = buffer_;
T* sstr = buffer_ + left;
while( (strt - buffer_) < length_ )
{
*(strt++) = *(sstr++);
}
buffer_[length_] = 0;
return *this;
}
const BrewString<T>& trim()
{
if (lengthImpl() <1 )
return *this;
UINT i = 0;
for ( UINT ln = length_; i < ln; i++ )
{
if ( !isspace(buffer_[i]) )
break;
}
UINT j = length_ - 1;
for ( ; j > i; j-- )
{
if ( !isspace(buffer_[j]) )
break;
}
return partialString( i, j + 1);
}
const BrewString<T>& toLowerCase( ) const
{
if (pData_ && buffer_)
STRLOWER(buffer_);
return *this;
}
const BrewString<T>& toUpperCase( ) const
{
if (pData_ && buffer_)
STRUPPER(buffer_);
return *this;
}
const T* toCharArray() const { return bufferImpl();}
const UINT length( ) const { return lengthImpl(); }
const UINT capacity( ) const { return capacityImpl(); }
const T charAt( int index ) const
{
return (!isIndexOutOfBounds( index )) ? buffer_[ index ] : 0;
}
bool isEmpty() const
{
return !(pData_ && length_);
}
void ensureCapacity(UINT sz)
{
if (!pData_)
{
increaseBuffer(sz);
buffer_[length_] = 0;
return;
}
int l = sz - length_;
UINT newLen = l>0 ? l : length_;
increaseBuffer(newLen);
}
void setLength(UINT sz)
{
if (sz < lengthImpl())
{
length_ = sz;
capacity_ = sz;
buffer_[sz] = 0;
return;
}
if (sz > lengthImpl())
{
increaseBuffer(sz - lengthImpl());
buffer_[length_] = 0;
}
}
T& operator[]( UINT idx )
{
return *(buffer_+idx);
}
const T& operator[]( UINT idx ) const
{
return *(buffer_+idx);
}
private:
void setBuffer(UINT sz)
{
pData_ = (DATA*)MALLOC(sizeof(DATA) + sz*sizeof(T));
if (pData_)
capacity_ = sz;
}
UINT increaseBuffer(UINT sz)
{
if (!pData_)
{
setBuffer( sz );
length_ = 0;
return sz;
}
UINT newLen = length_ + sz;
if (newLen > capacity_)
{
DATA *temp = pData_;
setBuffer( newLen );
length_ = newLen - sz;
cpy( temp->buffer);
FREE (temp);
if (!buffer_) return 0;
}
return newLen;
}
bool isIndexOutOfBounds( UINT index ) const
{
return (( index >= lengthImpl() ) || ( index <0 ) );
}
UINT getLen(const BrewString& s) const
{ return s.pData_?s.length_:0;}
UINT getLen(const T* ch) const
{ return ch?STRLEN(ch):0;}
const T* getBuf(const BrewString& s) const
{ return s.buffer_;}
const T* getBuf(const T* ch) const
{ return ch;}
template <class U>
const BrewString<T> &
opEqImpl( const U &rhs )
{
UINT ln = getLen(rhs);
if (!pData_ || ln > capacityImpl() )
{
FREE( pData_);
setBuffer( ln );
}
length_ = ln;
cpy(getBuf(rhs));
return *this;
}
template <class U>
void CopyCtorImpl( const U &rhs, UINT sz)
{
UINT ln = getLen(rhs);
sz = (sz == 0) || (sz > ln)? ln : sz;
setBuffer( sz );
length_ = sz;
cpy( getBuf(rhs) );
}
void cpy(const T* rhs)
{
if (pData_ && buffer_ && rhs)
{
MEMCPY( buffer_, rhs , length_ );
buffer_[length_] = 0;
}
}
void cat(const T* rhs, UINT sz )
{
if (pData_ && buffer_ && rhs)
{
MEMCPY( buffer_+ length_, rhs , sz );
buffer_[sz + length_] = 0;
}
}
T* bufferImpl() const
{
return pData_?buffer_:0;
}
UINT lengthImpl() const
{
return pData_?length_:0;
}
UINT capacityImpl() const
{
return pData_?capacity_:0;
}
friend BrewString<T> operator+ ( const BrewString<T>& lhs, const T* rhs )
{
return BrewString<T>::opPlusImpl(lhs, rhs);
}
friend BrewString<T> operator+ ( const BrewString<T>& lhs, const BrewString<T>& rhs )
{
return BrewString<T>::opPlusImpl(lhs, rhs);
}
friend BrewString<T> operator+ ( const T* lhs, const BrewString<T>& rhs )
{
return BrewString<T>::opPlusImpl(lhs, rhs);
}
template < class U, class V>
static BrewString<T> opPlusImpl(const U& lhs, const V& rhs)
{
BrewString<T> t;
UINT lnl = t.getLen(lhs);
UINT lnr = t.getLen(rhs);
return BrewString<T>(lhs, lnl, rhs, lnr);
}
private:
struct DATA
{
UINT length;
UINT capacity;
T buffer[1];
};
DATA* pData_;
};
typedef BrewString<char> String;
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -