Coverage Report

Created: 2025-06-13 06:30

/src/wxwidgets/include/wx/arrstr.h
Line
Count
Source (jump to first uncovered line)
1
///////////////////////////////////////////////////////////////////////////////
2
// Name:        wx/arrstr.h
3
// Purpose:     wxArrayString class
4
// Author:      Mattia Barbon and Vadim Zeitlin
5
// Created:     07/07/03
6
// Copyright:   (c) 2003 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
7
// Licence:     wxWindows licence
8
///////////////////////////////////////////////////////////////////////////////
9
10
#ifndef _WX_ARRSTR_H
11
#define _WX_ARRSTR_H
12
13
#include "wx/defs.h"
14
#include "wx/string.h"
15
#include "wx/dynarray.h"
16
17
// these functions are only used in STL build now but we define them in any
18
// case for compatibility with the existing code outside of the library which
19
// could be using them
20
inline int wxCMPFUNC_CONV wxStringSortAscending(const wxString& s1, const wxString& s2)
21
0
{
22
0
    return s1.Cmp(s2);
23
0
}
24
25
inline int wxCMPFUNC_CONV wxStringSortDescending(const wxString& s1, const wxString& s2)
26
0
{
27
0
    return wxStringSortAscending(s2, s1);
28
0
}
29
30
// This comparison function ignores case when comparing strings differing not
31
// in case only, i.e. this ensures that "Aa" comes before "AB", unlike with
32
// wxStringSortAscending().
33
inline int wxCMPFUNC_CONV
34
wxDictionaryStringSortAscending(const wxString& s1, const wxString& s2)
35
0
{
36
0
    const int cmp = s1.CmpNoCase(s2);
37
0
    return cmp ? cmp : s1.Cmp(s2);
38
0
}
39
40
41
inline int wxCMPFUNC_CONV
42
wxDictionaryStringSortDescending(const wxString& s1, const wxString& s2)
43
0
{
44
0
    return wxDictionaryStringSortAscending(s2, s1);
45
0
}
46
47
WXDLLIMPEXP_BASE
48
int wxCMPFUNC_CONV wxCmpNatural(const wxString& s1, const wxString& s2);
49
50
WXDLLIMPEXP_BASE
51
int wxCMPFUNC_CONV wxCmpNaturalGeneric(const wxString& s1, const wxString& s2);
52
53
inline int wxCMPFUNC_CONV wxNaturalStringSortAscending(const wxString& s1, const wxString& s2)
54
0
{
55
0
    return wxCmpNatural(s1, s2);
56
0
}
57
58
inline int wxCMPFUNC_CONV wxNaturalStringSortDescending(const wxString& s1, const wxString& s2)
59
0
{
60
0
    return wxCmpNatural(s2, s1);
61
0
}
62
63
64
#if wxUSE_STD_CONTAINERS
65
66
typedef int (wxCMPFUNC_CONV *CMPFUNCwxString)(wxString*, wxString*);
67
68
class WXDLLIMPEXP_BASE wxWARN_UNUSED wxArrayString : public wxBaseArray<wxString>
69
{
70
public:
71
    // type of function used by wxArrayString::Sort()
72
    typedef int (wxCMPFUNC_CONV *CompareFunction)(const wxString& first,
73
                                                  const wxString& second);
74
75
4
    wxArrayString() = default;
76
    wxArrayString(size_t sz, const char** a);
77
    wxArrayString(size_t sz, const wchar_t** a);
78
    wxArrayString(size_t sz, const wxString* a);
79
    template<typename U>
80
    wxArrayString(std::initializer_list<U> list) : wxBaseArray<wxString>(list) { }
81
0
    wxArrayString(const std::vector<wxString>& vec) : wxBaseArray<wxString>(vec) { }
82
0
    wxArrayString(std::vector<wxString>&& vec) : wxBaseArray<wxString>(std::move(vec)) { }
83
    template<typename U>
84
    wxArrayString(const std::vector<U>& vec) : wxBaseArray<wxString>(vec.begin(), vec.end()) { }
85
86
    int Index(const wxString& str, bool bCase = true, bool bFromEnd = false) const;
87
88
    void Sort(bool reverseOrder = false);
89
    void Sort(CompareFunction function);
90
0
    void Sort(CMPFUNCwxString function) { wxBaseArray<wxString>::Sort(function); }
91
92
    size_t Add(const wxString& string, size_t copies = 1)
93
0
    {
94
0
        wxBaseArray<wxString>::Add(string, copies);
95
0
        return size() - copies;
96
0
    }
97
98
0
    const std::vector<wxString>& AsVector() const { return *this; }
99
};
100
101
// Unlike all the other sorted arrays, this one uses a comparison function
102
// taking objects by reference rather than value, so define a special functor
103
// wrapping it.
104
class wxSortedArrayString_SortFunction
105
{
106
public:
107
    typedef int (wxCMPFUNC_CONV *CMPFUNC)(const wxString&, const wxString&);
108
109
0
    explicit wxSortedArrayString_SortFunction(CMPFUNC f) : m_f(f) { }
110
111
    bool operator()(const wxString& s1, const wxString& s2)
112
0
      { return m_f(s1, s2) < 0; }
113
114
private:
115
    CMPFUNC m_f;
116
};
117
118
typedef wxBaseSortedArray<wxString, wxSortedArrayString_SortFunction>
119
    wxSortedArrayStringBase;
