11#include "r_32.h"
2+ #include <limits.h>
3+ #include <stdio.h>
24#include "rmalloc.h"
35#include "roaring.h"
46#include "common.h"
@@ -19,6 +21,53 @@ Bitmap* BITMAP_NILL = NULL;
1921 return REDISMODULE_ERR; \
2022 } while(0)
2123
24+ static int ReplyWithJaccardRatio (RedisModuleCtx * ctx , uint64_t intersection , uint64_t union_count ) {
25+ if (union_count == 0 ) {
26+ return RedisModule_ReplyWithStringBuffer (ctx , "-1" , 2 );
27+ }
28+
29+ if (intersection == 0 ) {
30+ return RedisModule_ReplyWithStringBuffer (ctx , "0" , 1 );
31+ }
32+
33+ if (intersection == union_count ) {
34+ return RedisModule_ReplyWithStringBuffer (ctx , "1" , 1 );
35+ }
36+
37+ static const uint64_t pow10 [] = {
38+ 1ULL , 10ULL , 100ULL , 1000ULL , 10000ULL , 100000ULL , 1000000ULL , 10000000ULL , 100000000ULL , 1000000000ULL
39+ };
40+
41+ uint64_t scaled = intersection ;
42+ for (int scale = 1 ; scale < (int ) (sizeof (pow10 ) / sizeof (pow10 [0 ])); scale ++ ) {
43+ if (scaled > UINT64_MAX / 10 ) {
44+ break ;
45+ }
46+
47+ scaled *= 10 ;
48+
49+ if (scaled % union_count == 0 ) {
50+ uint64_t value = scaled / union_count ;
51+ uint64_t int_part = value / pow10 [scale ];
52+ uint64_t frac_part = value % pow10 [scale ];
53+ char buffer [32 ];
54+ int len = snprintf (
55+ buffer ,
56+ sizeof (buffer ),
57+ "%llu.%0*llu" ,
58+ (unsigned long long ) int_part ,
59+ scale ,
60+ (unsigned long long ) frac_part );
61+ return RedisModule_ReplyWithStringBuffer (ctx , buffer , (size_t ) len );
62+ }
63+ }
64+
65+ double result = (double ) intersection / (double ) union_count ;
66+ char buffer [32 ];
67+ int len = snprintf (buffer , sizeof (buffer ), "%.17g" , result );
68+ return RedisModule_ReplyWithStringBuffer (ctx , buffer , (size_t ) len );
69+ }
70+
2271static int GetBitmapKey (RedisModuleCtx * ctx , RedisModuleString * keyName , Bitmap * * value_out , int mode ) {
2372 RedisModuleKey * key = RedisModule_OpenKey (ctx , keyName , mode );
2473 if (RedisModule_KeyType (key ) == REDISMODULE_KEYTYPE_EMPTY ) {
@@ -103,6 +152,10 @@ void BitmapFree(void* value) {
103152 * R.SETFULL <key>
104153 * */
105154int RSetFullCommand (RedisModuleCtx * ctx , RedisModuleString * * argv , int argc ) {
155+ if (argc != 2 ) {
156+ return RedisModule_WrongArity (ctx );
157+ }
158+
106159 RedisModule_AutoMemory (ctx );
107160 RedisModuleKey * key ;
108161 Bitmap * bitmap ;
@@ -127,6 +180,10 @@ int RSetFullCommand(RedisModuleCtx* ctx, RedisModuleString** argv, int argc) {
127180 * R.SETRANGE <key> <start_num> <end_num>
128181 * */
129182int RSetRangeCommand (RedisModuleCtx * ctx , RedisModuleString * * argv , int argc ) {
183+ if (argc != 4 ) {
184+ return RedisModule_WrongArity (ctx );
185+ }
186+
130187 RedisModule_AutoMemory (ctx );
131188 RedisModuleKey * key ;
132189 Bitmap * bitmap ;
@@ -226,6 +283,10 @@ int RGetBitCommand(RedisModuleCtx* ctx, RedisModuleString** argv, int argc) {
226283 * R.GETBITS <key> offset [offset1 offset2 ... offsetN]
227284 * */
228285int RGetBitManyCommand (RedisModuleCtx * ctx , RedisModuleString * * argv , int argc ) {
286+ if (argc < 3 ) {
287+ return RedisModule_WrongArity (ctx );
288+ }
289+
229290 RedisModule_AutoMemory (ctx );
230291 RedisModuleKey * key ;
231292 Bitmap * bitmap ;
@@ -270,6 +331,10 @@ int RGetBitManyCommand(RedisModuleCtx* ctx, RedisModuleString** argv, int argc)
270331 * R.CLEARBITS <key> offset [offset1 offset2 ... offsetN] [COUNT]
271332 * */
272333int RClearBitsCommand (RedisModuleCtx * ctx , RedisModuleString * * argv , int argc ) {
334+ if (argc < 3 ) {
335+ return RedisModule_WrongArity (ctx );
336+ }
337+
273338 RedisModule_AutoMemory (ctx );
274339 RedisModuleKey * key ;
275340 Bitmap * bitmap ;
@@ -318,6 +383,10 @@ int RClearBitsCommand(RedisModuleCtx* ctx, RedisModuleString** argv, int argc) {
318383 * R.OPTIMIZE <key> [MEM]
319384 * */
320385int ROptimizeBitCommand (RedisModuleCtx * ctx , RedisModuleString * * argv , int argc ) {
386+ if (argc < 2 || argc > 3 ) {
387+ return RedisModule_WrongArity (ctx );
388+ }
389+
321390 RedisModule_AutoMemory (ctx );
322391 Bitmap * bitmap ;
323392
@@ -348,6 +417,10 @@ int ROptimizeBitCommand(RedisModuleCtx* ctx, RedisModuleString** argv, int argc)
348417 * R.SETINTARRAY <key> <value1> [<value2> <value3> ... <valueN>]
349418 * */
350419int RSetIntArrayCommand (RedisModuleCtx * ctx , RedisModuleString * * argv , int argc ) {
420+ if (argc < 3 ) {
421+ return RedisModule_WrongArity (ctx );
422+ }
423+
351424 RedisModule_AutoMemory (ctx );
352425 RedisModuleKey * key ;
353426 Bitmap * bitmap ;
@@ -381,6 +454,10 @@ int RSetIntArrayCommand(RedisModuleCtx* ctx, RedisModuleString** argv, int argc)
381454 * R.DIFF <dest> <decreasing> <deductible>
382455 * */
383456int RDiffCommand (RedisModuleCtx * ctx , RedisModuleString * * argv , int argc ) {
457+ if (argc != 4 ) {
458+ return RedisModule_WrongArity (ctx );
459+ }
460+
384461 RedisModule_AutoMemory (ctx );
385462 RedisModuleKey * key ;
386463 Bitmap * bitmap ;
@@ -418,6 +495,10 @@ int RDiffCommand(RedisModuleCtx* ctx, RedisModuleString** argv, int argc) {
418495 * R.APPENDINTARRAY <key> <value1> [<value2> <value3> ... <valueN>]
419496 * */
420497int RAppendIntArrayCommand (RedisModuleCtx * ctx , RedisModuleString * * argv , int argc ) {
498+ if (argc < 3 ) {
499+ return RedisModule_WrongArity (ctx );
500+ }
501+
421502 RedisModule_AutoMemory (ctx );
422503 RedisModuleKey * key ;
423504 Bitmap * bitmap ;
@@ -457,6 +538,10 @@ int RAppendIntArrayCommand(RedisModuleCtx* ctx, RedisModuleString** argv, int ar
457538 * R.DELETEINTARRAY <key> <value1> [<value2> <value3> ... <valueN>]
458539 * */
459540int RDeleteIntArrayCommand (RedisModuleCtx * ctx , RedisModuleString * * argv , int argc ) {
541+ if (argc < 3 ) {
542+ return RedisModule_WrongArity (ctx );
543+ }
544+
460545 RedisModule_AutoMemory (ctx );
461546 RedisModuleKey * key ;
462547 Bitmap * bitmap ;
@@ -493,6 +578,10 @@ int RDeleteIntArrayCommand(RedisModuleCtx* ctx, RedisModuleString** argv, int ar
493578 * R.RANGEINTARRAY <key> <start> <end>
494579 * */
495580int RRangeIntArrayCommand (RedisModuleCtx * ctx , RedisModuleString * * argv , int argc ) {
581+ if (argc != 4 ) {
582+ return RedisModule_WrongArity (ctx );
583+ }
584+
496585 RedisModule_AutoMemory (ctx );
497586 RedisModuleKey * key ;
498587 Bitmap * bitmap ;
@@ -548,6 +637,10 @@ int RRangeIntArrayCommand(RedisModuleCtx* ctx, RedisModuleString** argv, int arg
548637 * R.GETINTARRAY <key>
549638 * */
550639int RGetIntArrayCommand (RedisModuleCtx * ctx , RedisModuleString * * argv , int argc ) {
640+ if (argc != 2 ) {
641+ return RedisModule_WrongArity (ctx );
642+ }
643+
551644 RedisModule_AutoMemory (ctx );
552645 RedisModuleKey * key ;
553646 Bitmap * bitmap ;
@@ -579,6 +672,10 @@ int RGetIntArrayCommand(RedisModuleCtx* ctx, RedisModuleString** argv, int argc)
579672 * R.SETBITARRAY <key> <value1>
580673 * */
581674int RSetBitArrayCommand (RedisModuleCtx * ctx , RedisModuleString * * argv , int argc ) {
675+ if (argc != 3 ) {
676+ return RedisModule_WrongArity (ctx );
677+ }
678+
582679 RedisModule_AutoMemory (ctx );
583680 RedisModuleKey * key ;
584681 Bitmap * bitmap ;
@@ -604,6 +701,10 @@ int RSetBitArrayCommand(RedisModuleCtx* ctx, RedisModuleString** argv, int argc)
604701 * R.GETBITARRAY <key>
605702 * */
606703int RGetBitArrayCommand (RedisModuleCtx * ctx , RedisModuleString * * argv , int argc ) {
704+ if (argc != 2 ) {
705+ return RedisModule_WrongArity (ctx );
706+ }
707+
607708 RedisModule_AutoMemory (ctx );
608709 RedisModuleKey * key ;
609710 Bitmap * bitmap ;
@@ -763,6 +864,10 @@ int RBitFlip(RedisModuleCtx* ctx, RedisModuleString** argv, int argc) {
763864 * R.BITOP <operation> <destkey> <key> [<key> ...]
764865 * */
765866int RBitOpCommand (RedisModuleCtx * ctx , RedisModuleString * * argv , int argc ) {
867+ if (argc < 4 ) {
868+ return RedisModule_WrongArity (ctx );
869+ }
870+
766871 RedisModule_AutoMemory (ctx );
767872 size_t len ;
768873 const char * operation = RedisModule_StringPtrLen (argv [1 ], & len );
@@ -798,6 +903,10 @@ int RBitOpCommand(RedisModuleCtx* ctx, RedisModuleString** argv, int argc) {
798903 * R.BITCOUNT <key>
799904 * */
800905int RBitCountCommand (RedisModuleCtx * ctx , RedisModuleString * * argv , int argc ) {
906+ if (argc != 2 ) {
907+ return RedisModule_WrongArity (ctx );
908+ }
909+
801910 RedisModule_AutoMemory (ctx );
802911 RedisModuleKey * key ;
803912 Bitmap * bitmap ;
@@ -820,6 +929,10 @@ int RBitCountCommand(RedisModuleCtx* ctx, RedisModuleString** argv, int argc) {
820929 * R.BITPOS <key> <bit>
821930 * */
822931int RBitPosCommand (RedisModuleCtx * ctx , RedisModuleString * * argv , int argc ) {
932+ if (argc != 3 ) {
933+ return RedisModule_WrongArity (ctx );
934+ }
935+
823936 RedisModule_AutoMemory (ctx );
824937 RedisModuleKey * key ;
825938 Bitmap * bitmap ;
@@ -847,6 +960,10 @@ int RBitPosCommand(RedisModuleCtx* ctx, RedisModuleString** argv, int argc) {
847960 * R.MIN <key>
848961 * */
849962int RMinCommand (RedisModuleCtx * ctx , RedisModuleString * * argv , int argc ) {
963+ if (argc != 2 ) {
964+ return RedisModule_WrongArity (ctx );
965+ }
966+
850967 RedisModule_AutoMemory (ctx );
851968 RedisModuleKey * key ;
852969 Bitmap * bitmap ;
@@ -868,6 +985,10 @@ int RMinCommand(RedisModuleCtx* ctx, RedisModuleString** argv, int argc) {
868985 * R.MAX <key>
869986 * */
870987int RMaxCommand (RedisModuleCtx * ctx , RedisModuleString * * argv , int argc ) {
988+ if (argc != 2 ) {
989+ return RedisModule_WrongArity (ctx );
990+ }
991+
871992 RedisModule_AutoMemory (ctx );
872993 RedisModuleKey * key ;
873994 Bitmap * bitmap ;
@@ -889,6 +1010,10 @@ int RMaxCommand(RedisModuleCtx* ctx, RedisModuleString** argv, int argc) {
8891010 * R.CLEAR <key>
8901011 * */
8911012int RClearCommand (RedisModuleCtx * ctx , RedisModuleString * * argv , int argc ) {
1013+ if (argc != 2 ) {
1014+ return RedisModule_WrongArity (ctx );
1015+ }
1016+
8921017 RedisModule_AutoMemory (ctx );
8931018 RedisModuleKey * key ;
8941019 Bitmap * bitmap ;
@@ -915,6 +1040,10 @@ int RClearCommand(RedisModuleCtx* ctx, RedisModuleString** argv, int argc) {
9151040 * R.CONTAINS <key1> <key2> [ALL, ALL_STRICT]
9161041 * */
9171042int RContainsCommand (RedisModuleCtx * ctx , RedisModuleString * * argv , int argc ) {
1043+ if (argc != 3 && argc != 4 ) {
1044+ return RedisModule_WrongArity (ctx );
1045+ }
1046+
9181047 RedisModule_AutoMemory (ctx );
9191048 Bitmap * b1 ;
9201049 Bitmap * b2 ;
@@ -954,6 +1083,10 @@ int RContainsCommand(RedisModuleCtx* ctx, RedisModuleString** argv, int argc) {
9541083 * R.JACCARD <key1> <key2>
9551084 * */
9561085int RJaccardCommand (RedisModuleCtx * ctx , RedisModuleString * * argv , int argc ) {
1086+ if (argc != 3 ) {
1087+ return RedisModule_WrongArity (ctx );
1088+ }
1089+
9571090 RedisModule_AutoMemory (ctx );
9581091 Bitmap * b1 ;
9591092 Bitmap * b2 ;
@@ -966,7 +1099,9 @@ int RJaccardCommand(RedisModuleCtx* ctx, RedisModuleString** argv, int argc) {
9661099 return REDISMODULE_ERR ;
9671100 }
9681101
969- return RedisModule_ReplyWithDouble (ctx , bitmap_jaccard (b1 , b2 ));
1102+ uint64_t intersection = roaring_bitmap_and_cardinality (b1 , b2 );
1103+ uint64_t union_count = roaring_bitmap_or_cardinality (b1 , b2 );
1104+ return ReplyWithJaccardRatio (ctx , intersection , union_count );
9701105}
9711106
9721107void R32Module_onShutdown (RedisModuleCtx * ctx , RedisModuleEvent e , uint64_t sub , void * data ) {
0 commit comments