X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/3931863650d4f4d126cac1992323df5fc39833dd..add6e9193dfbeec8ad88d4e341bc46165b97e3dd:/include/wx/arrstr.h diff --git a/include/wx/arrstr.h b/include/wx/arrstr.h index 4cf5cc4acc..e093c29731 100644 --- a/include/wx/arrstr.h +++ b/include/wx/arrstr.h @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////// -// Name: include/wx/arrstr.h +// Name: wx/arrstr.h // Purpose: wxArrayString class // Author: Mattia Barbon and Vadim Zeitlin // Modified by: @@ -15,10 +15,20 @@ #include "wx/defs.h" #include "wx/string.h" -WXDLLIMPEXP_BASE int wxStringSortAscending(wxString*, wxString*); -WXDLLIMPEXP_BASE int wxStringSortDescending(wxString*, wxString*); +// these functions are only used in STL build now but we define them in any +// case for compatibility with the existing code outside of the library which +// could be using them +inline int wxCMPFUNC_CONV wxStringSortAscending(wxString* s1, wxString* s2) +{ + return s1->Cmp(*s2); +} + +inline int wxCMPFUNC_CONV wxStringSortDescending(wxString* s1, wxString* s2) +{ + return wxStringSortAscending(s2, s1); +} -#if wxUSE_STL +#if wxUSE_STD_CONTAINERS #include "wx/dynarray.h" @@ -27,19 +37,36 @@ typedef wxString _wxArraywxBaseArrayStringBase; _WX_DECLARE_BASEARRAY_2(_wxArraywxBaseArrayStringBase, wxBaseArrayStringBase, wxArray_SortFunction, class WXDLLIMPEXP_BASE); -WX_DEFINE_USER_EXPORTED_TYPEARRAY(wxString, wxArrayStringBase, +WX_DEFINE_USER_EXPORTED_TYPEARRAY(wxString, wxArrayStringBase, wxBaseArrayStringBase, WXDLLIMPEXP_BASE); -_WX_DEFINE_SORTED_TYPEARRAY_2(wxString, wxSortedArrayStringBase, +_WX_DEFINE_SORTED_TYPEARRAY_2(wxString, wxSortedArrayStringBase, wxBaseArrayStringBase, = wxStringSortAscending, class WXDLLIMPEXP_BASE, CMPFUNCwxString); class WXDLLIMPEXP_BASE wxArrayString : public wxArrayStringBase { public: + // type of function used by wxArrayString::Sort() + typedef int (wxCMPFUNC_CONV *CompareFunction)(const wxString& first, + const wxString& second); + wxArrayString() { } wxArrayString(const wxArrayString& a) : wxArrayStringBase(a) { } + wxArrayString(size_t sz, const char** a); + wxArrayString(size_t sz, const wchar_t** a); + wxArrayString(size_t sz, const wxString* a); + + int Index(const wxString& str, bool bCase = true, bool bFromEnd = false) const; + + void Sort(bool reverseOrder = false); + void Sort(CompareFunction function); + void Sort(CMPFUNCwxString function) { wxArrayStringBase::Sort(function); } - int Index(const wxChar* sz, bool bCase = true, bool bFromEnd = false) const; + size_t Add(const wxString& string, size_t copies = 1) + { + wxArrayStringBase::Add(string, copies); + return size() - copies; + } }; class WXDLLIMPEXP_BASE wxSortedArrayString : public wxSortedArrayStringBase @@ -59,25 +86,37 @@ public: Add(src[n]); } - int Index(const wxChar* sz, bool bCase = true, bool bFromEnd = false) const; + int Index(const wxString& str, bool bCase = true, bool bFromEnd = false) const; + +private: + void Insert() + { + wxFAIL_MSG( "wxSortedArrayString::Insert() is not to be used" ); + } + + void Sort() + { + wxFAIL_MSG( "wxSortedArrayString::Sort() is not to be used" ); + } }; -#else // if !wxUSE_STL +#else // if !wxUSE_STD_CONTAINERS -// ---------------------------------------------------------------------------- -// The string array uses it's knowledge of internal structure of the wxString -// class to optimize string storage. Normally, we would store pointers to -// string, but as wxString is, in fact, itself a pointer (sizeof(wxString) is -// sizeof(char *)) we store these pointers instead. The cast to "wxString *" is -// really all we need to turn such pointer into a string! +// this shouldn't be defined for compilers not supporting template methods or +// without std::distance() // -// Of course, it can be called a dirty hack, but we use twice less memory and -// this approach is also more speed efficient, so it's probably worth it. -// -// Usage notes: when a string is added/inserted, a new copy of it is created, -// so the original string may be safely deleted. When a string is retrieved -// from the array (operator[] or Item() method), a reference is returned. -// ---------------------------------------------------------------------------- +// FIXME-VC6: currently it's only not defined for VC6 in DLL build as it +// doesn't export template methods from DLL correctly so even though +// it compiles them fine, we get link errors when using wxArrayString +#if !defined(__VISUALC6__) || !(defined(WXMAKINGDLL) || defined(WXUSINGDLL)) + #define wxHAS_VECTOR_TEMPLATE_ASSIGN +#endif + +#ifdef wxHAS_VECTOR_TEMPLATE_ASSIGN + #include "wx/beforestd.h" + #include + #include "wx/afterstd.h" +#endif // wxHAS_VECTOR_TEMPLATE_ASSIGN class WXDLLIMPEXP_BASE wxArrayString { @@ -92,20 +131,21 @@ public: // constructors and destructor // default ctor - wxArrayString() - : m_nSize(0), m_nCount(0), m_pItems(NULL), m_autoSort(FALSE) - { Init(FALSE); } - // if autoSort is TRUE, the array is always sorted (in alphabetical order) + wxArrayString() { Init(false); } + // if autoSort is true, the array is always sorted (in alphabetical order) // // NB: the reason for using int and not bool is that like this we can avoid // using this ctor for implicit conversions from "const char *" (which - // we'd like to be implicitly converted to wxString instead!) - // - // of course, using explicit would be even better - if all compilers - // supported it... - wxArrayString(int autoSort) - : m_nSize(0), m_nCount(0), m_pItems(NULL), m_autoSort(FALSE) - { Init(autoSort != 0); } + // we'd like to be implicitly converted to wxString instead!). This + // wouldn't be needed if the 'explicit' keyword was supported by all + // compilers, or if this was protected ctor for wxSortedArrayString, + // but we're stuck with it now. + wxEXPLICIT wxArrayString(int autoSort) { Init(autoSort != 0); } + // C string array ctor + wxArrayString(size_t sz, const char** a); + wxArrayString(size_t sz, const wchar_t** a); + // wxString string array ctor + wxArrayString(size_t sz, const wxString* a); // copy ctor wxArrayString(const wxArrayString& array); // assignment operator @@ -133,38 +173,34 @@ public: // items access (range checking is done in debug version) // get item at position uiIndex - wxString& Item(size_t nIndex) const + wxString& Item(size_t nIndex) { wxASSERT_MSG( nIndex < m_nCount, - _T("wxArrayString: index out of bounds") ); + wxT("wxArrayString: index out of bounds") ); - return *(wxString *)&(m_pItems[nIndex]); + return m_pItems[nIndex]; } + const wxString& Item(size_t nIndex) const { return const_cast(this)->Item(nIndex); } // same as Item() - wxString& operator[](size_t nIndex) const { return Item(nIndex); } + wxString& operator[](size_t nIndex) { return Item(nIndex); } + const wxString& operator[](size_t nIndex) const { return Item(nIndex); } // get last item - wxString& Last() const + wxString& Last() { wxASSERT_MSG( !IsEmpty(), - _T("wxArrayString: index out of bounds") ); - return Item(Count() - 1); + wxT("wxArrayString: index out of bounds") ); + return Item(GetCount() - 1); } + const wxString& Last() const { return const_cast(this)->Last(); } -#if WXWIN_COMPATIBILITY_2_4 - // return a wxString[], useful for the controls which - // take one in their ctor. You must delete[] it yourself - // once you are done with it. Will return NULL if the - // ArrayString was empty. - wxString* GetStringArray() const; -#endif // item management // Search the element in the array, starting from the beginning if - // bFromEnd is FALSE or from end otherwise. If bCase, comparison is case + // bFromEnd is false or from end otherwise. If bCase, comparison is case // sensitive (default). Returns index of the first item matched or // wxNOT_FOUND - int Index (const wxChar *sz, bool bCase = TRUE, bool bFromEnd = FALSE) const; + int Index (const wxString& str, bool bCase = true, bool bFromEnd = false) const; // add new element at the end (if the array is not sorted), return its // index size_t Add(const wxString& str, size_t nInsert = 1); @@ -173,18 +209,15 @@ public: // expand the array to have count elements void SetCount(size_t count); // remove first item matching this value - void Remove(const wxChar *sz); + void Remove(const wxString& sz); // remove item by index -#if WXWIN_COMPATIBILITY_2_4 - void Remove(size_t nIndex, size_t nRemove = 1) { RemoveAt(nIndex, nRemove); } -#endif void RemoveAt(size_t nIndex, size_t nRemove = 1); // sorting // sort array elements in alphabetical order (or reversed alphabetical - // order if reverseOrder parameter is TRUE) - void Sort(bool reverseOrder = FALSE); - // sort array elements using specified comparaison function + // order if reverseOrder parameter is true) + void Sort(bool reverseOrder = false); + // sort array elements using specified comparison function void Sort(CompareFunction compareFunction); void Sort(CompareFunction2 compareFunction); @@ -205,7 +238,7 @@ public: typedef int difference_type; typedef size_t size_type; - // FIXME: same in dynarray.h + // TODO: this code duplicates the one in dynarray.h class reverse_iterator { typedef wxString value_type; @@ -219,17 +252,17 @@ public: public: pointer m_ptr; reverse_iterator() : m_ptr(NULL) { } - reverse_iterator(pointer ptr) : m_ptr(ptr) { } + wxEXPLICIT reverse_iterator(pointer ptr) : m_ptr(ptr) { } reverse_iterator(const itor& it) : m_ptr(it.m_ptr) { } reference operator*() const { return *m_ptr; } pointer operator->() const { return m_ptr; } - itor operator++() { --m_ptr; return *this; } - itor operator++(int) + itor& operator++() { --m_ptr; return *this; } + const itor operator++(int) { reverse_iterator tmp = *this; --m_ptr; return tmp; } - itor operator--() { ++m_ptr; return *this; } - itor operator--(int) { itor tmp = *this; ++m_ptr; return tmp; } - bool operator ==(const itor& it) { return m_ptr == it.m_ptr; } - bool operator !=(const itor& it) { return m_ptr != it.m_ptr; } + itor& operator--() { ++m_ptr; return *this; } + const itor operator--(int) { itor tmp = *this; ++m_ptr; return tmp; } + bool operator ==(const itor& it) const { return m_ptr == it.m_ptr; } + bool operator !=(const itor& it) const { return m_ptr != it.m_ptr; } }; class const_reverse_iterator @@ -245,27 +278,49 @@ public: public: pointer m_ptr; const_reverse_iterator() : m_ptr(NULL) { } - const_reverse_iterator(pointer ptr) : m_ptr(ptr) { } + wxEXPLICIT const_reverse_iterator(pointer ptr) : m_ptr(ptr) { } const_reverse_iterator(const itor& it) : m_ptr(it.m_ptr) { } const_reverse_iterator(const reverse_iterator& it) : m_ptr(it.m_ptr) { } reference operator*() const { return *m_ptr; } pointer operator->() const { return m_ptr; } - itor operator++() { --m_ptr; return *this; } - itor operator++(int) + itor& operator++() { --m_ptr; return *this; } + const itor operator++(int) { itor tmp = *this; --m_ptr; return tmp; } - itor operator--() { ++m_ptr; return *this; } - itor operator--(int) { itor tmp = *this; ++m_ptr; return tmp; } - bool operator ==(const itor& it) { return m_ptr == it.m_ptr; } - bool operator !=(const itor& it) { return m_ptr != it.m_ptr; } + itor& operator--() { ++m_ptr; return *this; } + const itor operator--(int) { itor tmp = *this; ++m_ptr; return tmp; } + bool operator ==(const itor& it) const { return m_ptr == it.m_ptr; } + bool operator !=(const itor& it) const { return m_ptr != it.m_ptr; } }; - void assign(const_iterator first, const_iterator last); + wxArrayString(const_iterator first, const_iterator last) + { Init(false); assign(first, last); } + wxArrayString(size_type n, const_reference v) { Init(false); assign(n, v); } + +#ifdef wxHAS_VECTOR_TEMPLATE_ASSIGN + template + void assign(Iterator first, Iterator last) + { + clear(); + reserve(std::distance(first, last)); + for(; first != last; ++first) + push_back(*first); + } +#else // !wxHAS_VECTOR_TEMPLATE_ASSIGN + void assign(const_iterator first, const_iterator last) + { + clear(); + reserve(last - first); + for(; first != last; ++first) + push_back(*first); + } +#endif // wxHAS_VECTOR_TEMPLATE_ASSIGN/!wxHAS_VECTOR_TEMPLATE_ASSIGN + void assign(size_type n, const_reference v) { clear(); Add(v, n); } reference back() { return *(end() - 1); } const_reference back() const { return *(end() - 1); } - iterator begin() { return (wxString *)&(m_pItems[0]); } - const_iterator begin() const { return (wxString *)&(m_pItems[0]); } + iterator begin() { return m_pItems; } + const_iterator begin() const { return m_pItems; } size_type capacity() const { return m_nSize; } void clear() { Clear(); } bool empty() const { return IsEmpty(); } @@ -289,12 +344,21 @@ public: void pop_back() { RemoveAt(GetCount() - 1); } void push_back(const_reference v) { Add(v); } reverse_iterator rbegin() { return reverse_iterator(end() - 1); } - const_reverse_iterator rbegin() const; + const_reverse_iterator rbegin() const + { return const_reverse_iterator(end() - 1); } reverse_iterator rend() { return reverse_iterator(begin() - 1); } - const_reverse_iterator rend() const; + const_reverse_iterator rend() const + { return const_reverse_iterator(begin() - 1); } void reserve(size_type n) /* base::reserve*/; void resize(size_type n, value_type v = value_type()); size_type size() const { return GetCount(); } + void swap(wxArrayString& other) + { + wxSwap(m_nSize, other.m_nSize); + wxSwap(m_nCount, other.m_nCount); + wxSwap(m_pItems, other.m_pItems); + wxSwap(m_autoSort, other.m_autoSort); + } protected: void Init(bool autoSort); // common part of all ctors @@ -302,27 +366,151 @@ protected: private: void Grow(size_t nIncrement = 0); // makes array bigger if needed - void Free(); // free all the strings stored - - void DoSort(); // common part of all Sort() variants size_t m_nSize, // current size of the array m_nCount; // current number of elements - wxChar **m_pItems; // pointer to data + wxString *m_pItems; // pointer to data - bool m_autoSort; // if TRUE, keep the array always sorted + bool m_autoSort; // if true, keep the array always sorted }; class WXDLLIMPEXP_BASE wxSortedArrayString : public wxArrayString { public: - wxSortedArrayString() : wxArrayString(TRUE) + wxSortedArrayString() : wxArrayString(true) { } - wxSortedArrayString(const wxArrayString& array) : wxArrayString(TRUE) + wxSortedArrayString(const wxArrayString& array) : wxArrayString(true) { Copy(array); } }; -#endif // !wxUSE_STL +#endif // !wxUSE_STD_CONTAINERS -#endif +// this class provides a temporary wxString* from a +// wxArrayString +class WXDLLIMPEXP_BASE wxCArrayString +{ +public: + wxCArrayString( const wxArrayString& array ) + : m_array( array ), m_strings( NULL ) + { } + ~wxCArrayString() { delete[] m_strings; } + + size_t GetCount() const { return m_array.GetCount(); } + wxString* GetStrings() + { + if( m_strings ) return m_strings; + size_t count = m_array.GetCount(); + m_strings = new wxString[count]; + for( size_t i = 0; i < count; ++i ) + m_strings[i] = m_array[i]; + return m_strings; + } + + wxString* Release() + { + wxString *r = GetStrings(); + m_strings = NULL; + return r; + } + +private: + const wxArrayString& m_array; + wxString* m_strings; +}; + + +// ---------------------------------------------------------------------------- +// helper functions for working with arrays +// ---------------------------------------------------------------------------- + +// by default, these functions use the escape character to escape the +// separators occurring inside the string to be joined, this can be disabled by +// passing '\0' as escape + +WXDLLIMPEXP_BASE wxString wxJoin(const wxArrayString& arr, + const wxChar sep, + const wxChar escape = wxT('\\')); + +WXDLLIMPEXP_BASE wxArrayString wxSplit(const wxString& str, + const wxChar sep, + const wxChar escape = wxT('\\')); + + +// ---------------------------------------------------------------------------- +// This helper class allows to pass both C array of wxStrings or wxArrayString +// using the same interface. +// +// Use it when you have two methods taking wxArrayString or (int, wxString[]), +// that do the same thing. This class lets you iterate over input data in the +// same way whether it is a raw array of strings or wxArrayString. +// +// The object does not take ownership of the data -- internally it keeps +// pointers to the data, therefore the data must be disposed of by user +// and only after this object is destroyed. Usually it is not a problem as +// only temporary objects of this class are used. +// ---------------------------------------------------------------------------- + +class wxArrayStringsAdapter +{ +public: + // construct an adapter from a wxArrayString + wxArrayStringsAdapter(const wxArrayString& strings) + : m_type(wxSTRING_ARRAY), m_size(strings.size()) + { + m_data.array = &strings; + } + + // construct an adapter from a wxString[] + wxArrayStringsAdapter(unsigned int n, const wxString *strings) + : m_type(wxSTRING_POINTER), m_size(n) + { + m_data.ptr = strings; + } + + // construct an adapter from a single wxString + wxArrayStringsAdapter(const wxString& s) + : m_type(wxSTRING_POINTER), m_size(1) + { + m_data.ptr = &s; + } + + // default copy constructor is ok + + // iteration interface + size_t GetCount() const { return m_size; } + bool IsEmpty() const { return GetCount() == 0; } + const wxString& operator[] (unsigned int i) const + { + wxASSERT_MSG( i < GetCount(), wxT("index out of bounds") ); + if(m_type == wxSTRING_POINTER) + return m_data.ptr[i]; + return m_data.array->Item(i); + } + wxArrayString AsArrayString() const + { + if(m_type == wxSTRING_ARRAY) + return *m_data.array; + return wxArrayString(GetCount(), m_data.ptr); + } + +private: + // type of the data being held + enum wxStringContainerType + { + wxSTRING_ARRAY, // wxArrayString + wxSTRING_POINTER // wxString[] + }; + + wxStringContainerType m_type; + size_t m_size; + union + { + const wxString * ptr; + const wxArrayString * array; + } m_data; + + wxDECLARE_NO_ASSIGN_CLASS(wxArrayStringsAdapter); +}; + +#endif // _WX_ARRSTR_H