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 }