]> git.saurik.com Git - wxWidgets.git/blobdiff - include/wx/arrstr.h
Don't call IAutoComplete::Init() twice for the same control as this leaks memory...
[wxWidgets.git] / include / wx / arrstr.h
index 9643b64e7641dba42d9171d350cc12ba879fd502..9e6ec1a392e5d5a2337485756229d47fe735eec0 100644 (file)
 #include "wx/defs.h"
 #include "wx/string.h"
 
 #include "wx/defs.h"
 #include "wx/string.h"
 
-WXDLLIMPEXP_BASE int wxCMPFUNC_CONV wxStringSortAscending(wxString*, wxString*);
-WXDLLIMPEXP_BASE int wxCMPFUNC_CONV 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_STL
 
@@ -27,19 +37,36 @@ typedef wxString _wxArraywxBaseArrayStringBase;
 _WX_DECLARE_BASEARRAY_2(_wxArraywxBaseArrayStringBase, wxBaseArrayStringBase,
                         wxArray_SortFunction<wxString>,
                         class WXDLLIMPEXP_BASE);
 _WX_DECLARE_BASEARRAY_2(_wxArraywxBaseArrayStringBase, wxBaseArrayStringBase,
                         wxArray_SortFunction<wxString>,
                         class WXDLLIMPEXP_BASE);
-WX_DEFINE_USER_EXPORTED_TYPEARRAY(wxString, wxArrayStringBase, 
+WX_DEFINE_USER_EXPORTED_TYPEARRAY(wxString, wxArrayStringBase,
                                   wxBaseArrayStringBase, WXDLLIMPEXP_BASE);
                                   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:
                               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() { }
     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;
 
 
-    int Index(const wxChar* sz, bool bCase = true, bool bFromEnd = false) const;
+    void Sort(bool reverseOrder = false);
+    void Sort(CompareFunction function);
+    void Sort(CMPFUNCwxString function) { wxArrayStringBase::Sort(function); }
+
+    size_t Add(const wxString& string, size_t copies = 1)
+    {
+        wxArrayStringBase::Add(string, copies);
+        return size() - copies;
+    }
 };
 
 class WXDLLIMPEXP_BASE wxSortedArrayString : public wxSortedArrayStringBase
 };
 
 class WXDLLIMPEXP_BASE wxSortedArrayString : public wxSortedArrayStringBase
@@ -59,25 +86,37 @@ public:
             Add(src[n]);
     }
 
             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_STL
 
-// ----------------------------------------------------------------------------
-// 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!
-//
-// 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.
+// this shouldn't be defined for compilers not supporting template methods or
+// without std::distance()
 //
 //
-// 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 <iterator>
+    #include "wx/afterstd.h"
+#endif // wxHAS_VECTOR_TEMPLATE_ASSIGN
 
 class WXDLLIMPEXP_BASE wxArrayString
 {
 
 class WXDLLIMPEXP_BASE wxArrayString
 {
@@ -102,6 +141,11 @@ public:
     //     of course, using explicit would be even better - if all compilers
     //     supported it...
   wxArrayString(int autoSort) { Init(autoSort != 0); }
     //     of course, using explicit would be even better - if all compilers
     //     supported it...
   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
     // copy ctor
   wxArrayString(const wxArrayString& array);
     // assignment operator
@@ -134,7 +178,7 @@ public:
         wxASSERT_MSG( nIndex < m_nCount,
                       _T("wxArrayString: index out of bounds") );
 
         wxASSERT_MSG( nIndex < m_nCount,
                       _T("wxArrayString: index out of bounds") );
 
-        return *(wxString *)&(m_pItems[nIndex]);
+        return m_pItems[nIndex];
     }
 
     // same as Item()
     }
 
     // same as Item()
@@ -144,23 +188,16 @@ public:
   {
       wxASSERT_MSG( !IsEmpty(),
                     _T("wxArrayString: index out of bounds") );
   {
       wxASSERT_MSG( !IsEmpty(),
                     _T("wxArrayString: index out of bounds") );
-      return Item(Count() - 1);
+      return Item(GetCount() - 1);
   }
 
   }
 
-    // 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.
-#if WXWIN_COMPATIBILITY_2_4
-  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
     // sensitive (default). Returns index of the first item matched or
     // wxNOT_FOUND
 
   // 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
     // 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);
     // 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);
@@ -169,18 +206,15 @@ public:
     // expand the array to have count elements
   void SetCount(size_t count);
     // remove first item matching this value
     // 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
     // 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);
   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
+    // sort array elements using specified comparison function
   void Sort(CompareFunction compareFunction);
   void Sort(CompareFunction2 compareFunction);
 
   void Sort(CompareFunction compareFunction);
   void Sort(CompareFunction2 compareFunction);
 
@@ -201,7 +235,7 @@ public:
   typedef int difference_type;
   typedef size_t size_type;
 
   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;
   class reverse_iterator
   {
     typedef wxString value_type;
@@ -219,13 +253,13 @@ public:
     reverse_iterator(const itor& it) : m_ptr(it.m_ptr) { }
     reference operator*() const { return *m_ptr; }
     pointer operator->() const { return m_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; }
       { 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
   };
 
   class const_reverse_iterator
@@ -246,25 +280,44 @@ public:
     const_reverse_iterator(const reverse_iterator& it) : m_ptr(it.m_ptr) { }
     reference operator*() const { return *m_ptr; }
     pointer operator->() const { return 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 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; }
   };
 
   wxArrayString(const_iterator first, const_iterator last)
     { Init(false); assign(first, last); }
   wxArrayString(size_type n, const_reference v) { Init(false); assign(n, v); }
   };
 
   wxArrayString(const_iterator first, const_iterator last)
     { Init(false); assign(first, last); }
   wxArrayString(size_type n, const_reference v) { Init(false); assign(n, v); }
-  void assign(const_iterator first, const_iterator last);
+
+#ifdef wxHAS_VECTOR_TEMPLATE_ASSIGN
+  template <class Iterator>
+  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); }
   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(); }
   size_type capacity() const { return m_nSize; }
   void clear() { Clear(); }
   bool empty() const { return IsEmpty(); }
@@ -288,12 +341,21 @@ public:
   void pop_back() { RemoveAt(GetCount() - 1); }
   void push_back(const_reference v) { Add(v); }
   reverse_iterator rbegin() { return reverse_iterator(end() - 1); }
   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); }
   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 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
 
 protected:
   void Init(bool autoSort);             // common part of all ctors
@@ -301,14 +363,11 @@ protected:
 
 private:
   void Grow(size_t nIncrement = 0);     // makes array bigger if needed
 
 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
 
 
   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
 };
@@ -344,9 +403,111 @@ public:
             m_strings[i] = m_array[i];
         return m_strings;
     }
             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;
 };
 
 private:
     const wxArrayString& m_array;
     wxString* m_strings;
 };
 
-#endif
+
+// ----------------------------------------------------------------------------
+// helper functions for working with arrays
+// ----------------------------------------------------------------------------
+
+// by default, these functions use the escape character to escape the
+// separators occuring 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