durable_rules 0.33.13 → 0.34.01

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,116 @@
1
+ /*
2
+ * Copyright (c) 2009-2011, Salvatore Sanfilippo <antirez at gmail dot com>
3
+ * Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>
4
+ *
5
+ * All rights reserved.
6
+ *
7
+ * Redistribution and use in source and binary forms, with or without
8
+ * modification, are permitted provided that the following conditions are met:
9
+ *
10
+ * * Redistributions of source code must retain the above copyright notice,
11
+ * this list of conditions and the following disclaimer.
12
+ * * Redistributions in binary form must reproduce the above copyright
13
+ * notice, this list of conditions and the following disclaimer in the
14
+ * documentation and/or other materials provided with the distribution.
15
+ * * Neither the name of Redis nor the names of its contributors may be used
16
+ * to endorse or promote products derived from this software without
17
+ * specific prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29
+ * POSSIBILITY OF SUCH DAMAGE.
30
+ */
31
+
32
+
33
+ #ifndef __HIREDIS_READ_H
34
+ #define __HIREDIS_READ_H
35
+ #include <stdio.h> /* for size_t */
36
+
37
+ #define REDIS_ERR -1
38
+ #define REDIS_OK 0
39
+
40
+ /* When an error occurs, the err flag in a context is set to hold the type of
41
+ * error that occured. REDIS_ERR_IO means there was an I/O error and you
42
+ * should use the "errno" variable to find out what is wrong.
43
+ * For other values, the "errstr" field will hold a description. */
44
+ #define REDIS_ERR_IO 1 /* Error in read or write */
45
+ #define REDIS_ERR_EOF 3 /* End of file */
46
+ #define REDIS_ERR_PROTOCOL 4 /* Protocol error */
47
+ #define REDIS_ERR_OOM 5 /* Out of memory */
48
+ #define REDIS_ERR_OTHER 2 /* Everything else... */
49
+
50
+ #define REDIS_REPLY_STRING 1
51
+ #define REDIS_REPLY_ARRAY 2
52
+ #define REDIS_REPLY_INTEGER 3
53
+ #define REDIS_REPLY_NIL 4
54
+ #define REDIS_REPLY_STATUS 5
55
+ #define REDIS_REPLY_ERROR 6
56
+
57
+ #define REDIS_READER_MAX_BUF (1024*16) /* Default max unused reader buffer. */
58
+
59
+ #ifdef __cplusplus
60
+ extern "C" {
61
+ #endif
62
+
63
+ typedef struct redisReadTask {
64
+ int type;
65
+ int elements; /* number of elements in multibulk container */
66
+ int idx; /* index in parent (array) object */
67
+ void *obj; /* holds user-generated value for a read task */
68
+ struct redisReadTask *parent; /* parent task */
69
+ void *privdata; /* user-settable arbitrary field */
70
+ } redisReadTask;
71
+
72
+ typedef struct redisReplyObjectFunctions {
73
+ void *(*createString)(const redisReadTask*, char*, size_t);
74
+ void *(*createArray)(const redisReadTask*, int);
75
+ void *(*createInteger)(const redisReadTask*, long long);
76
+ void *(*createNil)(const redisReadTask*);
77
+ void (*freeObject)(void*);
78
+ } redisReplyObjectFunctions;
79
+
80
+ typedef struct redisReader {
81
+ int err; /* Error flags, 0 when there is no error */
82
+ char errstr[128]; /* String representation of error when applicable */
83
+
84
+ char *buf; /* Read buffer */
85
+ size_t pos; /* Buffer cursor */
86
+ size_t len; /* Buffer length */
87
+ size_t maxbuf; /* Max length of unused buffer */
88
+
89
+ redisReadTask rstack[9];
90
+ int ridx; /* Index of current read task */
91
+ void *reply; /* Temporary reply pointer */
92
+
93
+ redisReplyObjectFunctions *fn;
94
+ void *privdata;
95
+ } redisReader;
96
+
97
+ /* Public API for the protocol parser. */
98
+ redisReader *redisReaderCreateWithFunctions(redisReplyObjectFunctions *fn);
99
+ void redisReaderFree(redisReader *r);
100
+ int redisReaderFeed(redisReader *r, const char *buf, size_t len);
101
+ int redisReaderGetReply(redisReader *r, void **reply);
102
+
103
+ /* Backwards compatibility, can be removed on big version bump. */
104
+ #define redisReplyReaderCreate redisReaderCreate
105
+ #define redisReplyReaderFree redisReaderFree
106
+ #define redisReplyReaderFeed redisReaderFeed
107
+ #define redisReplyReaderGetReply redisReaderGetReply
108
+ #define redisReplyReaderSetPrivdata(_r, _p) (int)(((redisReader*)(_r))->privdata = (_p))
109
+ #define redisReplyReaderGetObject(_r) (((redisReader*)(_r))->reply)
110
+ #define redisReplyReaderGetError(_r) (((redisReader*)(_r))->errstr)
111
+
112
+ #ifdef __cplusplus
113
+ }
114
+ #endif
115
+
116
+ #endif
data/deps/hiredis/sds.c CHANGED
@@ -1,6 +1,6 @@
1
- /* SDSLib, A C dynamic strings library
1
+ /* SDS (Simple Dynamic Strings), A C dynamic strings library.
2
2
  *
3
- * Copyright (c) 2006-2012, Salvatore Sanfilippo <antirez at gmail dot com>
3
+ * Copyright (c) 2006-2014, Salvatore Sanfilippo <antirez at gmail dot com>
4
4
  * All rights reserved.
5
5
  *
6
6
  * Redistribution and use in source and binary forms, with or without
@@ -33,8 +33,8 @@
33
33
  #include <string.h>
34
34
  #include <ctype.h>
35
35
  #include <assert.h>
36
+
36
37
  #include "sds.h"
37
- #include "zmalloc.h"
38
38
 
39
39
  /* Create a new sds string with the content specified by the 'init' pointer
40
40
  * and 'initlen'.
@@ -52,9 +52,9 @@ sds sdsnewlen(const void *init, size_t initlen) {
52
52
  struct sdshdr *sh;
53
53
 
54
54
  if (init) {
55
- sh = zmalloc(sizeof(struct sdshdr)+initlen+1);
55
+ sh = malloc(sizeof *sh+initlen+1);
56
56
  } else {
57
- sh = zcalloc(sizeof(struct sdshdr)+initlen+1);
57
+ sh = calloc(sizeof *sh+initlen+1,1);
58
58
  }
59
59
  if (sh == NULL) return NULL;
60
60
  sh->len = initlen;
@@ -85,7 +85,7 @@ sds sdsdup(const sds s) {
85
85
  /* Free an sds string. No operation is performed if 's' is NULL. */
86
86
  void sdsfree(sds s) {
87
87
  if (s == NULL) return;
88
- zfree(s-sizeof(struct sdshdr));
88
+ free(s-sizeof(struct sdshdr));
89
89
  }
90
90
 
91
91
  /* Set the sds string length to the length as obtained with strlen(), so
@@ -103,7 +103,7 @@ void sdsfree(sds s) {
103
103
  * the output will be "6" as the string was modified but the logical length
104
104
  * remains 6 bytes. */
105
105
  void sdsupdatelen(sds s) {
106
- struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));
106
+ struct sdshdr *sh = (void*) (s-sizeof *sh);
107
107
  int reallen = strlen(s);
108
108
  sh->free += (sh->len-reallen);
109
109
  sh->len = reallen;
@@ -114,7 +114,7 @@ void sdsupdatelen(sds s) {
114
114
  * so that next append operations will not require allocations up to the
115
115
  * number of bytes previously available. */
116
116
  void sdsclear(sds s) {
117
- struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));
117
+ struct sdshdr *sh = (void*) (s-sizeof *sh);
118
118
  sh->free += sh->len;
119
119
  sh->len = 0;
120
120
  sh->buf[0] = '\0';
@@ -123,7 +123,7 @@ void sdsclear(sds s) {
123
123
  /* Enlarge the free space at the end of the sds string so that the caller
124
124
  * is sure that after calling this function can overwrite up to addlen
125
125
  * bytes after the end of the string, plus one more byte for nul term.
126
- *
126
+ *
127
127
  * Note: this does not change the *length* of the sds string as returned
128
128
  * by sdslen(), but only the free buffer space we have. */
129
129
  sds sdsMakeRoomFor(sds s, size_t addlen) {
@@ -133,13 +133,13 @@ sds sdsMakeRoomFor(sds s, size_t addlen) {
133
133
 
134
134
  if (free >= addlen) return s;
135
135
  len = sdslen(s);
136
- sh = (void*) (s-(sizeof(struct sdshdr)));
136
+ sh = (void*) (s-sizeof *sh);
137
137
  newlen = (len+addlen);
138
138
  if (newlen < SDS_MAX_PREALLOC)
139
139
  newlen *= 2;
140
140
  else
141
141
  newlen += SDS_MAX_PREALLOC;
142
- newsh = zrealloc(sh, sizeof(struct sdshdr)+newlen+1);
142
+ newsh = realloc(sh, sizeof *newsh+newlen+1);
143
143
  if (newsh == NULL) return NULL;
144
144
 
145
145
  newsh->free = newlen - len;
@@ -155,8 +155,8 @@ sds sdsMakeRoomFor(sds s, size_t addlen) {
155
155
  sds sdsRemoveFreeSpace(sds s) {
156
156
  struct sdshdr *sh;
157
157
 
158
- sh = (void*) (s-(sizeof(struct sdshdr)));
159
- sh = zrealloc(sh, sizeof(struct sdshdr)+sh->len+1);
158
+ sh = (void*) (s-sizeof *sh);
159
+ sh = realloc(sh, sizeof *sh+sh->len+1);
160
160
  sh->free = 0;
161
161
  return sh->buf;
162
162
  }
@@ -169,7 +169,7 @@ sds sdsRemoveFreeSpace(sds s) {
169
169
  * 4) The implicit null term.
170
170
  */
171
171
  size_t sdsAllocSize(sds s) {
172
- struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));
172
+ struct sdshdr *sh = (void*) (s-sizeof *sh);
173
173
 
174
174
  return sizeof(*sh)+sh->len+sh->free+1;
175
175
  }
@@ -198,7 +198,7 @@ size_t sdsAllocSize(sds s) {
198
198
  * sdsIncrLen(s, nread);
199
199
  */
200
200
  void sdsIncrLen(sds s, int incr) {
201
- struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));
201
+ struct sdshdr *sh = (void*) (s-sizeof *sh);
202
202
 
203
203
  assert(sh->free >= incr);
204
204
  sh->len += incr;
@@ -213,7 +213,7 @@ void sdsIncrLen(sds s, int incr) {
213
213
  * if the specified length is smaller than the current length, no operation
214
214
  * is performed. */
215
215
  sds sdsgrowzero(sds s, size_t len) {
216
- struct sdshdr *sh = (void*)(s-(sizeof(struct sdshdr)));
216
+ struct sdshdr *sh = (void*) (s-sizeof *sh);
217
217
  size_t totlen, curlen = sh->len;
218
218
 
219
219
  if (len <= curlen) return s;
@@ -221,7 +221,7 @@ sds sdsgrowzero(sds s, size_t len) {
221
221
  if (s == NULL) return NULL;
222
222
 
223
223
  /* Make sure added region doesn't contain garbage */
224
- sh = (void*)(s-(sizeof(struct sdshdr)));
224
+ sh = (void*)(s-sizeof *sh);
225
225
  memset(s+curlen,0,(len-curlen+1)); /* also set trailing \0 byte */
226
226
  totlen = sh->len+sh->free;
227
227
  sh->len = len;
@@ -240,7 +240,7 @@ sds sdscatlen(sds s, const void *t, size_t len) {
240
240
 
241
241
  s = sdsMakeRoomFor(s,len);
242
242
  if (s == NULL) return NULL;
243
- sh = (void*) (s-(sizeof(struct sdshdr)));
243
+ sh = (void*) (s-sizeof *sh);
244
244
  memcpy(s+curlen, t, len);
245
245
  sh->len = curlen+len;
246
246
  sh->free = sh->free-len;
@@ -267,13 +267,13 @@ sds sdscatsds(sds s, const sds t) {
267
267
  /* Destructively modify the sds string 's' to hold the specified binary
268
268
  * safe string pointed by 't' of length 'len' bytes. */
269
269
  sds sdscpylen(sds s, const char *t, size_t len) {
270
- struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));
270
+ struct sdshdr *sh = (void*) (s-sizeof *sh);
271
271
  size_t totlen = sh->free+sh->len;
272
272
 
273
273
  if (totlen < len) {
274
274
  s = sdsMakeRoomFor(s,len-sh->len);
275
275
  if (s == NULL) return NULL;
276
- sh = (void*) (s-(sizeof(struct sdshdr)));
276
+ sh = (void*) (s-sizeof *sh);
277
277
  totlen = sh->free+sh->len;
278
278
  }
279
279
  memcpy(s, t, len);
@@ -289,6 +289,73 @@ sds sdscpy(sds s, const char *t) {
289
289
  return sdscpylen(s, t, strlen(t));
290
290
  }
291
291
 
292
+ /* Helper for sdscatlonglong() doing the actual number -> string
293
+ * conversion. 's' must point to a string with room for at least
294
+ * SDS_LLSTR_SIZE bytes.
295
+ *
296
+ * The function returns the lenght of the null-terminated string
297
+ * representation stored at 's'. */
298
+ #define SDS_LLSTR_SIZE 21
299
+ int sdsll2str(char *s, long long value) {
300
+ char *p, aux;
301
+ unsigned long long v;
302
+ size_t l;
303
+
304
+ /* Generate the string representation, this method produces
305
+ * an reversed string. */
306
+ v = (value < 0) ? -value : value;
307
+ p = s;
308
+ do {
309
+ *p++ = '0'+(v%10);
310
+ v /= 10;
311
+ } while(v);
312
+ if (value < 0) *p++ = '-';
313
+
314
+ /* Compute length and add null term. */
315
+ l = p-s;
316
+ *p = '\0';
317
+
318
+ /* Reverse the string. */
319
+ p--;
320
+ while(s < p) {
321
+ aux = *s;
322
+ *s = *p;
323
+ *p = aux;
324
+ s++;
325
+ p--;
326
+ }
327
+ return l;
328
+ }
329
+
330
+ /* Identical sdsll2str(), but for unsigned long long type. */
331
+ int sdsull2str(char *s, unsigned long long v) {
332
+ char *p, aux;
333
+ size_t l;
334
+
335
+ /* Generate the string representation, this method produces
336
+ * an reversed string. */
337
+ p = s;
338
+ do {
339
+ *p++ = '0'+(v%10);
340
+ v /= 10;
341
+ } while(v);
342
+
343
+ /* Compute length and add null term. */
344
+ l = p-s;
345
+ *p = '\0';
346
+
347
+ /* Reverse the string. */
348
+ p--;
349
+ while(s < p) {
350
+ aux = *s;
351
+ *s = *p;
352
+ *p = aux;
353
+ s++;
354
+ p--;
355
+ }
356
+ return l;
357
+ }
358
+
292
359
  /* Like sdscatpritf() but gets va_list instead of being variadic. */
293
360
  sds sdscatvprintf(sds s, const char *fmt, va_list ap) {
294
361
  va_list cpy;
@@ -296,20 +363,20 @@ sds sdscatvprintf(sds s, const char *fmt, va_list ap) {
296
363
  size_t buflen = 16;
297
364
 
298
365
  while(1) {
299
- buf = zmalloc(buflen);
366
+ buf = malloc(buflen);
300
367
  if (buf == NULL) return NULL;
301
368
  buf[buflen-2] = '\0';
302
369
  va_copy(cpy,ap);
303
370
  vsnprintf(buf, buflen, fmt, cpy);
304
371
  if (buf[buflen-2] != '\0') {
305
- zfree(buf);
372
+ free(buf);
306
373
  buflen *= 2;
307
374
  continue;
308
375
  }
309
376
  break;
310
377
  }
311
378
  t = sdscat(s, buf);
312
- zfree(buf);
379
+ free(buf);
313
380
  return t;
314
381
  }
315
382
 
@@ -321,8 +388,8 @@ sds sdscatvprintf(sds s, const char *fmt, va_list ap) {
321
388
  *
322
389
  * Example:
323
390
  *
324
- * s = sdsempty("Sum is: ");
325
- * s = sdscatprintf(s,"%d+%d = %d",a,b,a+b).
391
+ * s = sdsnew("Sum is: ");
392
+ * s = sdscatprintf(s,"%d+%d = %d",a,b,a+b);
326
393
  *
327
394
  * Often you need to create a string from scratch with the printf-alike
328
395
  * format. When this is the need, just use sdsempty() as the target string:
@@ -338,6 +405,127 @@ sds sdscatprintf(sds s, const char *fmt, ...) {
338
405
  return t;
339
406
  }
340
407
 
408
+ /* This function is similar to sdscatprintf, but much faster as it does
409
+ * not rely on sprintf() family functions implemented by the libc that
410
+ * are often very slow. Moreover directly handling the sds string as
411
+ * new data is concatenated provides a performance improvement.
412
+ *
413
+ * However this function only handles an incompatible subset of printf-alike
414
+ * format specifiers:
415
+ *
416
+ * %s - C String
417
+ * %S - SDS string
418
+ * %i - signed int
419
+ * %I - 64 bit signed integer (long long, int64_t)
420
+ * %u - unsigned int
421
+ * %U - 64 bit unsigned integer (unsigned long long, uint64_t)
422
+ * %T - A size_t variable.
423
+ * %% - Verbatim "%" character.
424
+ */
425
+ sds sdscatfmt(sds s, char const *fmt, ...) {
426
+ struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));
427
+ size_t initlen = sdslen(s);
428
+ const char *f = fmt;
429
+ int i;
430
+ va_list ap;
431
+
432
+ va_start(ap,fmt);
433
+ f = fmt; /* Next format specifier byte to process. */
434
+ i = initlen; /* Position of the next byte to write to dest str. */
435
+ while(*f) {
436
+ char next, *str;
437
+ int l;
438
+ long long num;
439
+ unsigned long long unum;
440
+
441
+ /* Make sure there is always space for at least 1 char. */
442
+ if (sh->free == 0) {
443
+ s = sdsMakeRoomFor(s,1);
444
+ sh = (void*) (s-(sizeof(struct sdshdr)));
445
+ }
446
+
447
+ switch(*f) {
448
+ case '%':
449
+ next = *(f+1);
450
+ f++;
451
+ switch(next) {
452
+ case 's':
453
+ case 'S':
454
+ str = va_arg(ap,char*);
455
+ l = (next == 's') ? strlen(str) : sdslen(str);
456
+ if (sh->free < l) {
457
+ s = sdsMakeRoomFor(s,l);
458
+ sh = (void*) (s-(sizeof(struct sdshdr)));
459
+ }
460
+ memcpy(s+i,str,l);
461
+ sh->len += l;
462
+ sh->free -= l;
463
+ i += l;
464
+ break;
465
+ case 'i':
466
+ case 'I':
467
+ if (next == 'i')
468
+ num = va_arg(ap,int);
469
+ else
470
+ num = va_arg(ap,long long);
471
+ {
472
+ char buf[SDS_LLSTR_SIZE];
473
+ l = sdsll2str(buf,num);
474
+ if (sh->free < l) {
475
+ s = sdsMakeRoomFor(s,l);
476
+ sh = (void*) (s-(sizeof(struct sdshdr)));
477
+ }
478
+ memcpy(s+i,buf,l);
479
+ sh->len += l;
480
+ sh->free -= l;
481
+ i += l;
482
+ }
483
+ break;
484
+ case 'u':
485
+ case 'U':
486
+ case 'T':
487
+ if (next == 'u')
488
+ unum = va_arg(ap,unsigned int);
489
+ else if(next == 'U')
490
+ unum = va_arg(ap,unsigned long long);
491
+ else
492
+ unum = (unsigned long long)va_arg(ap,size_t);
493
+ {
494
+ char buf[SDS_LLSTR_SIZE];
495
+ l = sdsull2str(buf,unum);
496
+ if (sh->free < l) {
497
+ s = sdsMakeRoomFor(s,l);
498
+ sh = (void*) (s-(sizeof(struct sdshdr)));
499
+ }
500
+ memcpy(s+i,buf,l);
501
+ sh->len += l;
502
+ sh->free -= l;
503
+ i += l;
504
+ }
505
+ break;
506
+ default: /* Handle %% and generally %<unknown>. */
507
+ s[i++] = next;
508
+ sh->len += 1;
509
+ sh->free -= 1;
510
+ break;
511
+ }
512
+ break;
513
+ default:
514
+ s[i++] = *f;
515
+ sh->len += 1;
516
+ sh->free -= 1;
517
+ break;
518
+ }
519
+ f++;
520
+ }
521
+ va_end(ap);
522
+
523
+ /* Add null-term */
524
+ s[i] = '\0';
525
+ return s;
526
+ }
527
+
528
+
341
529
  /* Remove the part of the string from left and from right composed just of
342
530
  * contiguous characters found in 'cset', that is a null terminted C string.
343
531
  *
@@ -352,8 +540,8 @@ sds sdscatprintf(sds s, const char *fmt, ...) {
352
540
  *
353
541
  * Output will be just "Hello World".
354
542
  */
355
- sds sdstrim(sds s, const char *cset) {
356
- struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));
543
+ void sdstrim(sds s, const char *cset) {
544
+ struct sdshdr *sh = (void*) (s-sizeof *sh);
357
545
  char *start, *end, *sp, *ep;
358
546
  size_t len;
359
547
 
@@ -366,7 +554,6 @@ sds sdstrim(sds s, const char *cset) {
366
554
  sh->buf[len] = '\0';
367
555
  sh->free = sh->free+(sh->len-len);
368
556
  sh->len = len;
369
- return s;
370
557
  }
371
558
 
372
559
  /* Turn the string into a smaller (or equal) string containing only the
@@ -383,10 +570,10 @@ sds sdstrim(sds s, const char *cset) {
383
570
  * Example:
384
571
  *
385
572
  * s = sdsnew("Hello World");
386
- * sdstrim(s,1,-1); => "ello Worl"
573
+ * sdsrange(s,1,-1); => "ello World"
387
574
  */
388
575
  void sdsrange(sds s, int start, int end) {
389
- struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));
576
+ struct sdshdr *sh = (void*) (s-sizeof *sh);
390
577
  size_t newlen, len = sdslen(s);
391
578
 
392
579
  if (len == 0) return;
@@ -474,7 +661,7 @@ sds *sdssplitlen(const char *s, int len, const char *sep, int seplen, int *count
474
661
 
475
662
  if (seplen < 1 || len < 0) return NULL;
476
663
 
477
- tokens = zmalloc(sizeof(sds)*slots);
664
+ tokens = malloc(sizeof(sds)*slots);
478
665
  if (tokens == NULL) return NULL;
479
666
 
480
667
  if (len == 0) {
@@ -487,7 +674,7 @@ sds *sdssplitlen(const char *s, int len, const char *sep, int seplen, int *count
487
674
  sds *newtokens;
488
675
 
489
676
  slots *= 2;
490
- newtokens = zrealloc(tokens,sizeof(sds)*slots);
677
+ newtokens = realloc(tokens,sizeof(sds)*slots);
491
678
  if (newtokens == NULL) goto cleanup;
492
679
  tokens = newtokens;
493
680
  }
@@ -511,7 +698,7 @@ cleanup:
511
698
  {
512
699
  int i;
513
700
  for (i = 0; i < elements; i++) sdsfree(tokens[i]);
514
- zfree(tokens);
701
+ free(tokens);
515
702
  *count = 0;
516
703
  return NULL;
517
704
  }
@@ -522,7 +709,7 @@ void sdsfreesplitres(sds *tokens, int count) {
522
709
  if (!tokens) return;
523
710
  while(count--)
524
711
  sdsfree(tokens[count]);
525
- zfree(tokens);
712
+ free(tokens);
526
713
  }
527
714
 
528
715
  /* Create an sds string from a long long value. It is much faster than:
@@ -582,7 +769,7 @@ int is_hex_digit(char c) {
582
769
  (c >= 'A' && c <= 'F');
583
770
  }
584
771
 
585
- /* Helper function for sdssplitargs() that converts an hex digit into an
772
+ /* Helper function for sdssplitargs() that converts a hex digit into an
586
773
  * integer from 0 to 15 */
587
774
  int hex_digit_to_int(char c) {
588
775
  switch(c) {
@@ -715,13 +902,13 @@ sds *sdssplitargs(const char *line, int *argc) {
715
902
  if (*p) p++;
716
903
  }
717
904
  /* add the token to the vector */
718
- vector = zrealloc(vector,((*argc)+1)*sizeof(char*));
905
+ vector = realloc(vector,((*argc)+1)*sizeof(char*));
719
906
  vector[*argc] = current;
720
907
  (*argc)++;
721
908
  current = NULL;
722
909
  } else {
723
910
  /* Even on empty input string return something not NULL. */
724
- if (vector == NULL) vector = zmalloc(sizeof(void*));
911
+ if (vector == NULL) vector = malloc(sizeof(void*));
725
912
  return vector;
726
913
  }
727
914
  }
@@ -729,7 +916,7 @@ sds *sdssplitargs(const char *line, int *argc) {
729
916
  err:
730
917
  while((*argc)--)
731
918
  sdsfree(vector[*argc]);
732
- zfree(vector);
919
+ free(vector);
733
920
  if (current) sdsfree(current);
734
921
  *argc = 0;
735
922
  return NULL;
@@ -760,13 +947,25 @@ sds sdsmapchars(sds s, const char *from, const char *to, size_t setlen) {
760
947
 
761
948
  /* Join an array of C strings using the specified separator (also a C string).
762
949
  * Returns the result as an sds string. */
763
- sds sdsjoin(char **argv, int argc, char *sep) {
950
+ sds sdsjoin(char **argv, int argc, char *sep, size_t seplen) {
764
951
  sds join = sdsempty();
765
952
  int j;
766
953
 
767
954
  for (j = 0; j < argc; j++) {
768
955
  join = sdscat(join, argv[j]);
769
- if (j != argc-1) join = sdscat(join,sep);
956
+ if (j != argc-1) join = sdscatlen(join,sep,seplen);
957
+ }
958
+ return join;
959
+ }
960
+
961
+ /* Like sdsjoin, but joins an array of SDS strings. */
962
+ sds sdsjoinsds(sds *argv, int argc, const char *sep, size_t seplen) {
963
+ sds join = sdsempty();
964
+ int j;
965
+
966
+ for (j = 0; j < argc; j++) {
967
+ join = sdscatsds(join, argv[j]);
968
+ if (j != argc-1) join = sdscatlen(join,sep,seplen);
770
969
  }
771
970
  return join;
772
971
  }
@@ -807,36 +1006,43 @@ int main(void) {
807
1006
  sdslen(x) == 3 && memcmp(x,"123\0",4) ==0)
808
1007
 
809
1008
  sdsfree(x);
810
- x = sdstrim(sdsnew("xxciaoyyy"),"xy");
1009
+ x = sdsnew("xxciaoyyy");
1010
+ sdstrim(x,"xy");
811
1011
  test_cond("sdstrim() correctly trims characters",
812
1012
  sdslen(x) == 4 && memcmp(x,"ciao\0",5) == 0)
813
1013
 
814
- y = sdsrange(sdsdup(x),1,1);
1014
+ y = sdsdup(x);
1015
+ sdsrange(y,1,1);
815
1016
  test_cond("sdsrange(...,1,1)",
816
1017
  sdslen(y) == 1 && memcmp(y,"i\0",2) == 0)
817
1018
 
818
1019
  sdsfree(y);
819
- y = sdsrange(sdsdup(x),1,-1);
1020
+ y = sdsdup(x);
1021
+ sdsrange(y,1,-1);
820
1022
  test_cond("sdsrange(...,1,-1)",
821
1023
  sdslen(y) == 3 && memcmp(y,"iao\0",4) == 0)
822
1024
 
823
1025
  sdsfree(y);
824
- y = sdsrange(sdsdup(x),-2,-1);
1026
+ y = sdsdup(x);
1027
+ sdsrange(y,-2,-1);
825
1028
  test_cond("sdsrange(...,-2,-1)",
826
1029
  sdslen(y) == 2 && memcmp(y,"ao\0",3) == 0)
827
1030
 
828
1031
  sdsfree(y);
829
- y = sdsrange(sdsdup(x),2,1);
1032
+ y = sdsdup(x);
1033
+ sdsrange(y,2,1);
830
1034
  test_cond("sdsrange(...,2,1)",
831
1035
  sdslen(y) == 0 && memcmp(y,"\0",1) == 0)
832
1036
 
833
1037
  sdsfree(y);
834
- y = sdsrange(sdsdup(x),1,100);
1038
+ y = sdsdup(x);
1039
+ sdsrange(y,1,100);
835
1040
  test_cond("sdsrange(...,1,100)",
836
1041
  sdslen(y) == 3 && memcmp(y,"iao\0",4) == 0)
837
1042
 
838
1043
  sdsfree(y);
839
- y = sdsrange(sdsdup(x),100,100);
1044
+ y = sdsdup(x);
1045
+ sdsrange(y,100,100);
840
1046
  test_cond("sdsrange(...,100,100)",
841
1047
  sdslen(y) == 0 && memcmp(y,"\0",1) == 0)
842
1048
 
@@ -858,6 +1064,13 @@ int main(void) {
858
1064
  y = sdsnew("bar");
859
1065
  test_cond("sdscmp(bar,bar)", sdscmp(x,y) < 0)
860
1066
 
1067
+ sdsfree(y);
1068
+ sdsfree(x);
1069
+ x = sdsnewlen("\a\n\0foo\r",7);
1070
+ y = sdscatrepr(sdsempty(),x,sdslen(x));
1071
+ test_cond("sdscatrepr(...data...)",
1072
+ memcmp(y,"\"\\a\\n\\x00foo\\r\"",15) == 0)
1073
+
861
1074
  {
862
1075
  int oldfree;
863
1076