Improve digit counting for multibulk creation

This replaces the old intlen() implementation with a slightly
faster way of counting digits.

Implementation taken from the same place where digits10() in
redis/src/util.c came from.

The old 'intlen' allowed negative inputs, but no usage in hiredis
was passing negative numbers, so that ability is removed.  Also,
the new implementation can count higher (uint64_t) instead of
limited to just int as before.

Fixes #295 by replacing implementation
This commit is contained in:
Matt Stancliff 2015-01-20 10:58:35 -05:00
parent 802456def1
commit 195aca3427
2 changed files with 17 additions and 16 deletions

View File

@ -186,23 +186,23 @@ static void *createNilObject(const redisReadTask *task) {
return r;
}
/* Calculate the number of bytes needed to represent an integer as string. */
static int intlen(int i) {
int len = 0;
if (i < 0) {
len++;
i = -i;
}
do {
len++;
i /= 10;
} while(i);
return len;
/* Return the number of digits of 'v' when converted to string in radix 10.
* Implementation borrowed from link in redis/src/util.c:string2ll(). */
static uint32_t countDigits(uint64_t v) {
uint32_t result = 1;
for (;;) {
if (v < 10) return result;
if (v < 100) return result + 1;
if (v < 1000) return result + 2;
if (v < 10000) return result + 3;
v /= 10000U;
result += 4;
}
}
/* Helper that calculates the bulk length given a certain string length. */
static size_t bulklen(size_t len) {
return 1+intlen(len)+2+len+2;
return 1+countDigits(len)+2+len+2;
}
int redisvFormatCommand(char **target, const char *format, va_list ap) {
@ -392,7 +392,7 @@ int redisvFormatCommand(char **target, const char *format, va_list ap) {
curarg = NULL;
/* Add bytes needed to hold multi bulk count */
totlen += 1+intlen(argc)+2;
totlen += 1+countDigits(argc)+2;
/* Build the command at protocol level */
cmd = malloc(totlen+1);
@ -485,7 +485,7 @@ int redisFormatSdsCommandArgv(sds *target, int argc, const char **argv,
return -1;
/* Calculate our total size */
totlen = 1+intlen(argc)+2;
totlen = 1+countDigits(argc)+2;
for (j = 0; j < argc; j++) {
len = argvlen ? argvlen[j] : strlen(argv[j]);
totlen += bulklen(len);
@ -536,7 +536,7 @@ int redisFormatCommandArgv(char **target, int argc, const char **argv, const siz
return -1;
/* Calculate number of bytes needed for the command */
totlen = 1+intlen(argc)+2;
totlen = 1+countDigits(argc)+2;
for (j = 0; j < argc; j++) {
len = argvlen ? argvlen[j] : strlen(argv[j]);
totlen += bulklen(len);

View File

@ -34,6 +34,7 @@
#include "read.h"
#include <stdarg.h> /* for va_list */
#include <sys/time.h> /* for struct timeval */
#include <stdint.h> /* uintXX_t, etc */
#include "sds.h" /* for sds */
#define HIREDIS_MAJOR 0