// ---------------------------------------------------------------------- // File: ResponseParsing.cc // Author: Georgios Bitzes - CERN // ---------------------------------------------------------------------- /************************************************************************ * qclient - A simple redis C++ client with support for redirects * * Copyright (C) 2018 CERN/Switzerland * * * * This program is free software: you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation, either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see .* ************************************************************************/ #include "qclient/ResponseParsing.hh" #include "qclient/QClient.hh" #include #define SSTR(message) static_cast(std::ostringstream().flush() << message).str() namespace qclient { StatusParser::StatusParser(const redisReply *reply) { if(reply == nullptr) { error = "Received null redisReply"; isOk = false; return; } if(reply->type != REDIS_REPLY_STATUS) { error = SSTR("Unexpected reply type; was expecting STATUS, received " << qclient::describeRedisReply(reply)); isOk = false; return; } isOk = true; val = std::string(reply->str, reply->len); } StatusParser::StatusParser(const redisReplyPtr reply) : StatusParser(reply.get()) { } bool StatusParser::ok() const { return isOk; } std::string StatusParser::err() const { return error; } std::string StatusParser::value() const { return val; } IntegerParser::IntegerParser(const redisReply *reply) { if(reply == nullptr) { error = "Received null redisReply"; isOk = false; return; } if(reply->type != REDIS_REPLY_INTEGER) { error = SSTR("Unexpected reply type; was expecting INTEGER, received " << qclient::describeRedisReply(reply)); isOk = false; return; } isOk = true; val = reply->integer; } IntegerParser::IntegerParser(const redisReplyPtr reply) : IntegerParser(reply.get()) { } bool IntegerParser::ok() const { return isOk; } std::string IntegerParser::err() const { return error; } long long IntegerParser::value() const { return val; } StringParser::StringParser(const redisReply *reply) { if(reply == nullptr) { error = "Received null redisReply"; isOk = false; return; } if(reply->type != REDIS_REPLY_STRING) { error = SSTR("Unexpected reply type; was expecting STRING, received " << qclient::describeRedisReply(reply)); isOk = false; return; } isOk = true; val = std::string(reply->str, reply->len); } StringParser::StringParser(const redisReplyPtr reply) : StringParser(reply.get()) { } bool StringParser::ok() const { return isOk; } std::string StringParser::err() const { return error; } std::string StringParser::value() const { return val; } HgetallParser::HgetallParser(const redisReplyPtr reply) : HgetallParser(reply.get()) {} HgetallParser::HgetallParser(const redisReply *reply) { if(reply == nullptr) { error = "Received null redisReply"; isOk = false; return; } if(reply->type != REDIS_REPLY_ARRAY) { error = SSTR("Unexpected reply type; was expecting ARRAY, received " << qclient::describeRedisReply(reply)); isOk = false; return; } if(reply->elements % 2 != 0) { error = SSTR("Unexpected number of elements; expected a multiple of 2, received " << reply->elements); isOk = false; return; } for(size_t i = 0; i < reply->elements; i += 2) { StringParser parserKey(reply->element[i]); if(!parserKey.ok()) { error = SSTR("Unexpected reply type for element #" << i << ": " << parserKey.err()); isOk = false; return; } StringParser parserValue(reply->element[i+1]); if(!parserValue.ok()) { error = SSTR("Unexpected reply type for element #" << i+1 << ": " << parserValue.err()); isOk = false; return; } if(val.find(parserKey.value()) != val.end()) { error = SSTR("Found duplicate key: '" << parserKey.value() << "'"); isOk = false; return; } val.emplace(parserKey.value(), parserValue.value()); } isOk = true; } bool HgetallParser::ok() const { return isOk; } std::string HgetallParser::err() const { return error; } std::map HgetallParser::value() const { return val; } }