120
121
class WXDLLIMPEXP_BASE wxSortedArrayString : public wxSortedArrayStringBase
122
{
123
public:
124
    wxSortedArrayString() : wxSortedArrayStringBase(wxStringSortAscending)
125
0
        { }
126
    wxSortedArrayString(const wxArrayString& src)
127
        : wxSortedArrayStringBase(wxStringSortAscending)
128
0
    {
129
0
        reserve(src.size());
130
0
131
0
        for ( size_t n = 0; n < src.size(); n++ )
132
0
            Add(src[n]);
133
0
    }
134
    explicit wxSortedArrayString(wxArrayString::CompareFunction compareFunction)
135
        : wxSortedArrayStringBase(compareFunction)
136
0
        { }
137
138
    int Index(const wxString& str, bool bCase = true, bool bFromEnd = false) const;
139
140
private:
141
    void Insert()
142
0
    {
143
0
        wxFAIL_MSG( "wxSortedArrayString::Insert() is not to be used" );
144
0
    }
145
146
    void Sort()
147
0
    {
148
0
        wxFAIL_MSG( "wxSortedArrayString::Sort() is not to be used" );
149
0
    }
150
};
151
152
#else // if !wxUSE_STD_CONTAINERS
153
154
#include "wx/beforestd.h"
155
#include <iterator>
156
#include "wx/afterstd.h"
157
158
class WXDLLIMPEXP_BASE wxWARN_UNUSED wxArrayString
159
{
160
public:
161
  // type of function used by wxArrayString::Sort()
162
  typedef int (wxCMPFUNC_CONV *CompareFunction)(const wxString& first,
163
                                 const wxString& second);
164
  // type of function used by wxArrayString::Sort(), for compatibility with
165
  // wxArray
166
  typedef int (wxCMPFUNC_CONV *CompareFunction2)(wxString* first,
167
                                  wxString* second);
168
169
  // constructors and destructor
170
    // default ctor
171
  wxArrayString() = default;
172
    // if autoSort is true, the array is always sorted (in alphabetical order)
173
    //
174
    // NB: the reason for using int and not bool is that like this we can avoid
175
    //     using this ctor for implicit conversions from "const char *" (which
176
    //     we'd like to be implicitly converted to wxString instead!). This
177
    //     wouldn't be needed if the 'explicit' keyword was supported by all
178
    //     compilers, or if this was protected ctor for wxSortedArrayString,
179
    //     but we're stuck with it now.
180
  explicit wxArrayString(int autoSort)
181
  {
182
      if ( autoSort )
183
          m_autoSort = true;
184
  }
185
    // C string array ctor
186
  wxArrayString(size_t sz, const char** a);
187
  wxArrayString(size_t sz, const wchar_t** a);
188
    // wxString string array ctor
189
  wxArrayString(size_t sz, const wxString* a);
190
    // copy ctor
191
  wxArrayString(const wxArrayString& array);
192
    // list constructor
193
  template<typename U>
194
  wxArrayString(std::initializer_list<U> list) { assign(list.begin(), list.end()); }
195
    // ctor from a std::vector
196
  template<typename U>
197
  wxArrayString(const std::vector<U>& vec) { assign(vec.begin(), vec.end()); }
198
    // assignment operator
199
  wxArrayString& operator=(const wxArrayString& src);
200
    // not virtual, this class should not be derived from
201
 ~wxArrayString();
202
203
  // memory management
204
    // empties the list, but doesn't release memory
205
  void Empty();
206
    // empties the list and releases memory
207
  void Clear();
208
    // preallocates memory for given number of items
209
  void Alloc(size_t nCount);
210
    // minimizes the memory usage (by freeing all extra memory)
211
  void Shrink();
212
213
  // simple accessors
214
    // number of elements in the array
215
  size_t GetCount() const { return m_nCount; }
216
    // is it empty?
217
  bool IsEmpty() const { return m_nCount == 0; }
218
    // number of elements in the array (GetCount is preferred API)
219
  size_t Count() const { return m_nCount; }
220
221
  // items access (range checking is done in debug version)
222
    // get item at position uiIndex
223
  wxString& Item(size_t nIndex)
224
    {
225
        wxASSERT_MSG( nIndex < m_nCount,
226
                      wxT("wxArrayString: index out of bounds") );
227
228
        return m_pItems[nIndex];
229
    }
230
  const wxString& Item(size_t nIndex) const { return const_cast<wxArrayString*>(this)->Item(nIndex); }
231
232
    // same as Item()
233
  wxString& operator[](size_t nIndex) { return Item(nIndex); }
234
  const wxString& operator[](size_t nIndex) const { return Item(nIndex); }
235
    // get last item
236
  wxString& Last()
237
  {
238
      wxASSERT_MSG( !IsEmpty(),
239
                    wxT("wxArrayString: index out of bounds") );
240
      return Item(GetCount() - 1);
241
  }
242
  const wxString& Last() const { return const_cast<wxArrayString*>(this)->Last(); }
243
244
    // get all items as a vector
245
  std::vector<wxString> AsVector() const;
246
247
  // item management
248
    // Search the element in the array, starting from the beginning if
249
    // bFromEnd is false or from end otherwise. If bCase, comparison is case
250
    // sensitive (default). Returns index of the first item matched or
251
    // wxNOT_FOUND
252
  int  Index (const wxString& str, bool bCase = true, bool bFromEnd = false) const;
253
    // add new element at the end (if the array is not sorted), return its
254
    // index
255
  size_t Add(const wxString& str, size_t nInsert = 1);
256
    // add new element at given position
257
  void Insert(const wxString& str, size_t uiIndex, size_t nInsert = 1);
258
    // expand the array to have count elements
259
  void SetCount(size_t count);
260
    // remove first item matching this value
261
  void Remove(const wxString& sz);
262
    // remove item by index
263
  void RemoveAt(size_t nIndex, size_t nRemove = 1);
264
265
  // sorting
266
    // sort array elements in alphabetical order (or reversed alphabetical
267
    // order if reverseOrder parameter is true)
268
  void Sort(bool reverseOrder = false);
269
    // sort array elements using specified comparison function
270
  void Sort(CompareFunction compareFunction);
271
  void Sort(CompareFunction2 compareFunction);
272
273
  // comparison
274
    // compare two arrays case sensitively
275
  bool operator==(const wxArrayString& a) const;
276
    // compare two arrays case sensitively
277
  bool operator!=(const wxArrayString& a) const { return !(*this == a); }
278
279
  // STL-like interface
280
  typedef wxString value_type;
281
  typedef value_type* pointer;
282
  typedef const value_type* const_pointer;
283
  typedef value_type* iterator;
284
  typedef const value_type* const_iterator;
285
  typedef value_type& reference;
286
  typedef const value_type& const_reference;
287
  typedef int difference_type;
288
  typedef size_t size_type;
289
290
  // TODO: this code duplicates the one in dynarray.h
291
  class reverse_iterator
292
  {
293
    typedef wxString value_type;
294
    typedef value_type* pointer;
295
    typedef value_type& reference;
296
    typedef reverse_iterator itor;
297
    friend itor operator+(int o, const itor& it);
298
    friend itor operator+(const itor& it, int o);
299
    friend itor operator-(const itor& it, int o);
300
    friend difference_type operator -(const itor& i1, const itor& i2);
301
  public:
302
    pointer m_ptr;
303
    reverse_iterator() : m_ptr(nullptr) { }
304
    explicit reverse_iterator(pointer ptr) : m_ptr(ptr) { }
305
    reverse_iterator(const itor& it) : m_ptr(it.m_ptr) { }
306
    reference operator*() const { return *m_ptr; }
307
    pointer operator->() const { return m_ptr; }
308
    itor& operator++() { --m_ptr; return *this; }
309
    const itor operator++(int)
310
      { const reverse_iterator tmp = *this; --m_ptr; return tmp; }
311
    itor& operator--() { ++m_ptr; return *this; }
312
    const itor operator--(int) { const itor tmp = *this; ++m_ptr; return tmp; }
313
    bool operator ==(const itor& it) const { return m_ptr == it.m_ptr; }
314
    bool operator !=(const itor& it) const { return m_ptr != it.m_ptr; }
315
  };
316
317
  class const_reverse_iterator
318
  {
319
    typedef wxString value_type;
320
    typedef const value_type* pointer;
321
    typedef const value_type& reference;
322
    typedef const_reverse_iterator itor;
323
    friend itor operator+(int o, const itor& it);
324
    friend itor operator+(const itor& it, int o);
325
    friend itor operator-(const itor& it, int o);
326
    friend difference_type operator -(const itor& i1, const itor& i2);
327
  public:
328
    pointer m_ptr;
329
    const_reverse_iterator() : m_ptr(nullptr) { }
330
    explicit const_reverse_iterator(pointer ptr) : m_ptr(ptr) { }
331
    const_reverse_iterator(const itor& it) : m_ptr(it.m_ptr) { }
332
    const_reverse_iterator(const reverse_iterator& it) : m_ptr(it.m_ptr) { }
333
    reference operator*() const { return *m_ptr; }
334
    pointer operator->() const { return m_ptr; }
335
    itor& operator++() { --m_ptr; return *this; }
336
    const itor operator++(int)
337
      { const itor tmp = *this; --m_ptr; return tmp; }
338
    itor& operator--() { ++m_ptr; return *this; }
339
    const itor operator--(int) { const itor tmp = *this; ++m_ptr; return tmp; }
340
    bool operator ==(const itor& it) const { return m_ptr == it.m_ptr; }
341
    bool operator !=(const itor& it) const { return m_ptr != it.m_ptr; }
342
  };
343
344
  wxArrayString(const_iterator first, const_iterator last)
345
    { assign(first, last); }
346
  wxArrayString(size_type n, const_reference v) { assign(n, v); }
347
348
  template <class Iterator>
349
  void assign(Iterator first, Iterator last)
350
  {
351
      clear();
352
      reserve(std::distance(first, last));
353
      for(; first != last; ++first)
354
          push_back(*first);
355
  }
356
357
  void assign(size_type n, const_reference v)
358
    { clear(); Add(v, n); }
359
  reference back() { return *(end() - 1); }
360
  const_reference back() const { return *(end() - 1); }
361
  iterator begin() { return m_pItems; }
362
  const_iterator begin() const { return m_pItems; }
363
  size_type capacity() const { return m_nSize; }
364
  void clear() { Clear(); }
365
  bool empty() const { return IsEmpty(); }
366
  iterator end() { return begin() + GetCount(); }
367
  const_iterator end() const { return begin() + GetCount(); }
368
  iterator erase(iterator first, iterator last)
369
  {
370
      size_t idx = first - begin();
371
      RemoveAt(idx, last - first);
372
      return begin() + idx;
373
  }
374
  iterator erase(iterator it) { return erase(it, it + 1); }
375
  reference front() { return *begin(); }
376
  const_reference front() const { return *begin(); }
377
  void insert(iterator it, size_type n, const_reference v)
378
    { Insert(v, it - begin(), n); }
379
  iterator insert(iterator it, const_reference v = value_type())
380
    { size_t idx = it - begin(); Insert(v, idx); return begin() + idx; }
381
  void insert(iterator it, const_iterator first, const_iterator last);
382
  size_type max_size() const { return INT_MAX; }
383
  void pop_back() { RemoveAt(GetCount() - 1); }
384
  void push_back(const_reference v) { Add(v); }
385
  reverse_iterator rbegin() { return reverse_iterator(end() - 1); }
386
  const_reverse_iterator rbegin() const
387
    { return const_reverse_iterator(end() - 1); }
388
  reverse_iterator rend() { return reverse_iterator(begin() - 1); }
389
  const_reverse_iterator rend() const
390
    { return const_reverse_iterator(begin() - 1); }
391
  void reserve(size_type n) /* base::reserve*/;
392
  void resize(size_type n, value_type v = value_type());
393
  size_type size() const { return GetCount(); }
394
  void swap(wxArrayString& other)
395
  {
396
      wxSwap(m_nSize, other.m_nSize);
397
      wxSwap(m_nCount, other.m_nCount);
398
      wxSwap(m_pItems, other.m_pItems);
399
      wxSwap(m_autoSort, other.m_autoSort);
400
  }
401
402
protected:
403
  void Copy(const wxArrayString& src);  // copies the contents of another array
404
405
  CompareFunction m_compareFunction = nullptr; // set only from wxSortedArrayString
406
407
private:
408
  // Allocate the new buffer big enough to hold m_nCount + nIncrement items and
409
  // return the pointer to the old buffer, which must be deleted by the caller
410
  // (if the old buffer is big enough, just return nullptr).
411
  wxString *Grow(size_t nIncrement);
412
413
  // Binary search in the sorted array: return the index of the string if it's
414
  // present, otherwise, if lowerBound is true, return the position at which
415
  // the string should be inserted and if it's false return wxNOT_FOUND.
416
  size_t BinarySearch(const wxString& str, bool lowerBound) const;
417
418
  size_t  m_nSize = 0,    // current size of the array
419
          m_nCount = 0;   // current number of elements
420
421
  wxString *m_pItems = nullptr; // pointer to data
422
423
  bool    m_autoSort = false; // if true, keep the array always sorted
424
};
425
426
class WXDLLIMPEXP_BASE wxSortedArrayString : public wxArrayString
427
{
428
public:
429
  wxSortedArrayString() : wxArrayString(true)
430
    { }
431
  wxSortedArrayString(const wxArrayString& array) : wxArrayString(true)
432
    { Copy(array); }
433
434
  explicit wxSortedArrayString(CompareFunction compareFunction)
435
      : wxArrayString(true)
436
    { m_compareFunction = compareFunction; }
437
};
438
439
#endif // !wxUSE_STD_CONTAINERS
440
441
// this class provides a temporary wxString* from a
442
// wxArrayString
443
class WXDLLIMPEXP_BASE wxCArrayString
444
{
445
public:
446
    wxCArrayString( const wxArrayString& array )
447
        : m_array( array ), m_strings( nullptr )
448
0
    { }
449
0
    ~wxCArrayString() { delete[] m_strings; }
450
451
0
    size_t GetCount() const { return m_array.GetCount(); }
452
    wxString* GetStrings()
453
0
    {
454
0
        if( m_strings ) return m_strings;
455
0
        const size_t count = m_array.GetCount();
456
0
        m_strings = new wxString[count];
457
0
        for( size_t i = 0; i < count; ++i )
458
0
            m_strings[i] = m_array[i];
459
0
        return m_strings;
460
0
    }
461
462
    wxString* Release()
463
0
    {
464
0
        wxString *r = GetStrings();
465
0
        m_strings = nullptr;
466
0
        return r;
467
0
    }
468
469
private:
470
    const wxArrayString& m_array;
471
    wxString* m_strings;
472
};
473
474
475
// ----------------------------------------------------------------------------
476
// helper functions for working with arrays
477
// ----------------------------------------------------------------------------
478
479
// by default, these functions use the escape character to escape the
480
// separators occurring inside the string to be joined, this can be disabled by
481
// passing '\0' as escape
482
483
WXDLLIMPEXP_BASE wxString wxJoin(const wxArrayString& arr,
484
                                 const wxChar sep,
485
                                 const wxChar escape = wxT('\\'));
