Commit 3b431e0e10c632ccd2aea1b82183531bea524ef1

Authored by Hayk Martirosyan
1 parent a2138a65

Add set and unordered_set reply type templates

Useful based on what kind of data you need.
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&lt;std::vector&lt;std::string&gt;&gt;::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&lt;nullptr_t&gt;() { 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
... ...