#include <sys/time.h>
#include <string.h>
#include <iostream>
#include <string>
#include <vector>
#include <hiredis/hiredis.h>
namespace single_redis_client {
namespace details {
template <typename T>
static constexpr bool is_int64_v() {
return std::is_same<int, std::int64_t>::value;
}
template <typename T>
static constexpr bool is_uint64_v() {
return std::is_same<int, std::uint64_t>::value;
}
template <typename T>
static constexpr bool is_64_integer() {
return is_int64_v<T>() || is_uint64_v<T>();
}
template <typename T>
static constexpr bool is_string_v() {
return std::is_same<T, std::string>::value;
}
template <typename T>
static constexpr bool is_constchar_v() {
return std::is_same<T, const char *>::value;
}
template <typename T>
static constexpr bool is_char_array_v() {
return std::is_array<T>::value && std::is_same<char, std::remove_reference<decltype(*std::declval<T>())>>::value;
}
}
class redis_client {
public:
redis_client() = default;
~redis_client() {
if (nullptr != conn_) {
redisFree(conn_);
conn_ = nullptr;
}
}
public:
struct redis_config {
const char *ip = "127.0.0.1";
int port = 6379;
int timeout = 5;
std::string err_msg;
};
public:
bool init(redis_config &config) {
struct timeval tm = { config.timeout, 0 };
conn_ = redisConnectWithTimeout(config.ip, config.port, tm);
if (nullptr == conn_) {
config.err_msg = "redisConnectWithTimeout called failed redis context is null.";
return false;
}
if (conn_->err) {
config.err_msg = conn_->err;
return false;
}
return true;
}
template <typename T>
bool set(const char *key, const T &val, std::string &err_msg) {
redisReply *reply = nullptr;
std::string str_val;
if (details::is_string_v<T>() || details::is_constchar_v<T>()) {
str_val = val;
}
else if (std::is_floating_point<T>::value) {
double num = *((double *)(&val));
str_val = std::to_string(num);
}
else if (std::is_integral<T>::value) {
long num = *((long *)(&val));
str_val = std::to_string(num);
}
else {
err_msg = "not support data type.";
reply_guard guard(reply);
return false;
}
reply = (redisReply *)redisCommand(conn_, "SET %b %b", key, strlen(key), str_val.c_str(), str_val.size());
if (nullptr == reply) {
err_msg = "redisCommand execute failed, reply is null.";
return false;
}
reply_guard guard(reply);
if (!(REDIS_REPLY_STATUS == reply->type) && (0 == strcasecmp(reply->str, "OK"))) {
err_msg = reply->str;
return false;
}
return true;
}
private:
struct reply_guard {
reply_guard(redisReply *r) : reply_(r) {
}
~reply_guard() {
if (nullptr != reply_) {
freeReplyObject(reply_);
reply_ = nullptr;
}
}
private:
redisReply *reply_ = nullptr;
};
private:
redisContext *conn_ = nullptr;
};
}
int main() {
single_redis_client::redis_client client;
single_redis_client::redis_client::redis_config config;
if (false == client.init(config)) {
std::cerr << config.err_msg << std::endl;
return -1;
}
std::string str0 = "111";
if (false == client.set("key1", str0, config.err_msg)) {
std::cerr << config.err_msg << std::endl;
}
const char *str1 = "111";
if (false == client.set("key2", str1, config.err_msg)) {
std::cerr << config.err_msg << std::endl;
}
double n0 = 11.11;
if (false == client.set("key3", n0, config.err_msg)) {
std::cerr << config.err_msg << std::endl;
}
long n1 = 22222;
if (false == client.set("key4", n1, config.err_msg)) {
std::cerr << config.err_msg << std::endl;
}
return 0;
}