Permalink
Find file
Fetching contributors…
Cannot retrieve contributors at this time
executable file 366 lines (301 sloc) 7.25 KB
#ifndef com_sleepless_text_str_cpp
#define com_sleepless_text_str_cpp
// Copyright 2004 Sleepless Software Inc. All Rights Reserved
#include <stdio.h>
#include <string.h>
#include <ctype.h>
struct Str
{
char *buf;
int cap;
bool grow(int n)
{
int newCap = n;
char *newBuf = new char[newCap];
if(!newBuf)
return false;
newBuf[0] = 0;
if(buf)
{
copy(newBuf, buf, newCap);
delete buf;
}
buf = newBuf;
cap = newCap;
return true;
}
Str()
{
buf = 0;
cap = 0;
grow(64);
}
Str(int c)
{
buf = 0;
cap = 0;
grow(c);
}
Str(const char *s)
{
buf = 0;
cap = 0;
grow((int)strlen(s) + 1);
copy(buf, s, cap);
}
~Str()
{
if(buf)
delete buf;
}
int capacity()
{
return cap;
}
const char *get()
{
return buf;
}
char *getw()
{
return buf;
}
void set(const char *n)
{
int nl = (int)strlen(n) + 1;
if(nl > cap)
grow(nl);
copy(buf, n, cap);
}
void add(const char *n)
{
int l = (int)strlen(buf);
int nl = (int)strlen(n);
if((l + nl + 1) > cap)
grow(l + nl + 1);
append(buf, n, cap);
}
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
// Clones a string and returns ptr to it or NULL.
// Uses 'new', so use 'delete' to dispose of the clone.
static char *dup(const char *s)
{
char *s2 = new char[(int)strlen(s) + 1];
strcpy(s2, s);
return s2;
}
// Make all chars in a string lower case
static void lower(char *p)
{
while(*p)
{
*p = tolower(*p);
p++;
}
}
// Make all chars in a string upper case
static void upper(char *p)
{
while(*p)
{
*p = toupper(*p);
p++;
}
}
// Removes white space from the beginning and end of a string.
static char *trim(char *line)
{
while(line[0] && isspace(line[(int)strlen(line) - 1]))
line[(int)strlen(line) - 1] = 0;
while(line[0] && isspace(line[0]))
strcpy(line, line + 1);
return line;
}
// Returns true if 'line' starts with 'pre' (case insensitive)
static int startsWith(const char *line, const char *pre)
{
return equalsLen(line, pre, (int)strlen(pre));
}
// Returns true if 'line' starts with 'pre' (case sensitive)
static int startsWithCase(const char *line, const char *pre)
{
return equalsCaseLen(line, pre, (int)strlen(pre));
}
// Returns true if 'line' ends with 'suf' (case insensitive)
static int endsWith(const char *line, const char *suf)
{
int len1 = (int)strlen(line);
int len2 = (int)strlen(suf);
if(len1 < len2)
return false;
return equalsLen(line + (len1 - len2), suf, len2);
}
// XXX endsWithCase()
//// Returns true if 's1' is the same as 's2' (case insensitive)
static int equals(const char *s1, const char *s2)
{
return compare(s1, s2) == 0;
}
//// Returns true if 's1' is the same as 's2' (case sensitive)
static int equalsCase(const char *s1, const char *s2)
{
return compareCase(s1, s2) == 0;
}
// case insensitive n-length string compare
static int equalsLen(const char* s1, const char *s2, size_t n)
{
return compareLen(s1, s2, n) == 0;
}
// case sensitive n-length string compare
static int equalsCaseLen(const char* s1, const char *s2, size_t n)
{
return compareCaseLen(s1, s2, n) == 0;
}
// Case insensitive.
// Returns a pointer to first occurance of 'q' in 's' (case insensitive)
// or NULL if not found.
static const char *contains(const char *s, const char *q)
{
// not very intelligent, but should get the job done.
const char *r = s;
int l = (int)strlen(q);
while(*r)
{
if(compareLen(r, q, l) == 0)
return r;
r++;
}
return NULL;
}
// Case sensitive.
// Returns a pointer to first occurance of 'q' in 's' or NULL if
// not found.
static const char *containsCase(const char *s, const char *q)
{
return strstr(s, q);
}
// Like strcpy but takes a dst buf len, copies only what will fit,
// and makes sure dst is 0 terminated.
// Returns null if 'dstsize' is less than 1.
static char *copy(char *dst, const char *src, int dstsize)
{
if(dstsize < 1)
return 0;
//strncpy(dst, src, dstsize);
// I can't use strcpy cause it wipes the whole buffer clean and
// that's not really what I want cause I have char ptrs up inside
// the buffer (see httpd.cpp, queryTags/ARgs, so I'll do it by hand.
char *d = dst;
const char *s = src;
int n = 0;
while(*s && (n < (dstsize - 1)))
{
*d++ = *s++;
n++;
}
*d = 0;
return dst;
}
// Like strcat but takes a dst buf len, copies only what will fit,
// and makes sure dst is 0 terminated.
// Returns null if 'src' won't fit.
static char *append(char *dst, const char *src, int dstsize)
{
int len = (int)strlen(dst);
return Str::copy(dst + len, src, dstsize - len);
}
static char *append(char *dst, int n, int dstsize)
{
char buf[50];
sprintf(buf, "%d", n);
return Str::append(dst, buf, dstsize);
}
static char *append(char *dst, unsigned int n, int dstsize)
{
char buf[50];
sprintf(buf, "%u", n);
return Str::append(dst, buf, dstsize);
}
static char *append(char *dst, long n, int dstsize)
{
char buf[50];
sprintf(buf, "%ld", n);
return Str::append(dst, buf, dstsize);
}
static char *append(char *dst, unsigned long n, int dstsize)
{
char buf[50];
sprintf(buf, "%lu", n);
return Str::append(dst, buf, dstsize);
}
static char *append(char *dst, float n, int dstsize)
{
char buf[50];
sprintf(buf, "%f", n);
return Str::append(dst, buf, dstsize);
}
//////////////////////////////////////////////////////////////////
// Same as strcmp()
static int compare(const void *s1, const void *s2)
{
const unsigned char *p1 = (const unsigned char *) s1;
const unsigned char *p2 = (const unsigned char *) s2;
int ret;
unsigned char c1;
if (p1 == p2)
return 0;
for (; !(ret = (c1 = tolower(*p1)) - tolower(*p2)); p1++, p2++)
if (c1 == '\0') break;
return ret;
}
// Same as strcasecmp()
static int compareCase(const void *s1, const void *s2)
{
const unsigned char *p1 = (const unsigned char *) s1;
const unsigned char *p2 = (const unsigned char *) s2;
int ret;
unsigned char c1;
if (p1 == p2)
return 0;
for (; !(ret = (c1 = tolower(*p1)) - tolower(*p2)); p1++, p2++)
if (c1 == '\0') break;
return ret;
}
// Same as strncmp()
static int compareLen(const char* s1, const char *s2, size_t n)
{
if (n != 0) {
const unsigned char *us1 = (const unsigned char *)s1;
const unsigned char *us2 = (const unsigned char *)s2;
do {
if (tolower(*us1) != tolower(*us2++))
return (tolower(*us1) - tolower(*--us2));
if (*us1++ == '\0')
break;
} while (--n != 0);
}
return (0);
}
// Same as strncasecmp()
static int compareCaseLen(const char* s1, const char *s2, size_t n)
{
if (n != 0) {
const unsigned char *us1 = (const unsigned char *)s1;
const unsigned char *us2 = (const unsigned char *)s2;
do {
if (tolower(*us1) != tolower(*us2++))
return (tolower(*us1) - tolower(*--us2));
if (*us1++ == '\0')
break;
} while (--n != 0);
}
return (0);
}
};
#define STR_CPY(s,a) Str::copy(s, a, sizeof(s))
#define STR_APP(s,a) Str::append(s, a, sizeof(s))
#define STR_SAME(s1,s2) Str::equals(s1, s2)
#endif