UNIXworkcode

1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 * 4 * Copyright 2016 Olaf Wintermann. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <stdlib.h> 30 #include <string.h> 31 #include <stdarg.h> 32 #include <ctype.h> 33 34 #include "string.h" 35 #include "allocator.h" 36 37 sstr_t sstr(char *cstring) { 38 sstr_t string; 39 string.ptr = cstring; 40 string.length = strlen(cstring); 41 return string; 42 } 43 44 sstr_t sstrn(char *cstring, size_t length) { 45 sstr_t string; 46 string.ptr = cstring; 47 string.length = length; 48 return string; 49 } 50 51 size_t sstrnlen(size_t n, sstr_t s, ...) { 52 va_list ap; 53 size_t size = s.length; 54 va_start(ap, s); 55 56 for (size_t i = 1 ; i < n ; i++) { 57 sstr_t str = va_arg(ap, sstr_t); 58 size += str.length; 59 } 60 va_end(ap); 61 62 return size; 63 } 64 65 static sstr_t sstrvcat_a( 66 UcxAllocator *a, 67 size_t count, 68 sstr_t s1, 69 sstr_t s2, 70 va_list ap) { 71 sstr_t str; 72 str.ptr = NULL; 73 str.length = 0; 74 if(count < 2) { 75 return str; 76 } 77 78 sstr_t *strings = (sstr_t*) calloc(count, sizeof(sstr_t)); 79 if(!strings) { 80 return str; 81 } 82 83 // get all args and overall length 84 strings[0] = s1; 85 strings[1] = s2; 86 size_t strlen = s1.length + s2.length; 87 for (size_t i=2;i<count;i++) { 88 sstr_t s = va_arg (ap, sstr_t); 89 strings[i] = s; 90 strlen += s.length; 91 } 92 93 // create new string 94 str.ptr = (char*) almalloc(a, strlen + 1); 95 str.length = strlen; 96 if(!str.ptr) { 97 free(strings); 98 str.length = 0; 99 return str; 100 } 101 102 // concatenate strings 103 size_t pos = 0; 104 for (size_t i=0;i<count;i++) { 105 sstr_t s = strings[i]; 106 memcpy(str.ptr + pos, s.ptr, s.length); 107 pos += s.length; 108 } 109 110 str.ptr[str.length] = '\0'; 111 112 free(strings); 113 114 return str; 115 } 116 117 sstr_t sstrcat(size_t count, sstr_t s1, sstr_t s2, ...) { 118 va_list ap; 119 va_start(ap, s2); 120 sstr_t s = sstrvcat_a(ucx_default_allocator(), count, s1, s2, ap); 121 va_end(ap); 122 return s; 123 } 124 125 sstr_t sstrcat_a(UcxAllocator *a, size_t count, sstr_t s1, sstr_t s2, ...) { 126 va_list ap; 127 va_start(ap, s2); 128 sstr_t s = sstrvcat_a(a, count, s1, s2, ap); 129 va_end(ap); 130 return s; 131 } 132 133 sstr_t sstrsubs(sstr_t s, size_t start) { 134 return sstrsubsl (s, start, s.length-start); 135 } 136 137 sstr_t sstrsubsl(sstr_t s, size_t start, size_t length) { 138 sstr_t new_sstr; 139 if (start >= s.length) { 140 new_sstr.ptr = NULL; 141 new_sstr.length = 0; 142 } else { 143 if (length > s.length-start) { 144 length = s.length-start; 145 } 146 new_sstr.ptr = &s.ptr[start]; 147 new_sstr.length = length; 148 } 149 return new_sstr; 150 } 151 152 sstr_t sstrchr(sstr_t s, int c) { 153 for(size_t i=0;i<s.length;i++) { 154 if(s.ptr[i] == c) { 155 return sstrsubs(s, i); 156 } 157 } 158 sstr_t n; 159 n.ptr = NULL; 160 n.length = 0; 161 return n; 162 } 163 164 sstr_t sstrrchr(sstr_t s, int c) { 165 if (s.length > 0) { 166 for(size_t i=s.length;i>0;i--) { 167 if(s.ptr[i-1] == c) { 168 return sstrsubs(s, i-1); 169 } 170 } 171 } 172 sstr_t n; 173 n.ptr = NULL; 174 n.length = 0; 175 return n; 176 } 177 178 sstr_t sstrstr(sstr_t string, sstr_t match) { 179 if (match.length == 0) { 180 return string; 181 } 182 183 for (size_t i = 0 ; i < string.length ; i++) { 184 sstr_t substr = sstrsubs(string, i); 185 if (sstrprefix(substr, match)) { 186 return substr; 187 } 188 } 189 190 sstr_t emptystr; 191 emptystr.length = 0; 192 emptystr.ptr = NULL; 193 return emptystr; 194 } 195 196 sstr_t* sstrsplit(sstr_t s, sstr_t d, ssize_t *n) { 197 return sstrsplit_a(ucx_default_allocator(), s, d, n); 198 } 199 200 sstr_t* sstrsplit_a(UcxAllocator *allocator, sstr_t s, sstr_t d, ssize_t *n) { 201 if (s.length == 0 || d.length == 0) { 202 *n = -1; 203 return NULL; 204 } 205 206 sstr_t* result; 207 ssize_t nmax = *n; 208 *n = 1; 209 210 /* special case: exact match - no processing needed */ 211 if (sstrcmp(s, d) == 0) { 212 *n = 0; 213 return NULL; 214 } 215 sstr_t sv = sstrdup(s); 216 if (sv.length == 0) { 217 *n = -2; 218 return NULL; 219 } 220 221 for (size_t i = 0 ; i < s.length ; i++) { 222 sstr_t substr = sstrsubs(sv, i); 223 if (sstrprefix(substr, d)) { 224 (*n)++; 225 for (size_t j = 0 ; j < d.length ; j++) { 226 sv.ptr[i+j] = 0; 227 } 228 i += d.length - 1; // -1, because the loop will do a i++ 229 } 230 if ((*n) == nmax) break; 231 } 232 result = (sstr_t*) almalloc(allocator, sizeof(sstr_t)*(*n)); 233 234 if (result) { 235 char *pptr = sv.ptr; 236 for (ssize_t i = 0 ; i < *n ; i++) { 237 size_t l = strlen(pptr); 238 char* ptr = (char*) almalloc(allocator, l + 1); 239 if (ptr) { 240 memcpy(ptr, pptr, l); 241 ptr[l] = 0; 242 243 result[i] = sstrn(ptr, l); 244 pptr += l + d.length; 245 } else { 246 for (ssize_t j = i-1 ; j >= 0 ; j--) { 247 alfree(allocator, result[j].ptr); 248 } 249 alfree(allocator, result); 250 *n = -2; 251 break; 252 } 253 } 254 } else { 255 *n = -2; 256 } 257 258 free(sv.ptr); 259 260 return result; 261 } 262 263 int sstrcmp(sstr_t s1, sstr_t s2) { 264 if (s1.length == s2.length) { 265 return memcmp(s1.ptr, s2.ptr, s1.length); 266 } else if (s1.length > s2.length) { 267 return 1; 268 } else { 269 return -1; 270 } 271 } 272 273 int sstrcasecmp(sstr_t s1, sstr_t s2) { 274 if (s1.length == s2.length) { 275 #ifdef _WIN32 276 return _strnicmp(s1.ptr, s2.ptr, s1.length); 277 #else 278 return strncasecmp(s1.ptr, s2.ptr, s1.length); 279 #endif 280 } else if (s1.length > s2.length) { 281 return 1; 282 } else { 283 return -1; 284 } 285 } 286 287 sstr_t sstrdup(sstr_t s) { 288 return sstrdup_a(ucx_default_allocator(), s); 289 } 290 291 sstr_t sstrdup_a(UcxAllocator *allocator, sstr_t s) { 292 sstr_t newstring; 293 newstring.ptr = (char*)almalloc(allocator, s.length + 1); 294 if (newstring.ptr) { 295 newstring.length = s.length; 296 newstring.ptr[newstring.length] = 0; 297 298 memcpy(newstring.ptr, s.ptr, s.length); 299 } else { 300 newstring.length = 0; 301 } 302 303 return newstring; 304 } 305 306 sstr_t sstrtrim(sstr_t string) { 307 sstr_t newstr = string; 308 309 while (newstr.length > 0 && isspace(*newstr.ptr)) { 310 newstr.ptr++; 311 newstr.length--; 312 } 313 while (newstr.length > 0 && isspace(newstr.ptr[newstr.length-1])) { 314 newstr.length--; 315 } 316 317 return newstr; 318 } 319 320 int sstrprefix(sstr_t string, sstr_t prefix) { 321 if (string.length == 0) { 322 return prefix.length == 0; 323 } 324 if (prefix.length == 0) { 325 return 1; 326 } 327 328 if (prefix.length > string.length) { 329 return 0; 330 } else { 331 return memcmp(string.ptr, prefix.ptr, prefix.length) == 0; 332 } 333 } 334 335 int sstrsuffix(sstr_t string, sstr_t suffix) { 336 if (string.length == 0) { 337 return suffix.length == 0; 338 } 339 if (suffix.length == 0) { 340 return 1; 341 } 342 343 if (suffix.length > string.length) { 344 return 0; 345 } else { 346 return memcmp(string.ptr+string.length-suffix.length, 347 suffix.ptr, suffix.length) == 0; 348 } 349 } 350 351 sstr_t sstrlower(sstr_t string) { 352 sstr_t ret = sstrdup(string); 353 for (size_t i = 0; i < ret.length ; i++) { 354 ret.ptr[i] = tolower(ret.ptr[i]); 355 } 356 return ret; 357 } 358 359 sstr_t sstrlower_a(UcxAllocator *allocator, sstr_t string) { 360 sstr_t ret = sstrdup_a(allocator, string); 361 for (size_t i = 0; i < ret.length ; i++) { 362 ret.ptr[i] = tolower(ret.ptr[i]); 363 } 364 return ret; 365 } 366 367 sstr_t sstrupper(sstr_t string) { 368 sstr_t ret = sstrdup(string); 369 for (size_t i = 0; i < ret.length ; i++) { 370 ret.ptr[i] = toupper(ret.ptr[i]); 371 } 372 return ret; 373 } 374 375 sstr_t sstrupper_a(UcxAllocator *allocator, sstr_t string) { 376 sstr_t ret = sstrdup_a(allocator, string); 377 for (size_t i = 0; i < ret.length ; i++) { 378 ret.ptr[i] = toupper(ret.ptr[i]); 379 } 380 return ret; 381 } 382