#include "wx/string.h"
#include "wx/intl.h"
#if wxUSE_THREADS
- #include <wx/thread.h>
+ #include "wx/thread.h"
#endif
#endif
{
wxStringData data;
wxChar dummy;
-} g_strEmpty = { {-1, 0, 0}, _T('\0') };
+} g_strEmpty = { {-1, 0, 0}, wxT('\0') };
// empty C style string: points to 'string data' byte of g_strEmpty
-extern const wxChar WXDLLEXPORT *g_szNul = &g_strEmpty.dummy;
+extern const wxChar WXDLLEXPORT *wxEmptyString = &g_strEmpty.dummy;
// ----------------------------------------------------------------------------
// conditional compilation
return is;
}
+ostream& operator<<(ostream& os, const wxString& str)
+{
+ os << str.c_str();
+ return os;
+}
+
#endif //std::string compatibility
// ----------------------------------------------------------------------------
}
}
-#else
+#else // ANSI
#if wxUSE_WCHAR_T
// from wide string
Init();
}
}
-#endif
+#endif // wxUSE_WCHAR_T
-#endif
+#endif // Unicode/ANSI
// ---------------------------------------------------------------------------
// memory allocation
pData->nDataLength = nLen;
pData->nAllocLength = nLen + EXTRA_ALLOC;
m_pchData = pData->data(); // data starts after wxStringData
- m_pchData[nLen] = _T('\0');
+ m_pchData[nLen] = wxT('\0');
}
// must be called before changing this string
pData->nDataLength = 0;
pData->nAllocLength = nLen;
m_pchData = pData->data(); // data starts after wxStringData
- m_pchData[0u] = _T('\0');
+ m_pchData[0u] = wxT('\0');
}
else if ( pData->IsShared() ) {
pData->Unlock(); // memory not freed because shared
AllocBeforeWrite(nSrcLen);
memcpy(m_pchData, pszSrcData, nSrcLen*sizeof(wxChar));
GetStringData()->nDataLength = nSrcLen;
- m_pchData[nSrcLen] = _T('\0');
+ m_pchData[nSrcLen] = wxT('\0');
}
}
// fast concatenation - all is done in our buffer
memcpy(m_pchData + nLen, pszSrcData, nSrcLen*sizeof(wxChar));
- m_pchData[nNewLen] = _T('\0'); // put terminating '\0'
+ m_pchData[nNewLen] = wxT('\0'); // put terminating '\0'
GetStringData()->nDataLength = nNewLen; // and fix the length
}
//else: the string to append was empty
wxString wxString::BeforeFirst(wxChar ch) const
{
wxString str;
- for ( const wxChar *pc = m_pchData; *pc != _T('\0') && *pc != ch; pc++ )
+ for ( const wxChar *pc = m_pchData; *pc != wxT('\0') && *pc != ch; pc++ )
str += *pc;
return str;
wxString strTemp;
const wxChar *pCurrent = m_pchData;
const wxChar *pSubstr;
- while ( *pCurrent != _T('\0') ) {
+ while ( *pCurrent != wxT('\0') ) {
pSubstr = wxStrstr(pCurrent, szOld);
if ( pSubstr == NULL ) {
// strTemp is unused if no replacements were made, so avoid the copy
psz--;
// truncate at trailing space start
- *++psz = _T('\0');
+ *++psz = wxT('\0');
GetStringData()->nDataLength = psz - m_pchData;
}
else
if ( uiLen < Len() ) {
CopyBeforeWrite();
- *(m_pchData + uiLen) = _T('\0');
+ *(m_pchData + uiLen) = wxT('\0');
GetStringData()->nDataLength = uiLen;
}
//else: nothing to do, string is already short enough
wxString& wxString::operator<<(int i)
{
wxString res;
- res.Printf(_T("%d"), i);
+ res.Printf(wxT("%d"), i);
return (*this) << res;
}
wxString& wxString::operator<<(float f)
{
wxString res;
- res.Printf(_T("%f"), f);
+ res.Printf(wxT("%f"), f);
return (*this) << res;
}
wxString& wxString::operator<<(double d)
{
wxString res;
- res.Printf(_T("%g"), d);
+ res.Printf(wxT("%g"), d);
return (*this) << res;
}
Reinit();
for (size_t n = 0; pszFormat[n]; n++)
- if (pszFormat[n] == _T('%')) {
+ if (pszFormat[n] == wxT('%')) {
static char s_szFlags[256] = "%";
size_t flagofs = 1;
bool adj_left = FALSE, in_prec = FALSE,
do {
#define CHECK_PREC if (in_prec && !prec_dot) { s_szFlags[flagofs++] = '.'; prec_dot = TRUE; }
switch (pszFormat[++n]) {
- case _T('\0'):
+ case wxT('\0'):
done = TRUE;
break;
- case _T('%'):
- *this += _T('%');
+ case wxT('%'):
+ *this += wxT('%');
done = TRUE;
break;
- case _T('#'):
- case _T('0'):
- case _T(' '):
- case _T('+'):
- case _T('\''):
+ case wxT('#'):
+ case wxT('0'):
+ case wxT(' '):
+ case wxT('+'):
+ case wxT('\''):
CHECK_PREC
s_szFlags[flagofs++] = pszFormat[n];
break;
- case _T('-'):
+ case wxT('-'):
CHECK_PREC
adj_left = TRUE;
s_szFlags[flagofs++] = pszFormat[n];
break;
- case _T('.'):
+ case wxT('.'):
CHECK_PREC
in_prec = TRUE;
prec_dot = FALSE;
max_width = 0;
// dot will be auto-added to s_szFlags if non-negative number follows
break;
- case _T('h'):
+ case wxT('h'):
ilen = -1;
CHECK_PREC
s_szFlags[flagofs++] = pszFormat[n];
break;
- case _T('l'):
+ case wxT('l'):
ilen = 1;
CHECK_PREC
s_szFlags[flagofs++] = pszFormat[n];
break;
- case _T('q'):
- case _T('L'):
+ case wxT('q'):
+ case wxT('L'):
ilen = 2;
CHECK_PREC
s_szFlags[flagofs++] = pszFormat[n];
break;
- case _T('Z'):
+ case wxT('Z'):
ilen = 3;
CHECK_PREC
s_szFlags[flagofs++] = pszFormat[n];
break;
- case _T('*'):
+ case wxT('*'):
{
int len = va_arg(argptr, int);
if (in_prec) {
flagofs += ::sprintf(s_szFlags+flagofs,"%d",len);
}
break;
- case _T('1'): case _T('2'): case _T('3'):
- case _T('4'): case _T('5'): case _T('6'):
- case _T('7'): case _T('8'): case _T('9'):
+ case wxT('1'): case wxT('2'): case wxT('3'):
+ case wxT('4'): case wxT('5'): case wxT('6'):
+ case wxT('7'): case wxT('8'): case wxT('9'):
{
int len = 0;
CHECK_PREC
- while ((pszFormat[n]>=_T('0')) && (pszFormat[n]<=_T('9'))) {
+ while ((pszFormat[n]>=wxT('0')) && (pszFormat[n]<=wxT('9'))) {
s_szFlags[flagofs++] = pszFormat[n];
- len = len*10 + (pszFormat[n] - _T('0'));
+ len = len*10 + (pszFormat[n] - wxT('0'));
n++;
}
if (in_prec) max_width = len;
n--; // the main loop pre-increments n again
}
break;
- case _T('d'):
- case _T('i'):
- case _T('o'):
- case _T('u'):
- case _T('x'):
- case _T('X'):
+ case wxT('d'):
+ case wxT('i'):
+ case wxT('o'):
+ case wxT('u'):
+ case wxT('x'):
+ case wxT('X'):
CHECK_PREC
s_szFlags[flagofs++] = pszFormat[n];
s_szFlags[flagofs] = '\0';
*this += wxString(s_szScratch);
done = TRUE;
break;
- case _T('e'):
- case _T('E'):
- case _T('f'):
- case _T('g'):
- case _T('G'):
+ case wxT('e'):
+ case wxT('E'):
+ case wxT('f'):
+ case wxT('g'):
+ case wxT('G'):
CHECK_PREC
s_szFlags[flagofs++] = pszFormat[n];
s_szFlags[flagofs] = '\0';
*this += wxString(s_szScratch);
done = TRUE;
break;
- case _T('p'):
+ case wxT('p'):
{
void *val = va_arg(argptr, void *);
CHECK_PREC
done = TRUE;
}
break;
- case _T('c'):
+ case wxT('c'):
{
wxChar val = va_arg(argptr, int);
// we don't need to honor padding here, do we?
done = TRUE;
}
break;
- case _T('s'):
+ case wxT('s'):
if (ilen == -1) {
// wx extension: we'll let %hs mean non-Unicode strings
char *val = va_arg(argptr, char *);
size_t len = wxSTRING_MAXLEN;
if (val) {
for (len = 0; val[len] && (len<max_width); len++);
- } else val = _T("(null)");
+ } else val = wxT("(null)");
wxString s(val, len);
#endif
if (s.Len() < min_width)
- s.Pad(min_width - s.Len(), _T(' '), adj_left);
+ s.Pad(min_width - s.Len(), wxT(' '), adj_left);
*this += s;
} else {
wxChar *val = va_arg(argptr, wxChar *);
size_t len = wxSTRING_MAXLEN;
if (val) {
for (len = 0; val[len] && (len<max_width); len++);
- } else val = _T("(null)");
+ } else val = wxT("(null)");
wxString s(val, len);
if (s.Len() < min_width)
- s.Pad(min_width - s.Len(), _T(' '), adj_left);
+ s.Pad(min_width - s.Len(), wxT(' '), adj_left);
*this += s;
}
done = TRUE;
break;
- case _T('n'):
+ case wxT('n'):
if (ilen == 0) {
int *val = va_arg(argptr, int *);
*val = Len();
s_szFlags[flagofs++] = pszFormat[n];
else {
// bad format
- *this += _T('%'); // just to pass the glibc tst-printf.c
+ *this += wxT('%'); // just to pass the glibc tst-printf.c
n--;
done = TRUE;
}
// ----------------------------------------------------------------------------
// misc other operations
// ----------------------------------------------------------------------------
+
+// returns TRUE if the string matches the pattern which may contain '*' and
+// '?' metacharacters (as usual, '?' matches any character and '*' any number
+// of them)
bool wxString::Matches(const wxChar *pszMask) const
{
// check char by char
const wxChar *pszTxt;
- for ( pszTxt = c_str(); *pszMask != _T('\0'); pszMask++, pszTxt++ ) {
+ for ( pszTxt = c_str(); *pszMask != wxT('\0'); pszMask++, pszTxt++ ) {
switch ( *pszMask ) {
- case _T('?'):
- if ( *pszTxt == _T('\0') )
+ case wxT('?'):
+ if ( *pszTxt == wxT('\0') )
return FALSE;
- pszTxt++;
- pszMask++;
+ // pszText and pszMask will be incremented in the loop statement
+
break;
- case _T('*'):
+ case wxT('*'):
{
// ignore special chars immediately following this one
- while ( *pszMask == _T('*') || *pszMask == _T('?') )
+ while ( *pszMask == wxT('*') || *pszMask == wxT('?') )
pszMask++;
// if there is nothing more, match
- if ( *pszMask == _T('\0') )
+ if ( *pszMask == wxT('\0') )
return TRUE;
// are there any other metacharacters in the mask?
size_t uiLenMask;
- const wxChar *pEndMask = wxStrpbrk(pszMask, _T("*?"));
+ const wxChar *pEndMask = wxStrpbrk(pszMask, wxT("*?"));
if ( pEndMask != NULL ) {
// we have to match the string between two metachars
}
// match only if nothing left
- return *pszTxt == _T('\0');
+ return *pszTxt == wxT('\0');
}
// Count the number of chars
#define STRING(p) ((wxString *)(&(p)))
// ctor
-wxArrayString::wxArrayString()
+wxArrayString::wxArrayString(bool autoSort)
{
m_nSize =
m_nCount = 0;
m_pItems = (wxChar **) NULL;
+ m_autoSort = autoSort;
}
// copy ctor
m_nSize =
m_nCount = 0;
m_pItems = (wxChar **) NULL;
+ m_autoSort = src.m_autoSort;
*this = src;
}
if ( m_nSize > 0 )
Clear();
+ Copy(src);
+
+ return *this;
+}
+
+void wxArrayString::Copy(const wxArrayString& src)
+{
if ( src.m_nCount > ARRAY_DEFAULT_INITIAL_SIZE )
Alloc(src.m_nCount);
// we can't just copy the pointers here because otherwise we would share
- // the strings with another array
- for ( size_t n = 0; n < src.m_nCount; n++ )
- Add(src[n]);
-
+ // the strings with another array because strings are ref counted
+#if 0
if ( m_nCount != 0 )
memcpy(m_pItems, src.m_pItems, m_nCount*sizeof(wxChar *));
+#endif // 0
- return *this;
+ for ( size_t n = 0; n < src.m_nCount; n++ )
+ Add(src[n]);
+
+ // if the other array is auto sorted too, we're already sorted, but
+ // otherwise we should rearrange the items
+ if ( m_autoSort && !src.m_autoSort )
+ Sort();
}
// grow the array
else {
// otherwise when it's called for the first time, nIncrement would be 0
// and the array would never be expanded
-#if defined(__VISAGECPP__)
- int array_size = ARRAY_DEFAULT_INITIAL_SIZE;
+#if defined(__VISAGECPP__) && defined(__WXDEBUG__)
+ int array_size = ARRAY_DEFAULT_INITIAL_SIZE;
wxASSERT( array_size != 0 );
#else
wxASSERT( ARRAY_DEFAULT_INITIAL_SIZE != 0 );
// searches the array for an item (forward or backwards)
int wxArrayString::Index(const wxChar *sz, bool bCase, bool bFromEnd) const
{
- if ( bFromEnd ) {
- if ( m_nCount > 0 ) {
- size_t ui = m_nCount;
- do {
- if ( STRING(m_pItems[--ui])->IsSameAs(sz, bCase) )
- return ui;
- }
- while ( ui != 0 );
+ if ( m_autoSort ) {
+ // use binary search in the sorted array
+ wxASSERT_MSG( bCase && !bFromEnd,
+ wxT("search parameters ignored for auto sorted array") );
+
+ size_t i,
+ lo = 0,
+ hi = m_nCount;
+ int res;
+ while ( lo < hi ) {
+ i = (lo + hi)/2;
+
+ res = wxStrcmp(sz, m_pItems[i]);
+ if ( res < 0 )
+ hi = i;
+ else if ( res > 0 )
+ lo = i + 1;
+ else
+ return i;
}
+
+ return wxNOT_FOUND;
}
else {
- for( size_t ui = 0; ui < m_nCount; ui++ ) {
- if( STRING(m_pItems[ui])->IsSameAs(sz, bCase) )
- return ui;
+ // use linear search in unsorted array
+ if ( bFromEnd ) {
+ if ( m_nCount > 0 ) {
+ size_t ui = m_nCount;
+ do {
+ if ( STRING(m_pItems[--ui])->IsSameAs(sz, bCase) )
+ return ui;
+ }
+ while ( ui != 0 );
+ }
+ }
+ else {
+ for( size_t ui = 0; ui < m_nCount; ui++ ) {
+ if( STRING(m_pItems[ui])->IsSameAs(sz, bCase) )
+ return ui;
+ }
}
}
}
// add item at the end
-void wxArrayString::Add(const wxString& str)
-{
- wxASSERT( str.GetStringData()->IsValid() );
+size_t wxArrayString::Add(const wxString& str)
+{
+ if ( m_autoSort ) {
+ // insert the string at the correct position to keep the array sorted
+ size_t i,
+ lo = 0,
+ hi = m_nCount;
+ int res;
+ while ( lo < hi ) {
+ i = (lo + hi)/2;
+
+ res = wxStrcmp(str, m_pItems[i]);
+ if ( res < 0 )
+ hi = i;
+ else if ( res > 0 )
+ lo = i + 1;
+ else {
+ lo = hi = i;
+ break;
+ }
+ }
- Grow();
+ wxASSERT_MSG( lo == hi, wxT("binary search broken") );
- // the string data must not be deleted!
- str.GetStringData()->Lock();
- m_pItems[m_nCount++] = (wxChar *)str.c_str();
+ Insert(str, lo);
+
+ return (size_t)lo;
+ }
+ else {
+ wxASSERT( str.GetStringData()->IsValid() );
+
+ Grow();
+
+ // the string data must not be deleted!
+ str.GetStringData()->Lock();
+
+ // just append
+ m_pItems[m_nCount] = (wxChar *)str.c_str(); // const_cast
+
+ return m_nCount++;
+ }
}
// add item at the given position
{
wxASSERT( str.GetStringData()->IsValid() );
- wxCHECK_RET( nIndex <= m_nCount, _("bad index in wxArrayString::Insert") );
+ wxCHECK_RET( nIndex <= m_nCount, wxT("bad index in wxArrayString::Insert") );
Grow();
// removes item from array (by index)
void wxArrayString::Remove(size_t nIndex)
{
- wxCHECK_RET( nIndex <= m_nCount, _("bad index in wxArrayString::Remove") );
+ wxCHECK_RET( nIndex <= m_nCount, wxT("bad index in wxArrayString::Remove") );
// release our lock
Item(nIndex).GetStringData()->Unlock();
int iIndex = Index(sz);
wxCHECK_RET( iIndex != wxNOT_FOUND,
- _("removing inexistent element in wxArrayString::Remove") );
+ wxT("removing inexistent element in wxArrayString::Remove") );
Remove(iIndex);
}
void wxArrayString::DoSort()
{
+ wxCHECK_RET( !m_autoSort, wxT("can't use this method with sorted arrays") );
+
// just sort the pointers using qsort() - of course it only works because
// wxString() *is* a pointer to its data
qsort(m_pItems, m_nCount, sizeof(wxChar *), wxStringCompareFunction);