File: hash.c

package info (click to toggle)
redict 7.3.6%2Bds-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 15,112 kB
  • sloc: ansic: 129,434; tcl: 46,164; makefile: 930; python: 815; ruby: 572; sh: 482; javascript: 30
file content (96 lines) | stat: -rw-r--r-- 3,744 bytes parent folder | download | duplicates (3)
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;
    }
}