Created
May 9, 2023 18:40
-
-
Save michael-grunder/54ee26173b619f1546c60b0141bb675b to your computer and use it in GitHub Desktop.
A small example storing binary data in a Redis set with hiredis.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Compile with: cc -Wall -ggdb3 -o hiredis-binary-example hiredis-binary-example.c -lhiredis | |
#include <stdio.h> | |
#include <hiredis/hiredis.h> | |
#include <stddef.h> | |
#include <stdlib.h> | |
#include <string.h> | |
struct binaryData { | |
char *str; | |
size_t len; | |
}; | |
/* Some binary data. This could come from anywhere */ | |
struct binaryData emojis[] = { | |
{ "\xf0\x9f\x98\x81", 4 }, | |
{ "\xf0\x9f\x98\x82", 4 }, | |
{ "\xf0\x9f\x98\x8d", 4 }, | |
{ "\xf0\x9f\x91\x8d", 4 }, | |
{ "\xe2\x9d\xa4", 3 }, | |
{ "\xf0\x9f\x98\x98", 4 }, | |
{ "\xf0\x9f\x98\x89", 4 }, | |
{ "\xf0\x9f\x98\x8e", 4 }, | |
{ "\xf0\x9f\xa4\xa3", 4 }, | |
{ "\xf0\x9f\xa4\x94", 4 } | |
}; | |
#define panicAbortLiteral(literal) panicAbort("%s", literal) | |
#define panicAbort(fmt, ...) \ | |
do { \ | |
fprintf(stderr, "Error: " fmt "\n", __VA_ARGS__); \ | |
exit(1); \ | |
} while (0) | |
void verifyRedisReply(redisContext *c, redisReply *reply, int type) { | |
if (c->err) { | |
panicAbort("Error sending redis command (%s)", c->err ? c->errstr : NULL); | |
} else if (reply == NULL) { | |
panicAbortLiteral("Hiredis returned a NULL reply!"); | |
} else if (reply->type != type) { | |
panicAbort("Redis returned type %d but expected type %d", reply->type, type); | |
} | |
} | |
/* Just a helper that takes binary data and hex encodes it for printing */ | |
size_t binaryToHex(char *dst, const char *src, size_t len) { | |
const char * const hexmap = "0123456789abcdef"; | |
size_t i; | |
for (i = 0; i < len; i++) { | |
*dst++ = hexmap[(src[i] >> 4) & 0xf]; | |
*dst++ = hexmap[src[i] & 0xf]; | |
} | |
return len * 2; | |
} | |
int main(void) { | |
redisContext *c; | |
redisReply *reply; | |
char hex[8]; | |
c = redisConnect("localhost", 6379); | |
if (c == NULL) { | |
panicAbortLiteral("Failed to create redisContext"); | |
} else if (c->err) { | |
panicAbort("Couldn't connect to redis at %s:%d (%s)", "localhost", 6379, c->err ? c->errstr : "unknown"); | |
} | |
reply = redisCommand(c, "DEL %s", "emoji-set"); | |
verifyRedisReply(c, reply, REDIS_REPLY_INTEGER); | |
freeReplyObject(reply); | |
for (size_t i = 0; i < sizeof(emojis)/sizeof(*emojis); i++) { | |
reply = redisCommand(c, "SADD %s %b", "emoji-set", emojis[i].str, emojis[i].len); | |
verifyRedisReply(c, reply, REDIS_REPLY_INTEGER); | |
freeReplyObject(reply); | |
} | |
reply = redisCommand(c, "SMEMBERS %s", "emoji-set"); | |
verifyRedisReply(c, reply, REDIS_REPLY_ARRAY); | |
for (size_t i = 0; i < reply->elements; i++) { | |
verifyRedisReply(c, reply->element[i], REDIS_REPLY_STRING); | |
memset(hex, 0, sizeof(hex)); | |
binaryToHex(hex, reply->element[i]->str, reply->element[i]->len); | |
printf("[%zu] %8s => ", i, hex); | |
for (size_t j = 0; j < reply->element[i]->len; j++) { | |
putchar(reply->element[i]->str[j]); | |
} | |
printf("\n"); | |
} | |
freeReplyObject(reply); | |
redisFree(c); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment