]> git.saurik.com Git - wxWidgets.git/blobdiff - include/wx/string.h
Removed wxPGProperty:GetArrIndex() in favor of GetIndexInParent()
[wxWidgets.git] / include / wx / string.h
index 3f9214b00b3cc5abf7722772a1e7e92b43370f79..44e0d7d2ae009cd9d4248672da854d0a5dc59cd2 100644 (file)
@@ -594,27 +594,41 @@ private:
       unsigned lastUsed;
   };
 
       unsigned lastUsed;
   };
 
-  // notice that we must use an accessor function and not a static variable
-  // because when the TLS variables support is implemented in the library (and
-  // not by the compiler), the global s_cache variable could be not yet
-  // initialized when a ctor of another global object is executed and if that
-  // ctor uses any wxString methods, bad things happen
+#ifndef wxHAS_COMPILER_TLS
+  // we must use an accessor function and not a static variable when the TLS
+  // variables support is implemented in the library (and not by the compiler)
+  // because the global s_cache variable could be not yet initialized when a
+  // ctor of another global object is executed and if that ctor uses any
+  // wxString methods, bad things happen
   //
   //
-  // also note that for the same reason this function _is_ MT-safe: we know
-  // it's going to be called during the program startup (currently during
-  // globals initialization but even if they ever stop using wxString, it would
-  // still be called by wxInitialize()), i.e. before any threads are created
-  static Cache& GetCache()
+  // however notice that this approach does not work when compiler TLS is used,
+  // at least not with g++ 4.1.2 under amd64 as it apparently compiles code
+  // using this accessor incorrectly when optimizations are enabled (-O2 is
+  // enough) -- luckily we don't need it then neither as static __thread
+  // variables are initialized by 0 anyhow then and so we can use the variable
+  // directly
+  WXEXPORT static Cache& GetCache()
   {
       static wxTLS_TYPE(Cache) s_cache;
 
       return wxTLS_VALUE(s_cache);
   }
   {
       static wxTLS_TYPE(Cache) s_cache;
 
       return wxTLS_VALUE(s_cache);
   }
+  
+  // this helper struct is used to ensure that GetCache() is called during
+  // static initialization time, i.e. before any threads creation, as otherwise
+  // the static s_cache construction inside GetCache() wouldn't be MT-safe
+  friend struct wxStrCacheInitializer;
+#else // wxHAS_COMPILER_TLS
+  static wxTLS_TYPE(Cache) ms_cache;
+  static Cache& GetCache() { return wxTLS_VALUE(ms_cache); }
+#endif // !wxHAS_COMPILER_TLS/wxHAS_COMPILER_TLS
 
   static Cache::Element *GetCacheBegin() { return GetCache().cached; }
   static Cache::Element *GetCacheEnd() { return GetCacheBegin() + Cache::SIZE; }
   static unsigned& LastUsedCacheElement() { return GetCache().lastUsed; }
 
 
   static Cache::Element *GetCacheBegin() { return GetCache().cached; }
   static Cache::Element *GetCacheEnd() { return GetCacheBegin() + Cache::SIZE; }
   static unsigned& LastUsedCacheElement() { return GetCache().lastUsed; }
 
+  // this is used in debug builds only to provide a convenient function,
+  // callable from a debugger, to show the cache contents
   friend struct wxStrCacheDumper;
 
   // uncomment this to have access to some profiling statistics on program
   friend struct wxStrCacheDumper;
 
   // uncomment this to have access to some profiling statistics on program
@@ -635,7 +649,7 @@ private:
                lenhits; // number of cache hits in length()
   } ms_cacheStats;
 
                lenhits; // number of cache hits in length()
   } ms_cacheStats;
 
-  friend struct ShowCacheStats;
+  friend struct wxStrCacheStatsDumper;
 
   #define wxCACHE_PROFILE_FIELD_INC(field) ms_cacheStats.field++
   #define wxCACHE_PROFILE_FIELD_ADD(field, val) ms_cacheStats.field += (val)
 
   #define wxCACHE_PROFILE_FIELD_INC(field) ms_cacheStats.field++
   #define wxCACHE_PROFILE_FIELD_ADD(field, val) ms_cacheStats.field += (val)
@@ -657,7 +671,15 @@ private:
       // profiling seems to show a small but consistent gain if we use this
       // simple loop instead of starting from the last used element (there are
       // a lot of misses in this function...)
       // profiling seems to show a small but consistent gain if we use this
       // simple loop instead of starting from the last used element (there are
       // a lot of misses in this function...)
