302 lines
6.0 KiB
C
302 lines
6.0 KiB
C
#include <c_Str.h>
|
|
#include <c_Memory.h>
|
|
#include <string.h>
|
|
#include <limits.h>
|
|
|
|
#define idx(i, len) ((i) <= 0 ? (i) + (len) : (i) - 1)
|
|
|
|
#define convert(s, i, j) do { int _len; \
|
|
assert(s); _len = (int)strlen(s); \
|
|
i = idx(i, _len); j = idx(j, _len); \
|
|
if (i > j) { int t = i; i = j; j = t; } \
|
|
assert(i >= 0 && j <= _len); } while (0)
|
|
|
|
/* ------------------------------------------------------------------------------------------------------------------ */
|
|
/* */
|
|
|
|
char *c_Str_sub(const char *s, int i, int j) {
|
|
char *str, *p;
|
|
convert(s, i, j);
|
|
p = str = C_ALLOC(j - i + 1);
|
|
while (i < j)
|
|
*p++ = s[i++];
|
|
*p = '\0';
|
|
return str;
|
|
}
|
|
|
|
char *c_Str_dup(const char *s, int i, int j, int n) {
|
|
int k;
|
|
char *str, *p;
|
|
assert(n >= 0);
|
|
convert(s, i, j);
|
|
p = str = C_ALLOC(n*(j - i) + 1);
|
|
if (j - i > 0)
|
|
while (n-- > 0)
|
|
for (k = i; k < j; k++)
|
|
*p++ = s[k];
|
|
*p = '\0';
|
|
return str;
|
|
}
|
|
|
|
char *c_Str_reverse(const char *s, int i, int j) {
|
|
char *str, *p;
|
|
convert(s, i, j);
|
|
p = str = C_ALLOC(j - i + 1);
|
|
while (j > i)
|
|
*p++ = s[--j];
|
|
*p = '\0';
|
|
return str;
|
|
}
|
|
|
|
char *c_Str_cat(const char *s1, int i1, int j1,
|
|
const char *s2, int i2, int j2) {
|
|
char *str, *p;
|
|
convert(s1, i1, j1);
|
|
convert(s2, i2, j2);
|
|
p = str = C_ALLOC(j1 - i1 + j2 - i2 + 1);
|
|
while (i1 < j1)
|
|
*p++ = s1[i1++];
|
|
while (i2 < j2)
|
|
*p++ = s2[i2++];
|
|
*p = '\0';
|
|
return str;
|
|
}
|
|
|
|
char *c_Str_catv(const char *s, ...) {
|
|
char *str, *p;
|
|
const char *save = s;
|
|
int i, j, len = 0;
|
|
va_list ap;
|
|
va_start(ap, s);
|
|
while (s) {
|
|
i = va_arg(ap, int);
|
|
j = va_arg(ap, int);
|
|
convert(s, i, j);
|
|
len += j - i;
|
|
s = va_arg(ap, const char *);
|
|
}
|
|
va_end(ap);
|
|
p = str = C_ALLOC(len + 1);
|
|
s = save;
|
|
va_start(ap, s);
|
|
while (s) {
|
|
i = va_arg(ap, int);
|
|
j = va_arg(ap, int);
|
|
convert(s, i, j);
|
|
while (i < j)
|
|
*p++ = s[i++];
|
|
s = va_arg(ap, const char *);
|
|
}
|
|
va_end(ap);
|
|
*p = '\0';
|
|
return str;
|
|
}
|
|
|
|
char *c_Str_map(const char *s, int i, int j,
|
|
const char *from, const char *to) {
|
|
static char map[256] = { 0 };
|
|
if (from && to) {
|
|
unsigned c;
|
|
for (c = 0; c < sizeof map; c++)
|
|
map[c] = c;
|
|
while (*from && *to)
|
|
map[(unsigned char)*from++] = *to++;
|
|
assert(*from == 0 && *to == 0);
|
|
} else {
|
|
assert(from == NULL && to == NULL && s);
|
|
assert(map['a']);
|
|
}
|
|
if (s) {
|
|
char *str, *p;
|
|
convert(s, i, j);
|
|
p = str = C_ALLOC(j - i + 1);
|
|
while (i < j)
|
|
*p++ = map[(unsigned char)s[i++]];
|
|
*p = '\0';
|
|
return str;
|
|
} else
|
|
return NULL;
|
|
}
|
|
|
|
int c_Str_pos(const char *s, int i) {
|
|
assert(s);
|
|
const int len = (int) strlen(s);
|
|
i = idx(i, len);
|
|
assert(i >= 0 && i <= len);
|
|
return i + 1;
|
|
}
|
|
|
|
int c_Str_len(const char *s, int i, int j) {
|
|
convert(s, i, j);
|
|
return j - i;
|
|
}
|
|
|
|
int c_Str_cmp(const char *s1, int i1, int j1,
|
|
const char *s2, int i2, int j2) {
|
|
convert(s1, i1, j1);
|
|
convert(s2, i2, j2);
|
|
s1 += i1;
|
|
s2 += i2;
|
|
if (j1 - i1 < j2 - i2) {
|
|
int cond = strncmp(s1, s2, j1 - i1);
|
|
return cond == 0 ? -1 : cond;
|
|
} else if (j1 - i1 > j2 - i2) {
|
|
const int cond = strncmp(s1, s2, j2 - i2);
|
|
return cond == 0 ? +1 : cond;
|
|
} else
|
|
return strncmp(s1, s2, j1 - i1);
|
|
}
|
|
|
|
int c_Str_chr(const char *s, int i, int j, int c) {
|
|
convert(s, i, j);
|
|
for ( ; i < j; i++)
|
|
if (s[i] == c)
|
|
return i + 1;
|
|
return 0;
|
|
}
|
|
|
|
int c_Str_rchr(const char *s, int i, int j, int c) {
|
|
convert(s, i, j);
|
|
while (j > i)
|
|
if (s[--j] == c)
|
|
return j + 1;
|
|
return 0;
|
|
}
|
|
|
|
int c_Str_upto(const char *s, int i, int j,
|
|
const char *set) {
|
|
assert(set);
|
|
convert(s, i, j);
|
|
for ( ; i < j; i++)
|
|
if (strchr(set, s[i]))
|
|
return i + 1;
|
|
return 0;
|
|
}
|
|
|
|
int c_Str_rupto(const char *s, int i, int j,
|
|
const char *set) {
|
|
assert(set);
|
|
convert(s, i, j);
|
|
while (j > i)
|
|
if (strchr(set, s[--j]))
|
|
return j + 1;
|
|
return 0;
|
|
}
|
|
|
|
int c_Str_find(const char *s, int i, int j,
|
|
const char *str) {
|
|
convert(s, i, j);
|
|
assert(str);
|
|
const int len = (int)strlen(str);
|
|
if (len == 0)
|
|
return i + 1;
|
|
else if (len == 1) {
|
|
for ( ; i < j; i++)
|
|
if (s[i] == *str)
|
|
return i + 1;
|
|
} else
|
|
for ( ; i + len <= j; i++)
|
|
if ((strncmp(&s[i], str, len) == 0))
|
|
return i + 1;
|
|
return 0;
|
|
}
|
|
|
|
int c_Str_rfind(const char *s, int i, int j, const char *str) {
|
|
convert(s, i, j);
|
|
assert(str);
|
|
const int len =(int)strlen(str);
|
|
if (len == 0)
|
|
return j + 1;
|
|
else if (len == 1) {
|
|
while (j > i)
|
|
if (s[--j] == *str)
|
|
return j + 1;
|
|
} else
|
|
for ( ; j - len >= i; j--)
|
|
if (strncmp(&s[j-len], str, len) == 0)
|
|
return j - len + 1;
|
|
return 0;
|
|
}
|
|
|
|
int c_Str_any(const char *s, int i, const char *set) {
|
|
assert(s);
|
|
assert(set);
|
|
const int len =(int)strlen(s);
|
|
i = idx(i, len);
|
|
assert(i >= 0 && i <= len);
|
|
if (i < len && strchr(set, s[i]))
|
|
return i + 2;
|
|
return 0;
|
|
}
|
|
int c_Str_many(const char *s, int i, int j,
|
|
const char *set) {
|
|
assert(set);
|
|
convert(s, i, j);
|
|
if (i < j && strchr(set, s[i])) {
|
|
do
|
|
i++;
|
|
while (i < j && strchr(set, s[i]));
|
|
return i + 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int c_Str_rmany(const char *s, int i, int j,
|
|
const char *set) {
|
|
assert(set);
|
|
convert(s, i, j);
|
|
if (j > i && strchr(set, s[j-1])) {
|
|
do
|
|
--j;
|
|
while (j >= i && strchr(set, s[j]));
|
|
return j + 2;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int c_Str_match(const char *s, int i, int j, const char *str) {
|
|
convert(s, i, j);
|
|
assert(str);
|
|
const int len =(int)strlen(str);
|
|
if (len == 0)
|
|
return i + 1;
|
|
else if (len == 1) {
|
|
if (i < j && s[i] == *str)
|
|
return i + 2;
|
|
} else if (i + len <= j && (strncmp(&s[i], str, len) == 0))
|
|
return i + len + 1;
|
|
return 0;
|
|
}
|
|
|
|
int c_Str_rmatch(const char *s, int i, int j, const char *str) {
|
|
convert(s, i, j);
|
|
assert(str);
|
|
const int len =(int)strlen(str);
|
|
if (len == 0)
|
|
return j + 1;
|
|
else if (len == 1) {
|
|
if (j > i && s[j-1] == *str)
|
|
return j;
|
|
} else if (j - len >= i
|
|
&& strncmp(&s[j-len], str, len) == 0)
|
|
return j - len + 1;
|
|
return 0;
|
|
}
|
|
|
|
void c_Str_fmt(int code, va_list_box *box,
|
|
int put(int c, void *cl), void *cl,
|
|
unsigned char flags[], int width, int precision) {
|
|
assert(box && flags);
|
|
char *s = va_arg(box->ap, char *);
|
|
int i = va_arg(box->ap, int);
|
|
int j = va_arg(box->ap, int);
|
|
convert(s, i, j);
|
|
c_Fmt_puts(s + i, j - i, put, cl, flags,
|
|
width, precision);
|
|
}
|
|
|
|
void c_Str_free(char* s) {
|
|
C_FREE(s);
|
|
}
|
|
|