links/string.c
2021-08-28 18:37:32 +03:00

324 lines
6.8 KiB
C

/* string.c
* (c) 2002 Mikulas Patocka
* This file is a part of the Links program, released under GPL.
*/
#include "links.h"
int snprint(unsigned char *s, int n, my_uintptr_t num)
{
my_uintptr_t q = 1;
while (q <= num / 10) q *= 10;
while (n-- > 1 && q) {
*(s++) = (unsigned char)(num / q + '0');
num %= q;
#ifdef __DECC_VER
do_not_optimize_here(&q); /* compiler bug */
#endif
q /= 10;
}
*s = 0;
return !!q;
}
int snzprint(unsigned char *s, int n, off_t num)
{
off_t q = 1;
if (n > 1 && num < 0) *(s++) = '-', num = -num, n--;
while (q <= num / 10) q *= 10;
while (n-- > 1 && q) {
*(s++) = (unsigned char)(num / q + '0');
num %= q;
#ifdef __DECC_VER
do_not_optimize_here(&q); /* compiler bug */
#endif
q /= 10;
}
*s = 0;
return !!q;
}
void add_to_strn(unsigned char **s, unsigned char *a)
{
unsigned char *p;
size_t l1 = strlen(cast_const_char *s), l2 = strlen(cast_const_char a);
if (((l1 | l2) | (l1 + l2 + 1)) > MAXINT) overalloc();
p = (unsigned char *)mem_realloc(*s, l1 + l2 + 1);
strcat(cast_char p, cast_const_char a);
*s = p;
}
void extend_str(unsigned char **s, int n)
{
size_t l = strlen(cast_const_char *s);
if (((l | n) | (l + n + 1)) > MAXINT) overalloc();
*s = (unsigned char *)mem_realloc(*s, l + n + 1);
}
void add_bytes_to_str(unsigned char **s, int *l, unsigned char *a, size_t ll)
{
unsigned char *p;
size_t old_length;
size_t new_length;
size_t x;
if (!ll)
return;
p = *s;
old_length = (unsigned)*l;
if (ll + old_length >= (unsigned)MAXINT / 2 || ll + old_length < ll) overalloc();
new_length = old_length + ll;
*l = (int)new_length;
x = old_length ^ new_length;
if (x >= old_length) {
/* Need to realloc */
#ifdef HAVE___BUILTIN_CLZ
#if !( \
defined(__tune_i386__) || \
defined(__tune_i486__) || \
defined(__tune_i586__) || \
defined(__tune_k6__) || \
defined(__tune_lakemont__) || \
(defined(__alpha__) && !defined(__alpha_cix__)) || \
(defined(__mips) && __mips < 32) || \
(defined(__ARM_ARCH) && __ARM_ARCH < 5) || \
(defined(__sparc__) && (!defined(__VIS__) || __VIS__ < 0x300)) ||\
defined(__hppa) || \
defined(__riscv) || \
defined(__sh__))
if (!(sizeof(unsigned) & (sizeof(unsigned) - 1))) {
new_length = 2U << ((sizeof(unsigned) * 8 - 1)
#ifdef __ICC
-
#else
^
#endif
__builtin_clz(new_length));
} else
#endif
#endif
{
new_length |= new_length >> 1;
new_length |= new_length >> 2;
new_length |= new_length >> 4;
new_length |= new_length >> 8;
new_length |= new_length >> 16;
new_length++;
}
p = (unsigned char *)mem_realloc(p, new_length);
*s = p;
}
p[*l] = 0;
memcpy(p + old_length, a, ll);
}
void add_to_str(unsigned char **s, int *l, unsigned char *a)
{
add_bytes_to_str(s, l, a, strlen(cast_const_char a));
}
void add_chr_to_str(unsigned char **s, int *l, unsigned char a)
{
add_bytes_to_str(s, l, &a, 1);
}
void add_unsigned_long_num_to_str(unsigned char **s, int *l, my_uintptr_t n)
{
unsigned char a[64];
snprint(a, 64, n);
add_to_str(s, l, a);
}
void add_num_to_str(unsigned char **s, int *l, off_t n)
{
unsigned char a[64];
if (n >= 0 && n < 1000) {
unsigned sn = (unsigned)n;
unsigned char *p = a;
if (sn >= 100) {
*p++ = '0' + sn / 100;
sn %= 100;
goto d10;
}
if (sn >= 10) {
d10:
*p++ = '0' + sn / 10;
sn %= 10;
}
*p++ = '0' + sn;
add_bytes_to_str(s, l, a, p - a);
} else {
snzprint(a, 64, n);
add_to_str(s, l, a);
}
}
void add_knum_to_str(unsigned char **s, int *l, off_t n)
{
unsigned char a[13];
if (n && n / (1024 * 1024) * (1024 * 1024) == n) snzprint(a, 12, n / (1024 * 1024)), a[strlen(cast_const_char a) + 1] = 0, a[strlen(cast_const_char a)] = 'M';
else if (n && n / 1024 * 1024 == n) snzprint(a, 12, n / 1024), a[strlen(cast_const_char a) + 1] = 0, a[strlen(cast_const_char a)] = 'k';
else snzprint(a, 13, n);
add_to_str(s, l, a);
}
long strtolx(unsigned char *c, unsigned char **end)
{
char *end_c;
long l;
if (c[0] == '0' && upcase(c[1]) == 'X' && c[2]) l = strtol(cast_const_char(c + 2), &end_c, 16);
else l = strtol(cast_const_char c, &end_c, 10);
*end = cast_uchar end_c;
if (upcase(**end) == 'K') {
(*end)++;
if (l < -MAXINT / 1024) return -MAXINT;
if (l > MAXINT / 1024) return MAXINT;
return l * 1024;
}
if (upcase(**end) == 'M') {
(*end)++;
if (l < -MAXINT / (1024 * 1024)) return -MAXINT;
if (l > MAXINT / (1024 * 1024)) return MAXINT;
return l * (1024 * 1024);
}
return l;
}
my_strtoll_t my_strtoll(unsigned char *string, unsigned char **end)
{
char *end_c;
my_strtoll_t f;
errno = 0;
#if defined(HAVE_STRTOLL)
f = strtoll(cast_const_char string, &end_c, 10);
#elif defined(HAVE_STRTOQ)
f = strtoq(cast_const_char string, &end_c, 10);
#elif defined(HAVE_STRTOIMAX)
f = strtoimax(cast_const_char string, &end_c, 10);
#else
f = strtol(cast_const_char string, &end_c, 10);
#endif
if (end)
*end = cast_uchar end_c;
if (f < 0 || errno) return -1;
return f;
}
/* Copies at most dst_size chars into dst. Ensures null termination of dst. */
void safe_strncpy(unsigned char *dst, const unsigned char *src, size_t dst_size)
{
dst[dst_size - 1] = 0;
strncpy(cast_char dst, cast_const_char src, dst_size - 1);
}
#ifdef JS
/* deletes all nonprintable characters from string */
void skip_nonprintable(unsigned char *txt)
{
unsigned char *txt1=txt;
if (!txt||!*txt)return;
for (;*txt;txt++)
switch(*txt)
{
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 11:
case 12:
case 13:
case 14:
case 15:
case 16:
case 17:
case 18:
case 19:
case 20:
case 21:
case 22:
case 23:
case 24:
case 25:
case 26:
case 27:
case 28:
case 29:
case 30:
case 31:
break;
case 9:
*txt1=' ';
txt1++;
break;
default:
*txt1=*txt;
txt1++;
break;
}
*txt1=0;
}
#endif
/* don't use strcasecmp because it depends on locale */
int casestrcmp(const unsigned char *s1, const unsigned char *s2)
{
while (1) {
unsigned char c1 = *s1;
unsigned char c2 = *s2;
c1 = locase(c1);
c2 = locase(c2);
if (c1 != c2) {
return (int)c1 - (int)c2;
}
if (!*s1) break;
s1++, s2++;
}
return 0;
}
/* case insensitive compare of 2 strings */
/* comparison ends after len (or less) characters */
/* return value: 1=strings differ, 0=strings are same */
int casecmp(const unsigned char *c1, const unsigned char *c2, size_t len)
{
size_t i;
for (i = 0; i < len; i++) if (srch_cmp(c1[i], c2[i])) return 1;
return 0;
}
int casestrstr(const unsigned char *h, const unsigned char *n)
{
const unsigned char *p;
for (p=h;*p;p++)
{
if (!srch_cmp(*p,*n)) /* same */
{
const unsigned char *q, *r;
for (q=n, r=p;*r&&*q;)
{
if (!srch_cmp(*q,*r)) r++,q++; /* same */
else break;
}
if (!*q) return 1;
}
}
return 0;
}
unsigned hash_string(unsigned char *u)
{
unsigned hash = 0;
for (; *u; u++)
hash = hash * 0x11 + *u;
return hash;
}