1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/arrstr.cpp
3 // Purpose: wxArrayString class
4 // Author: Vadim Zeitlin
8 // Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ===========================================================================
13 // headers, declarations, constants
14 // ===========================================================================
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
23 #include "wx/arrstr.h"
25 #include "wx/beforestd.h"
28 #include "wx/afterstd.h"
30 // ============================================================================
32 // ============================================================================
34 wxArrayString::wxArrayString(size_t sz, const char** a)
39 for (size_t i=0; i < sz; i++)
43 wxArrayString::wxArrayString(size_t sz, const wchar_t** a)
48 for (size_t i=0; i < sz; i++)
52 wxArrayString::wxArrayString(size_t sz, const wxString* a)
57 for (size_t i=0; i < sz; i++)
63 // size increment = min(50% of current size, ARRAY_MAXSIZE_INCREMENT)
64 #define ARRAY_MAXSIZE_INCREMENT 4096
66 #ifndef ARRAY_DEFAULT_INITIAL_SIZE // also defined in dynarray.h
67 #define ARRAY_DEFAULT_INITIAL_SIZE (16)
71 void wxArrayString::Init(bool autoSort)
76 m_autoSort = autoSort;
80 wxArrayString::wxArrayString(const wxArrayString& src)
87 // assignment operator
88 wxArrayString& wxArrayString::operator=(const wxArrayString& src)
95 m_autoSort = src.m_autoSort;
100 void wxArrayString::Copy(const wxArrayString& src)
102 if ( src.m_nCount > ARRAY_DEFAULT_INITIAL_SIZE )
105 for ( size_t n = 0; n < src.m_nCount; n++ )
110 void wxArrayString::Grow(size_t nIncrement)
112 // only do it if no more place
113 if ( (m_nSize - m_nCount) < nIncrement ) {
114 // if ARRAY_DEFAULT_INITIAL_SIZE were set to 0, the initially empty would
116 #if ARRAY_DEFAULT_INITIAL_SIZE == 0
117 #error "ARRAY_DEFAULT_INITIAL_SIZE must be > 0!"
120 if ( m_nSize == 0 ) {
121 // was empty, alloc some memory
122 m_nSize = ARRAY_DEFAULT_INITIAL_SIZE;
123 if (m_nSize < nIncrement)
124 m_nSize = nIncrement;
125 m_pItems = new wxString[m_nSize];
128 // otherwise when it's called for the first time, nIncrement would be 0
129 // and the array would never be expanded
130 // add 50% but not too much
131 size_t ndefIncrement = m_nSize < ARRAY_DEFAULT_INITIAL_SIZE
132 ? ARRAY_DEFAULT_INITIAL_SIZE : m_nSize >> 1;
133 if ( ndefIncrement > ARRAY_MAXSIZE_INCREMENT )
134 ndefIncrement = ARRAY_MAXSIZE_INCREMENT;
135 if ( nIncrement < ndefIncrement )
136 nIncrement = ndefIncrement;
137 m_nSize += nIncrement;
138 wxString *pNew = new wxString[m_nSize];
140 // copy data to new location
141 for ( size_t j = 0; j < m_nCount; j++ )
142 pNew[j] = m_pItems[j];
144 // delete old memory (but do not release the strings!)
152 // deletes all the strings from the list
153 void wxArrayString::Empty()
158 // as Empty, but also frees memory
159 void wxArrayString::Clear()
168 wxArrayString::~wxArrayString()
173 void wxArrayString::reserve(size_t nSize)
178 // pre-allocates memory (frees the previous data!)
179 void wxArrayString::Alloc(size_t nSize)
181 // only if old buffer was not big enough
182 if ( nSize > m_nSize ) {
183 wxString *pNew = new wxString[nSize];
187 for ( size_t j = 0; j < m_nCount; j++ )
188 pNew[j] = m_pItems[j];
196 // minimizes the memory usage by freeing unused memory
197 void wxArrayString::Shrink()
199 // only do it if we have some memory to free
200 if( m_nCount < m_nSize ) {
201 // allocates exactly as much memory as we need
202 wxString *pNew = new wxString[m_nCount];
204 // copy data to new location
205 for ( size_t j = 0; j < m_nCount; j++ )
206 pNew[j] = m_pItems[j];
213 // searches the array for an item (forward or backwards)
214 int wxArrayString::Index(const wxString& str, bool bCase, bool bFromEnd) const
217 // use binary search in the sorted array
218 wxASSERT_MSG( bCase && !bFromEnd,
219 wxT("search parameters ignored for auto sorted array") );
228 res = str.compare(m_pItems[i]);
240 // use linear search in unsorted array
242 if ( m_nCount > 0 ) {
243 size_t ui = m_nCount;
245 if ( m_pItems[--ui].IsSameAs(str, bCase) )
252 for( size_t ui = 0; ui < m_nCount; ui++ ) {
253 if( m_pItems[ui].IsSameAs(str, bCase) )
262 // add item at the end
263 size_t wxArrayString::Add(const wxString& str, size_t nInsert)
266 // insert the string at the correct position to keep the array sorted
274 res = str.Cmp(m_pItems[i]);
285 wxASSERT_MSG( lo == hi, wxT("binary search broken") );
287 Insert(str, lo, nInsert);
294 for (size_t i = 0; i < nInsert; i++)
297 m_pItems[m_nCount + i] = str;
299 size_t ret = m_nCount;
305 // add item at the given position
306 void wxArrayString::Insert(const wxString& str, size_t nIndex, size_t nInsert)
308 wxCHECK_RET( nIndex <= m_nCount, wxT("bad index in wxArrayString::Insert") );
309 wxCHECK_RET( m_nCount <= m_nCount + nInsert,
310 wxT("array size overflow in wxArrayString::Insert") );
314 for (int j = m_nCount - nIndex - 1; j >= 0; j--)
315 m_pItems[nIndex + nInsert + j] = m_pItems[nIndex + j];
317 for (size_t i = 0; i < nInsert; i++)
319 m_pItems[nIndex + i] = str;
324 // range insert (STL 23.2.4.3)
326 wxArrayString::insert(iterator it, const_iterator first, const_iterator last)
328 const int idx = it - begin();
333 // reset "it" since it can change inside Grow()
336 while ( first != last )
338 it = insert(it, *first);
340 // insert returns an iterator to the last element inserted but we need
341 // insert the next after this one, that is before the next one
348 void wxArrayString::resize(size_type n, value_type v)
352 else if ( n > m_nCount )
353 Add(v, n - m_nCount);
357 void wxArrayString::SetCount(size_t count)
362 while ( m_nCount < count )
363 m_pItems[m_nCount++] = s;
366 // removes item from array (by index)
367 void wxArrayString::RemoveAt(size_t nIndex, size_t nRemove)
369 wxCHECK_RET( nIndex < m_nCount, wxT("bad index in wxArrayString::Remove") );
370 wxCHECK_RET( nIndex + nRemove <= m_nCount,
371 wxT("removing too many elements in wxArrayString::Remove") );
373 for ( size_t j = 0; j < m_nCount - nIndex -nRemove; j++)
374 m_pItems[nIndex + j] = m_pItems[nIndex + nRemove + j];
379 // removes item from array (by value)
380 void wxArrayString::Remove(const wxString& sz)
382 int iIndex = Index(sz);
384 wxCHECK_RET( iIndex != wxNOT_FOUND,
385 wxT("removing inexistent element in wxArrayString::Remove") );
390 // ----------------------------------------------------------------------------
392 // ----------------------------------------------------------------------------
394 // we need an adaptor as our predicates use qsort() convention and so return
395 // negative, null or positive value depending on whether the first item is less
396 // than, equal to or greater than the other one while we need a real boolean
397 // predicate now that we use std::sort()
398 struct wxSortPredicateAdaptor
400 wxSortPredicateAdaptor(wxArrayString::CompareFunction compareFunction)
401 : m_compareFunction(compareFunction)
405 bool operator()(const wxString& first, const wxString& second) const
407 return (*m_compareFunction)(first, second) < 0;
410 wxArrayString::CompareFunction m_compareFunction;
413 void wxArrayString::Sort(CompareFunction compareFunction)
415 wxCHECK_RET( !m_autoSort, wxT("can't use this method with sorted arrays") );
417 std::sort(m_pItems, m_pItems + m_nCount,
418 wxSortPredicateAdaptor(compareFunction));
421 struct wxSortPredicateAdaptor2
423 wxSortPredicateAdaptor2(wxArrayString::CompareFunction2 compareFunction)
424 : m_compareFunction(compareFunction)
428 bool operator()(const wxString& first, const wxString& second) const
430 return (*m_compareFunction)(const_cast<wxString *>(&first),
431 const_cast<wxString *>(&second)) < 0;
434 wxArrayString::CompareFunction2 m_compareFunction;
437 void wxArrayString::Sort(CompareFunction2 compareFunction)
439 std::sort(m_pItems, m_pItems + m_nCount,
440 wxSortPredicateAdaptor2(compareFunction));
443 void wxArrayString::Sort(bool reverseOrder)
446 std::sort(m_pItems, m_pItems + m_nCount, std::greater<wxString>());
448 std::sort(m_pItems, m_pItems + m_nCount);
451 bool wxArrayString::operator==(const wxArrayString& a) const
453 if ( m_nCount != a.m_nCount )
456 for ( size_t n = 0; n < m_nCount; n++ )
458 if ( Item(n) != a[n] )
467 // ===========================================================================
468 // wxJoin and wxSplit
469 // ===========================================================================
471 #include "wx/tokenzr.h"
473 wxString wxJoin(const wxArrayString& arr, const wxChar sep, const wxChar escape)
475 size_t count = arr.size();
477 return wxEmptyString;
481 // pre-allocate memory using the estimation of the average length of the
482 // strings in the given array: this is very imprecise, of course, but
483 // better than nothing
484 str.reserve(count*(arr[0].length() + arr[count-1].length()) / 2);
486 if ( escape == wxT('\0') )
488 // escaping is disabled:
489 for ( size_t i = 0; i < count; i++ )
496 else // use escape character
498 for ( size_t n = 0; n < count; n++ )
503 for ( wxString::const_iterator i = arr[n].begin(),
508 const wxChar ch = *i;
510 str += escape; // escape this separator
516 str.Shrink(); // release extra memory if we allocated too much
520 wxArrayString wxSplit(const wxString& str, const wxChar sep, const wxChar escape)
522 if ( escape == wxT('\0') )
524 // simple case: we don't need to honour the escape character
525 return wxStringTokenize(str, sep, wxTOKEN_RET_EMPTY_ALL);
530 wxChar prev = wxT('\0');
532 for ( wxString::const_iterator i = str.begin(),
537 const wxChar ch = *i;
541 if ( prev == escape )
543 // remove the escape character and don't consider this
544 // occurrence of 'sep' as a real separator
545 *curr.rbegin() = sep;
547 else // real separator
553 else // normal character
561 // add the last token
562 if ( !curr.empty() || prev == sep )