Commit 3b431e0e10c632ccd2aea1b82183531bea524ef1
1 parent
a2138a65
Add set and unordered_set reply type templates
Useful based on what kind of data you need.
Showing
4 changed files
with
112 additions
and
32 deletions
examples/data_types.cpp
| 1 | 1 | /** |
| 2 | -* Basic use of Redox to set and get a Redis key. | |
| 2 | +* Test special data type templates for multi-element replies using Redox. | |
| 3 | 3 | */ |
| 4 | 4 | |
| 5 | 5 | #include <iostream> |
| 6 | 6 | #include "../src/redox.hpp" |
| 7 | +#include <set> | |
| 8 | +#include <unordered_set> | |
| 9 | +#include <vector> | |
| 7 | 10 | |
| 8 | 11 | using namespace std; |
| 9 | 12 | |
| ... | ... | @@ -16,15 +19,40 @@ int main(int argc, char* argv[]) { |
| 16 | 19 | |
| 17 | 20 | rdx.command_blocking("LPUSH mylist 1 2 3 4 5 6 7 8 9 10"); |
| 18 | 21 | |
| 19 | - auto c = rdx.command_blocking<vector<string>>("LRANGE mylist -3 -1"); | |
| 20 | - if(!c->ok()) cerr << "Error with LRANGE: " << c->status() << endl; | |
| 21 | - for(const string& s : c->reply()) cout << s << endl; | |
| 22 | - c->free(); | |
| 23 | - | |
| 24 | -// if(!rdx.set("apples", "are great!")) // Set a key, check if succeeded | |
| 25 | -// cerr << "Failed to set key!" << endl; | |
| 26 | -// | |
| 27 | -// cout << "key = alaska, value = \"" << rdx.get("apples") << "\"" << endl; | |
| 28 | - | |
| 29 | - rdx.stop(); // Shut down the event loop | |
| 22 | + rdx.command<vector<string>>("LRANGE mylist 0 4", | |
| 23 | + [](const string& cmd, const vector<string>& reply){ | |
| 24 | + cout << "Last 5 elements as a vector: "; | |
| 25 | + for(const string& s : reply) cout << s << " "; | |
| 26 | + cout << endl; | |
| 27 | + }, | |
| 28 | + [](const string& cmd, int status) { | |
| 29 | + cerr << "Error with LRANGE: " << status << endl; | |
| 30 | + } | |
| 31 | + ); | |
| 32 | + | |
| 33 | + rdx.command<unordered_set<string>>("LRANGE mylist 0 4", | |
| 34 | + [](const string& cmd, const unordered_set<string>& reply){ | |
| 35 | + cout << "Last 5 elements as an unordered set: "; | |
| 36 | + for(const string& s : reply) cout << s << " "; | |
| 37 | + cout << endl; | |
| 38 | + }, | |
| 39 | + [](const string& cmd, int status) { | |
| 40 | + cerr << "Error with LRANGE: " << status << endl; | |
| 41 | + } | |
| 42 | + ); | |
| 43 | + | |
| 44 | + rdx.command<set<string>>("LRANGE mylist 0 4", | |
| 45 | + [&rdx](const string& cmd, const set<string>& reply){ | |
| 46 | + cout << "Last 5 elements as a set: "; | |
| 47 | + for(const string& s : reply) cout << s << " "; | |
| 48 | + cout << endl; | |
| 49 | + rdx.stop_signal(); | |
| 50 | + }, | |
| 51 | + [&rdx](const string& cmd, int status) { | |
| 52 | + cerr << "Error with LRANGE: " << status << endl; | |
| 53 | + rdx.stop_signal(); | |
| 54 | + } | |
| 55 | + ); | |
| 56 | + | |
| 57 | + rdx.block(); // Shut down the event loop | |
| 30 | 58 | } | ... | ... |
src/command.cpp
| ... | ... | @@ -3,7 +3,8 @@ |
| 3 | 3 | */ |
| 4 | 4 | |
| 5 | 5 | #include <vector> |
| 6 | -#include <assert.h> | |
| 6 | +#include <set> | |
| 7 | +#include <unordered_set> | |
| 7 | 8 | |
| 8 | 9 | #include "command.hpp" |
| 9 | 10 | |
| ... | ... | @@ -134,4 +135,52 @@ void Command<std::vector<std::string>>::invoke_callback() { |
| 134 | 135 | } |
| 135 | 136 | } |
| 136 | 137 | |
| 138 | +template<> | |
| 139 | +void Command<std::unordered_set<std::string>>::invoke_callback() { | |
| 140 | + | |
| 141 | + if(is_error_reply()) invoke_error(REDOX_ERROR_REPLY); | |
| 142 | + | |
| 143 | + else if(reply_obj->type != REDIS_REPLY_ARRAY) { | |
| 144 | + std::cerr << "[ERROR] " << cmd << ": Received non-array reply." << std::endl; | |
| 145 | + invoke_error(REDOX_WRONG_TYPE); | |
| 146 | + | |
| 147 | + } else { | |
| 148 | + std::unordered_set<std::string> v; | |
| 149 | + size_t count = reply_obj->elements; | |
| 150 | + for(size_t i = 0; i < count; i++) { | |
| 151 | + redisReply* r = *(reply_obj->element + i); | |
| 152 | + if(r->type != REDIS_REPLY_STRING) { | |
| 153 | + std::cerr << "[ERROR] " << cmd << ": Received non-array reply." << std::endl; | |
| 154 | + invoke_error(REDOX_WRONG_TYPE); | |
| 155 | + } | |
| 156 | + v.insert(r->str); | |
| 157 | + } | |
| 158 | + invoke(v); | |
| 159 | + } | |
| 160 | +} | |
| 161 | + | |
| 162 | +template<> | |
| 163 | +void Command<std::set<std::string>>::invoke_callback() { | |
| 164 | + | |
| 165 | + if(is_error_reply()) invoke_error(REDOX_ERROR_REPLY); | |
| 166 | + | |
| 167 | + else if(reply_obj->type != REDIS_REPLY_ARRAY) { | |
| 168 | + std::cerr << "[ERROR] " << cmd << ": Received non-array reply." << std::endl; | |
| 169 | + invoke_error(REDOX_WRONG_TYPE); | |
| 170 | + | |
| 171 | + } else { | |
| 172 | + std::set<std::string> v; | |
| 173 | + size_t count = reply_obj->elements; | |
| 174 | + for(size_t i = 0; i < count; i++) { | |
| 175 | + redisReply* r = *(reply_obj->element + i); | |
| 176 | + if(r->type != REDIS_REPLY_STRING) { | |
| 177 | + std::cerr << "[ERROR] " << cmd << ": Received non-array reply." << std::endl; | |
| 178 | + invoke_error(REDOX_WRONG_TYPE); | |
| 179 | + } | |
| 180 | + v.insert(r->str); | |
| 181 | + } | |
| 182 | + invoke(v); | |
| 183 | + } | |
| 184 | +} | |
| 185 | + | |
| 137 | 186 | } // End namespace redox | ... | ... |
src/redox.cpp
| ... | ... | @@ -308,42 +308,36 @@ void Redox::process_queued_commands(struct ev_loop* loop, ev_async* async, int r |
| 308 | 308 | rdx->command_queue.pop(); |
| 309 | 309 | |
| 310 | 310 | if(rdx->process_queued_command<redisReply*>(id)) {} |
| 311 | - else if(rdx->process_queued_command<string>(id)) {} | |
| 311 | + else if(rdx->process_queued_command<std::string>(id)) {} | |
| 312 | 312 | else if(rdx->process_queued_command<char*>(id)) {} |
| 313 | 313 | else if(rdx->process_queued_command<int>(id)) {} |
| 314 | 314 | else if(rdx->process_queued_command<long long int>(id)) {} |
| 315 | - else if(rdx->process_queued_command<nullptr_t>(id)) {} | |
| 316 | - else if(rdx->process_queued_command<vector<string>>(id)) {} | |
| 315 | + else if(rdx->process_queued_command<std::nullptr_t>(id)) {} | |
| 316 | + else if(rdx->process_queued_command<std::vector<std::string>>(id)) {} | |
| 317 | + else if(rdx->process_queued_command<std::set<std::string>>(id)) {} | |
| 318 | + else if(rdx->process_queued_command<std::unordered_set<std::string>>(id)) {} | |
| 317 | 319 | else throw runtime_error("[FATAL] Command pointer not found in any queue!"); |
| 318 | 320 | } |
| 319 | 321 | } |
| 320 | 322 | |
| 321 | -// ---------------------------- | |
| 323 | +// --------------------------------- | |
| 324 | +// get_command_map specializations | |
| 325 | +// --------------------------------- | |
| 322 | 326 | |
| 323 | 327 | template<> unordered_map<long, Command<redisReply*>*>& |
| 324 | -Redox::get_command_map<redisReply*>() { | |
| 325 | -// cout << "redis reply command map at " << &commands_redis_reply << endl; | |
| 326 | - return commands_redis_reply; } | |
| 328 | +Redox::get_command_map<redisReply*>() { return commands_redis_reply; } | |
| 327 | 329 | |
| 328 | 330 | template<> unordered_map<long, Command<string>*>& |
| 329 | -Redox::get_command_map<string>() { | |
| 330 | -// cout << "string command map at " << &commands_string_r << endl; | |
| 331 | - return commands_string_r; } | |
| 331 | +Redox::get_command_map<string>() { return commands_string_r; } | |
| 332 | 332 | |
| 333 | 333 | template<> unordered_map<long, Command<char*>*>& |
| 334 | -Redox::get_command_map<char*>() { | |
| 335 | -// cout << "char* command map at " << &commands_char_p << endl; | |
| 336 | - return commands_char_p; } | |
| 334 | +Redox::get_command_map<char*>() { return commands_char_p; } | |
| 337 | 335 | |
| 338 | 336 | template<> unordered_map<long, Command<int>*>& |
| 339 | -Redox::get_command_map<int>() { | |
| 340 | -// cout << "int command map at " << &commands_int << " has size: " << commands_int.size() << endl; | |
| 341 | - return commands_int; } | |
| 337 | +Redox::get_command_map<int>() { return commands_int; } | |
| 342 | 338 | |
| 343 | 339 | template<> unordered_map<long, Command<long long int>*>& |
| 344 | -Redox::get_command_map<long long int>() { | |
| 345 | -// cout << "long long int command map at " << &commands_long_long_int << endl; | |
| 346 | - return commands_long_long_int; } | |
| 340 | +Redox::get_command_map<long long int>() { return commands_long_long_int; } | |
| 347 | 341 | |
| 348 | 342 | template<> unordered_map<long, Command<nullptr_t>*>& |
| 349 | 343 | Redox::get_command_map<nullptr_t>() { return commands_null; } |
| ... | ... | @@ -351,6 +345,12 @@ Redox::get_command_map<nullptr_t>() { return commands_null; } |
| 351 | 345 | template<> unordered_map<long, Command<vector<string>>*>& |
| 352 | 346 | Redox::get_command_map<vector<string>>() { return commands_vector_string; } |
| 353 | 347 | |
| 348 | +template<> unordered_map<long, Command<set<string>>*>& | |
| 349 | +Redox::get_command_map<set<string>>() { return commands_set_string; } | |
| 350 | + | |
| 351 | +template<> unordered_map<long, Command<unordered_set<string>>*>& | |
| 352 | +Redox::get_command_map<unordered_set<string>>() { return commands_unordered_set_string; } | |
| 353 | + | |
| 354 | 354 | // ---------------------------- |
| 355 | 355 | // Helpers |
| 356 | 356 | // ---------------------------- | ... | ... |
src/redox.hpp
| ... | ... | @@ -14,6 +14,7 @@ |
| 14 | 14 | |
| 15 | 15 | #include <string> |
| 16 | 16 | #include <queue> |
| 17 | +#include <set> | |
| 17 | 18 | #include <unordered_map> |
| 18 | 19 | #include <unordered_set> |
| 19 | 20 | |
| ... | ... | @@ -235,6 +236,8 @@ private: |
| 235 | 236 | std::unordered_map<long, Command<long long int>*> commands_long_long_int; |
| 236 | 237 | std::unordered_map<long, Command<std::nullptr_t>*> commands_null; |
| 237 | 238 | std::unordered_map<long, Command<std::vector<std::string>>*> commands_vector_string; |
| 239 | + std::unordered_map<long, Command<std::set<std::string>>*> commands_set_string; | |
| 240 | + std::unordered_map<long, Command<std::unordered_set<std::string>>*> commands_unordered_set_string; | |
| 238 | 241 | std::mutex command_map_guard; // Guards access to all of the above |
| 239 | 242 | |
| 240 | 243 | // Return the correct map from the above, based on the template specialization | ... | ... |