home *** CD-ROM | disk | FTP | other *** search
/ GameStar 2006 March / Gamestar_82_2006-03_dvd.iso / DVDStar / Editace / quake4_sdkv10.exe / source / idlib / Str.h < prev    next >
C/C++ Source or Header  |  2005-11-14  |  29KB  |  1,097 lines

  1.  
  2. #ifndef __STR_H__
  3. #define __STR_H__
  4.  
  5. /*
  6. ===============================================================================
  7.  
  8.     Character string
  9.  
  10. ===============================================================================
  11. */
  12.  
  13. // these library functions should not be used for cross platform compatibility
  14. #define strcmp            idStr::Cmp        // use_idStr_Cmp
  15. #define strncmp            use_idStr_Cmpn
  16. #define StrCmpN            use_idStr_Cmpn
  17. #define strcmpi            use_idStr_Icmp
  18. #define StrCmpI            use_idStr_Icmp
  19. #define stricmp            idStr::Icmp        // use_idStr_Icmp
  20. #define _stricmp        use_idStr_Icmp
  21. #define strcasecmp        use_idStr_Icmp
  22. #define strnicmp        use_idStr_Icmpn
  23. #define _strnicmp        use_idStr_Icmpn
  24. #define _memicmp        use_idStr_Icmpn
  25. #define StrCmpNI        use_idStr_Icmpn
  26. #define snprintf        use_idStr_snPrintf
  27. #define _snprintf        use_idStr_snPrintf
  28. #define vsnprintf        use_idStr_vsnPrintf
  29. #define _vsnprintf        use_idStr_vsnPrintf
  30.  
  31. #ifdef _XENON
  32. class __declspec(align(16)) idVec4;
  33. #else
  34. class idVec4;
  35. #endif
  36.  
  37. #ifndef FILE_HASH_SIZE
  38. #define FILE_HASH_SIZE        1024
  39. #endif
  40.  
  41. // color escape character
  42. const int C_COLOR_ESCAPE            = '^';
  43. const int C_COLOR_DEFAULT            = '0';
  44. const int C_COLOR_RED                = '1';
  45. const int C_COLOR_GREEN                = '2';
  46. const int C_COLOR_YELLOW            = '3';
  47. const int C_COLOR_BLUE                = '4';
  48. const int C_COLOR_CYAN                = '5';
  49. const int C_COLOR_MAGENTA            = '6';
  50. const int C_COLOR_WHITE                = '7';
  51. const int C_COLOR_GRAY                = '8';
  52. const int C_COLOR_BLACK                = '9';
  53. // RAVEN BEGIN
  54. // bdube: added
  55. const int C_COLOR_CONSOLE            = ':';
  56. // RAVEN END
  57.  
  58. // color escape string
  59. #define S_COLOR_DEFAULT                "^0"
  60. #define S_COLOR_RED                    "^1"
  61. #define S_COLOR_GREEN                "^2"
  62. #define S_COLOR_YELLOW                "^3"
  63. #define S_COLOR_BLUE                "^4"
  64. #define S_COLOR_CYAN                "^5"
  65. #define S_COLOR_MAGENTA                "^6"
  66. #define S_COLOR_WHITE                "^7"
  67. #define S_COLOR_GRAY                "^8"
  68. #define S_COLOR_BLACK                "^9"
  69. // RAVEN BEGIN
  70. // bdube: added
  71. #define S_COLOR_CONSOLE                "^:"
  72. // ddynerman: team colors
  73. #define S_COLOR_MARINE                "^c683"
  74. #define S_COLOR_STROGG                "^c950"
  75. #define S_COLOR_ALERT                "^c920"
  76. // ddynerman: MP icons
  77. #define I_VOICE_ENABLED                "^ivce"
  78. #define I_VOICE_DISABLED            "^ivcd"
  79. #define I_FRIEND_ENABLED            "^ifde"
  80. #define I_FRIEND_DISABLED            "^ifdd"
  81. #define I_FLAG_MARINE                "^iflm"
  82. #define I_FLAG_STROGG                "^ifls"
  83. // shouchard:  server browser stuff
  84. #define I_SERVER_DEDICATED            "^ids0"
  85. #define I_SERVER_DEDICATED_PB        "^idsp"
  86. #define I_SERVER_LOCKED                "^isl0"
  87. #define I_SERVER_FAVORITE            "^isf0"
  88. const int VA_BUF_LEN = 16384;
  89. const int VA_NUM_BUFS = 8;
  90. // RAVEN END
  91.  
  92. // make idStr a multiple of 16 bytes long
  93. // don't make too large to keep memory requirements to a minimum
  94. const int STR_ALLOC_BASE            = 20;
  95. const int STR_ALLOC_GRAN            = 32;
  96.  
  97. typedef enum {
  98.     MEASURE_SIZE = 0,
  99.     MEASURE_BANDWIDTH
  100. } Measure_t;
  101.  
  102. // RAVEN BEGIN
  103. // bdube: string escape codes
  104. #define S_ESCAPE_UNKNOWN            BIT(0)
  105. #define S_ESCAPE_COLOR                BIT(1)
  106. #define S_ESCAPE_COLORINDEX            BIT(2)
  107. #define S_ESCAPE_ICON                BIT(3)
  108. #define S_ESCAPE_COMMAND            BIT(4)
  109. #define    S_ESCAPE_ALL                ( S_ESCAPE_COLOR | S_ESCAPE_COLORINDEX | S_ESCAPE_ICON | S_ESCAPE_COMMAND )
  110. // RAVEN END
  111.  
  112. class idStr {
  113.  
  114. public:
  115.                         idStr( void );
  116.                         idStr( const idStr &text );
  117.                         idStr( const idStr &text, int start, int end );
  118.                         idStr( const char *text );
  119.                         idStr( const char *text, int start, int end );
  120.                         explicit idStr( const bool b );
  121.                         explicit idStr( const char c );
  122.                         explicit idStr( const int i );
  123.                         explicit idStr( const unsigned u );
  124.                         explicit idStr( const float f );
  125.                         ~idStr( void );
  126.  
  127.     size_t                Size( void ) const;
  128.     const char *        c_str( void ) const;
  129.     operator            const char *( void ) const;
  130.     operator            const char *( void );
  131.  
  132.     char                operator[]( int index ) const;
  133.     char &                operator[]( int index );
  134.  
  135.     void                operator=( const idStr &text );
  136.     void                operator=( const char *text );
  137.  
  138.     friend idStr        operator+( const idStr &a, const idStr &b );
  139.     friend idStr        operator+( const idStr &a, const char *b );
  140.     friend idStr        operator+( const char *a, const idStr &b );
  141.  
  142.     friend idStr        operator+( const idStr &a, const float b );
  143.     friend idStr        operator+( const idStr &a, const int b );
  144.     friend idStr        operator+( const idStr &a, const unsigned b );
  145.     friend idStr        operator+( const idStr &a, const bool b );
  146.     friend idStr        operator+( const idStr &a, const char b );
  147.  
  148.     idStr &                operator+=( const idStr &a );
  149.     idStr &                operator+=( const char *a );
  150.     idStr &                operator+=( const float a );
  151.     idStr &                operator+=( const char a );
  152.     idStr &                operator+=( const int a );
  153.     idStr &                operator+=( const unsigned a );
  154.     idStr &                operator+=( const bool a );
  155.  
  156.                         // case sensitive compare
  157.     friend bool            operator==( const idStr &a, const idStr &b );
  158.     friend bool            operator==( const idStr &a, const char *b );
  159.     friend bool            operator==( const char *a, const idStr &b );
  160.  
  161.                         // case sensitive compare
  162.     friend bool            operator!=( const idStr &a, const idStr &b );
  163.     friend bool            operator!=( const idStr &a, const char *b );
  164.     friend bool            operator!=( const char *a, const idStr &b );
  165.  
  166.                         // case sensitive compare
  167.     int                    Cmp( const char *text ) const;
  168.     int                    Cmpn( const char *text, int n ) const;
  169.     int                    CmpPrefix( const char *text ) const;
  170.  
  171.                         // case insensitive compare
  172.     int                    Icmp( const char *text ) const;
  173.     int                    Icmpn( const char *text, int n ) const;
  174.     int                    IcmpPrefix( const char *text ) const;
  175.  
  176.                         // case insensitive compare ignoring color
  177. // RAVEN BEGIN
  178. // bdube: changed to escapes
  179.     int                    IcmpNoEscape( const char *text ) const;
  180. // RAVEN END
  181.  
  182.                         // compares paths and makes sure folders come first
  183.     int                    IcmpPath( const char *text ) const;
  184.     int                    IcmpnPath( const char *text, int n ) const;
  185.     int                    IcmpPrefixPath( const char *text ) const;
  186.  
  187.     int                    Length( void ) const;
  188.     int                    Allocated( void ) const;
  189.     void                Empty( void );
  190.     bool                IsEmpty( void ) const;
  191.     void                Clear( void );
  192.     void                Append( const char a );
  193.     void                Append( const idStr &text );
  194.     void                Append( const char *text );
  195.     void                Append( const char *text, int len );
  196.     void                Insert( const char a, int index );
  197.     void                Insert( const char *text, int index );
  198.     void                ToLower( void );
  199.     void                ToUpper( void );
  200.     bool                IsNumeric( void ) const;
  201.     bool                HasLower( void ) const;
  202.     bool                HasUpper( void ) const;
  203. // RAVEN BEGIN
  204. // bdube: escapes
  205.     int                    IsEscape( int* type = NULL ) const;
  206.     int                    LengthWithoutEscapes ( void ) const;    
  207.     idStr &                RemoveEscapes ( int escapes = S_ESCAPE_ALL );
  208. // RAVEN END
  209.     void                CapLength( int );
  210.     void                Fill( const char ch, int newlen );
  211.     int                    Find( const char c, int start = 0, int end = -1 ) const;
  212.     int                    Find( const char *text, bool casesensitive = true, int start = 0, int end = -1 ) const;
  213.     bool                Filter( const char *filter, bool casesensitive = true ) const;
  214.     int                    Last( const char c ) const;                        // return the index to the last occurance of 'c', returns -1 if not found
  215.     const char *        Left( int len, idStr &result ) const;            // store the leftmost 'len' characters in the result
  216.     const char *        Right( int len, idStr &result ) const;            // store the rightmost 'len' characters in the result
  217.     const char *        Mid( int start, int len, idStr &result ) const;    // store 'len' characters starting at 'start' in result
  218.     idStr                Left( int len ) const;                            // return the leftmost 'len' characters
  219.     idStr                Right( int len ) const;                            // return the rightmost 'len' characters
  220.     idStr                Mid( int start, int len ) const;                // return 'len' characters starting at 'start'
  221.     void                StripLeading( const char c );                    // strip char from front as many times as the char occurs
  222.     void                StripLeading( const char *string );                // strip string from front as many times as the string occurs
  223.     bool                StripLeadingOnce( const char *string );            // strip string from front just once if it occurs
  224.     void                StripTrailing( const char c );                    // strip char from end as many times as the char occurs
  225.     void                StripTrailing( const char *string );            // strip string from end as many times as the string occurs
  226.     bool                StripTrailingOnce( const char *string );        // strip string from end just once if it occurs
  227.     void                Strip( const char c );                            // strip char from front and end as many times as the char occurs
  228.     void                Strip( const char *string );                    // strip string from front and end as many times as the string occurs
  229.     void                StripTrailingWhitespace( void );                // strip trailing white space characters
  230. // RAVEN BEGIN
  231.     void                StripUntil( const char c );                        // strip until this character is reached or there is no string left
  232. // RAVEN END
  233.     idStr &                StripQuotes( void );                            // strip quotes around string
  234. // RAVEN BEGIN
  235. // scork: added replacement-count return
  236.     int                    Replace( const char *old, const char *nw );
  237. // RAVEN END
  238.  
  239.  
  240.     // file name methods
  241.     int                    FileNameHash( void ) const;                        // hash key for the filename (skips extension)
  242.     idStr &                BackSlashesToSlashes( void );                    // convert slashes
  243. // RAVEN BEGIN
  244. // jscott:
  245.     idStr &                SlashesToBackSlashes( void );                    // convert slashes
  246. // nmckenzie: char swapping routine
  247.     bool                HasChar( const char check );
  248.     bool                HasChars( const char *check );
  249.     idStr &                ReplaceChar( const char from, const char to );
  250.     idStr &                ReplaceChars( const char *from, const char to );
  251. // RAVEN END
  252.     idStr &                SetFileExtension( const char *extension );        // set the given file extension
  253.     idStr &                StripFileExtension( void );                        // remove any file extension
  254.     idStr &                StripAbsoluteFileExtension( void );                // remove any file extension looking from front (useful if there are multiple .'s)
  255.     idStr &                DefaultFileExtension( const char *extension );    // if there's no file extension use the default
  256.     idStr &                DefaultPath( const char *basepath );            // if there's no path use the default
  257.     void                AppendPath( const char *text );                    // append a partial path
  258.     idStr &                StripFilename( void );                            // remove the filename from a path
  259.     idStr &                StripPath( void );                                // remove the path from the filename
  260.     void                ExtractFilePath( idStr &dest ) const;            // copy the file path to another string
  261.     void                ExtractFileName( idStr &dest ) const;            // copy the filename to another string
  262.     void                ExtractFileBase( idStr &dest ) const;            // copy the filename minus the extension to another string
  263.     void                ExtractFileExtension( idStr &dest ) const;        // copy the file extension to another string
  264.     bool                CheckExtension( const char *ext );
  265.     void                ScrubFileName( void );                            // Turns a bad file name into a good one or your money back
  266.  
  267. // RAVEN BEGIN
  268. // jscott: like the declManager version, but globally accessable
  269.     void                MakeNameCanonical( void );
  270.     void                EnsurePrintable( void );
  271. // RAVEN END
  272.  
  273. // RAVEN BEGIN
  274. // abahr
  275.     void                Split( idList<idStr>& list, const char delimiter = ',', const char groupDelimiter = '\''  );
  276. // RAVEN END
  277.  
  278.     // char * methods to replace library functions
  279.     static int            Length( const char *s );
  280.     static char *        ToLower( char *s );
  281.     static char *        ToUpper( char *s );
  282.     static bool            IsNumeric( const char *s );
  283.     static bool            HasLower( const char *s );
  284.     static bool            HasUpper( const char *s );
  285. // RAVEN BEGIN
  286. // bdube: escape codes
  287.     static int            IsEscape( const char *s, int* type = NULL );
  288.     static int            LengthWithoutEscapes ( const char *s );    
  289.     static char *        RemoveEscapes ( char *s, int escapes = S_ESCAPE_ALL );
  290. // RAVEN END
  291.     static int            Cmp( const char *s1, const char *s2 );
  292.     static int            Cmpn( const char *s1, const char *s2, int n );
  293.     static int            Icmp( const char *s1, const char *s2 );
  294.     static int            Icmpn( const char *s1, const char *s2, int n );
  295. // RAVEN BEGIN
  296. // bdube: escapes
  297.     static int            IcmpNoEscape( const char *s1, const char *s2 );
  298. // RAVEN END
  299.     static int            IcmpPath( const char *s1, const char *s2 );            // compares paths and makes sure folders come first
  300.     static int            IcmpnPath( const char *s1, const char *s2, int n );    // compares paths and makes sure folders come first
  301.     static void            Append( char *dest, int size, const char *src );
  302.     static void            Copynz( char *dest, const char *src, int destsize );
  303.     static int            snPrintf( char *dest, int size, const char *fmt, ... ) id_attribute((format(printf,3,4)));
  304.     static int            vsnPrintf( char *dest, int size, const char *fmt, va_list argptr );
  305.     static int            FindChar( const char *str, const char c, int start = 0, int end = -1 );
  306.     static int            FindText( const char *str, const char *text, bool casesensitive = true, int start = 0, int end = -1 );
  307.     static bool            Filter( const char *filter, const char *name, bool casesensitive );
  308.     static void            StripMediaName( const char *name, idStr &mediaName );
  309.     static bool            CheckExtension( const char *name, const char *ext );
  310.     static const char *    FloatArrayToString( const float *array, const int length, const int precision );
  311.  
  312.     // hash keys
  313.     static int            Hash( const char *string );
  314.     static int            Hash( const char *string, int length );
  315.     static int            IHash( const char *string );                    // case insensitive
  316.     static int            IHash( const char *string, int length );        // case insensitive
  317.  
  318.     // character methods
  319.     static char            ToLower( byte c );
  320.     static char            ToUpper( byte c );
  321.     static bool            CharIsPrintable( byte c );
  322.     static bool            CharIsLower( byte c );
  323.     static bool            CharIsUpper( byte c );
  324.     static bool            CharIsAlpha( byte c );
  325.     static bool            CharIsNumeric( byte c );
  326.     static bool            CharIsNewLine( byte c );
  327.     static bool            CharIsTab( byte c );
  328.     static int            ColorIndex( int c );
  329.     static idVec4 &        ColorForIndex( int i );
  330.  
  331.     friend int            sprintf( idStr &dest, const char *fmt, ... );
  332.     friend int            vsprintf( idStr &dest, const char *fmt, va_list ap );
  333.  
  334.     void                ReAllocate( int amount, bool keepold );                // reallocate string data buffer
  335.     void                FreeData( void );                                    // free allocated string memory
  336.  
  337.                         // format value in the given measurement with the best unit, returns the best unit
  338.     int                    BestUnit( const char *format, float value, Measure_t measure );
  339.                         // format value in the requested unit and measurement
  340.     void                SetUnit( const char *format, float value, int unit, Measure_t measure );
  341.  
  342.     static void            InitMemory( void );
  343.     static void            ShutdownMemory( void );
  344.     static void            PurgeMemory( void );
  345.     static void            ShowMemoryUsage_f( const idCmdArgs &args );
  346.  
  347.     int                    DynamicMemoryUsed() const;
  348.     static idStr        FormatNumber( int number );
  349.  
  350.     static void            Split( const char* source, idList<idStr>& list, const char delimiter = ',', const char groupDelimiter = '\''  );
  351.  
  352. protected:
  353.     int                    len;
  354.     char *                data;
  355.     int                    alloced;
  356.     char                baseBuffer[ STR_ALLOC_BASE ];
  357.  
  358.     void                Init( void );                                        // initialize string using base buffer
  359.     void                EnsureAlloced( int amount, bool keepold = true );    // ensure string data buffer is large anough
  360.  
  361. // RAVEN BEGIN
  362. public:
  363.     static const bool    printableCharacter[256];
  364.     static const char    upperCaseCharacter[256];
  365.     static const char    lowerCaseCharacter[256];
  366. // RAVEN END
  367. };
  368.  
  369. char *                    va( const char *fmt, ... ) id_attribute((format(printf,1,2)));
  370.  
  371. // RAVEN BEGIN
  372. // abahr
  373. char*                    fe( int errorId );
  374. // RAVEN END
  375.  
  376. ID_INLINE void idStr::EnsureAlloced( int amount, bool keepold ) {
  377.     if ( amount > alloced ) {
  378.         ReAllocate( amount, keepold );
  379.     }
  380. }
  381.  
  382. ID_INLINE void idStr::Init( void ) {
  383.     len = 0;
  384.     alloced = STR_ALLOC_BASE;
  385.     data = baseBuffer;
  386.     data[ 0 ] = '\0';
  387. #ifdef ID_DEBUG_MEMORY
  388.     memset( baseBuffer, 0, sizeof( baseBuffer ) );
  389. #endif
  390. }
  391.  
  392. ID_INLINE idStr::idStr( void ) {
  393.     Init();
  394. }
  395.  
  396. ID_INLINE idStr::idStr( const idStr &text ) {
  397.     int l;
  398.  
  399.     Init();
  400.     l = text.Length();
  401.     EnsureAlloced( l + 1 );
  402.     strcpy( data, text.data );
  403.     len = l;
  404. }
  405.  
  406. ID_INLINE idStr::idStr( const idStr &text, int start, int end ) {
  407.     int i;
  408.     int l;
  409.  
  410.     Init();
  411.     if ( end > text.Length() ) {
  412.         end = text.Length();
  413.     }
  414.     if ( start > text.Length() ) {
  415.         start = text.Length();
  416.     } else if ( start < 0 ) {
  417.         start = 0;
  418.     }
  419.  
  420.     l = end - start;
  421.     if ( l < 0 ) {
  422.         l = 0;
  423.     }
  424.  
  425.     EnsureAlloced( l + 1 );
  426.  
  427.     for ( i = 0; i < l; i++ ) {
  428.         data[ i ] = text[ start + i ];
  429.     }
  430.  
  431.     data[ l ] = '\0';
  432.     len = l;
  433. }
  434.  
  435. ID_INLINE idStr::idStr( const char *text ) {
  436.     int l;
  437.  
  438.     Init();
  439.     if ( text ) {
  440.         l = strlen( text );
  441.         EnsureAlloced( l + 1 );
  442.         strcpy( data, text );
  443.         len = l;
  444.     }
  445. }
  446.  
  447. ID_INLINE idStr::idStr( const char *text, int start, int end ) {
  448.     int i;
  449.     int l = strlen( text );
  450.  
  451.     Init();
  452.     if ( end > l ) {
  453.         end = l;
  454.     }
  455.     if ( start > l ) {
  456.         start = l;
  457.     } else if ( start < 0 ) {
  458.         start = 0;
  459.     }
  460.  
  461.     l = end - start;
  462.     if ( l < 0 ) {
  463.         l = 0;
  464.     }
  465.  
  466.     EnsureAlloced( l + 1 );
  467.  
  468.     for ( i = 0; i < l; i++ ) {
  469.         data[ i ] = text[ start + i ];
  470.     }
  471.  
  472.     data[ l ] = '\0';
  473.     len = l;
  474. }
  475.  
  476. ID_INLINE idStr::idStr( const bool b ) {
  477.     Init();
  478.     EnsureAlloced( 2 );
  479.     data[ 0 ] = b ? '1' : '0';
  480.     data[ 1 ] = '\0';
  481.     len = 1;
  482. }
  483.  
  484. ID_INLINE idStr::idStr( const char c ) {
  485.     Init();
  486.     EnsureAlloced( 2 );
  487.     data[ 0 ] = c;
  488.     data[ 1 ] = '\0';
  489.     len = 1;
  490. }
  491.  
  492. ID_INLINE idStr::idStr( const int i ) {
  493.     char text[ 64 ];
  494.     int l;
  495.  
  496.     Init();
  497.     l = sprintf( text, "%d", i );
  498.     EnsureAlloced( l + 1 );
  499.     strcpy( data, text );
  500.     len = l;
  501. }
  502.  
  503. ID_INLINE idStr::idStr( const unsigned u ) {
  504.     char text[ 64 ];
  505.     int l;
  506.  
  507.     Init();
  508.     l = sprintf( text, "%u", u );
  509.     EnsureAlloced( l + 1 );
  510.     strcpy( data, text );
  511.     len = l;
  512. }
  513.  
  514. ID_INLINE idStr::idStr( const float f ) {
  515.     char text[ 64 ];
  516.     int l;
  517.  
  518.     Init();
  519.     l = idStr::snPrintf( text, sizeof( text ), "%f", f );
  520.     while( l > 0 && text[l-1] == '0' ) text[--l] = '\0';
  521.     while( l > 0 && text[l-1] == '.' ) text[--l] = '\0';
  522.     EnsureAlloced( l + 1 );
  523.     strcpy( data, text );
  524.     len = l;
  525. }
  526.  
  527. ID_INLINE idStr::~idStr( void ) {
  528.     FreeData();
  529. }
  530.  
  531. ID_INLINE size_t idStr::Size( void ) const {
  532.     return sizeof( *this ) + Allocated();
  533. }
  534.  
  535. ID_INLINE const char *idStr::c_str( void ) const {
  536.     return data;
  537. }
  538.  
  539. ID_INLINE idStr::operator const char *( void ) {
  540.     return c_str();
  541. }
  542.  
  543. ID_INLINE idStr::operator const char *( void ) const {
  544.     return c_str();
  545. }
  546.  
  547. ID_INLINE char idStr::operator[]( int index ) const {
  548.     assert( ( index >= 0 ) && ( index <= len ) );
  549.     return data[ index ];
  550. }
  551.  
  552. ID_INLINE char &idStr::operator[]( int index ) {
  553.     assert( ( index >= 0 ) && ( index <= len ) );
  554.     return data[ index ];
  555. }
  556.  
  557. ID_INLINE void idStr::operator=( const idStr &text ) {
  558.     int l;
  559.  
  560.     l = text.Length();
  561.     EnsureAlloced( l + 1, false );
  562.     memcpy( data, text.data, l );
  563.     data[l] = '\0';
  564.     len = l;
  565. }
  566.  
  567. ID_INLINE idStr operator+( const idStr &a, const idStr &b ) {
  568.     idStr result( a );
  569.     result.Append( b );
  570.     return result;
  571. }
  572.  
  573. ID_INLINE idStr operator+( const idStr &a, const char *b ) {
  574.     idStr result( a );
  575.     result.Append( b );
  576.     return result;
  577. }
  578.  
  579. ID_INLINE idStr operator+( const char *a, const idStr &b ) {
  580.     idStr result( a );
  581.     result.Append( b );
  582.     return result;
  583. }
  584.  
  585. ID_INLINE idStr operator+( const idStr &a, const bool b ) {
  586.     idStr result( a );
  587.     result.Append( b ? "true" : "false" );
  588.     return result;
  589. }
  590.  
  591. ID_INLINE idStr operator+( const idStr &a, const char b ) {
  592.     idStr result( a );
  593.     result.Append( b );
  594.     return result;
  595. }
  596.  
  597. ID_INLINE idStr operator+( const idStr &a, const float b ) {
  598.     char    text[ 64 ];
  599.     idStr    result( a );
  600.  
  601.     sprintf( text, "%f", b );
  602.     result.Append( text );
  603.  
  604.     return result;
  605. }
  606.  
  607. ID_INLINE idStr operator+( const idStr &a, const int b ) {
  608.     char    text[ 64 ];
  609.     idStr    result( a );
  610.  
  611.     sprintf( text, "%d", b );
  612.     result.Append( text );
  613.  
  614.     return result;
  615. }
  616.  
  617. ID_INLINE idStr operator+( const idStr &a, const unsigned b ) {
  618.     char    text[ 64 ];
  619.     idStr    result( a );
  620.  
  621.     sprintf( text, "%u", b );
  622.     result.Append( text );
  623.  
  624.     return result;
  625. }
  626.  
  627. ID_INLINE idStr &idStr::operator+=( const float a ) {
  628.     char text[ 64 ];
  629.  
  630.     sprintf( text, "%f", a );
  631.     Append( text );
  632.  
  633.     return *this;
  634. }
  635.  
  636. ID_INLINE idStr &idStr::operator+=( const int a ) {
  637.     char text[ 64 ];
  638.  
  639.     sprintf( text, "%d", a );
  640.     Append( text );
  641.  
  642.     return *this;
  643. }
  644.  
  645. ID_INLINE idStr &idStr::operator+=( const unsigned a ) {
  646.     char text[ 64 ];
  647.  
  648.     sprintf( text, "%u", a );
  649.     Append( text );
  650.  
  651.     return *this;
  652. }
  653.  
  654. ID_INLINE idStr &idStr::operator+=( const idStr &a ) {
  655.     Append( a );
  656.     return *this;
  657. }
  658.  
  659. ID_INLINE idStr &idStr::operator+=( const char *a ) {
  660.     Append( a );
  661.     return *this;
  662. }
  663.  
  664. ID_INLINE idStr &idStr::operator+=( const char a ) {
  665.     Append( a );
  666.     return *this;
  667. }
  668.  
  669. ID_INLINE idStr &idStr::operator+=( const bool a ) {
  670.     Append( a ? "true" : "false" );
  671.     return *this;
  672. }
  673.  
  674. ID_INLINE bool operator==( const idStr &a, const idStr &b ) {
  675.     return ( !idStr::Cmp( a.data, b.data ) );
  676. }
  677.  
  678. ID_INLINE bool operator==( const idStr &a, const char *b ) {
  679.     assert( b );
  680.     return ( !idStr::Cmp( a.data, b ) );
  681. }
  682.  
  683. ID_INLINE bool operator==( const char *a, const idStr &b ) {
  684.     assert( a );
  685.     return ( !idStr::Cmp( a, b.data ) );
  686. }
  687.  
  688. ID_INLINE bool operator!=( const idStr &a, const idStr &b ) {
  689.     return !( a == b );
  690. }
  691.  
  692. ID_INLINE bool operator!=( const idStr &a, const char *b ) {
  693.     return !( a == b );
  694. }
  695.  
  696. ID_INLINE bool operator!=( const char *a, const idStr &b ) {
  697.     return !( a == b );
  698. }
  699.  
  700. ID_INLINE int idStr::Cmp( const char *text ) const {
  701.     assert( text );
  702.     return idStr::Cmp( data, text );
  703. }
  704.  
  705. ID_INLINE int idStr::Cmpn( const char *text, int n ) const {
  706.     assert( text );
  707.     return idStr::Cmpn( data, text, n );
  708. }
  709.  
  710. ID_INLINE int idStr::CmpPrefix( const char *text ) const {
  711.     assert( text );
  712.     return idStr::Cmpn( data, text, strlen( text ) );
  713. }
  714.  
  715. ID_INLINE int idStr::Icmp( const char *text ) const {
  716.     assert( text );
  717.     return idStr::Icmp( data, text );
  718. }
  719.  
  720. ID_INLINE int idStr::Icmpn( const char *text, int n ) const {
  721.     assert( text );
  722.     return idStr::Icmpn( data, text, n );
  723. }
  724.  
  725. ID_INLINE int idStr::IcmpPrefix( const char *text ) const {
  726.     assert( text );
  727.     return idStr::Icmpn( data, text, strlen( text ) );
  728. }
  729.  
  730. // RAVEN BEGIN
  731. // bdube: escapes
  732. ID_INLINE int idStr::IcmpNoEscape( const char *text ) const {
  733.     assert( text );
  734.     return idStr::IcmpNoEscape( data, text );
  735. }
  736. // RAVEN END
  737.  
  738. ID_INLINE int idStr::IcmpPath( const char *text ) const {
  739.     assert( text );
  740.     return idStr::IcmpPath( data, text );
  741. }
  742.  
  743. ID_INLINE int idStr::IcmpnPath( const char *text, int n ) const {
  744.     assert( text );
  745.     return idStr::IcmpnPath( data, text, n );
  746. }
  747.  
  748. ID_INLINE int idStr::IcmpPrefixPath( const char *text ) const {
  749.     assert( text );
  750.     return idStr::IcmpnPath( data, text, strlen( text ) );
  751. }
  752.  
  753. ID_INLINE int idStr::Length( void ) const {
  754.     return len;
  755. }
  756.  
  757. ID_INLINE int idStr::Allocated( void ) const {
  758.     if ( data != baseBuffer ) {
  759.         return alloced;
  760.     } else {
  761.         return 0;
  762.     }
  763. }
  764.  
  765. ID_INLINE void idStr::Empty( void ) {
  766.     EnsureAlloced( 1 );
  767.     data[ 0 ] = '\0';
  768.     len = 0;
  769. }
  770.  
  771. ID_INLINE bool idStr::IsEmpty( void ) const {
  772.     return ( idStr::Cmp( data, "" ) == 0 );
  773. }
  774.  
  775. ID_INLINE void idStr::Clear( void ) {
  776.     FreeData();
  777.     Init();
  778. }
  779.  
  780. ID_INLINE void idStr::Append( const char a ) {
  781.     EnsureAlloced( len + 2 );
  782.     data[ len ] = a;
  783.     len++;
  784.     data[ len ] = '\0';
  785. }
  786.  
  787. ID_INLINE void idStr::Append( const idStr &text ) {
  788.     int newLen;
  789.     int i;
  790.  
  791.     newLen = len + text.Length();
  792.     EnsureAlloced( newLen + 1 );
  793.     for ( i = 0; i < text.len; i++ ) {
  794.         data[ len + i ] = text[ i ];
  795.     }
  796.     len = newLen;
  797.     data[ len ] = '\0';
  798. }
  799.  
  800. ID_INLINE void idStr::Append( const char *text ) {
  801.     int newLen;
  802.     int i;
  803.  
  804.     if ( text ) {
  805.         newLen = len + strlen( text );
  806.         EnsureAlloced( newLen + 1 );
  807.         for ( i = 0; text[ i ]; i++ ) {
  808.             data[ len + i ] = text[ i ];
  809.         }
  810.         len = newLen;
  811.         data[ len ] = '\0';
  812.     }
  813. }
  814.  
  815. ID_INLINE void idStr::Append( const char *text, int l ) {
  816.     int newLen;
  817.     int i;
  818.  
  819.     if ( text && l ) {
  820.         newLen = len + l;
  821.         EnsureAlloced( newLen + 1 );
  822.         for ( i = 0; text[ i ] && i < l; i++ ) {
  823.             data[ len + i ] = text[ i ];
  824.         }
  825.         len = newLen;
  826.         data[ len ] = '\0';
  827.     }
  828. }
  829.  
  830. ID_INLINE void idStr::Insert( const char a, int index ) {
  831.     int i, l;
  832.  
  833.     if ( index < 0 ) {
  834.         index = 0;
  835.     } else if ( index > len ) {
  836.         index = len;
  837.     }
  838.  
  839.     l = 1;
  840.     EnsureAlloced( len + l + 1 );
  841.     for ( i = len; i >= index; i-- ) {
  842.         data[i+l] = data[i];
  843.     }
  844.     data[index] = a;
  845.     len++;
  846. }
  847.  
  848. ID_INLINE void idStr::Insert( const char *text, int index ) {
  849.     int i, l;
  850.  
  851.     if ( index < 0 ) {
  852.         index = 0;
  853.     } else if ( index > len ) {
  854.         index = len;
  855.     }
  856.  
  857.     l = strlen( text );
  858.     EnsureAlloced( len + l + 1 );
  859.     for ( i = len; i >= index; i-- ) {
  860.         data[i+l] = data[i];
  861.     }
  862.     for ( i = 0; i < l; i++ ) {
  863.         data[index+i] = text[i];
  864.     }
  865.     len += l;
  866. }
  867.  
  868. ID_INLINE void idStr::ToLower( void ) {
  869.     for (int i = 0; data[i]; i++ ) {
  870. // RAVEN BEGIN
  871.         data[i] = ToLower( data[i] );
  872. // RAVEN END
  873.     }
  874. }
  875.  
  876. ID_INLINE void idStr::ToUpper( void ) {
  877.     for (int i = 0; data[i]; i++ ) {
  878. // RAVEN BEGIN
  879.         data[i] = ToUpper( data[i] );
  880. // RAVEN END
  881.     }
  882. }
  883.  
  884. ID_INLINE bool idStr::IsNumeric( void ) const {
  885.     return idStr::IsNumeric( data );
  886. }
  887.  
  888. ID_INLINE bool idStr::HasLower( void ) const {
  889.     return idStr::HasLower( data );
  890. }
  891.  
  892. ID_INLINE bool idStr::HasUpper( void ) const {
  893.     return idStr::HasUpper( data );
  894. }
  895.  
  896. ID_INLINE int idStr::IsEscape( int* type ) const {
  897.     return idStr::IsEscape( data, type );
  898. }
  899. ID_INLINE idStr &idStr::RemoveEscapes ( int escapes ) {
  900.     idStr::RemoveEscapes( data, escapes );
  901.     len = Length( c_str() );
  902.     return *this;
  903. }
  904. ID_INLINE int idStr::LengthWithoutEscapes( void ) const {
  905.     return idStr::LengthWithoutEscapes( data );
  906. }
  907. // RAVEN END
  908.  
  909. ID_INLINE void idStr::CapLength( int newlen ) {
  910.     if ( len <= newlen ) {
  911.         return;
  912.     }
  913.     data[ newlen ] = 0;
  914.     len = newlen;
  915. }
  916.  
  917. ID_INLINE void idStr::Fill( const char ch, int newlen ) {
  918.     EnsureAlloced( newlen + 1 );
  919.     len = newlen;
  920.     memset( data, ch, len );
  921.     data[ len ] = 0;
  922. }
  923.  
  924. ID_INLINE int idStr::Find( const char c, int start, int end ) const {
  925.     if ( end == -1 ) {
  926.         end = len;
  927.     }
  928.     return idStr::FindChar( data, c, start, end );
  929. }
  930.  
  931. ID_INLINE int idStr::Find( const char *text, bool casesensitive, int start, int end ) const {
  932.     if ( end == -1 ) {
  933.         end = len;
  934.     }
  935.     return idStr::FindText( data, text, casesensitive, start, end );
  936. }
  937.  
  938. ID_INLINE bool idStr::Filter( const char *filter, bool casesensitive ) const {
  939.     return idStr::Filter( filter, data, casesensitive );
  940. }
  941.  
  942. ID_INLINE const char *idStr::Left( int len, idStr &result ) const {
  943.     return Mid( 0, len, result );
  944. }
  945.  
  946. ID_INLINE const char *idStr::Right( int len, idStr &result ) const {
  947.     if ( len >= Length() ) {
  948.         result = *this;
  949.         return result;
  950.     }
  951.     return Mid( Length() - len, len, result );
  952. }
  953.  
  954. ID_INLINE idStr idStr::Left( int len ) const {
  955.     return Mid( 0, len );
  956. }
  957.  
  958. ID_INLINE idStr idStr::Right( int len ) const {
  959.     if ( len >= Length() ) {
  960.         return *this;
  961.     }
  962.     return Mid( Length() - len, len );
  963. }
  964.  
  965. ID_INLINE void idStr::Strip( const char c ) {
  966.     StripLeading( c );
  967.     StripTrailing( c );
  968. }
  969.  
  970. ID_INLINE void idStr::Strip( const char *string ) {
  971.     StripLeading( string );
  972.     StripTrailing( string );
  973. }
  974.  
  975. ID_INLINE bool idStr::CheckExtension( const char *ext ) {
  976.     return idStr::CheckExtension( data, ext );
  977. }
  978.  
  979. ID_INLINE int idStr::Length( const char *s ) {
  980.     int i;
  981.     for ( i = 0; s[i]; i++ ) {}
  982.     return i;
  983. }
  984.  
  985. ID_INLINE char *idStr::ToLower( char *s ) {
  986.     for ( int i = 0; s[i]; i++ ) {
  987. // RAVEN BEGIN
  988.         s[i] = ToLower( s[i] );
  989. // RAVEN END
  990.     }
  991.     return s;
  992. }
  993.  
  994. ID_INLINE char *idStr::ToUpper( char *s ) {
  995.     for ( int i = 0; s[i]; i++ ) {
  996. // RAVEN BEGIN
  997.         s[i] = ToUpper( s[i] );
  998. // RAVEN END
  999.     }
  1000.     return s;
  1001. }
  1002.  
  1003. ID_INLINE int idStr::Hash( const char *string ) {
  1004.     int i, hash = 0;
  1005.     for ( i = 0; *string != '\0'; i++ ) {
  1006.         hash += ( *string++ ) * ( i + 119 );
  1007.     }
  1008.     return hash;
  1009. }
  1010.  
  1011. ID_INLINE int idStr::Hash( const char *string, int length ) {
  1012.     int i, hash = 0;
  1013.     for ( i = 0; i < length; i++ ) {
  1014.         hash += ( *string++ ) * ( i + 119 );
  1015.     }
  1016.     return hash;
  1017. }
  1018.  
  1019. ID_INLINE int idStr::IHash( const char *string ) {
  1020.     int i, hash = 0;
  1021.     for( i = 0; *string != '\0'; i++ ) {
  1022.         hash += ToLower( *string++ ) * ( i + 119 );
  1023.     }
  1024.     return hash;
  1025. }
  1026.  
  1027. ID_INLINE int idStr::IHash( const char *string, int length ) {
  1028.     int i, hash = 0;
  1029.     for ( i = 0; i < length; i++ ) {
  1030.         hash += ToLower( *string++ ) * ( i + 119 );
  1031.     }
  1032.     return hash;
  1033. }
  1034.  
  1035. ID_INLINE char idStr::ToLower( byte c ) {
  1036. // RAVEN BEGIN
  1037.     if( lowerCaseCharacter[c] ) {
  1038.         return lowerCaseCharacter[c];
  1039.     }
  1040. // RAVEN END
  1041.     return c;
  1042. }
  1043.  
  1044. ID_INLINE char idStr::ToUpper( byte c ) {
  1045. // RAVEN BEGIN
  1046.     if( upperCaseCharacter[c] ) {
  1047.         return upperCaseCharacter[c];
  1048.     }
  1049. // RAVEN END
  1050.     return c;
  1051. }
  1052.  
  1053. ID_INLINE bool idStr::CharIsPrintable( byte c ) {
  1054. // RAVEN BEGIN
  1055.     return printableCharacter[c];
  1056. // RAVEN END
  1057. }
  1058.  
  1059. ID_INLINE bool idStr::CharIsLower( byte c ) {
  1060. // RAVEN BEGIN
  1061.     return !!lowerCaseCharacter[c] && ( lowerCaseCharacter[c] == c );
  1062. // RAVEN END
  1063. }
  1064.  
  1065. ID_INLINE bool idStr::CharIsUpper( byte c ) {
  1066. // RAVEN BEGIN
  1067.     return !!upperCaseCharacter[c] && ( upperCaseCharacter[c] == c );
  1068. // RAVEN END
  1069. }
  1070.  
  1071. ID_INLINE bool idStr::CharIsAlpha( byte c ) {
  1072.     // test for regular ascii and western European high-ascii chars
  1073.     return !!upperCaseCharacter[c];
  1074. }
  1075.  
  1076. ID_INLINE bool idStr::CharIsNumeric( byte c ) {
  1077.     return ( c <= '9' && c >= '0' );
  1078. }
  1079.  
  1080. ID_INLINE bool idStr::CharIsNewLine( byte c ) {
  1081.     return ( c == '\n' || c == '\r' || c == '\v' );
  1082. }
  1083.  
  1084. ID_INLINE bool idStr::CharIsTab( byte c ) {
  1085.     return ( c == '\t' );
  1086. }
  1087.  
  1088. ID_INLINE int idStr::ColorIndex( int c ) {
  1089.     return ( c & 15 );
  1090. }
  1091.  
  1092. ID_INLINE int idStr::DynamicMemoryUsed() const {
  1093.     return ( data == baseBuffer ) ? 0 : alloced;
  1094. }
  1095.  
  1096. #endif /* !__STR_H__ */
  1097.