mirror of
https://codeberg.org/redict/redict.git
synced 2025-01-22 16:18:28 -05:00
Merge pull request #6541 from artix75/module-long-double
Module API: add support for long double conversions and replies
This commit is contained in:
commit
45025713a8
41
src/module.c
41
src/module.c
@ -1012,6 +1012,21 @@ RedisModuleString *RM_CreateStringFromLongLong(RedisModuleCtx *ctx, long long ll
|
||||
return RM_CreateString(ctx,buf,len);
|
||||
}
|
||||
|
||||
/* Like RedisModule_CreatString(), but creates a string starting from a long
|
||||
* double.
|
||||
*
|
||||
* The returned string must be released with RedisModule_FreeString() or by
|
||||
* enabling automatic memory management.
|
||||
*
|
||||
* The passed context 'ctx' may be NULL if necessary, see the
|
||||
* RedisModule_CreateString() documentation for more info. */
|
||||
RedisModuleString *RM_CreateStringFromLongDouble(RedisModuleCtx *ctx, long double ld, int humanfriendly) {
|
||||
char buf[MAX_LONG_DOUBLE_CHARS];
|
||||
size_t len = ld2string(buf,sizeof(buf),ld,
|
||||
(humanfriendly ? LD_STR_HUMAN : LD_STR_AUTO));
|
||||
return RM_CreateString(ctx,buf,len);
|
||||
}
|
||||
|
||||
/* Like RedisModule_CreatString(), but creates a string starting from another
|
||||
* RedisModuleString.
|
||||
*
|
||||
@ -1116,6 +1131,14 @@ int RM_StringToDouble(const RedisModuleString *str, double *d) {
|
||||
return (retval == C_OK) ? REDISMODULE_OK : REDISMODULE_ERR;
|
||||
}
|
||||
|
||||
/* Convert the string into a long double, storing it at `*ld`.
|
||||
* Returns REDISMODULE_OK on success or REDISMODULE_ERR if the string is
|
||||
* not a valid string representation of a double value. */
|
||||
int RM_StringToLongDouble(const RedisModuleString *str, long double *ld) {
|
||||
int retval = string2ld(str->ptr,sdslen(str->ptr),ld);
|
||||
return retval ? REDISMODULE_OK : REDISMODULE_ERR;
|
||||
}
|
||||
|
||||
/* Compare two string objects, returning -1, 0 or 1 respectively if
|
||||
* a < b, a == b, a > b. Strings are compared byte by byte as two
|
||||
* binary blobs without any encoding care / collation attempt. */
|
||||
@ -1441,6 +1464,21 @@ int RM_ReplyWithDouble(RedisModuleCtx *ctx, double d) {
|
||||
return REDISMODULE_OK;
|
||||
}
|
||||
|
||||
/* Send a string reply obtained converting the long double 'ld' into a bulk
|
||||
* string. This function is basically equivalent to converting a long double
|
||||
* into a string into a C buffer, and then calling the function
|
||||
* RedisModule_ReplyWithStringBuffer() with the buffer and length.
|
||||
* The double string uses human readable formatting (see
|
||||
* `addReplyHumanLongDouble` in networking.c).
|
||||
*
|
||||
* The function always returns REDISMODULE_OK. */
|
||||
int RM_ReplyWithLongDouble(RedisModuleCtx *ctx, long double ld) {
|
||||
client *c = moduleGetReplyClient(ctx);
|
||||
if (c == NULL) return REDISMODULE_OK;
|
||||
addReplyHumanLongDouble(c, ld);
|
||||
return REDISMODULE_OK;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
* Commands replication API
|
||||
* -------------------------------------------------------------------------- */
|
||||
@ -7140,6 +7178,7 @@ void moduleRegisterCoreAPI(void) {
|
||||
REGISTER_API(ReplyWithNull);
|
||||
REGISTER_API(ReplyWithCallReply);
|
||||
REGISTER_API(ReplyWithDouble);
|
||||
REGISTER_API(ReplyWithLongDouble);
|
||||
REGISTER_API(GetSelectedDb);
|
||||
REGISTER_API(SelectDb);
|
||||
REGISTER_API(OpenKey);
|
||||
@ -7150,6 +7189,7 @@ void moduleRegisterCoreAPI(void) {
|
||||
REGISTER_API(ListPop);
|
||||
REGISTER_API(StringToLongLong);
|
||||
REGISTER_API(StringToDouble);
|
||||
REGISTER_API(StringToLongDouble);
|
||||
REGISTER_API(Call);
|
||||
REGISTER_API(CallReplyProto);
|
||||
REGISTER_API(FreeCallReply);
|
||||
@ -7161,6 +7201,7 @@ void moduleRegisterCoreAPI(void) {
|
||||
REGISTER_API(CreateStringFromCallReply);
|
||||
REGISTER_API(CreateString);
|
||||
REGISTER_API(CreateStringFromLongLong);
|
||||
REGISTER_API(CreateStringFromLongDouble);
|
||||
REGISTER_API(CreateStringFromString);
|
||||
REGISTER_API(CreateStringPrintf);
|
||||
REGISTER_API(FreeString);
|
||||
|
@ -461,6 +461,7 @@ size_t REDISMODULE_API_FUNC(RedisModule_CallReplyLength)(RedisModuleCallReply *r
|
||||
RedisModuleCallReply *REDISMODULE_API_FUNC(RedisModule_CallReplyArrayElement)(RedisModuleCallReply *reply, size_t idx);
|
||||
RedisModuleString *REDISMODULE_API_FUNC(RedisModule_CreateString)(RedisModuleCtx *ctx, const char *ptr, size_t len);
|
||||
RedisModuleString *REDISMODULE_API_FUNC(RedisModule_CreateStringFromLongLong)(RedisModuleCtx *ctx, long long ll);
|
||||
RedisModuleString *REDISMODULE_API_FUNC(RedisModule_CreateStringFromLongDouble)(RedisModuleCtx *ctx, long double ld, int humanfriendly);
|
||||
RedisModuleString *REDISMODULE_API_FUNC(RedisModule_CreateStringFromString)(RedisModuleCtx *ctx, const RedisModuleString *str);
|
||||
RedisModuleString *REDISMODULE_API_FUNC(RedisModule_CreateStringPrintf)(RedisModuleCtx *ctx, const char *fmt, ...);
|
||||
void REDISMODULE_API_FUNC(RedisModule_FreeString)(RedisModuleCtx *ctx, RedisModuleString *str);
|
||||
@ -478,9 +479,11 @@ int REDISMODULE_API_FUNC(RedisModule_ReplyWithEmptyString)(RedisModuleCtx *ctx);
|
||||
int REDISMODULE_API_FUNC(RedisModule_ReplyWithVerbatimString)(RedisModuleCtx *ctx, const char *buf, size_t len);
|
||||
int REDISMODULE_API_FUNC(RedisModule_ReplyWithNull)(RedisModuleCtx *ctx);
|
||||
int REDISMODULE_API_FUNC(RedisModule_ReplyWithDouble)(RedisModuleCtx *ctx, double d);
|
||||
int REDISMODULE_API_FUNC(RedisModule_ReplyWithLongDouble)(RedisModuleCtx *ctx, long double d);
|
||||
int REDISMODULE_API_FUNC(RedisModule_ReplyWithCallReply)(RedisModuleCtx *ctx, RedisModuleCallReply *reply);
|
||||
int REDISMODULE_API_FUNC(RedisModule_StringToLongLong)(const RedisModuleString *str, long long *ll);
|
||||
int REDISMODULE_API_FUNC(RedisModule_StringToDouble)(const RedisModuleString *str, double *d);
|
||||
int REDISMODULE_API_FUNC(RedisModule_StringToLongDouble)(const RedisModuleString *str, long double *d);
|
||||
void REDISMODULE_API_FUNC(RedisModule_AutoMemory)(RedisModuleCtx *ctx);
|
||||
int REDISMODULE_API_FUNC(RedisModule_Replicate)(RedisModuleCtx *ctx, const char *cmdname, const char *fmt, ...);
|
||||
int REDISMODULE_API_FUNC(RedisModule_ReplicateVerbatim)(RedisModuleCtx *ctx);
|
||||
@ -679,6 +682,7 @@ static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int
|
||||
REDISMODULE_GET_API(ReplyWithNull);
|
||||
REDISMODULE_GET_API(ReplyWithCallReply);
|
||||
REDISMODULE_GET_API(ReplyWithDouble);
|
||||
REDISMODULE_GET_API(ReplyWithLongDouble);
|
||||
REDISMODULE_GET_API(GetSelectedDb);
|
||||
REDISMODULE_GET_API(SelectDb);
|
||||
REDISMODULE_GET_API(OpenKey);
|
||||
@ -689,6 +693,7 @@ static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int
|
||||
REDISMODULE_GET_API(ListPop);
|
||||
REDISMODULE_GET_API(StringToLongLong);
|
||||
REDISMODULE_GET_API(StringToDouble);
|
||||
REDISMODULE_GET_API(StringToLongDouble);
|
||||
REDISMODULE_GET_API(Call);
|
||||
REDISMODULE_GET_API(CallReplyProto);
|
||||
REDISMODULE_GET_API(FreeCallReply);
|
||||
@ -700,6 +705,7 @@ static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int
|
||||
REDISMODULE_GET_API(CreateStringFromCallReply);
|
||||
REDISMODULE_GET_API(CreateString);
|
||||
REDISMODULE_GET_API(CreateStringFromLongLong);
|
||||
REDISMODULE_GET_API(CreateStringFromLongDouble);
|
||||
REDISMODULE_GET_API(CreateStringFromString);
|
||||
REDISMODULE_GET_API(CreateStringPrintf);
|
||||
REDISMODULE_GET_API(FreeString);
|
||||
|
@ -6,6 +6,8 @@
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#define UNUSED(x) (void)(x)
|
||||
|
||||
int test_call_generic(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
|
||||
{
|
||||
if (argc<2) {
|
||||
@ -40,6 +42,45 @@ int test_call_info(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
|
||||
return REDISMODULE_OK;
|
||||
}
|
||||
|
||||
int test_ld_conv(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
|
||||
UNUSED(argv);
|
||||
UNUSED(argc);
|
||||
long double ld = 0.00000000000000001L;
|
||||
const char *ldstr = "0.00000000000000001";
|
||||
RedisModuleString *s1 = RedisModule_CreateStringFromLongDouble(ctx, ld, 1);
|
||||
RedisModuleString *s2 =
|
||||
RedisModule_CreateString(ctx, ldstr, strlen(ldstr));
|
||||
if (RedisModule_StringCompare(s1, s2) != 0) {
|
||||
char err[4096];
|
||||
snprintf(err, 4096,
|
||||
"Failed to convert long double to string ('%s' != '%s')",
|
||||
RedisModule_StringPtrLen(s1, NULL),
|
||||
RedisModule_StringPtrLen(s2, NULL));
|
||||
RedisModule_ReplyWithError(ctx, err);
|
||||
goto final;
|
||||
}
|
||||
long double ld2 = 0;
|
||||
if (RedisModule_StringToLongDouble(s2, &ld2) == REDISMODULE_ERR) {
|
||||
RedisModule_ReplyWithError(ctx,
|
||||
"Failed to convert string to long double");
|
||||
goto final;
|
||||
}
|
||||
if (ld2 != ld) {
|
||||
char err[4096];
|
||||
snprintf(err, 4096,
|
||||
"Failed to convert string to long double (%.40Lf != %.40Lf)",
|
||||
ld2,
|
||||
ld);
|
||||
RedisModule_ReplyWithError(ctx, err);
|
||||
goto final;
|
||||
}
|
||||
RedisModule_ReplyWithLongDouble(ctx, ld2);
|
||||
final:
|
||||
RedisModule_FreeString(ctx, s1);
|
||||
RedisModule_FreeString(ctx, s2);
|
||||
return REDISMODULE_OK;
|
||||
}
|
||||
|
||||
int test_flushall(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
|
||||
{
|
||||
REDISMODULE_NOT_USED(argv);
|
||||
@ -151,6 +192,8 @@ int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
|
||||
return REDISMODULE_ERR;
|
||||
if (RedisModule_CreateCommand(ctx,"test.call_info", test_call_info,"",0,0,0) == REDISMODULE_ERR)
|
||||
return REDISMODULE_ERR;
|
||||
if (RedisModule_CreateCommand(ctx,"test.ld_conversion", test_ld_conv, "",0,0,0) == REDISMODULE_ERR)
|
||||
return REDISMODULE_ERR;
|
||||
if (RedisModule_CreateCommand(ctx,"test.flushall", test_flushall,"",0,0,0) == REDISMODULE_ERR)
|
||||
return REDISMODULE_ERR;
|
||||
if (RedisModule_CreateCommand(ctx,"test.dbsize", test_dbsize,"",0,0,0) == REDISMODULE_ERR)
|
||||
|
@ -16,6 +16,11 @@ start_server {tags {"modules"}} {
|
||||
assert { [string match "*cmdstat_module*" $info] }
|
||||
}
|
||||
|
||||
test {test long double conversions} {
|
||||
set ld [r test.ld_conversion]
|
||||
assert {[string match $ld "0.00000000000000001"]}
|
||||
}
|
||||
|
||||
test {test module db commands} {
|
||||
r set x foo
|
||||
set key [r test.randomkey]
|
||||
|
Loading…
Reference in New Issue
Block a user