This function is similar to sdscatprintf, but much faster as it does * not rely on sprintf() family functions implemented by the libc that * are often very slow. Moreover directly handling the sds string as * new data is concatenated provides a performance improvement. * * However this function only handles an incompatible subset of printf-alike * format specifiers: * * %s - C String * %S
| 598 | * %% - Verbatim "%" character. |
| 599 | */ |
| 600 | sds sdscatfmt(sds s, char const *fmt, ...) { |
| 601 | size_t initlen = sdslen(s); |
| 602 | const char *f = fmt; |
| 603 | long i; |
| 604 | va_list ap; |
| 605 | |
| 606 | /* To avoid continuous reallocations, let's start with a buffer that |
| 607 | * can hold at least two times the format string itself. It's not the |
| 608 | * best heuristic but seems to work in practice. */ |
| 609 | s = sdsMakeRoomFor(s, initlen + strlen(fmt)*2); |
| 610 | va_start(ap,fmt); |
| 611 | f = fmt; /* Next format specifier byte to process. */ |
| 612 | i = initlen; /* Position of the next byte to write to dest str. */ |
| 613 | while(*f) { |
| 614 | char next, *str; |
| 615 | size_t l; |
| 616 | long long num; |
| 617 | unsigned long long unum; |
| 618 | |
| 619 | /* Make sure there is always space for at least 1 char. */ |
| 620 | if (sdsavail(s)==0) { |
| 621 | s = sdsMakeRoomFor(s,1); |
| 622 | } |
| 623 | |
| 624 | switch(*f) { |
| 625 | case '%': |
| 626 | next = *(f+1); |
| 627 | f++; |
| 628 | switch(next) { |
| 629 | case 's': |
| 630 | case 'S': |
| 631 | str = va_arg(ap,char*); |
| 632 | l = (next == 's') ? strlen(str) : sdslen(str); |
| 633 | if (sdsavail(s) < l) { |
| 634 | s = sdsMakeRoomFor(s,l); |
| 635 | } |
| 636 | memcpy(s+i,str,l); |
| 637 | sdsinclen(s,l); |
| 638 | i += l; |
| 639 | break; |
| 640 | case 'i': |
| 641 | case 'I': |
| 642 | if (next == 'i') |
| 643 | num = va_arg(ap,int); |
| 644 | else |
| 645 | num = va_arg(ap,long long); |
| 646 | { |
| 647 | char buf[SDS_LLSTR_SIZE]; |
| 648 | l = sdsll2str(buf,num); |
| 649 | if (sdsavail(s) < l) { |
| 650 | s = sdsMakeRoomFor(s,l); |
| 651 | } |
| 652 | memcpy(s+i,buf,l); |
| 653 | sdsinclen(s,l); |
| 654 | i += l; |
| 655 | } |
| 656 | break; |
| 657 | case 'u': |
no test coverage detected