doom3-gpl
Doom 3 GPL source release
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Str.cpp
Go to the documentation of this file.
1 /*
2 ===========================================================================
3 
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
6 
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
8 
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13 
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
21 
22 In addition, the Doom 3 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 Source Code. If not, please request a copy in writing from id Software at the address below.
23 
24 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.
25 
26 ===========================================================================
27 */
28 
29 #include "precompiled.h"
30 #pragma hdrstop
31 
32 #if !defined( ID_REDIRECT_NEWDELETE ) && !defined( MACOS_X )
33  #define USE_STRING_DATA_ALLOCATOR
34 #endif
35 
36 #ifdef USE_STRING_DATA_ALLOCATOR
37 static idDynamicBlockAlloc<char, 1<<18, 128> stringDataAllocator;
38 #endif
39 
41 {
42  idVec4(0.0f, 0.0f, 0.0f, 1.0f),
43  idVec4(1.0f, 0.0f, 0.0f, 1.0f), // S_COLOR_RED
44  idVec4(0.0f, 1.0f, 0.0f, 1.0f), // S_COLOR_GREEN
45  idVec4(1.0f, 1.0f, 0.0f, 1.0f), // S_COLOR_YELLOW
46  idVec4(0.0f, 0.0f, 1.0f, 1.0f), // S_COLOR_BLUE
47  idVec4(0.0f, 1.0f, 1.0f, 1.0f), // S_COLOR_CYAN
48  idVec4(1.0f, 0.0f, 1.0f, 1.0f), // S_COLOR_MAGENTA
49  idVec4(1.0f, 1.0f, 1.0f, 1.0f), // S_COLOR_WHITE
50  idVec4(0.5f, 0.5f, 0.5f, 1.0f), // S_COLOR_GRAY
51  idVec4(0.0f, 0.0f, 0.0f, 1.0f), // S_COLOR_BLACK
52  idVec4(0.0f, 0.0f, 0.0f, 1.0f),
53  idVec4(0.0f, 0.0f, 0.0f, 1.0f),
54  idVec4(0.0f, 0.0f, 0.0f, 1.0f),
55  idVec4(0.0f, 0.0f, 0.0f, 1.0f),
56  idVec4(0.0f, 0.0f, 0.0f, 1.0f),
57  idVec4(0.0f, 0.0f, 0.0f, 1.0f),
58 };
59 
60 const char *units[2][4] =
61 {
62  { "B", "KB", "MB", "GB" },
63  { "B/s", "KB/s", "MB/s", "GB/s" }
64 };
65 
66 /*
67 ============
68 idStr::ColorForIndex
69 ============
70 */
72  return g_color_table[ i & 15 ];
73 }
74 
75 /*
76 ============
77 idStr::ReAllocate
78 ============
79 */
80 void idStr::ReAllocate( int amount, bool keepold ) {
81  char *newbuffer;
82  int newsize;
83  int mod;
84 
85  //assert( data );
86  assert( amount > 0 );
87 
88  mod = amount % STR_ALLOC_GRAN;
89  if ( !mod ) {
90  newsize = amount;
91  }
92  else {
93  newsize = amount + STR_ALLOC_GRAN - mod;
94  }
95  alloced = newsize;
96 
97 #ifdef USE_STRING_DATA_ALLOCATOR
98  newbuffer = stringDataAllocator.Alloc( alloced );
99 #else
100  newbuffer = new char[ alloced ];
101 #endif
102  if ( keepold && data ) {
103  data[ len ] = '\0';
104  strcpy( newbuffer, data );
105  }
106 
107  if ( data && data != baseBuffer ) {
108 #ifdef USE_STRING_DATA_ALLOCATOR
109  stringDataAllocator.Free( data );
110 #else
111  delete [] data;
112 #endif
113  }
114 
115  data = newbuffer;
116 }
117 
118 /*
119 ============
120 idStr::FreeData
121 ============
122 */
123 void idStr::FreeData( void ) {
124  if ( data && data != baseBuffer ) {
125 #ifdef USE_STRING_DATA_ALLOCATOR
126  stringDataAllocator.Free( data );
127 #else
128  delete[] data;
129 #endif
130  data = baseBuffer;
131  }
132 }
133 
134 /*
135 ============
136 idStr::operator=
137 ============
138 */
139 void idStr::operator=( const char *text ) {
140  int l;
141  int diff;
142  int i;
143 
144  if ( !text ) {
145  // safe behaviour if NULL
146  EnsureAlloced( 1, false );
147  data[ 0 ] = '\0';
148  len = 0;
149  return;
150  }
151 
152  if ( text == data ) {
153  return; // copying same thing
154  }
155 
156  // check if we're aliasing
157  if ( text >= data && text <= data + len ) {
158  diff = text - data;
159 
160  assert( strlen( text ) < (unsigned)len );
161 
162  for ( i = 0; text[ i ]; i++ ) {
163  data[ i ] = text[ i ];
164  }
165 
166  data[ i ] = '\0';
167 
168  len -= diff;
169 
170  return;
171  }
172 
173  l = strlen( text );
174  EnsureAlloced( l + 1, false );
175  strcpy( data, text );
176  len = l;
177 }
178 
179 /*
180 ============
181 idStr::FindChar
182 
183 returns -1 if not found otherwise the index of the char
184 ============
185 */
186 int idStr::FindChar( const char *str, const char c, int start, int end ) {
187  int i;
188 
189  if ( end == -1 ) {
190  end = strlen( str ) - 1;
191  }
192  for ( i = start; i <= end; i++ ) {
193  if ( str[i] == c ) {
194  return i;
195  }
196  }
197  return -1;
198 }
199 
200 /*
201 ============
202 idStr::FindText
203 
204 returns -1 if not found otherwise the index of the text
205 ============
206 */
207 int idStr::FindText( const char *str, const char *text, bool casesensitive, int start, int end ) {
208  int l, i, j;
209 
210  if ( end == -1 ) {
211  end = strlen( str );
212  }
213  l = end - strlen( text );
214  for ( i = start; i <= l; i++ ) {
215  if ( casesensitive ) {
216  for ( j = 0; text[j]; j++ ) {
217  if ( str[i+j] != text[j] ) {
218  break;
219  }
220  }
221  } else {
222  for ( j = 0; text[j]; j++ ) {
223  if ( ::toupper( str[i+j] ) != ::toupper( text[j] ) ) {
224  break;
225  }
226  }
227  }
228  if ( !text[j] ) {
229  return i;
230  }
231  }
232  return -1;
233 }
234 
235 /*
236 ============
237 idStr::Filter
238 
239 Returns true if the string conforms the given filter.
240 Several metacharacter may be used in the filter.
241 
242 * match any string of zero or more characters
243 ? match any single character
244 [abc...] match any of the enclosed characters; a hyphen can
245  be used to specify a range (e.g. a-z, A-Z, 0-9)
246 
247 ============
248 */
249 bool idStr::Filter( const char *filter, const char *name, bool casesensitive ) {
250  idStr buf;
251  int i, found, index;
252 
253  while(*filter) {
254  if (*filter == '*') {
255  filter++;
256  buf.Empty();
257  for (i = 0; *filter; i++) {
258  if ( *filter == '*' || *filter == '?' || (*filter == '[' && *(filter+1) != '[') ) {
259  break;
260  }
261  buf += *filter;
262  if ( *filter == '[' ) {
263  filter++;
264  }
265  filter++;
266  }
267  if ( buf.Length() ) {
268  index = idStr(name).Find( buf.c_str(), casesensitive );
269  if ( index == -1 ) {
270  return false;
271  }
272  name += index + strlen(buf);
273  }
274  }
275  else if (*filter == '?') {
276  filter++;
277  name++;
278  }
279  else if (*filter == '[') {
280  if ( *(filter+1) == '[' ) {
281  if ( *name != '[' ) {
282  return false;
283  }
284  filter += 2;
285  name++;
286  }
287  else {
288  filter++;
289  found = false;
290  while(*filter && !found) {
291  if (*filter == ']' && *(filter+1) != ']') {
292  break;
293  }
294  if (*(filter+1) == '-' && *(filter+2) && (*(filter+2) != ']' || *(filter+3) == ']')) {
295  if (casesensitive) {
296  if (*name >= *filter && *name <= *(filter+2)) {
297  found = true;
298  }
299  }
300  else {
301  if ( ::toupper(*name) >= ::toupper(*filter) && ::toupper(*name) <= ::toupper(*(filter+2)) ) {
302  found = true;
303  }
304  }
305  filter += 3;
306  }
307  else {
308  if (casesensitive) {
309  if (*filter == *name) {
310  found = true;
311  }
312  }
313  else {
314  if ( ::toupper(*filter) == ::toupper(*name) ) {
315  found = true;
316  }
317  }
318  filter++;
319  }
320  }
321  if (!found) {
322  return false;
323  }
324  while(*filter) {
325  if ( *filter == ']' && *(filter+1) != ']' ) {
326  break;
327  }
328  filter++;
329  }
330  filter++;
331  name++;
332  }
333  }
334  else {
335  if (casesensitive) {
336  if (*filter != *name) {
337  return false;
338  }
339  }
340  else {
341  if ( ::toupper(*filter) != ::toupper(*name) ) {
342  return false;
343  }
344  }
345  filter++;
346  name++;
347  }
348  }
349  return true;
350 }
351 
352 /*
353 =============
354 idStr::StripMediaName
355 
356  makes the string lower case, replaces backslashes with forward slashes, and removes extension
357 =============
358 */
359 void idStr::StripMediaName( const char *name, idStr &mediaName ) {
360  char c;
361 
362  mediaName.Empty();
363 
364  for ( c = *name; c; c = *(++name) ) {
365  // truncate at an extension
366  if ( c == '.' ) {
367  break;
368  }
369  // convert backslashes to forward slashes
370  if ( c == '\\' ) {
371  mediaName.Append( '/' );
372  } else {
373  mediaName.Append( idStr::ToLower( c ) );
374  }
375  }
376 }
377 
378 /*
379 =============
380 idStr::CheckExtension
381 =============
382 */
383 bool idStr::CheckExtension( const char *name, const char *ext ) {
384  const char *s1 = name + Length( name ) - 1;
385  const char *s2 = ext + Length( ext ) - 1;
386  int c1, c2, d;
387 
388  do {
389  c1 = *s1--;
390  c2 = *s2--;
391 
392  d = c1 - c2;
393  while( d ) {
394  if ( c1 <= 'Z' && c1 >= 'A' ) {
395  d += ('a' - 'A');
396  if ( !d ) {
397  break;
398  }
399  }
400  if ( c2 <= 'Z' && c2 >= 'A' ) {
401  d -= ('a' - 'A');
402  if ( !d ) {
403  break;
404  }
405  }
406  return false;
407  }
408  } while( s1 > name && s2 > ext );
409 
410  return ( s1 >= name );
411 }
412 
413 /*
414 =============
415 idStr::FloatArrayToString
416 =============
417 */
418 const char *idStr::FloatArrayToString( const float *array, const int length, const int precision ) {
419  static int index = 0;
420  static char str[4][16384]; // in case called by nested functions
421  int i, n;
422  char format[16], *s;
423 
424  // use an array of string so that multiple calls won't collide
425  s = str[ index ];
426  index = (index + 1) & 3;
427 
428  idStr::snPrintf( format, sizeof( format ), "%%.%df", precision );
429  n = idStr::snPrintf( s, sizeof( str[0] ), format, array[0] );
430  if ( precision > 0 ) {
431  while( n > 0 && s[n-1] == '0' ) s[--n] = '\0';
432  while( n > 0 && s[n-1] == '.' ) s[--n] = '\0';
433  }
434  idStr::snPrintf( format, sizeof( format ), " %%.%df", precision );
435  for ( i = 1; i < length; i++ ) {
436  n += idStr::snPrintf( s + n, sizeof( str[0] ) - n, format, array[i] );
437  if ( precision > 0 ) {
438  while( n > 0 && s[n-1] == '0' ) s[--n] = '\0';
439  while( n > 0 && s[n-1] == '.' ) s[--n] = '\0';
440  }
441  }
442  return s;
443 }
444 
445 /*
446 ============
447 idStr::Last
448 
449 returns -1 if not found otherwise the index of the char
450 ============
451 */
452 int idStr::Last( const char c ) const {
453  int i;
454 
455  for( i = Length(); i > 0; i-- ) {
456  if ( data[ i - 1 ] == c ) {
457  return i - 1;
458  }
459  }
460 
461  return -1;
462 }
463 
464 /*
465 ============
466 idStr::StripLeading
467 ============
468 */
469 void idStr::StripLeading( const char c ) {
470  while( data[ 0 ] == c ) {
471  memmove( &data[ 0 ], &data[ 1 ], len );
472  len--;
473  }
474 }
475 
476 /*
477 ============
478 idStr::StripLeading
479 ============
480 */
481 void idStr::StripLeading( const char *string ) {
482  int l;
483 
484  l = strlen( string );
485  if ( l > 0 ) {
486  while ( !Cmpn( string, l ) ) {
487  memmove( data, data + l, len - l + 1 );
488  len -= l;
489  }
490  }
491 }
492 
493 /*
494 ============
495 idStr::StripLeadingOnce
496 ============
497 */
498 bool idStr::StripLeadingOnce( const char *string ) {
499  int l;
500 
501  l = strlen( string );
502  if ( ( l > 0 ) && !Cmpn( string, l ) ) {
503  memmove( data, data + l, len - l + 1 );
504  len -= l;
505  return true;
506  }
507  return false;
508 }
509 
510 /*
511 ============
512 idStr::StripTrailing
513 ============
514 */
515 void idStr::StripTrailing( const char c ) {
516  int i;
517 
518  for( i = Length(); i > 0 && data[ i - 1 ] == c; i-- ) {
519  data[ i - 1 ] = '\0';
520  len--;
521  }
522 }
523 
524 /*
525 ============
526 idStr::StripLeading
527 ============
528 */
529 void idStr::StripTrailing( const char *string ) {
530  int l;
531 
532  l = strlen( string );
533  if ( l > 0 ) {
534  while ( ( len >= l ) && !Cmpn( string, data + len - l, l ) ) {
535  len -= l;
536  data[len] = '\0';
537  }
538  }
539 }
540 
541 /*
542 ============
543 idStr::StripTrailingOnce
544 ============
545 */
546 bool idStr::StripTrailingOnce( const char *string ) {
547  int l;
548 
549  l = strlen( string );
550  if ( ( l > 0 ) && ( len >= l ) && !Cmpn( string, data + len - l, l ) ) {
551  len -= l;
552  data[len] = '\0';
553  return true;
554  }
555  return false;
556 }
557 
558 /*
559 ============
560 idStr::Replace
561 ============
562 */
563 void idStr::Replace( const char *old, const char *nw ) {
564  int oldLen, newLen, i, j, count;
565  idStr oldString( data );
566 
567  oldLen = strlen( old );
568  newLen = strlen( nw );
569 
570  // Work out how big the new string will be
571  count = 0;
572  for( i = 0; i < oldString.Length(); i++ ) {
573  if( !idStr::Cmpn( &oldString[i], old, oldLen ) ) {
574  count++;
575  i += oldLen - 1;
576  }
577  }
578 
579  if( count ) {
580  EnsureAlloced( len + ( ( newLen - oldLen ) * count ) + 2, false );
581 
582  // Replace the old data with the new data
583  for( i = 0, j = 0; i < oldString.Length(); i++ ) {
584  if( !idStr::Cmpn( &oldString[i], old, oldLen ) ) {
585  memcpy( data + j, nw, newLen );
586  i += oldLen - 1;
587  j += newLen;
588  } else {
589  data[j] = oldString[i];
590  j++;
591  }
592  }
593  data[j] = 0;
594  len = strlen( data );
595  }
596 }
597 
598 /*
599 ============
600 idStr::Mid
601 ============
602 */
603 const char *idStr::Mid( int start, int len, idStr &result ) const {
604  int i;
605 
606  result.Empty();
607 
608  i = Length();
609  if ( i == 0 || len <= 0 || start >= i ) {
610  return NULL;
611  }
612 
613  if ( start + len >= i ) {
614  len = i - start;
615  }
616 
617  result.Append( &data[ start ], len );
618  return result;
619 }
620 
621 /*
622 ============
623 idStr::Mid
624 ============
625 */
626 idStr idStr::Mid( int start, int len ) const {
627  int i;
628  idStr result;
629 
630  i = Length();
631  if ( i == 0 || len <= 0 || start >= i ) {
632  return result;
633  }
634 
635  if ( start + len >= i ) {
636  len = i - start;
637  }
638 
639  result.Append( &data[ start ], len );
640  return result;
641 }
642 
643 /*
644 ============
645 idStr::StripTrailingWhitespace
646 ============
647 */
649  int i;
650 
651  // cast to unsigned char to prevent stripping off high-ASCII characters
652  for( i = Length(); i > 0 && (unsigned char)(data[ i - 1 ]) <= ' '; i-- ) {
653  data[ i - 1 ] = '\0';
654  len--;
655  }
656 }
657 
658 /*
659 ============
660 idStr::StripQuotes
661 
662 Removes the quotes from the beginning and end of the string
663 ============
664 */
666 {
667  if ( data[0] != '\"' )
668  {
669  return *this;
670  }
671 
672  // Remove the trailing quote first
673  if ( data[len-1] == '\"' )
674  {
675  data[len-1] = '\0';
676  len--;
677  }
678 
679  // Strip the leading quote now
680  len--;
681  memmove( &data[ 0 ], &data[ 1 ], len );
682  data[len] = '\0';
683 
684  return *this;
685 }
686 
687 /*
688 =====================================================================
689 
690  filename methods
691 
692 =====================================================================
693 */
694 
695 /*
696 ============
697 idStr::FileNameHash
698 ============
699 */
700 int idStr::FileNameHash( void ) const {
701  int i;
702  long hash;
703  char letter;
704 
705  hash = 0;
706  i = 0;
707  while( data[i] != '\0' ) {
708  letter = idStr::ToLower( data[i] );
709  if ( letter == '.' ) {
710  break; // don't include extension
711  }
712  if ( letter =='\\' ) {
713  letter = '/';
714  }
715  hash += (long)(letter)*(i+119);
716  i++;
717  }
718  hash &= (FILE_HASH_SIZE-1);
719  return hash;
720 }
721 
722 /*
723 ============
724 idStr::BackSlashesToSlashes
725 ============
726 */
728  int i;
729 
730  for ( i = 0; i < len; i++ ) {
731  if ( data[ i ] == '\\' ) {
732  data[ i ] = '/';
733  }
734  }
735  return *this;
736 }
737 
738 /*
739 ============
740 idStr::SetFileExtension
741 ============
742 */
743 idStr &idStr::SetFileExtension( const char *extension ) {
745  if ( *extension != '.' ) {
746  Append( '.' );
747  }
748  Append( extension );
749  return *this;
750 }
751 
752 /*
753 ============
754 idStr::StripFileExtension
755 ============
756 */
758  int i;
759 
760  for ( i = len-1; i >= 0; i-- ) {
761  if ( data[i] == '.' ) {
762  data[i] = '\0';
763  len = i;
764  break;
765  }
766  }
767  return *this;
768 }
769 
770 /*
771 ============
772 idStr::StripAbsoluteFileExtension
773 ============
774 */
776  int i;
777 
778  for ( i = 0; i < len; i++ ) {
779  if ( data[i] == '.' ) {
780  data[i] = '\0';
781  len = i;
782  break;
783  }
784  }
785 
786  return *this;
787 }
788 
789 /*
790 ==================
791 idStr::DefaultFileExtension
792 ==================
793 */
794 idStr &idStr::DefaultFileExtension( const char *extension ) {
795  int i;
796 
797  // do nothing if the string already has an extension
798  for ( i = len-1; i >= 0; i-- ) {
799  if ( data[i] == '.' ) {
800  return *this;
801  }
802  }
803  if ( *extension != '.' ) {
804  Append( '.' );
805  }
806  Append( extension );
807  return *this;
808 }
809 
810 /*
811 ==================
812 idStr::DefaultPath
813 ==================
814 */
815 idStr &idStr::DefaultPath( const char *basepath ) {
816  if ( ( ( *this )[ 0 ] == '/' ) || ( ( *this )[ 0 ] == '\\' ) ) {
817  // absolute path location
818  return *this;
819  }
820 
821  *this = basepath + *this;
822  return *this;
823 }
824 
825 /*
826 ====================
827 idStr::AppendPath
828 ====================
829 */
830 void idStr::AppendPath( const char *text ) {
831  int pos;
832  int i = 0;
833 
834  if ( text && text[i] ) {
835  pos = len;
836  EnsureAlloced( len + strlen( text ) + 2 );
837 
838  if ( pos ) {
839  if ( data[ pos-1 ] != '/' ) {
840  data[ pos++ ] = '/';
841  }
842  }
843  if ( text[i] == '/' ) {
844  i++;
845  }
846 
847  for ( ; text[ i ]; i++ ) {
848  if ( text[ i ] == '\\' ) {
849  data[ pos++ ] = '/';
850  } else {
851  data[ pos++ ] = text[ i ];
852  }
853  }
854  len = pos;
855  data[ pos ] = '\0';
856  }
857 }
858 
859 /*
860 ==================
861 idStr::StripFilename
862 ==================
863 */
865  int pos;
866 
867  pos = Length() - 1;
868  while( ( pos > 0 ) && ( ( *this )[ pos ] != '/' ) && ( ( *this )[ pos ] != '\\' ) ) {
869  pos--;
870  }
871 
872  if ( pos < 0 ) {
873  pos = 0;
874  }
875 
876  CapLength( pos );
877  return *this;
878 }
879 
880 /*
881 ==================
882 idStr::StripPath
883 ==================
884 */
886  int pos;
887 
888  pos = Length();
889  while( ( pos > 0 ) && ( ( *this )[ pos - 1 ] != '/' ) && ( ( *this )[ pos - 1 ] != '\\' ) ) {
890  pos--;
891  }
892 
893  *this = Right( Length() - pos );
894  return *this;
895 }
896 
897 /*
898 ====================
899 idStr::ExtractFilePath
900 ====================
901 */
902 void idStr::ExtractFilePath( idStr &dest ) const {
903  int pos;
904 
905  //
906  // back up until a \ or the start
907  //
908  pos = Length();
909  while( ( pos > 0 ) && ( ( *this )[ pos - 1 ] != '/' ) && ( ( *this )[ pos - 1 ] != '\\' ) ) {
910  pos--;
911  }
912 
913  Left( pos, dest );
914 }
915 
916 /*
917 ====================
918 idStr::ExtractFileName
919 ====================
920 */
921 void idStr::ExtractFileName( idStr &dest ) const {
922  int pos;
923 
924  //
925  // back up until a \ or the start
926  //
927  pos = Length() - 1;
928  while( ( pos > 0 ) && ( ( *this )[ pos - 1 ] != '/' ) && ( ( *this )[ pos - 1 ] != '\\' ) ) {
929  pos--;
930  }
931 
932  Right( Length() - pos, dest );
933 }
934 
935 /*
936 ====================
937 idStr::ExtractFileBase
938 ====================
939 */
940 void idStr::ExtractFileBase( idStr &dest ) const {
941  int pos;
942  int start;
943 
944  //
945  // back up until a \ or the start
946  //
947  pos = Length() - 1;
948  while( ( pos > 0 ) && ( ( *this )[ pos - 1 ] != '/' ) && ( ( *this )[ pos - 1 ] != '\\' ) ) {
949  pos--;
950  }
951 
952  start = pos;
953  while( ( pos < Length() ) && ( ( *this )[ pos ] != '.' ) ) {
954  pos++;
955  }
956 
957  Mid( start, pos - start, dest );
958 }
959 
960 /*
961 ====================
962 idStr::ExtractFileExtension
963 ====================
964 */
965 void idStr::ExtractFileExtension( idStr &dest ) const {
966  int pos;
967 
968  //
969  // back up until a . or the start
970  //
971  pos = Length() - 1;
972  while( ( pos > 0 ) && ( ( *this )[ pos - 1 ] != '.' ) ) {
973  pos--;
974  }
975 
976  if ( !pos ) {
977  // no extension
978  dest.Empty();
979  } else {
980  Right( Length() - pos, dest );
981  }
982 }
983 
984 
985 /*
986 =====================================================================
987 
988  char * methods to replace library functions
989 
990 =====================================================================
991 */
992 
993 /*
994 ============
995 idStr::IsNumeric
996 
997 Checks a string to see if it contains only numerical values.
998 ============
999 */
1000 bool idStr::IsNumeric( const char *s ) {
1001  int i;
1002  bool dot;
1003 
1004  if ( *s == '-' ) {
1005  s++;
1006  }
1007 
1008  dot = false;
1009  for ( i = 0; s[i]; i++ ) {
1010  if ( !isdigit( s[i] ) ) {
1011  if ( ( s[ i ] == '.' ) && !dot ) {
1012  dot = true;
1013  continue;
1014  }
1015  return false;
1016  }
1017  }
1018 
1019  return true;
1020 }
1021 
1022 /*
1023 ============
1024 idStr::HasLower
1025 
1026 Checks if a string has any lowercase chars
1027 ============
1028 */
1029 bool idStr::HasLower( const char *s ) {
1030  if ( !s ) {
1031  return false;
1032  }
1033 
1034  while ( *s ) {
1035  if ( CharIsLower( *s ) ) {
1036  return true;
1037  }
1038  s++;
1039  }
1040 
1041  return false;
1042 }
1043 
1044 /*
1045 ============
1046 idStr::HasUpper
1047 
1048 Checks if a string has any uppercase chars
1049 ============
1050 */
1051 bool idStr::HasUpper( const char *s ) {
1052  if ( !s ) {
1053  return false;
1054  }
1055 
1056  while ( *s ) {
1057  if ( CharIsUpper( *s ) ) {
1058  return true;
1059  }
1060  s++;
1061  }
1062 
1063  return false;
1064 }
1065 
1066 /*
1067 ================
1068 idStr::Cmp
1069 ================
1070 */
1071 int idStr::Cmp( const char *s1, const char *s2 ) {
1072  int c1, c2, d;
1073 
1074  do {
1075  c1 = *s1++;
1076  c2 = *s2++;
1077 
1078  d = c1 - c2;
1079  if ( d ) {
1080  return ( INTSIGNBITNOTSET( d ) << 1 ) - 1;
1081  }
1082  } while( c1 );
1083 
1084  return 0; // strings are equal
1085 }
1086 
1087 /*
1088 ================
1089 idStr::Cmpn
1090 ================
1091 */
1092 int idStr::Cmpn( const char *s1, const char *s2, int n ) {
1093  int c1, c2, d;
1094 
1095  assert( n >= 0 );
1096 
1097  do {
1098  c1 = *s1++;
1099  c2 = *s2++;
1100 
1101  if ( !n-- ) {
1102  return 0; // strings are equal until end point
1103  }
1104 
1105  d = c1 - c2;
1106  if ( d ) {
1107  return ( INTSIGNBITNOTSET( d ) << 1 ) - 1;
1108  }
1109  } while( c1 );
1110 
1111  return 0; // strings are equal
1112 }
1113 
1114 /*
1115 ================
1116 idStr::Icmp
1117 ================
1118 */
1119 int idStr::Icmp( const char *s1, const char *s2 ) {
1120  int c1, c2, d;
1121 
1122  do {
1123  c1 = *s1++;
1124  c2 = *s2++;
1125 
1126  d = c1 - c2;
1127  while( d ) {
1128  if ( c1 <= 'Z' && c1 >= 'A' ) {
1129  d += ('a' - 'A');
1130  if ( !d ) {
1131  break;
1132  }
1133  }
1134  if ( c2 <= 'Z' && c2 >= 'A' ) {
1135  d -= ('a' - 'A');
1136  if ( !d ) {
1137  break;
1138  }
1139  }
1140  return ( INTSIGNBITNOTSET( d ) << 1 ) - 1;
1141  }
1142  } while( c1 );
1143 
1144  return 0; // strings are equal
1145 }
1146 
1147 /*
1148 ================
1149 idStr::Icmpn
1150 ================
1151 */
1152 int idStr::Icmpn( const char *s1, const char *s2, int n ) {
1153  int c1, c2, d;
1154 
1155  assert( n >= 0 );
1156 
1157  do {
1158  c1 = *s1++;
1159  c2 = *s2++;
1160 
1161  if ( !n-- ) {
1162  return 0; // strings are equal until end point
1163  }
1164 
1165  d = c1 - c2;
1166  while( d ) {
1167  if ( c1 <= 'Z' && c1 >= 'A' ) {
1168  d += ('a' - 'A');
1169  if ( !d ) {
1170  break;
1171  }
1172  }
1173  if ( c2 <= 'Z' && c2 >= 'A' ) {
1174  d -= ('a' - 'A');
1175  if ( !d ) {
1176  break;
1177  }
1178  }
1179  return ( INTSIGNBITNOTSET( d ) << 1 ) - 1;
1180  }
1181  } while( c1 );
1182 
1183  return 0; // strings are equal
1184 }
1185 
1186 /*
1187 ================
1188 idStr::Icmp
1189 ================
1190 */
1191 int idStr::IcmpNoColor( const char *s1, const char *s2 ) {
1192  int c1, c2, d;
1193 
1194  do {
1195  while ( idStr::IsColor( s1 ) ) {
1196  s1 += 2;
1197  }
1198  while ( idStr::IsColor( s2 ) ) {
1199  s2 += 2;
1200  }
1201  c1 = *s1++;
1202  c2 = *s2++;
1203 
1204  d = c1 - c2;
1205  while( d ) {
1206  if ( c1 <= 'Z' && c1 >= 'A' ) {
1207  d += ('a' - 'A');
1208  if ( !d ) {
1209  break;
1210  }
1211  }
1212  if ( c2 <= 'Z' && c2 >= 'A' ) {
1213  d -= ('a' - 'A');
1214  if ( !d ) {
1215  break;
1216  }
1217  }
1218  return ( INTSIGNBITNOTSET( d ) << 1 ) - 1;
1219  }
1220  } while( c1 );
1221 
1222  return 0; // strings are equal
1223 }
1224 
1225 /*
1226 ================
1227 idStr::IcmpPath
1228 ================
1229 */
1230 int idStr::IcmpPath( const char *s1, const char *s2 ) {
1231  int c1, c2, d;
1232 
1233 #if 0
1234 //#if !defined( _WIN32 )
1235  idLib::common->Printf( "WARNING: IcmpPath used on a case-sensitive filesystem?\n" );
1236 #endif
1237 
1238  do {
1239  c1 = *s1++;
1240  c2 = *s2++;
1241 
1242  d = c1 - c2;
1243  while( d ) {
1244  if ( c1 <= 'Z' && c1 >= 'A' ) {
1245  d += ('a' - 'A');
1246  if ( !d ) {
1247  break;
1248  }
1249  }
1250  if ( c1 == '\\' ) {
1251  d += ('/' - '\\');
1252  if ( !d ) {
1253  break;
1254  }
1255  }
1256  if ( c2 <= 'Z' && c2 >= 'A' ) {
1257  d -= ('a' - 'A');
1258  if ( !d ) {
1259  break;
1260  }
1261  }
1262  if ( c2 == '\\' ) {
1263  d -= ('/' - '\\');
1264  if ( !d ) {
1265  break;
1266  }
1267  }
1268  // make sure folders come first
1269  while( c1 ) {
1270  if ( c1 == '/' || c1 == '\\' ) {
1271  break;
1272  }
1273  c1 = *s1++;
1274  }
1275  while( c2 ) {
1276  if ( c2 == '/' || c2 == '\\' ) {
1277  break;
1278  }
1279  c2 = *s2++;
1280  }
1281  if ( c1 && !c2 ) {
1282  return -1;
1283  } else if ( !c1 && c2 ) {
1284  return 1;
1285  }
1286  // same folder depth so use the regular compare
1287  return ( INTSIGNBITNOTSET( d ) << 1 ) - 1;
1288  }
1289  } while( c1 );
1290 
1291  return 0;
1292 }
1293 
1294 /*
1295 ================
1296 idStr::IcmpnPath
1297 ================
1298 */
1299 int idStr::IcmpnPath( const char *s1, const char *s2, int n ) {
1300  int c1, c2, d;
1301 
1302 #if 0
1303 //#if !defined( _WIN32 )
1304  idLib::common->Printf( "WARNING: IcmpPath used on a case-sensitive filesystem?\n" );
1305 #endif
1306 
1307  assert( n >= 0 );
1308 
1309  do {
1310  c1 = *s1++;
1311  c2 = *s2++;
1312 
1313  if ( !n-- ) {
1314  return 0; // strings are equal until end point
1315  }
1316 
1317  d = c1 - c2;
1318  while( d ) {
1319  if ( c1 <= 'Z' && c1 >= 'A' ) {
1320  d += ('a' - 'A');
1321  if ( !d ) {
1322  break;
1323  }
1324  }
1325  if ( c1 == '\\' ) {
1326  d += ('/' - '\\');
1327  if ( !d ) {
1328  break;
1329  }
1330  }
1331  if ( c2 <= 'Z' && c2 >= 'A' ) {
1332  d -= ('a' - 'A');
1333  if ( !d ) {
1334  break;
1335  }
1336  }
1337  if ( c2 == '\\' ) {
1338  d -= ('/' - '\\');
1339  if ( !d ) {
1340  break;
1341  }
1342  }
1343  // make sure folders come first
1344  while( c1 ) {
1345  if ( c1 == '/' || c1 == '\\' ) {
1346  break;
1347  }
1348  c1 = *s1++;
1349  }
1350  while( c2 ) {
1351  if ( c2 == '/' || c2 == '\\' ) {
1352  break;
1353  }
1354  c2 = *s2++;
1355  }
1356  if ( c1 && !c2 ) {
1357  return -1;
1358  } else if ( !c1 && c2 ) {
1359  return 1;
1360  }
1361  // same folder depth so use the regular compare
1362  return ( INTSIGNBITNOTSET( d ) << 1 ) - 1;
1363  }
1364  } while( c1 );
1365 
1366  return 0;
1367 }
1368 
1369 /*
1370 =============
1371 idStr::Copynz
1372 
1373 Safe strncpy that ensures a trailing zero
1374 =============
1375 */
1376 void idStr::Copynz( char *dest, const char *src, int destsize ) {
1377  if ( !src ) {
1378  idLib::common->Warning( "idStr::Copynz: NULL src" );
1379  return;
1380  }
1381  if ( destsize < 1 ) {
1382  idLib::common->Warning( "idStr::Copynz: destsize < 1" );
1383  return;
1384  }
1385 
1386  strncpy( dest, src, destsize-1 );
1387  dest[destsize-1] = 0;
1388 }
1389 
1390 /*
1391 ================
1392 idStr::Append
1393 
1394  never goes past bounds or leaves without a terminating 0
1395 ================
1396 */
1397 void idStr::Append( char *dest, int size, const char *src ) {
1398  int l1;
1399 
1400  l1 = strlen( dest );
1401  if ( l1 >= size ) {
1402  idLib::common->Error( "idStr::Append: already overflowed" );
1403  }
1404  idStr::Copynz( dest + l1, src, size - l1 );
1405 }
1406 
1407 /*
1408 ================
1409 idStr::LengthWithoutColors
1410 ================
1411 */
1412 int idStr::LengthWithoutColors( const char *s ) {
1413  int len;
1414  const char *p;
1415 
1416  if ( !s ) {
1417  return 0;
1418  }
1419 
1420  len = 0;
1421  p = s;
1422  while( *p ) {
1423  if ( idStr::IsColor( p ) ) {
1424  p += 2;
1425  continue;
1426  }
1427  p++;
1428  len++;
1429  }
1430 
1431  return len;
1432 }
1433 
1434 /*
1435 ================
1436 idStr::RemoveColors
1437 ================
1438 */
1439 char *idStr::RemoveColors( char *string ) {
1440  char *d;
1441  char *s;
1442  int c;
1443 
1444  s = string;
1445  d = string;
1446  while( (c = *s) != 0 ) {
1447  if ( idStr::IsColor( s ) ) {
1448  s++;
1449  }
1450  else {
1451  *d++ = c;
1452  }
1453  s++;
1454  }
1455  *d = '\0';
1456 
1457  return string;
1458 }
1459 
1460 /*
1461 ================
1462 idStr::snPrintf
1463 ================
1464 */
1465 int idStr::snPrintf( char *dest, int size, const char *fmt, ...) {
1466  int len;
1467  va_list argptr;
1468  char buffer[32000]; // big, but small enough to fit in PPC stack
1469 
1470  va_start( argptr, fmt );
1471  len = vsprintf( buffer, fmt, argptr );
1472  va_end( argptr );
1473  if ( len >= sizeof( buffer ) ) {
1474  idLib::common->Error( "idStr::snPrintf: overflowed buffer" );
1475  }
1476  if ( len >= size ) {
1477  idLib::common->Warning( "idStr::snPrintf: overflow of %i in %i\n", len, size );
1478  len = size;
1479  }
1480  idStr::Copynz( dest, buffer, size );
1481  return len;
1482 }
1483 
1484 /*
1485 ============
1486 idStr::vsnPrintf
1487 
1488 vsnprintf portability:
1489 
1490 C99 standard: vsnprintf returns the number of characters (excluding the trailing
1491 '\0') which would have been written to the final string if enough space had been available
1492 snprintf and vsnprintf do not write more than size bytes (including the trailing '\0')
1493 
1494 win32: _vsnprintf returns the number of characters written, not including the terminating null character,
1495 or a negative value if an output error occurs. If the number of characters to write exceeds count, then count
1496 characters are written and -1 is returned and no trailing '\0' is added.
1497 
1498 idStr::vsnPrintf: always appends a trailing '\0', returns number of characters written (not including terminal \0)
1499 or returns -1 on failure or if the buffer would be overflowed.
1500 ============
1501 */
1502 int idStr::vsnPrintf( char *dest, int size, const char *fmt, va_list argptr ) {
1503  int ret;
1504 
1505 #ifdef _WIN32
1506 #undef _vsnprintf
1507  ret = _vsnprintf( dest, size-1, fmt, argptr );
1508 #define _vsnprintf use_idStr_vsnPrintf
1509 #else
1510 #undef vsnprintf
1511  ret = vsnprintf( dest, size, fmt, argptr );
1512 #define vsnprintf use_idStr_vsnPrintf
1513 #endif
1514  dest[size-1] = '\0';
1515  if ( ret < 0 || ret >= size ) {
1516  return -1;
1517  }
1518  return ret;
1519 }
1520 
1521 /*
1522 ============
1523 sprintf
1524 
1525 Sets the value of the string using a printf interface.
1526 ============
1527 */
1528 int sprintf( idStr &string, const char *fmt, ... ) {
1529  int l;
1530  va_list argptr;
1531  char buffer[32000];
1532 
1533  va_start( argptr, fmt );
1534  l = idStr::vsnPrintf( buffer, sizeof(buffer)-1, fmt, argptr );
1535  va_end( argptr );
1536  buffer[sizeof(buffer)-1] = '\0';
1537 
1538  string = buffer;
1539  return l;
1540 }
1541 
1542 /*
1543 ============
1544 vsprintf
1545 
1546 Sets the value of the string using a vprintf interface.
1547 ============
1548 */
1549 int vsprintf( idStr &string, const char *fmt, va_list argptr ) {
1550  int l;
1551  char buffer[32000];
1552 
1553  l = idStr::vsnPrintf( buffer, sizeof(buffer)-1, fmt, argptr );
1554  buffer[sizeof(buffer)-1] = '\0';
1555 
1556  string = buffer;
1557  return l;
1558 }
1559 
1560 /*
1561 ============
1562 va
1563 
1564 does a varargs printf into a temp buffer
1565 NOTE: not thread safe
1566 ============
1567 */
1568 char *va( const char *fmt, ... ) {
1569  va_list argptr;
1570  static int index = 0;
1571  static char string[4][16384]; // in case called by nested functions
1572  char *buf;
1573 
1574  buf = string[index];
1575  index = (index + 1) & 3;
1576 
1577  va_start( argptr, fmt );
1578  vsprintf( buf, fmt, argptr );
1579  va_end( argptr );
1580 
1581  return buf;
1582 }
1583 
1584 
1585 
1586 /*
1587 ============
1588 idStr::BestUnit
1589 ============
1590 */
1591 int idStr::BestUnit( const char *format, float value, Measure_t measure ) {
1592  int unit = 1;
1593  while ( unit <= 3 && ( 1 << ( unit * 10 ) < value ) ) {
1594  unit++;
1595  }
1596  unit--;
1597  value /= 1 << ( unit * 10 );
1598  sprintf( *this, format, value );
1599  *this += " ";
1600  *this += units[ measure ][ unit ];
1601  return unit;
1602 }
1603 
1604 /*
1605 ============
1606 idStr::SetUnit
1607 ============
1608 */
1609 void idStr::SetUnit( const char *format, float value, int unit, Measure_t measure ) {
1610  value /= 1 << ( unit * 10 );
1611  sprintf( *this, format, value );
1612  *this += " ";
1613  *this += units[ measure ][ unit ];
1614 }
1615 
1616 /*
1617 ================
1618 idStr::InitMemory
1619 ================
1620 */
1621 void idStr::InitMemory( void ) {
1622 #ifdef USE_STRING_DATA_ALLOCATOR
1623  stringDataAllocator.Init();
1624 #endif
1625 }
1626 
1627 /*
1628 ================
1629 idStr::ShutdownMemory
1630 ================
1631 */
1633 #ifdef USE_STRING_DATA_ALLOCATOR
1634  stringDataAllocator.Shutdown();
1635 #endif
1636 }
1637 
1638 /*
1639 ================
1640 idStr::PurgeMemory
1641 ================
1642 */
1643 void idStr::PurgeMemory( void ) {
1644 #ifdef USE_STRING_DATA_ALLOCATOR
1645  stringDataAllocator.FreeEmptyBaseBlocks();
1646 #endif
1647 }
1648 
1649 /*
1650 ================
1651 idStr::ShowMemoryUsage_f
1652 ================
1653 */
1655 #ifdef USE_STRING_DATA_ALLOCATOR
1656  idLib::common->Printf( "%6d KB string memory (%d KB free in %d blocks, %d empty base blocks)\n",
1657  stringDataAllocator.GetBaseBlockMemory() >> 10, stringDataAllocator.GetFreeBlockMemory() >> 10,
1658  stringDataAllocator.GetNumFreeBlocks(), stringDataAllocator.GetNumEmptyBaseBlocks() );
1659 #endif
1660 }
1661 
1662 /*
1663 ================
1664 idStr::FormatNumber
1665 ================
1666 */
1668  int gran;
1669  int count;
1670 };
1671 
1672 // elements of list need to decend in size
1674  { 1000000000, 0 },
1675  { 1000000, 0 },
1676  { 1000, 0 }
1677 };
1678 
1679 int numFormatList = sizeof(formatList) / sizeof( formatList[0] );
1680 
1681 
1683  idStr string;
1684  bool hit;
1685 
1686  // reset
1687  for ( int i = 0; i < numFormatList; i++ ) {
1688  formatList_t *li = formatList + i;
1689  li->count = 0;
1690  }
1691 
1692  // main loop
1693  do {
1694  hit = false;
1695 
1696  for ( int i = 0; i < numFormatList; i++ ) {
1697  formatList_t *li = formatList + i;
1698 
1699  if ( number >= li->gran ) {
1700  li->count++;
1701  number -= li->gran;
1702  hit = true;
1703  break;
1704  }
1705  }
1706  } while ( hit );
1707 
1708  // print out
1709  bool found = false;
1710 
1711  for ( int i = 0; i < numFormatList; i++ ) {
1712  formatList_t *li = formatList + i;
1713 
1714  if ( li->count ) {
1715  if ( !found ) {
1716  string += va( "%i,", li->count );
1717  } else {
1718  string += va( "%3.3i,", li->count );
1719  }
1720  found = true;
1721  }
1722  else if ( found ) {
1723  string += va( "%3.3i,", li->count );
1724  }
1725  }
1726 
1727  if ( found ) {
1728  string += va( "%3.3i", number );
1729  }
1730  else {
1731  string += va( "%i", number );
1732  }
1733 
1734  // pad to proper size
1735  int count = 11 - string.Length();
1736 
1737  for ( int i = 0; i < count; i++ ) {
1738  string.Insert( " ", 0 );
1739  }
1740 
1741  return string;
1742 }
1743 
idStr(void)
Definition: Str.h:344
static int snPrintf(char *dest, int size, const char *fmt,...) id_attribute((format(printf
Definition: Str.cpp:1465
GLsizei const GLfloat * value
Definition: glext.h:3614
char * data
Definition: Str.h:317
idStr & SetFileExtension(const char *extension)
Definition: Str.cpp:743
Measure_t
Definition: Str.h:111
static bool CharIsUpper(int c)
Definition: Str.h:1013
void FreeEmptyBaseBlocks(void)
Definition: Heap.h:523
assert(prefInfo.fullscreenBtn)
int Cmp(const char *text) const
Definition: Str.h:652
void ToLower(void)
Definition: Str.h:817
void StripLeading(const char c)
Definition: Str.cpp:469
idStr & DefaultPath(const char *basepath)
Definition: Str.cpp:815
GLenum GLsizei GLenum format
Definition: glext.h:2846
idVec4 g_color_table[16]
Definition: Str.cpp:40
idStr & StripQuotes(void)
Definition: Str.cpp:665
int numFormatList
Definition: Str.cpp:1679
bool Filter(const char *filter, bool casesensitive) const
Definition: Str.h:888
int Length(void) const
Definition: Str.h:702
bool StripTrailingOnce(const char *string)
Definition: Str.cpp:546
void StripTrailingWhitespace(void)
Definition: Str.cpp:648
GLenum GLsizei n
Definition: glext.h:3705
void StripTrailing(const char c)
Definition: Str.cpp:515
int GetFreeBlockMemory(void) const
Definition: Heap.h:411
void ExtractFileBase(idStr &dest) const
Definition: Str.cpp:940
static const char * FloatArrayToString(const float *array, const int length, const int precision)
Definition: Str.cpp:418
static void StripMediaName(const char *name, idStr &mediaName)
Definition: Str.cpp:359
GLenum GLsizei const GLvoid * string
Definition: glext.h:3472
const char * Left(int len, idStr &result) const
Definition: Str.h:892
static void ShowMemoryUsage_f(const idCmdArgs &args)
Definition: Str.cpp:1654
GLdouble s
Definition: glext.h:2935
GLuint src
Definition: glext.h:5390
idStr & DefaultFileExtension(const char *extension)
Definition: Str.cpp:794
GLenum GLsizei len
Definition: glext.h:3472
type * Alloc(const int num)
Definition: Heap.h:570
int i
Definition: process.py:33
int Cmpn(const char *text, int n) const
Definition: Str.h:657
Boolean result
int IcmpNoColor(const char *text) const
Definition: Str.h:682
#define FILE_HASH_SIZE
Definition: FileSystem.cpp:256
static idVec4 & ColorForIndex(int i)
Definition: Str.cpp:71
void Free(type *ptr)
Definition: Heap.h:631
friend int sprintf(idStr &dest, const char *fmt,...)
Definition: Str.cpp:1528
#define vsnprintf
int Icmp(const char *text) const
Definition: Str.h:667
int BestUnit(const char *format, float value, Measure_t measure)
Definition: Str.cpp:1591
idStr & BackSlashesToSlashes(void)
Definition: Str.cpp:727
list l
Definition: prepare.py:17
bool HasLower(void) const
Definition: Str.h:841
void ExtractFilePath(idStr &dest) const
Definition: Str.cpp:902
static bool CharIsLower(int c)
Definition: Str.h:1008
idStr & StripPath(void)
Definition: Str.cpp:885
void ReAllocate(int amount, bool keepold)
Definition: Str.cpp:80
int Icmpn(const char *text, int n) const
Definition: Str.h:672
bool CheckExtension(const char *ext)
Definition: Str.h:925
void ExtractFileName(idStr &dest) const
Definition: Str.cpp:921
GLuint GLuint GLsizei count
Definition: glext.h:2845
void Shutdown(void)
Definition: Heap.h:461
GLuint index
Definition: glext.h:3476
const GLubyte * c
Definition: glext.h:4677
Definition: Vector.h:808
idStr & StripFileExtension(void)
Definition: Str.cpp:757
static idStr FormatNumber(int number)
Definition: Str.cpp:1682
void Empty(void)
Definition: Str.h:714
int count
Definition: Str.cpp:1669
GLuint GLuint end
Definition: glext.h:2845
int GetNumEmptyBaseBlocks(void) const
Definition: Heap.h:556
#define INTSIGNBITNOTSET(i)
Definition: Math.h:72
static void InitMemory(void)
Definition: Str.cpp:1621
#define NULL
Definition: Lib.h:88
void EnsureAlloced(int amount, bool keepold=true)
Definition: Str.h:328
GLsizei GLsizei GLenum GLenum const GLvoid * data
Definition: glext.h:2853
GLuint buffer
Definition: glext.h:3108
#define _vsnprintf
Definition: Str.h:73
void CapLength(int)
Definition: Str.h:859
idStr & StripAbsoluteFileExtension(void)
Definition: Str.cpp:775
static void Copynz(char *dest, const char *src, int destsize)
Definition: Str.cpp:1376
static int FindText(const char *str, const char *text, bool casesensitive=true, int start=0, int end=-1)
Definition: Str.cpp:207
const int STR_ALLOC_GRAN
Definition: Str.h:109
const char * Right(int len, idStr &result) const
Definition: Str.h:896
idStr & RemoveColors(void)
Definition: Str.h:849
int GetBaseBlockMemory(void) const
Definition: Heap.h:407
virtual void Printf(const char *fmt,...) id_attribute((format(printf
void AppendPath(const char *text)
Definition: Str.cpp:830
friend int vsprintf(idStr &dest, const char *fmt, va_list ap)
Definition: Str.cpp:1549
void Init(void)
Definition: Heap.h:456
int FileNameHash(void) const
Definition: Str.cpp:700
int IcmpnPath(const char *text, int n) const
Definition: Str.h:692
bool IsNumeric(void) const
Definition: Str.h:833
static int FindChar(const char *str, const char c, int start=0, int end=-1)
Definition: Str.cpp:186
void operator=(const idStr &text)
Definition: Str.h:509
static void ShutdownMemory(void)
Definition: Str.cpp:1632
const char * Mid(int start, int len, idStr &result) const
Definition: Str.cpp:603
const char * units[2][4]
Definition: Str.cpp:60
int len
Definition: Str.h:316
int alloced
Definition: Str.h:318
static int static int vsnPrintf(char *dest, int size, const char *fmt, va_list argptr)
Definition: Str.cpp:1502
GLenum filter
Definition: glext.h:3704
tuple f
Definition: idal.py:89
int GetNumFreeBlocks(void) const
Definition: Heap.h:410
void Append(const char a)
Definition: Str.h:729
int Last(const char c) const
Definition: Str.cpp:452
const GLcharARB * name
Definition: glext.h:3629
GLsizeiptr size
Definition: glext.h:3112
Definition: Str.h:116
GLsizei const GLcharARB const GLint * length
Definition: glext.h:3599
int vsprintf(idStr &string, const char *fmt, va_list argptr)
Definition: Str.cpp:1549
const char * c_str(void) const
Definition: Str.h:487
void SetUnit(const char *format, float value, int unit, Measure_t measure)
Definition: Str.cpp:1609
int gran
Definition: Str.cpp:1668
GLint j
Definition: qgl.h:264
float dot(float a[], float b[])
Definition: Model_lwo.cpp:3883
char * va(const char *fmt,...)
Definition: Str.cpp:1568
void ExtractFileExtension(idStr &dest) const
Definition: Str.cpp:965
void FreeData(void)
Definition: Str.cpp:123
char baseBuffer[STR_ALLOC_BASE]
Definition: Str.h:319
bool HasUpper(void) const
Definition: Str.h:845
virtual void Error(const char *fmt,...) id_attribute((format(printf
void Replace(const char *old, const char *nw)
Definition: Str.cpp:563
GLfloat GLfloat p
Definition: glext.h:4674
virtual void virtual void Warning(const char *fmt,...) id_attribute((format(printf
int sprintf(idStr &string, const char *fmt,...)
Definition: Str.cpp:1528
int LengthWithoutColors(void) const
Definition: Str.h:855
idStr & StripFilename(void)
Definition: Str.cpp:864
GLuint start
Definition: glext.h:2845
static void PurgeMemory(void)
Definition: Str.cpp:1643
formatList_t formatList[]
Definition: Str.cpp:1673
bool IsColor(void) const
Definition: Str.h:837
int IcmpPath(const char *text) const
Definition: Str.h:687
bool StripLeadingOnce(const char *string)
Definition: Str.cpp:498
static class idCommon * common
Definition: Lib.h:53