Skip to content

Instantly share code, notes, and snippets.

@michael-grunder
Created May 9, 2023 18:40
Show Gist options
  • Save michael-grunder/54ee26173b619f1546c60b0141bb675b to your computer and use it in GitHub Desktop.
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.
// 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