test for intset integer encodability test and some small refactoring

This commit is contained in:
antirez 2010-08-26 18:47:03 +02:00
parent 23c64fe50d
commit ec7e138926
3 changed files with 33 additions and 11 deletions

View File

@ -769,6 +769,8 @@ int stringmatch(const char *pattern, const char *string, int nocase);
long long memtoll(const char *p, int *err); long long memtoll(const char *p, int *err);
int ll2string(char *s, size_t len, long long value); int ll2string(char *s, size_t len, long long value);
int isStringRepresentableAsLong(sds s, long *longval); int isStringRepresentableAsLong(sds s, long *longval);
int isStringRepresentableAsLongLong(sds s, long long *longval);
int isObjectRepresentableAsLongLong(robj *o, long long *llongval);
/* Configuration */ /* Configuration */
void loadServerConfig(char *filename); void loadServerConfig(char *filename);

View File

@ -8,7 +8,7 @@
* an integer-encodable value, an intset will be returned. Otherwise a regular * an integer-encodable value, an intset will be returned. Otherwise a regular
* hash table. */ * hash table. */
robj *setTypeCreate(robj *value) { robj *setTypeCreate(robj *value) {
if (getLongLongFromObject(value,NULL) == REDIS_OK) if (isObjectRepresentableAsLongLong(value,NULL) == REDIS_OK)
return createIntsetObject(); return createIntsetObject();
return createSetObject(); return createSetObject();
} }
@ -21,7 +21,7 @@ int setTypeAdd(robj *subject, robj *value) {
return 1; return 1;
} }
} else if (subject->encoding == REDIS_ENCODING_INTSET) { } else if (subject->encoding == REDIS_ENCODING_INTSET) {
if (getLongLongFromObject(value,&llval) == REDIS_OK) { if (isObjectRepresentableAsLongLong(value,&llval) == REDIS_OK) {
uint8_t success = 0; uint8_t success = 0;
subject->ptr = intsetAdd(subject->ptr,llval,&success); subject->ptr = intsetAdd(subject->ptr,llval,&success);
if (success) { if (success) {
@ -55,7 +55,7 @@ int setTypeRemove(robj *subject, robj *value) {
return 1; return 1;
} }
} else if (subject->encoding == REDIS_ENCODING_INTSET) { } else if (subject->encoding == REDIS_ENCODING_INTSET) {
if (getLongLongFromObject(value,&llval) == REDIS_OK) { if (isObjectRepresentableAsLongLong(value,&llval) == REDIS_OK) {
uint8_t success; uint8_t success;
subject->ptr = intsetRemove(subject->ptr,llval,&success); subject->ptr = intsetRemove(subject->ptr,llval,&success);
if (success) return 1; if (success) return 1;
@ -71,7 +71,7 @@ int setTypeIsMember(robj *subject, robj *value) {
if (subject->encoding == REDIS_ENCODING_HT) { if (subject->encoding == REDIS_ENCODING_HT) {
return dictFind((dict*)subject->ptr,value) != NULL; return dictFind((dict*)subject->ptr,value) != NULL;
} else if (subject->encoding == REDIS_ENCODING_INTSET) { } 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); return intsetFind((intset*)subject->ptr,llval);
} }
} else { } else {

View File

@ -200,24 +200,44 @@ int ll2string(char *s, size_t len, long long value) {
return l; 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 * (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 */ * 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; char buf[32], *endptr;
long value; long long value;
int slen; int slen;
value = strtol(s, &endptr, 10); value = strtoll(s, &endptr, 10);
if (endptr[0] != '\0') return REDIS_ERR; if (endptr[0] != '\0') return REDIS_ERR;
slen = ll2string(buf,32,value); slen = ll2string(buf,32,value);
/* If the number converted back into a string is not identical /* If the number converted back into a string is not identical
* then it's not possible to encode the string as integer */ * then it's not possible to encode the string as integer */
if (sdslen(s) != (unsigned)slen || memcmp(buf,s,slen)) return REDIS_ERR; if (sdslen(s) != (unsigned)slen || memcmp(buf,s,slen)) return REDIS_ERR;
if (longval) *longval = value; if (llongval) *llongval = value;
return REDIS_OK; 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);
}
}