Main Page | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

q_shared.cpp

Go to the documentation of this file.
00001 /*
00002 ===========================================================================
00003 Copyright (C) 1999-2005 Id Software, Inc.
00004 
00005 This file is part of Quake III Arena source code.
00006 
00007 Quake III Arena source code is free software; you can redistribute it
00008 and/or modify it under the terms of the GNU General Public License as
00009 published by the Free Software Foundation; either version 2 of the License,
00010 or (at your option) any later version.
00011 
00012 Quake III Arena source code is distributed in the hope that it will be
00013 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Foobar; if not, write to the Free Software
00019 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020 ===========================================================================
00021 */
00022 // q_shared.c -- stateless support routines that are included in each code dll
00023 #include "q_shared.h"
00024 
00025 /*
00026 ============================================================================
00027 
00028 GROWLISTS
00029 
00030 ============================================================================
00031 */
00032 
00033 // malloc / free all in one place for debugging
00034 extern "C" void *Com_Allocate( int bytes );
00035 extern "C" void Com_Dealloc( void *ptr );
00036 
00037 void Com_InitGrowList( growList_t *list, int maxElements ) {
00038     list->maxElements = maxElements;
00039     list->currentElements = 0;
00040     list->elements = (void **)Com_Allocate( list->maxElements * sizeof( void * ) );
00041 }
00042 
00043 int Com_AddToGrowList( growList_t *list, void *data ) {
00044     void    **old;
00045 
00046     if ( list->currentElements != list->maxElements ) {
00047         list->elements[list->currentElements] = data;
00048         return list->currentElements++;
00049     }
00050 
00051     // grow, reallocate and move
00052     old = list->elements;
00053 
00054     if ( list->maxElements < 0 ) {
00055         Com_Error( ERR_FATAL, "Com_AddToGrowList: maxElements = %i", list->maxElements );
00056     }
00057 
00058     if ( list->maxElements == 0 ) {
00059         // initialize the list to hold 100 elements
00060         Com_InitGrowList( list, 100 );
00061         return Com_AddToGrowList( list, data );
00062     }
00063 
00064     list->maxElements *= 2;
00065 
00066     Com_DPrintf( "Resizing growlist to %i maxElements\n", list->maxElements );
00067 
00068     list->elements = (void **)Com_Allocate( list->maxElements * sizeof( void * ) );
00069 
00070     if ( !list->elements ) {
00071         Com_Error( ERR_DROP, "Growlist alloc failed" );
00072     }
00073 
00074     memcpy( list->elements, old, list->currentElements * sizeof( void * ) );
00075 
00076     Com_Dealloc( old );
00077 
00078     return Com_AddToGrowList( list, data );
00079 }
00080 
00081 void *Com_GrowListElement( const growList_t *list, int index ) {
00082     if ( index < 0 || index >= list->currentElements ) {
00083         Com_Error( ERR_DROP, "Com_GrowListElement: %i out of range of %i", 
00084             index, list->currentElements );
00085     }
00086     return list->elements[index];
00087 }
00088 
00089 int Com_IndexForGrowListElement( const growList_t *list, const void *element ) {
00090     int     i;
00091 
00092     for ( i = 0 ; i < list->currentElements ; i++ ) {
00093         if ( list->elements[i] == element ) {
00094             return i;
00095         }
00096     }
00097     return -1;
00098 }
00099 
00100 //============================================================================
00101 
00102 
00103 float Com_Clamp( float min, float max, float value ) {
00104     if ( value < min ) {
00105         return min;
00106     }
00107     if ( value > max ) {
00108         return max;
00109     }
00110     return value;
00111 }
00112 
00113 /*
00114 ============
00115 Com_StringContains
00116 ============
00117 */
00118 const char *Com_StringContains( const char *str1, const char *str2, int casesensitive) {
00119     int len, i, j;
00120 
00121     len = strlen(str1) - strlen(str2);
00122     for (i = 0; i <= len; i++, str1++) {
00123         for (j = 0; str2[j]; j++) {
00124             if (casesensitive) {
00125                 if (str1[j] != str2[j]) {
00126                     break;
00127                 }
00128             }
00129             else {
00130                 if (toupper(str1[j]) != toupper(str2[j])) {
00131                     break;
00132                 }
00133             }
00134         }
00135         if (!str2[j]) {
00136             return str1;
00137         }
00138     }
00139     return NULL;
00140 }
00141 
00142 /*
00143 ============
00144 Com_Filter
00145 ============
00146 */
00147 int Com_Filter( const char *filter, const char *name, int casesensitive)
00148 {
00149     char buf[MAX_TOKEN_CHARS];
00150     const char *ptr;
00151     int i, found;
00152 
00153     while(*filter) {
00154         if (*filter == '*') {
00155             filter++;
00156             for (i = 0; *filter; i++) {
00157                 if (*filter == '*' || *filter == '?') break;
00158                 buf[i] = *filter;
00159                 filter++;
00160             }
00161             buf[i] = '\0';
00162             if (strlen(buf)) {
00163                 ptr = Com_StringContains(name, buf, casesensitive);
00164                 if (!ptr) return qfalse;
00165                 name = ptr + strlen(buf);
00166             }
00167         }
00168         else if (*filter == '?') {
00169             filter++;
00170             name++;
00171         }
00172         else if (*filter == '[' && *(filter+1) == '[') {
00173             filter++;
00174         }
00175         else if (*filter == '[') {
00176             filter++;
00177             found = qfalse;
00178             while(*filter && !found) {
00179                 if (*filter == ']' && *(filter+1) != ']') break;
00180                 if (*(filter+1) == '-' && *(filter+2) && (*(filter+2) != ']' || *(filter+3) == ']')) {
00181                     if (casesensitive) {
00182                         if (*name >= *filter && *name <= *(filter+2)) found = qtrue;
00183                     }
00184                     else {
00185                         if (toupper(*name) >= toupper(*filter) &&
00186                             toupper(*name) <= toupper(*(filter+2))) found = qtrue;
00187                     }
00188                     filter += 3;
00189                 }
00190                 else {
00191                     if (casesensitive) {
00192                         if (*filter == *name) found = qtrue;
00193                     }
00194                     else {
00195                         if (toupper(*filter) == toupper(*name)) found = qtrue;
00196                     }
00197                     filter++;
00198                 }
00199             }
00200             if (!found) return qfalse;
00201             while(*filter) {
00202                 if (*filter == ']' && *(filter+1) != ']') break;
00203                 filter++;
00204             }
00205             filter++;
00206             name++;
00207         }
00208         else {
00209             if (casesensitive) {
00210                 if (*filter != *name) return qfalse;
00211             }
00212             else {
00213                 if (toupper(*filter) != toupper(*name)) return qfalse;
00214             }
00215             filter++;
00216             name++;
00217         }
00218     }
00219     return qtrue;
00220 }
00221 
00222 
00223 /*
00224 ================
00225 Com_HashString
00226 
00227 ================
00228 */
00229 int Com_HashString( const char *fname ) {
00230     int     i;
00231     long    hash;
00232     char    letter;
00233 
00234     hash = 0;
00235     i = 0;
00236     while (fname[i] != '\0') {
00237         letter = tolower(fname[i]);
00238         if (letter =='.') break;                // don't include extension
00239         if (letter =='\\') letter = '/';        // damn path names
00240         hash+=(long)(letter)*(i+119);
00241         i++;
00242     }
00243     hash &= (FILE_HASH_SIZE-1);
00244     return hash;
00245 }
00246 
00247 
00248 /*
00249 ============
00250 Com_SkipPath
00251 ============
00252 */
00253 char *Com_SkipPath (char *pathname)
00254 {
00255     char    *last;
00256     
00257     last = pathname;
00258     while (*pathname)
00259     {
00260         if (*pathname=='/')
00261             last = pathname+1;
00262         pathname++;
00263     }
00264     return last;
00265 }
00266 
00267 /*
00268 ============
00269 Com_StripExtension
00270 ============
00271 */
00272 void Com_StripExtension( const char *in, char *out ) {
00273     while ( *in && *in != '.' ) {
00274         *out++ = *in++;
00275     }
00276     *out = 0;
00277 }
00278 
00279 
00280 /*
00281 ==================
00282 Com_DefaultExtension
00283 ==================
00284 */
00285 void Com_DefaultExtension (char *path, int maxSize, const char *extension ) {
00286     char    oldPath[MAX_QPATH];
00287     char    *src;
00288 
00289 //
00290 // if path doesn't have a .EXT, append extension
00291 // (extension should include the .)
00292 //
00293     src = path + strlen(path) - 1;
00294 
00295     while (*src != '/' && src != path) {
00296         if ( *src == '.' ) {
00297             return;                 // it has an extension
00298         }
00299         src--;
00300     }
00301 
00302     Q_strncpyz( oldPath, path, sizeof( oldPath ) );
00303     Com_sprintf( path, maxSize, "%s%s", oldPath, extension );
00304 }
00305 
00306 /*
00307 ============================================================================
00308 
00309                     BYTE ORDER FUNCTIONS
00310 
00311 ============================================================================
00312 */
00313 
00314 // can't just use function pointers, or dll linkage can
00315 // mess up when qcommon is included in multiple places
00316 static short    (*_BigShort) (short l);
00317 static short    (*_LittleShort) (short l);
00318 static int      (*_BigLong) (int l);
00319 static int      (*_LittleLong) (int l);
00320 static float    (*_BigFloat) (float l);
00321 static float    (*_LittleFloat) (float l);
00322 
00323 short   BigShort(short l){return _BigShort(l);}
00324 short   LittleShort(short l) {return _LittleShort(l);}
00325 int     BigLong (int l) {return _BigLong(l);}
00326 int     LittleLong (int l) {return _LittleLong(l);}
00327 float   BigFloat (float l) {return _BigFloat(l);}
00328 float   LittleFloat (float l) {return _LittleFloat(l);}
00329 
00330 short   ShortSwap (short l)
00331 {
00332     byte    b1,b2;
00333 
00334     b1 = l&255;
00335     b2 = (l>>8)&255;
00336 
00337     return (b1<<8) + b2;
00338 }
00339 
00340 short   ShortNoSwap (short l)
00341 {
00342     return l;
00343 }
00344 
00345 int    LongSwap (int l)
00346 {
00347     byte    b1,b2,b3,b4;
00348 
00349     b1 = l&255;
00350     b2 = (l>>8)&255;
00351     b3 = (l>>16)&255;
00352     b4 = (l>>24)&255;
00353 
00354     return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
00355 }
00356 
00357 int LongNoSwap (int l)
00358 {
00359     return l;
00360 }
00361 
00362 float FloatSwap (float f)
00363 {
00364     union
00365     {
00366         float   f;
00367         byte    b[4];
00368     } dat1, dat2;
00369     
00370     
00371     dat1.f = f;
00372     dat2.b[0] = dat1.b[3];
00373     dat2.b[1] = dat1.b[2];
00374     dat2.b[2] = dat1.b[1];
00375     dat2.b[3] = dat1.b[0];
00376     return dat2.f;
00377 }
00378 
00379 float FloatNoSwap (float f)
00380 {
00381     return f;
00382 }
00383 
00384 /*
00385 ================
00386 Swap_Init
00387 ================
00388 */
00389 void Swap_Init (void)
00390 {
00391     byte    swaptest[2] = {1,0};
00392 
00393 // set the byte swapping variables in a portable manner 
00394     if ( *(short *)swaptest == 1)
00395     {
00396         _BigShort = ShortSwap;
00397         _LittleShort = ShortNoSwap;
00398         _BigLong = LongSwap;
00399         _LittleLong = LongNoSwap;
00400         _BigFloat = FloatSwap;
00401         _LittleFloat = FloatNoSwap;
00402     }
00403     else
00404     {
00405         _BigShort = ShortNoSwap;
00406         _LittleShort = ShortSwap;
00407         _BigLong = LongNoSwap;
00408         _LittleLong = LongSwap;
00409         _BigFloat = FloatNoSwap;
00410         _LittleFloat = FloatSwap;
00411     }
00412 
00413 }
00414 
00415 /*
00416 ===============
00417 Com_ParseInfos
00418 ===============
00419 */
00420 int Com_ParseInfos( const char *buf, int max, char infos[][MAX_INFO_STRING] ) {
00421     const char  *token;
00422     int     count;
00423     char    key[MAX_TOKEN_CHARS];
00424 
00425     count = 0;
00426 
00427     while ( 1 ) {
00428         token = Com_Parse( &buf );
00429         if ( !token[0] ) {
00430             break;
00431         }
00432         if ( strcmp( token, "{" ) ) {
00433             Com_Printf( "Missing { in info file\n" );
00434             break;
00435         }
00436 
00437         if ( count == max ) {
00438             Com_Printf( "Max infos exceeded\n" );
00439             break;
00440         }
00441 
00442         infos[count][0] = 0;
00443         while ( 1 ) {
00444             token = Com_Parse( &buf );
00445             if ( !token[0] ) {
00446                 Com_Printf( "Unexpected end of info file\n" );
00447                 break;
00448             }
00449             if ( !strcmp( token, "}" ) ) {
00450                 break;
00451             }
00452             Q_strncpyz( key, token, sizeof( key ) );
00453 
00454             token = Com_ParseOnLine( &buf );
00455             if ( !token[0] ) {
00456                 token = "<NULL>";
00457             }
00458             Info_SetValueForKey( infos[count], key, token );
00459         }
00460         count++;
00461     }
00462 
00463     return count;
00464 }
00465 
00466 
00467 
00468 /*
00469 ============================================================================
00470 
00471                     LIBRARY REPLACEMENT FUNCTIONS
00472 
00473 ============================================================================
00474 */
00475 
00476 int Q_isprint( int c )
00477 {
00478     if ( c >= 0x20 && c <= 0x7E )
00479         return ( 1 );
00480     return ( 0 );
00481 }
00482 
00483 int Q_islower( int c )
00484 {
00485     if (c >= 'a' && c <= 'z')
00486         return ( 1 );
00487     return ( 0 );
00488 }
00489 
00490 int Q_isupper( int c )
00491 {
00492     if (c >= 'A' && c <= 'Z')
00493         return ( 1 );
00494     return ( 0 );
00495 }
00496 
00497 int Q_isalpha( int c )
00498 {
00499     if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
00500         return ( 1 );
00501     return ( 0 );
00502 }
00503 
00504 char* Q_strrchr( const char* string, int c )
00505 {
00506     char cc = c;
00507     char *s;
00508     char *sp=(char *)0;
00509 
00510     s = (char*)string;
00511 
00512     while (*s)
00513     {
00514         if (*s == cc)
00515             sp = s;
00516         s++;
00517     }
00518     if (cc == 0)
00519         sp = s;
00520 
00521     return sp;
00522 }
00523 
00524 /*
00525 =============
00526 Q_strncpyz
00527  
00528 Safe strncpy that ensures a trailing zero
00529 =============
00530 */
00531 void Q_strncpyz( char *dest, const char *src, int destsize ) {
00532     if ( !src ) {
00533         Com_Error( ERR_FATAL, "Q_strncpyz: NULL src" );
00534     }
00535     if ( destsize < 1 ) {
00536         Com_Error(ERR_FATAL,"Q_strncpyz: destsize < 1" ); 
00537     }
00538 
00539     strncpy( dest, src, destsize-1 );
00540     dest[destsize-1] = 0;
00541 }
00542                  
00543 int Q_stricmpn (const char *s1, const char *s2, int n) {
00544     int     c1, c2;
00545     
00546     do {
00547         c1 = *s1++;
00548         c2 = *s2++;
00549 
00550         if (!n--) {
00551             return 0;       // strings are equal until end point
00552         }
00553         
00554         if (c1 != c2) {
00555             if (c1 >= 'a' && c1 <= 'z') {
00556                 c1 -= ('a' - 'A');
00557             }
00558             if (c2 >= 'a' && c2 <= 'z') {
00559                 c2 -= ('a' - 'A');
00560             }
00561             if (c1 != c2) {
00562                 return c1 < c2 ? -1 : 1;
00563             }
00564         }
00565     } while (c1);
00566     
00567     return 0;       // strings are equal
00568 }
00569 
00570 int Q_strncmp (const char *s1, const char *s2, int n) {
00571     int     c1, c2;
00572     
00573     do {
00574         c1 = *s1++;
00575         c2 = *s2++;
00576 
00577         if (!n--) {
00578             return 0;       // strings are equal until end point
00579         }
00580         
00581         if (c1 != c2) {
00582             return c1 < c2 ? -1 : 1;
00583         }
00584     } while (c1);
00585     
00586     return 0;       // strings are equal
00587 }
00588 
00589 int Q_stricmp (const char *s1, const char *s2) {
00590     return Q_stricmpn (s1, s2, 99999);
00591 }
00592 
00593 
00594 char *Q_strlwr( char *s1 ) {
00595     char    *s;
00596 
00597     s = s1;
00598     while ( *s ) {
00599         *s = tolower(*s);
00600         s++;
00601     }
00602     return s1;
00603 }
00604 
00605 char *Q_strupr( char *s1 ) {
00606     char    *s;
00607 
00608     s = s1;
00609     while ( *s ) {
00610         *s = toupper(*s);
00611         s++;
00612     }
00613     return s1;
00614 }
00615 
00616 
00617 // never goes past bounds or leaves without a terminating 0
00618 void Q_strcat( char *dest, int size, const char *src ) {
00619     int     l1;
00620 
00621     l1 = strlen( dest );
00622     if ( l1 >= size ) {
00623         Com_Error( ERR_FATAL, "Q_strcat: already overflowed" );
00624     }
00625     Q_strncpyz( dest + l1, src, size - l1 );
00626 }
00627 
00628 
00629 int Q_PrintStrlen( const char *string ) {
00630     int         len;
00631     const char  *p;
00632 
00633     if( !string ) {
00634         return 0;
00635     }
00636 
00637     len = 0;
00638     p = string;
00639     while( *p ) {
00640         if( Q_IsColorString( p ) ) {
00641             p += 2;
00642             continue;
00643         }
00644         p++;
00645         len++;
00646     }
00647 
00648     return len;
00649 }
00650 
00651 
00652 char *Q_CleanStr( char *string ) {
00653     char*   d;
00654     char*   s;
00655     int     c;
00656 
00657     s = string;
00658     d = string;
00659     while ((c = *s) != 0 ) {
00660         if ( Q_IsColorString( s ) ) {
00661             s++;
00662         }       
00663         else if ( c >= 0x20 && c <= 0x7E ) {
00664             *d++ = c;
00665         }
00666         s++;
00667     }
00668     *d = '\0';
00669 
00670     return string;
00671 }
00672 
00673 
00674 void QDECL Com_sprintf( char *dest, int size, const char *fmt, ...) {
00675     int     len;
00676     va_list     argptr;
00677     char    bigbuffer[32000];   // big, but small enough to fit in PPC stack
00678 
00679     va_start (argptr,fmt);
00680     len = vsprintf (bigbuffer,fmt,argptr);
00681     va_end (argptr);
00682     if ( len >= sizeof( bigbuffer ) ) {
00683         Com_Error( ERR_FATAL, "Com_sprintf: overflowed bigbuffer" );
00684     }
00685     if (len >= size) {
00686         Com_Printf ("Com_sprintf: overflow of %i in %i\n", len, size);
00687     }
00688     Q_strncpyz (dest, bigbuffer, size );
00689 }
00690 
00691 
00692 /*
00693 ============
00694 va
00695 
00696 does a varargs printf into a temp buffer, so I don't need to have
00697 varargs versions of all text functions.
00698 FIXME: make this buffer size safe someday
00699 ============
00700 */
00701 char    * QDECL va( char *format, ... ) {
00702     va_list     argptr;
00703     static char     string[2][32000];   // in case va is called by nested functions
00704     static int      index = 0;
00705     char    *buf;
00706 
00707     buf = string[index & 1];
00708     index++;
00709 
00710     va_start (argptr, format);
00711     vsprintf (buf, format,argptr);
00712     va_end (argptr);
00713 
00714     return buf;
00715 }
00716 
00717 
00718 /*
00719 =====================================================================
00720 
00721   INFO STRINGS
00722 
00723 =====================================================================
00724 */
00725 
00726 /*
00727 ===============
00728 Info_ValueForKey
00729 
00730 Searches the string for the given
00731 key and returns the associated value, or an empty string.
00732 FIXME: overflow check?
00733 ===============
00734 */
00735 char *Info_ValueForKey( const char *s, const char *key ) {
00736     char    pkey[MAX_INFO_KEY];
00737     static  char value[2][MAX_INFO_VALUE];  // use two buffers so compares
00738                                             // work without stomping on each other
00739     static  int valueindex = 0;
00740     char    *o;
00741     
00742     if ( !s || !key ) {
00743         return "";
00744     }
00745 
00746     if ( strlen( s ) >= MAX_INFO_STRING ) {
00747         Com_Error( ERR_DROP, "Info_ValueForKey: oversize infostring" );
00748     }
00749 
00750     valueindex ^= 1;
00751     if (*s == '\\')
00752         s++;
00753     while (1)
00754     {
00755         o = pkey;
00756         while (*s != '\\')
00757         {
00758             if (!*s)
00759                 return "";
00760             *o++ = *s++;
00761         }
00762         *o = 0;
00763         s++;
00764 
00765         o = value[valueindex];
00766 
00767         while (*s != '\\' && *s)
00768         {
00769             *o++ = *s++;
00770         }
00771         *o = 0;
00772 
00773         if (!Q_stricmp (key, pkey) )
00774             return value[valueindex];
00775 
00776         if (!*s)
00777             break;
00778         s++;
00779     }
00780 
00781     return "";
00782 }
00783 
00784 
00785 /*
00786 ===================
00787 Info_NextPair
00788 
00789 Used to itterate through all the key/value pairs in an info string
00790 ===================
00791 */
00792 void Info_NextPair( const char *(*head), char key[MAX_INFO_KEY], char value[MAX_INFO_VALUE] ) {
00793     char    *o;
00794     const char  *s;
00795 
00796     s = *head;
00797 
00798     if ( *s == '\\' ) {
00799         s++;
00800     }
00801     key[0] = 0;
00802     value[0] = 0;
00803 
00804     o = key;
00805     while ( *s != '\\' ) {
00806         if ( !*s ) {
00807             *o = 0;
00808             *head = s;
00809             return;
00810         }
00811         *o++ = *s++;
00812     }
00813     *o = 0;
00814     s++;
00815 
00816     o = value;
00817     while ( *s != '\\' && *s ) {
00818         *o++ = *s++;
00819     }
00820     *o = 0;
00821 
00822     *head = s;
00823 }
00824 
00825 
00826 /*
00827 ===================
00828 Info_RemoveKey
00829 ===================
00830 */
00831 void Info_RemoveKey( char *s, const char *key ) {
00832     char    *start;
00833     char    pkey[MAX_INFO_KEY];
00834     char    value[MAX_INFO_VALUE];
00835     char    *o;
00836 
00837     if ( strlen( s ) >= MAX_INFO_STRING ) {
00838         Com_Error( ERR_DROP, "Info_RemoveKey: oversize infostring" );
00839     }
00840 
00841     if (strchr (key, '\\')) {
00842         return;
00843     }
00844 
00845     while (1)
00846     {
00847         start = s;
00848         if (*s == '\\')
00849             s++;
00850         o = pkey;
00851         while (*s != '\\')
00852         {
00853             if (!*s)
00854                 return;
00855             *o++ = *s++;
00856         }
00857         *o = 0;
00858         s++;
00859 
00860         o = value;
00861         while (*s != '\\' && *s)
00862         {
00863             if (!*s)
00864                 return;
00865             *o++ = *s++;
00866         }
00867         *o = 0;
00868 
00869         if (!strcmp (key, pkey) )
00870         {
00871             strcpy (start, s);  // remove this part
00872             return;
00873         }
00874 
00875         if (!*s)
00876             return;
00877     }
00878 
00879 }
00880 
00881 
00882 /*
00883 ==================
00884 Info_Validate
00885 
00886 Some characters are illegal in info strings because they
00887 can mess up the server's parsing
00888 ==================
00889 */
00890 qboolean Info_Validate( const char *s ) {
00891     if ( strchr( s, '\"' ) ) {
00892         return qfalse;
00893     }
00894     if ( strchr( s, ';' ) ) {
00895         return qfalse;
00896     }
00897     return qtrue;
00898 }
00899 
00900 /*
00901 ==================
00902 Info_SetValueForKey
00903 
00904 Changes or adds a key/value pair
00905 ==================
00906 */
00907 void Info_SetValueForKey( char *s, const char *key, const char *value ) {
00908     char    newi[MAX_INFO_STRING];
00909 
00910     if ( strlen( s ) >= MAX_INFO_STRING ) {
00911         Com_Error( ERR_DROP, "Info_SetValueForKey: oversize infostring" );
00912     }
00913 
00914     if (strchr (key, '\\') || strchr (value, '\\'))
00915     {
00916         Com_Printf ("Can't use keys or values with a \\\n");
00917         return;
00918     }
00919 
00920     if (strchr (key, ';') || strchr (value, ';'))
00921     {
00922         Com_Printf ("Can't use keys or values with a semicolon\n");
00923         return;
00924     }
00925 
00926     if (strchr (key, '\"') || strchr (value, '\"'))
00927     {
00928         Com_Printf ("Can't use keys or values with a \"\n");
00929         return;
00930     }
00931 
00932     Info_RemoveKey (s, key);
00933     if (!value || !strlen(value))
00934         return;
00935 
00936     Com_sprintf (newi, sizeof(newi), "\\%s\\%s", key, value);
00937 
00938     if (strlen(newi) + strlen(s) > MAX_INFO_STRING)
00939     {
00940         Com_Printf ("Info string length exceeded\n");
00941         return;
00942     }
00943 
00944     strcat (s, newi);
00945 }
00946 
00947 //====================================================================
00948 
00949 
00950 /*
00951 ===============
00952 ParseHex
00953 ===============
00954 */
00955 int ParseHex( const char *text ) {
00956     int     value;
00957     int     c;
00958 
00959     value = 0;
00960     while ( ( c = *text++ ) != 0 ) {
00961         if ( c >= '0' && c <= '9' ) {
00962             value = value * 16 + c - '0';
00963             continue;
00964         }
00965         if ( c >= 'a' && c <= 'f' ) {
00966             value = value * 16 + 10 + c - 'a';
00967             continue;
00968         }
00969         if ( c >= 'A' && c <= 'F' ) {
00970             value = value * 16 + 10 + c - 'A';
00971             continue;
00972         }
00973     }
00974 
00975     return value;
00976 }

Generated on Thu Aug 25 12:37:59 2005 for Quake III Arena by  doxygen 1.3.9.1