diff options
Diffstat (limited to 'tools/globalcode/utility/util.c')
-rw-r--r-- | tools/globalcode/utility/util.c | 724 |
1 files changed, 724 insertions, 0 deletions
diff --git a/tools/globalcode/utility/util.c b/tools/globalcode/utility/util.c new file mode 100644 index 0000000..79764df --- /dev/null +++ b/tools/globalcode/utility/util.c @@ -0,0 +1,724 @@ +/*----------------------------------------------------------------------------- +** Copyright (C) 2001 Radical Entertainment Ltd. All rights reserved. +** +** winutil.h +** +** Description: A set of utilities which are specific to the windows development +** environment. +** +** Modification History: +** + Created Aug 03, 2001 -- bkusy +**---------------------------------------------------------------------------*/ + +/*---------------------------------------- +** System Includes +**--------------------------------------*/ +#include <string.h> +#include <stdio.h> +#include <assert.h> + +/*---------------------------------------- +** Project Includes +**--------------------------------------*/ +#include "util.h" + +/*---------------------------------------- +** Constants +**--------------------------------------*/ +#define BUFFER_SIZE 512 + +/*---------------------------------------- +** Globals +**--------------------------------------*/ +char* util_optarg; +int util_optind; +int util_opterr = 1; +int util_optopt; + + +/*----------------------------------------------------------------------------- +** u t i l _ b a s e n a m e +** +** Synopsis: Determine the basename in a file path. ( eg/ would return +** "newfile.c" from the path "/usr/home/newfile.c". +** +** Parameters: buffer - buffer to receive basename. +** size - size of buffer. +** path - path to determine basename from. +** +** Returns: non-zero if successful, 0 if buffer is too small. +** +** Constraints: path must use '/' and not '\' as directory separators. +** +**---------------------------------------------------------------------------*/ +int util_basename( char* buffer, int size, const char* path ) +{ + char* d; + char* n; + char* e; + int length; + int result = 0; + + assert( buffer ); + + util_decomposeFilePath( path, &d, &n, &e ); + + length = strlen( n ) + strlen( e ) + 1; + + if ( length < size ) + { + strcpy( buffer, n ); + strcat( buffer, "." ); + strcat( buffer, e ); + + result = 1; + } + + return result; +} +/*----------------------------------------------------------------------------- +** u t i l _ c h a n g e F i l e E x t e n s i o n +** +** Synopsis: Changes the file extension in the given buffer to the given +** given extension. +** +** Parameters: buffer - the file path to be modified. +** ext - the new file extension. +** +** Returns: NOTHING +** +** Constraints: If the original file path does not have an extension, as +** identified by the presence of a "." character, no change will +** take place. +** If the new extension is longer than the old extension, no +** change will take place. +** +**---------------------------------------------------------------------------*/ +void util_changeFileExtension( char* buffer, const char* ext ) +{ + char* oldExt = 0; + + assert( buffer ); + assert( ext ); + + oldExt = (char*)(util_rindex( buffer, '.' )); + + if ( oldExt ) + { + oldExt++; + + if ( strlen( oldExt ) <= strlen( ext ) ) + { + strcpy( oldExt, ext ); + } + } +} + +/*----------------------------------------------------------------------------- +** u t i l _ d e c o m p o s e F i l e P a t h +** +** Synopsis: Decompose a file path into its directory, filename and extension. +** +** Parameters: path - the path to decompose. +** dir - a pointer which will be set to the start of the directory. +** name - a pointer which will be set to the start of the name. +** ext - a pointer which will be set to the start of the extension. +** +** Returns: NOTHING +** +** Constraints: path must use '/' and not '\' as directory separators. The pointers +** returned in dir, name, and ext are only valid until the next call +** to util_DecomposePath(). +** +**---------------------------------------------------------------------------*/ +void util_decomposeFilePath( const char* path, char** dir, char** name, char** ext ) +{ + static char buffer[ BUFFER_SIZE + 1 ]; + strncpy( buffer, path, BUFFER_SIZE ); + + *ext = strrchr( buffer, '.' ); + if ( *ext ) + { + /* + * Remove the extension by replacing '.' with a NULL character. + */ + **ext = '\0'; + + /* + * The extension will be in the next position. + */ + (*ext)++; + } + + *name = strrchr( buffer, '/' ); + if ( *name ) + { + /* + * Remove the name by replacing the last '/' with a NULL character. + */ + **name = '\0'; + + /* + * The name will be in the next position. + */ + (*name)++; + + /* + * Set dir to the start of the string and we are done. + */ + *dir = buffer; + } + else + { + /* + * Name must extend to the beginning of the path. Set the name pointer + * accordingly and set dir to null. + */ + *name = buffer; + *dir = 0; + } +} + +/*----------------------------------------------------------------------------- +** u t i l _ d i r n a m e +** +** Synopsis: Determine the directory in a file path. +** +** Parameters: buffer - buffer to recieve directory. +** size - size of buffer. +** path - the path to retrieve the directory from. +** +** Returns: non-zero if successful, zero if buffer is too small to receive +** the directory. +** +** Constraints: path must use '/' and not '\' as directory separators. +** +**---------------------------------------------------------------------------*/ +int util_dirname( char* buffer, int size, const char* path ) +{ + char* d; + char* n; + char* e; + int length; + int result = 0; + + util_decomposeFilePath( path, &d, &n, &e ); + + length = strlen( d ); + if ( length < size ) + { + strcpy( buffer, d ); + result = 1; + } + + return result; +} + +/*----------------------------------------------------------------------------- +** u t i l _ f i l e E x i s t s +** +** Synopsis: Determines if the give file exists. +** +** Parameters: filename - the name of the file to check for existence. +** +** Returns: 0 if file does not exist, non-zero otherwise. +** +** Constraints: +** +**---------------------------------------------------------------------------*/ +int util_fileExists( const char* filename ) +{ + FILE *fp; + + assert( filename ); + + fp = fopen( filename, "r" ); + + if ( fp ) + { + fclose( fp ); + return 1; + } + + return 0; +} + +/*----------------------------------------------------------------------------- +** u t i l _ g e t o p t _ i n i t +** +** Synopsis: Initializes the getopt parser. +** +** Parameters: NONE +** +** Returns: NOTHING +** +** Constraints: NONE +** +** Author: Angus Mackay +** +**---------------------------------------------------------------------------*/ +void util_getopt_init() +{ + util_optind = 1; +} + +/*----------------------------------------------------------------------------- +** u t i l _ g e t o p t +** +** Synopsis: Used to parse command line arguments based on a specified +** syntax. The argument for the current option is stored in +** the global variable "util_optarg". +** +** Parameters: argc - the number of arguments in the array. +** argv - the argumnet array. +** opts - option specifier string. Options can be of two forms: +** boolean flags ( its either there or it isn't ) and +** flag value pairs in which a flag is always followed +** by some value. Options which require an argument +** must be followed by a ":" in the option specifier +** string. So for a command which can have two boolean +** flags, "h" and "i", and two argument flags, "t" and +** "u", the following option specifier string would be +** used: "hit:u:". +** +** Returns: the option character found, or -1 if no more option +** characters. +** +** Constraints: NONE +** +** Author: Angus Mackay +** +**---------------------------------------------------------------------------*/ +int util_getopt( int argc, char* const* argv, const char* opts ) +{ + static int init_done = 0; + static int suboptionpos = 1; + + if(!init_done) { util_getopt_init(); init_done = 1; } + + util_optarg = NULL; + + if(util_optind == argc) + { + /* we are done */ + return(-1); + } + + if(argv[util_optind][0] == '-') + { + char *argp; + + /* test for end of arg marker */ + if(argv[util_optind][1] == '-' && argv[util_optind][2] == '\0') + { + suboptionpos = 1; + util_optind++; + return(-1); + } + + for(argp=&(argv[util_optind][suboptionpos]); *argp != '\0'; argp++) + { + char *optp; + int numcolon = 0; + char *p; + + if((optp=strchr(opts, *argp)) == NULL) + { + if(util_opterr != 0) + { + fprintf(stderr, "%s: illegal option -- %c\n", argv[0], *argp); + } + util_optopt = *argp; + suboptionpos++; + if(argv[util_optind][suboptionpos] == '\0') + { + suboptionpos = 1; + util_optind++; + } + return('?'); + } + + /* zero, one or two colons? */ + for(p=(optp+1); *p == ':'; p++) { numcolon++; } + switch(numcolon) + { + /* no argument */ + case 0: + suboptionpos++; + if(argv[util_optind][suboptionpos] == '\0') + { + suboptionpos = 1; + util_optind++; + } + return(*optp); + break; + + /* manditory argument */ + case 1: + /* the argument is seperated by a space */ + if(argp[1] == '\0') + { + /* ther are more args */ + if(util_optind+1 == argc) + { + suboptionpos++; + if(argv[util_optind][suboptionpos] == '\0') + { + suboptionpos = 1; + util_optind++; + } + if(util_opterr != 0) + { + fprintf(stderr, "%s: option requires an argument -- %c\n", + argv[0], *argp); + } + util_optopt = *argp; + return('?'); + } + + util_optind++; + suboptionpos = 1; + util_optarg = argv[util_optind]; + util_optind++; + return(*optp); + } + + /* the argument is attached */ + util_optarg = argp+1; + suboptionpos = 1; + util_optind++; + return(*optp); + break; + + /* optional argument */ + case 2: + /* the argument is seperated by a space */ + if(argp[1] == '\0') + { + util_optind++; + suboptionpos = 1; + util_optarg = NULL; + return(*optp); + } + + /* the argument is attached */ + suboptionpos = 1; + util_optarg = argp+1; + util_optind++; + return(*optp); + break; + + /* a case of too many colons */ + default: + suboptionpos++; + if(argv[util_optind][suboptionpos] == '\0') + { + suboptionpos = 1; + util_optind++; + } + util_optopt = '?'; + return('?'); + break; + } + } + suboptionpos = 1; + } + else + { + /* we are done */ + return(-1); + } + + /* we shouldn't get here */ + return(-1); +} + +/*----------------------------------------------------------------------------- +** u t i l _ i n d e x +** +** Synopsis: returns a pointer to the first occurrence of the character +** "c" in the string "s". +** +** Parameters: s - the string to search. +** c - the character to search for. +** +** Returns: a pointer to the matched character, or NULL if the character +** is not found. +** +** Constraints: NONE +** +**---------------------------------------------------------------------------*/ +const char* util_index( const char* s, int c ) +{ + const char* result = 0; + const char* sp = 0; + + assert( s ); + + sp = s; + + while ( *sp != '\0' ) + { + if ( *sp == c ) + { + result = sp; + break; + } + + sp++; + } + + return result; +} + +/*----------------------------------------------------------------------------- +** u t i l _ p o s i x F i l e P a t h +** +** Synopsis: Ensures the given path uses POSIX style slashes. +** +** Parameters: path - the path to "posixfy". +** +** Returns: NOTHING +** +** Constraints: NONE +** +**---------------------------------------------------------------------------*/ +void util_posixFilePath( char* path ) +{ + char* pp = path; + while ( *pp ) + { + if ( '\\' == *pp ) *pp = '/'; + pp++; + } +} + +/*----------------------------------------------------------------------------- +** u t i l _ r e p l a c e C h a r a c t e r s +** +** Synopsis: Replace characters in a string. +** +** Parameters: find - the character to find. +** replace - the charcter to replace the found character with. +** string - the string within which to do the find/replace. +** +** Returns: NOTHING +** +** Constraints: NONE +** +**---------------------------------------------------------------------------*/ +void util_replaceCharacters( char find, char replace, char* string ) +{ + char* p = 0; + + if ( string ) + { + while ( p = strchr( string, find ) ) + { + *p = replace; + } + } +} + +/*----------------------------------------------------------------------------- +** u t i l _ r e v e r s e S p a n +** +** Synopsis: Finds the suffix which is composed completely of characters in +** in the spanSet in the specified string. +** +** Example: end = util_ReverseSpan( "name123", "312" ); +** * +** * end now points to "123". +** * +** end = util_ReverseSpan( "name123", "21" ); +** * +** * end would point to NULL because the character "3" is not +** * in the spanSet. +** +** Parameters: string - the string to be searched. +** spanSet - a string of characters that can be in the suffix. +** +** Returns: a pointer to the suffix string, or NULL if there is no +** suffix. +** +** Constraints: NONE +** +**---------------------------------------------------------------------------*/ +const char* util_reverseSpan( const char* string, const char* spanSet ) +{ + const char* sp = 0; + const char* next_sp = 0; + int isEndSpan = 0; + + /* + * Set a pointer to the end of the string to be searched. + */ + sp = string + strlen( string ); + + /* + * If the string passed in is empty, we are done. + */ + if ( sp == string ) return sp; + + while( sp > string && !isEndSpan ) + { + next_sp = sp - 1; + + if ( strchr( spanSet, *next_sp ) ) + { + sp--; + } + else + { + isEndSpan = 1; + } + } + + return sp; +} + +/*----------------------------------------------------------------------------- +** u t i l _ r i n d e x +** +** Synopsis: returns a pointer to the last occurrence of the character +** "c" in the string "s". +** +** Parameters: s - the string to search. +** c - the character to search for. +** +** Returns: a pointer to the matched character, or NULL if the character +** is not found. +** +** Constraints: NONE +** +**---------------------------------------------------------------------------*/ +const char* util_rindex( const char* s, int c ) +{ + const char* result = 0; + const char* sp = 0; + int length; + + assert( s ); + + length = strlen(s); + sp = s + length; + + if ( length > 0 ) + { + while ( sp != s ) + { + sp--; + + if ( *sp == c ) + { + result = sp; + break; + } + } + } + + return result; +} + +/*----------------------------------------------------------------------------- +** u t i l _ s u b s t i t u t e +** +** Synopsis: Substitue strings matchin "find" with "replace" in "string". +** If this cannot be done without exceeding the size of "string" +** An error will be returned and "string" will be as it was +** when util_substitute was originally called. +** +** Parameters: find - the substring to find. +** replace - the substring to insert in place of found strings. +** string - the string to operate on. +** stringSize - the maximum size the string can grow to. +** firstOnly - flag. If non-zero only the first occurence of +** "find" will be replaced. If zero, all occurences +** will be replaced. +** +** Returns: 0 on error, the new size of the string on success. +** +** Constraints: NONE +** +**---------------------------------------------------------------------------*/ +int util_substitute( const char* find, + const char* replace, + char* string, + int stringSize, + int firstOnly + ) +{ + char buffer[ BUFFER_SIZE + 1 ]; + char* sp; + char* bp; + char* p; + int findLength = strlen( find ); + int replaceLength = strlen( replace ); + int count = 0; + int total = 0; + int tooBig = 0; + int status = 0; + + assert( stringSize <= BUFFER_SIZE ); + + bp = buffer; + sp = string; + while( !tooBig && (p = strstr( sp, find )) ) + { + /* + * Determine the number of characters since last find. + * Add to total characters. + * If total characters exceeds "stringSize" then break and return + * error. Otherwise copy characters since last find to buffer. + */ + count = p - sp; + total += count; + if ( total >= stringSize ) + { + tooBig = 1; + continue; + } + strncpy( bp, sp, count ); + bp += count; + *bp = '\0'; + + /* + * If adding the replace string causes buffer to exceed "stringSize" + * break and return error. Otherwise copy the replace string into + * buffer. + */ + total += replaceLength; + if ( total >= stringSize ) + { + tooBig = 1; + continue; + } + strcpy( bp, replace ); + bp += replaceLength; + + /* + * Update the position of sp so that it points to next character + * after the last found "find" string. + */ + sp += count + findLength; + } + + if ( !tooBig ) + { + /* + * Attempt to copy the remaining portion of string into buffer. + * If successful, copy buffer into string and return success. + * Otherwise return error. + */ + total += strlen( sp ); + if ( total < stringSize ) + { + strcpy( bp, sp ); + strcpy( string, buffer ); + status = strlen( string ); + } + } + + return status; +} + |