libproff/str.c
/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following functions.
- strerror
- strExchange
- strLower
- strUpper
- strSnip
- strCaseEq
- strnCaseEq
- strcasecmp
- strncasecmp
- strCaseStr
- strnCaseStr
- strStripLeftRight
- strStripEOL
- strnStripEOL
- strMakeEOLn
- strMakeEOLrn
- strHash
- lp_strListAdd
- strListFree
- lp_strStackAdd
- lp_strnStackAdd
- strStackFree
- strToi
- strKToi
/* $Id: str.c,v 1.2 2000/06/11 19:28:49 proff Exp $ */
#include "libproff.h"
#include "mmalloc.h"
#define TRUE 1
#define FALSE 0
#define bool int
#ifndef HAVE_STRERROR
extern char *sys_errlist;
EXPORT char *strerror(int n)
/* [<][>][^][v][top][bottom][index][help] */
{
return sys_errlist[n];
}
#endif /* HAVE_STRERROR */
EXPORT int strExchange (char *s, char c1, char c2)
/* [<][>][^][v][top][bottom][index][help] */
{
char *head = s;
for (; *s; s++)
if (*s == c1)
*s = c2;
return s - head;
}
EXPORT int strLower (char *s)
/* [<][>][^][v][top][bottom][index][help] */
{
char *head = s;
for (; *s; s++)
*s = tolower (*s);
return s - head;
}
EXPORT int strUpper (char *s)
/* [<][>][^][v][top][bottom][index][help] */
{
char *head = s;
for (; *s; s++)
*s = toupper (*s);
return s - head;
}
/* start is a \0 terminated list of starting characters
* end is a \0 terminated list of ending characters
*
* the string stored in buf does not include the starting or ending terminators
* and is null terminated.
*
* returns length of snipped string.
*
* buf[0] = '\0' if no string was snipped
*/
EXPORT int strSnip (char *s, int len, char *start, char *end, char *buf, int blen)
/* [<][>][^][v][top][bottom][index][help] */
{
int n = 0;
char *endp;
buf[0] = '\0';
for (endp = s+len; (!len || s<endp) && *s; s++)
{
char *p;
for (p = start; *p; p++)
if (*s == *p)
goto hit;
}
goto ret;
hit:
s++;
for (; (!len || s<endp) && *s; s++, n++)
{
char *p;
for (p = end; *p; p++)
if (*s == *p)
goto ret;
*buf++=*s;
}
buf[0] = '\0';
return 0;
ret:
buf[n] = '\0';
return n;
}
/* gcc has strcmp built-in (fast) so we use macros if we can. */
#ifndef HAVE_STRCASECMP
EXPORT int strCaseEq (char *s, char *s2)
/* [<][>][^][v][top][bottom][index][help] */
{
do
{
if (tolower (*s) != tolower (*s2))
return FALSE;
} while (*s++ && *s2++);
return TRUE;
}
EXPORT int strnCaseEq (char *s, char *s2, int n)
/* [<][>][^][v][top][bottom][index][help] */
{
do
{
if (tolower (*s) != tolower (*s2))
return FALSE;
} while (--n<0);
return TRUE;
}
EXPORT int strcasecmp (char *s, char *s2)
/* [<][>][^][v][top][bottom][index][help] */
{
do
{
char c1=tolower(*s);
char c2=tolower(*s2);
if (c1>c2)
return 1;
if (c1<c2)
return -1;
} while (*s++ && *s2++);
return 0;
}
EXPORT int strncasecmp (char *s, char *s2, int n)
/* [<][>][^][v][top][bottom][index][help] */
{
do
{
char c1=tolower(*s);
char c2=tolower(*s2);
if (c1>c2)
return 1;
if (c1<c2)
return -1;
} while (--n);
return 0;
}
#endif
EXPORT char *strCaseStr (char *s, char *find)
/* [<][>][^][v][top][bottom][index][help] */
{
char c, sc;
size_t len;
if ((c = *find++) != 0) {
len = strlen(find);
do {
do {
if ((sc = *s++) == 0)
return NULL;
} while (sc != c);
} while (!strnCaseEq(s, find, len));
s--;
}
return (char *)s;
}
EXPORT char *strnCaseStr (char *s, char *find, int slen)
/* [<][>][^][v][top][bottom][index][help] */
{
char c, sc;
size_t len;
char *send = s+slen;
if ((c = *find++) != 0) {
len = strlen(find);
do {
do {
if ((sc = *s++) == 0 || s>=send)
return NULL;
} while (sc != c);
} while (!strnCaseEq(s, find, len));
s--;
}
return ((char *)s);
}
EXPORT int strStripLeftRight (char *s)
/* [<][>][^][v][top][bottom][index][help] */
{
char *p;
int n;
for (p = s; *p; p++)
if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
continue;
else
break;
if (p!=s)
strcpy (s, p);
n = strlen (s);
if (*p)
{
for (p = s + n - 1; p >= s && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t'); p--) ;
*(p + 1) = '\0';
return p - s + 1;
}
return n;
}
EXPORT int strStripEOL (char *s)
/* [<][>][^][v][top][bottom][index][help] */
{
char *head = s;
for (; *s; s++)
if (*s == '\r' || *s == '\n')
{
*s = '\0';
break;
}
return s - head;
}
/*
* as above, but n = size of string
*/
EXPORT int strnStripEOL (char *s, int n)
/* [<][>][^][v][top][bottom][index][help] */
{
n--;
while (n>=0 && (s[n] == '\r' || s[n] == '\n'))
s[n--]='\0';
return n+1;
}
EXPORT int strMakeEOLn (char *s)
/* [<][>][^][v][top][bottom][index][help] */
{
char *head = s;
for (;; s++)
if (!*s || *s == '\r')
{
*s++ = '\n';
*s = '\0';
break;
}
return s - head;
}
EXPORT int strMakeEOLrn (char *s)
/* [<][>][^][v][top][bottom][index][help] */
{
char *head = s;
for (;; s++)
if (!*s || *s == '\n' || *s == '\r')
{
*s++ = '\r';
*s++ = '\n';
*s = '\0';
break;
}
return s - head;
}
EXPORT n_u32 strHash (n_u32 h, char *s)
/* [<][>][^][v][top][bottom][index][help] */
{
int n;
for (n = 0; s[n]; n++)
h = (((h << 5) | (h >> (32 - 5))) ^ (s[n] & 0xff) ^ n) & 0xffffffff;
return h;
}
EXPORT struct strList * lp_strListAdd (struct strList *l, char *s, char *desc)
/* [<][>][^][v][top][bottom][index][help] */
{
if (l)
{
l->next = (struct strList *) lp_Smalloc (sizeof *l, desc);
l->next->head = l->head;
l = l->next;
} else
{
l = (struct strList *) lp_Smalloc (sizeof *l, desc);
l->head = l;
}
l->next = NULL;
l->data = lp_Sstrdup (s, desc);
return l;
}
EXPORT void strListFree (struct strList *l)
/* [<][>][^][v][top][bottom][index][help] */
{
l = l->head;
while (l)
{
struct strList *t = l;
t = l;
l = l->next;
free (t->data);
free (t);
}
}
#define STRSTACK_BLOCK_SIZE 4096 /* page size divisible */
/*
* l->used includes the terminating null
*/
EXPORT struct strStack *lp_strStackAdd (struct strStack *l, char *s, char *desc)
/* [<][>][^][v][top][bottom][index][help] */
{
int len;
len = strlen (s);
if (!l)
{
l = Smalloc (sizeof *l);
l->used = 1; /* the nil */
l->len = (len/STRSTACK_BLOCK_SIZE + 1) * STRSTACK_BLOCK_SIZE;
l->data = lp_Smalloc(l->len, desc);
}
if (l->used + len > l->len)
{
l->len += len;
l->len = (l->len/STRSTACK_BLOCK_SIZE + 1) * STRSTACK_BLOCK_SIZE;
l->data = lp_Srealloc (l->data, l->len, desc);
}
memcpy (l->data + l->used - 1, s, len+1);
l->used += len;
return l;
}
EXPORT struct strStack *lp_strnStackAdd (struct strStack *l, char *s, int len, char *desc)
/* [<][>][^][v][top][bottom][index][help] */
{
if (!l)
{
l = Smalloc (sizeof *l);
l->used = 1; /* the nil */
l->len = (len/STRSTACK_BLOCK_SIZE + 1) * STRSTACK_BLOCK_SIZE;
l->data = lp_Smalloc (l->len, desc);
}
if (l->used + len > l->len)
{
l->len += len;
l->len = (l->len/STRSTACK_BLOCK_SIZE + 1) * STRSTACK_BLOCK_SIZE;
l->data = lp_Srealloc (l->data, l->len, desc);
}
memcpy (l->data + l->used - 1, s, len);
l->used += len;
l->data[l->used-1] = '\0';
return l;
}
EXPORT void strStackFree (struct strStack *l)
/* [<][>][^][v][top][bottom][index][help] */
{
free (l->data);
free (l);
}
/*
* no negatives, -1 is error, must have at least one digit, skips leading white space
*/
EXPORT int strToi (char *s)
/* [<][>][^][v][top][bottom][index][help] */
{
int i=0;
for (;isspace(*s); s++) ;
if (!isdigit(*s))
return -1;
do
{
i*=10;
i+=*s-'0';
} while (isdigit (*++s));
return i;
}
EXPORT bool strKToi(char *s, int *i)
/* [<][>][^][v][top][bottom][index][help] */
{
char c;
char *p;
int k;
for (p = s; *p && isspace (*p); p++) {}
for (; isdigit(*p) || *p == 'x' || *p == 'X'; p++) {}
c = *p;
*p = '\0';
if (sscanf (s, "%i", &k)!=1)
{
*p=c;
*i=0;
return FALSE;
}
switch (tolower(c))
{
case 'g':
k*=1024;
case 'm':
k*=1024;
case 'k':
k*=1024;
default:
break;
}
*p = c;
*i = k;
return TRUE;
}