home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / lib / xp / xp_str.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  12.2 KB  |  556 lines

  1. /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19.  
  20. #include "xp.h"
  21. #include "xp_str.h"
  22. #include <ctype.h>
  23. #include <stdarg.h>
  24.  
  25. #ifdef PROFILE
  26. #pragma profile on
  27. #endif
  28.  
  29. #if !defined(XP_WIN) && !defined(XP_OS2) /* keep this out of the winfe */
  30. #if defined(DEBUG)
  31.  
  32. char *
  33. NOT_NULL (const char * p)
  34. {
  35.     XP_ASSERT(p);
  36.     return (char*) p;
  37. }
  38.  
  39. #endif
  40. #endif
  41.  
  42. #define TOLOWER_TABLE_SIZE 128
  43.  
  44. PRIVATE uint8 *
  45. xp_get_tolower_table()
  46. {
  47.     static uint8 tolower_table[TOLOWER_TABLE_SIZE];
  48.     static XP_Bool first_time = TRUE;
  49.  
  50.     if(first_time)
  51.     {
  52.         int i;
  53.         first_time = FALSE;
  54.  
  55.         /* build the tolower_table */
  56.         for(i=0; i < sizeof(tolower_table); i++)
  57.         {
  58.             tolower_table[i] = (uint8) tolower((char)i);
  59.         }
  60.     }
  61.  
  62.     return tolower_table;
  63. }
  64.  
  65. PRIVATE uint8 *
  66. xp_get_toupper_table()
  67. {
  68.     static uint8 toupper_table[TOLOWER_TABLE_SIZE];
  69.     static XP_Bool first_time = TRUE;
  70.  
  71.     if(first_time)
  72.     {
  73.         int i;
  74.         first_time = FALSE;
  75.  
  76.         /* build the tolower_table */
  77.         for(i=0; i < sizeof(toupper_table); i++)
  78.         {
  79.             toupper_table[i] = (uint8) toupper((char)i);
  80.         }
  81.     }
  82.  
  83.     return toupper_table;
  84. }
  85.  
  86. #define XP_STR_TOUPPER(c) (c < TOLOWER_TABLE_SIZE ? toupper_table[c] : c)
  87. #define XP_STR_TOLOWER(c) (c < TOLOWER_TABLE_SIZE ? tolower_table[c] : c)
  88.  
  89. /* fast table driven tolower routine 
  90.  *
  91.  * We only deal with 7 bit ascii
  92.  */
  93. PUBLIC int
  94. xp_tolower(int c)
  95. {
  96.     uint8 *tolower_table = xp_get_tolower_table();
  97.  
  98.     return XP_STR_TOLOWER(c);
  99. }
  100.  
  101. /* fast table driven toupper routine 
  102.  *
  103.  * We only deal with 7 bit ascii
  104.  */
  105. PUBLIC int
  106. xp_toupper(int c)
  107. {
  108.     uint8 *toupper_table = xp_get_toupper_table();
  109.  
  110.     return XP_STR_TOUPPER(c);
  111. }
  112.  
  113. /* find a substring within a string with a case insensitive search
  114.  */
  115. PUBLIC char *
  116. strcasestr (const char * str, const char * substr)
  117. {
  118.     register const char *pA;
  119.     register const char *pB;
  120.     register const char *pC;
  121.     uint8 *toupper_table = xp_get_toupper_table();
  122.  
  123.     if(!str)
  124.         return(NULL);
  125.     
  126.     for(pA=str; *pA; pA++)
  127.       {
  128.         if(XP_STR_TOUPPER(*pA) == XP_STR_TOUPPER(*substr))
  129.           {
  130.             for(pB=pA, pC=substr; ; pB++, pC++)
  131.               {
  132.                 if(!(*pC))
  133.                     return((char *)pA);
  134.  
  135.                 if(!(*pB))
  136.                     break;
  137.  
  138.                 if(XP_STR_TOUPPER(*pB) != XP_STR_TOUPPER(*pC))
  139.                     break;
  140.               }
  141.           }
  142.       }
  143.  
  144.     return(NULL);
  145. }
  146.  
  147. /* find a char within a specified length string
  148.  */
  149. PUBLIC char *
  150. strnchr (const char * str, const char single, int32 len)
  151. {
  152.     register int count=0;
  153.     register const char *pA;
  154.  
  155.     if(!str)
  156.         return(NULL);
  157.    
  158.     for(pA=str; count < len; pA++, count++)
  159.       {
  160.         if(*pA == single)
  161.           {
  162.              return((char *)pA);
  163.           }
  164.  
  165.         if(!(*pA))
  166.             return(NULL);
  167.       }
  168.  
  169.     return(NULL);
  170. }
  171.  
  172. /* find a substring within a specified length string with a case 
  173.  * insensitive search
  174.  */
  175. PUBLIC char *
  176. strncasestr (const char * str, const char * substr, int32 len)
  177. {
  178.     register int count=0;
  179.     register int count2=0;
  180.     register const char *pA;
  181.     register const char *pB;
  182.     register const char *pC;
  183.     uint8 *toupper_table = xp_get_toupper_table();
  184.  
  185.     if(!str || !substr)
  186.         return(NULL);
  187.    
  188.     for(pA=str; count < len; pA++, count++)
  189.       {
  190.         if(XP_STR_TOUPPER(*pA) == XP_STR_TOUPPER(*substr))
  191.           {
  192.             for(pB=pA, pC=substr, count2=count; count2<len; 
  193.                                                     count2++,pB++,pC++)
  194.               {
  195.                 if(!(*pC))
  196.                     return((char *)pA);
  197.  
  198.                 if(!(*pB))
  199.                     break;
  200.  
  201.                 if(XP_TO_UPPER(*pB) != XP_TO_UPPER(*pC))
  202.                     break;
  203.               }
  204.           }
  205.       }
  206.  
  207.     return(NULL);
  208. }
  209.  
  210.  
  211. /*    compare strings in a case insensitive manner
  212. */
  213. PUBLIC int 
  214. strcasecomp (const char* one, const char *two)
  215. {
  216.     const char *pA;
  217.     const char *pB;
  218.     uint8 *toupper_table = xp_get_toupper_table();
  219.  
  220.     for(pA=one, pB=two; *pA && *pB; pA++, pB++) 
  221.       {
  222.         register int tmp = XP_STR_TOUPPER(*pA) - XP_STR_TOUPPER(*pB);
  223.         if (tmp) 
  224.             return tmp;
  225.       }
  226.  
  227.     if (*pA) 
  228.         return 1;    
  229.     if (*pB) 
  230.         return -1;
  231.     return 0;    
  232. }
  233.  
  234.  
  235. /*    compare strings in a case insensitive manner with a length limit
  236. */
  237. PUBLIC int 
  238. strncasecomp (const char* one, const char * two, int n)
  239. {
  240.     const char *pA;
  241.     const char *pB;
  242.     uint8 *toupper_table = xp_get_toupper_table();
  243.     
  244.     for(pA=one, pB=two;; pA++, pB++) 
  245.       {
  246.         int tmp;
  247.         if (pA == one+n) 
  248.             return 0;    
  249.         if (!(*pA && *pB)) 
  250.             return *pA - *pB;
  251.         tmp = XP_STR_TOUPPER(*pA) - XP_STR_TOUPPER(*pB);
  252.         if (tmp) 
  253.             return tmp;
  254.       }
  255. }
  256.  
  257. /*    Allocate a new copy of a block of binary data, and returns it
  258.  */
  259. PUBLIC char * 
  260. NET_BACopy (char **destination, const char *source, size_t length)
  261. {
  262.     if(*destination)
  263.       {
  264.         XP_FREE(*destination);
  265.         *destination = 0;
  266.       }
  267.  
  268.     if (! source)
  269.       {
  270.         *destination = NULL;
  271.       }
  272.     else 
  273.       {
  274.         *destination = (char *) XP_ALLOC (length);
  275.         if (*destination == NULL) 
  276.             return(NULL);
  277.         XP_MEMCPY(*destination, source, length);
  278.       }
  279.     return *destination;
  280. }
  281.  
  282. /*    binary block Allocate and Concatenate
  283.  *
  284.  *   destination_length  is the length of the existing block
  285.  *   source_length   is the length of the block being added to the 
  286.  *   destination block
  287.  */
  288. PUBLIC char * 
  289. NET_BACat (char **destination, 
  290.            size_t destination_length, 
  291.            const char *source, 
  292.            size_t source_length)
  293. {
  294.     if (source) 
  295.       {
  296.         if (*destination) 
  297.           {
  298.               *destination = (char *) XP_REALLOC (*destination, destination_length + source_length);
  299.             if (*destination == NULL) 
  300.               return(NULL);
  301.  
  302.             XP_MEMMOVE (*destination + destination_length, source, source_length);
  303.  
  304.           } 
  305.         else 
  306.           {
  307.             *destination = (char *) XP_ALLOC (source_length);
  308.             if (*destination == NULL) 
  309.               return(NULL);
  310.  
  311.             XP_MEMCPY(*destination, source, source_length);
  312.           }
  313.     }
  314.  
  315.   return *destination;
  316. }
  317.  
  318. /*    Very similar to strdup except it free's too
  319.  */
  320. PUBLIC char * 
  321. NET_SACopy (char **destination, const char *source)
  322. {
  323.     if(*destination)
  324.       {
  325.         XP_FREE(*destination);
  326.         *destination = 0;
  327.       }
  328.     if (! source)
  329.       {
  330.         *destination = NULL;
  331.       }
  332.     else 
  333.       {
  334.         *destination = (char *) XP_ALLOC (XP_STRLEN(source) + 1);
  335.         if (*destination == NULL) 
  336.              return(NULL);
  337.  
  338.         XP_STRCPY (*destination, source);
  339.       }
  340.     return *destination;
  341. }
  342.  
  343. /*  Again like strdup but it concatinates and free's and uses Realloc
  344. */
  345. PUBLIC char *
  346. NET_SACat (char **destination, const char *source)
  347. {
  348.     if (source && *source)
  349.       {
  350.         if (*destination)
  351.           {
  352.             int length = XP_STRLEN (*destination);
  353.             *destination = (char *) XP_REALLOC (*destination, length + XP_STRLEN(source) + 1);
  354.             if (*destination == NULL)
  355.             return(NULL);
  356.  
  357.             XP_STRCPY (*destination + length, source);
  358.           }
  359.         else
  360.           {
  361.             *destination = (char *) XP_ALLOC (XP_STRLEN(source) + 1);
  362.             if (*destination == NULL)
  363.                 return(NULL);
  364.  
  365.              XP_STRCPY (*destination, source);
  366.           }
  367.       }
  368.     return *destination;
  369. }
  370.  
  371. /* remove front and back white space
  372.  * modifies the original string
  373.  */
  374. PUBLIC char *
  375. XP_StripLine (char *string)
  376. {
  377.     char * ptr;
  378.  
  379.     /* remove leading blanks */
  380.     while(*string=='\t' || *string==' ' || *string=='\r' || *string=='\n')
  381.         string++;    
  382.  
  383.     for(ptr=string; *ptr; ptr++)
  384.         ;   /* NULL BODY; Find end of string */
  385.  
  386.     /* remove trailing blanks */
  387.     for(ptr--; ptr >= string; ptr--) 
  388.       {
  389.         if(*ptr=='\t' || *ptr==' ' || *ptr=='\r' || *ptr=='\n') 
  390.             *ptr = '\0'; 
  391.         else 
  392.             break;
  393.       }
  394.  
  395.     return string;
  396. }
  397.  
  398. /************************************************************************/
  399.  
  400. char *XP_AppendStr(char *in, const char *append)
  401. {
  402.     int alen, inlen;
  403.  
  404.     alen = XP_STRLEN(append);
  405.     if (in) {
  406.         inlen = XP_STRLEN(in);
  407.         in = (char*) XP_REALLOC(in,inlen+alen+1);
  408.         if (in) {
  409.             XP_MEMCPY(in+inlen, append, alen+1);
  410.         }
  411.     } else {
  412.         in = (char*) XP_ALLOC(alen+1);
  413.         if (in) {
  414.             XP_MEMCPY(in, append, alen+1);
  415.         }
  416.     }
  417.     return in;
  418. }
  419.  
  420. char *XP_Cat(char *a0, ...)
  421. {
  422.     va_list ap;
  423.     char *a, *result, *cp;
  424.     int len;
  425.  
  426.     /* Count up string length's */
  427.     va_start(ap, a0);
  428.     len = 1;
  429.     a = a0;
  430.     while (a != (char*) NULL) {
  431.         len += XP_STRLEN(a);
  432.         a = va_arg(ap, char*);
  433.     }
  434.     va_end(ap);
  435.  
  436.     /* Allocate memory and copy strings */
  437.     va_start(ap, a0);
  438.     result = cp = (char*) XP_ALLOC(len);
  439.     if (!cp) return 0;
  440.     a = a0;
  441.     while (a != (char*) NULL) {
  442.         len = XP_STRLEN(a);
  443.         XP_MEMCPY(cp, a, len);
  444.         cp += len;
  445.         a = va_arg(ap, char*);
  446.     }
  447.     *cp = 0;
  448.     va_end(ap);
  449.     return result;
  450. }
  451.  
  452. /************************************************************************
  453.  * These are "safe" versions of the runtime library routines. The RTL
  454.  * versions do not null-terminate dest IFF strlen(src) >= destLength.
  455.  * These versions always null-terminate, which is why they're safe.
  456.  */
  457.  
  458. char *XP_STRNCAT_SAFE (char *dest, const char *src, size_t maxToCat)
  459. {
  460.     int destLen; 
  461.     char *result; 
  462.  
  463.     destLen = XP_STRLEN (dest);
  464.     result = strncat (dest, src, --maxToCat);
  465.     dest[destLen + maxToCat] = '\0';
  466.     return result;
  467. }
  468.  
  469. char *XP_STRNCPY_SAFE (char *dest, const char *src, size_t destLength)
  470. {
  471.     char *result = strncpy (dest, src, --destLength);
  472.     dest[destLength] = '\0';
  473.     return result;
  474. }
  475.  
  476. /*************************************************
  477.    The following functions are used to implement
  478.    a thread safe strtok
  479.  *************************************************/
  480. /*
  481.  * Get next token from string *stringp, where tokens are (possibly empty)
  482.  * strings separated by characters from delim.  Tokens are separated
  483.  * by exactly one delimiter iff the skip parameter is false; otherwise
  484.  * they are separated by runs of characters from delim, because we
  485.  * skip over any initial `delim' characters.
  486.  *
  487.  * Writes NULs into the string at *stringp to end tokens.
  488.  * delim will usually, but need not, remain CONSTant from call to call.
  489.  * On return, *stringp points past the last NUL written (if there might
  490.  * be further tokens), or is NULL (if there are definitely no more tokens).
  491.  *
  492.  * If *stringp is NULL, strtoken returns NULL.
  493.  */
  494. static 
  495. char *strtoken_r(char ** stringp, const char *delim, int skip)
  496. {
  497.     char *s;
  498.     const char *spanp;
  499.     int c, sc;
  500.     char *tok;
  501.  
  502.     if ((s = *stringp) == NULL)
  503.         return (NULL);
  504.  
  505.     if (skip) {
  506.         /*
  507.          * Skip (span) leading delimiters (s += strspn(s, delim)).
  508.          */
  509.     cont:
  510.         c = *s;
  511.         for (spanp = delim; (sc = *spanp++) != 0;) {
  512.             if (c == sc) {
  513.                 s++;
  514.                 goto cont;
  515.             }
  516.         }
  517.         if (c == 0) {        /* no token found */
  518.             *stringp = NULL;
  519.             return (NULL);
  520.         }
  521.     }
  522.  
  523.     /*
  524.      * Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
  525.      * Note that delim must have one NUL; we stop if we see that, too.
  526.      */
  527.     for (tok = s;;) {
  528.         c = *s++;
  529.         spanp = delim;
  530.         do {
  531.             if ((sc = *spanp++) == c) {
  532.                 if (c == 0)
  533.                     s = NULL;
  534.                 else
  535.                     s[-1] = 0;
  536.                 *stringp = s;
  537.                 return( (char *) tok );
  538.             }
  539.         } while (sc != 0);
  540.     }
  541.     /* NOTREACHED */
  542. }
  543.  
  544.  
  545. char *XP_STRTOK_R(char *s1, const char *s2, char **lasts)
  546. {
  547.     if (s1)
  548.         *lasts = s1;
  549.     return (strtoken_r(lasts, s2, 1));
  550. }
  551.  
  552.  
  553. #ifdef PROFILE
  554. #pragma profile off
  555. #endif
  556.