1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
|
// SPDX-FileCopyrightText: 2024 Redict Contributors
// SPDX-FileCopyrightText: 2024 Salvatore Sanfilippo <antirez at gmail dot com>
//
// SPDX-License-Identifier: BSD-3-Clause
// SPDX-License-Identifier: LGPL-3.0-only
#include "redictmodule.h"
#include <strings.h>
#include <errno.h>
#include <stdlib.h>
/* If a string is ":deleted:", the special value for deleted hash fields is
* returned; otherwise the input string is returned. */
static RedictModuleString *value_or_delete(RedictModuleString *s) {
if (!strcasecmp(RedictModule_StringPtrLen(s, NULL), ":delete:"))
return REDICTMODULE_HASH_DELETE;
else
return s;
}
/* HASH.SET key flags field1 value1 [field2 value2 ..]
*
* Sets 1-4 fields. Returns the same as RedictModule_HashSet().
* Flags is a string of "nxa" where n = NX, x = XX, a = COUNT_ALL.
* To delete a field, use the value ":delete:".
*/
int hash_set(RedictModuleCtx *ctx, RedictModuleString **argv, int argc) {
if (argc < 5 || argc % 2 == 0 || argc > 11)
return RedictModule_WrongArity(ctx);
RedictModule_AutoMemory(ctx);
RedictModuleKey *key = RedictModule_OpenKey(ctx, argv[1], REDICTMODULE_WRITE);
size_t flags_len;
const char *flags_str = RedictModule_StringPtrLen(argv[2], &flags_len);
int flags = REDICTMODULE_HASH_NONE;
for (size_t i = 0; i < flags_len; i++) {
switch (flags_str[i]) {
case 'n': flags |= REDICTMODULE_HASH_NX; break;
case 'x': flags |= REDICTMODULE_HASH_XX; break;
case 'a': flags |= REDICTMODULE_HASH_COUNT_ALL; break;
}
}
/* Test some varargs. (In real-world, use a loop and set one at a time.) */
int result;
errno = 0;
if (argc == 5) {
result = RedictModule_HashSet(key, flags,
argv[3], value_or_delete(argv[4]),
NULL);
} else if (argc == 7) {
result = RedictModule_HashSet(key, flags,
argv[3], value_or_delete(argv[4]),
argv[5], value_or_delete(argv[6]),
NULL);
} else if (argc == 9) {
result = RedictModule_HashSet(key, flags,
argv[3], value_or_delete(argv[4]),
argv[5], value_or_delete(argv[6]),
argv[7], value_or_delete(argv[8]),
NULL);
} else if (argc == 11) {
result = RedictModule_HashSet(key, flags,
argv[3], value_or_delete(argv[4]),
argv[5], value_or_delete(argv[6]),
argv[7], value_or_delete(argv[8]),
argv[9], value_or_delete(argv[10]),
NULL);
} else {
return RedictModule_ReplyWithError(ctx, "ERR too many fields");
}
/* Check errno */
if (result == 0) {
if (errno == ENOTSUP)
return RedictModule_ReplyWithError(ctx, REDICTMODULE_ERRORMSG_WRONGTYPE);
else
RedictModule_Assert(errno == ENOENT);
}
return RedictModule_ReplyWithLongLong(ctx, result);
}
int RedictModule_OnLoad(RedictModuleCtx *ctx, RedictModuleString **argv, int argc) {
REDICTMODULE_NOT_USED(argv);
REDICTMODULE_NOT_USED(argc);
if (RedictModule_Init(ctx, "hash", 1, REDICTMODULE_APIVER_1) ==
REDICTMODULE_OK &&
RedictModule_CreateCommand(ctx, "hash.set", hash_set, "write",
1, 1, 1) == REDICTMODULE_OK) {
return REDICTMODULE_OK;
} else {
return REDICTMODULE_ERR;
}
}
|