links

lynx-like text mode web browser
git clone anongit@rnpnr.xyz:links.git
Log | Files | Refs | Feed | README | LICENSE

string.c (5212B)


      1 /* string.c
      2  * (c) 2002 Mikulas Patocka
      3  * This file is a part of the Links program, released under GPL.
      4  */
      5 
      6 #include <limits.h>
      7 
      8 #include "links.h"
      9 
     10 /* case insensitive compare of 2 strings */
     11 /* comparison ends after len (or less) characters */
     12 /* return value: 1=strings differ, 0=strings are same */
     13 static inline int
     14 srch_cmp(unsigned char c1, unsigned char c2)
     15 {
     16 	return upcase(c1) != upcase(c2);
     17 }
     18 
     19 int
     20 cmpbeg(const unsigned char *str, const unsigned char *b)
     21 {
     22 	while (*str && upcase(*str) == upcase(*b)) {
     23 		str++;
     24 		b++;
     25 	}
     26 	return !!*b;
     27 }
     28 
     29 int
     30 xstrcmp(const unsigned char *s1, const unsigned char *s2)
     31 {
     32 	if (!s1 && !s2)
     33 		return 0;
     34 	if (!s1)
     35 		return -1;
     36 	if (!s2)
     37 		return 1;
     38 	return strcmp(cast_const_char s1, cast_const_char s2);
     39 }
     40 
     41 int
     42 snprint(unsigned char *s, int n, int num)
     43 {
     44 	int q = 1;
     45 	while (q <= num / 10)
     46 		q *= 10;
     47 	while (n-- > 1 && q) {
     48 		*(s++) = (unsigned char)(num / q + '0');
     49 		num %= q;
     50 		q /= 10;
     51 	}
     52 	*s = 0;
     53 	return !!q;
     54 }
     55 
     56 int
     57 snzprint(unsigned char *s, int n, off_t num)
     58 {
     59 	off_t q = 1;
     60 	if (n > 1 && num < 0) {
     61 		*(s++) = '-';
     62 		num = -num;
     63 		n--;
     64 	}
     65 	while (q <= num / 10)
     66 		q *= 10;
     67 	while (n-- > 1 && q) {
     68 		*(s++) = (unsigned char)(num / q + '0');
     69 		num %= q;
     70 		q /= 10;
     71 	}
     72 	*s = 0;
     73 	return !!q;
     74 }
     75 
     76 void
     77 add_to_strn(unsigned char **s, unsigned char *a)
     78 {
     79 	unsigned char *p;
     80 	size_t l1 = strlen(cast_const_char * s), l2 = strlen(cast_const_char a);
     81 	if (((l1 | l2) | (l1 + l2 + 1)) > INT_MAX)
     82 		overalloc();
     83 	p = xrealloc(*s, l1 + l2 + 1);
     84 	strcat(cast_char p, cast_const_char a);
     85 	*s = p;
     86 }
     87 
     88 void
     89 extend_str(unsigned char **s, int n)
     90 {
     91 	size_t l = strlen(cast_const_char * s);
     92 	if (((l | n) | (l + n + 1)) > INT_MAX)
     93 		overalloc();
     94 	*s = xrealloc(*s, l + n + 1);
     95 }
     96 
     97 /* returns: new text length excluding the 0 byte */
     98 size_t
     99 add_bytes_to_str(unsigned char **s, size_t sl, unsigned char *a, size_t al)
    100 {
    101 	unsigned char *p = *s;
    102 	size_t ol = sl;
    103 
    104 	if (al == 0)
    105 		return ol;
    106 
    107 	sl += al;
    108 	p = xreallocarray(p, sl + 1, sizeof(unsigned char));
    109 	p[sl] = 0;
    110 	memcpy(p + ol, a, al);
    111 	*s = p;
    112 
    113 	return sl;
    114 }
    115 
    116 size_t
    117 add_to_str(unsigned char **s, size_t l, unsigned char *a)
    118 {
    119 	return add_bytes_to_str(s, l, a, strlen(cast_const_char a));
    120 }
    121 
    122 size_t
    123 add_chr_to_str(unsigned char **s, size_t sl, unsigned char a)
    124 {
    125 	return add_bytes_to_str(s, sl, &a, 1);
    126 }
    127 
    128 void
    129 add_unsigned_long_num_to_str(unsigned char **s, int *l, unsigned long n)
    130 {
    131 	unsigned char a[64];
    132 	snprint(a, 64, n);
    133 	*l = add_to_str(s, *l, a);
    134 }
    135 
    136 size_t
    137 add_num_to_str(unsigned char **s, size_t l, off_t n)
    138 {
    139 	unsigned char a[64];
    140 	if (n >= 0 && n < 1000) {
    141 		unsigned sn = (unsigned)n;
    142 		unsigned char *p = a;
    143 		if (sn >= 100) {
    144 			*p++ = '0' + sn / 100;
    145 			sn %= 100;
    146 			goto d10;
    147 		}
    148 		if (sn >= 10) {
    149 d10:
    150 			*p++ = '0' + sn / 10;
    151 			sn %= 10;
    152 		}
    153 		*p++ = '0' + sn;
    154 		l = add_bytes_to_str(s, l, a, p - a);
    155 	} else {
    156 		snzprint(a, 64, n);
    157 		l = add_to_str(s, l, a);
    158 	}
    159 
    160 	return l;
    161 }
    162 
    163 size_t
    164 add_knum_to_str(unsigned char **s, size_t l, off_t n)
    165 {
    166 	unsigned char a[13];
    167 	if (n && n / (1024 * 1024) * (1024 * 1024) == n) {
    168 		snzprint(a, 12, n / (1024 * 1024));
    169 		a[strlen(cast_const_char a) + 1] = 0;
    170 		a[strlen(cast_const_char a)] = 'M';
    171 	} else if (n && n / 1024 * 1024 == n) {
    172 		snzprint(a, 12, n / 1024);
    173 		a[strlen(cast_const_char a) + 1] = 0;
    174 		a[strlen(cast_const_char a)] = 'k';
    175 	} else
    176 		snzprint(a, 13, n);
    177 	return add_to_str(s, l, a);
    178 }
    179 
    180 long
    181 strtolx(unsigned char *c, unsigned char **end)
    182 {
    183 	char *end_c;
    184 	long l;
    185 	if (c[0] == '0' && upcase(c[1]) == 'X' && c[2])
    186 		l = strtol(cast_const_char(c + 2), &end_c, 16);
    187 	else
    188 		l = strtol(cast_const_char c, &end_c, 10);
    189 	*end = cast_uchar end_c;
    190 	if (upcase(**end) == 'K') {
    191 		(*end)++;
    192 		if (l < -INT_MAX / 1024)
    193 			return -INT_MAX;
    194 		if (l > INT_MAX / 1024)
    195 			return INT_MAX;
    196 		return l * 1024;
    197 	}
    198 	if (upcase(**end) == 'M') {
    199 		(*end)++;
    200 		if (l < -INT_MAX / (1024 * 1024))
    201 			return -INT_MAX;
    202 		if (l > INT_MAX / (1024 * 1024))
    203 			return INT_MAX;
    204 		return l * (1024 * 1024);
    205 	}
    206 	return l;
    207 }
    208 
    209 /* Copies at most dst_size chars into dst. Ensures null termination of dst. */
    210 void
    211 safe_strncpy(unsigned char *dst, const unsigned char *src, size_t dst_size)
    212 {
    213 	dst[dst_size - 1] = 0;
    214 	strncpy(cast_char dst, cast_const_char src, dst_size - 1);
    215 }
    216 
    217 /* don't use strcasecmp because it depends on locale */
    218 int
    219 casestrcmp(const unsigned char *s1, const unsigned char *s2)
    220 {
    221 	while (1) {
    222 		unsigned char c1 = *s1;
    223 		unsigned char c2 = *s2;
    224 		c1 = locase(c1);
    225 		c2 = locase(c2);
    226 		if (c1 != c2) {
    227 			return (int)c1 - (int)c2;
    228 		}
    229 		if (!*s1)
    230 			break;
    231 		s1++;
    232 		s2++;
    233 	}
    234 	return 0;
    235 }
    236 
    237 /* case insensitive compare of 2 strings */
    238 /* comparison ends after len (or less) characters */
    239 /* return value: 1=strings differ, 0=strings are same */
    240 int
    241 casecmp(const unsigned char *c1, const unsigned char *c2, size_t len)
    242 {
    243 	size_t i;
    244 	for (i = 0; i < len; i++)
    245 		if (srch_cmp(c1[i], c2[i]))
    246 			return 1;
    247 	return 0;
    248 }
    249 
    250 int
    251 casestrstr(const unsigned char *h, const unsigned char *n)
    252 {
    253 	const unsigned char *p;
    254 
    255 	for (p = h; *p; p++) {
    256 		if (!srch_cmp(*p, *n)) /* same */
    257 		{
    258 			const unsigned char *q, *r;
    259 			for (q = n, r = p; *r && *q;) {
    260 				if (!srch_cmp(*q, *r)) {
    261 					r++;
    262 					q++; /* same */
    263 				} else
    264 					break;
    265 			}
    266 			if (!*q)
    267 				return 1;
    268 		}
    269 	}
    270 
    271 	return 0;
    272 }