/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- * * The contents of this file are subject to the Netscape Public License * Version 1.0 (the "NPL"); you may not use this file except in * compliance with the NPL. You may obtain a copy of the NPL at * http://www.mozilla.org/NPL/ * * Software distributed under the NPL is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL * for the specific language governing rights and limitations under the * NPL. * * The Initial Developer of this code under the NPL is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998 Netscape Communications Corporation. All Rights * Reserved. */ #include "xp.h" #include "xp_str.h" #include #include #ifdef PROFILE #pragma profile on #endif #if !defined(XP_WIN) && !defined(XP_OS2) /* keep this out of the winfe */ #if defined(DEBUG) char * NOT_NULL (const char * p) { XP_ASSERT(p); return (char*) p; } #endif #endif #define TOLOWER_TABLE_SIZE 128 PRIVATE uint8 * xp_get_tolower_table() { static uint8 tolower_table[TOLOWER_TABLE_SIZE]; static XP_Bool first_time = TRUE; if(first_time) { int i; first_time = FALSE; /* build the tolower_table */ for(i=0; i < sizeof(tolower_table); i++) { tolower_table[i] = (uint8) tolower((char)i); } } return tolower_table; } PRIVATE uint8 * xp_get_toupper_table() { static uint8 toupper_table[TOLOWER_TABLE_SIZE]; static XP_Bool first_time = TRUE; if(first_time) { int i; first_time = FALSE; /* build the tolower_table */ for(i=0; i < sizeof(toupper_table); i++) { toupper_table[i] = (uint8) toupper((char)i); } } return toupper_table; } #define XP_STR_TOUPPER(c) (c < TOLOWER_TABLE_SIZE ? toupper_table[c] : c) #define XP_STR_TOLOWER(c) (c < TOLOWER_TABLE_SIZE ? tolower_table[c] : c) /* fast table driven tolower routine * * We only deal with 7 bit ascii */ PUBLIC int xp_tolower(int c) { uint8 *tolower_table = xp_get_tolower_table(); return XP_STR_TOLOWER(c); } /* fast table driven toupper routine * * We only deal with 7 bit ascii */ PUBLIC int xp_toupper(int c) { uint8 *toupper_table = xp_get_toupper_table(); return XP_STR_TOUPPER(c); } /* find a substring within a string with a case insensitive search */ PUBLIC char * strcasestr (const char * str, const char * substr) { register const char *pA; register const char *pB; register const char *pC; uint8 *toupper_table = xp_get_toupper_table(); if(!str) return(NULL); for(pA=str; *pA; pA++) { if(XP_STR_TOUPPER(*pA) == XP_STR_TOUPPER(*substr)) { for(pB=pA, pC=substr; ; pB++, pC++) { if(!(*pC)) return((char *)pA); if(!(*pB)) break; if(XP_STR_TOUPPER(*pB) != XP_STR_TOUPPER(*pC)) break; } } } return(NULL); } /* find a char within a specified length string */ PUBLIC char * strnchr (const char * str, const char single, int32 len) { register int count=0; register const char *pA; if(!str) return(NULL); for(pA=str; count < len; pA++, count++) { if(*pA == single) { return((char *)pA); } if(!(*pA)) return(NULL); } return(NULL); } /* find a substring within a specified length string with a case * insensitive search */ PUBLIC char * strncasestr (const char * str, const char * substr, int32 len) { register int count=0; register int count2=0; register const char *pA; register const char *pB; register const char *pC; uint8 *toupper_table = xp_get_toupper_table(); if(!str || !substr) return(NULL); for(pA=str; count < len; pA++, count++) { if(XP_STR_TOUPPER(*pA) == XP_STR_TOUPPER(*substr)) { for(pB=pA, pC=substr, count2=count; count2= destLength. * These versions always null-terminate, which is why they're safe. */ char *XP_STRNCAT_SAFE (char *dest, const char *src, size_t maxToCat) { int destLen; char *result; destLen = XP_STRLEN (dest); result = strncat (dest, src, --maxToCat); dest[destLen + maxToCat] = '\0'; return result; } char *XP_STRNCPY_SAFE (char *dest, const char *src, size_t destLength) { char *result = strncpy (dest, src, --destLength); dest[destLength] = '\0'; return result; } /************************************************* The following functions are used to implement a thread safe strtok *************************************************/ /* * Get next token from string *stringp, where tokens are (possibly empty) * strings separated by characters from delim. Tokens are separated * by exactly one delimiter iff the skip parameter is false; otherwise * they are separated by runs of characters from delim, because we * skip over any initial `delim' characters. * * Writes NULs into the string at *stringp to end tokens. * delim will usually, but need not, remain CONSTant from call to call. * On return, *stringp points past the last NUL written (if there might * be further tokens), or is NULL (if there are definitely no more tokens). * * If *stringp is NULL, strtoken returns NULL. */ static char *strtoken_r(char ** stringp, const char *delim, int skip) { char *s; const char *spanp; int c, sc; char *tok; if ((s = *stringp) == NULL) return (NULL); if (skip) { /* * Skip (span) leading delimiters (s += strspn(s, delim)). */ cont: c = *s; for (spanp = delim; (sc = *spanp++) != 0;) { if (c == sc) { s++; goto cont; } } if (c == 0) { /* no token found */ *stringp = NULL; return (NULL); } } /* * Scan token (scan for delimiters: s += strcspn(s, delim), sort of). * Note that delim must have one NUL; we stop if we see that, too. */ for (tok = s;;) { c = *s++; spanp = delim; do { if ((sc = *spanp++) == c) { if (c == 0) s = NULL; else s[-1] = 0; *stringp = s; return( (char *) tok ); } } while (sc != 0); } /* NOTREACHED */ } char *XP_STRTOK_R(char *s1, const char *s2, char **lasts) { if (s1) *lasts = s1; return (strtoken_r(lasts, s2, 1)); } #ifdef PROFILE #pragma profile off #endif