Home | Namespaces | Hierarchy | Alphabetical List | Class list | Files | Namespace Members | Class members | File members | Tutorials

# irrString.h

Go to the documentation of this file.

    00001 // Copyright (C) 2002-2009 Nikolaus Gebhardt
    00002 // This file is part of the "Irrlicht Engine" and the "irrXML" project.
    00003 // For conditions of distribution and use, see copyright notice in irrlicht.h and irrXML.h
    00004
    00005 #ifndef __IRR_STRING_H_INCLUDED__
    00006 #define __IRR_STRING_H_INCLUDED__
    00007
    00008 #include "irrTypes.h"
    00009 #include "irrAllocator.h"
    00010 #include "irrMath.h"
    00011 #include <stdio.h>
    00012 #include <string.h>
    00013 #include <stdlib.h>
    00014
    00015 namespace irr
    00016 {
    00017 namespace core
    00018 {
    00019
    00021
    00032 enum eLocaleID
    00033 {
    00034         IRR_LOCALE_ANSI = 0,
    00035         IRR_LOCALE_GERMAN = 1
    00036 };
    00037
    00038 static eLocaleID locale_current = IRR_LOCALE_ANSI;
    00039 static inline void locale_set ( eLocaleID id )
    00040 {
    00041         locale_current = id;
    00042 }
    00043
    00045 static inline u32 locale_lower ( u32 x )
    00046 {
    00047         switch ( locale_current )
    00048         {
    00049                 case IRR_LOCALE_GERMAN:
    00050                 case IRR_LOCALE_ANSI:
    00051                         break;
    00052         }
    00053         // ansi
    00054         return x >= 'A' && x <= 'Z' ? x + 0x20 : x;
    00055 }
    00056
    00058 static inline u32 locale_upper ( u32 x )
    00059 {
    00060         switch ( locale_current )
    00061         {
    00062                 case IRR_LOCALE_GERMAN:
    00063                 case IRR_LOCALE_ANSI:
    00064                         break;
    00065         }
    00066
    00067         // ansi
    00068         return x >= 'a' && x <= 'z' ? x + ( 'A' - 'a' ) : x;
    00069 }
    00070
    00071
    00072 template <typename T, typename TAlloc = irrAllocator<T> >
    00073 class string
    00074 {
    00075 public:
    00076
    00078         string()
    00079         : array(0), allocated(1), used(1)
    00080         {
    00081                 array = allocator.allocate(1); // new T[1];
    00082                 array[0] = 0x0;
    00083         }
    00084
    00085
    00087         string(const string<T>& other)
    00088         : array(0), allocated(0), used(0)
    00089         {
    00090                 *this = other;
    00091         }
    00092
    00094         template <class B>
    00095         string(const string<B>& other)
    00096         : array(0), allocated(0), used(0)
    00097         {
    00098                 *this = other;
    00099         }
    00100
    00101
    00103         explicit string(const double number)
    00104         : array(0), allocated(0), used(0)
    00105         {
    00106                 c8 tmpbuf[255];
    00107                 snprintf(tmpbuf, 255, "%0.6f", number);
    00108                 *this = tmpbuf;
    00109         }
    00110
    00111
    00113         explicit string(int number)
    00114         : array(0), allocated(0), used(0)
    00115         {
    00116                 // store if negative and make positive
    00117
    00118                 bool negative = false;
    00119                 if (number < 0)
    00120                 {
    00121                         number *= -1;
    00122                         negative = true;
    00123                 }
    00124
    00125                 // temporary buffer for 16 numbers
    00126
    00127                 c8 tmpbuf[16]={0};
    00128                 u32 idx = 15;
    00129
    00130                 // special case '0'
    00131
    00132                 if (!number)
    00133                 {
    00134                         tmpbuf[14] = '0';
    00135                         *this = &tmpbuf[14];
    00136                         return;
    00137                 }
    00138
    00139                 // add numbers
    00140
    00141                 while(number && idx)
    00142                 {
    00143                         --idx;
    00144                         tmpbuf[idx] = (c8)('0' + (number % 10));
    00145                         number /= 10;
    00146                 }
    00147
    00148                 // add sign
    00149
    00150                 if (negative)
    00151                 {
    00152                         --idx;
    00153                         tmpbuf[idx] = '-';
    00154                 }
    00155
    00156                 *this = &tmpbuf[idx];
    00157         }
    00158
    00159
    00161         explicit string(unsigned int number)
    00162         : array(0), allocated(0), used(0)
    00163         {
    00164                 // temporary buffer for 16 numbers
    00165
    00166                 c8 tmpbuf[16]={0};
    00167                 u32 idx = 15;
    00168
    00169                 // special case '0'
    00170
    00171                 if (!number)
    00172                 {
    00173                         tmpbuf[14] = '0';
    00174                         *this = &tmpbuf[14];
    00175                         return;
    00176                 }
    00177
    00178                 // add numbers
    00179
    00180                 while(number && idx)
    00181                 {
    00182                         --idx;
    00183                         tmpbuf[idx] = (c8)('0' + (number % 10));
    00184                         number /= 10;
    00185                 }
    00186
    00187                 *this = &tmpbuf[idx];
    00188         }
    00189
    00190
    00192         template <class B>
    00193         string(const B* const c, u32 length)
    00194         : array(0), allocated(0), used(0)
    00195         {
    00196                 if (!c)
    00197                 {
    00198                         // correctly init the string to an empty one
    00199                         *this="";
    00200                         return;
    00201                 }
    00202
    00203                 allocated = used = length+1;
    00204                 array = allocator.allocate(used); // new T[used];
    00205
    00206                 for (u32 l = 0; l<length; ++l)
    00207                         array[l] = (T)c[l];
    00208
    00209                 array[length] = 0;
    00210         }
    00211
    00212
    00214         template <class B>
    00215         string(const B* const c)
    00216         : array(0), allocated(0), used(0)
    00217         {
    00218                 *this = c;
    00219         }
    00220
    00221
    00223         virtual ~string()
    00224         {
    00225                 allocator.deallocate(array); // delete [] array;
    00226         }
    00227
    00228
    00230         string<T>& operator=(const string<T>& other)
    00231         {
    00232                 if (this == &other)
    00233                         return *this;
    00234
    00235                 allocator.deallocate(array); // delete [] array;
    00236                 allocated = used = other.size()+1;
    00237                 array = allocator.allocate(used); //new T[used];
    00238
    00239                 const T* p = other.c_str();
    00240                 for (u32 i=0; i<used; ++i, ++p)
    00241                         array[i] = *p;
    00242
    00243                 return *this;
    00244         }
    00245
    00247         template <class B>
    00248         string<T>& operator=(const string<B>& other)
    00249         {
    00250                 *this = other.c_str();
    00251                 return *this;
    00252         }
    00253
    00254
    00256         template <class B>
    00257         string<T>& operator=(const B* const c)
    00258         {
    00259                 if (!c)
    00260                 {
    00261                         if (!array)
    00262                         {
    00263                                 array = allocator.allocate(1); //new T[1];
    00264                                 allocated = 1;
    00265                         }
    00266                         used = 1;
    00267                         array[0] = 0x0;
    00268                         return *this;
    00269                 }
    00270
    00271                 if ((void*)c == (void*)array)
    00272                         return *this;
    00273
    00274                 u32 len = 0;
    00275                 const B* p = c;
    00276                 while(*p)
    00277                 {
    00278                         ++len;
    00279                         ++p;
    00280                 }
    00281
    00282                 // we'll take the old string for a while, because the new
    00283                 // string could be a part of the current string.
    00284                 T* oldArray = array;
    00285
    00286                 ++len;
    00287                 allocated = used = len;
    00288                 array = allocator.allocate(used); //new T[used];
    00289
    00290                 for (u32 l = 0; l<len; ++l)
    00291                         array[l] = (T)c[l];
    00292
    00293                 allocator.deallocate(oldArray); // delete [] oldArray;
    00294                 return *this;
    00295         }
    00296
    00297
    00299         string<T> operator+(const string<T>& other) const
    00300         {
    00301                 string<T> str(*this);
    00302                 str.append(other);
    00303
    00304                 return str;
    00305         }
    00306
    00307
    00309         template <class B>
    00310         string<T> operator+(const B* const c) const
    00311         {
    00312                 string<T> str(*this);
    00313                 str.append(c);
    00314
    00315                 return str;
    00316         }
    00317
    00318
    00320         T& operator [](const u32 index)
    00321         {
    00322                 _IRR_DEBUG_BREAK_IF(index>=used) // bad index
    00323                 return array[index];
    00324         }
    00325
    00326
    00328         const T& operator [](const u32 index) const
    00329         {
    00330                 _IRR_DEBUG_BREAK_IF(index>=used) // bad index
    00331                 return array[index];
    00332         }
    00333
    00334
    00336         bool operator ==(const T* const str) const
    00337         {
    00338                 if (!str)
    00339                         return false;
    00340
    00341                 u32 i;
    00342                 for(i=0; array[i] && str[i]; ++i)
    00343                         if (array[i] != str[i])
    00344                                 return false;
    00345
    00346                 return !array[i] && !str[i];
    00347         }
    00348
    00349
    00351         bool operator ==(const string<T>& other) const
    00352         {
    00353                 for(u32 i=0; array[i] && other.array[i]; ++i)
    00354                         if (array[i] != other.array[i])
    00355                                 return false;
    00356
    00357                 return used == other.used;
    00358         }
    00359
    00360
    00362         bool operator <(const string<T>& other) const
    00363         {
    00364                 for(u32 i=0; array[i] && other.array[i]; ++i)
    00365                 {
    00366                         s32 diff = array[i] - other.array[i];
    00367                         if ( diff )
    00368                                 return diff < 0;
    00369 /*
    00370                         if (array[i] != other.array[i])
    00371                                 return (array[i] < other.array[i]);
    00372 */
    00373                 }
    00374
    00375                 return used < other.used;
    00376         }
    00377
    00378
    00380         bool operator !=(const T* const str) const
    00381         {
    00382                 return !(*this == str);
    00383         }
    00384
    00385
    00387         bool operator !=(const string<T>& other) const
    00388         {
    00389                 return !(*this == other);
    00390         }
    00391
    00392
    00394
    00395         u32 size() const
    00396         {
    00397                 return used-1;
    00398         }
    00399
    00400
    00402
    00403         const T* c_str() const
    00404         {
    00405                 return array;
    00406         }
    00407
    00408
    00410         void make_lower()
    00411         {
    00412                 for (u32 i=0; i<used; ++i)
    00413                         array[i] = locale_lower ( array[i] );
    00414         }
    00415
    00416
    00418         void make_upper()
    00419         {
    00420                 for (u32 i=0; i<used; ++i)
    00421                         array[i] = locale_upper ( array[i] );
    00422         }
    00423
    00424
    00426
    00428         bool equals_ignore_case(const string<T>& other) const
    00429         {
    00430                 for(u32 i=0; array[i] && other[i]; ++i)
    00431                         if (locale_lower( array[i]) != locale_lower(other[i]))
    00432                                 return false;
    00433
    00434                 return used == other.used;
    00435         }
    00436
    00438
    00441         bool equals_substring_ignore_case(const string<T>&other, const s32 sourcePos = 0 ) const
    00442         {
    00443                 if ( (u32) sourcePos > used )
    00444                         return false;
    00445
    00446                 u32 i;
    00447                 for( i=0; array[sourcePos + i] && other[i]; ++i)
    00448                         if (locale_lower( array[sourcePos + i]) != locale_lower(other[i]))
    00449                                 return false;
    00450
    00451                 return array[sourcePos + i] == 0 && other[i] == 0;
    00452         }
    00453
    00454
    00456
    00458         bool lower_ignore_case(const string<T>& other) const
    00459         {
    00460                 for(u32 i=0; array[i] && other.array[i]; ++i)
    00461                 {
    00462                         s32 diff = (s32) locale_lower ( array[i] ) - (s32) locale_lower ( other.array[i] );
    00463                         if ( diff )
    00464                                 return diff < 0;
    00465                 }
    00466
    00467                 return used < other.used;
    00468         }
    00469
    00470
    00472
    00475         bool equalsn(const string<T>& other, u32 n) const
    00476         {
    00477                 u32 i;
    00478                 for(i=0; array[i] && other[i] && i < n; ++i)
    00479                         if (array[i] != other[i])
    00480                                 return false;
    00481
    00482                 // if one (or both) of the strings was smaller then they
    00483                 // are only equal if they have the same length
    00484                 return (i == n) || (used == other.used);
    00485         }
    00486
    00487
    00489
    00492         bool equalsn(const T* const str, u32 n) const
    00493         {
    00494                 if (!str)
    00495                         return false;
    00496                 u32 i;
    00497                 for(i=0; array[i] && str[i] && i < n; ++i)
    00498                         if (array[i] != str[i])
    00499                                 return false;
    00500
    00501                 // if one (or both) of the strings was smaller then they
    00502                 // are only equal if they have the same length
    00503                 return (i == n) || (array[i] == 0 && str[i] == 0);
    00504         }
    00505
    00506
    00508
    00509         void append(T character)
    00510         {
    00511                 if (used + 1 > allocated)
    00512                         reallocate(used + 1);
    00513
    00514                 ++used;
    00515
    00516                 array[used-2] = character;
    00517                 array[used-1] = 0;
    00518         }
    00519
    00520
    00522
    00523         void append(const T* const other)
    00524         {
    00525                 if (!other)
    00526                         return;
    00527
    00528                 u32 len = 0;
    00529                 const T* p = other;
    00530                 while(*p)
    00531                 {
    00532                         ++len;
    00533                         ++p;
    00534                 }
    00535
    00536                 if (used + len > allocated)
    00537                         reallocate(used + len);
    00538
    00539                 --used;
    00540                 ++len;
    00541
    00542                 for (u32 l=0; l<len; ++l)
    00543                         array[l+used] = *(other+l);
    00544
    00545                 used += len;
    00546         }
    00547
    00548
    00550
    00551         void append(const string<T>& other)
    00552         {
    00553                 --used;
    00554                 u32 len = other.size()+1;
    00555
    00556                 if (used + len > allocated)
    00557                         reallocate(used + len);
    00558
    00559                 for (u32 l=0; l<len; ++l)
    00560                         array[used+l] = other[l];
    00561
    00562                 used += len;
    00563         }
    00564
    00565
    00567
    00569         void append(const string<T>& other, u32 length)
    00570         {
    00571                 if (other.size() < length)
    00572                 {
    00573                         append(other);
    00574                         return;
    00575                 }
    00576
    00577                 if (used + length > allocated)
    00578                         reallocate(used + length);
    00579
    00580                 --used;
    00581
    00582                 for (u32 l=0; l<length; ++l)
    00583                         array[l+used] = other[l];
    00584                 used += length;
    00585
    00586                 // ensure proper termination
    00587                 array[used]=0;
    00588                 ++used;
    00589         }
    00590
    00591
    00593
    00594         void reserve(u32 count)
    00595         {
    00596                 if (count < allocated)
    00597                         return;
    00598
    00599                 reallocate(count);
    00600         }
    00601
    00602
    00604
    00607         s32 findFirst(T c) const
    00608         {
    00609                 for (u32 i=0; i<used; ++i)
    00610                         if (array[i] == c)
    00611                                 return i;
    00612
    00613                 return -1;
    00614         }
    00615
    00617
    00623         s32 findFirstChar(const T* const c, u32 count) const
    00624         {
    00625                 if (!c)
    00626                         return -1;
    00627
    00628                 for (u32 i=0; i<used; ++i)
    00629                         for (u32 j=0; j<count; ++j)
    00630                                 if (array[i] == c[j])
    00631                                         return i;
    00632
    00633                 return -1;
    00634         }
    00635
    00636
    00638
    00644         template <class B>
    00645         s32 findFirstCharNotInList(const B* const c, u32 count) const
    00646         {
    00647                 for (u32 i=0; i<used-1; ++i)
    00648                 {
    00649                         u32 j;
    00650                         for (j=0; j<count; ++j)
    00651                                 if (array[i] == c[j])
    00652                                         break;
    00653
    00654                         if (j==count)
    00655                                 return i;
    00656                 }
    00657
    00658                 return -1;
    00659         }
    00660
    00662
    00668         template <class B>
    00669         s32 findLastCharNotInList(const B* const c, u32 count) const
    00670         {
    00671                 for (s32 i=(s32)(used-2); i>=0; --i)
    00672                 {
    00673                         u32 j;
    00674                         for (j=0; j<count; ++j)
    00675                                 if (array[i] == c[j])
    00676                                         break;
    00677
    00678                         if (j==count)
    00679                                 return i;
    00680                 }
    00681
    00682                 return -1;
    00683         }
    00684
    00686
    00690         s32 findNext(T c, u32 startPos) const
    00691         {
    00692                 for (u32 i=startPos; i<used; ++i)
    00693                         if (array[i] == c)
    00694                                 return i;
    00695
    00696                 return -1;
    00697         }
    00698
    00699
    00701
    00705         s32 findLast(T c, s32 start = -1) const
    00706         {
    00707                 start = core::clamp ( start < 0 ? (s32)(used) - 1 : start, 0, (s32)(used) - 1 );
    00708                 for (s32 i=start; i>=0; --i)
    00709                         if (array[i] == c)
    00710                                 return i;
    00711
    00712                 return -1;
    00713         }
    00714
    00716
    00722         s32 findLastChar(const T* const c, u32 count) const
    00723         {
    00724                 if (!c)
    00725                         return -1;
    00726
    00727                 for (s32 i=used-1; i>=0; --i)
    00728                         for (u32 j=0; j<count; ++j)
    00729                                 if (array[i] == c[j])
    00730                                         return i;
    00731
    00732                 return -1;
    00733         }
    00734
    00735
    00737
    00740         template <class B>
    00741         s32 find(const B* const str) const
    00742         {
    00743                 if (str && *str)
    00744                 {
    00745                         u32 len = 0;
    00746
    00747                         while (str[len])
    00748                                 ++len;
    00749
    00750                         if (len > used-1)
    00751                                 return -1;
    00752
    00753                         for (u32 i=0; i<used-len; ++i)
    00754                         {
    00755                                 u32 j=0;
    00756
    00757                                 while(str[j] && array[i+j] == str[j])
    00758                                         ++j;
    00759
    00760                                 if (!str[j])
    00761                                         return i;
    00762                         }
    00763                 }
    00764
    00765                 return -1;
    00766         }
    00767
    00768
    00770
    00772         string<T> subString(u32 begin, s32 length) const
    00773         {
    00774                 // if start after string
    00775                 // or no proper substring length
    00776                 if ((length <= 0) || (begin>=size()))
    00777                         return string<T>("");
    00778                 // clamp length to maximal value
    00779                 if ((length+begin) > size())
    00780                         length = size()-begin;
    00781
    00782                 string<T> o;
    00783                 o.reserve(length+1);
    00784
    00785                 for (s32 i=0; i<length; ++i)
    00786                         o.array[i] = array[i+begin];
    00787
    00788                 o.array[length] = 0;
    00789                 o.used = o.allocated;
    00790
    00791                 return o;
    00792         }
    00793
    00794
    00796
    00797         string<T>& operator += (T c)
    00798         {
    00799                 append(c);
    00800                 return *this;
    00801         }
    00802
    00803
    00805
    00806         string<T>& operator += (const T* const c)
    00807         {
    00808                 append(c);
    00809                 return *this;
    00810         }
    00811
    00812
    00814
    00815         string<T>& operator += (const string<T>& other)
    00816         {
    00817                 append(other);
    00818                 return *this;
    00819         }
    00820
    00821
    00823
    00824         string<T>& operator += (const int i)
    00825         {
    00826                 append(string<T>(i));
    00827                 return *this;
    00828         }
    00829
    00830
    00832
    00833         string<T>& operator += (const unsigned int i)
    00834         {
    00835                 append(string<T>(i));
    00836                 return *this;
    00837         }
    00838
    00839
    00841
    00842         string<T>& operator += (const long i)
    00843         {
    00844                 append(string<T>(i));
    00845                 return *this;
    00846         }
    00847
    00848
    00850
    00851         string<T>& operator += (const unsigned long& i)
    00852         {
    00853                 append(string<T>(i));
    00854                 return *this;
    00855         }
    00856
    00857
    00859
    00860         string<T>& operator += (const double i)
    00861         {
    00862                 append(string<T>(i));
    00863                 return *this;
    00864         }
    00865
    00866
    00868
    00869         string<T>& operator += (const float i)
    00870         {
    00871                 append(string<T>(i));
    00872                 return *this;
    00873         }
    00874
    00875
    00877
    00879         void replace(T toReplace, T replaceWith)
    00880         {
    00881                 for (u32 i=0; i<used; ++i)
    00882                         if (array[i] == toReplace)
    00883                                 array[i] = replaceWith;
    00884         }
    00885
    00886
    00888
    00890         string<T>& trim(const string<T> & whitespace = " \t\n\r")
    00891         {
    00892                 // find start and end of the substring without the specified characters
    00893                 const s32 begin = findFirstCharNotInList(whitespace.c_str(), whitespace.used);
    00894                 if (begin == -1)
    00895                         return (*this="");
    00896
    00897                 const s32 end = findLastCharNotInList(whitespace.c_str(), whitespace.used);
    00898
    00899                 return (*this = subString(begin, (end +1) - begin));
    00900         }
    00901
    00902
    00904
    00907         void erase(u32 index)
    00908         {
    00909                 _IRR_DEBUG_BREAK_IF(index>=used) // access violation
    00910
    00911                 for (u32 i=index+1; i<used; ++i)
    00912                         array[i-1] = array[i];
    00913
    00914                 --used;
    00915         }
    00916
    00918         void validate()
    00919         {
    00920                 // terminate on existing null
    00921                 for (u32 i=0; i<allocated; ++i)
    00922                 {
    00923                         if (array[i] == 0)
    00924                         {
    00925                                 used = i + 1;
    00926                                 return;
    00927                         }
    00928                 }
    00929
    00930                 // terminate
    00931                 if ( allocated > 0 )
    00932                 {
    00933                         used = allocated - 1;
    00934                         array[used] = 0;
    00935                 }
    00936                 else
    00937                 {
    00938                         used = 0;
    00939                 }
    00940         }
    00941
    00943         inline T lastChar() const
    00944         {
    00945                 return used > 1 ? array[used-2] : 0;
    00946         }
    00947
    00948 private:
    00949
    00951         void reallocate(u32 new_size)
    00952         {
    00953                 T* old_array = array;
    00954
    00955                 array = allocator.allocate(new_size); //new T[new_size];
    00956                 allocated = new_size;
    00957
    00958                 u32 amount = used < new_size ? used : new_size;
    00959                 for (u32 i=0; i<amount; ++i)
    00960                         array[i] = old_array[i];
    00961
    00962                 if (allocated < used)
    00963                         used = allocated;
    00964
    00965                 allocator.deallocate(old_array); // delete [] old_array;
    00966         }
    00967
    00968         //--- member variables
    00969
    00970         T* array;
    00971         TAlloc allocator;
    00972         u32 allocated;
    00973         u32 used;
    00974 };
    00975
    00976
    00978 typedef string<c8> stringc;
    00979
    00981 typedef string<wchar_t> stringw;
    00982
    00983
    00984 } // end namespace core
    00985 } // end namespace irr
    00986
    00987 #endif
    00988

| The Irrlicht Engine Documentation © 2003-2009 by Nikolaus Gebhardt. Generated on Sun Jan 10 09:24:04 2010 by Doxygen (1.5.6)