hxstring.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:20k
- /* ***** BEGIN LICENSE BLOCK *****
- * Source last modified: $Id: hxstring.cpp,v 1.17.2.3 2004/07/09 01:45:59 hubbe Exp $
- *
- * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
- *
- * The contents of this file, and the files included with this file,
- * are subject to the current version of the RealNetworks Public
- * Source License (the "RPSL") available at
- * http://www.helixcommunity.org/content/rpsl unless you have licensed
- * the file under the current version of the RealNetworks Community
- * Source License (the "RCSL") available at
- * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
- * will apply. You may also obtain the license terms directly from
- * RealNetworks. You may not use this file except in compliance with
- * the RPSL or, if you have a valid RCSL with RealNetworks applicable
- * to this file, the RCSL. Please see the applicable RPSL or RCSL for
- * the rights, obligations and limitations governing use of the
- * contents of the file.
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License Version 2 or later (the
- * "GPL") in which case the provisions of the GPL are applicable
- * instead of those above. If you wish to allow use of your version of
- * this file only under the terms of the GPL, and not to allow others
- * to use your version of this file under the terms of either the RPSL
- * or RCSL, indicate your decision by deleting the provisions above
- * and replace them with the notice and other provisions required by
- * the GPL. If you do not delete the provisions above, a recipient may
- * use your version of this file under the terms of any one of the
- * RPSL, the RCSL or the GPL.
- *
- * This file is part of the Helix DNA Technology. RealNetworks is the
- * developer of the Original Code and owns the copyrights in the
- * portions it created.
- *
- * This file, and the files included with this file, is distributed
- * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
- * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
- * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
- * ENJOYMENT OR NON-INFRINGEMENT.
- *
- * Technology Compatibility Kit Test Suite(s) Location:
- * http://www.helixcommunity.org/content/tck
- *
- * Contributor(s):
- *
- * ***** END LICENSE BLOCK ***** */
- #include "hxstring.h"
- #include "hlxclib/string.h"
- #include "hlxclib/ctype.h"
- #include "hxassert.h"
- #ifdef HELIX_FEATURE_STR_2X_GROWTH
- #define DEFAULT_GROWTH_FUNC CHXString::DoublingGrowth
- #else
- #define DEFAULT_GROWTH_FUNC CHXString::MinimalGrowth
- #endif /* HELIX_FEATURE_STR_2X_GROWTH */
- #if !defined(HELIX_CONFIG_NOSTATICS)
- const CHXString HXEmptyString;
- #else
- const char* const _g_emptyString = NULL;
- #endif
- CHXStringRep::CHXStringRep(INT32 strSize, bool bSetLength) :
- m_refCount(1),
- m_strSize(0),
- m_bufSize((strSize > 0) ? strSize + 1 : 1),
- m_pData(new char[m_bufSize]) // Depends on m_bufSize being initialized
- {
- if( m_pData )
- {
- m_pData[0] = ' ';
- if (bSetLength)
- {
- m_strSize = strSize;
- m_pData[m_strSize] = ' ';
- }
- }
- }
- CHXStringRep::CHXStringRep(const char* pStr) :
- m_refCount(1),
- m_strSize((pStr) ? strlen(pStr) : 0),
- m_bufSize(m_strSize + 1), // Depends on m_strSize being initialized
- m_pData(new char[m_bufSize]) // Depends on m_bufSize being initialized
- {
- if( m_pData )
- {
- if (pStr)
- strcpy(m_pData, pStr); /* Flawfinder: ignore */
- else
- m_pData[0] = ' ';
- }
- }
- CHXStringRep::CHXStringRep(const char* pStr, INT32 strSize) :
- m_refCount(1),
- m_strSize(strSize),
- m_bufSize((strSize > 0) ? strSize + 1: 1),
- m_pData(new char[m_bufSize]) // Depends on m_bufSize being initialized
- {
- if( m_pData )
- {
- if (pStr)
- strncpy(m_pData, pStr, m_strSize); /* Flawfinder: ignore */
- m_pData[m_strSize] = ' ';
-
- m_strSize = strlen(m_pData);
- }
- }
- CHXStringRep::CHXStringRep(char ch, INT32 count) :
- m_refCount(1),
- m_strSize((ch) ? count : 0),
- m_bufSize(count + 1),
- m_pData(new char[m_bufSize]) // Depends on m_bufSize being initialized
- {
- if( m_pData )
- {
- memset(m_pData, ch, count);
- m_pData[m_strSize] = ' ';
- }
- }
- CHXStringRep::~CHXStringRep()
- {
- HX_VECTOR_DELETE(m_pData);
- m_pData = 0;
- }
- void CHXStringRep::AddRef()
- {
- m_refCount++;
- }
- void CHXStringRep::Release()
- {
- if ((--m_refCount) == 0)
- delete this;
- }
- void CHXStringRep::Resize(INT32 newStrSize)
- {
- HX_ASSERT(newStrSize >= 0);
- INT32 newBufSize = newStrSize + 1;
- if (newBufSize != m_bufSize)
- {
- delete [] m_pData;
- m_pData = new char[newBufSize];
- m_bufSize = newBufSize;
- }
- }
- void CHXStringRep::ResizeAndCopy(INT32 newStrSize, bool bSetLength)
- {
- HX_ASSERT(newStrSize >= 0);
- INT32 newBufSize = newStrSize + 1;
- if (newBufSize != m_bufSize)
- {
- char* pNewBuf = new char[newBufSize];
- if( !pNewBuf )
- {
- // It would be swell to be able to notify the caller that we are
- // out of memory.
- return;
- }
- if (newStrSize < m_strSize)
- m_strSize = newStrSize;
- if (m_pData)
- strncpy(pNewBuf, m_pData, m_strSize); /* Flawfinder: ignore */
- pNewBuf[m_strSize] = ' ';
- if (bSetLength)
- {
- m_strSize = newStrSize;
- pNewBuf[m_strSize] = ' ';
- }
- delete [] m_pData;
- m_pData = pNewBuf;
- m_bufSize = newBufSize;
- }
- }
- void CHXStringRep::Copy(const char* pStr, INT32 strSize)
- {
- HX_ASSERT(strSize >= 0);
-
- if (m_bufSize < (strSize + 1))
- Resize(strSize);
- if( m_pData )
- {
- strncpy(m_pData, pStr, strSize); /* Flawfinder: ignore */
- m_pData[strSize] = ' ';
- m_strSize = strSize;
- }
- }
- CHXString::CHXString(StringGrowthFunc pGrowthFunc) :
- m_pRep(0),
- m_pGrowthFunc((pGrowthFunc) ? pGrowthFunc : DEFAULT_GROWTH_FUNC)
- {}
- CHXString::CHXString(const CHXString& rhs) :
- m_pRep(rhs.m_pRep),
- m_pGrowthFunc(rhs.m_pGrowthFunc)
- {
- if (m_pRep)
- m_pRep->AddRef();
- }
- CHXString::CHXString(char ch, int length,
- StringGrowthFunc pGrowthFunc) :
- m_pRep(new CHXStringRep(ch, length)),
- m_pGrowthFunc((pGrowthFunc) ? pGrowthFunc : DEFAULT_GROWTH_FUNC)
- {}
- CHXString::CHXString(const char* pStr,
- StringGrowthFunc pGrowthFunc) :
- m_pRep(NULL),
- m_pGrowthFunc((pGrowthFunc) ? pGrowthFunc : DEFAULT_GROWTH_FUNC)
- {
- if (pStr && *pStr)
- {
- /* Only create a CHXStringRep if the string
- * is not empty
- */
- m_pRep = new CHXStringRep(pStr);
- }
- }
- CHXString::CHXString(const char* pStr, int length,
- StringGrowthFunc pGrowthFunc) :
- m_pRep(NULL),
- m_pGrowthFunc((pGrowthFunc) ? pGrowthFunc : DEFAULT_GROWTH_FUNC)
- {
- if (pStr && (length > 0) && *pStr)
- {
- /* Only create a CHXStringRep if the string
- * is not empty
- */
- m_pRep = new CHXStringRep(pStr, length);
- }
- }
- CHXString::CHXString(const unsigned char* pStr,
- StringGrowthFunc pGrowthFunc) :
- m_pRep(NULL),
- m_pGrowthFunc((pGrowthFunc) ? pGrowthFunc : DEFAULT_GROWTH_FUNC)
- {
- if (pStr && *pStr)
- {
- /* Only create a CHXStringRep if the string
- * is not empty
- */
- m_pRep = new CHXStringRep((const char*)pStr);
- }
- }
- CHXString::~CHXString()
- {
- if (m_pRep)
- {
- m_pRep->Release();
- m_pRep = NULL;
- }
- }
- void CHXString::Empty()
- {
- if (m_pRep)
- {
- m_pRep->Release();
- m_pRep = NULL;
- }
- }
- void CHXString::SetAt(INT32 i, char ch)
- {
- HX_ASSERT(m_pRep && (i < m_pRep->GetBufferSize()));
- if (m_pRep)
- {
- EnsureUnique();
- m_pRep->GetBuffer()[i] = ch;
- }
- }
- const CHXString& CHXString::operator=(const CHXString& rhs)
- {
- if (&rhs != this)
- {
- if (m_pRep)
- m_pRep->Release();
- m_pRep = rhs.m_pRep;
-
- if (m_pRep)
- m_pRep->AddRef();
- m_pGrowthFunc = rhs.m_pGrowthFunc;
- }
- return *this;
- }
- const CHXString& CHXString::operator=(char ch)
- {
- if (m_pRep)
- {
- EnsureUnique();
- if (m_pRep->GetBufferSize() < 2)
- m_pRep->Resize(1);
-
- m_pRep->GetBuffer()[0] = ch;
- m_pRep->GetBuffer()[1] = ' ';
-
- if (ch)
- m_pRep->SetStringSize(1);
- else
- m_pRep->SetStringSize(0);
- }
- else
- m_pRep = new CHXStringRep(ch, 1);
- return *this;
- }
- const CHXString& CHXString::operator=(const char* pStr)
- {
- if (m_pRep)
- {
- EnsureUnique();
- m_pRep->Copy(pStr, SafeStrlen(pStr));
- }
- else if (pStr && *pStr)
- m_pRep = new CHXStringRep(pStr);
- return *this;
- }
- const CHXString& CHXString::operator=(const unsigned char* pStr)
- {
- if (m_pRep)
- {
- EnsureUnique();
- m_pRep->Copy((const char*)pStr, SafeStrlen((const char*)pStr));
- }
- else if (pStr && *pStr)
- m_pRep = new CHXStringRep((const char*)pStr);
- return *this;
- }
- const CHXString& CHXString::operator+=(const CHXString& rhs)
- {
- // Be careful here. You must make sure that this implementation
- // handles the case where (&rhs == this)
- if (rhs.m_pRep)
- Append(rhs.m_pRep->GetBuffer(), rhs.m_pRep->GetStringSize());
-
- return *this;
- }
- const CHXString& CHXString::operator+=(char ch)
- {
- if (ch)
- Append(&ch, 1);
- return *this;
- }
- const CHXString& CHXString::operator+=(const char* pStr)
- {
- // Make sure that someone is not trying to be tricky and
- // append part of this string to itself.
- HX_ASSERT(!m_pRep ||
- (pStr < m_pRep->GetBuffer()) ||
- (pStr > m_pRep->GetBuffer() + m_pRep->GetBufferSize()));
- Append(pStr, SafeStrlen(pStr));
- return *this;
- }
- CHXString operator+(const CHXString& strA, const CHXString& strB)
- {
- CHXString ret(strA);
- ret += strB;
- return ret;
- }
- CHXString operator+ (const CHXString& str, char ch)
- {
- CHXString ret(str);
- ret += ch;
- return ret;
- }
- CHXString operator+ (char ch , const CHXString& str)
- {
- CHXString ret(ch);
- ret += str;
- return ret;
- }
- CHXString operator+ (const CHXString& strA, const char* pStrB)
- {
- CHXString ret(strA);
- ret += pStrB;
- return ret;
- }
- CHXString operator+ (const char* pStrA, const CHXString& strB)
- {
- CHXString ret(pStrA);
- ret += strB;
- return ret;
- }
- char* CHXString::GetBuffer(INT32 minSize)
- {
- // NOTE: minSize is string length, not including ending zero byte...
- HX_ASSERT(minSize >= 0);
- if (m_pRep)
- {
- if (m_pRep->GetBufferSize() < (minSize + 1))
- {
- EnsureUnique();
- m_pRep->ResizeAndCopy(minSize);
- }
- }
- else
- m_pRep = new CHXStringRep(minSize);
- return m_pRep->GetBuffer();
- }
- void CHXString::ReleaseBuffer(INT32 newSize)
- {
- // NOTE: newSize is string length, not including ending zero byte...
- if (m_pRep)
- {
- // Update the string size since the caller could've changed the
- // internal data (the whole point of this GetBuffer()/ReleaseBuffer()
- // stuff).
- char* pBuf = m_pRep->GetBuffer();
- if (newSize >= m_pRep->GetBufferSize())
- {
- HX_ASSERT(newSize < m_pRep->GetBufferSize());
- // ...so if it's too big, clamp it to the max available.
- newSize = m_pRep->GetBufferSize() - 1;
- }
- if (newSize >= 0)
- pBuf[newSize] = ' ';
- else
- newSize = strlen(pBuf);
- if (newSize > 0)
- {
- m_pRep->SetStringSize(newSize);
- m_pRep->ResizeAndCopy(newSize);
- }
- else
- {
- if (m_pRep)
- {
- m_pRep->Release();
- m_pRep = NULL;
- }
- }
- }
- else
- {
- HX_ASSERT(!"Shouldn't call ReleaseBuffer() without GetBuffer()");
- if (newSize > 0)
- m_pRep = new CHXStringRep(newSize);
- }
- }
- char* CHXString::GetBufferSetLength(INT32 newSize)
- {
- // NOTE : newSize is a string length, not including ending zero byte...
- HX_ASSERT(newSize >= 0);
- if (m_pRep)
- {
- EnsureUnique();
- m_pRep->ResizeAndCopy(newSize, true);
- }
- else if (newSize > 0)
- m_pRep = new CHXStringRep(newSize, true);
- return m_pRep->GetBuffer();
- }
- void CHXString::FreeExtra()
- {
- if (m_pRep)
- {
- INT32 newSize = GetLength();
- if (newSize > 0)
- {
- EnsureUnique();
- m_pRep->ResizeAndCopy(newSize);
- }
- else
- {
- if (m_pRep)
- {
- m_pRep->Release();
- m_pRep = NULL;
- }
- }
- }
- }
- INT32 CHXString::GetAllocLength() const
- {
- return GetLength();
- }
- INT32 CHXString::SetMinBufSize(INT32 minSize)
- {
- // NOTE: minSize is a string length, not including ending zero byte...
- HX_ASSERT(minSize >= 0);
- INT32 ret = 0;
- if (m_pRep)
- {
- if (minSize >= m_pRep->GetStringSize())
- {
- if (minSize)
- {
- EnsureUnique();
- m_pRep->ResizeAndCopy(minSize);
- }
- else
- {
- if (m_pRep)
- {
- m_pRep->Release();
- m_pRep = NULL;
- }
- }
- }
-
- if (m_pRep)
- ret = m_pRep->GetBufferSize() - 1;
- }
- else if (minSize > 0)
- {
- m_pRep = new CHXStringRep(minSize);
- ret = minSize;
- }
- return ret;
- }
- #if defined(_MACINTOSH) || defined(_MAC_UNIX)
- #include "platform/mac/fullpathname.h"
- #include "platform/mac/cfwrappers.h"
- const CHXString& CHXString::SetFromStr255(const Str255 src)
- {
- char temp[256]; /* Flawfinder: ignore */
-
- if (src==NULL)
- {
- Empty();
- }
- else
- {
- memcpy (temp, &src[1], src[0]); /* Flawfinder: ignore */
- temp[src[0]] = 0;
- *this = CHXString( temp, src[0]);
- }
-
- return *this;
- }
- const CHXString& CHXString::AppendFromStr255(const Str255 src)
- {
- char temp[256]; /* Flawfinder: ignore */
-
- if (src!=NULL)
- {
- memcpy (temp, &src[1], src[0]); /* Flawfinder: ignore */
- temp[src[0]] = 0;
- CHXString tempS;
- tempS = temp;
- *this = *this + tempS;
- }
- return *this;
- }
- const CHXString& CHXString::InsertFromStr255(const Str255 src)
- {
- char temp[256]; /* Flawfinder: ignore */
-
- if (src!=NULL)
- {
- memcpy (temp, &src[1], src[0]); /* Flawfinder: ignore */
- temp[src[0]] = 0;
- CHXString tempS;
- tempS = temp;
- *this = tempS + *this;
- }
-
- return *this;
- }
-
- const CHXString& CHXString::SetFromIndString(short strlist, short item)
- {
- Str255 theStr;
- GetIndString(theStr,strlist,item);
- SetFromStr255(theStr);
- return *this;
- }
- const CHXString& CHXString::operator =(FSSpec spec)
- {
- CHXString temp;
-
- PathNameFromFSSpec(&spec, temp);
- *this=temp;
- return *this;
- }
- CHXString::operator const FSSpec(void)
- {
- FSSpec spec;
- (void) FSSpecFromPathName((const char*)(*this), &spec);
- return spec;
- }
- HX_RESULT CHXString::MakeStr255(Str255& outPascalString) const
- {
- UINT32 len = GetLength();
- if (m_pRep)
- c2pstrcpy(outPascalString, m_pRep->GetBuffer());
-
- return (len <= 255 ? HXR_OK : HXR_FAIL);
- }
- #if !defined(_CARBON) && !defined(_MAC_UNIX)
- CHXString::operator Str255* (void)
- {
- #error "Not Implemented"
- }
- CHXString::operator const Str255* (void) const
- {
- #error "Not Implemented"
- }
- CHXString::operator ConstStr255Param (void) const
- {
- #error "Not Implemented"
- }
- #else
- const CHXString& CHXString::operator =(const FSRef& ref)
- {
- CHXString temp;
-
- (void) PathFromFSRef(&ref, temp);
- *this = temp;
- return *this;
- }
- CHXString::operator const FSRef(void)
- {
- FSRef ref;
- ZeroInit(&ref);
- (void) FSRefFromPath((const char*)(*this), &ref);
-
- return ref;
- }
- const CHXString& CHXString::operator =(CFStringRef ref)
- {
- #ifdef _MAC_CFM
- CFStringEncoding encoding = CFStringGetSystemEncoding();
- #else
- CFStringEncoding encoding = kCFStringEncodingUTF8;
- #endif
- // we need the string to be canonically decomposed Unicode in case it'll be used as a path on
- // an HFS disk, so we'll make a mutable copy of the string, normalize it, and then encode that as UTF-8
-
- const CFIndex kNoMaxLength = 0;
-
- CFMutableStringRef mutableRef = CFStringCreateMutableCopy(kCFAllocatorDefault, kNoMaxLength, ref);
- #ifndef __MWERKS__
- // our version of CodeWarrior doesn't have CFStringNormalize in the headers since they are pre-10.2 headers, alas
- CFStringNormalize(mutableRef, kCFStringNormalizationFormD);
- #endif
-
- (void) SetFromCFString(mutableRef, encoding);
- CFRelease(mutableRef);
-
- return *this;
- }
- HX_RESULT CHXString::SetFromCFString(CFStringRef ref, CFStringEncoding encoding)
- {
- CHXString strTemp;
- char * pBuffer;
- BOOL bSuccess;
- CFIndex buffSize;
- bSuccess = FALSE;
- //const CFStringEncoding kEncoding = kCFStringEncodingUTF8;
- buffSize = 1 + CFStringGetMaximumSizeForEncoding(CFStringGetLength(ref), encoding);
- pBuffer = strTemp.GetBuffer(buffSize);
- if (pBuffer)
- {
- bSuccess = CFStringGetCString(ref, pBuffer, buffSize, encoding);
- strTemp.ReleaseBuffer();
- }
- *this = strTemp;
- return bSuccess ? HXR_OK : HXR_FAIL;
- }
- HX_RESULT CHXString::SetFromHFSUniStr255(const HFSUniStr255& uniName,
- CFStringEncoding encoding)
- {
- CHXCFString cfs(uniName);
- if (cfs.IsSet())
- {
- SetFromCFString(cfs, encoding);
- return HXR_OK;
- }
- return HXR_FAIL;
- }
- HX_RESULT CHXString::MakeHFSUniStr255(HFSUniStr255& outUniName, CFStringEncoding encoding) const
- {
- if (GetLength() < 256)
- {
- CHXCFString cfs((const char*)(*this), encoding);
- if (cfs.IsSet())
- {
- outUniName = (HFSUniStr255) cfs;
- return HXR_OK;
- }
- }
- return HXR_FAIL;
- }
- #endif /* _CARBON || _MAC_UNIX */
- #endif /* _MACINTOSH || _MAC_UNIX */
- void CHXString::Init(const char* pStr, UINT32 size)
- {
- if (size == UINT_MAX)
- size = (UINT32)SafeStrlen(pStr);
- if (m_pRep)
- {
- if ((UINT32)m_pRep->GetBufferSize() < (size + 1))
- m_pRep->Resize(size);
-
- strncpy(m_pRep->GetBuffer(), pStr, size); /* Flawfinder: ignore */
- m_pRep->GetBuffer()[size] = ' ';
- m_pRep->SetStringSize(SafeStrlen(m_pRep->GetBuffer()));
- }
- else
- m_pRep = new CHXStringRep(pStr, size);
- }
- void CHXString::Nuke()
- {
- if (m_pRep)
- {
- m_pRep->Release();
- m_pRep = 0;
- }
- }
- void CHXString::ConcatInPlace(const char* pStr, const UINT32 size)
- {
- Append(pStr, (INT32)size);
- }
- void CHXString::EnsureUnique()
- {
- if (m_pRep && m_pRep->IsShared())
- {
- // m_pRep is being shared. Time to copy it so that we
- // have our own copy.
- CHXStringRep* pOld = m_pRep;
- m_pRep = new CHXStringRep(pOld->GetBuffer(),
- pOld->GetStringSize());
- pOld->Release();
- }
- }
- void CHXString::Release()
- {
- }
- INT32 CHXString::MinimalGrowth(INT32 currentSize, INT32 sizeNeeded)
- {
- return sizeNeeded;
- }
- INT32 CHXString::DoublingGrowth(INT32 currentSize, INT32 sizeNeeded)
- {
- INT32 ret = currentSize;
- while (ret < sizeNeeded)
- ret *= 2;
- return ret;
- }
- void CHXString::Append(const char* pStr, INT32 size)
- {
- HX_ASSERT(size >= 0);
- if (size)
- {
- if (m_pRep)
- {
- EnsureUnique();
-
- int newSize = m_pRep->GetStringSize() + size;
- Grow(newSize + 1);
- strncpy(m_pRep->GetBuffer() + m_pRep->GetStringSize(), pStr, size); /* Flawfinder: ignore */
-
- m_pRep->GetBuffer()[newSize] = ' ';
- m_pRep->SetStringSize(newSize);
- }
- else
- m_pRep = new CHXStringRep(pStr, size);
- }
- }
- void CHXString::Grow(INT32 newSize)
- {
- HX_ASSERT(m_pRep);
- HX_ASSERT(newSize >= 0);
- if (newSize > m_pRep->GetBufferSize())
- {
- INT32 growSize = m_pGrowthFunc(m_pRep->GetBufferSize(), newSize);
-
- // Protect ourselves from bad grow functions
- if (growSize < newSize)
- growSize = newSize;
-
- m_pRep->ResizeAndCopy(growSize - 1);
- }
- }