libsheepy

C lib for handling text files, strings and json like data structure with an object oriented system
git clone https://spartatek.se/git/libsheepy.git
Log | Files | Refs | README | LICENSE

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: