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.
- checksums.yaml +4 -4
- data/deps/hiredis/Makefile +110 -41
- data/deps/hiredis/async.c +87 -22
- data/deps/hiredis/async.h +4 -0
- data/deps/hiredis/fmacros.h +6 -1
- data/deps/hiredis/hiredis.c +270 -534
- data/deps/hiredis/hiredis.h +89 -76
- data/deps/hiredis/net.c +206 -47
- data/deps/hiredis/net.h +12 -6
- data/deps/hiredis/read.c +525 -0
- data/deps/hiredis/read.h +116 -0
- data/deps/hiredis/sds.c +260 -47
- data/deps/hiredis/sds.h +11 -6
- data/deps/hiredis/test.c +171 -18
- data/deps/hiredis/win32.h +42 -0
- data/librb/durable.rb +35 -6
- data/librb/engine.rb +173 -40
- data/src/rules/events.c +42 -4
- data/src/rules/net.c +184 -96
- data/src/rules/net.h +10 -0
- data/src/rules/rules.h +13 -0
- data/src/rulesrb/rules.c +55 -0
- metadata +5 -3
- data/deps/hiredis/zmalloc.h +0 -13
data/deps/hiredis/read.h
ADDED
|
@@ -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
|
-
/*
|
|
1
|
+
/* SDS (Simple Dynamic Strings), A C dynamic strings library.
|
|
2
2
|
*
|
|
3
|
-
* Copyright (c) 2006-
|
|
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 =
|
|
55
|
+
sh = malloc(sizeof *sh+initlen+1);
|
|
56
56
|
} else {
|
|
57
|
-
sh =
|
|
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
|
-
|
|
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-
|
|
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-
|
|
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-
|
|
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 =
|
|
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-
|
|
159
|
-
sh =
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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 =
|
|
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
|
-
|
|
372
|
+
free(buf);
|
|
306
373
|
buflen *= 2;
|
|
307
374
|
continue;
|
|
308
375
|
}
|
|
309
376
|
break;
|
|
310
377
|
}
|
|
311
378
|
t = sdscat(s, buf);
|
|
312
|
-
|
|
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 =
|
|
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
|
-
|
|
356
|
-
struct sdshdr *sh = (void*) (s-
|
|
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
|
-
*
|
|
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-
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
|