486
487
WXDLLIMPEXP_BASE wxArrayString wxSplit(const wxString& str,
488
                                       const wxChar sep,
489
                                       const wxChar escape = wxT('\\'));
490
491
492
// ----------------------------------------------------------------------------
493
// This helper class allows to pass both C array of wxStrings or wxArrayString
494
// using the same interface.
495
//
496
// Use it when you have two methods taking wxArrayString or (int, wxString[]),
497
// that do the same thing. This class lets you iterate over input data in the
498
// same way whether it is a raw array of strings or wxArrayString.
499
//
500
// The object does not take ownership of the data -- internally it keeps
501
// pointers to the data, therefore the data must be disposed of by user
502
// and only after this object is destroyed. Usually it is not a problem as
503
// only temporary objects of this class are used.
504
// ----------------------------------------------------------------------------
505
506
class wxArrayStringsAdapter
507
{
508
public:
509
    // construct an adapter from a wxArrayString
510
    wxArrayStringsAdapter(const wxArrayString& strings)
511
        : m_type(wxSTRING_ARRAY), m_size(strings.size())
512
0
    {
513
0
        m_data.array = &strings;
514
0
    }
515
516
    // construct an adapter from a wxString[]
517
    wxArrayStringsAdapter(unsigned int n, const wxString *strings)
518
        : m_type(wxSTRING_POINTER), m_size(n)
519
0
    {
520
0
        m_data.ptr = strings;
521
0
    }
522
523
    // construct an adapter from a vector of strings
524
    wxArrayStringsAdapter(const std::vector<wxString>& strings)
525
        : m_type(wxSTRING_POINTER), m_size(strings.size())
526
0
    {
527
0
        m_data.ptr = m_size == 0 ? nullptr : &strings[0];
528
0
    }
529
530
    // construct an adapter from a single wxString
531
    wxArrayStringsAdapter(const wxString& s)
532
        : m_type(wxSTRING_POINTER), m_size(1)
533
0
    {
534
0
        m_data.ptr = &s;
535
0
    }
536
537
    // default copy constructor is ok
538
539
    // iteration interface
540
0
    size_t GetCount() const { return m_size; }
541
0
    bool IsEmpty() const { return GetCount() == 0; }
542
    const wxString& operator[] (unsigned int i) const
543
0
    {
544
0
        wxASSERT_MSG( i < GetCount(), wxT("index out of bounds") );
545
0
        if(m_type == wxSTRING_POINTER)
546
0
            return m_data.ptr[i];
547
0
        return m_data.array->Item(i);
548
0
    }
549
    wxArrayString AsArrayString() const
550
0
    {
551
0
        if(m_type == wxSTRING_ARRAY)
552
0
            return *m_data.array;
553
0
        return wxArrayString(GetCount(), m_data.ptr);
554
0
    }
555
556
private:
557
    // type of the data being held
558
    enum wxStringContainerType
559
    {
560
        wxSTRING_ARRAY,  // wxArrayString
561
        wxSTRING_POINTER // wxString[]
562
    };
563
564
    wxStringContainerType m_type;
565
    size_t m_size;
566
    union
567
    {
568
        const wxString *      ptr;
569
        const wxArrayString * array;
570
    } m_data;
571
572
    wxDECLARE_NO_ASSIGN_CLASS(wxArrayStringsAdapter);
573
};
574
575
#endif // _WX_ARRSTR_H