Skip to content

Commit 2d76736

Browse files
committed
Added new sdscatfmt() %u and %U format specifiers.
This commit also fixes a bug in the implementation of sdscatfmt() resulting from stale references to the SDS string header after sdsMakeRoomFor() calls.
1 parent 53575c4 commit 2d76736

File tree

1 file changed

+71
-4
lines changed

1 file changed

+71
-4
lines changed

src/sds.c

Lines changed: 71 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,35 @@ int sdsll2str(char *s, long long value) {
327327
return l;
328328
}
329329

330+
/* Identical sdsll2str(), but for unsigned long long type. */
331+
int sdsull2str(char *s, unsigned long long v) {
332+
char *p, aux;
333+
size_t l;
334+
335+
/* Generate the string representation, this method produces
336+
* an reversed string. */
337+
p = s;
338+
do {
339+
*p++ = '0'+(v%10);
340+
v /= 10;
341+
} while(v);
342+
343+
/* Compute length and add null term. */
344+
l = p-s;
345+
*p = '\0';
346+
347+
/* Reverse the string. */
348+
p--;
349+
while(s < p) {
350+
aux = *s;
351+
*s = *p;
352+
*p = aux;
353+
s++;
354+
p--;
355+
}
356+
return l;
357+
}
358+
330359
/* Create an sds string from a long long value. It is much faster than:
331360
*
332361
* sdscatprintf(sdsempty(),"%lld\n", value);
@@ -410,8 +439,10 @@ sds sdscatprintf(sds s, const char *fmt, ...) {
410439
*
411440
* %s - C String
412441
* %S - SDS string
413-
* %i - signed integer
442+
* %i - signed int
414443
* %I - 64 bit signed integer (long long, int64_t)
444+
* %u - unsigned int
445+
* %U - 64 bit unsigned integer (unsigned long long, uint64_t)
415446
* %% - Verbatim "%" character.
416447
*/
417448
sds sdscatfmt(sds s, char const *fmt, ...) {
@@ -428,9 +459,13 @@ sds sdscatfmt(sds s, char const *fmt, ...) {
428459
char next, *str;
429460
size_t l;
430461
long long num;
462+
unsigned long long unum;
431463

432464
/* Make sure there is always space for at least 1 char. */
433-
if (sh->free == 0) s = sdsMakeRoomFor(s,1);
465+
if (sh->free == 0) {
466+
s = sdsMakeRoomFor(s,1);
467+
sh = (void*) (s-(sizeof(struct sdshdr)));
468+
}
434469

435470
switch(*f) {
436471
case '%':
@@ -441,7 +476,10 @@ sds sdscatfmt(sds s, char const *fmt, ...) {
441476
case 'S':
442477
str = va_arg(ap,char*);
443478
l = (next == 's') ? strlen(str) : sdslen(str);
444-
if (sh->free < l) s = sdsMakeRoomFor(s,l);
479+
if (sh->free < l) {
480+
s = sdsMakeRoomFor(s,l);
481+
sh = (void*) (s-(sizeof(struct sdshdr)));
482+
}
445483
memcpy(s+i,str,l);
446484
sh->len += l;
447485
sh->free -= l;
@@ -456,7 +494,29 @@ sds sdscatfmt(sds s, char const *fmt, ...) {
456494
{
457495
char buf[SDS_LLSTR_SIZE];
458496
l = sdsll2str(buf,num);
459-
if (sh->free < l) s = sdsMakeRoomFor(s,l);
497+
if (sh->free < l) {
498+
s = sdsMakeRoomFor(s,l);
499+
sh = (void*) (s-(sizeof(struct sdshdr)));
500+
}
501+
memcpy(s+i,buf,l);
502+
sh->len += l;
503+
sh->free -= l;
504+
i += l;
505+
}
506+
break;
507+
case 'u':
508+
case 'U':
509+
if (next == 'u')
510+
unum = va_arg(ap,unsigned int);
511+
else
512+
unum = va_arg(ap,unsigned long long);
513+
{
514+
char buf[SDS_LLSTR_SIZE];
515+
l = sdsull2str(buf,unum);
516+
if (sh->free < l) {
517+
s = sdsMakeRoomFor(s,l);
518+
sh = (void*) (s-(sizeof(struct sdshdr)));
519+
}
460520
memcpy(s+i,buf,l);
461521
sh->len += l;
462522
sh->free -= l;
@@ -943,6 +1003,13 @@ int main(void) {
9431003
memcmp(x,"--Hello Hi! World -9223372036854775808,"
9441004
"9223372036854775807--",60) == 0)
9451005

1006+
sdsfree(x);
1007+
x = sdsnew("--");
1008+
x = sdscatfmt(x, "%u,%U--", UINT_MAX, ULLONG_MAX);
1009+
test_cond("sdscatfmt() seems working with unsigned numbers",
1010+
sdslen(x) == 35 &&
1011+
memcmp(x,"--4294967295,18446744073709551615--",35) == 0)
1012+
9461013
sdsfree(x);
9471014
x = sdsnew("xxciaoyyy");
9481015
sdstrim(x,"xy");

0 commit comments

Comments
 (0)