diff --git a/deps/redis/util.c b/deps/redis/util.c index 8fe9e04..3524577 100644 --- a/deps/redis/util.c +++ b/deps/redis/util.c @@ -207,15 +207,6 @@ int lpStringToInt64(const char *s, unsigned long slen, int64_t *value) { return 1; } -double zzlStrtod(unsigned char *vstr, unsigned int vlen) { - char buf[128]; - if (vlen > sizeof(buf) - 1) - vlen = sizeof(buf) - 1; - memcpy(buf,vstr,vlen); - buf[vlen] = '\0'; - return strtod(buf,NULL); -} - /* Returns 1 if the double value can safely be represented in long long without * precision loss, in which case the corresponding long long is stored in the out variable. */ static int double2ll(double d, long long *out) { diff --git a/deps/redis/util.h b/deps/redis/util.h index 890375b..39b8162 100644 --- a/deps/redis/util.h +++ b/deps/redis/util.h @@ -14,11 +14,20 @@ /* Bytes needed for long -> str + '\0' */ #define LONG_STR_SIZE 21 +/* The maximum number of characters needed to for d2string/fpconv_dtoa call. + * Since it uses %g and not %f, some 40 chars should be enough. */ +#define MAX_D2STRING_CHARS 128 + int ll2string(char *s, size_t len, long long value); int ull2string(char *s, size_t len, unsigned long long value); int lpStringToInt64(const char *s, unsigned long slen, int64_t *value); unsigned int getEnvVar(const char* varName, unsigned int defaultVal); -double zzlStrtod(unsigned char *vstr, unsigned int vlen); + +/* This is the exact function that is used in redis zset implementation for + * double <-> string conversions. Using some other function may result in + * incompatibilities as you can also convert double to string that results in + * loss of precision, or it might not represent inf, -inf or nan values + * similar to this function output. */ int d2string(char *buf, size_t len, double value); #endif /*LIBRDB_UTIL_H*/ diff --git a/src/ext/handlersToJson.c b/src/ext/handlersToJson.c index 5bc312a..01d910f 100644 --- a/src/ext/handlersToJson.c +++ b/src/ext/handlersToJson.c @@ -348,7 +348,7 @@ static RdbRes toJsonSet(RdbParser *p, void *userData, RdbBulk member) { static RdbRes toJsonZset(RdbParser *p, void *userData, RdbBulk member, double score) { RdbxToJson *ctx = userData; - char score_str[64]; + char score_str[MAX_D2STRING_CHARS]; int len = d2string(score_str, sizeof(score_str), score); if (ctx->state == R2J_IN_KEY) { diff --git a/src/ext/handlersToResp.c b/src/ext/handlersToResp.c index bf6b7a8..f21b45d 100644 --- a/src/ext/handlersToResp.c +++ b/src/ext/handlersToResp.c @@ -364,7 +364,7 @@ static RdbRes toRespZset(RdbParser *p, void *userData, RdbBulk member, double sc IOV_CONST(&iov[3], "\r\n$"); /* write score */ - char score_str[256]; + char score_str[MAX_D2STRING_CHARS]; int len = d2string(score_str, sizeof(score_str), score); assert(len != 0); IOV_VALUE(&iov[4], len, scoreLenStr); diff --git a/src/lib/parser.c b/src/lib/parser.c index b779676..8555517 100644 --- a/src/lib/parser.c +++ b/src/lib/parser.c @@ -31,6 +31,7 @@ #include "../../deps/redis/zipmap.h" #include "../../deps/redis/intset.h" #include "../../deps/redis/lzf.h" +#include "../../deps/redis/t_zset.h" #define DONE_FILL_BULK SIZE_MAX @@ -2036,7 +2037,7 @@ RdbStatus rdbLoadDoubleValue(RdbParser *p, double *val) { /* Try to read double value and then copy it to the destination including one * byte prefix. See rdbLoadDoubleValue() for details. */ -RdbStatus rdbLoadDoubleValueToDest(RdbParser *p, char *dst, int *written) { +RdbStatus rdbLoadDoubleValueToBuff(RdbParser *p, char *dst, int *written) { double val; unsigned char len; BulkInfo *binfo; @@ -2053,11 +2054,10 @@ RdbStatus rdbLoadDoubleValueToDest(RdbParser *p, char *dst, int *written) { case 253: /* NAN */ return RDB_STATUS_OK; default: - IF_NOT_OK_RETURN(rdbLoad(p, len, RQ_ALLOC, NULL, &binfo)); - if (sscanf(binfo->ref, "%lg", &val) != 1) + IF_NOT_OK_RETURN(rdbLoad(p, len, RQ_ALLOC_REF, dst, &binfo)); + if (sscanf(dst, "%lg", &val) != 1) return RDB_STATUS_ERROR; - memcpy(dst, binfo->ref, len); *written += len; return RDB_STATUS_OK; } diff --git a/src/lib/parser.h b/src/lib/parser.h index ae9a59e..56a5bf8 100644 --- a/src/lib/parser.h +++ b/src/lib/parser.h @@ -445,7 +445,7 @@ void subElementCallEnd(RdbParser *p, RdbBulk *bulkResult, size_t *len); RdbStatus rdbLoadFloatValue(RdbParser *p, float *val); RdbStatus rdbLoadBinaryDoubleValue(RdbParser *p, double *val); RdbStatus rdbLoadDoubleValue(RdbParser *p, double *val); -RdbStatus rdbLoadDoubleValueToDest(RdbParser *p, char *dst, int *written); +RdbStatus rdbLoadDoubleValueToBuff(RdbParser *p, char *dst, int *written); RdbStatus rdbLoadLen(RdbParser *p, int *isencoded, uint64_t *lenptr, unsigned char* outbuff, int *outbufflen); RdbStatus rdbLoadInteger(RdbParser *p, int enctype, AllocTypeRq type, char *refBuf, BulkInfo **out); RdbStatus rdbLoadString(RdbParser *p, AllocTypeRq type, char *refBuf, BulkInfo **out); diff --git a/src/lib/parserRaw.c b/src/lib/parserRaw.c index 4102392..f980048 100644 --- a/src/lib/parserRaw.c +++ b/src/lib/parserRaw.c @@ -625,7 +625,7 @@ RdbStatus elementRawZset(RdbParser *p) { IF_NOT_OK_RETURN(aggUpdateWritten(p, sizeof(double))); } else { int written; - IF_NOT_OK_RETURN(rdbLoadDoubleValueToDest(p, rawCtx->at, &written)); + IF_NOT_OK_RETURN(rdbLoadDoubleValueToBuff(p, rawCtx->at, &written)); IF_NOT_OK_RETURN(aggUpdateWritten(p, written)); }