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:
parent
802456def1
commit
195aca3427
32
hiredis.c
32
hiredis.c
@ -186,23 +186,23 @@ static void *createNilObject(const redisReadTask *task) {
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Calculate the number of bytes needed to represent an integer as string. */
|
/* Return the number of digits of 'v' when converted to string in radix 10.
|
||||||
static int intlen(int i) {
|
* Implementation borrowed from link in redis/src/util.c:string2ll(). */
|
||||||
int len = 0;
|
static uint32_t countDigits(uint64_t v) {
|
||||||
if (i < 0) {
|
uint32_t result = 1;
|
||||||
len++;
|
for (;;) {
|
||||||
i = -i;
|
if (v < 10) return result;
|
||||||
}
|
if (v < 100) return result + 1;
|
||||||
do {
|
if (v < 1000) return result + 2;
|
||||||
len++;
|
if (v < 10000) return result + 3;
|
||||||
i /= 10;
|
v /= 10000U;
|
||||||
} while(i);
|
result += 4;
|
||||||
return len;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Helper that calculates the bulk length given a certain string length. */
|
/* Helper that calculates the bulk length given a certain string length. */
|
||||||
static size_t bulklen(size_t len) {
|
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) {
|
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;
|
curarg = NULL;
|
||||||
|
|
||||||
/* Add bytes needed to hold multi bulk count */
|
/* Add bytes needed to hold multi bulk count */
|
||||||
totlen += 1+intlen(argc)+2;
|
totlen += 1+countDigits(argc)+2;
|
||||||
|
|
||||||
/* Build the command at protocol level */
|
/* Build the command at protocol level */
|
||||||
cmd = malloc(totlen+1);
|
cmd = malloc(totlen+1);
|
||||||
@ -485,7 +485,7 @@ int redisFormatSdsCommandArgv(sds *target, int argc, const char **argv,
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* Calculate our total size */
|
/* Calculate our total size */
|
||||||
totlen = 1+intlen(argc)+2;
|
totlen = 1+countDigits(argc)+2;
|
||||||
for (j = 0; j < argc; j++) {
|
for (j = 0; j < argc; j++) {
|
||||||
len = argvlen ? argvlen[j] : strlen(argv[j]);
|
len = argvlen ? argvlen[j] : strlen(argv[j]);
|
||||||
totlen += bulklen(len);
|
totlen += bulklen(len);
|
||||||
@ -536,7 +536,7 @@ int redisFormatCommandArgv(char **target, int argc, const char **argv, const siz
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* Calculate number of bytes needed for the command */
|
/* Calculate number of bytes needed for the command */
|
||||||
totlen = 1+intlen(argc)+2;
|
totlen = 1+countDigits(argc)+2;
|
||||||
for (j = 0; j < argc; j++) {
|
for (j = 0; j < argc; j++) {
|
||||||
len = argvlen ? argvlen[j] : strlen(argv[j]);
|
len = argvlen ? argvlen[j] : strlen(argv[j]);
|
||||||
totlen += bulklen(len);
|
totlen += bulklen(len);
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#include "read.h"
|
#include "read.h"
|
||||||
#include <stdarg.h> /* for va_list */
|
#include <stdarg.h> /* for va_list */
|
||||||
#include <sys/time.h> /* for struct timeval */
|
#include <sys/time.h> /* for struct timeval */
|
||||||
|
#include <stdint.h> /* uintXX_t, etc */
|
||||||
#include "sds.h" /* for sds */
|
#include "sds.h" /* for sds */
|
||||||
|
|
||||||
#define HIREDIS_MAJOR 0
|
#define HIREDIS_MAJOR 0
|
||||||
|
Loading…
Reference in New Issue
Block a user