Skip to content
This repository
Browse code

Tests for string2ll; move isObject* to object.c

  • Loading branch information...
commit 5d08193126df54405dae3073c62b7c19ae03d1a4 1 parent af0e51f
Pieter Noordhuis pietern authored
3  src/Makefile
@@ -125,8 +125,7 @@ t_string.o: t_string.c redis.h fmacros.h config.h ae.h sds.h dict.h \
125 125 adlist.h zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h
126 126 t_zset.o: t_zset.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h \
127 127 zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h
128   -util.o: util.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h \
129   - zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h
  128 +util.o: util.c util.h
130 129 cluster.o: redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h \
131 130 zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h
132 131 ziplist.o: ziplist.c zmalloc.h ziplist.h
12 src/object.c
@@ -202,6 +202,16 @@ int checkType(redisClient *c, robj *o, int type) {
202 202 return 0;
203 203 }
204 204
  205 +int isObjectRepresentableAsLongLong(robj *o, long long *llval) {
  206 + redisAssert(o->type == REDIS_STRING);
  207 + if (o->encoding == REDIS_ENCODING_INT) {
  208 + if (llval) *llval = (long) o->ptr;
  209 + return REDIS_OK;
  210 + } else {
  211 + return string2ll(o->ptr,sdslen(o->ptr),llval) ? REDIS_OK : REDIS_ERR;
  212 + }
  213 +}
  214 +
