00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef __CS_STRINGARRAY_H__
00021 #define __CS_STRINGARRAY_H__
00022
00027 #include <stdarg.h>
00028 #include "csextern.h"
00029 #include "csutil/array.h"
00030 #include "csutil/util.h"
00031 #include "csutil/csstring.h"
00032
00033 class csStringArrayElementHandler : public csArrayElementHandler<const char*>
00034 {
00035 public:
00036 static void Construct (const char** address, const char* const& src)
00037 {
00038 *address = csStrNew (src);
00039 }
00040
00041 static void Destroy (const char** address)
00042 {
00043 delete[] (char*)*address;
00044 }
00045
00046 static void InitRegion (const char** address, size_t count)
00047 {
00048 memset (address, 0, count*sizeof (const char*));
00049 }
00050 };
00051
00052 namespace CS
00053 {
00054 namespace Utility
00055 {
00061 template <class Allocator = CS::Memory::AllocatorMalloc,
00062 class CapacityHandler = csArrayCapacityFixedGrow<16> >
00063 class StringArray :
00064 public csArray<const char*, csStringArrayElementHandler, Allocator,
00065 CapacityHandler>
00066 {
00067 private:
00068 typedef csArray<const char*, csStringArrayElementHandler, Allocator,
00069 CapacityHandler> superclass;
00070
00071 public:
00076 StringArray (size_t limit = 0, const CapacityHandler& ch = CapacityHandler())
00077 : superclass(limit, ch)
00078 {
00079 }
00080
00082 static int CaseSensitiveCompare (const char* const &item1,
00083 const char* const &item2)
00084 {
00085 return strcmp (item1, item2);
00086 }
00087
00089 static int CaseInsensitiveCompare (const char* const &item1,
00090 const char* const &item2)
00091 {
00092 return csStrCaseCmp (item1, item2);
00093 }
00094
00098 void Sort (int(*compare)(char const* const&, char const* const&))
00099 {
00100 superclass::Sort (compare);
00101 }
00102
00108 void Sort (bool case_sensitive = true)
00109 {
00110 if (case_sensitive)
00111 Sort (CaseSensitiveCompare);
00112 else
00113 Sort (CaseInsensitiveCompare);
00114 }
00115
00121 size_t FindSortedKey (csArrayCmp<char const*, char const*> comparekey,
00122 size_t* candidate = 0) const
00123 {
00124 return superclass::FindSortedKey(comparekey, candidate);
00125 }
00126
00132 size_t FindSortedKey (char const* key, bool case_sensitive = true,
00133 size_t* candidate = 0) const
00134 {
00135 int(*cf)(char const* const&, char const* const&) =
00136 case_sensitive ? CaseSensitiveCompare : CaseInsensitiveCompare;
00137 return FindSortedKey(csArrayCmp<char const*, char const*>(key, cf),
00138 candidate);
00139 }
00140
00145 size_t InsertSorted (const char* item, bool case_sensitive = true,
00146 size_t* equal_index = 0)
00147 {
00148 int(*cf)(char const* const&, char const* const&) =
00149 case_sensitive ? CaseSensitiveCompare : CaseInsensitiveCompare;
00150 return superclass::InsertSorted (item, cf, equal_index);
00151 }
00152
00158 char* Pop ()
00159 {
00160 CS_ASSERT (this->GetSize () > 0);
00161 size_t l = this->GetSize () - 1;
00162 char* ret = (char*)this->Get (l);
00163 this->InitRegion (l, 1);
00164 this->SetSize (l);
00165 return ret;
00166 }
00167
00174 size_t Find (const char* str) const
00175 {
00176 for (size_t i = 0; i < this->GetSize (); i++)
00177 if (! strcmp (this->Get (i), str))
00178 return i;
00179 return (size_t)-1;
00180 }
00181
00188 bool Delete (const char* item)
00189 {
00190 size_t const n = Find (item);
00191 if (n != csArrayItemNotFound)
00192 return superclass::DeleteIndex (n);
00193 return false;
00194 }
00195
00202 size_t FindCaseInsensitive (const char* str) const
00203 {
00204 for (size_t i = 0; i < this->GetSize (); i++)
00205 if (!csStrCaseCmp (this->Get (i), str))
00206 return i;
00207 return (size_t)-1;
00208 }
00209
00221 size_t Contains(const char* str, bool case_sensitive = true) const
00222 {
00223 return case_sensitive ? Find(str) : FindCaseInsensitive(str);
00224 }
00225
00229 enum ConsecutiveDelimiterMode
00230 {
00232 delimSplitEach,
00238 delimIgnore,
00242 delimIgnoreDifferent
00243 };
00244
00253 StringArray (const char* str, const char* delimiters,
00254 ConsecutiveDelimiterMode delimMode = delimSplitEach,
00255 size_t limit = 0, const CapacityHandler& ch = CapacityHandler())
00256 : superclass(limit, ch)
00257 {
00258 SplitString(str, delimiters, delimMode);
00259 }
00260
00267 size_t SplitString (const char* str, const char* delimiters,
00268 ConsecutiveDelimiterMode delimMode = delimSplitEach)
00269 {
00270 size_t num = 0;
00271 csString currentString = "";
00272 int lastDelim = -1;
00273
00274 const char* p = str;
00275 while (*p != 0)
00276 {
00277 if (strchr (delimiters, *p))
00278 {
00279 bool newString = true;
00280 switch (delimMode)
00281 {
00282 case delimSplitEach:
00283 break;
00284 case delimIgnore:
00285 newString = lastDelim == -1;
00286 break;
00287 case delimIgnoreDifferent:
00288 newString = (lastDelim == -1) || (lastDelim == *p);
00289 break;
00290 }
00291 if (newString)
00292 {
00293 this->Push (currentString);
00294 currentString.Empty();
00295 num++;
00296 lastDelim = *p;
00297 }
00298 }
00299 else
00300 {
00301 currentString.Append (*p);
00302 lastDelim = -1;
00303 }
00304 p++;
00305 }
00306
00307 this->Push (currentString);
00308 return num + 1;
00309 }
00310 };
00311 }
00312 }
00313
00317 class csStringArray :
00318 public CS::Utility::StringArray<CS::Memory::AllocatorMalloc,
00319 csArrayCapacityDefault>
00320 {
00321 public:
00328 csStringArray (size_t limit = 0, size_t threshold = 0)
00329 : CS::Utility::StringArray<CS::Memory::AllocatorMalloc,
00330 csArrayCapacityDefault> (limit, threshold)
00331 {
00332 }
00333
00343 csStringArray (const char* str, const char* delimiters,
00344 ConsecutiveDelimiterMode delimMode = delimSplitEach,
00345 size_t limit = 0, size_t threshold = 0)
00346 : CS::Utility::StringArray<CS::Memory::AllocatorMalloc,
00347 csArrayCapacityDefault> (str, delimiters,
00348 delimMode, limit, threshold)
00349 {
00350 }
00351 };
00352
00353 #endif // __CS_STRINGARRAY_H__