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
| 637 | * %% - Verbatim "%" character. |
| 638 | */ |
| 639 | sds sdscatfmt(sds s, char const *fmt, ...) { |
| 640 | size_t initlen = sdslen(s); |
| 641 | const char *f = fmt; |
| 642 | long i; |
| 643 | va_list ap; |
| 644 | |
| 645 | /* To avoid continuous reallocations, let's start with a buffer that |
| 646 | * can hold at least two times the format string itself. It's not the |
| 647 | * best heuristic but seems to work in practice. */ |
| 648 | s = sdsMakeRoomFor(s, strlen(fmt)*2); |
| 649 | va_start(ap,fmt); |
| 650 | f = fmt; /* Next format specifier byte to process. */ |
| 651 | i = initlen; /* Position of the next byte to write to dest str. */ |
| 652 | while(*f) { |
| 653 | char next, *str; |
| 654 | size_t l; |
| 655 | long long num; |
| 656 | unsigned long long unum; |
| 657 | |
| 658 | /* Make sure there is always space for at least 1 char. */ |
| 659 | if (sdsavail(s)==0) { |
| 660 | s = sdsMakeRoomFor(s,1); |
| 661 | } |
| 662 | |
| 663 | switch(*f) { |
| 664 | case '%': |
| 665 | next = *(f+1); |
| 666 | f++; |
| 667 | switch(next) { |
| 668 | case 's': |
| 669 | case 'S': |
| 670 | str = va_arg(ap,char*); |
| 671 | l = (next == 's') ? strlen(str) : sdslen(str); |
| 672 | if (sdsavail(s) < l) { |
| 673 | s = sdsMakeRoomFor(s,l); |
| 674 | } |
| 675 | memcpy(s+i,str,l); |
| 676 | sdsinclen(s,l); |
| 677 | i += l; |
| 678 | break; |
| 679 | case 'i': |
| 680 | case 'I': |
| 681 | if (next == 'i') |
| 682 | num = va_arg(ap,int); |
| 683 | else |
| 684 | num = va_arg(ap,long long); |
| 685 | { |
| 686 | char buf[SDS_LLSTR_SIZE]; |
| 687 | l = sdsll2str(buf,num); |
| 688 | if (sdsavail(s) < l) { |
| 689 | s = sdsMakeRoomFor(s,l); |
| 690 | } |
| 691 | memcpy(s+i,buf,l); |
| 692 | sdsinclen(s,l); |
| 693 | i += l; |
| 694 | } |
| 695 | break; |
| 696 | case 'u': |
no test coverage detected