205 215 /* Try to encode a string object in order to save space */
206 216 robj *tryObjectEncoding(robj *o) {
207 217 long value;
@@ -219,7 +229,7 @@ robj *tryObjectEncoding(robj *o) {
219 229 redisAssert(o->type == REDIS_STRING);
220 230
221 231 /* Check if we can represent this string as a long integer */
222   - if (isStringRepresentableAsLong(s,&value) == REDIS_ERR) return o;
  232 + if (!string2l(s,sdslen(s),&value)) return o;
223 233
224 234 /* Ok, this object can be encoded...
225 235 *
14 src/redis.h
@@ -30,6 +30,7 @@
30 30 #include "ziplist.h" /* Compact list data structure */
31 31 #include "intset.h" /* Compact integer set structure */
32 32 #include "version.h"
  33 +#include "util.h"
33 34
34 35 /* Error codes */
35 36 #define REDIS_OK 0
@@ -852,6 +853,7 @@ void freeHashObject(robj *o);
852 853 robj *createObject(int type, void *ptr);
853 854 robj *createStringObject(char *ptr, size_t len);
854 855 robj *dupStringObject(robj *o);
  856 +int isObjectRepresentableAsLongLong(robj *o, long long *llongval);
855 857 robj *tryObjectEncoding(robj *o);
856 858 robj *getDecodedObject(robj *o);
857 859 size_t stringObjectLen(robj *o);
@@ -1028,18 +1030,6 @@ int pubsubUnsubscribeAllPatterns(redisClient *c, int notify);
1028 1030 void freePubsubPattern(void *p);
1029 1031 int listMatchPubsubPattern(void *a, void *b);
1030 1032
1031   -/* Utility functions */
1032   -int stringmatchlen(const char *pattern, int patternLen,
1033   - const char *string, int stringLen, int nocase);
1034   -int stringmatch(const char *pattern, const char *string, int nocase);
1035   -long long memtoll(const char *p, int *err);
1036   -int ll2string(char *s, size_t len, long long value);
1037   -int string2ll(char *s, size_t len, long long *value);
1038   -int d2string(char *s, size_t len, double value);
1039   -int isStringRepresentableAsLong(sds s, long *longval);
1040   -int isStringRepresentableAsLongLong(sds s, long long *longval);
1041   -int isObjectRepresentableAsLongLong(robj *o, long long *llongval);
1042   -
1043 1033 /* Configuration */
1044 1034 void loadServerConfig(char *filename);
1045 1035 void appendServerSaveParams(time_t seconds, int changes);
163 src/util.c
... ... @@ -1,7 +1,10 @@
1   -#include "redis.h"
  1 +#include <stdlib.h>
  2 +#include <stdio.h>
  3 +#include <string.h>
2 4 #include <ctype.h>
3 5 #include <limits.h>
4 6 #include <math.h>
  7 +#include "util.h"
5 8
6 9 /* Glob-style pattern matching. */
7 10 int stringmatchlen(const char *pattern, int patternLen,
@@ -213,6 +216,12 @@ int string2ll(char *s, size_t slen, long long *value) {
213 216 if (plen == slen)
214 217 return 0;
215 218
  219 + /* Special case: first and only digit is 0. */
  220 + if (slen == 1 && p[0] == '0') {
  221 + if (value != NULL) *value = 0;
  222 + return 1;
  223 + }
  224 +
216 225 if (p[0] == '-') {
217 226 negative = 1;
218 227 p++; plen++;
@@ -250,7 +259,7 @@ int string2ll(char *s, size_t slen, long long *value) {
250 259 return 0;
251 260
252 261 if (negative) {
253   - if (v > (-(unsigned long long)LLONG_MIN)) /* Overflow. */
  262 + if (v > ((unsigned long long)(-(LLONG_MIN+1))+1)) /* Overflow. */
254 263 return 0;
255 264 if (value != NULL) *value = -v;
256 265 } else {
@@ -261,6 +270,22 @@ int string2ll(char *s, size_t slen, long long *value) {
261 270 return 1;
262 271 }
263 272
  273 +/* Convert a string into a long. Returns 1 if the string could be parsed into a
  274 + * (non-overflowing) long, 0 otherwise. The value will be set to the parsed
  275 + * value when appropriate. */
  276 +int string2l(char *s, size_t slen, long *lval) {
  277 + long long llval;
  278 +
  279 + if (!string2ll(s,slen,&llval))
  280 + return 0;
  281 +
  282 + if (llval < LONG_MIN || llval > LONG_MAX)
  283 + return 0;
  284 +
  285 + *lval = (long)llval;
  286 + return 1;
  287 +}
  288 +
264 289 /* Convert a double to a string representation. Returns the number of bytes
265 290 * required. The representation should always be parsable by stdtod(3). */
266 291 int d2string(char *buf, size_t len, double value) {
@@ -300,44 +325,108 @@ int d2string(char *buf, size_t len, double value) {
300 325 return len;
301 326 }
302 327
303   -/* Check if the sds string 's' can be represented by a long long
304   - * (that is, is a number that fits into long without any other space or
305   - * character before or after the digits, so that converting this number
306   - * back to a string will result in the same bytes as the original string).
307   - *
308   - * If so, the function returns REDIS_OK and *llongval is set to the value
309   - * of the number. Otherwise REDIS_ERR is returned */
310   -int isStringRepresentableAsLongLong(sds s, long long *llongval) {
311   - char buf[32], *endptr;
312   - long long value;
313   - int slen;
314   -
315   - value = strtoll(s, &endptr, 10);
316   - if (endptr[0] != '\0') return REDIS_ERR;
317   - slen = ll2string(buf,32,value);
318   -
319   - /* If the number converted back into a string is not identical
320   - * then it's not possible to encode the string as integer */
321   - if (sdslen(s) != (unsigned)slen || memcmp(buf,s,slen)) return REDIS_ERR;
322   - if (llongval) *llongval = value;
323   - return REDIS_OK;
  328 +#ifdef UTIL_TEST_MAIN
  329 +#include <assert.h>
  330 +
  331 +void test_string2ll(void) {
  332 + char buf[32];
  333 + long long v;
  334 +
  335 + /* May not start with +. */
  336 + strcpy(buf,"+1");
  337 + assert(string2ll(buf,strlen(buf),&v) == 0);
  338 +
  339 + /* May not start with 0. */
  340 + strcpy(buf,"01");
  341 + assert(string2ll(buf,strlen(buf),&v) == 0);
  342 +
  343 + strcpy(buf,"-1");
  344 + assert(string2ll(buf,strlen(buf),&v) == 1);
  345 + assert(v == -1);
  346 +
  347 + strcpy(buf,"0");
  348 + assert(string2ll(buf,strlen(buf),&v) == 1);
  349 + assert(v == 0);
  350 +
  351 + strcpy(buf,"1");
  352 + assert(string2ll(buf,strlen(buf),&v) == 1);
  353 + assert(v == 1);
  354 +
  355 + strcpy(buf,"99");
  356 + assert(string2ll(buf,strlen(buf),&v) == 1);
  357 + assert(v == 99);
  358 +
  359 + strcpy(buf,"-99");
  360 + assert(string2ll(buf,strlen(buf),&v) == 1);
  361 + assert(v == -99);
  362 +
  363 + strcpy(buf,"-9223372036854775808");
  364 + assert(string2ll(buf,strlen(buf),&v) == 1);
  365 + assert(v == LLONG_MIN);
  366 +
  367 + strcpy(buf,"-9223372036854775809"); /* overflow */
  368 + assert(string2ll(buf,strlen(buf),&v) == 0);
  369 +
  370 + strcpy(buf,"9223372036854775807");
  371 + assert(string2ll(buf,strlen(buf),&v) == 1);
  372 + assert(v == LLONG_MAX);
  373 +
  374 + strcpy(buf,"9223372036854775808"); /* overflow */
  375 + assert(string2ll(buf,strlen(buf),&v) == 0);
324 376 }
325 377
326   -int isStringRepresentableAsLong(sds s, long *longval) {
327   - long long ll;
  378 +void test_string2l(void) {
  379 + char buf[32];
  380 + long v;
  381 +
  382 + /* May not start with +. */
  383 + strcpy(buf,"+1");
  384 + assert(string2l(buf,strlen(buf),&v) == 0);
  385 +
  386 + /* May not start with 0. */
  387 + strcpy(buf,"01");
  388 + assert(string2l(buf,strlen(buf),&v) == 0);
  389 +
  390 + strcpy(buf,"-1");
  391 + assert(string2l(buf,strlen(buf),&v) == 1);
  392 + assert(v == -1);
  393 +
  394 + strcpy(buf,"0");
  395 + assert(string2l(buf,strlen(buf),&v) == 1);
  396 + assert(v == 0);
  397 +
  398 + strcpy(buf,"1");
  399 + assert(string2l(buf,strlen(buf),&v) == 1);
  400 + assert(v == 1);
  401 +
  402 + strcpy(buf,"99");
  403 + assert(string2l(buf,strlen(buf),&v) == 1);
  404 + assert(v == 99);
328 405
329   - if (isStringRepresentableAsLongLong(s,&ll) == REDIS_ERR) return REDIS_ERR;
330   - if (ll < LONG_MIN || ll > LONG_MAX) return REDIS_ERR;
331   - *longval = (long)ll;
332   - return REDIS_OK;
  406 + strcpy(buf,"-99");
  407 + assert(string2l(buf,strlen(buf),&v) == 1);
  408 + assert(v == -99);
  409 +
  410 +#if LONG_MAX != LLONG_MAX
  411 + strcpy(buf,"-2147483648");
  412 + assert(string2l(buf,strlen(buf),&v) == 1);
  413 + assert(v == LONG_MIN);
  414 +
  415 + strcpy(buf,"-2147483649"); /* overflow */
  416 + assert(string2l(buf,strlen(buf),&v) == 0);
  417 +
  418 + strcpy(buf,"2147483647");
  419 + assert(string2l(buf,strlen(buf),&v) == 1);
  420 + assert(v == LONG_MAX);
  421 +
  422 + strcpy(buf,"2147483648"); /* overflow */
  423 + assert(string2l(buf,strlen(buf),&v) == 0);
  424 +#endif
333 425 }
334 426
335   -int isObjectRepresentableAsLongLong(robj *o, long long *llongval) {
336   - redisAssert(o->type == REDIS_STRING);
337   - if (o->encoding == REDIS_ENCODING_INT) {
338   - if (llongval) *llongval = (long) o->ptr;
339   - return REDIS_OK;
340   - } else {
341   - return isStringRepresentableAsLongLong(o->ptr,llongval);
342   - }
  427 +int main(int argc, char **argv) {
  428 + test_string2ll();
  429 + test_string2l();
  430 + return 0;
343 431 }
  432 +#endif
12 src/util.h
... ... @@ -0,0 +1,12 @@
  1 +#ifndef __REDIS_UTIL_H
  2 +#define __REDIS_UTIL_H
  3 +
  4 +int stringmatchlen(const char *p, int plen, const char *s, int slen, int nocase);
  5 +int stringmatch(const char *p, const char *s, int nocase);
  6 +long long memtoll(const char *p, int *err);
  7 +int ll2string(char *s, size_t len, long long value);
  8 +int string2ll(char *s, size_t slen, long long *value);
  9 +int string2l(char *s, size_t slen, long *value);
  10 +int d2string(char *buf, size_t len, double value);
  11 +
  12 +#endif

0 comments on commit 5d08193

Please sign in to comment.
Something went wrong with that request. Please try again.