From ec7e138926b7b587adc247e8c64da6d3b1706434 Mon Sep 17 00:00:00 2001 From: antirez Date: Thu, 26 Aug 2010 18:47:03 +0200 Subject: [PATCH] test for intset integer encodability test and some small refactoring --- src/redis.h | 2 ++ src/t_set.c | 8 ++++---- src/util.c | 34 +++++++++++++++++++++++++++------- 3 files changed, 33 insertions(+), 11 deletions(-) diff --git a/src/redis.h b/src/redis.h index 6156a6ca..a4fdcb19 100644 --- a/src/redis.h +++ b/src/redis.h @@ -769,6 +769,8 @@ int stringmatch(const char *pattern, const char *string, int nocase); long long memtoll(const char *p, int *err); int ll2string(char *s, size_t len, long long value); int isStringRepresentableAsLong(sds s, long *longval); +int isStringRepresentableAsLongLong(sds s, long long *longval); +int isObjectRepresentableAsLongLong(robj *o, long long *llongval); /* Configuration */ void loadServerConfig(char *filename); diff --git a/src/t_set.c b/src/t_set.c index 97fc5bf4..68e13227 100644 --- a/src/t_set.c +++ b/src/t_set.c @@ -8,7 +8,7 @@ * an integer-encodable value, an intset will be returned. Otherwise a regular * hash table. */ robj *setTypeCreate(robj *value) { - if (getLongLongFromObject(value,NULL) == REDIS_OK) + if (isObjectRepresentableAsLongLong(value,NULL) == REDIS_OK) return createIntsetObject(); return createSetObject(); } @@ -21,7 +21,7 @@ int setTypeAdd(robj *subject, robj *value) { return 1; } } else if (subject->encoding == REDIS_ENCODING_INTSET) { - if (getLongLongFromObject(value,&llval) == REDIS_OK) { + if (isObjectRepresentableAsLongLong(value,&llval) == REDIS_OK) { uint8_t success = 0; subject->ptr = intsetAdd(subject->ptr,llval,&success); if (success) { @@ -55,7 +55,7 @@ int setTypeRemove(robj *subject, robj *value) { return 1; } } else if (subject->encoding == REDIS_ENCODING_INTSET) { - if (getLongLongFromObject(value,&llval) == REDIS_OK) { + if (isObjectRepresentableAsLongLong(value,&llval) == REDIS_OK) { uint8_t success; subject->ptr = intsetRemove(subject->ptr,llval,&success); if (success) return 1; @@ -71,7 +71,7 @@ int setTypeIsMember(robj *subject, robj *value) { if (subject->encoding == REDIS_ENCODING_HT) { return dictFind((dict*)subject->ptr,value) != NULL; } else if (subject->encoding == REDIS_ENCODING_INTSET) { - if (getLongLongFromObject(value,&llval) == REDIS_OK) { + if (isObjectRepresentableAsLongLong(value,&llval) == REDIS_OK) { return intsetFind((intset*)subject->ptr,llval); } } else { diff --git a/src/util.c b/src/util.c index cc2794f6..e304ff83 100644 --- a/src/util.c +++ b/src/util.c @@ -200,24 +200,44 @@ int ll2string(char *s, size_t len, long long value) { return l; } -/* Check if the nul-terminated string 's' can be represented by a long +/* Check if the sds string 's' can be represented by a long long * (that is, is a number that fits into long without any other space or - * character before or after the digits). + * character before or after the digits, so that converting this number + * back to a string will result in the same bytes as the original string). * - * If so, the function returns REDIS_OK and *longval is set to the value + * If so, the function returns REDIS_OK and *llongval is set to the value * of the number. Otherwise REDIS_ERR is returned */ -int isStringRepresentableAsLong(sds s, long *longval) { +int isStringRepresentableAsLongLong(sds s, long long *llongval) { char buf[32], *endptr; - long value; + long long value; int slen; - value = strtol(s, &endptr, 10); + value = strtoll(s, &endptr, 10); if (endptr[0] != '\0') return REDIS_ERR; slen = ll2string(buf,32,value); /* If the number converted back into a string is not identical * then it's not possible to encode the string as integer */ if (sdslen(s) != (unsigned)slen || memcmp(buf,s,slen)) return REDIS_ERR; - if (longval) *longval = value; + if (llongval) *llongval = value; + return REDIS_OK; +} + +int isStringRepresentableAsLong(sds s, long *longval) { + long long ll; + + if (isStringRepresentableAsLongLong(s,&ll) == REDIS_ERR) return REDIS_ERR; + if (ll < LONG_MIN || ll > LONG_MAX) return REDIS_ERR; + *longval = (long)ll; return REDIS_OK; } + +int isObjectRepresentableAsLongLong(robj *o, long long *llongval) { + redisAssert(o->type == REDIS_STRING); + if (o->encoding == REDIS_ENCODING_INT) { + if (llongval) *llongval = (long) o->ptr; + return REDIS_OK; + } else { + return isStringRepresentableAsLongLong(o->ptr,llongval); + } +} -- 2.45.2