habeebi
unknown
plain_text
a year ago
20 kB
4
Indexable
#define GSCVSID "$Header: /home/cvs/ficc/liberty/src/kool_ade/src/string.c,v 1.45 2014/07/20 09:33:23 sharps Exp $" /**************************************************************** ** ** STRING.C - Lots of little string functions ** ** Copyright 1994 - Goldman, Sachs & Co. - New York ** ** $Log: string.c,v $ ** Revision 1.45 2014/07/20 09:33:23 sharps ** IS:6012-539693 Use GS_PRI.SIZE macros ** ** Revision 1.44 2013/01/28 10:05:44 guptans ** IS:6012-367102 Added rStrIStr ** ** Revision 1.43 2012/11/16 14:56:27 chex ** IS:6012-345049 remove unused backout ** ** Revision 1.42 2012/09/13 15:47:21 chex ** IS:6012-345049 remove string.h since it builds just fine without it ** ** Revision 1.41 2012/09/12 19:59:23 chex ** IS:6012-345049 string.c is included in autofunc's build. Use getenv when building autofunc and backout when building others ** ** Revision 1.40 2012/09/11 19:56:23 chex ** IS:6012-345049 use strcasestr to do case-insensitive string search on Linux ** ** Revision 1.39 2010/10/07 14:27:02 uschoj ** IS:6012-132636 Make it build on linux64_g4 ** ** Revision 1.38 2010/06/01 11:47:45 keatlj ** IS:6012-93680 show kool_ade on the heap ** ** Revision 1.37 2009/02/24 16:23:09 uschoj ** IS:6012-18954 gcc4 fixes ** ** Revision 1.36 2007/10/30 16:41:12 burchk ** IS:822506 Remove StrToUpper and StrToLower, since we already have StrLower ** and StrUpper ** ****************************************************************/ // Need this test so it can build in autofunc (grrrr) #ifndef BUILDING_KOOL_ADE #define BUILDING_KOOL_ADE #endif #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #define INCL_ALLOCA #define INCL_FILEIO #include <portable.h> #include <portable/gsinttypes.h> #include <cctype> #include <cstdarg> #include <cstdlib> #include <strings.h> #include <err.h> #include <kool_ade.h> #include <vccrtdbg.h> /**************************************************************** ** Routine: StrIStr ** Returns: Pointer to first occurrence of String2 in String1 ** Summary: Case insensitive strstr function ** Action : Case insensitive strstr function ****************************************************************/ char *StrIStr( register char *String1, const char *String2 ) { #if CC_OS == CC_OS_UNIX && CC_UNIX_REV == CC_UNIX_LINUX return !*String2 ? 0 : strcasestr( String1, String2 ); #endif register char Lower = (char)tolower(*String2), Upper = (char)toupper(*String2); size_t Len = strlen(String2); if( !Len ) return NULL; for( ; *String1; String1++) if( *String1 == Lower || *String1 == Upper ) if( strncasecmp( String1+1, String2+1, Len-1 ) == 0 ) return String1; return NULL; } /**************************************************************** ** Routine: rStrIStr ** Returns: pointer to last occurrence of String2 in String1 < Pos ** Action : case insensitive rstrstr function ****************************************************************/ char *rStrIStr( char *String1, int Limit, char const *String2 ) { char *Prev = NULL, *Curr, *CutOff = String1 + Limit - strlen( String2 ) + 1; while( TRUE ) { Curr = StrIStr( String1, String2 ); if( !Curr || Curr > CutOff ) break; Prev = Curr; String1 = Curr + 1; } return( Prev ); } /**************************************************************** ** Routine: StrPaste ** Returns: Allocated string ** Summary: Paste a bunch of strings together ** Action : StrPaste pastes a list of strings together into one ** allocated string. StrPaste( "a", "b", "c", NULL ) ** returns "abc". ** NOTE: Final argument MUST be NULL ** NOTE: The returned string must be free()d later. ****************************************************************/ char *StrPaste( const char *First, ... ) { va_list Marker; size_t Len; char *Output, *Pos; const char *Arg; Len = 0; va_start( Marker, First ); for( Arg = First; Arg; Arg = va_arg( Marker, const char *)) Len += strlen( Arg ); va_end( Marker ); Output = Pos = (char *)malloc( Len+1 ); va_start( Marker, First ); for( Arg = First; Arg; Arg = va_arg( Marker, const char *)) { strcpy( Pos, Arg ); Pos += strlen( Pos ); } va_end( Marker ); return Output; } /**************************************************************** ** Routine: StrReplace ** Returns: Allocated, substituted string ** Summary: Simple substring replacement ** Action : StrReplace is a simple substring replace function ** which replaces SubStr within Input with Replace. ** Flags is a combination of the following values: ** REPL_GLOBAL - Global replace within Input ** REPL_FREE - Free Input argument ** REPL_CASE - Case sensitive search ** (Default is to ignore case) ** The REPL_FREE flag allow multiple calls to StrReplace ** to be easily chained. ** Str = StrReplace( Str, "Foo", "Bar", REPL_FREE ); ** Str = StrReplace( Str, "Cow", "Pig", REPL_FREE ); ****************************************************************/ char *StrReplace( char *Input, const char *SubStr, const char *Replace, int Flags ) { size_t SubLen = strlen( SubStr ), RepLen = strlen( Replace ); char *InPos, *Tmp, *Found, *Output; size_t OutLen = 0, NewLen, InLen; InPos = Input; Output = strdup( "" ); while( 1 ) { if( Flags & REPL_CASE ) Found = strstr( InPos, SubStr ); else Found = StrIStr( InPos, SubStr ); if( !Found ) { OutLen += strlen( InPos ); Output = (char *)realloc( Output, OutLen + 1 ); strcat( Output, InPos ); break; } InLen = static_cast<size_t>( Found - InPos ); NewLen = OutLen + InLen + RepLen; Output = (char *)realloc( Output, NewLen + 1 ); Tmp = Output + OutLen; strncpy( Tmp, InPos, InLen ); strcpy( Tmp+InLen, Replace ); InPos = Found + SubLen; OutLen = NewLen; if( !(Flags & REPL_GLOBAL) ) { OutLen += strlen( InPos ); Output = (char *)realloc( Output, OutLen + 1 ); strcat( Output, InPos ); break; } } if( Flags & REPL_FREE ) free( Input ); return Output; } /**************************************************************** ** Routine: StrWildMatch ** Returns: TRUE - String matches Pattern ** FALSE - no match ** Action : Perform wildcard match using '*' and '?' ****************************************************************/ int StrWildMatch( const char *Pattern, const char *String ) { int Pat, Str; while( 0 != (Pat = *Pattern )) { if( Pat == '*' ) { Pattern++; if( !*Pattern ) return TRUE; for( ; *String; String++ ) if( StrWildMatch( Pattern, String )) return TRUE; return FALSE; } if( Pat == '?' ) { Pattern++; String++; continue; } if( !(Str = *String )) return FALSE; if( toupper( Pat ) != toupper( Str ) ) return FALSE; Pattern++; String++; } return *Pattern == *String; } /**************************************************************** ** Routine: StrRTrim ** Returns: String pointer passed in ** Summary: Trim trailing spaces in place ** Action : StrRTrim trims spaces from the right end of a ** string. The string is modified in place. ** Example: // Modify a copy of a string ** Copy = StrRTrim( strdup( "a string " )); ** ** // Modify a string in place ** InPlace = StrRTrim( "another string " ); ****************************************************************/ char *StrRTrim( char *Str ) { ssize_t Pos; for( Pos = static_cast<ssize_t>( strlen( Str ) ); --Pos >= 0 && isspace( Str[ Pos ] ); ); if( isspace( Str[ Pos + 1 ] ) ) Str[ Pos + 1 ] = '\0'; return Str; } /**************************************************************** ** Routine: StrLTrim ** Returns: String passed in ** Summary: Trim leading spaces in place ** Action : StrLTrim trims spaces from the left end of a ** string. The string is modified in place. ** Example: // Modify a copy of a string ** Copy = StrLTrim( strdup( " a string" )); ** ** // Modify a string in place ** InPlace = StrLTrim( " another string" ); ****************************************************************/ char *StrLTrim( char *Str ) { char *FirstNonSpace; for( FirstNonSpace = Str; isspace( *FirstNonSpace ); FirstNonSpace++ ); if( FirstNonSpace != Str ) memmove( Str, FirstNonSpace, strlen( FirstNonSpace ) + 1 ); return Str; } /**************************************************************** ** Routine: StrBegins ** Returns: TRUE or FALSE ** Summary: Does Str begin with BegStr? ** Action : Compare the beginning of Str with EndStr and return ** TRUE if they match. ** Example: // These are TRUE ** StrBegins( "Long String", "Long" ); ** StrBegins( "Long String", "Long String" ); ** ** // These are FALSE ** StrBegins( "Long String", "long" ); ** StrBegins( "Long", "Long String" ); ** SeeAlso: StrEnds, StrIBegins, StrIEnds ****************************************************************/ int StrBegins( const char *Str, const char *BegStr ) { size_t Len1 = strlen( Str ), Len2 = strlen( BegStr ); if( Len1 < Len2 ) return FALSE; return 0 == strncmp( Str, BegStr, Len2 ); } /**************************************************************** ** Routine: StrEnds ** Returns: TRUE or FALSE ** Summary: Does Str end with EndStr? ** Action : Compare the end of Str with EndStr and return TRUE ** if they match. ** Example: // These are TRUE ** StrEnds( "Long String", "ing" ); ** StrEnds( "Long String", "Long String" ); ** ** // These are FALSE ** StrEnds( "Long String", "string" ); ** StrEnds( "ing", "Long String" ); ** SeeAlso: StrBegins, StrIBegins, StrIEnds ****************************************************************/ int StrEnds( const char *Str, const char *EndStr ) { size_t Len1 = strlen( Str ), Len2 = strlen( EndStr ); if( Len1 < Len2 ) return FALSE; return 0 == strcmp( Str + Len1 - Len2, EndStr ); } /**************************************************************** ** Routine: StrIBegins ** Returns: TRUE or FALSE ** Summary: Does Str begin with BegStr? ** Action : Compare the beginning of Str with EndStr and return ** TRUE if they match. ** Example: // These are TRUE ** StrIBegins( "Long String", "Long" ); ** StrIBegins( "Long String", "Long String" ); ** StrIBegins( "Long String", "long" ); ** ** // These are FALSE ** StrIBegins( "Long", "Long String" ); ** SeeAlso: StrBegins, StrIEnds, StrIEnds ****************************************************************/ int StrIBegins( const char *Str, const char *BegStr ) { size_t Len1 = strlen( Str ), Len2 = strlen( BegStr ); if( Len1 < Len2 ) return FALSE; return 0 == strncasecmp( Str, BegStr, Len2 ); } /**************************************************************** ** Routine: StrIEnds ** Returns: TRUE or FALSE ** Summary: Does Str end with EndStr? ** Action : Compare the end of Str with EndStr and return TRUE ** if they match. ** Example: // These are TRUE ** StrIEnds( "Long String", "ing" ); ** StrIEnds( "Long String", "Long String" ); ** StrIEnds( "Long String", "string" ); ** ** // These are FALSE ** StrIEnds( "ing", "Long String" ); ** SeeAlso: StrBegins, StrEnds, StrIBegins ****************************************************************/ int StrIEnds( const char *Str, const char *EndStr ) { size_t Len1 = strlen( Str ), Len2 = strlen( EndStr ); if( Len1 < Len2 ) return FALSE; return 0 == strcasecmp( Str + Len1 - Len2, EndStr ); } /**************************************************************** ** Routine: StrChrCount ** Returns: Count occurrences of characters ** Action : Returns the number of occurrences of characters ** from CharSet in String ** ** You can set End == -1 to mean end of string ****************************************************************/ size_t StrChrCount( const char *String, const char *CharSet, ssize_t Start, ssize_t End ) { size_t Len = strlen( String ); size_t Count = 0; const char *StrEnd; if( End < 0 || static_cast<size_t>( End ) > Len ) End = static_cast<ssize_t>( Len ); if( Start < 0 ) Start = 0; if( static_cast<size_t>( Start ) >= Len ) return 0; StrEnd = String + End; for( String += Start; ( String += strcspn( String, CharSet ) ) < StrEnd && *String; ++String ) ++Count; return Count; } /**************************************************************** ** Routine: StrTokenize ** Returns: Count of tokens found, -1 on error ** Action : Parse a space/quote delimited line, ala slang.dat. ** Modifies String and fills in Tokens with pointers ** to each token in String. ** ** Handles spaces, tabs, and quoted strings. Ignores ** comments starting with //. A blank line or a line ** with only a comment returns a token count of zero. ** ** Example: char *Tokens[ 9 ], ** Example[] = "Example\t\"quoted text\" foo"; ** StrTokenize( Example, 8, Tokens ); ****************************************************************/ int StrTokenize( char *String, // Input string (will be modified) int MaxTokens, char **Tokens // [ MaxTokens+1 ] NULL terminated on return ) { int TokenCount = 0; while( *String ) { // Skip spaces and tabs while( *String && ISSPACE( *String )) String++; // Check for blank field or comment if( *String == '\0' || ( *String == '/' && String[1] == '/' )) break; // Check for too many tokens if( TokenCount >= MaxTokens ) { Err( ERR_INVALID_STRING , "StrTokenize: @, too many tokens [max: %d]", MaxTokens ); return -1; } // Parse quoted or non-quoted field if( *String == '"' ) { String++; Tokens[ TokenCount++ ] = String; while( *String && *String != '"' ) String++; if( *String != '"' ) { Err( ERR_INVALID_STRING , "StrTokenize: @, missing closing double quote" ); return -1; } *String++ = '\0'; } else { Tokens[ TokenCount++ ] = String; while( *String && !ISSPACE( *String )) String++; if( *String ) *String++ = '\0'; } } Tokens[ TokenCount ] = NULL; return TokenCount; } /**************************************************************** ** Routine: StrQuoteUrl ** Returns: allocated string quoted for URL display ** Action : Quote URL special characters ****************************************************************/ char *StrQuoteUrl( const char *Str ) { char *NewStr, *NewStrBuf, c; NewStr = NewStrBuf = (char *) malloc( strlen( Str ) * 3 + 1 ); while( (c = *Str++) ) switch( c ) { case ' ': *NewStr++ = '+'; break; case '/': case '%': case '+': case '#': case '?': case ',': case ':': case '&': case '"': case '\'': NewStr += sprintf( NewStr, "%%%02x", c ); break; default: *NewStr++ = c; break; }; *NewStr++ = '\0'; return NewStrBuf; } /**************************************************************** ** Routine: StrQuoteHtml ** Returns: allocated string quoted for HTML display ** Action : Quote HTML special characters ****************************************************************/ char *StrQuoteHtml( const char *HtmlStr ) { const char *Str; char *NewStr; char *NewStrBuf; size_t NewLen = 1; for( Str = HtmlStr; *Str != '\0'; ++Str ) { switch( *Str ) { case '<': case '>': case '&': case '"': NewLen += 6; // Largest of the replacement strings break; default: NewLen++; break; } } NewStr = (char *) alloca( NewLen+1 ); NewStrBuf = NewStr; for( Str = HtmlStr; *Str != '\0'; ++Str ) { char const* AppendMe = NULL; switch( *Str ) { case '<': AppendMe = "<"; break; case '>': AppendMe = ">"; break; case '&': AppendMe = "&"; break; case '"': AppendMe = """; break; default: *NewStr++ = *Str; break; } if( AppendMe ) { strcpy( NewStr, AppendMe ); NewStr += strlen( NewStr ); } } *NewStr = '\0'; return strdup( NewStrBuf ); } static int hexToInt( char hex ) { if( hex >= '0' && hex <= '9' ) return( hex - '0' ); if( hex >= 'A' && hex <= 'F' ) return( hex - 'A' + 10 ); if( hex >= 'a' && hex <= 'f' ) return( hex - 'a' + 10 ); return -1; } /**************************************************************** ** Routine: StrFromUrl ** Returns: allocated string ** Action : Convert a URL-quoted string to a plain string ****************************************************************/ char *StrFromUrl( const char *Str // URL-quoted string (w/ + & %20 ) { char *NewStr, *NewStrBuf, c; NewStr = NewStrBuf = (char *) malloc( strlen( Str ) + 1 ); while( (c = *Str++) ) switch( c ) { case '%': if( *Str && *(Str + 1) && isxdigit( *Str ) && isxdigit( *(Str + 1) ) ) { *NewStr++ = (char) (0x10 * hexToInt( *Str ) + hexToInt( *(Str + 1) ) ); Str += 2; } else *NewStr++ = '%'; break; case '+': *NewStr++ = ' '; break; default: *NewStr++ = c; break; }; *NewStr++ = '\0'; return NewStrBuf; } /**************************************************************** ** Routine: StrBaseName ** Returns: Pointer to file part of Path ** Action : Returns string following final file separator. If ** finds none, return Path ** Params : Path - Path passed as String ****************************************************************/ const char *StrBaseName( const char *Path ) { const char *p, *d; if( !Path ) return( NULL ); for( p = Path + strlen( Path ); p >= Path; p-- ) for( d = FILENAME_SEPARATORS; *d; d++ ) if( *p == *d ) return( p+1 ); return( Path ); } /**************************************************************** ** Routine: StringToUniqueId ** Returns: uint32 from input string, or 0 on error ** Action : Convert numeric string to unique id. 0 is not a valid unique id ** so return that on error. ** NOTE: This is not intended as a general purpose conversion routine: ** it's specific to secdb unique IDs. ****************************************************************/ uint32_t StringToUniqueId( const char *Str ) { size_t Len = strlen( Str ); // String must not be blank, or > 10 chars (max size of decimal representation of uint32_t) if( 0 == Len ) return static_cast<uint32_t>( Err( ERR_INVALID_ARGUMENTS, "StringToUniqueId: Input string blank" ) ); const size_t MaxLen = 10; if( Len > MaxLen ) return static_cast<uint32_t>( Err( ERR_INVALID_ARGUMENTS, "StringToUniqueId: Input string ('%s') too long (%" GS_PRIuSIZE ">%" GS_PRIuSIZE "d)", Str, Len, MaxLen ) ); // Must be digits only for( const char *p = Str; *p; ++p ) if( !ISDIGIT( *p ) ) return static_cast<uint32_t>( Err( ERR_INVALID_ARGUMENTS, "StringToUniqueId: Input string ('%s') contains non-digit %c", Str, *p ) ); uint32_t Id; if( 1 != sscanf( Str, "%u", &Id ) ) return static_cast<uint32_t>( Err( ERR_INVALID_ARGUMENTS, "StringToUniqueId: Failed to parse input string ('%s')", Str ) ); // Now check that it matches the input (a bit paranoid) char Str1[ MaxLen + 1 ]; sprintf( Str1, "%u", Id ); if( strcmp( Str, Str1 ) ) return static_cast<uint32_t>( Err( ERR_INVALID_ARGUMENTS, "StringToUniqueId: Consistency check failed (input='%s', id=%u, id as string='%s')", Str, Id, Str1 ) ); return Id; }
Editor is loading...
Leave a Comment