-      for ( Cache::Element *c = GetCacheBegin(); c != GetCacheEnd(); c++ )
+      Cache::Element * const cacheBegin = GetCacheBegin();
+#ifndef wxHAS_COMPILER_TLS
+      // during destruction tls calls may return NULL, in this case return NULL 
+      // immediately without accessing anything else
+      if ( cacheBegin == NULL )
+        return NULL;
+#endif
+      Cache::Element * const cacheEnd = GetCacheEnd();
+      for ( Cache::Element *c = cacheBegin; c != cacheEnd; c++ )
       {
           if ( c->str == this )
               return c;
       {
           if ( c->str == this )
               return c;
@@ -719,7 +741,9 @@ private:
       // used for length caching only so far, i.e. it doesn't count as a hit
       // from our point of view
       if ( cache->pos )
       // used for length caching only so far, i.e. it doesn't count as a hit
       // from our point of view
       if ( cache->pos )
+      {
           wxCACHE_PROFILE_FIELD_INC(poshits);
           wxCACHE_PROFILE_FIELD_INC(poshits);
+      }
 
       if ( pos == cache->pos )
           return cache->impl;
 
       if ( pos == cache->pos )
           return cache->impl;
@@ -841,19 +865,19 @@ public:
   #else
     #define WX_STR_ITERATOR_TAG std::random_access_iterator_tag
   #endif
   #else
     #define WX_STR_ITERATOR_TAG std::random_access_iterator_tag
   #endif
-  #define WX_STR_ITERATOR_CATEGORY typedef WX_STR_ITERATOR_TAG iterator_category;
+  #define WX_DEFINE_ITERATOR_CATEGORY(cat) typedef cat iterator_category;
 #else
   // not defining iterator_category at all in this case is better than defining
   // it as some dummy type -- at least it results in more intelligible error
   // messages
 #else
   // not defining iterator_category at all in this case is better than defining
   // it as some dummy type -- at least it results in more intelligible error
   // messages
-  #define WX_STR_ITERATOR_CATEGORY
+  #define WX_DEFINE_ITERATOR_CATEGORY(cat)
 #endif
 
   #define WX_STR_ITERATOR_IMPL(iterator_name, pointer_type, reference_type) \
       private:                                                              \
           typedef wxStringImpl::iterator_name underlying_iterator;          \
       public:                                                               \
 #endif
 
   #define WX_STR_ITERATOR_IMPL(iterator_name, pointer_type, reference_type) \
       private:                                                              \
           typedef wxStringImpl::iterator_name underlying_iterator;          \
       public:                                                               \
-          WX_STR_ITERATOR_CATEGORY                                          \
+          WX_DEFINE_ITERATOR_CATEGORY(WX_STR_ITERATOR_TAG)                  \
           typedef wxUniChar value_type;                                     \
           typedef int difference_type;                                      \
           typedef reference_type reference;                                 \
           typedef wxUniChar value_type;                                     \
           typedef int difference_type;                                      \
           typedef reference_type reference;                                 \
@@ -1088,7 +1112,7 @@ public:
   public:
       typedef T iterator_type;
 
   public:
       typedef T iterator_type;
 
-      typedef typename T::iterator_category iterator_category;
+      WX_DEFINE_ITERATOR_CATEGORY(typename T::iterator_category)
       typedef typename T::value_type value_type;
       typedef typename T::difference_type difference_type;
       typedef typename T::reference reference;
       typedef typename T::value_type value_type;
       typedef typename T::difference_type difference_type;
       typedef typename T::reference reference;
@@ -1434,12 +1458,7 @@ public:
     // truncate the string to given length
   wxString& Truncate(size_t uiLen);
     // empty string contents
     // truncate the string to given length
   wxString& Truncate(size_t uiLen);
     // empty string contents
-  void Empty()
-  {
-    Truncate(0);
-
-    wxASSERT_MSG( empty(), _T("string not empty after call to Empty()?") );
-  }
+  void Empty() { clear(); }
     // empty the string and free memory
   void Clear() { clear(); }
 
     // empty the string and free memory
   void Clear() { clear(); }
 
@@ -1507,11 +1526,53 @@ public:
       { return at(n); }
 #endif // size_t != unsigned int
 
       { return at(n); }
 #endif // size_t != unsigned int
 
-    // explicit conversion to C string (use this with printf()!)
+
+    /*
+        Overview of wxString conversions, implicit and explicit:
+
+        - wxString has a std::[w]string-like c_str() method, however it does
+          not return a C-style string directly but instead returns wxCStrData
+          helper object which is convertible to either "char *" narrow string
+          or "wchar_t *" wide string. Usually the correct conversion will be
+          applied by the compiler automatically but if this doesn't happen you
+          need to explicitly choose one using wxCStrData::AsChar() or AsWChar()
+          methods or another wxString conversion function.
+
+        - One of the places where the conversion does *NOT* happen correctly is
+          when c_str() is passed to a vararg function such as printf() so you
+          must *NOT* use c_str() with them. Either use wxPrintf() (all wx
+          functions do handle c_str() correctly, even if they appear to be
+          vararg (but they're not, really)) or add an explicit AsChar() or, if
+          compatibility with previous wxWidgets versions is important, add a
+          cast to "const char *".
+
+        - In non-STL mode only, wxString is also implicitly convertible to
+          wxCStrData. The same warning as above applies.
+
+        - c_str() is polymorphic as it can be converted to either narrow or
+          wide string. If you explicitly need one or the other, choose to use
+          mb_str() (for narrow) or wc_str() (for wide) instead. Notice that
+          these functions can return either the pointer to string directly (if
+          this is what the string uses internally) or a temporary buffer
+          containing the string and convertible to it. Again, conversion will
+          usually be done automatically by the compiler but beware of the
+          vararg functions: you need an explicit cast when using them.
+
+        - There are also non-const versions of mb_str() and wc_str() called
+          char_str() and wchar_str(). They are only meant to be used with
+          non-const-correct functions and they always return buffers.
+
+        - Finally wx_str() returns whatever string representation is used by
+          wxString internally. It may be either a narrow or wide string
+          depending on wxWidgets build mode but it will always be a raw pointer
+          (and not a buffer).
+     */
+
+    // explicit conversion to wxCStrData
     wxCStrData c_str() const { return wxCStrData(this); }
     wxCStrData data() const { return c_str(); }
 
     wxCStrData c_str() const { return wxCStrData(this); }
     wxCStrData data() const { return c_str(); }
 
-    // implicit conversion to C string
+    // implicit conversion to wxCStrData
     operator wxCStrData() const { return c_str(); }
 
     // the first two operators conflict with operators for conversion to
     operator wxCStrData() const { return c_str(); }
 
     // the first two operators conflict with operators for conversion to