/////////////////////////////////////////////////////////////////////////////
#ifdef __GNUG__
-#pragma implementation "string.h"
+ #pragma implementation "string.h"
#endif
/*
#include "wx/wxprec.h"
#ifdef __BORLANDC__
-#pragma hdrstop
+ #pragma hdrstop
#endif
#ifndef WX_PRECOMP
#include <string.h>
#include <stdlib.h>
-// This probably isn't right, what should it be Vadim?
-// Otherwise we end up with no wxVsprintf defined.
-#ifdef __WXMOTIF__
-#define HAVE_VPRINTF
+#ifdef __SALFORDC__
+ #include <clib.h>
#endif
-#ifdef wxUSE_WCSRTOMBS
+#if wxUSE_WCSRTOMBS
#include <wchar.h> // for wcsrtombs(), see comments where it's used
#endif // GNU
// static class variables definition
// ---------------------------------------------------------------------------
-#ifdef STD_STRING_COMPATIBILITY
- const size_t wxString::npos = STRING_MAXLEN;
-#endif
+#ifdef wxSTD_STRING_COMPATIBILITY
+ const size_t wxString::npos = wxSTRING_MAXLEN;
+#endif // wxSTD_STRING_COMPATIBILITY
// ----------------------------------------------------------------------------
// static data
} g_strEmpty = { {-1, 0, 0}, '\0' };
// empty C style string: points to 'string data' byte of g_strEmpty
-extern const char *g_szNul = &g_strEmpty.dummy;
+extern const char WXDLLEXPORT *g_szNul = &g_strEmpty.dummy;
// ----------------------------------------------------------------------------
// conditional compilation
// function: for Unix this is done with configure, for Windows we test the
// compiler explicitly.
#ifdef __WXMSW__
- #ifdef _MSC_VER
+ #ifdef __VISUALC__
#define wxVsprintf _vsnprintf
#endif
#else // !Windows
// always available), but it's unsafe because it doesn't check for buffer
// size - so give a warning
#define wxVsprintf(buffer,len,format,argptr) vsprintf(buffer,format, argptr)
- #pragma message("Using sprintf() because no snprintf()-like function defined")
+
+ #if defined(__VISUALC__)
+ #pragma message("Using sprintf() because no snprintf()-like function defined")
+ #elif defined(__GNUG__) && !defined(__UNIX__)
+ #warning "Using sprintf() because no snprintf()-like function defined"
+ #elif defined(__MWERKS__)
+ #warning "Using sprintf() because no snprintf()-like function defined"
+ #endif //compiler
+#endif // no vsnprintf
+
+#ifdef _AIX
+ // AIX has vsnprintf, but there's no prototype in the system headers.
+ extern "C" int vsnprintf(char* str, size_t n, const char* format, va_list ap);
#endif
// ----------------------------------------------------------------------------
// global functions
// ----------------------------------------------------------------------------
-#ifdef STD_STRING_COMPATIBILITY
+#ifdef wxSTD_STRING_COMPATIBILITY
// MS Visual C++ version 5.0 provides the new STL headers as well as the old
// iostream ones.
//
// ATTN: you can _not_ use both of these in the same program!
-#if wxUSE_IOSTREAMH
-#include <iostream.h>
-#define NAMESPACE
-#else
-#include <iostream>
-# ifdef _MSC_VER
- using namespace std;
-# endif
-// for msvc (bcc50+ also) you don't need these NAMESPACE defines,
-// using namespace std; takes care of that.
-#define NAMESPACE std::
-#endif
-#ifdef __WXMSW__
- #ifdef _MSC_VER
- #define wxVsprintf _vsnprintf
- #endif
-#else
- #if defined ( HAVE_VSNPRINTF )
- #define wxVsprintf vsnprintf
- #endif
-#endif
-
-#ifndef wxVsprintf
- // vsprintf() is ANSI so we can always use it, but it's unsafe!
- #define wxVsprintf(buffer,len,format,argptr) vsprintf(buffer,format, argptr)
- #pragma message("Using sprintf() because no snprintf()-like function defined")
-#endif
-
-NAMESPACE istream& operator>>(NAMESPACE istream& is, wxString& WXUNUSED(str))
+istream& operator>>(istream& is, wxString& WXUNUSED(str))
{
#if 0
int w = is.width(0);
if ( is.ipfx(0) ) {
- NAMESPACE streambuf *sb = is.rdbuf();
+ streambuf *sb = is.rdbuf();
str.erase();
while ( true ) {
int ch = sb->sbumpc ();
if ( ch == EOF ) {
- is.setstate(NAMESPACE ios::eofbit);
+ is.setstate(ios::eofbit);
break;
}
else if ( isspace(ch) ) {
is.isfx();
if ( str.length() == 0 )
- is.setstate(NAMESPACE ios::failbit);
+ is.setstate(ios::failbit);
#endif
return is;
}
wxASSERT( nPos <= Strlen(psz) );
- if ( nLength == STRING_MAXLEN )
+ if ( nLength == wxSTRING_MAXLEN )
nLength = Strlen(psz + nPos);
STATISTICS_ADD(InitialLength, nLength);
InitWith((const char *)psz, 0, nLength);
}
-#ifdef STD_STRING_COMPATIBILITY
+#ifdef wxSTD_STRING_COMPATIBILITY
// poor man's iterators are "void *" pointers
wxString::wxString(const void *pStart, const void *pEnd)
// NB: GNU libc5 wcstombs() is completely broken, don't use it (it doesn't
// honor the 3rd parameter, thus it will happily crash here).
-#ifdef wxUSE_WCSRTOMBS
+#if wxUSE_WCSRTOMBS
// don't know if it's really needed (or if we can pass NULL), but better safe
// than quick
mbstate_t mbstate;
pData->Unlock();
AllocBuffer(nLen);
}
+ else {
+ // update the string length
+ pData->nDataLength = nLen;
+ }
wxASSERT( !GetStringData()->IsShared() ); // we must be the only owner
}
wxStringData *pData = GetStringData();
size_t nLen = pData->nDataLength;
- // default value of nCount is STRING_MAXLEN and means "till the end"
- if ( nCount == STRING_MAXLEN )
+ // default value of nCount is wxSTRING_MAXLEN and means "till the end"
+ if ( nCount == wxSTRING_MAXLEN )
{
nCount = nLen - nFirst;
}
// get all characters after the last occurence of ch
// (returns the whole string if ch not found)
-wxString wxString::Right(char ch) const
+wxString wxString::AfterLast(char ch) const
{
wxString str;
int iPos = Find(ch, TRUE);
- if ( iPos == NOT_FOUND )
+ if ( iPos == wxNOT_FOUND )
str = *this;
else
str = c_str() + iPos + 1;
// get all characters before the first occurence of ch
// (returns the whole string if ch not found)
-wxString wxString::Left(char ch) const
+wxString wxString::BeforeFirst(char ch) const
{
wxString str;
for ( const char *pc = m_pchData; *pc != '\0' && *pc != ch; pc++ )
/// get all characters before the last occurence of ch
/// (returns empty string if ch not found)
-wxString wxString::Before(char ch) const
+wxString wxString::BeforeLast(char ch) const
{
wxString str;
int iPos = Find(ch, TRUE);
- if ( iPos != NOT_FOUND && iPos != 0 )
+ if ( iPos != wxNOT_FOUND && iPos != 0 )
str = wxString(c_str(), iPos);
return str;
/// get all characters after the first occurence of ch
/// (returns empty string if ch not found)
-wxString wxString::After(char ch) const
+wxString wxString::AfterFirst(char ch) const
{
wxString str;
int iPos = Find(ch);
- if ( iPos != NOT_FOUND )
+ if ( iPos != wxNOT_FOUND )
str = c_str() + iPos + 1;
return str;
psz++;
// fix up data and length
- int nDataLength = GetStringData()->nDataLength - (psz - m_pchData);
+ int nDataLength = GetStringData()->nDataLength - (psz - (const char*) m_pchData);
memmove(m_pchData, psz, (nDataLength + 1)*sizeof(char));
GetStringData()->nDataLength = nDataLength;
}
}
// ---------------------------------------------------------------------------
-// finding (return NOT_FOUND if not found and index otherwise)
+// finding (return wxNOT_FOUND if not found and index otherwise)
// ---------------------------------------------------------------------------
// find a character
{
const char *psz = bFromEnd ? strrchr(m_pchData, ch) : strchr(m_pchData, ch);
- return (psz == NULL) ? NOT_FOUND : psz - m_pchData;
+ return (psz == NULL) ? wxNOT_FOUND : psz - (const char*) m_pchData;
}
// find a sub-string (like strstr)
{
const char *psz = strstr(m_pchData, pszSub);
- return (psz == NULL) ? NOT_FOUND : psz - m_pchData;
+ return (psz == NULL) ? wxNOT_FOUND : psz - (const char*) m_pchData;
}
// ---------------------------------------------------------------------------
return *pszTxt == '\0';
}
+// Count the number of chars
+int wxString::Freq(char ch) const
+{
+ int count = 0;
+ int len = Len();
+ for (int i = 0; i < len; i++)
+ {
+ if (GetChar(i) == ch)
+ count ++;
+ }
+ return count;
+}
+
+// convert to upper case, return the copy of the string
+wxString wxString::Upper() const
+{ wxString s(*this); return s.MakeUpper(); }
+
+// convert to lower case, return the copy of the string
+wxString wxString::Lower() const { wxString s(*this); return s.MakeLower(); }
+
+int wxString::sprintf(const char *pszFormat, ...)
+ {
+ va_list argptr;
+ va_start(argptr, pszFormat);
+ int iLen = PrintfV(pszFormat, argptr);
+ va_end(argptr);
+ return iLen;
+ }
+
// ---------------------------------------------------------------------------
// standard C++ library string functions
// ---------------------------------------------------------------------------
-#ifdef STD_STRING_COMPATIBILITY
+#ifdef wxSTD_STRING_COMPATIBILITY
wxString& wxString::insert(size_t nPos, const wxString& str)
{
}
// VC++ 1.5 can't cope with the default argument in the header.
-#if ! (defined(_MSC_VER) && !defined(__WIN32__))
+#if !defined(__VISUALC__) || defined(__WIN32__)
size_t wxString::find(const char* sz, size_t nStart, size_t n) const
{
return find(wxString(sz, n == npos ? 0 : n), nStart);
}
-#endif
+#endif // VC++ 1.5
// Gives a duplicate symbol (presumably a case-insensitivity problem)
#if !defined(__BORLANDC__)
}
// VC++ 1.5 can't cope with the default argument in the header.
-#if ! (defined(_MSC_VER) && !defined(__WIN32__))
+#if !defined(__VISUALC__) || defined(__WIN32__)
size_t wxString::rfind(const char* sz, size_t nStart, size_t n) const
{
return rfind(wxString(sz, n == npos ? 0 : n), nStart);
return p == NULL ? npos : p - c_str();
}
-#endif
+#endif // VC++ 1.5
wxString wxString::substr(size_t nStart, size_t nLen) const
{
}
}
- return NOT_FOUND;
+ return wxNOT_FOUND;
}
// add item at the end
{
int iIndex = Index(sz);
- wxCHECK_RET( iIndex != NOT_FOUND,
+ wxCHECK_RET( iIndex != wxNOT_FOUND,
_("removing inexistent element in wxArrayString::Remove") );
Remove(iIndex);
}
+// ----------------------------------------------------------------------------
+// sorting
+// ----------------------------------------------------------------------------
+
+// we can only sort one array at a time with the quick-sort based
+// implementation
+#if wxUSE_THREADS
+ #include <wx/thread.h>
+
+ // need a critical section to protect access to gs_compareFunction and
+ // gs_sortAscending variables
+ static wxCriticalSection *gs_critsectStringSort = NULL;
+
+ // call this before the value of the global sort vars is changed/after
+ // you're finished with them
+ #define START_SORT() wxASSERT( !gs_critsectStringSort ); \
+ gs_critsectStringSort = new wxCriticalSection; \
+ gs_critsectStringSort->Enter()
+ #define END_SORT() gs_critsectStringSort->Leave(); \
+ delete gs_critsectStringSort; \
+ gs_critsectStringSort = NULL
+#else // !threads
+ #define START_SORT()
+ #define END_SORT()
+#endif // wxUSE_THREADS
+
+// function to use for string comparaison
+static wxArrayString::CompareFunction gs_compareFunction = NULL;
+
+// if we don't use the compare function, this flag tells us if we sort the
+// array in ascending or descending order
+static bool gs_sortAscending = TRUE;
+
+// function which is called by quick sort
+static int wxStringCompareFunction(const void *first, const void *second)
+{
+ wxString *strFirst = (wxString *)first;
+ wxString *strSecond = (wxString *)second;
+
+ if ( gs_compareFunction ) {
+ return gs_compareFunction(*strFirst, *strSecond);
+ }
+ else {
+ int result = strcmp(strFirst->c_str(), strSecond->c_str());
+
+ return gs_sortAscending ? result : -result;
+ }
+}
+
// sort array elements using passed comparaison function
+void wxArrayString::Sort(CompareFunction compareFunction)
+{
+ START_SORT();
+
+ wxASSERT( !gs_compareFunction ); // must have been reset to NULL
+ gs_compareFunction = compareFunction;
+
+ DoSort();
+
+ END_SORT();
+}
+
+void wxArrayString::Sort(bool reverseOrder)
+{
+ START_SORT();
+
+ wxASSERT( !gs_compareFunction ); // must have been reset to NULL
+ gs_sortAscending = !reverseOrder;
+
+ DoSort();
+
+ END_SORT();
+}
-void wxArrayString::Sort(bool WXUNUSED(bCase), bool WXUNUSED(bReverse) )
+void wxArrayString::DoSort()
{
- //@@@@ TO DO
- //qsort(m_pItems, m_nCount, sizeof(char *), fCmp);
+ // 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(char *), wxStringCompareFunction);
}