Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ruanhaishen
redis
Commits
45025713
Unverified
Commit
45025713
authored
Nov 19, 2019
by
Salvatore Sanfilippo
Committed by
GitHub
Nov 19, 2019
Browse files
Merge pull request #6541 from artix75/module-long-double
Module API: add support for long double conversions and replies
parents
e916058f
e7144fbe
Changes
4
Hide whitespace changes
Inline
Side-by-side
src/module.c
View file @
45025713
...
...
@@ -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
);
...
...
src/redismodule.h
View file @
45025713
...
...
@@ -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
);
...
...
tests/modules/misc.c
View file @
45025713
...
...
@@ -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
)
...
...
tests/unit/moduleapi/misc.tcl
View file @
45025713
...
...
@@ -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
]
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment