common/redisreply.h (74 lines of code) (raw):
#ifndef __REDISREPLY__
#define __REDISREPLY__
#include <hiredis/hiredis.h>
#include <string>
#include <stdexcept>
#include "rediscommand.h"
namespace swss {
class RedisContext;
class RedisError : public std::runtime_error
{
int m_err;
std::string m_errstr;
mutable std::string m_message;
public:
RedisError(const std::string& arg, redisContext *ctx)
: std::runtime_error(arg)
, m_err(ctx->err)
, m_errstr(ctx->errstr)
{
}
const char *what() const noexcept override
{
if (m_message.empty())
{
m_message = std::string("RedisError: ") + std::runtime_error::what() + ", err=" + std::to_string(m_err) + ": errstr=" + m_errstr;
}
return m_message.c_str();
}
};
// Follow the data structure used by redis-py
// ref: https://redis-py.readthedocs.io/en/stable/_modules/redis/client.html#Redis.pubsub
struct RedisMessage
{
std::string type;
std::string pattern;
std::string channel;
std::string data;
};
class RedisReply
{
public:
/*
* Send a new command to redis and wait for reply
* No reply type specified.
*/
RedisReply(RedisContext *ctx, const RedisCommand& command);
RedisReply(RedisContext *ctx, const std::string& command);
/*
* Send a new command to redis and waits for reply
* The reply must be one of REDIS_REPLY_* format (e.g. REDIS_REPLY_STATUS,
* REDIS_REPLY_INTEGER, ...)
* isFormatted - Set to true if the command is already formatted in redis
* protocol
*/
RedisReply(RedisContext *ctx, const RedisCommand& command, int expectedType);
RedisReply(RedisContext *ctx, const std::string& command, int expectedType);
/* auto_ptr for native structure (Free the memory on destructor) */
RedisReply(redisReply *reply);
/* Free the resources */
~RedisReply();
/* Return the actual reply object and release the ownership */
redisReply *release();
/* Return the actual reply object */
redisReply *getContext();
size_t getChildCount();
redisReply *getChild(size_t index);
/* Return the actual child reply object and release the ownership */
redisReply *releaseChild(size_t index);
void checkReplyType(int expectedType);
template<typename TYPE>
TYPE getReply();
/* Check that the status is OK, throw exception otherwise */
void checkStatusOK();
/* Check that the status is QUEUED, throw exception otherwise */
void checkStatusQueued();
std::string to_string();
static std::string to_string(redisReply *reply, std::string command = std::string());
private:
void checkStatus(const char *status);
void checkReply();
static std::string formatReply(std::string command, struct redisReply **element, size_t elements);
static std::string formatReply(std::string command, long long integer);
static std::string formatReply(std::string command, const char* str, size_t len);
static std::string formatSscanReply(struct redisReply **element, size_t elements);
static std::string formatHscanReply(struct redisReply **element, size_t elements);
static std::string formatDictReply(struct redisReply **element, size_t elements);
static std::string formatArrayReply(struct redisReply **element, size_t elements);
static std::string formatListReply(struct redisReply **element, size_t elements);
static std::string formatTupleReply(struct redisReply **element, size_t elements);
static std::string formatStringWithQuot(std::string str);
redisReply *m_reply;
};
}
#endif