Str.h 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216
  1. /*
  2. ===========================================================================
  3. Doom 3 BFG Edition GPL Source Code
  4. Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
  6. Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
  17. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
  18. ===========================================================================
  19. */
  20. #ifndef __STR_H__
  21. #define __STR_H__
  22. /*
  23. ===============================================================================
  24. Character string
  25. ===============================================================================
  26. */
  27. #define ASSERT_ENUM_STRING( string, index ) ( 1 / (int)!( string - index ) ) ? #string : ""
  28. enum utf8Encoding_t {
  29. UTF8_PURE_ASCII, // no characters with values > 127
  30. UTF8_ENCODED_BOM, // characters > 128 encoded with UTF8, but no byte-order-marker at the beginning
  31. UTF8_ENCODED_NO_BOM, // characters > 128 encoded with UTF8, with a byte-order-marker at the beginning
  32. UTF8_INVALID, // has values > 127 but isn't valid UTF8
  33. UTF8_INVALID_BOM // has a byte-order-marker at the beginning, but isn't valuid UTF8 -- it's messed up
  34. };
  35. // these library functions should not be used for cross platform compatibility
  36. #define strcmp idStr::Cmp // use_idStr_Cmp
  37. #define strncmp use_idStr_Cmpn
  38. #if defined( StrCmpN )
  39. #undef StrCmpN
  40. #endif
  41. #define StrCmpN use_idStr_Cmpn
  42. #if defined( strcmpi )
  43. #undef strcmpi
  44. #endif
  45. #define strcmpi use_idStr_Icmp
  46. #if defined( StrCmpI )
  47. #undef StrCmpI
  48. #endif
  49. #define StrCmpI use_idStr_Icmp
  50. #if defined( StrCmpNI )
  51. #undef StrCmpNI
  52. #endif
  53. #define StrCmpNI use_idStr_Icmpn
  54. #define stricmp idStr::Icmp // use_idStr_Icmp
  55. #define _stricmp use_idStr_Icmp
  56. #define strcasecmp use_idStr_Icmp
  57. #define strnicmp use_idStr_Icmpn
  58. #define _strnicmp use_idStr_Icmpn
  59. #define _memicmp use_idStr_Icmpn
  60. #define snprintf use_idStr_snPrintf
  61. #define _snprintf use_idStr_snPrintf
  62. #define vsnprintf use_idStr_vsnPrintf
  63. #define _vsnprintf use_idStr_vsnPrintf
  64. class idVec4;
  65. #ifndef FILE_HASH_SIZE
  66. #define FILE_HASH_SIZE 1024
  67. #endif
  68. // color escape character
  69. const int C_COLOR_ESCAPE = '^';
  70. const int C_COLOR_DEFAULT = '0';
  71. const int C_COLOR_RED = '1';
  72. const int C_COLOR_GREEN = '2';
  73. const int C_COLOR_YELLOW = '3';
  74. const int C_COLOR_BLUE = '4';
  75. const int C_COLOR_CYAN = '5';
  76. const int C_COLOR_ORANGE = '6';
  77. const int C_COLOR_WHITE = '7';
  78. const int C_COLOR_GRAY = '8';
  79. const int C_COLOR_BLACK = '9';
  80. // color escape string
  81. #define S_COLOR_DEFAULT "^0"
  82. #define S_COLOR_RED "^1"
  83. #define S_COLOR_GREEN "^2"
  84. #define S_COLOR_YELLOW "^3"
  85. #define S_COLOR_BLUE "^4"
  86. #define S_COLOR_CYAN "^5"
  87. #define S_COLOR_ORANGE "^6"
  88. #define S_COLOR_WHITE "^7"
  89. #define S_COLOR_GRAY "^8"
  90. #define S_COLOR_BLACK "^9"
  91. // make idStr a multiple of 16 bytes long
  92. // don't make too large to keep memory requirements to a minimum
  93. const int STR_ALLOC_BASE = 20;
  94. const int STR_ALLOC_GRAN = 32;
  95. typedef enum {
  96. MEASURE_SIZE = 0,
  97. MEASURE_BANDWIDTH
  98. } Measure_t;
  99. class idStr {
  100. public:
  101. idStr();
  102. idStr( const idStr &text );
  103. idStr( const idStr &text, int start, int end );
  104. idStr( const char *text );
  105. idStr( const char *text, int start, int end );
  106. explicit idStr( const bool b );
  107. explicit idStr( const char c );
  108. explicit idStr( const int i );
  109. explicit idStr( const unsigned u );
  110. explicit idStr( const float f );
  111. ~idStr();
  112. size_t Size() const;
  113. const char * c_str() const;
  114. operator const char *() const;
  115. operator const char *();
  116. char operator[]( int index ) const;
  117. char & operator[]( int index );
  118. void operator=( const idStr &text );
  119. void operator=( const char *text );
  120. friend idStr operator+( const idStr &a, const idStr &b );
  121. friend idStr operator+( const idStr &a, const char *b );
  122. friend idStr operator+( const char *a, const idStr &b );
  123. friend idStr operator+( const idStr &a, const float b );
  124. friend idStr operator+( const idStr &a, const int b );
  125. friend idStr operator+( const idStr &a, const unsigned b );
  126. friend idStr operator+( const idStr &a, const bool b );
  127. friend idStr operator+( const idStr &a, const char b );
  128. idStr & operator+=( const idStr &a );
  129. idStr & operator+=( const char *a );
  130. idStr & operator+=( const float a );
  131. idStr & operator+=( const char a );
  132. idStr & operator+=( const int a );
  133. idStr & operator+=( const unsigned a );
  134. idStr & operator+=( const bool a );
  135. // case sensitive compare
  136. friend bool operator==( const idStr &a, const idStr &b );
  137. friend bool operator==( const idStr &a, const char *b );
  138. friend bool operator==( const char *a, const idStr &b );
  139. // case sensitive compare
  140. friend bool operator!=( const idStr &a, const idStr &b );
  141. friend bool operator!=( const idStr &a, const char *b );
  142. friend bool operator!=( const char *a, const idStr &b );
  143. // case sensitive compare
  144. int Cmp( const char *text ) const;
  145. int Cmpn( const char *text, int n ) const;
  146. int CmpPrefix( const char *text ) const;
  147. // case insensitive compare
  148. int Icmp( const char *text ) const;
  149. int Icmpn( const char *text, int n ) const;
  150. int IcmpPrefix( const char *text ) const;
  151. // case insensitive compare ignoring color
  152. int IcmpNoColor( const char *text ) const;
  153. // compares paths and makes sure folders come first
  154. int IcmpPath( const char *text ) const;
  155. int IcmpnPath( const char *text, int n ) const;
  156. int IcmpPrefixPath( const char *text ) const;
  157. int Length() const;
  158. int Allocated() const;
  159. void Empty();
  160. bool IsEmpty() const;
  161. void Clear();
  162. void Append( const char a );
  163. void Append( const idStr &text );
  164. void Append( const char *text );
  165. void Append( const char *text, int len );
  166. void Insert( const char a, int index );
  167. void Insert( const char *text, int index );
  168. void ToLower();
  169. void ToUpper();
  170. bool IsNumeric() const;
  171. bool IsColor() const;
  172. bool HasLower() const;
  173. bool HasUpper() const;
  174. int LengthWithoutColors() const;
  175. idStr & RemoveColors();
  176. void CapLength( int );
  177. void Fill( const char ch, int newlen );
  178. ID_INLINE int UTF8Length();
  179. ID_INLINE uint32 UTF8Char( int & idx );
  180. static int UTF8Length( const byte * s );
  181. static ID_INLINE uint32 UTF8Char( const char * s, int & idx );
  182. static uint32 UTF8Char( const byte * s, int & idx );
  183. void AppendUTF8Char( uint32 c );
  184. ID_INLINE void ConvertToUTF8();
  185. static bool IsValidUTF8( const uint8 * s, const int maxLen, utf8Encoding_t & encoding );
  186. static ID_INLINE bool IsValidUTF8( const char * s, const int maxLen, utf8Encoding_t & encoding ) { return IsValidUTF8( ( const uint8* )s, maxLen, encoding ); }
  187. static ID_INLINE bool IsValidUTF8( const uint8 * s, const int maxLen );
  188. static ID_INLINE bool IsValidUTF8( const char * s, const int maxLen ) { return IsValidUTF8( ( const uint8* )s, maxLen ); }
  189. int Find( const char c, int start = 0, int end = -1 ) const;
  190. int Find( const char *text, bool casesensitive = true, int start = 0, int end = -1 ) const;
  191. bool Filter( const char *filter, bool casesensitive ) const;
  192. int Last( const char c ) const; // return the index to the last occurance of 'c', returns -1 if not found
  193. const char * Left( int len, idStr &result ) const; // store the leftmost 'len' characters in the result
  194. const char * Right( int len, idStr &result ) const; // store the rightmost 'len' characters in the result
  195. const char * Mid( int start, int len, idStr &result ) const; // store 'len' characters starting at 'start' in result
  196. idStr Left( int len ) const; // return the leftmost 'len' characters
  197. idStr Right( int len ) const; // return the rightmost 'len' characters
  198. idStr Mid( int start, int len ) const; // return 'len' characters starting at 'start'
  199. void Format( VERIFY_FORMAT_STRING const char *fmt, ... ); // perform a threadsafe sprintf to the string
  200. static idStr FormatInt( const int num, bool isCash = false ); // formats an integer as a value with commas
  201. static idStr FormatCash( const int num ) { return FormatInt( num, true ); }
  202. void StripLeading( const char c ); // strip char from front as many times as the char occurs
  203. void StripLeading( const char *string ); // strip string from front as many times as the string occurs
  204. bool StripLeadingOnce( const char *string ); // strip string from front just once if it occurs
  205. void StripTrailing( const char c ); // strip char from end as many times as the char occurs
  206. void StripTrailing( const char *string ); // strip string from end as many times as the string occurs
  207. bool StripTrailingOnce( const char *string ); // strip string from end just once if it occurs
  208. void Strip( const char c ); // strip char from front and end as many times as the char occurs
  209. void Strip( const char *string ); // strip string from front and end as many times as the string occurs
  210. void StripTrailingWhitespace(); // strip trailing white space characters
  211. idStr & StripQuotes(); // strip quotes around string
  212. bool Replace( const char *old, const char *nw );
  213. bool ReplaceChar( const char old, const char nw );
  214. ID_INLINE void CopyRange( const char * text, int start, int end );
  215. // file name methods
  216. int FileNameHash() const; // hash key for the filename (skips extension)
  217. idStr & BackSlashesToSlashes(); // convert slashes
  218. idStr & SlashesToBackSlashes(); // convert slashes
  219. idStr & SetFileExtension( const char *extension ); // set the given file extension
  220. idStr & StripFileExtension(); // remove any file extension
  221. idStr & StripAbsoluteFileExtension(); // remove any file extension looking from front (useful if there are multiple .'s)
  222. idStr & DefaultFileExtension( const char *extension ); // if there's no file extension use the default
  223. idStr & DefaultPath( const char *basepath ); // if there's no path use the default
  224. void AppendPath( const char *text ); // append a partial path
  225. idStr & StripFilename(); // remove the filename from a path
  226. idStr & StripPath(); // remove the path from the filename
  227. void ExtractFilePath( idStr &dest ) const; // copy the file path to another string
  228. void ExtractFileName( idStr &dest ) const; // copy the filename to another string
  229. void ExtractFileBase( idStr &dest ) const; // copy the filename minus the extension to another string
  230. void ExtractFileExtension( idStr &dest ) const; // copy the file extension to another string
  231. bool CheckExtension( const char *ext );
  232. // char * methods to replace library functions
  233. static int Length( const char *s );
  234. static char * ToLower( char *s );
  235. static char * ToUpper( char *s );
  236. static bool IsNumeric( const char *s );
  237. static bool IsColor( const char *s );
  238. static bool HasLower( const char *s );
  239. static bool HasUpper( const char *s );
  240. static int LengthWithoutColors( const char *s );
  241. static char * RemoveColors( char *s );
  242. static int Cmp( const char *s1, const char *s2 );
  243. static int Cmpn( const char *s1, const char *s2, int n );
  244. static int Icmp( const char *s1, const char *s2 );
  245. static int Icmpn( const char *s1, const char *s2, int n );
  246. static int IcmpNoColor( const char *s1, const char *s2 );
  247. static int IcmpPath( const char *s1, const char *s2 ); // compares paths and makes sure folders come first
  248. static int IcmpnPath( const char *s1, const char *s2, int n ); // compares paths and makes sure folders come first
  249. static void Append( char *dest, int size, const char *src );
  250. static void Copynz( char *dest, const char *src, int destsize );
  251. static int snPrintf( char *dest, int size, VERIFY_FORMAT_STRING const char *fmt, ... );
  252. static int vsnPrintf( char *dest, int size, const char *fmt, va_list argptr );
  253. static int FindChar( const char *str, const char c, int start = 0, int end = -1 );
  254. static int FindText( const char *str, const char *text, bool casesensitive = true, int start = 0, int end = -1 );
  255. static bool Filter( const char *filter, const char *name, bool casesensitive );
  256. static void StripMediaName( const char *name, idStr &mediaName );
  257. static bool CheckExtension( const char *name, const char *ext );
  258. static const char * FloatArrayToString( const float *array, const int length, const int precision );
  259. static const char * CStyleQuote( const char *str );
  260. static const char * CStyleUnQuote( const char *str );
  261. // hash keys
  262. static int Hash( const char *string );
  263. static int Hash( const char *string, int length );
  264. static int IHash( const char *string ); // case insensitive
  265. static int IHash( const char *string, int length ); // case insensitive
  266. // character methods
  267. static char ToLower( char c );
  268. static char ToUpper( char c );
  269. static bool CharIsPrintable( int c );
  270. static bool CharIsLower( int c );
  271. static bool CharIsUpper( int c );
  272. static bool CharIsAlpha( int c );
  273. static bool CharIsNumeric( int c );
  274. static bool CharIsNewLine( char c );
  275. static bool CharIsTab( char c );
  276. static int ColorIndex( int c );
  277. static idVec4 & ColorForIndex( int i );
  278. friend int sprintf( idStr &dest, const char *fmt, ... );
  279. friend int vsprintf( idStr &dest, const char *fmt, va_list ap );
  280. void ReAllocate( int amount, bool keepold ); // reallocate string data buffer
  281. void FreeData(); // free allocated string memory
  282. // format value in the given measurement with the best unit, returns the best unit
  283. int BestUnit( const char *format, float value, Measure_t measure );
  284. // format value in the requested unit and measurement
  285. void SetUnit( const char *format, float value, int unit, Measure_t measure );
  286. static void InitMemory();
  287. static void ShutdownMemory();
  288. static void PurgeMemory();
  289. static void ShowMemoryUsage_f( const idCmdArgs &args );
  290. int DynamicMemoryUsed() const;
  291. static idStr FormatNumber( int number );
  292. protected:
  293. int len;
  294. char * data;
  295. int allocedAndFlag; // top bit is used to store a flag that indicates if the string data is static or not
  296. char baseBuffer[ STR_ALLOC_BASE ];
  297. void EnsureAlloced( int amount, bool keepold = true ); // ensure string data buffer is large anough
  298. // sets the data point to the specified buffer... note that this ignores makes the passed buffer empty and ignores
  299. // anything currently in the idStr's dynamic buffer. This method is intended to be called only from a derived class's constructor.
  300. ID_INLINE void SetStaticBuffer( char * buffer, const int bufferLength );
  301. private:
  302. // initialize string using base buffer... call ONLY FROM CONSTRUCTOR
  303. ID_INLINE void Construct();
  304. static const uint32 STATIC_BIT = 31;
  305. static const uint32 STATIC_MASK = 1u << STATIC_BIT;
  306. static const uint32 ALLOCED_MASK = STATIC_MASK - 1;
  307. ID_INLINE int GetAlloced() const { return allocedAndFlag & ALLOCED_MASK; }
  308. ID_INLINE void SetAlloced( const int a ) { allocedAndFlag = ( allocedAndFlag & STATIC_MASK ) | ( a & ALLOCED_MASK); }
  309. ID_INLINE bool IsStatic() const { return ( allocedAndFlag & STATIC_MASK ) != 0; }
  310. ID_INLINE void SetStatic( const bool isStatic ) { allocedAndFlag = ( allocedAndFlag & ALLOCED_MASK ) | ( isStatic << STATIC_BIT ); }
  311. public:
  312. static const int INVALID_POSITION = -1;
  313. };
  314. char * va( VERIFY_FORMAT_STRING const char *fmt, ... );
  315. /*
  316. ================================================================================================
  317. Sort routines for sorting idList<idStr>
  318. ================================================================================================
  319. */
  320. class idSort_Str : public idSort_Quick< idStr, idSort_Str > {
  321. public:
  322. int Compare( const idStr & a, const idStr & b ) const { return a.Icmp( b ); }
  323. };
  324. class idSort_PathStr : public idSort_Quick< idStr, idSort_PathStr > {
  325. public:
  326. int Compare( const idStr & a, const idStr & b ) const { return a.IcmpPath( b ); }
  327. };
  328. /*
  329. ========================
  330. idStr::Construct
  331. ========================
  332. */
  333. ID_INLINE void idStr::Construct() {
  334. SetStatic( false );
  335. SetAlloced( STR_ALLOC_BASE );
  336. data = baseBuffer;
  337. len = 0;
  338. data[ 0 ] = '\0';
  339. #ifdef ID_DEBUG_UNINITIALIZED_MEMORY
  340. memset( baseBuffer, 0, sizeof( baseBuffer ) );
  341. #endif
  342. }
  343. ID_INLINE void idStr::EnsureAlloced( int amount, bool keepold ) {
  344. // static string's can't reallocate
  345. if ( IsStatic() ) {
  346. release_assert( amount <= GetAlloced() );
  347. return;
  348. }
  349. if ( amount > GetAlloced() ) {
  350. ReAllocate( amount, keepold );
  351. }
  352. }
  353. /*
  354. ========================
  355. idStr::SetStaticBuffer
  356. ========================
  357. */
  358. ID_INLINE void idStr::SetStaticBuffer( char * buffer, const int bufferLength ) {
  359. // this should only be called on a freshly constructed idStr
  360. assert( data == baseBuffer );
  361. data = buffer;
  362. len = 0;
  363. SetAlloced( bufferLength );
  364. SetStatic( true );
  365. }
  366. ID_INLINE idStr::idStr() {
  367. Construct();
  368. }
  369. ID_INLINE idStr::idStr( const idStr &text ) {
  370. Construct();
  371. int l;
  372. l = text.Length();
  373. EnsureAlloced( l + 1 );
  374. strcpy( data, text.data );
  375. len = l;
  376. }
  377. ID_INLINE idStr::idStr( const idStr &text, int start, int end ) {
  378. Construct();
  379. int i;
  380. int l;
  381. if ( end > text.Length() ) {
  382. end = text.Length();
  383. }
  384. if ( start > text.Length() ) {
  385. start = text.Length();
  386. } else if ( start < 0 ) {
  387. start = 0;
  388. }
  389. l = end - start;
  390. if ( l < 0 ) {
  391. l = 0;
  392. }
  393. EnsureAlloced( l + 1 );
  394. for ( i = 0; i < l; i++ ) {
  395. data[ i ] = text[ start + i ];
  396. }
  397. data[ l ] = '\0';
  398. len = l;
  399. }
  400. ID_INLINE idStr::idStr( const char *text ) {
  401. Construct();
  402. int l;
  403. if ( text ) {
  404. l = strlen( text );
  405. EnsureAlloced( l + 1 );
  406. strcpy( data, text );
  407. len = l;
  408. }
  409. }
  410. ID_INLINE idStr::idStr( const char *text, int start, int end ) {
  411. Construct();
  412. int i;
  413. int l = strlen( text );
  414. if ( end > l ) {
  415. end = l;
  416. }
  417. if ( start > l ) {
  418. start = l;
  419. } else if ( start < 0 ) {
  420. start = 0;
  421. }
  422. l = end - start;
  423. if ( l < 0 ) {
  424. l = 0;
  425. }
  426. EnsureAlloced( l + 1 );
  427. for ( i = 0; i < l; i++ ) {
  428. data[ i ] = text[ start + i ];
  429. }
  430. data[ l ] = '\0';
  431. len = l;
  432. }
  433. ID_INLINE idStr::idStr( const bool b ) {
  434. Construct();
  435. EnsureAlloced( 2 );
  436. data[ 0 ] = b ? '1' : '0';
  437. data[ 1 ] = '\0';
  438. len = 1;
  439. }
  440. ID_INLINE idStr::idStr( const char c ) {
  441. Construct();
  442. EnsureAlloced( 2 );
  443. data[ 0 ] = c;
  444. data[ 1 ] = '\0';
  445. len = 1;
  446. }
  447. ID_INLINE idStr::idStr( const int i ) {
  448. Construct();
  449. char text[ 64 ];
  450. int l;
  451. l = sprintf( text, "%d", i );
  452. EnsureAlloced( l + 1 );
  453. strcpy( data, text );
  454. len = l;
  455. }
  456. ID_INLINE idStr::idStr( const unsigned u ) {
  457. Construct();
  458. char text[ 64 ];
  459. int l;
  460. l = sprintf( text, "%u", u );
  461. EnsureAlloced( l + 1 );
  462. strcpy( data, text );
  463. len = l;
  464. }
  465. ID_INLINE idStr::idStr( const float f ) {
  466. Construct();
  467. char text[ 64 ];
  468. int l;
  469. l = idStr::snPrintf( text, sizeof( text ), "%f", f );
  470. while( l > 0 && text[l-1] == '0' ) text[--l] = '\0';
  471. while( l > 0 && text[l-1] == '.' ) text[--l] = '\0';
  472. EnsureAlloced( l + 1 );
  473. strcpy( data, text );
  474. len = l;
  475. }
  476. ID_INLINE idStr::~idStr() {
  477. FreeData();
  478. }
  479. ID_INLINE size_t idStr::Size() const {
  480. return sizeof( *this ) + Allocated();
  481. }
  482. ID_INLINE const char *idStr::c_str() const {
  483. return data;
  484. }
  485. ID_INLINE idStr::operator const char *() {
  486. return c_str();
  487. }
  488. ID_INLINE idStr::operator const char *() const {
  489. return c_str();
  490. }
  491. ID_INLINE char idStr::operator[]( int index ) const {
  492. assert( ( index >= 0 ) && ( index <= len ) );
  493. return data[ index ];
  494. }
  495. ID_INLINE char &idStr::operator[]( int index ) {
  496. assert( ( index >= 0 ) && ( index <= len ) );
  497. return data[ index ];
  498. }
  499. ID_INLINE void idStr::operator=( const idStr &text ) {
  500. int l;
  501. l = text.Length();
  502. EnsureAlloced( l + 1, false );
  503. memcpy( data, text.data, l );
  504. data[l] = '\0';
  505. len = l;
  506. }
  507. ID_INLINE idStr operator+( const idStr &a, const idStr &b ) {
  508. idStr result( a );
  509. result.Append( b );
  510. return result;
  511. }
  512. ID_INLINE idStr operator+( const idStr &a, const char *b ) {
  513. idStr result( a );
  514. result.Append( b );
  515. return result;
  516. }
  517. ID_INLINE idStr operator+( const char *a, const idStr &b ) {
  518. idStr result( a );
  519. result.Append( b );
  520. return result;
  521. }
  522. ID_INLINE idStr operator+( const idStr &a, const bool b ) {
  523. idStr result( a );
  524. result.Append( b ? "true" : "false" );
  525. return result;
  526. }
  527. ID_INLINE idStr operator+( const idStr &a, const char b ) {
  528. idStr result( a );
  529. result.Append( b );
  530. return result;
  531. }
  532. ID_INLINE idStr operator+( const idStr &a, const float b ) {
  533. char text[ 64 ];
  534. idStr result( a );
  535. sprintf( text, "%f", b );
  536. result.Append( text );
  537. return result;
  538. }
  539. ID_INLINE idStr operator+( const idStr &a, const int b ) {
  540. char text[ 64 ];
  541. idStr result( a );
  542. sprintf( text, "%d", b );
  543. result.Append( text );
  544. return result;
  545. }
  546. ID_INLINE idStr operator+( const idStr &a, const unsigned b ) {
  547. char text[ 64 ];
  548. idStr result( a );
  549. sprintf( text, "%u", b );
  550. result.Append( text );
  551. return result;
  552. }
  553. ID_INLINE idStr &idStr::operator+=( const float a ) {
  554. char text[ 64 ];
  555. sprintf( text, "%f", a );
  556. Append( text );
  557. return *this;
  558. }
  559. ID_INLINE idStr &idStr::operator+=( const int a ) {
  560. char text[ 64 ];
  561. sprintf( text, "%d", a );
  562. Append( text );
  563. return *this;
  564. }
  565. ID_INLINE idStr &idStr::operator+=( const unsigned a ) {
  566. char text[ 64 ];
  567. sprintf( text, "%u", a );
  568. Append( text );
  569. return *this;
  570. }
  571. ID_INLINE idStr &idStr::operator+=( const idStr &a ) {
  572. Append( a );
  573. return *this;
  574. }
  575. ID_INLINE idStr &idStr::operator+=( const char *a ) {
  576. Append( a );
  577. return *this;
  578. }
  579. ID_INLINE idStr &idStr::operator+=( const char a ) {
  580. Append( a );
  581. return *this;
  582. }
  583. ID_INLINE idStr &idStr::operator+=( const bool a ) {
  584. Append( a ? "true" : "false" );
  585. return *this;
  586. }
  587. ID_INLINE bool operator==( const idStr &a, const idStr &b ) {
  588. return ( !idStr::Cmp( a.data, b.data ) );
  589. }
  590. ID_INLINE bool operator==( const idStr &a, const char *b ) {
  591. assert( b );
  592. return ( !idStr::Cmp( a.data, b ) );
  593. }
  594. ID_INLINE bool operator==( const char *a, const idStr &b ) {
  595. assert( a );
  596. return ( !idStr::Cmp( a, b.data ) );
  597. }
  598. ID_INLINE bool operator!=( const idStr &a, const idStr &b ) {
  599. return !( a == b );
  600. }
  601. ID_INLINE bool operator!=( const idStr &a, const char *b ) {
  602. return !( a == b );
  603. }
  604. ID_INLINE bool operator!=( const char *a, const idStr &b ) {
  605. return !( a == b );
  606. }
  607. ID_INLINE int idStr::Cmp( const char *text ) const {
  608. assert( text );
  609. return idStr::Cmp( data, text );
  610. }
  611. ID_INLINE int idStr::Cmpn( const char *text, int n ) const {
  612. assert( text );
  613. return idStr::Cmpn( data, text, n );
  614. }
  615. ID_INLINE int idStr::CmpPrefix( const char *text ) const {
  616. assert( text );
  617. return idStr::Cmpn( data, text, strlen( text ) );
  618. }
  619. ID_INLINE int idStr::Icmp( const char *text ) const {
  620. assert( text );
  621. return idStr::Icmp( data, text );
  622. }
  623. ID_INLINE int idStr::Icmpn( const char *text, int n ) const {
  624. assert( text );
  625. return idStr::Icmpn( data, text, n );
  626. }
  627. ID_INLINE int idStr::IcmpPrefix( const char *text ) const {
  628. assert( text );
  629. return idStr::Icmpn( data, text, strlen( text ) );
  630. }
  631. ID_INLINE int idStr::IcmpNoColor( const char *text ) const {
  632. assert( text );
  633. return idStr::IcmpNoColor( data, text );
  634. }
  635. ID_INLINE int idStr::IcmpPath( const char *text ) const {
  636. assert( text );
  637. return idStr::IcmpPath( data, text );
  638. }
  639. ID_INLINE int idStr::IcmpnPath( const char *text, int n ) const {
  640. assert( text );
  641. return idStr::IcmpnPath( data, text, n );
  642. }
  643. ID_INLINE int idStr::IcmpPrefixPath( const char *text ) const {
  644. assert( text );
  645. return idStr::IcmpnPath( data, text, strlen( text ) );
  646. }
  647. ID_INLINE int idStr::Length() const {
  648. return len;
  649. }
  650. ID_INLINE int idStr::Allocated() const {
  651. if ( data != baseBuffer ) {
  652. return GetAlloced();
  653. } else {
  654. return 0;
  655. }
  656. }
  657. ID_INLINE void idStr::Empty() {
  658. EnsureAlloced( 1 );
  659. data[ 0 ] = '\0';
  660. len = 0;
  661. }
  662. ID_INLINE bool idStr::IsEmpty() const {
  663. return ( idStr::Cmp( data, "" ) == 0 );
  664. }
  665. ID_INLINE void idStr::Clear() {
  666. if ( IsStatic() ) {
  667. len = 0;
  668. data[ 0 ] = '\0';
  669. return;
  670. }
  671. FreeData();
  672. Construct();
  673. }
  674. ID_INLINE void idStr::Append( const char a ) {
  675. EnsureAlloced( len + 2 );
  676. data[ len ] = a;
  677. len++;
  678. data[ len ] = '\0';
  679. }
  680. ID_INLINE void idStr::Append( const idStr &text ) {
  681. int newLen;
  682. int i;
  683. newLen = len + text.Length();
  684. EnsureAlloced( newLen + 1 );
  685. for ( i = 0; i < text.len; i++ ) {
  686. data[ len + i ] = text[ i ];
  687. }
  688. len = newLen;
  689. data[ len ] = '\0';
  690. }
  691. ID_INLINE void idStr::Append( const char *text ) {
  692. int newLen;
  693. int i;
  694. if ( text ) {
  695. newLen = len + strlen( text );
  696. EnsureAlloced( newLen + 1 );
  697. for ( i = 0; text[ i ]; i++ ) {
  698. data[ len + i ] = text[ i ];
  699. }
  700. len = newLen;
  701. data[ len ] = '\0';
  702. }
  703. }
  704. ID_INLINE void idStr::Append( const char *text, int l ) {
  705. int newLen;
  706. int i;
  707. if ( text && l ) {
  708. newLen = len + l;
  709. EnsureAlloced( newLen + 1 );
  710. for ( i = 0; text[ i ] && i < l; i++ ) {
  711. data[ len + i ] = text[ i ];
  712. }
  713. len = newLen;
  714. data[ len ] = '\0';
  715. }
  716. }
  717. ID_INLINE void idStr::Insert( const char a, int index ) {
  718. int i, l;
  719. if ( index < 0 ) {
  720. index = 0;
  721. } else if ( index > len ) {
  722. index = len;
  723. }
  724. l = 1;
  725. EnsureAlloced( len + l + 1 );
  726. for ( i = len; i >= index; i-- ) {
  727. data[i+l] = data[i];
  728. }
  729. data[index] = a;
  730. len++;
  731. }
  732. ID_INLINE void idStr::Insert( const char *text, int index ) {
  733. int i, l;
  734. if ( index < 0 ) {
  735. index = 0;
  736. } else if ( index > len ) {
  737. index = len;
  738. }
  739. l = strlen( text );
  740. EnsureAlloced( len + l + 1 );
  741. for ( i = len; i >= index; i-- ) {
  742. data[i+l] = data[i];
  743. }
  744. for ( i = 0; i < l; i++ ) {
  745. data[index+i] = text[i];
  746. }
  747. len += l;
  748. }
  749. ID_INLINE void idStr::ToLower() {
  750. for (int i = 0; data[i]; i++ ) {
  751. if ( CharIsUpper( data[i] ) ) {
  752. data[i] += ( 'a' - 'A' );
  753. }
  754. }
  755. }
  756. ID_INLINE void idStr::ToUpper() {
  757. for (int i = 0; data[i]; i++ ) {
  758. if ( CharIsLower( data[i] ) ) {
  759. data[i] -= ( 'a' - 'A' );
  760. }
  761. }
  762. }
  763. ID_INLINE bool idStr::IsNumeric() const {
  764. return idStr::IsNumeric( data );
  765. }
  766. ID_INLINE bool idStr::IsColor() const {
  767. return idStr::IsColor( data );
  768. }
  769. ID_INLINE bool idStr::HasLower() const {
  770. return idStr::HasLower( data );
  771. }
  772. ID_INLINE bool idStr::HasUpper() const {
  773. return idStr::HasUpper( data );
  774. }
  775. ID_INLINE idStr &idStr::RemoveColors() {
  776. idStr::RemoveColors( data );
  777. len = Length( data );
  778. return *this;
  779. }
  780. ID_INLINE int idStr::LengthWithoutColors() const {
  781. return idStr::LengthWithoutColors( data );
  782. }
  783. ID_INLINE void idStr::CapLength( int newlen ) {
  784. if ( len <= newlen ) {
  785. return;
  786. }
  787. data[ newlen ] = 0;
  788. len = newlen;
  789. }
  790. ID_INLINE void idStr::Fill( const char ch, int newlen ) {
  791. EnsureAlloced( newlen + 1 );
  792. len = newlen;
  793. memset( data, ch, len );
  794. data[ len ] = 0;
  795. }
  796. /*
  797. ========================
  798. idStr::UTF8Length
  799. ========================
  800. */
  801. ID_INLINE int idStr::UTF8Length() {
  802. return UTF8Length( (byte *)data );
  803. }
  804. /*
  805. ========================
  806. idStr::UTF8Char
  807. ========================
  808. */
  809. ID_INLINE uint32 idStr::UTF8Char( int & idx ) {
  810. return UTF8Char( (byte *)data, idx );
  811. }
  812. /*
  813. ========================
  814. idStr::ConvertToUTF8
  815. ========================
  816. */
  817. ID_INLINE void idStr::ConvertToUTF8() {
  818. idStr temp( *this );
  819. Clear();
  820. for( int index = 0; index < temp.Length(); ++index ) {
  821. AppendUTF8Char( temp[index] );
  822. }
  823. }
  824. /*
  825. ========================
  826. idStr::UTF8Char
  827. ========================
  828. */
  829. ID_INLINE uint32 idStr::UTF8Char( const char * s, int & idx ) {
  830. return UTF8Char( (byte *)s, idx );
  831. }
  832. /*
  833. ========================
  834. idStr::IsValidUTF8
  835. ========================
  836. */
  837. ID_INLINE bool idStr::IsValidUTF8( const uint8 * s, const int maxLen ) {
  838. utf8Encoding_t encoding;
  839. return IsValidUTF8( s, maxLen, encoding );
  840. }
  841. ID_INLINE int idStr::Find( const char c, int start, int end ) const {
  842. if ( end == -1 ) {
  843. end = len;
  844. }
  845. return idStr::FindChar( data, c, start, end );
  846. }
  847. ID_INLINE int idStr::Find( const char *text, bool casesensitive, int start, int end ) const {
  848. if ( end == -1 ) {
  849. end = len;
  850. }
  851. return idStr::FindText( data, text, casesensitive, start, end );
  852. }
  853. ID_INLINE bool idStr::Filter( const char *filter, bool casesensitive ) const {
  854. return idStr::Filter( filter, data, casesensitive );
  855. }
  856. ID_INLINE const char *idStr::Left( int len, idStr &result ) const {
  857. return Mid( 0, len, result );
  858. }
  859. ID_INLINE const char *idStr::Right( int len, idStr &result ) const {
  860. if ( len >= Length() ) {
  861. result = *this;
  862. return result;
  863. }
  864. return Mid( Length() - len, len, result );
  865. }
  866. ID_INLINE idStr idStr::Left( int len ) const {
  867. return Mid( 0, len );
  868. }
  869. ID_INLINE idStr idStr::Right( int len ) const {
  870. if ( len >= Length() ) {
  871. return *this;
  872. }
  873. return Mid( Length() - len, len );
  874. }
  875. ID_INLINE void idStr::Strip( const char c ) {
  876. StripLeading( c );
  877. StripTrailing( c );
  878. }
  879. ID_INLINE void idStr::Strip( const char *string ) {
  880. StripLeading( string );
  881. StripTrailing( string );
  882. }
  883. ID_INLINE bool idStr::CheckExtension( const char *ext ) {
  884. return idStr::CheckExtension( data, ext );
  885. }
  886. ID_INLINE int idStr::Length( const char *s ) {
  887. int i;
  888. for ( i = 0; s[i]; i++ ) {}
  889. return i;
  890. }
  891. ID_INLINE char *idStr::ToLower( char *s ) {
  892. for ( int i = 0; s[i]; i++ ) {
  893. if ( CharIsUpper( s[i] ) ) {
  894. s[i] += ( 'a' - 'A' );
  895. }
  896. }
  897. return s;
  898. }
  899. ID_INLINE char *idStr::ToUpper( char *s ) {
  900. for ( int i = 0; s[i]; i++ ) {
  901. if ( CharIsLower( s[i] ) ) {
  902. s[i] -= ( 'a' - 'A' );
  903. }
  904. }
  905. return s;
  906. }
  907. ID_INLINE int idStr::Hash( const char *string ) {
  908. int i, hash = 0;
  909. for ( i = 0; *string != '\0'; i++ ) {
  910. hash += ( *string++ ) * ( i + 119 );
  911. }
  912. return hash;
  913. }
  914. ID_INLINE int idStr::Hash( const char *string, int length ) {
  915. int i, hash = 0;
  916. for ( i = 0; i < length; i++ ) {
  917. hash += ( *string++ ) * ( i + 119 );
  918. }
  919. return hash;
  920. }
  921. ID_INLINE int idStr::IHash( const char *string ) {
  922. int i, hash = 0;
  923. for( i = 0; *string != '\0'; i++ ) {
  924. hash += ToLower( *string++ ) * ( i + 119 );
  925. }
  926. return hash;
  927. }
  928. ID_INLINE int idStr::IHash( const char *string, int length ) {
  929. int i, hash = 0;
  930. for ( i = 0; i < length; i++ ) {
  931. hash += ToLower( *string++ ) * ( i + 119 );
  932. }
  933. return hash;
  934. }
  935. ID_INLINE bool idStr::IsColor( const char *s ) {
  936. return ( s[0] == C_COLOR_ESCAPE && s[1] != '\0' && s[1] != ' ' );
  937. }
  938. ID_INLINE char idStr::ToLower( char c ) {
  939. if ( c <= 'Z' && c >= 'A' ) {
  940. return ( c + ( 'a' - 'A' ) );
  941. }
  942. return c;
  943. }
  944. ID_INLINE char idStr::ToUpper( char c ) {
  945. if ( c >= 'a' && c <= 'z' ) {
  946. return ( c - ( 'a' - 'A' ) );
  947. }
  948. return c;
  949. }
  950. ID_INLINE bool idStr::CharIsPrintable( int c ) {
  951. // test for regular ascii and western European high-ascii chars
  952. return ( c >= 0x20 && c <= 0x7E ) || ( c >= 0xA1 && c <= 0xFF );
  953. }
  954. ID_INLINE bool idStr::CharIsLower( int c ) {
  955. // test for regular ascii and western European high-ascii chars
  956. return ( c >= 'a' && c <= 'z' ) || ( c >= 0xE0 && c <= 0xFF );
  957. }
  958. ID_INLINE bool idStr::CharIsUpper( int c ) {
  959. // test for regular ascii and western European high-ascii chars
  960. return ( c <= 'Z' && c >= 'A' ) || ( c >= 0xC0 && c <= 0xDF );
  961. }
  962. ID_INLINE bool idStr::CharIsAlpha( int c ) {
  963. // test for regular ascii and western European high-ascii chars
  964. return ( ( c >= 'a' && c <= 'z' ) || ( c >= 'A' && c <= 'Z' ) ||
  965. ( c >= 0xC0 && c <= 0xFF ) );
  966. }
  967. ID_INLINE bool idStr::CharIsNumeric( int c ) {
  968. return ( c <= '9' && c >= '0' );
  969. }
  970. ID_INLINE bool idStr::CharIsNewLine( char c ) {
  971. return ( c == '\n' || c == '\r' || c == '\v' );
  972. }
  973. ID_INLINE bool idStr::CharIsTab( char c ) {
  974. return ( c == '\t' );
  975. }
  976. ID_INLINE int idStr::ColorIndex( int c ) {
  977. return ( c & 15 );
  978. }
  979. ID_INLINE int idStr::DynamicMemoryUsed() const {
  980. return ( data == baseBuffer ) ? 0 : GetAlloced();
  981. }
  982. /*
  983. ========================
  984. idStr::CopyRange
  985. ========================
  986. */
  987. ID_INLINE void idStr::CopyRange( const char * text, int start, int end ) {
  988. int l = end - start;
  989. if ( l < 0 ) {
  990. l = 0;
  991. }
  992. EnsureAlloced( l + 1 );
  993. for ( int i = 0; i < l; i++ ) {
  994. data[ i ] = text[ start + i ];
  995. }
  996. data[ l ] = '\0';
  997. len = l;
  998. }
  999. #endif /* !__STR_H__ */