qse/qse/lib/cmn/str_bas.c
hyung-hwan d418e651e5 - added easy C API functions for sed and cut
- added a sample C program for sed
- added C++ API for cut.
2009-12-22 06:29:52 +00:00

809 lines
15 KiB
C

/*
* $Id: str_bas.c 320 2009-12-21 12:29:52Z hyunghwan.chung $
*
Copyright 2006-2009 Chung, Hyung-Hwan.
This file is part of QSE.
QSE is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
QSE is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with QSE. If not, see <http://www.gnu.org/licenses/>.
*/
#include <qse/cmn/str.h>
#include <qse/cmn/chr.h>
#include "mem.h"
qse_size_t qse_strlen (const qse_char_t* str)
{
const qse_char_t* p = str;
while (*p != QSE_T('\0')) p++;
return p - str;
}
qse_size_t qse_strbytes (const qse_char_t* str)
{
const qse_char_t* p = str;
while (*p != QSE_T('\0')) p++;
return (p - str) * QSE_SIZEOF(qse_char_t);
}
qse_size_t qse_strcpy (qse_char_t* buf, const qse_char_t* str)
{
qse_char_t* org = buf;
while ((*buf++ = *str++) != QSE_T('\0'));
return buf - org - 1;
}
qse_size_t qse_strxcpy (
qse_char_t* buf, qse_size_t bsz, const qse_char_t* str)
{
qse_char_t* p, * p2;
p = buf; p2 = buf + bsz - 1;
while (p < p2)
{
if (*str == QSE_T('\0')) break;
*p++ = *str++;
}
if (bsz > 0) *p = QSE_T('\0');
return p - buf;
}
qse_size_t qse_strncpy (
qse_char_t* buf, const qse_char_t* str, qse_size_t len)
{
/*
const qse_char_t* end = str + len;
while (str < end) *buf++ = *str++;
*buf = QSE_T('\0');
return len;
*/
if (len > 0)
{
qse_size_t n = (len-1) >> 3; /* (len-1) / 8 */
switch (len & 7) /* len % 8 */
{
repeat:
case 0: *buf++ = *str++;
case 7: *buf++ = *str++;
case 6: *buf++ = *str++;
case 5: *buf++ = *str++;
case 4: *buf++ = *str++;
case 3: *buf++ = *str++;
case 2: *buf++ = *str++;
case 1: *buf++ = *str++;
if (n <= 0) break;
n--;
goto repeat;
}
}
*buf = QSE_T('\0');
return len;
}
qse_size_t qse_strxncpy (
qse_char_t* buf, qse_size_t bsz, const qse_char_t* str, qse_size_t len)
{
qse_size_t n;
if (bsz <= 0) return 0;
if ((n = bsz - 1) > len) n = len;
QSE_MEMCPY (buf, str, n * QSE_SIZEOF(qse_char_t));
buf[n] = QSE_T('\0');
return n;
}
qse_size_t qse_strfcpy (
qse_char_t* buf, const qse_char_t* fmt, const qse_char_t* str[])
{
qse_char_t* b = buf;
const qse_char_t* f = fmt;
while (*f != QSE_T('\0'))
{
if (*f == QSE_T('$'))
{
if (f[1] == QSE_T('{') &&
(f[2] >= QSE_T('0') && f[2] <= QSE_T('9')))
{
const qse_char_t* tmp;
qse_size_t idx = 0;
tmp = f;
f += 2;
do idx = idx * 10 + (*f++ - QSE_T('0'));
while (*f >= QSE_T('0') && *f <= QSE_T('9'));
if (*f != QSE_T('}'))
{
f = tmp;
goto normal;
}
f++;
tmp = str[idx];
while (*tmp != QSE_T('\0')) *b++ = *tmp++;
continue;
}
else if (f[1] == QSE_T('$')) f++;
}
normal:
*b++ = *f++;
}
*b = QSE_T('\0');
return b - buf;
}
qse_size_t qse_strfncpy (
qse_char_t* buf, const qse_char_t* fmt, const qse_cstr_t str[])
{
qse_char_t* b = buf;
const qse_char_t* f = fmt;
while (*f != QSE_T('\0'))
{
if (*f == QSE_T('$'))
{
if (f[1] == QSE_T('{') &&
(f[2] >= QSE_T('0') && f[2] <= QSE_T('9')))
{
const qse_char_t* tmp, * tmpend;
qse_size_t idx = 0;
tmp = f;
f += 2;
do idx = idx * 10 + (*f++ - QSE_T('0'));
while (*f >= QSE_T('0') && *f <= QSE_T('9'));
if (*f != QSE_T('}'))
{
f = tmp;
goto normal;
}
f++;
tmp = str[idx].ptr;
tmpend = tmp + str[idx].len;
while (tmp < tmpend) *b++ = *tmp++;
continue;
}
else if (f[1] == QSE_T('$')) f++;
}
normal:
*b++ = *f++;
}
*b = QSE_T('\0');
return b - buf;
}
qse_size_t qse_strxfcpy (
qse_char_t* buf, qse_size_t bsz,
const qse_char_t* fmt, const qse_char_t* str[])
{
qse_char_t* b = buf;
qse_char_t* end = buf + bsz - 1;
const qse_char_t* f = fmt;
if (bsz <= 0) return 0;
while (*f != QSE_T('\0'))
{
if (*f == QSE_T('$'))
{
if (f[1] == QSE_T('{') &&
(f[2] >= QSE_T('0') && f[2] <= QSE_T('9')))
{
const qse_char_t* tmp;
qse_size_t idx = 0;
tmp = f;
f += 2;
do idx = idx * 10 + (*f++ - QSE_T('0'));
while (*f >= QSE_T('0') && *f <= QSE_T('9'));
if (*f != QSE_T('}'))
{
f = tmp;
goto normal;
}
f++;
tmp = str[idx];
while (*tmp != QSE_T('\0'))
{
if (b >= end) goto fini;
*b++ = *tmp++;
}
continue;
}
else if (f[1] == QSE_T('$')) f++;
}
normal:
if (b >= end) break;
*b++ = *f++;
}
fini:
*b = QSE_T('\0');
return b - buf;
}
qse_size_t qse_strxfncpy (
qse_char_t* buf, qse_size_t bsz,
const qse_char_t* fmt, const qse_cstr_t str[])
{
qse_char_t* b = buf;
qse_char_t* end = buf + bsz - 1;
const qse_char_t* f = fmt;
if (bsz <= 0) return 0;
while (*f != QSE_T('\0'))
{
if (*f == QSE_T('$'))
{
if (f[1] == QSE_T('{') &&
(f[2] >= QSE_T('0') && f[2] <= QSE_T('9')))
{
const qse_char_t* tmp, * tmpend;
qse_size_t idx = 0;
tmp = f;
f += 2;
do idx = idx * 10 + (*f++ - QSE_T('0'));
while (*f >= QSE_T('0') && *f <= QSE_T('9'));
if (*f != QSE_T('}'))
{
f = tmp;
goto normal;
}
f++;
tmp = str[idx].ptr;
tmpend = tmp + str[idx].len;
while (tmp < tmpend)
{
if (b >= end) goto fini;
*b++ = *tmp++;
}
continue;
}
else if (f[1] == QSE_T('$')) f++;
}
normal:
if (b >= end) break;
*b++ = *f++;
}
fini:
*b = QSE_T('\0');
return b - buf;
}
qse_size_t qse_strxcat (qse_char_t* buf, qse_size_t bsz, const qse_char_t* str)
{
qse_char_t* p, * p2;
qse_size_t blen;
blen = qse_strlen(buf);
if (blen >= bsz) return blen; /* something wrong */
p = buf + blen;
p2 = buf + bsz - 1;
while (p < p2)
{
if (*str == QSE_T('\0')) break;
*p++ = *str++;
}
if (bsz > 0) *p = QSE_T('\0');
return p - buf;
}
qse_size_t qse_strxncat (
qse_char_t* buf, qse_size_t bsz, const qse_char_t* str, qse_size_t len)
{
qse_char_t* p, * p2;
const qse_char_t* end;
qse_size_t blen;
blen = qse_strlen(buf);
if (blen >= bsz) return blen; /* something wrong */
p = buf + blen;
p2 = buf + bsz - 1;
end = str + len;
while (p < p2)
{
if (str >= end) break;
*p++ = *str++;
}
if (bsz > 0) *p = QSE_T('\0');
return p - buf;
}
int qse_strcmp (const qse_char_t* s1, const qse_char_t* s2)
{
while (*s1 == *s2)
{
if (*s1 == QSE_T('\0')) return 0;
s1++, s2++;
}
return (*s1 > *s2)? 1: -1;
}
int qse_strxcmp (const qse_char_t* s1, qse_size_t len, const qse_char_t* s2)
{
const qse_char_t* end = s1 + len;
while (s1 < end && *s2 != QSE_T('\0') && *s1 == *s2) s1++, s2++;
if (s1 == end && *s2 == QSE_T('\0')) return 0;
if (*s1 == *s2) return (s1 < end)? 1: -1;
return (*s1 > *s2)? 1: -1;
}
int qse_strxncmp (
const qse_char_t* s1, qse_size_t len1,
const qse_char_t* s2, qse_size_t len2)
{
qse_char_t c1, c2;
const qse_char_t* end1 = s1 + len1;
const qse_char_t* end2 = s2 + len2;
while (s1 < end1)
{
c1 = *s1;
if (s2 < end2)
{
c2 = *s2;
if (c1 > c2) return 1;
if (c1 < c2) return -1;
}
else return 1;
s1++; s2++;
}
return (s2 < end2)? -1: 0;
}
int qse_strcasecmp (const qse_char_t* s1, const qse_char_t* s2)
{
while (QSE_TOUPPER(*s1) == QSE_TOUPPER(*s2))
{
if (*s1 == QSE_C('\0')) return 0;
s1++, s2++;
}
return (QSE_TOUPPER(*s1) > QSE_TOUPPER(*s2))? 1: -1;
}
int qse_strxncasecmp (
const qse_char_t* s1, qse_size_t len1,
const qse_char_t* s2, qse_size_t len2)
{
qse_char_t c1, c2;
const qse_char_t* end1 = s1 + len1;
const qse_char_t* end2 = s2 + len2;
while (s1 < end1)
{
c1 = QSE_TOUPPER (*s1);
if (s2 < end2)
{
c2 = QSE_TOUPPER (*s2);
if (c1 > c2) return 1;
if (c1 < c2) return -1;
}
else return 1;
s1++; s2++;
}
return (s2 < end2)? -1: 0;
}
qse_char_t* qse_strdup (const qse_char_t* str, qse_mmgr_t* mmgr)
{
qse_char_t* tmp;
tmp = (qse_char_t*) QSE_MMGR_ALLOC (
mmgr, (qse_strlen(str)+1)*QSE_SIZEOF(qse_char_t));
if (tmp == QSE_NULL) return QSE_NULL;
qse_strcpy (tmp, str);
return tmp;
}
qse_char_t* qse_strdup2 (
const qse_char_t* str1, const qse_char_t* str2, qse_mmgr_t* mmgr)
{
return qse_strxdup2 (
str1, qse_strlen(str1), str2, qse_strlen(str2), mmgr);
}
qse_char_t* qse_strxdup (
const qse_char_t* str, qse_size_t len, qse_mmgr_t* mmgr)
{
qse_char_t* tmp;
tmp = (qse_char_t*) QSE_MMGR_ALLOC (
mmgr, (len+1)*QSE_SIZEOF(qse_char_t));
if (tmp == QSE_NULL) return QSE_NULL;
qse_strncpy (tmp, str, len);
return tmp;
}
qse_char_t* qse_strxdup2 (
const qse_char_t* str1, qse_size_t len1,
const qse_char_t* str2, qse_size_t len2, qse_mmgr_t* mmgr)
{
qse_char_t* tmp;
tmp = (qse_char_t*) QSE_MMGR_ALLOC (
mmgr, (len1+len2+1) * QSE_SIZEOF(qse_char_t));
if (tmp == QSE_NULL) return QSE_NULL;
qse_strncpy (tmp, str1, len1);
qse_strncpy (tmp + len1, str2, len2);
return tmp;
}
qse_char_t* qse_strstr (const qse_char_t* str, const qse_char_t* sub)
{
const qse_char_t* x, * y;
y = sub;
if (*y == QSE_T('\0')) return (qse_char_t*)str;
while (*str != QSE_T('\0'))
{
if (*str != *y)
{
str++;
continue;
}
x = str;
while (1)
{
if (*y == QSE_T('\0')) return (qse_char_t*)str;
if (*x++ != *y++) break;
}
y = sub;
str++;
}
return QSE_NULL;
}
qse_char_t* qse_strxstr (
const qse_char_t* str, qse_size_t size, const qse_char_t* sub)
{
return qse_strxnstr (str, size, sub, qse_strlen(sub));
}
qse_char_t* qse_strxnstr (
const qse_char_t* str, qse_size_t strsz,
const qse_char_t* sub, qse_size_t subsz)
{
const qse_char_t* end, * subp;
if (subsz == 0) return (qse_char_t*)str;
if (strsz < subsz) return QSE_NULL;
end = str + strsz - subsz;
subp = sub + subsz;
while (str <= end)
{
const qse_char_t* x = str;
const qse_char_t* y = sub;
while (1)
{
if (y >= subp) return (qse_char_t*)str;
if (*x != *y) break;
x++; y++;
}
str++;
}
return QSE_NULL;
}
qse_char_t* qse_strcasestr (const qse_char_t* str, const qse_char_t* sub)
{
const qse_char_t* x, * y;
y = sub;
if (*y == QSE_T('\0')) return (qse_char_t*)str;
while (*str != QSE_T('\0'))
{
if (QSE_TOUPPER(*str) != QSE_TOUPPER(*y))
{
str++;
continue;
}
x = str;
while (1)
{
if (*y == QSE_T('\0')) return (qse_char_t*)str;
if (QSE_TOUPPER(*x) != QSE_TOUPPER(*y)) break;
x++; y++;
}
y = sub;
str++;
}
return QSE_NULL;
}
qse_char_t* qse_strxcasestr (
const qse_char_t* str, qse_size_t size, const qse_char_t* sub)
{
return qse_strxncasestr (str, size, sub, qse_strlen(sub));
}
qse_char_t* qse_strxncasestr (
const qse_char_t* str, qse_size_t strsz,
const qse_char_t* sub, qse_size_t subsz)
{
const qse_char_t* end, * subp;
if (subsz == 0) return (qse_char_t*)str;
if (strsz < subsz) return QSE_NULL;
end = str + strsz - subsz;
subp = sub + subsz;
while (str <= end)
{
const qse_char_t* x = str;
const qse_char_t* y = sub;
while (1)
{
if (y >= subp) return (qse_char_t*)str;
if (QSE_TOUPPER(*x) != QSE_TOUPPER(*y)) break;
x++; y++;
}
str++;
}
return QSE_NULL;
}
qse_char_t* qse_strrstr (const qse_char_t* str, const qse_char_t* sub)
{
return qse_strxnrstr (str, qse_strlen(str), sub, qse_strlen(sub));
}
qse_char_t* qse_strxrstr (
const qse_char_t* str, qse_size_t size, const qse_char_t* sub)
{
return qse_strxnrstr (str, size, sub, qse_strlen(sub));
}
qse_char_t* qse_strxnrstr (
const qse_char_t* str, qse_size_t strsz,
const qse_char_t* sub, qse_size_t subsz)
{
const qse_char_t* p = str + strsz;
const qse_char_t* subp = sub + subsz;
if (subsz == 0) return (qse_char_t*)p;
if (strsz < subsz) return QSE_NULL;
p = p - subsz;
while (p >= str)
{
const qse_char_t* x = p;
const qse_char_t* y = sub;
while (1)
{
if (y >= subp) return (qse_char_t*)p;
if (*x != *y) break;
x++; y++;
}
p--;
}
return QSE_NULL;
}
qse_char_t* qse_strchr (const qse_char_t* str, qse_cint_t c)
{
while (*str != QSE_T('\0'))
{
if (*str == c) return (qse_char_t*)str;
str++;
}
return QSE_NULL;
}
qse_char_t* qse_strxchr (const qse_char_t* str, qse_size_t len, qse_cint_t c)
{
const qse_char_t* end = str + len;
while (str < end)
{
if (*str == c) return (qse_char_t*)str;
str++;
}
return QSE_NULL;
}
qse_char_t* qse_strrchr (const qse_char_t* str, qse_cint_t c)
{
const qse_char_t* end = str;
while (*end != QSE_T('\0')) end++;
while (end > str)
{
if (*--end == c) return (qse_char_t*)end;
}
return QSE_NULL;
}
qse_char_t* qse_strxrchr (const qse_char_t* str, qse_size_t len, qse_cint_t c)
{
const qse_char_t* end = str + len;
while (end > str)
{
if (*--end == c) return (qse_char_t*)end;
}
return QSE_NULL;
}
qse_char_t* qse_strbeg (const qse_char_t* str, const qse_char_t* sub)
{
while (*sub != QSE_T('\0'))
{
if (*str != *sub) return QSE_NULL;
str++; sub++;
}
/* returns the pointer to the next character of the match */
return (qse_char_t*)str;
}
qse_char_t* qse_strxbeg (
const qse_char_t* str, qse_size_t len, const qse_char_t* sub)
{
const qse_char_t* end = str + len;
while (*sub != QSE_T('\0'))
{
if (str >= end || *str != *sub) return QSE_NULL;
str++; sub++;
}
/* returns the pointer to the next character of the match */
return (qse_char_t*)str;
}
qse_char_t* qse_strnbeg (
const qse_char_t* str, const qse_char_t* sub, qse_size_t len)
{
const qse_char_t* end = sub + len;
while (sub < end)
{
if (*str == QSE_T('\0') || *str != *sub) return QSE_NULL;
str++; sub++;
}
/* returns the pointer to the next character of the match */
return (qse_char_t*)str;
}
qse_char_t* qse_strxnbeg (
const qse_char_t* str, qse_size_t len1,
const qse_char_t* sub, qse_size_t len2)
{
const qse_char_t* end1, * end2;
if (len2 > len1) return QSE_NULL;
end1 = str + len1;
end2 = sub + len2;
while (sub < end2)
{
if (str >= end1 || *str != *sub) return QSE_NULL;
str++; sub++;
}
/* returns the pointer to the next character of the match */
return (qse_char_t*)str;
}
qse_char_t* qse_strend (const qse_char_t* str, const qse_char_t* sub)
{
return qse_strxnend (str, qse_strlen(str), sub, qse_strlen(sub));
}
qse_char_t* qse_strxend (
const qse_char_t* str, qse_size_t len, const qse_char_t* sub)
{
return qse_strxnend (str, len, sub, qse_strlen(sub));
}
qse_char_t* qse_strnend (
const qse_char_t* str, const qse_char_t* sub, qse_size_t len)
{
return qse_strxnend (str, qse_strlen(str), sub, len);
}
qse_char_t* qse_strxnend (
const qse_char_t* str, qse_size_t len1,
const qse_char_t* sub, qse_size_t len2)
{
const qse_char_t* end1, * end2;
if (len2 > len1) return QSE_NULL;
end1 = str + len1;
end2 = sub + len2;
while (end2 > sub)
{
if (end1 <= str) return QSE_NULL;
if (*(--end1) != *(--end2)) return QSE_NULL;
}
/* returns the pointer to the match start */
return (qse_char_t*)end1;
}