libsheepyBt.h (24518B)
1 /* 2 * btt is a dynamic Byte buffer Type (Bytes Type) 3 * 4 * Status: under development, not tested, the comments don't match the implementation 5 * 6 * # How btt works 7 * 8 * When a btt object represents a string, it doesn't need to be NUL terminated, 9 * this allow spliting string more efficiently. 10 * 11 * - simple to use 12 * - binary safe 13 * - computationally efficient 14 * - works with memcheck 15 * 16 * 17 * # Advantages and disadvantages of btt 18 * 19 * btt is implemented using a structure defining the byte buffer like this: 20 * ``` 21 * struct { 22 * u8 *b; 23 * u32 len; 24 * u32 alloc; 25 * } btt; 26 * ``` 27 * when b is on the heap (even len 0), alloc is above 0 28 * 29 * The btt structure is managed by the *B functions. 30 * The *B (not b*B) functions don't modify the first btt parameter. 31 * The functions named b*B modify the first bbt pointer parameter and return a btt pointer. 32 * The functions named *PB take a btt pointer whereas *B function take a btt struct as parameter. 33 * *BB functions take btt struct in all string parameters 34 * 35 * - Disadvantage 1: btt doesn't work with standard C string functions 36 * 37 * - Advantage 1: Giving the address of a btt to B functions, updates the btt in place: 38 * ``` 39 * pushBG(&b, s); 40 * ``` 41 * 42 * - Advantage 2: trimming and slicing buffers don't need memory allocations and spliting uses less memory allocations 43 * 44 * - Advantage 3: the index for accessing the bytes in btt is range check in the getB, setB functions and it works even the buffer in btt is reallocated 45 * 46 * 47 * # btt basics 48 * 49 * Here is how to declare a btt, assign a string (RO) and print it: 50 * 51 * ``` 52 * btt mystring = ccharB("Hello World!"); 53 * printB(mystring); 54 * 55 * output> Hello World! 56 * ``` 57 * 58 * The above small program shows a few important things about btt: 59 * - btt are stack allocated (or heap allocated) 60 * - printB prints the btt content 61 * - there is no memory allocations so there is no free. 62 * 63 * 64 * # Creating btt strings 65 * 66 * ``` 67 * btt mystring = ccharB("Hello World!"); 68 * btt mystring2 = charB(strdup("Hello World!")); 69 * btt mybuf = voidB("Binary", sizeof("Binary"), false); 70 * createCharB(mystring3, "bytes", false); 71 * // from another string: 72 * btt mirror = mystring; 73 * btt empty = {0}; 74 * // preallocate buf 75 * btt pre = newB(allocateSize); 76 * // allocate btt struct and buf 77 * btt *heap = allocNewB(allocateSize); 78 * 79 * // allocate and set string 80 * btt *new = allocB("STR", false); 81 * finishB(new); 82 * ``` 83 * 84 * # Obtaining the string length 85 * 86 * ``` 87 * int len = mystring.len; 88 * ``` 89 * 90 * 91 * # Destroying strings 92 * 93 * - freeB frees the buffer pointed by .b and can be called with non allocated btt objects (it does nothing) 94 * - terminateB frees the buffer if allocated and the btt struct 95 * - finishB frees the btt struct only (doesn't touch the .b buffer) 96 * 97 * 98 * # Concatenating strings 99 * 100 * ``` 101 * createCharB(str, strdup("Hello "), true); 102 * pushBG(&str, "World!"); 103 * printB(str); 104 * freeB(str); 105 * 106 * output> Hello World! 107 * ``` 108 * 109 * 110 * # TODO Formatting strings 111 * 112 * 113 * # Trimming and slicing 114 * 115 * ``` 116 * btt T = ccharB(" trim "); 117 * btt r = trimB(T); 118 * btt s = sliceB(T, 2, 6); 119 * ``` 120 * 121 * 122 * # String copying 123 * 124 * ``` 125 * // copy btt 126 * btt mystringCopy = copyB(mystring); 127 * // the buffer in mystringCopy is heap allocated 128 * freeB(mystringCopy); 129 * 130 * // duplicate btt 131 * btt *dup = dupB(mystring); 132 * // dup and the buffer in dup are heap allocated 133 * terminateB(dup); 134 * ``` 135 * 136 * # Splitting strings 137 * 138 * ``` 139 * btt ss = ccharB("Hello World!"); 140 * vbtt ll = splitB(ss, " "); 141 * puts(""); 142 * vectorForEach(&ll, e) { 143 * printB(*e); 144 * puts(""); 145 * } 146 * vectorFree(&ll); 147 * ``` 148 * 149 * 150 * # Inner workings 151 * 152 * When alloc is 0 and len > 0, the buffer has not been allocated 153 * 154 * createCharB declares a btt object with the given string, there is no allocation 155 * 156 * Appending strings: 157 * s is updated, b or i are same 158 * bPushB(&s, "qwqw"); 159 * bPushManyB(&s, "qwqw", "qweqw"); 160 * 161 * New string: 162 * 1 malloc (better cache locality): 163 * btt s2 = pushB(s, "qweqwe"); 164 * btt s3 = pushManyB(s, "qweqwe", "wer"); 165 * 166 * //2 mallocs: 167 * //btt *s4 = appendB(s, "qweqwe"); 168 * //btt *s5 = appendManyB(s, "qweqwe", "wer"); 169 * 170 * btt s6 = catB("1","2"); 171 * 172 * pushB(&s, s2); 173 * 174 * Printing string: 175 * logI("%q", &s); 176 * printf("%c %c\n", s.b[0], s.b[1]); 177 * 178 * Spliting string doesn't require any buffer copying 179 * createCharB(h, "Hello World!", 0); 180 * 181 * btt h2 = {0}; 182 * h2.b = h.b+6; 183 * h2.len = 5; 184 * 185 * Example: 186 * Empty btt: 187 * btt s = {0}; 188 * Assign C string: 189 * s = voidB("a string", no); 190 * s.b = "asdasd"; 191 * b.len = strlen(s.b); 192 * 193 */ 194 #pragma once 195 196 #include "libsheepy.h" 197 198 // btt bytes type 199 // point to a byte buffer at .b of length .len 200 // .alloc is the allocated size of the buffer 201 typ struct { 202 u8 *b; 203 u32 len; 204 u32 alloc; 205 } btt; 206 207 typ struct { 208 u8 *b; 209 u64 len; 210 u64 alloc; 211 } bt64t; 212 // TODO functions supporting bt64t 213 214 // vector of btt elements 215 // This data structure has good performance for small element counts 216 typ struct { 217 u32 count; 218 u32 maxCount; 219 btt *array; 220 } vbtt; 221 222 // dynamic segmented vector of btt elements 223 // This data structure has good performance for large element counts 224 typ struct { 225 u32 count; 226 u32 maxCount; 227 void** buffers; 228 btt element; 229 } dbtt; 230 231 // object returned by some functions 232 #define emptybt ((btt){0}) 233 #define emptyvbt ((vbtt){0}) 234 #define emptydbt ((dbtt){0}) 235 236 237 // assign a u8 a[count] array to btt object 238 // Example: 239 // u8 s[10] = {0}; 240 // btt b; 241 // arrayB(b, s); 242 #define arrayB(name, a)\ 243 (name).b = a; (name).len = 0; (name).alloc = ARRAY_SIZE(a) 244 245 // declare name vbtt object and assign the a array defined as btt a[maxCnt] with cnt element already initialized 246 #define vectorB(name, a, cnt, maxCnt)\ 247 vbtt name; name.count = cnt; name.maxCount = maxCnt; name.array = a 248 249 // declare name vbtt object, declare the a array of count btt elements and assign it to name the vbtt object 250 #define listB(name, a, maxCnt)\ 251 btt a[maxCnt] = {0}; vbtt name; name.count = 0; name.maxCount = maxCnt; name.array = a 252 253 // declare name vbtt object and assign the empty a array defined as btt a[maxCnt] 254 #define listAB(name, a)\ 255 vbtt name; name.count = 0; name.maxCount = ARRAY_SIZE(a); name.array = a 256 257 // initialize a btt object with a heap allocated string 258 #define charB(string) (btt){.b = string, .len = strlen(string), .alloc = strlen(string)} 259 // initialize a btt object with a string that can't be reallocated 260 #define ccharB(string) (btt){.b = string, .len = strlen(string), .alloc = 0 } 261 // initialize a btt object with a heap allocated binary buffer 262 #define voidB( buf, length, allocated) (btt){.b = buf, .len = length, .alloc = (allocated) ? length : 0 } 263 264 265 /** 266 * declare pointer name with type btt and terminate name when it is out of scope 267 */ 268 #define cleanBP(name) btt *name CLEANUP(cleanUpTerminateB) 269 270 /** 271 * allocate btt (pointer) and clean up when it is out of scope 272 */ 273 #define cleanAllocateB(obj) ;cleanBP(obj); obj = allocNewB(8) 274 275 /** 276 * declare local object name with type btt and free name when it is out of scope 277 */ 278 #define cleanB(name) btt name CLEANUP(cleanUpFreeLocalB) 279 280 /** 281 * declare pointer name with type btt and free name when it is out of scope 282 */ 283 #define cleanFreeBP(name) btt *name CLEANUP(cleanUpFreeB) 284 285 /** 286 * declare pointer name with type btt and finish name when it is out of scope 287 */ 288 #define cleanFinishBP(name) btt *name CLEANUP(cleanUpFinishB) 289 290 // create name btt object and initialize it with a string 291 // string is char* and is evaluated one time, allocated true/false 292 #define createCharB(name, string, allocated) btt name;u8 *UNIQVAR(s) = (u8*)string;name.b = UNIQVAR(s); name.len = strlen(UNIQVAR(s)); name.alloc = (allocated) ? name.len : 0 293 294 // create name btt object and initialize it with a binary buffer 295 #define createB(name, buf, length, allocated) btt name;name.b = buf; name.len = len; name.alloc = (allocated) ? name.length : 0 296 297 #define createAllocateCharB(name, string, allocated)\ 298 btt *name = malloc(sizeof(*name)); u8 *UNIQVAR(s) = (u8*)string;name->b = UNIQVAR(s); name->len = strlen(UNIQVAR(s)); name->alloc = (allocated) ? name->len : 0 299 300 #define createAllocateB(name, buf, length, allocated)\ 301 btt *name = malloc(sizeof(*name));name->b = buf; name->len = length; name->alloc = (allocated) ? name->len : 0 302 303 // create clean name btt object and initialize it with a string 304 // string is char* and is evaluated one time 305 #define cleanCharB(name, string) cleanB(name);u8 *UNIQVAR(s) = (u8*)string;name.b = UNIQVAR(s); name.len = strlen(UNIQVAR(s)); name.alloc = name.len 306 307 // create clean name btt object and initialize it with a binary buffer 308 #define ccleanB(name, buf, length) cleanB(name);name.b = buf; name.len = len; name.alloc = name.length 309 310 #define cleanAllocateCharB(name, string, allocated)\ 311 cleanBP(name) = malloc(sizeof(*name)); u8 *UNIQVAR(s) = (u8*)string;name->b = UNIQVAR(s); name->len = strlen(UNIQVAR(s)); name->alloc = (allocated) ? name->len : 0 312 313 #define ccleanAllocateB(name, buf, length, allocated)\ 314 cleanBP(name) = malloc(sizeof(*name));name->b = buf; name->len = length; name->alloc = (allocated) ? name->len : 0 315 316 317 // return a btt object with s as buffer 318 btt initCharB(char *s); 319 320 // return a btt object with s as buffer 321 // the buffer is not going to be reallocated 322 btt initCCharB(char *s); 323 324 // return a btt object with buf as buffer 325 btt initB(void *buf, u32 len, bool allocated); 326 327 // return a btt object with a heap allocated buffer of size allocateSize 328 btt newB(u32 allocateSize); 329 330 // return a heap allocated btt object with a heap allocated buffer of size allocateSize 331 btt *allocNewB(u32 allocateSize); 332 333 // reallocate b.b 334 bool reallocB(btt *b, size_t newSize); 335 336 // return a heap allocated btt object with buf assigned to it 337 btt *allocCharB(char *buf); 338 339 // return a heap allocated btt object with buf assigned to it 340 btt *allocCCharB(char *buf); 341 342 btt *allocBufB(void *buf, u32 len, bool allocated); 343 344 // return a heap allocated btt object with b assigned to it 345 btt *allocB(const btt b); 346 347 /** 348 * return a heap allocated btt object with *b assigned to it 349 */ 350 btt *allocPB(const btt *b); 351 352 #define allocBG(b) _Generic(b,\ 353 btt: allocB,\ 354 const btt: allocB,\ 355 btt*: allocPB,\ 356 const btt*: allocPB,\ 357 char*: allocCharB,\ 358 const char*: allocCCharB\ 359 )(b) 360 361 // return a btt object with a heap allocated copy of b.b 362 btt copyB(const btt b); 363 364 btt copyPB(btt *b); 365 366 #define copyBG(b) _Generic(b,\ 367 btt: copyB,\ 368 btt*: copyPB\ 369 )(b) 370 371 // return a heap allocated btt object with a heap allocated copy of b.b 372 btt *dupB(const btt b); 373 374 btt *dupPB(btt *b); 375 376 #define dupBG(b) _Generic(b,\ 377 btt: dupB,\ 378 btt*: dupPB\ 379 )(b) 380 381 // assign a to b, b is freed if it was allocated 382 btt *setValB(btt *b, btt *a); 383 384 // TODO: 385 // ..lenB 386 // ..freeB 387 // ..terminateB(btt *b) 388 // ..pushBB 389 // ..pushManyBB 390 // // NO - growzero: memset 0 to new part 391 // ..slice 392 // ..trim 393 // countB 394 // findB ..findCharB 395 // formatB 396 // iFormatB 397 // bFormatB 398 // ..copyB 399 // ..splitB 400 // splitLenB 401 // listFreeB 402 // ..join 403 // ..toCharB convert to char* 404 // getB setB setBB set .b getBB get .b 405 // 406 // extra sds splitargs 407 // splitArgs quoted string, multiple spaces 408 409 410 // use b.b instead 411 // u8* bufferB(btt b) { 412 // ret b.b; 413 // } 414 415 // use b.len instead 416 // size_t lenB(btt b) { 417 // ret b.len; 418 // } 419 420 /** 421 * free heap allocated .b 422 * nothing if not heap allocated 423 */ 424 void freeB(btt b); 425 426 /** 427 * free heap allocated .b and assign null to .b 428 * nothing if not heap allocated 429 */ 430 void freenB(btt *b); 431 432 /** 433 * free the heap allocated btt object (container only, not .b) 434 */ 435 void finishB(btt **b); 436 437 /** 438 * free the heap allocated btt object and free .b 439 */ 440 void terminateB(btt **b); 441 442 // terminate val when it is out of scope 443 void cleanUpTerminateB(btt **val); 444 445 // free local val when it is out of scope 446 void cleanUpFreeLocalB(btt *val); 447 448 // free val when it is out of scope 449 void cleanUpFreeB(btt **val); 450 451 // finish val when it is out of scope 452 void cleanUpFinishB(btt **val); 453 454 // convert btt to char* allocated on heap 455 char *toCharB(btt *b); 456 457 bool isEmptyB(const btt b); 458 459 bool isEmptyPB(btt *b); 460 461 bool isValidB(const btt b); 462 463 bool isValidPB(btt *b); 464 465 bool eqCharB(btt a, char *b); 466 467 // return a btt object with s appended to b 468 // b doesn't need to have a heap allocated buffer 469 #define appendB pushB 470 btt pushB(const btt b, const char *s); 471 472 // TODO pushManyB 473 474 // update b and append s 475 // b.b is reallocated 476 #define bAppendB bPushB 477 btt *bPushB(btt *b, const char *s); 478 479 // '\0' at the end of b to convert b.b to C string char* 480 btt *bPushNulB(btt *b); 481 482 // TODO bPushManyB 483 484 // return a btt object with s btt object appended to b 485 // b doesn't need to have a heap allocated buffer 486 #define appendBB pushBB 487 btt pushBB(const btt b, const btt s); 488 489 // TODO bPushManyBB 490 491 // update b and append s btt object 492 // b.b is reallocated 493 #define bAppendBB bPushBB 494 btt *bPushBB(btt *b, const btt s); 495 496 // TODO bPushManyBB 497 498 // return a btt object with *s btt object appended to b 499 // b doesn't need to have a heap allocated buffer 500 #define appendBPB pushBPB 501 btt pushBPB(const btt b, const btt *s); 502 503 // TODO bPushManyBPB 504 505 // update b and append *s btt object 506 // b.b is reallocated 507 #define bAppendBPB bPushBPB 508 btt *bPushBPB(btt *b, const btt *s); 509 510 // TODO bPushManyBB 511 512 // return a btt object with s appended to *b 513 // b doesn't need to have a heap allocated buffer 514 #define appendPB pushPB 515 btt pushPB(const btt *b, const char *s); 516 // TODO pushManyPB... 517 518 // return a btt object with s btt object appended to *b 519 // b doesn't need to have a heap allocated buffer 520 #define appendPBB pushPBB 521 btt pushPBB(const btt *b, const btt s); 522 // TODO pushManyPBB... 523 524 // return a btt object with *s btt object appended to *b 525 // b doesn't need to have a heap allocated buffer 526 #define appendPBPB pushPBPB 527 btt pushPBPB(const btt *b, const btt *s); 528 // TODO pushManyPBPB... 529 530 // insert string in string 531 btt *bInsertB(btt *b, int64_t index, const char *s); 532 btt *bInsertBB(btt *b, int64_t index, const btt *s); 533 534 // delete range in string 535 btt *bDelB(btt *string, int64_t start, int64_t end); 536 537 // del a character in string 538 btt *bDelElemB(btt *string, int64_t index); 539 540 #define appendBG pushBG 541 #define pushBG(b, s) _Generic( b,\ 542 btt: _Generic(s,\ 543 const char *: pushB,\ 544 char *: pushB,\ 545 const btt: pushBB,\ 546 btt: pushBB,\ 547 const btt*: pushBPB,\ 548 btt*: pushBPB\ 549 ),\ 550 btt*: _Generic(s,\ 551 const char *: bPushB,\ 552 char *: bPushB,\ 553 const btt: bPushBB,\ 554 btt: bPushBB,\ 555 const btt*: bPushBPB,\ 556 btt*: bPushBPB\ 557 ),\ 558 const btt*: _Generic(s,\ 559 const char *: pushPB,\ 560 char *: pushPB,\ 561 const btt: pushPBB,\ 562 btt: pushPBB,\ 563 const btt*: pushPBPB,\ 564 btt*: pushPBPB\ 565 )\ 566 )(b, s) 567 568 // btt catBF(const char *paramType, ...) MUST_CHECK; 569 #define catB(...) catBF("", __VA_ARGS__, NULL) 570 571 // add allocates btt object 572 // btt *addBF(const char *paramType, ...) MUST_CHECK; 573 #define addB(...) catBF("", __VA_ARGS__, NULL) 574 575 // %q to print btt 576 // %Q to print btt* 577 // printB(char *fmt, ...) 578 579 // register %q and %Q 580 // register_printf_specifier('q', print_q, print_q_arginfo); 581 // register_printf_specifier('Q', print_Q, print_Q_arginfo); 582 583 /** 584 * %q printf type specifier, RGB foreground, uint32_t 585 */ 586 // int print_q(FILE *stream, const struct printf_info *info, const void *const *args) { 587 // u32 rgbColor; 588 // char b[20]; 589 // int len; 590 // 591 // rgbColor = *((const u32*) args[0]); 592 // snprintf(b, sizeof(b), TERMRGB "%u;%u;%um", rgbColor>>16, (rgbColor&0xFF00)>>8, rgbColor&0xFF); 593 // 594 // /* Pad to the minimum field width and print to the stream. */ 595 // //len = fprintf(stream, "%*s", (info->left ? -info->width : info->width), b) 596 // sheepyRGBFP; 597 // return(len); 598 // } 599 600 /** 601 * procress printf argument 602 */ 603 // int print_q_arginfo(const struct printf_info *info UNUSED, size_t n, int *argtypes, int* size) { 604 // 605 // if (n > 0) { 606 // argtypes[0] = PA_POINTER; 607 // size[0] = sizeof(u32); 608 // } 609 // return(1); 610 // } 611 612 613 // (btt).b is NULL on error 614 btt readFileB(const char *filePath) MUST_CHECK; 615 int writeFileB(const char *filePath, btt b) MUST_CHECK; 616 617 int64_t findCharB(btt b, const char *needle); 618 619 // split b in vb static vector 620 // the vector is not reallocated 621 vbtt *sasplitB(vbtt *vb, const btt b, const btt delim); 622 623 // split b in vb static vector 624 // the vector is not reallocated 625 vbtt *sasplitCharB(vbtt *vb, const btt b, char *delim); 626 627 // split b in vb static vector 628 // the vector is not reallocated 629 vbtt *sasplitDPB(vbtt *vb, const btt b, const btt *delim); 630 631 // split b in vb static vector 632 // the vector is not reallocated 633 vbtt *sasplitPB(vbtt *vb, const btt *b, const btt delim); 634 635 // split b in vb static vector 636 // the vector is not reallocated 637 vbtt *sasplitPCharB(vbtt *vb, const btt *b, char *delim); 638 639 // split b in vb static vector 640 // the vector is not reallocated 641 vbtt *sasplitPDPB(vbtt *vb, const btt *b, const btt *delim); 642 643 #define sasplitBG(vb, b, delim) _Generic(b,\ 644 btt: _Generic(delim,\ 645 char*: sasplitCharB,\ 646 const char*: sasplitCharB,\ 647 btt: sasplitB,\ 648 const btt: sasplitB,\ 649 btt*: sasplitDPB,\ 650 const btt*: sasplitDPB),\ 651 const btt: _Generic(delim,\ 652 char*: sasplitCharB,\ 653 const char*: sasplitCharB,\ 654 btt: sasplitB,\ 655 const btt: sasplitB,\ 656 btt*: sasplitDPB,\ 657 const btt*: sasplitDPB),\ 658 btt*: _Generic(delim,\ 659 char*: sasplitPCharB,\ 660 const char*: sasplitPCharB,\ 661 btt: sasplitPB,\ 662 const btt: sasplitPB,\ 663 btt*: sasplitPDPB,\ 664 const btt*: sasplitPDPB),\ 665 const btt*: _Generic(delim,\ 666 char*: sasplitPCharB,\ 667 const char*: sasplitPCharB,\ 668 btt: sasplitPB,\ 669 const btt: sasplitPB,\ 670 btt*: sasplitPDPB,\ 671 const btt*: sasplitPDPB)\ 672 )(vb, b, delim) 673 674 // split b in vb vector 675 vbtt *asplitB(vbtt *vb, const btt b, const btt delim); 676 677 // split b in vb vector 678 vbtt *asplitCharB(vbtt *vb, const btt b, char *delim); 679 680 // split b in vb vector 681 vbtt *asplitDPB(vbtt *vb, const btt b, const btt *delim); 682 683 // split b in vb vector 684 vbtt *asplitPB(vbtt *vb, const btt *b, const btt delim); 685 686 // split b in vb vector 687 vbtt *asplitPCharB(vbtt *vb, const btt *b, char *delim); 688 689 // split b in vb vector 690 vbtt *asplitPDPB(vbtt *vb, const btt *b, const btt *delim); 691 692 #define asplitBG(vb, b, delim) _Generic(b,\ 693 btt: _Generic(delim,\ 694 char*: asplitCharB,\ 695 const char*: asplitCharB,\ 696 btt: asplitB,\ 697 const btt: asplitB,\ 698 btt*: asplitDPB,\ 699 const btt*: asplitDPB),\ 700 const btt: _Generic(delim,\ 701 char*: asplitCharB,\ 702 const char*: asplitCharB,\ 703 btt: asplitB,\ 704 const btt: asplitB,\ 705 btt*: asplitDPB,\ 706 const btt*: asplitDPB),\ 707 btt*: _Generic(delim,\ 708 char*: asplitPCharB,\ 709 const char*: asplitPCharB,\ 710 btt: asplitPB,\ 711 const btt: asplitPB,\ 712 btt*: asplitPDPB,\ 713 const btt*: asplitPDPB),\ 714 const btt*: _Generic(delim,\ 715 char*: asplitPCharB,\ 716 const char*: asplitPCharB,\ 717 btt: asplitPB,\ 718 const btt: asplitPB,\ 719 btt*: asplitPDPB,\ 720 const btt*: asplitPDPB)\ 721 )(vb, b, delim) 722 723 // return vbtt vector with tokens from b 724 // this function has good performance for small element counts 725 vbtt splitB(const btt b, const btt delim); 726 727 // return vbtt vector with tokens from b 728 // this function has good performance for small element counts 729 vbtt splitCharB(const btt b, char *delim); 730 731 // split b in vb vector 732 vbtt splitDPB(const btt b, const btt *delim); 733 734 // split b in vb vector 735 vbtt splitPB(const btt *b, const btt delim); 736 737 // return vbtt vector with tokens from b 738 // this function has good performance for small element counts 739 vbtt splitPCharB(const btt *b, char *delim); 740 741 // split b in vb vector 742 vbtt splitPDPB(const btt *b, const btt *delim); 743 744 #define splitBG(b, delim) _Generic(b,\ 745 btt: _Generic(delim,\ 746 char*: splitCharB,\ 747 const char*: splitCharB,\ 748 btt: splitB,\ 749 const btt: splitB,\ 750 btt*: splitDPB,\ 751 const btt*: splitDPB),\ 752 const btt: _Generic(delim,\ 753 char*: splitCharB,\ 754 const char*: splitCharB,\ 755 btt: splitB,\ 756 const btt: splitB,\ 757 btt*: splitDPB,\ 758 const btt*: splitDPB),\ 759 btt*: _Generic(delim,\ 760 char*: splitPCharB,\ 761 const char*: splitPCharB,\ 762 btt: splitPB,\ 763 const btt: splitPB,\ 764 btt*: splitPDPB,\ 765 const btt*: splitPDPB),\ 766 const btt*: _Generic(delim,\ 767 char*: splitPCharB,\ 768 const char*: splitPCharB,\ 769 btt: splitPB,\ 770 const btt: splitPB,\ 771 btt*: splitPDPB,\ 772 const btt*: splitPDPB)\ 773 )(b, delim) 774 775 776 777 // return dbtt vector with tokens from b 778 // this function has good performance for large element counts 779 dbtt dsplitB(const btt b, const btt delim); 780 781 // return dbtt vector with tokens from b 782 // this function has good performance for large element counts 783 dbtt dsplitCharB(const btt b, char *delim); 784 785 // return dbtt vector with tokens from b 786 // this function has good performance for large element counts 787 dbtt dsplitDPB(const btt b, const btt *delim); 788 789 // return dbtt vector with tokens from b 790 // this function has good performance for large element counts 791 dbtt dsplitPB(const btt *b, const btt delim); 792 793 // return dbtt vector with tokens from b 794 // this function has good performance for large element counts 795 dbtt dsplitPCharB(const btt *b, char *delim); 796 797 // return dbtt vector with tokens from b 798 // this function has good performance for large element counts 799 dbtt dsplitPDPB(const btt *b, const btt *delim); 800 801 #define dsplitBG(b, delim) _Generic(b,\ 802 btt: _Generic(delim,\ 803 char*: dsplitCharB,\ 804 const char*: dsplitCharB,\ 805 btt: dsplitB,\ 806 const btt: dsplitB,\ 807 btt*: dsplitDPB,\ 808 const btt*: dsplitDPB),\ 809 const btt: _Generic(delim,\ 810 char*: dsplitCharB,\ 811 const char*: dsplitCharB,\ 812 btt: dsplitB,\ 813 const btt: dsplitB,\ 814 btt*: dsplitDPB,\ 815 const btt*: dsplitDPB),\ 816 btt*: _Generic(delim,\ 817 char*: dsplitPCharB,\ 818 const char*: dsplitPCharB,\ 819 btt: dsplitPB,\ 820 const btt: dsplitPB,\ 821 btt*: dsplitPDPB,\ 822 const btt*: dsplitPDPB),\ 823 const btt*: _Generic(delim,\ 824 char*: dsplitPCharB,\ 825 const char*: dsplitPCharB,\ 826 btt: dsplitPB,\ 827 const btt: dsplitPB,\ 828 btt*: dsplitPDPB,\ 829 const btt*: dsplitPDPB)\ 830 )(b, delim) 831 832 833 // slice String 834 // return a btt object which is the string between start and end 835 // negative indexes are allowed 836 btt sliceB(const btt b, int64_t start, int64_t end); 837 838 // slice String 839 // update the b btt object and keep only the string between start and end 840 // negative indexes are allowed 841 btt *bSliceB(btt *b, int64_t start, int64_t end); 842 843 // slice String 844 // return a btt object which is the string between start and end 845 // negative indexes are allowed 846 btt slicePB(const btt *b, int64_t start, int64_t end); 847 848 #define sliceBG(b, start, end) _Generic(b,\ 849 btt: sliceB,\ 850 const btt: sliceB,\ 851 btt*: bSliceB,\ 852 const btt*: slicePB\ 853 )(b, start, end); 854 855 btt joinCharB(vbtt list, const char* delim); 856 857 // copyRngB 858 // return a btt object with a heap allocated copy of b.b from start to end 859 btt copyRngB(const btt b, int64_t start, int64_t end); 860 861 // copyRngPB 862 // return a btt object with a heap allocated copy of b.b from start to end 863 // TODO btt copyRngPB(btt *b, int64_t start, int64_t end); 864 865 // cropB copy and remove 866 btt bCropB(btt *b, int64_t start, int64_t end); 867 868 // return a btt object without the leading and trailing spaces 869 btt trimB(const btt b); 870 871 // update b btt object and remove the leading and trailing spaces 872 btt *bTrimB(btt *b); 873 874 // return a btt object without the leading and trailing spaces 875 btt trimPB(const btt *b); 876 877 #define trimBG(b) _Generic(b,\ 878 btt: trimB,\ 879 const btt: trimB,\ 880 btt*: bTrimB,\ 881 const btt*: trimPB\ 882 )(b) 883 884 /** 885 * remove empty strings from list 886 * 887 * \param 888 * list 889 * \return 890 * list without empty strings 891 * empty list when list is empty 892 * unchanged list when list is NULL 893 * NULL error 894 */ 895 vbtt *bCompactB(vbtt *list); 896 897 /** 898 * buffer size normalize path 899 * 900 * remove unecessary /, .. and . 901 * leading / is kept 902 * leading .. is kept 903 * leading . is removed 904 * 905 * '/../' becomes '/' 906 * 907 * \param 908 * path 909 * \return 910 * path modified path 911 * NULL when path is NULL 912 */ 913 btt *bNormalizePathB(btt *path); 914 915 void printB(const btt b); 916 917 void printDebugB(const btt b); 918 919 void printDebugInfoB(const btt b); 920 921 // vim: set expandtab ts=2 sw=2: