blob: bd36c40943a63351e07b1ba5778d80677676cc30 [file] [log] [blame]
/* -----------------------------------------------------------------------------
* This file is part of SWIG, which is licensed as a whole under version 3
* (or any later version) of the GNU General Public License. Some additional
* terms also apply to certain portions of SWIG. The full details of the SWIG
* license and copyrights can be found in the LICENSE and COPYRIGHT files
* included with the SWIG source code as distributed by the SWIG developers
* and at http://www.swig.org/legal.html.
*
* string.c
*
* Implements a string object that supports both sequence operations and
* file semantics.
* ----------------------------------------------------------------------------- */
char cvsroot_string_c[] = "$Id$";
#include "dohint.h"
extern DohObjInfo DohStringType;
typedef struct String {
DOH *file;
int line;
int maxsize; /* Max size allocated */
int len; /* Current length */
int hashkey; /* Hash key value */
int sp; /* Current position */
char *str; /* String data */
} String;
/* -----------------------------------------------------------------------------
* void *String_data() - Return as a 'void *'
* ----------------------------------------------------------------------------- */
static void *String_data(DOH *so) {
String *s = (String *) ObjData(so);
s->str[s->len] = 0;
return (void *) s->str;
}
/* static char *String_char(DOH *so) {
return (char *) String_data(so);
}
*/
/* -----------------------------------------------------------------------------
* int String_dump() - Serialize a string onto out
* ----------------------------------------------------------------------------- */
static int String_dump(DOH *so, DOH *out) {
int nsent;
int ret;
String *s = (String *) ObjData(so);
nsent = 0;
while (nsent < s->len) {
ret = Write(out, s->str + nsent, (s->len - nsent));
if (ret < 0)
return ret;
nsent += ret;
}
return nsent;
}
/* -----------------------------------------------------------------------------
* CopyString() - Copy a string
* ----------------------------------------------------------------------------- */
static DOH *CopyString(DOH *so) {
String *str;
String *s = (String *) ObjData(so);
str = (String *) DohMalloc(sizeof(String));
str->hashkey = s->hashkey;
str->sp = s->sp;
str->line = s->line;
str->file = s->file;
if (str->file)
Incref(str->file);
str->str = (char *) DohMalloc(s->len + 1);
memcpy(str->str, s->str, s->len);
str->maxsize = s->len;
str->len = s->len;
str->str[str->len] = 0;
return DohObjMalloc(&DohStringType, str);
}
/* -----------------------------------------------------------------------------
* DelString() - Delete a string
* ----------------------------------------------------------------------------- */
static void DelString(DOH *so) {
String *s = (String *) ObjData(so);
DohFree(s->str);
DohFree(s);
}
/* -----------------------------------------------------------------------------
* DohString_len() - Length of a string
* ----------------------------------------------------------------------------- */
static int String_len(DOH *so) {
String *s = (String *) ObjData(so);
return s->len;
}
/* -----------------------------------------------------------------------------
* int String_cmp() - Compare two strings
* ----------------------------------------------------------------------------- */
static int String_cmp(DOH *so1, DOH *so2) {
String *s1, *s2;
char *c1, *c2;
int maxlen, i;
s1 = (String *) ObjData(so1);
s2 = (String *) ObjData(so2);
maxlen = s1->len;
if (s2->len < maxlen)
maxlen = s2->len;
c1 = s1->str;
c2 = s2->str;
for (i = maxlen; i; --i, c1++, c2++) {
if (*c1 != *c2)
break;
}
if (i != 0) {
if (*c1 < *c2)
return -1;
else
return 1;
}
if (s1->len == s2->len)
return 0;
if (s1->len > s2->len)
return 1;
return -1;
}
/* -----------------------------------------------------------------------------
* int String_equal() - Say if two string are equal
* ----------------------------------------------------------------------------- */
static int String_equal(DOH *so1, DOH *so2) {
String *s1 = (String *) ObjData(so1);
String *s2 = (String *) ObjData(so2);
register int len = s1->len;
if (len != s2->len) {
return 0;
} else {
register char *c1 = s1->str;
register char *c2 = s2->str;
#if 0
register int mlen = len >> 2;
register int i = mlen;
for (; i; --i) {
if (*(c1++) != *(c2++))
return 0;
if (*(c1++) != *(c2++))
return 0;
if (*(c1++) != *(c2++))
return 0;
if (*(c1++) != *(c2++))
return 0;
}
for (i = len - (mlen << 2); i; --i) {
if (*(c1++) != *(c2++))
return 0;
}
return 1;
#else
return memcmp(c1, c2, len) == 0;
#endif
}
}
/* -----------------------------------------------------------------------------
* int String_hash() - Compute string hash value
* ----------------------------------------------------------------------------- */
static int String_hash(DOH *so) {
String *s = (String *) ObjData(so);
if (s->hashkey >= 0) {
return s->hashkey;
} else {
register char *c = s->str;
register int len = s->len > 50 ? 50 : s->len;
register int h = 0;
register int mlen = len >> 2;
register int i = mlen;
for (; i; --i) {
h = (h << 5) + *(c++);
h = (h << 5) + *(c++);
h = (h << 5) + *(c++);
h = (h << 5) + *(c++);
}
for (i = len - (mlen << 2); i; --i) {
h = (h << 5) + *(c++);
}
h &= 0x7fffffff;
s->hashkey = h;
return h;
}
}
/* -----------------------------------------------------------------------------
* DohString_append(String *s, const char *newstr) - Append to s
* ----------------------------------------------------------------------------- */
void DohString_append(DOH *so, DOH *str) {
int oldlen, newlen, newmaxsize, l, sp;
char *tc;
String *s = (String *) ObjData(so);
char *newstr = 0;
if (DohCheck(str)) {
String *ss = (String *) ObjData(str);
newstr = (char *) String_data((DOH *) str);
l = ss->len;
} else {
newstr = (char *) (str);
l = (int) strlen(newstr);
}
if (!newstr)
return;
s->hashkey = -1;
oldlen = s->len;
newlen = oldlen + l + 1;
if (newlen >= s->maxsize - 1) {
newmaxsize = 2 * s->maxsize;
if (newlen >= newmaxsize - 1)
newmaxsize = newlen + 1;
s->str = (char *) DohRealloc(s->str, newmaxsize);
assert(s->str);
s->maxsize = newmaxsize;
}
tc = s->str;
memcpy(tc + oldlen, newstr, l + 1);
sp = s->sp;
if (sp >= oldlen) {
int i = oldlen + l - sp;
tc += sp;
for (; i; --i) {
if (*(tc++) == '\n')
s->line++;
}
s->sp = oldlen + l;
}
s->len += l;
}
/* -----------------------------------------------------------------------------
* void String_clear() - Clear a string
* ----------------------------------------------------------------------------- */
static void String_clear(DOH *so) {
String *s = (String *) ObjData(so);
s->hashkey = -1;
s->len = 0;
*(s->str) = 0;
s->sp = 0;
s->line = 1;
}
/* -----------------------------------------------------------------------------
* void String_insert() - Insert a string
* ----------------------------------------------------------------------------- */
static int String_insert(DOH *so, int pos, DOH *str) {
String *s;
char *nstr;
int len;
char *data;
if (pos == DOH_END) {
DohString_append(so, str);
return 0;
}
s = (String *) ObjData(so);
s->hashkey = -1;
if (DohCheck(str)) {
String *ss = (String *) ObjData(str);
data = (char *) String_data(str);
len = ss->len;
} else {
data = (char *) (str);
len = (int) strlen(data);
}
nstr = s->str;
if (pos < 0)
pos = 0;
else if (pos > s->len)
pos = s->len;
/* See if there is room to insert the new data */
while (s->maxsize <= s->len + len) {
int newsize = 2 * s->maxsize;
s->str = (char *) DohRealloc(s->str, newsize);
assert(s->str);
s->maxsize = newsize;
}
memmove(s->str + pos + len, s->str + pos, (s->len - pos));
memcpy(s->str + pos, data, len);
if (s->sp >= pos) {
int i;
for (i = 0; i < len; i++) {
if (data[i] == '\n')
s->line++;
}
s->sp += len;
}
s->len += len;
s->str[s->len] = 0;
return 0;
}
/* -----------------------------------------------------------------------------
* int String_delitem() - Delete a character
* ----------------------------------------------------------------------------- */
static int String_delitem(DOH *so, int pos) {
String *s = (String *) ObjData(so);
s->hashkey = -1;
if (pos == DOH_END)
pos = s->len - 1;
if (pos == DOH_BEGIN)
pos = 0;
if (s->len == 0)
return 0;
if (s->sp > pos) {
s->sp--;
assert(s->sp >= 0);
if (s->str[pos] == '\n')
s->line--;
}
memmove(s->str + pos, s->str + pos + 1, ((s->len - 1) - pos));
s->len--;
s->str[s->len] = 0;
return 0;
}
/* -----------------------------------------------------------------------------
* int String_delslice() - Delete a range
* ----------------------------------------------------------------------------- */
static int String_delslice(DOH *so, int sindex, int eindex) {
String *s = (String *) ObjData(so);
int size;
if (s->len == 0)
return 0;
s->hashkey = -1;
if (eindex == DOH_END)
eindex = s->len;
if (sindex == DOH_BEGIN)
sindex = 0;
size = eindex - sindex;
if (s->sp > sindex) {
/* Adjust the file pointer and line count */
int i, end;
if (s->sp > eindex) {
end = eindex;
s->sp -= size;
} else {
end = s->sp;
s->sp = sindex;
}
for (i = sindex; i < end; i++) {
if (s->str[i] == '\n')
s->line--;
}
assert(s->sp >= 0);
}
memmove(s->str + sindex, s->str + eindex, s->len - eindex);
s->len -= size;
s->str[s->len] = 0;
return 0;
}
/* -----------------------------------------------------------------------------
* DOH *String_str() - Returns a string (used by printing commands)
* ----------------------------------------------------------------------------- */
static DOH *String_str(DOH *so) {
String *s = (String *) ObjData(so);
s->str[s->len] = 0;
return NewString(s->str);
}
/* -----------------------------------------------------------------------------
* int String_read() - Read data from a string
* ----------------------------------------------------------------------------- */
static int String_read(DOH *so, void *buffer, int len) {
int reallen, retlen;
char *cb;
String *s = (String *) ObjData(so);
if ((s->sp + len) > s->len)
reallen = (s->len - s->sp);
else
reallen = len;
cb = (char *) buffer;
retlen = reallen;
if (reallen > 0) {
memmove(cb, s->str + s->sp, reallen);
s->sp += reallen;
}
return retlen;
}
/* -----------------------------------------------------------------------------
* int String_write() - Write data to a string
* ----------------------------------------------------------------------------- */
static int String_write(DOH *so, void *buffer, int len) {
int newlen;
String *s = (String *) ObjData(so);
s->hashkey = -1;
if (s->sp > s->len)
s->sp = s->len;
newlen = s->sp + len + 1;
if (newlen > s->maxsize) {
s->str = (char *) DohRealloc(s->str, newlen);
assert(s->str);
s->maxsize = newlen;
s->len = s->sp + len;
}
if ((s->sp + len) > s->len)
s->len = s->sp + len;
memmove(s->str + s->sp, buffer, len);
s->sp += len;
s->str[s->len] = 0;
return len;
}
/* -----------------------------------------------------------------------------
* int String_seek() - Seek to a new position
* ----------------------------------------------------------------------------- */
static int String_seek(DOH *so, long offset, int whence) {
int pos, nsp, inc;
String *s = (String *) ObjData(so);
if (whence == SEEK_SET)
pos = 0;
else if (whence == SEEK_CUR)
pos = s->sp;
else if (whence == SEEK_END) {
pos = s->len;
offset = -offset;
} else
pos = s->sp;
nsp = pos + offset;
if (nsp < 0)
nsp = 0;
if (s->len > 0 && nsp > s->len)
nsp = s->len;
inc = (nsp > s->sp) ? 1 : -1;
{
#if 0
register int sp = s->sp;
register char *tc = s->str;
register int len = s->len;
while (sp != nsp) {
int prev = sp + inc;
if (prev >= 0 && prev <= len && tc[prev] == '\n')
s->line += inc;
sp += inc;
}
#else
register int sp = s->sp;
register char *tc = s->str;
if (inc > 0) {
while (sp != nsp) {
if (tc[++sp] == '\n')
++s->line;
}
} else {
while (sp != nsp) {
if (tc[--sp] == '\n')
--s->line;
}
}
#endif
s->sp = sp;
}
assert(s->sp >= 0);
return 0;
}
/* -----------------------------------------------------------------------------
* long String_tell() - Return current position
* ----------------------------------------------------------------------------- */
static long String_tell(DOH *so) {
String *s = (String *) ObjData(so);
return (long) (s->sp);
}
/* -----------------------------------------------------------------------------
* int String_putc()
* ----------------------------------------------------------------------------- */
static int String_putc(DOH *so, int ch) {
String *s = (String *) ObjData(so);
register int len = s->len;
register int sp = s->sp;
s->hashkey = -1;
if (sp >= len) {
register int maxsize = s->maxsize;
register char *tc = s->str;
if (len > (maxsize - 2)) {
maxsize *= 2;
tc = (char *) DohRealloc(tc, maxsize);
assert(tc);
s->maxsize = (int) maxsize;
s->str = tc;
}
tc += sp;
*tc = (char) ch;
*(++tc) = 0;
s->len = s->sp = sp + 1;
} else {
s->str[s->sp++] = (char) ch;
}
if (ch == '\n')
s->line++;
return ch;
}
/* -----------------------------------------------------------------------------
* int String_getc()
* ----------------------------------------------------------------------------- */
static int String_getc(DOH *so) {
int c;
String *s = (String *) ObjData(so);
if (s->sp >= s->len)
c = EOF;
else
c = (int)(unsigned char) s->str[s->sp++];
if (c == '\n')
s->line++;
return c;
}
/* -----------------------------------------------------------------------------
* int String_ungetc()
* ----------------------------------------------------------------------------- */
static int String_ungetc(DOH *so, int ch) {
String *s = (String *) ObjData(so);
if (ch == EOF)
return ch;
if (s->sp <= 0)
return EOF;
s->sp--;
if (ch == '\n')
s->line--;
return ch;
}
/* -----------------------------------------------------------------------------
* replace_simple(String *str, char *token, char *rep, int flags, int count)
*
* Replaces count non-overlapping occurrences of token with rep in a string.
* ----------------------------------------------------------------------------- */
static char *end_quote(char *s) {
char *qs;
char qc;
char *q;
char *nl;
qc = *s;
qs = s;
while (1) {
q = strpbrk(s + 1, "\"\'");
nl = strchr(s + 1, '\n');
if (nl && (nl < q)) {
/* A new line appears before the end of the string */
if (*(nl - 1) == '\\') {
s = nl + 1;
continue;
}
/* String was terminated by a newline. Wing it */
return qs;
}
if (!q && nl) {
return qs;
}
if (!q)
return 0;
if ((*q == qc) && (*(q - 1) != '\\'))
return q;
s = q;
}
}
static char *match_simple(char *base, char *s, char *token, int tokenlen) {
(void) base;
(void) tokenlen;
return strstr(s, token);
}
static char *match_identifier(char *base, char *s, char *token, int tokenlen) {
while (s) {
s = strstr(s, token);
if (!s)
return 0;
if ((s > base) && (isalnum((int) *(s - 1)) || (*(s - 1) == '_'))) {
s += tokenlen;
continue;
}
if (isalnum((int) *(s + tokenlen)) || (*(s + tokenlen) == '_')) {
s += tokenlen;
continue;
}
return s;
}
return 0;
}
static char *match_identifier_begin(char *base, char *s, char *token, int tokenlen) {
while (s) {
s = strstr(s, token);
if (!s)
return 0;
if ((s > base) && (isalnum((int) *(s - 1)) || (*(s - 1) == '_'))) {
s += tokenlen;
continue;
}
return s;
}
return 0;
}
static char *match_identifier_end(char *base, char *s, char *token, int tokenlen) {
(void) base;
while (s) {
s = strstr(s, token);
if (!s)
return 0;
if (isalnum((int) *(s + tokenlen)) || (*(s + tokenlen) == '_')) {
s += tokenlen;
continue;
}
return s;
}
return 0;
}
static int replace_simple(String *str, char *token, char *rep, int flags, int count, char *(*match) (char *, char *, char *, int)) {
int tokenlen; /* Length of the token */
int replen; /* Length of the replacement */
int delta, expand = 0;
int ic;
int rcount = 0;
int noquote = 0;
char *c, *s, *t, *first;
char *q, *q2;
register char *base;
int i;
/* Figure out if anything gets replaced */
if (!strlen(token))
return 0;
base = str->str;
tokenlen = strlen(token);
s = (*match) (base, base, token, tokenlen);
if (!s)
return 0; /* No matches. Who cares */
str->hashkey = -1;
if (flags & DOH_REPLACE_NOQUOTE)
noquote = 1;
/* If we are not replacing inside quotes, we need to do a little extra work */
if (noquote) {
q = strpbrk(base, "\"\'");
if (!q) {
noquote = 0; /* Well, no quotes to worry about. Oh well */
} else {
while (q && (q < s)) {
/* First match was found inside a quote. Try to find another match */
q2 = end_quote(q);
if (!q2) {
return 0;
}
if (q2 > s) {
/* Find next match */
s = (*match) (base, q2 + 1, token, tokenlen);
}
if (!s)
return 0; /* Oh well, no matches */
q = strpbrk(q2 + 1, "\"\'");
if (!q)
noquote = 0; /* No more quotes */
}
}
}
first = s;
replen = strlen(rep);
delta = (replen - tokenlen);
if (delta <= 0) {
/* String is either shrinking or staying the same size */
/* In this case, we do the replacement in place without memory reallocation */
ic = count;
t = s; /* Target of memory copies */
while (ic && s) {
if (replen) {
memcpy(t, rep, replen);
t += replen;
}
rcount++;
expand += delta;
/* Find the next location */
s += tokenlen;
if (ic == 1)
break;
c = (*match) (base, s, token, tokenlen);
if (noquote) {
q = strpbrk(s, "\"\'");
if (!q) {
noquote = 0;
} else {
while (q && (q < c)) {
/* First match was found inside a quote. Try to find another match */
q2 = end_quote(q);
if (!q2) {
c = 0;
break;
}
if (q2 > c)
c = (*match) (base, q2 + 1, token, tokenlen);
if (!c)
break;
q = strpbrk(q2 + 1, "\"\'");
if (!q)
noquote = 0; /* No more quotes */
}
}
}
if (delta) {
if (c) {
memmove(t, s, c - s);
t += (c - s);
} else {
memmove(t, s, (str->str + str->len) - s + 1);
}
} else {
t += (c - s);
}
s = c;
ic--;
}
if (s && delta) {
memmove(t, s, (str->str + str->len) - s + 1);
}
str->len += expand;
str->str[str->len] = 0;
if (str->sp >= str->len)
str->sp += expand; /* Fix the end of file pointer */
return rcount;
}
/* The string is expanding as a result of the replacement */
/* Figure out how much expansion is going to occur and allocate a new string */
{
char *ns;
int newsize;
rcount++;
ic = count - 1;
s += tokenlen;
while (ic && (c = (*match) (base, s, token, tokenlen))) {
if (noquote) {
q = strpbrk(s, "\"\'");
if (!q) {
break;
} else {
while (q && (q < c)) {
/* First match was found inside a quote. Try to find another match */
q2 = end_quote(q);
if (!q2) {
c = 0;
break;
}
if (q2 > c) {
c = (*match) (base, q2 + 1, token, tokenlen);
if (!c)
break;
}
q = strpbrk(q2 + 1, "\"\'");
if (!q)
noquote = 0;
}
}
}
if (c) {
rcount++;
ic--;
s = c + tokenlen;
} else {
break;
}
}
expand = delta * rcount; /* Total amount of expansion for the replacement */
newsize = str->maxsize;
while ((str->len + expand) >= newsize)
newsize *= 2;
ns = (char *) DohMalloc(newsize);
assert(ns);
t = ns;
s = first;
/* Copy the first part of the string */
if (first > str->str) {
memcpy(t, str->str, (first - str->str));
t += (first - str->str);
}
for (i = 0; i < rcount; i++) {
memcpy(t, rep, replen);
t += replen;
s += tokenlen;
c = (*match) (base, s, token, tokenlen);
if (noquote) {
q = strpbrk(s, "\"\'");
if (!q) {
noquote = 0;
} else {
while (q && (q < c)) {
/* First match was found inside a quote. Try to find another match */
q2 = end_quote(q);
if (!q2) {
c = 0;
break;
}
if (q2 > c) {
c = (*match) (base, q2 + 1, token, tokenlen);
if (!c)
break;
}
q = strpbrk(q2 + 1, "\"\'");
if (!q)
noquote = 0; /* No more quotes */
}
}
}
if (i < (rcount - 1)) {
memcpy(t, s, c - s);
t += (c - s);
} else {
memcpy(t, s, (str->str + str->len) - s + 1);
}
s = c;
}
c = str->str;
str->str = ns;
if (str->sp >= str->len)
str->sp += expand;
str->len += expand;
str->str[str->len] = 0;
str->maxsize = newsize;
DohFree(c);
return rcount;
}
}
/* -----------------------------------------------------------------------------
* int String_replace()
* ----------------------------------------------------------------------------- */
static int String_replace(DOH *stro, DOH *token, DOH *rep, int flags) {
int count = -1;
String *str = (String *) ObjData(stro);
if (flags & DOH_REPLACE_FIRST)
count = 1;
if (flags & DOH_REPLACE_ID_END) {
return replace_simple(str, Char(token), Char(rep), flags, count, match_identifier_end);
} else if (flags & DOH_REPLACE_ID_BEGIN) {
return replace_simple(str, Char(token), Char(rep), flags, count, match_identifier_begin);
} else if (flags & DOH_REPLACE_ID) {
return replace_simple(str, Char(token), Char(rep), flags, count, match_identifier);
} else {
return replace_simple(str, Char(token), Char(rep), flags, count, match_simple);
}
}
/* -----------------------------------------------------------------------------
* void String_chop(DOH *str)
* ----------------------------------------------------------------------------- */
static void String_chop(DOH *so) {
char *c;
String *str = (String *) ObjData(so);
/* Replace trailing whitespace */
c = str->str + str->len - 1;
while ((str->len > 0) && (isspace((int) *c))) {
if (str->sp >= str->len) {
str->sp--;
if (*c == '\n')
str->line--;
}
str->len--;
c--;
}
str->str[str->len] = 0;
assert(str->sp >= 0);
str->hashkey = -1;
}
static void String_setfile(DOH *so, DOH *file) {
DOH *fo;
String *str = (String *) ObjData(so);
if (!DohCheck(file)) {
fo = NewString(file);
Decref(fo);
} else
fo = file;
Incref(fo);
Delete(str->file);
str->file = fo;
}
static DOH *String_getfile(DOH *so) {
String *str = (String *) ObjData(so);
return str->file;
}
static void String_setline(DOH *so, int line) {
String *str = (String *) ObjData(so);
str->line = line;
}
static int String_getline(DOH *so) {
String *str = (String *) ObjData(so);
return str->line;
}
static DohListMethods StringListMethods = {
0, /* doh_getitem */
0, /* doh_setitem */
String_delitem, /* doh_delitem */
String_insert, /* doh_insitem */
String_delslice, /* doh_delslice */
};
static DohFileMethods StringFileMethods = {
String_read,
String_write,
String_putc,
String_getc,
String_ungetc,
String_seek,
String_tell,
0, /* close */
};
static DohStringMethods StringStringMethods = {
String_replace,
String_chop,
};
DohObjInfo DohStringType = {
"String", /* objname */
DelString, /* doh_del */
CopyString, /* doh_copy */
String_clear, /* doh_clear */
String_str, /* doh_str */
String_data, /* doh_data */
String_dump, /* doh_dump */
String_len, /* doh_len */
String_hash, /* doh_hash */
String_cmp, /* doh_cmp */
String_equal, /* doh_equal */
0, /* doh_first */
0, /* doh_next */
String_setfile, /* doh_setfile */
String_getfile, /* doh_getfile */
String_setline, /* doh_setline */
String_getline, /* doh_getline */
0, /* doh_mapping */
&StringListMethods, /* doh_sequence */
&StringFileMethods, /* doh_file */
&StringStringMethods, /* doh_string */
0, /* doh_position */
0
};
#define INIT_MAXSIZE 16
/* -----------------------------------------------------------------------------
* NewString(const char *c) - Create a new string
* ----------------------------------------------------------------------------- */
DOHString *DohNewString(const DOH *so) {
int l = 0, max;
String *str;
char *s;
int hashkey = -1;
if (DohCheck(so)) {
str = (String *) ObjData(so);
s = (char *) String_data((String *) so);
l = s ? str->len : 0;
hashkey = str->hashkey;
} else {
s = (char *) so;
l = s ? (int) strlen(s) : 0;
}
str = (String *) DohMalloc(sizeof(String));
str->hashkey = hashkey;
str->sp = 0;
str->line = 1;
str->file = 0;
max = INIT_MAXSIZE;
if (s) {
if ((l + 1) > max)
max = l + 1;
}
str->str = (char *) DohMalloc(max);
str->maxsize = max;
if (s) {
strcpy(str->str, s);
str->len = l;
str->sp = l;
} else {
str->str[0] = 0;
str->len = 0;
}
return DohObjMalloc(&DohStringType, str);
}
/* -----------------------------------------------------------------------------
* NewStringEmpty() - Create a new string
* ----------------------------------------------------------------------------- */
DOHString *DohNewStringEmpty(void) {
int max = INIT_MAXSIZE;
String *str = (String *) DohMalloc(sizeof(String));
str->hashkey = 0;
str->sp = 0;
str->line = 1;
str->file = 0;
str->str = (char *) DohMalloc(max);
str->maxsize = max;
str->str[0] = 0;
str->len = 0;
return DohObjMalloc(&DohStringType, str);
}
/* -----------------------------------------------------------------------------
* NewStringWithSize(const char *c, int len) - Create a new string
* ----------------------------------------------------------------------------- */
DOHString *DohNewStringWithSize(const DOH *so, int len) {
int l = 0, max;
String *str;
char *s;
if (DohCheck(so)) {
s = (char *) String_data((String *) so);
} else {
s = (char *) so;
}
str = (String *) DohMalloc(sizeof(String));
str->hashkey = -1;
str->sp = 0;
str->line = 1;
str->file = 0;
max = INIT_MAXSIZE;
if (s) {
l = (int) len;
if ((l + 1) > max)
max = l + 1;
}
str->str = (char *) DohMalloc(max);
str->maxsize = max;
if (s) {
strncpy(str->str, s, len);
str->len = l;
str->sp = l;
} else {
str->str[0] = 0;
str->len = 0;
}
return DohObjMalloc(&DohStringType, str);
}
/* -----------------------------------------------------------------------------
* NewStringf(DOH *fmt, ...)
*
* Create a new string from a list of objects.
* ----------------------------------------------------------------------------- */
DOHString *DohNewStringf(const DOH *fmt, ...) {
va_list ap;
DOH *r;
va_start(ap, fmt);
r = NewStringEmpty();
DohvPrintf(r, Char(fmt), ap);
va_end(ap);
return (DOHString *) r;
}
/* -----------------------------------------------------------------------------
* Strcmp()
* Strncmp()
* Strstr()
* Strchr()
*
* Some utility functions.
* ----------------------------------------------------------------------------- */
int DohStrcmp(const DOHString_or_char *s1, const DOHString_or_char *s2) {
const char *c1 = Char(s1);
const char *c2 = Char(s2);
if (c1 && c2) {
return strcmp(c1, c2);
} else {
return c1 < c2;
}
}
int DohStrncmp(const DOHString_or_char *s1, const DOHString_or_char *s2, int n) {
return strncmp(Char(s1), Char(s2), n);
}
char *DohStrstr(const DOHString_or_char *s1, const DOHString_or_char *s2) {
char *p1 = Char(s1);
char *p2 = Char(s2);
return p1 == 0 || p2 == 0 || *p2 == '\0' ? p1 : strstr(p1, p2);
}
char *DohStrchr(const DOHString_or_char *s1, int ch) {
return strchr(Char(s1), ch);
}