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 #include <iostream> 5 #include <iostream>
6 #include "../src/redox.hpp" 6 #include "../src/redox.hpp"
  7 +#include <set>
  8 +#include <unordered_set>
  9 +#include <vector>
7 10
8 using namespace std; 11 using namespace std;
9 12
@@ -16,15 +19,40 @@ int main(int argc, char* argv[]) { @@ -16,15 +19,40 @@ int main(int argc, char* argv[]) {
16 19
17 rdx.command_blocking("LPUSH mylist 1 2 3 4 5 6 7 8 9 10"); 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,7 +3,8 @@
3 */ 3 */
4 4
5 #include <vector> 5 #include <vector>
6 -#include <assert.h> 6 +#include <set>
  7 +#include <unordered_set>
7 8
8 #include "command.hpp" 9 #include "command.hpp"
9 10
@@ -134,4 +135,52 @@ void Command&lt;std::vector&lt;std::string&gt;&gt;::invoke_callback() { @@ -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 } // End namespace redox 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,42 +308,36 @@ void Redox::process_queued_commands(struct ev_loop* loop, ev_async* async, int r
308 rdx->command_queue.pop(); 308 rdx->command_queue.pop();
309 309
310 if(rdx->process_queued_command<redisReply*>(id)) {} 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 else if(rdx->process_queued_command<char*>(id)) {} 312 else if(rdx->process_queued_command<char*>(id)) {}
313 else if(rdx->process_queued_command<int>(id)) {} 313 else if(rdx->process_queued_command<int>(id)) {}
314 else if(rdx->process_queued_command<long long int>(id)) {} 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 else throw runtime_error("[FATAL] Command pointer not found in any queue!"); 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 template<> unordered_map<long, Command<redisReply*>*>& 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 template<> unordered_map<long, Command<string>*>& 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 template<> unordered_map<long, Command<char*>*>& 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 template<> unordered_map<long, Command<int>*>& 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 template<> unordered_map<long, Command<long long int>*>& 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 template<> unordered_map<long, Command<nullptr_t>*>& 342 template<> unordered_map<long, Command<nullptr_t>*>&
349 Redox::get_command_map<nullptr_t>() { return commands_null; } 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,6 +345,12 @@ Redox::get_command_map&lt;nullptr_t&gt;() { return commands_null; }
351 template<> unordered_map<long, Command<vector<string>>*>& 345 template<> unordered_map<long, Command<vector<string>>*>&
352 Redox::get_command_map<vector<string>>() { return commands_vector_string; } 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 // Helpers 355 // Helpers
356 // ---------------------------- 356 // ----------------------------
src/redox.hpp
@@ -14,6 +14,7 @@ @@ -14,6 +14,7 @@
14 14
15 #include <string> 15 #include <string>
16 #include <queue> 16 #include <queue>
  17 +#include <set>
17 #include <unordered_map> 18 #include <unordered_map>
18 #include <unordered_set> 19 #include <unordered_set>
19 20
@@ -235,6 +236,8 @@ private: @@ -235,6 +236,8 @@ private:
235 std::unordered_map<long, Command<long long int>*> commands_long_long_int; 236 std::unordered_map<long, Command<long long int>*> commands_long_long_int;
236 std::unordered_map<long, Command<std::nullptr_t>*> commands_null; 237 std::unordered_map<long, Command<std::nullptr_t>*> commands_null;
237 std::unordered_map<long, Command<std::vector<std::string>>*> commands_vector_string; 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 std::mutex command_map_guard; // Guards access to all of the above 241 std::mutex command_map_guard; // Guards access to all of the above
239 242
240 // Return the correct map from the above, based on the template specialization 243 // Return the correct map from the above, based on the template specialization