hiredis 0.5.2 → 0.6.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -8,12 +8,15 @@
8
8
  #include <unistd.h>
9
9
  #include <signal.h>
10
10
  #include <errno.h>
11
+ #include <limits.h>
11
12
 
12
13
  #include "hiredis.h"
14
+ #include "net.h"
13
15
 
14
16
  enum connection_type {
15
17
  CONN_TCP,
16
- CONN_UNIX
18
+ CONN_UNIX,
19
+ CONN_FD
17
20
  };
18
21
 
19
22
  struct config {
@@ -22,11 +25,12 @@ struct config {
22
25
  struct {
23
26
  const char *host;
24
27
  int port;
28
+ struct timeval timeout;
25
29
  } tcp;
26
30
 
27
31
  struct {
28
32
  const char *path;
29
- } unix;
33
+ } unix_sock;
30
34
  };
31
35
 
32
36
  /* The following lines make up our testing "framework" :) */
@@ -40,6 +44,13 @@ static long long usec(void) {
40
44
  return (((long long)tv.tv_sec)*1000000)+tv.tv_usec;
41
45
  }
42
46
 
47
+ /* The assert() calls below have side effects, so we need assert()
48
+ * even if we are compiling without asserts (-DNDEBUG). */
49
+ #ifdef NDEBUG
50
+ #undef assert
51
+ #define assert(e) (void)(e)
52
+ #endif
53
+
43
54
  static redisContext *select_database(redisContext *c) {
44
55
  redisReply *reply;
45
56
 
@@ -62,7 +73,7 @@ static redisContext *select_database(redisContext *c) {
62
73
  return c;
63
74
  }
64
75
 
65
- static void disconnect(redisContext *c) {
76
+ static int disconnect(redisContext *c, int keep_fd) {
66
77
  redisReply *reply;
67
78
 
68
79
  /* Make sure we're on DB 9. */
@@ -73,8 +84,11 @@ static void disconnect(redisContext *c) {
73
84
  assert(reply != NULL);
74
85
  freeReplyObject(reply);
75
86
 
76
- /* Free the context as well. */
87
+ /* Free the context as well, but keep the fd if requested. */
88
+ if (keep_fd)
89
+ return redisFreeKeepFd(c);
77
90
  redisFree(c);
91
+ return -1;
78
92
  }
79
93
 
80
94
  static redisContext *connect(struct config config) {
@@ -83,13 +97,25 @@ static redisContext *connect(struct config config) {
83
97
  if (config.type == CONN_TCP) {
84
98
  c = redisConnect(config.tcp.host, config.tcp.port);
85
99
  } else if (config.type == CONN_UNIX) {
86
- c = redisConnectUnix(config.unix.path);
100
+ c = redisConnectUnix(config.unix_sock.path);
101
+ } else if (config.type == CONN_FD) {
102
+ /* Create a dummy connection just to get an fd to inherit */
103
+ redisContext *dummy_ctx = redisConnectUnix(config.unix_sock.path);
104
+ if (dummy_ctx) {
105
+ int fd = disconnect(dummy_ctx, 1);
106
+ printf("Connecting to inherited fd %d\n", fd);
107
+ c = redisConnectFd(fd);
108
+ }
87
109
  } else {
88
110
  assert(NULL);
89
111
  }
90
112
 
91
- if (c->err) {
113
+ if (c == NULL) {
114
+ printf("Connection error: can't allocate redis context\n");
115
+ exit(1);
116
+ } else if (c->err) {
92
117
  printf("Connection error: %s\n", c->errstr);
118
+ redisFree(c);
93
119
  exit(1);
94
120
  }
95
121
 
@@ -125,13 +151,13 @@ static void test_format_commands(void) {
125
151
  free(cmd);
126
152
 
127
153
  test("Format command with %%b string interpolation: ");
128
- len = redisFormatCommand(&cmd,"SET %b %b","foo",3,"b\0r",3);
154
+ len = redisFormatCommand(&cmd,"SET %b %b","foo",(size_t)3,"b\0r",(size_t)3);
129
155
  test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\nb\0r\r\n",len) == 0 &&
130
156
  len == 4+4+(3+2)+4+(3+2)+4+(3+2));
131
157
  free(cmd);
132
158
 
133
159
  test("Format command with %%b and an empty string: ");
134
- len = redisFormatCommand(&cmd,"SET %b %b","foo",3,"",0);
160
+ len = redisFormatCommand(&cmd,"SET %b %b","foo",(size_t)3,"",(size_t)0);
135
161
  test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$0\r\n\r\n",len) == 0 &&
136
162
  len == 4+4+(3+2)+4+(3+2)+4+(0+2));
137
163
  free(cmd);
@@ -177,7 +203,7 @@ static void test_format_commands(void) {
177
203
  FLOAT_WIDTH_TEST(double);
178
204
 
179
205
  test("Format command with invalid printf format: ");
180
- len = redisFormatCommand(&cmd,"key:%08p %b",(void*)1234,"foo",3);
206
+ len = redisFormatCommand(&cmd,"key:%08p %b",(void*)1234,"foo",(size_t)3);
181
207
  test_cond(len == -1);
182
208
 
183
209
  const char *argv[3];
@@ -198,6 +224,44 @@ static void test_format_commands(void) {
198
224
  test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$7\r\nfoo\0xxx\r\n$3\r\nbar\r\n",len) == 0 &&
199
225
  len == 4+4+(3+2)+4+(7+2)+4+(3+2));
200
226
  free(cmd);
227
+
228
+ sds sds_cmd;
229
+
230
+ sds_cmd = sdsempty();
231
+ test("Format command into sds by passing argc/argv without lengths: ");
232
+ len = redisFormatSdsCommandArgv(&sds_cmd,argc,argv,NULL);
233
+ test_cond(strncmp(sds_cmd,"*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\nbar\r\n",len) == 0 &&
234
+ len == 4+4+(3+2)+4+(3+2)+4+(3+2));
235
+ sdsfree(sds_cmd);
236
+
237
+ sds_cmd = sdsempty();
238
+ test("Format command into sds by passing argc/argv with lengths: ");
239
+ len = redisFormatSdsCommandArgv(&sds_cmd,argc,argv,lens);
240
+ test_cond(strncmp(sds_cmd,"*3\r\n$3\r\nSET\r\n$7\r\nfoo\0xxx\r\n$3\r\nbar\r\n",len) == 0 &&
241
+ len == 4+4+(3+2)+4+(7+2)+4+(3+2));
242
+ sdsfree(sds_cmd);
243
+ }
244
+
245
+ static void test_append_formatted_commands(struct config config) {
246
+ redisContext *c;
247
+ redisReply *reply;
248
+ char *cmd;
249
+ int len;
250
+
251
+ c = connect(config);
252
+
253
+ test("Append format command: ");
254
+
255
+ len = redisFormatCommand(&cmd, "SET foo bar");
256
+
257
+ test_cond(redisAppendFormattedCommand(c, cmd, len) == REDIS_OK);
258
+
259
+ assert(redisGetReply(c, (void*)&reply) == REDIS_OK);
260
+
261
+ free(cmd);
262
+ freeReplyObject(reply);
263
+
264
+ disconnect(c, 0);
201
265
  }
202
266
 
203
267
  static void test_reply_reader(void) {
@@ -238,6 +302,82 @@ static void test_reply_reader(void) {
238
302
  strncasecmp(reader->errstr,"No support for",14) == 0);
239
303
  redisReaderFree(reader);
240
304
 
305
+ test("Correctly parses LLONG_MAX: ");
306
+ reader = redisReaderCreate();
307
+ redisReaderFeed(reader, ":9223372036854775807\r\n",22);
308
+ ret = redisReaderGetReply(reader,&reply);
309
+ test_cond(ret == REDIS_OK &&
310
+ ((redisReply*)reply)->type == REDIS_REPLY_INTEGER &&
311
+ ((redisReply*)reply)->integer == LLONG_MAX);
312
+ freeReplyObject(reply);
313
+ redisReaderFree(reader);
314
+
315
+ test("Set error when > LLONG_MAX: ");
316
+ reader = redisReaderCreate();
317
+ redisReaderFeed(reader, ":9223372036854775808\r\n",22);
318
+ ret = redisReaderGetReply(reader,&reply);
319
+ test_cond(ret == REDIS_ERR &&
320
+ strcasecmp(reader->errstr,"Bad integer value") == 0);
321
+ freeReplyObject(reply);
322
+ redisReaderFree(reader);
323
+
324
+ test("Correctly parses LLONG_MIN: ");
325
+ reader = redisReaderCreate();
326
+ redisReaderFeed(reader, ":-9223372036854775808\r\n",23);
327
+ ret = redisReaderGetReply(reader,&reply);
328
+ test_cond(ret == REDIS_OK &&
329
+ ((redisReply*)reply)->type == REDIS_REPLY_INTEGER &&
330
+ ((redisReply*)reply)->integer == LLONG_MIN);
331
+ freeReplyObject(reply);
332
+ redisReaderFree(reader);
333
+
334
+ test("Set error when < LLONG_MIN: ");
335
+ reader = redisReaderCreate();
336
+ redisReaderFeed(reader, ":-9223372036854775809\r\n",23);
337
+ ret = redisReaderGetReply(reader,&reply);
338
+ test_cond(ret == REDIS_ERR &&
339
+ strcasecmp(reader->errstr,"Bad integer value") == 0);
340
+ freeReplyObject(reply);
341
+ redisReaderFree(reader);
342
+
343
+ test("Set error when array < -1: ");
344
+ reader = redisReaderCreate();
345
+ redisReaderFeed(reader, "*-2\r\n+asdf\r\n",12);
346
+ ret = redisReaderGetReply(reader,&reply);
347
+ test_cond(ret == REDIS_ERR &&
348
+ strcasecmp(reader->errstr,"Multi-bulk length out of range") == 0);
349
+ freeReplyObject(reply);
350
+ redisReaderFree(reader);
351
+
352
+ test("Set error when bulk < -1: ");
353
+ reader = redisReaderCreate();
354
+ redisReaderFeed(reader, "$-2\r\nasdf\r\n",11);
355
+ ret = redisReaderGetReply(reader,&reply);
356
+ test_cond(ret == REDIS_ERR &&
357
+ strcasecmp(reader->errstr,"Bulk string length out of range") == 0);
358
+ freeReplyObject(reply);
359
+ redisReaderFree(reader);
360
+
361
+ test("Set error when array > INT_MAX: ");
362
+ reader = redisReaderCreate();
363
+ redisReaderFeed(reader, "*9223372036854775807\r\n+asdf\r\n",29);
364
+ ret = redisReaderGetReply(reader,&reply);
365
+ test_cond(ret == REDIS_ERR &&
366
+ strcasecmp(reader->errstr,"Multi-bulk length out of range") == 0);
367
+ freeReplyObject(reply);
368
+ redisReaderFree(reader);
369
+
370
+ #if LLONG_MAX > SIZE_MAX
371
+ test("Set error when bulk > SIZE_MAX: ");
372
+ reader = redisReaderCreate();
373
+ redisReaderFeed(reader, "$9223372036854775807\r\nasdf\r\n",28);
374
+ ret = redisReaderGetReply(reader,&reply);
375
+ test_cond(ret == REDIS_ERR &&
376
+ strcasecmp(reader->errstr,"Bulk string length out of range") == 0);
377
+ freeReplyObject(reply);
378
+ redisReaderFree(reader);
379
+ #endif
380
+
241
381
  test("Works with NULL functions for reply: ");
242
382
  reader = redisReaderCreate();
243
383
  reader->fn = NULL;
@@ -279,14 +419,32 @@ static void test_reply_reader(void) {
279
419
  redisReaderFree(reader);
280
420
  }
281
421
 
422
+ static void test_free_null(void) {
423
+ void *redisCtx = NULL;
424
+ void *reply = NULL;
425
+
426
+ test("Don't fail when redisFree is passed a NULL value: ");
427
+ redisFree(redisCtx);
428
+ test_cond(redisCtx == NULL);
429
+
430
+ test("Don't fail when freeReplyObject is passed a NULL value: ");
431
+ freeReplyObject(reply);
432
+ test_cond(reply == NULL);
433
+ }
434
+
282
435
  static void test_blocking_connection_errors(void) {
283
436
  redisContext *c;
284
437
 
285
438
  test("Returns error when host cannot be resolved: ");
286
- c = redisConnect((char*)"idontexist.local", 6379);
439
+ c = redisConnect((char*)"idontexist.test", 6379);
287
440
  test_cond(c->err == REDIS_ERR_OTHER &&
288
441
  (strcmp(c->errstr,"Name or service not known") == 0 ||
289
- strcmp(c->errstr,"Can't resolve: idontexist.local") == 0));
442
+ strcmp(c->errstr,"Can't resolve: idontexist.test") == 0 ||
443
+ strcmp(c->errstr,"nodename nor servname provided, or not known") == 0 ||
444
+ strcmp(c->errstr,"No address associated with hostname") == 0 ||
445
+ strcmp(c->errstr,"Temporary failure in name resolution") == 0 ||
446
+ strcmp(c->errstr,"hostname nor servname provided, or not known") == 0 ||
447
+ strcmp(c->errstr,"no address associated with name") == 0));
290
448
  redisFree(c);
291
449
 
292
450
  test("Returns error when the port is not open: ");
@@ -295,7 +453,7 @@ static void test_blocking_connection_errors(void) {
295
453
  strcmp(c->errstr,"Connection refused") == 0);
296
454
  redisFree(c);
297
455
 
298
- test("Returns error when the unix socket path doesn't accept connections: ");
456
+ test("Returns error when the unix_sock socket path doesn't accept connections: ");
299
457
  c = redisConnectUnix((char*)"/tmp/idontexist.sock");
300
458
  test_cond(c->err == REDIS_ERR_IO); /* Don't care about the message... */
301
459
  redisFree(c);
@@ -328,7 +486,7 @@ static void test_blocking_connection(struct config config) {
328
486
  freeReplyObject(reply);
329
487
 
330
488
  test("%%b String interpolation works: ");
331
- reply = redisCommand(c,"SET %b %b","foo",3,"hello\x00world",11);
489
+ reply = redisCommand(c,"SET %b %b","foo",(size_t)3,"hello\x00world",(size_t)11);
332
490
  freeReplyObject(reply);
333
491
  reply = redisCommand(c,"GET foo");
334
492
  test_cond(reply->type == REDIS_REPLY_STRING &&
@@ -376,7 +534,53 @@ static void test_blocking_connection(struct config config) {
376
534
  strcasecmp(reply->element[1]->str,"pong") == 0);
377
535
  freeReplyObject(reply);
378
536
 
379
- disconnect(c);
537
+ disconnect(c, 0);
538
+ }
539
+
540
+ static void test_blocking_connection_timeouts(struct config config) {
541
+ redisContext *c;
542
+ redisReply *reply;
543
+ ssize_t s;
544
+ const char *cmd = "DEBUG SLEEP 3\r\n";
545
+ struct timeval tv;
546
+
547
+ c = connect(config);
548
+ test("Successfully completes a command when the timeout is not exceeded: ");
549
+ reply = redisCommand(c,"SET foo fast");
550
+ freeReplyObject(reply);
551
+ tv.tv_sec = 0;
552
+ tv.tv_usec = 10000;
553
+ redisSetTimeout(c, tv);
554
+ reply = redisCommand(c, "GET foo");
555
+ test_cond(reply != NULL && reply->type == REDIS_REPLY_STRING && memcmp(reply->str, "fast", 4) == 0);
556
+ freeReplyObject(reply);
557
+ disconnect(c, 0);
558
+
559
+ c = connect(config);
560
+ test("Does not return a reply when the command times out: ");
561
+ s = write(c->fd, cmd, strlen(cmd));
562
+ tv.tv_sec = 0;
563
+ tv.tv_usec = 10000;
564
+ redisSetTimeout(c, tv);
565
+ reply = redisCommand(c, "GET foo");
566
+ test_cond(s > 0 && reply == NULL && c->err == REDIS_ERR_IO && strcmp(c->errstr, "Resource temporarily unavailable") == 0);
567
+ freeReplyObject(reply);
568
+
569
+ test("Reconnect properly reconnects after a timeout: ");
570
+ redisReconnect(c);
571
+ reply = redisCommand(c, "PING");
572
+ test_cond(reply != NULL && reply->type == REDIS_REPLY_STATUS && strcmp(reply->str, "PONG") == 0);
573
+ freeReplyObject(reply);
574
+
575
+ test("Reconnect properly uses owned parameters: ");
576
+ config.tcp.host = "foo";
577
+ config.unix_sock.path = "foo";
578
+ redisReconnect(c);
579
+ reply = redisCommand(c, "PING");
580
+ test_cond(reply != NULL && reply->type == REDIS_REPLY_STATUS && strcmp(reply->str, "PONG") == 0);
581
+ freeReplyObject(reply);
582
+
583
+ disconnect(c, 0);
380
584
  }
381
585
 
382
586
  static void test_blocking_io_errors(struct config config) {
@@ -402,7 +606,7 @@ static void test_blocking_io_errors(struct config config) {
402
606
 
403
607
  test("Returns I/O error when the connection is lost: ");
404
608
  reply = redisCommand(c,"QUIT");
405
- if (major >= 2 && minor > 0) {
609
+ if (major > 2 || (major == 2 && minor > 0)) {
406
610
  /* > 2.0 returns OK on QUIT and read() should be issued once more
407
611
  * to know the descriptor is at EOF. */
408
612
  test_cond(strcasecmp(reply->str,"OK") == 0 &&
@@ -430,6 +634,30 @@ static void test_blocking_io_errors(struct config config) {
430
634
  redisFree(c);
431
635
  }
432
636
 
637
+ static void test_invalid_timeout_errors(struct config config) {
638
+ redisContext *c;
639
+
640
+ test("Set error when an invalid timeout usec value is given to redisConnectWithTimeout: ");
641
+
642
+ config.tcp.timeout.tv_sec = 0;
643
+ config.tcp.timeout.tv_usec = 10000001;
644
+
645
+ c = redisConnectWithTimeout(config.tcp.host, config.tcp.port, config.tcp.timeout);
646
+
647
+ test_cond(c->err == REDIS_ERR_IO && strcmp(c->errstr, "Invalid timeout specified") == 0);
648
+ redisFree(c);
649
+
650
+ test("Set error when an invalid timeout sec value is given to redisConnectWithTimeout: ");
651
+
652
+ config.tcp.timeout.tv_sec = (((LONG_MAX) - 999) / 1000) + 1;
653
+ config.tcp.timeout.tv_usec = 0;
654
+
655
+ c = redisConnectWithTimeout(config.tcp.host, config.tcp.port, config.tcp.timeout);
656
+
657
+ test_cond(c->err == REDIS_ERR_IO && strcmp(c->errstr, "Invalid timeout specified") == 0);
658
+ redisFree(c);
659
+ }
660
+
433
661
  static void test_throughput(struct config config) {
434
662
  redisContext *c = connect(config);
435
663
  redisReply **replies;
@@ -464,6 +692,17 @@ static void test_throughput(struct config config) {
464
692
  free(replies);
465
693
  printf("\t(%dx LRANGE with 500 elements: %.3fs)\n", num, (t2-t1)/1000000.0);
466
694
 
695
+ replies = malloc(sizeof(redisReply*)*num);
696
+ t1 = usec();
697
+ for (i = 0; i < num; i++) {
698
+ replies[i] = redisCommand(c, "INCRBY incrkey %d", 1000000);
699
+ assert(replies[i] != NULL && replies[i]->type == REDIS_REPLY_INTEGER);
700
+ }
701
+ t2 = usec();
702
+ for (i = 0; i < num; i++) freeReplyObject(replies[i]);
703
+ free(replies);
704
+ printf("\t(%dx INCRBY: %.3fs)\n", num, (t2-t1)/1000000.0);
705
+
467
706
  num = 10000;
468
707
  replies = malloc(sizeof(redisReply*)*num);
469
708
  for (i = 0; i < num; i++)
@@ -492,7 +731,20 @@ static void test_throughput(struct config config) {
492
731
  free(replies);
493
732
  printf("\t(%dx LRANGE with 500 elements (pipelined): %.3fs)\n", num, (t2-t1)/1000000.0);
494
733
 
495
- disconnect(c);
734
+ replies = malloc(sizeof(redisReply*)*num);
735
+ for (i = 0; i < num; i++)
736
+ redisAppendCommand(c,"INCRBY incrkey %d", 1000000);
737
+ t1 = usec();
738
+ for (i = 0; i < num; i++) {
739
+ assert(redisGetReply(c, (void*)&replies[i]) == REDIS_OK);
740
+ assert(replies[i] != NULL && replies[i]->type == REDIS_REPLY_INTEGER);
741
+ }
742
+ t2 = usec();
743
+ for (i = 0; i < num; i++) freeReplyObject(replies[i]);
744
+ free(replies);
745
+ printf("\t(%dx INCRBY (pipelined): %.3fs)\n", num, (t2-t1)/1000000.0);
746
+
747
+ disconnect(c, 0);
496
748
  }
497
749
 
498
750
  // static long __test_callback_flags = 0;
@@ -600,11 +852,12 @@ int main(int argc, char **argv) {
600
852
  .host = "127.0.0.1",
601
853
  .port = 6379
602
854
  },
603
- .unix = {
855
+ .unix_sock = {
604
856
  .path = "/tmp/redis.sock"
605
857
  }
606
858
  };
607
859
  int throughput = 1;
860
+ int test_inherit_fd = 1;
608
861
 
609
862
  /* Ignore broken pipe signal (for I/O error tests). */
610
863
  signal(SIGPIPE, SIG_IGN);
@@ -620,9 +873,11 @@ int main(int argc, char **argv) {
620
873
  cfg.tcp.port = atoi(argv[0]);
621
874
  } else if (argc >= 2 && !strcmp(argv[0],"-s")) {
622
875
  argv++; argc--;
623
- cfg.unix.path = argv[0];
876
+ cfg.unix_sock.path = argv[0];
624
877
  } else if (argc >= 1 && !strcmp(argv[0],"--skip-throughput")) {
625
878
  throughput = 0;
879
+ } else if (argc >= 1 && !strcmp(argv[0],"--skip-inherit-fd")) {
880
+ test_inherit_fd = 0;
626
881
  } else {
627
882
  fprintf(stderr, "Invalid argument: %s\n", argv[0]);
628
883
  exit(1);
@@ -633,19 +888,31 @@ int main(int argc, char **argv) {
633
888
  test_format_commands();
634
889
  test_reply_reader();
635
890
  test_blocking_connection_errors();
891
+ test_free_null();
636
892
 
637
893
  printf("\nTesting against TCP connection (%s:%d):\n", cfg.tcp.host, cfg.tcp.port);
638
894
  cfg.type = CONN_TCP;
639
895
  test_blocking_connection(cfg);
896
+ test_blocking_connection_timeouts(cfg);
640
897
  test_blocking_io_errors(cfg);
898
+ test_invalid_timeout_errors(cfg);
899
+ test_append_formatted_commands(cfg);
641
900
  if (throughput) test_throughput(cfg);
642
901
 
643
- printf("\nTesting against Unix socket connection (%s):\n", cfg.unix.path);
902
+ printf("\nTesting against Unix socket connection (%s):\n", cfg.unix_sock.path);
644
903
  cfg.type = CONN_UNIX;
645
904
  test_blocking_connection(cfg);
905
+ test_blocking_connection_timeouts(cfg);
646
906
  test_blocking_io_errors(cfg);
647
907
  if (throughput) test_throughput(cfg);
648
908
 
909
+ if (test_inherit_fd) {
910
+ printf("\nTesting against inherited fd (%s):\n", cfg.unix_sock.path);
911
+ cfg.type = CONN_FD;
912
+ test_blocking_connection(cfg);
913
+ }
914
+
915
+
649
916
  if (fails) {
650
917
  printf("*** %d TESTS FAILED ***\n", fails);
651
918
  return 1;
@@ -0,0 +1,42 @@
1
+ #ifndef _WIN32_HELPER_INCLUDE
2
+ #define _WIN32_HELPER_INCLUDE
3
+ #ifdef _MSC_VER
4
+
5
+ #ifndef inline
6
+ #define inline __inline
7
+ #endif
8
+
9
+ #ifndef va_copy
10
+ #define va_copy(d,s) ((d) = (s))
11
+ #endif
12
+
13
+ #ifndef snprintf
14
+ #define snprintf c99_snprintf
15
+
16
+ __inline int c99_vsnprintf(char* str, size_t size, const char* format, va_list ap)
17
+ {
18
+ int count = -1;
19
+
20
+ if (size != 0)
21
+ count = _vsnprintf_s(str, size, _TRUNCATE, format, ap);
22
+ if (count == -1)
23
+ count = _vscprintf(format, ap);
24
+
25
+ return count;
26
+ }
27
+
28
+ __inline int c99_snprintf(char* str, size_t size, const char* format, ...)
29
+ {
30
+ int count;
31
+ va_list ap;
32
+
33
+ va_start(ap, format);
34
+ count = c99_vsnprintf(str, size, format, ap);
35
+ va_end(ap);
36
+
37
+ return count;
38
+ }
39
+ #endif
40
+
41
+ #endif
42
+ #endif
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hiredis
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.2
4
+ version: 0.6.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pieter Noordhuis
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-04-10 00:00:00.000000000 Z
11
+ date: 2018-11-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -28,16 +28,30 @@ dependencies:
28
28
  name: rake-compiler
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ~>
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
33
  version: 0.7.1
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ~>
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: 0.7.1
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 5.5.1
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 5.5.1
41
55
  description: Ruby wrapper for hiredis (protocol serialization/deserialization and
42
56
  blocking I/O)
43
57
  email:
@@ -47,38 +61,42 @@ extensions:
47
61
  - ext/hiredis_ext/extconf.rb
48
62
  extra_rdoc_files: []
49
63
  files:
50
- - ext/hiredis_ext/extconf.rb
64
+ - COPYING
65
+ - Rakefile
51
66
  - ext/hiredis_ext/connection.c
67
+ - ext/hiredis_ext/extconf.rb
52
68
  - ext/hiredis_ext/hiredis_ext.c
53
- - ext/hiredis_ext/reader.c
54
69
  - ext/hiredis_ext/hiredis_ext.h
55
- - vendor/hiredis/async.c
56
- - vendor/hiredis/dict.c
57
- - vendor/hiredis/hiredis.c
58
- - vendor/hiredis/net.c
59
- - vendor/hiredis/sds.c
60
- - vendor/hiredis/test.c
61
- - vendor/hiredis/async.h
62
- - vendor/hiredis/dict.h
63
- - vendor/hiredis/fmacros.h
64
- - vendor/hiredis/hiredis.h
65
- - vendor/hiredis/net.h
66
- - vendor/hiredis/sds.h
67
- - vendor/hiredis/COPYING
68
- - vendor/hiredis/Makefile
70
+ - ext/hiredis_ext/reader.c
71
+ - lib/hiredis.rb
69
72
  - lib/hiredis/connection.rb
70
- - lib/hiredis/errors.rb
71
73
  - lib/hiredis/ext/connection.rb
72
74
  - lib/hiredis/ext/reader.rb
73
75
  - lib/hiredis/reader.rb
74
76
  - lib/hiredis/ruby/connection.rb
75
77
  - lib/hiredis/ruby/reader.rb
76
78
  - lib/hiredis/version.rb
77
- - lib/hiredis.rb
78
- - COPYING
79
- - Rakefile
79
+ - vendor/hiredis/COPYING
80
+ - vendor/hiredis/Makefile
81
+ - vendor/hiredis/async.c
82
+ - vendor/hiredis/async.h
83
+ - vendor/hiredis/dict.c
84
+ - vendor/hiredis/dict.h
85
+ - vendor/hiredis/fmacros.h
86
+ - vendor/hiredis/hiredis.c
87
+ - vendor/hiredis/hiredis.h
88
+ - vendor/hiredis/net.c
89
+ - vendor/hiredis/net.h
90
+ - vendor/hiredis/read.c
91
+ - vendor/hiredis/read.h
92
+ - vendor/hiredis/sds.c
93
+ - vendor/hiredis/sds.h
94
+ - vendor/hiredis/sdsalloc.h
95
+ - vendor/hiredis/test.c
96
+ - vendor/hiredis/win32.h
80
97
  homepage: http://github.com/redis/hiredis-rb
81
- licenses: []
98
+ licenses:
99
+ - BSD-3-Clause
82
100
  metadata: {}
83
101
  post_install_message:
84
102
  rdoc_options: []
@@ -86,17 +104,17 @@ require_paths:
86
104
  - lib
87
105
  required_ruby_version: !ruby/object:Gem::Requirement
88
106
  requirements:
89
- - - '>='
107
+ - - ">="
90
108
  - !ruby/object:Gem::Version
91
109
  version: '0'
92
110
  required_rubygems_version: !ruby/object:Gem::Requirement
93
111
  requirements:
94
- - - '>='
112
+ - - ">="
95
113
  - !ruby/object:Gem::Version
96
114
  version: '0'
97
115
  requirements: []
98
116
  rubyforge_project:
99
- rubygems_version: 2.0.3
117
+ rubygems_version: 2.7.6
100
118
  signing_key:
101
119
  specification_version: 4
102
120
  summary: Ruby wrapper for hiredis (protocol serialization/deserialization and blocking
@@ -1,5 +0,0 @@
1
- module Hiredis
2
- class Error < StandardError; end
3
- class ProtocolError < Error; end
4
- class ReplyError < Error; end
5
- end