hiredis 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +1 -47
- data/ext/hiredis_ext/connection.c +104 -35
- data/ext/hiredis_ext/extconf.rb +1 -1
- data/ext/hiredis_ext/hiredis_ext.c +4 -2
- data/ext/hiredis_ext/hiredis_ext.h +0 -1
- data/ext/hiredis_ext/reader.c +0 -20
- data/lib/hiredis.rb +2 -10
- data/lib/hiredis/connection.rb +7 -14
- data/lib/hiredis/ext/connection.rb +16 -0
- data/lib/hiredis/ext/reader.rb +2 -0
- data/lib/hiredis/reader.rb +10 -1
- data/lib/hiredis/ruby/connection.rb +113 -0
- data/lib/hiredis/ruby/reader.rb +164 -0
- data/lib/hiredis/version.rb +1 -1
- data/vendor/hiredis/Makefile +4 -5
- data/vendor/hiredis/async.c +2 -0
- data/vendor/hiredis/async.h +3 -3
- data/vendor/hiredis/dict.c +27 -77
- data/vendor/hiredis/dict.h +12 -16
- data/vendor/hiredis/hiredis.c +26 -17
- data/vendor/hiredis/hiredis.h +4 -2
- data/vendor/hiredis/net.c +85 -18
- data/vendor/hiredis/net.h +2 -2
- data/vendor/hiredis/sds.c +129 -4
- data/vendor/hiredis/sds.h +2 -1
- data/vendor/hiredis/test.c +14 -5
- metadata +15 -29
- data/lib/hiredis/em.rb +0 -1
- data/lib/hiredis/em/base.rb +0 -36
- data/lib/hiredis/em/connection.rb +0 -25
data/vendor/hiredis/dict.h
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
/* Hash
|
1
|
+
/* Hash table implementation.
|
2
2
|
*
|
3
3
|
* This file implements in memory hash tables with insert/del/replace/find/
|
4
4
|
* get-random-element operations. Hash tables will auto resize if needed
|
@@ -111,20 +111,16 @@ typedef struct dictIterator {
|
|
111
111
|
#define dictSize(ht) ((ht)->used)
|
112
112
|
|
113
113
|
/* API */
|
114
|
-
|
115
|
-
|
116
|
-
int
|
117
|
-
int
|
118
|
-
int
|
119
|
-
int
|
120
|
-
void dictRelease(dict *ht);
|
121
|
-
dictEntry * dictFind(dict *ht, const void *key);
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
void dictReleaseIterator(dictIterator *iter);
|
126
|
-
dictEntry *dictGetRandomKey(dict *ht);
|
127
|
-
unsigned int dictGenHashFunction(const unsigned char *buf, int len);
|
128
|
-
void dictEmpty(dict *ht);
|
114
|
+
static unsigned int dictGenHashFunction(const unsigned char *buf, int len);
|
115
|
+
static dict *dictCreate(dictType *type, void *privDataPtr);
|
116
|
+
static int dictExpand(dict *ht, unsigned long size);
|
117
|
+
static int dictAdd(dict *ht, void *key, void *val);
|
118
|
+
static int dictReplace(dict *ht, void *key, void *val);
|
119
|
+
static int dictDelete(dict *ht, const void *key);
|
120
|
+
static void dictRelease(dict *ht);
|
121
|
+
static dictEntry * dictFind(dict *ht, const void *key);
|
122
|
+
static dictIterator *dictGetIterator(dict *ht);
|
123
|
+
static dictEntry *dictNext(dictIterator *iter);
|
124
|
+
static void dictReleaseIterator(dictIterator *iter);
|
129
125
|
|
130
126
|
#endif /* __DICT_H */
|
data/vendor/hiredis/hiredis.c
CHANGED
@@ -434,7 +434,7 @@ static int processItem(redisReader *r) {
|
|
434
434
|
}
|
435
435
|
}
|
436
436
|
|
437
|
-
void *redisReplyReaderCreate() {
|
437
|
+
void *redisReplyReaderCreate(void) {
|
438
438
|
redisReader *r = calloc(sizeof(redisReader),1);
|
439
439
|
r->error = NULL;
|
440
440
|
r->fn = &defaultFunctions;
|
@@ -493,7 +493,7 @@ static void redisSetReplyReaderError(redisReader *r, sds err) {
|
|
493
493
|
if (r->buf != NULL) {
|
494
494
|
sdsfree(r->buf);
|
495
495
|
r->buf = sdsempty();
|
496
|
-
r->pos = 0;
|
496
|
+
r->pos = r->len = 0;
|
497
497
|
}
|
498
498
|
r->ridx = -1;
|
499
499
|
r->error = err;
|
@@ -504,7 +504,7 @@ char *redisReplyReaderGetError(void *reader) {
|
|
504
504
|
return r->error;
|
505
505
|
}
|
506
506
|
|
507
|
-
void redisReplyReaderFeed(void *reader, char *buf, size_t len) {
|
507
|
+
void redisReplyReaderFeed(void *reader, const char *buf, size_t len) {
|
508
508
|
redisReader *r = reader;
|
509
509
|
|
510
510
|
/* Copy the provided buffer. */
|
@@ -538,15 +538,10 @@ int redisReplyReaderGetReply(void *reader, void **reply) {
|
|
538
538
|
if (processItem(r) < 0)
|
539
539
|
break;
|
540
540
|
|
541
|
-
/* Discard
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
sdsfree(r->buf);
|
546
|
-
r->buf = sdsempty();
|
547
|
-
} else {
|
548
|
-
r->buf = sdsrange(r->buf,r->pos,r->len);
|
549
|
-
}
|
541
|
+
/* Discard part of the buffer when we've consumed at least 1k, to avoid
|
542
|
+
* doing unnecessary calls to memmove() in sds.c. */
|
543
|
+
if (r->pos >= 1024) {
|
544
|
+
r->buf = sdsrange(r->buf,r->pos,-1);
|
550
545
|
r->pos = 0;
|
551
546
|
r->len = sdslen(r->buf);
|
552
547
|
}
|
@@ -798,7 +793,7 @@ void __redisSetError(redisContext *c, int type, const sds errstr) {
|
|
798
793
|
}
|
799
794
|
}
|
800
795
|
|
801
|
-
static redisContext *redisContextInit() {
|
796
|
+
static redisContext *redisContextInit(void) {
|
802
797
|
redisContext *c = calloc(sizeof(redisContext),1);
|
803
798
|
c->err = 0;
|
804
799
|
c->errstr = NULL;
|
@@ -826,28 +821,42 @@ void redisFree(redisContext *c) {
|
|
826
821
|
redisContext *redisConnect(const char *ip, int port) {
|
827
822
|
redisContext *c = redisContextInit();
|
828
823
|
c->flags |= REDIS_BLOCK;
|
829
|
-
redisContextConnectTcp(c,ip,port);
|
824
|
+
redisContextConnectTcp(c,ip,port,NULL);
|
825
|
+
return c;
|
826
|
+
}
|
827
|
+
|
828
|
+
redisContext *redisConnectWithTimeout(const char *ip, int port, struct timeval tv) {
|
829
|
+
redisContext *c = redisContextInit();
|
830
|
+
c->flags |= REDIS_BLOCK;
|
831
|
+
redisContextConnectTcp(c,ip,port,&tv);
|
830
832
|
return c;
|
831
833
|
}
|
832
834
|
|
833
835
|
redisContext *redisConnectNonBlock(const char *ip, int port) {
|
834
836
|
redisContext *c = redisContextInit();
|
835
837
|
c->flags &= ~REDIS_BLOCK;
|
836
|
-
redisContextConnectTcp(c,ip,port);
|
838
|
+
redisContextConnectTcp(c,ip,port,NULL);
|
837
839
|
return c;
|
838
840
|
}
|
839
841
|
|
840
842
|
redisContext *redisConnectUnix(const char *path) {
|
841
843
|
redisContext *c = redisContextInit();
|
842
844
|
c->flags |= REDIS_BLOCK;
|
843
|
-
redisContextConnectUnix(c,path);
|
845
|
+
redisContextConnectUnix(c,path,NULL);
|
846
|
+
return c;
|
847
|
+
}
|
848
|
+
|
849
|
+
redisContext *redisConnectUnixWithTimeout(const char *path, struct timeval tv) {
|
850
|
+
redisContext *c = redisContextInit();
|
851
|
+
c->flags |= REDIS_BLOCK;
|
852
|
+
redisContextConnectUnix(c,path,&tv);
|
844
853
|
return c;
|
845
854
|
}
|
846
855
|
|
847
856
|
redisContext *redisConnectUnixNonBlock(const char *path) {
|
848
857
|
redisContext *c = redisContextInit();
|
849
858
|
c->flags &= ~REDIS_BLOCK;
|
850
|
-
redisContextConnectUnix(c,path);
|
859
|
+
redisContextConnectUnix(c,path,NULL);
|
851
860
|
return c;
|
852
861
|
}
|
853
862
|
|
data/vendor/hiredis/hiredis.h
CHANGED
@@ -129,13 +129,13 @@ typedef struct redisContext {
|
|
129
129
|
} redisContext;
|
130
130
|
|
131
131
|
void freeReplyObject(void *reply);
|
132
|
-
void *redisReplyReaderCreate();
|
132
|
+
void *redisReplyReaderCreate(void);
|
133
133
|
int redisReplyReaderSetReplyObjectFunctions(void *reader, redisReplyObjectFunctions *fn);
|
134
134
|
int redisReplyReaderSetPrivdata(void *reader, void *privdata);
|
135
135
|
void *redisReplyReaderGetObject(void *reader);
|
136
136
|
char *redisReplyReaderGetError(void *reader);
|
137
137
|
void redisReplyReaderFree(void *ptr);
|
138
|
-
void redisReplyReaderFeed(void *reader, char *buf, size_t len);
|
138
|
+
void redisReplyReaderFeed(void *reader, const char *buf, size_t len);
|
139
139
|
int redisReplyReaderGetReply(void *reader, void **reply);
|
140
140
|
|
141
141
|
/* Functions to format a command according to the protocol. */
|
@@ -144,8 +144,10 @@ int redisFormatCommand(char **target, const char *format, ...);
|
|
144
144
|
int redisFormatCommandArgv(char **target, int argc, const char **argv, const size_t *argvlen);
|
145
145
|
|
146
146
|
redisContext *redisConnect(const char *ip, int port);
|
147
|
+
redisContext *redisConnectWithTimeout(const char *ip, int port, struct timeval tv);
|
147
148
|
redisContext *redisConnectNonBlock(const char *ip, int port);
|
148
149
|
redisContext *redisConnectUnix(const char *path);
|
150
|
+
redisContext *redisConnectUnixWithTimeout(const char *path, struct timeval tv);
|
149
151
|
redisContext *redisConnectUnixNonBlock(const char *path);
|
150
152
|
int redisSetTimeout(redisContext *c, struct timeval tv);
|
151
153
|
int redisSetReplyObjectFunctions(redisContext *c, redisReplyObjectFunctions *fn);
|
data/vendor/hiredis/net.c
CHANGED
@@ -33,6 +33,7 @@
|
|
33
33
|
#include "fmacros.h"
|
34
34
|
#include <sys/types.h>
|
35
35
|
#include <sys/socket.h>
|
36
|
+
#include <sys/select.h>
|
36
37
|
#include <sys/un.h>
|
37
38
|
#include <netinet/in.h>
|
38
39
|
#include <netinet/tcp.h>
|
@@ -67,7 +68,7 @@ static int redisCreateSocket(redisContext *c, int type) {
|
|
67
68
|
return s;
|
68
69
|
}
|
69
70
|
|
70
|
-
static int
|
71
|
+
static int redisSetBlocking(redisContext *c, int fd, int blocking) {
|
71
72
|
int flags;
|
72
73
|
|
73
74
|
/* Set the socket nonblocking.
|
@@ -79,9 +80,15 @@ static int redisSetNonBlock(redisContext *c, int fd) {
|
|
79
80
|
close(fd);
|
80
81
|
return REDIS_ERR;
|
81
82
|
}
|
82
|
-
|
83
|
+
|
84
|
+
if (blocking)
|
85
|
+
flags &= ~O_NONBLOCK;
|
86
|
+
else
|
87
|
+
flags |= O_NONBLOCK;
|
88
|
+
|
89
|
+
if (fcntl(fd, F_SETFL, flags) == -1) {
|
83
90
|
__redisSetError(c,REDIS_ERR_IO,
|
84
|
-
sdscatprintf(sdsempty(), "fcntl(F_SETFL
|
91
|
+
sdscatprintf(sdsempty(), "fcntl(F_SETFL): %s", strerror(errno)));
|
85
92
|
close(fd);
|
86
93
|
return REDIS_ERR;
|
87
94
|
}
|
@@ -93,11 +100,67 @@ static int redisSetTcpNoDelay(redisContext *c, int fd) {
|
|
93
100
|
if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(yes)) == -1) {
|
94
101
|
__redisSetError(c,REDIS_ERR_IO,
|
95
102
|
sdscatprintf(sdsempty(), "setsockopt(TCP_NODELAY): %s", strerror(errno)));
|
103
|
+
close(fd);
|
96
104
|
return REDIS_ERR;
|
97
105
|
}
|
98
106
|
return REDIS_OK;
|
99
107
|
}
|
100
108
|
|
109
|
+
static int redisContextWaitReady(redisContext *c, int fd, const struct timeval *timeout) {
|
110
|
+
struct timeval to;
|
111
|
+
struct timeval *toptr = NULL;
|
112
|
+
fd_set wfd;
|
113
|
+
int err;
|
114
|
+
socklen_t errlen;
|
115
|
+
|
116
|
+
/* Only use timeout when not NULL. */
|
117
|
+
if (timeout != NULL) {
|
118
|
+
to = *timeout;
|
119
|
+
toptr = &to;
|
120
|
+
}
|
121
|
+
|
122
|
+
if (errno == EINPROGRESS) {
|
123
|
+
FD_ZERO(&wfd);
|
124
|
+
FD_SET(fd, &wfd);
|
125
|
+
|
126
|
+
if (select(FD_SETSIZE, NULL, &wfd, NULL, toptr) == -1) {
|
127
|
+
__redisSetError(c,REDIS_ERR_IO,
|
128
|
+
sdscatprintf(sdsempty(), "select(2): %s", strerror(errno)));
|
129
|
+
close(fd);
|
130
|
+
return REDIS_ERR;
|
131
|
+
}
|
132
|
+
|
133
|
+
if (!FD_ISSET(fd, &wfd)) {
|
134
|
+
errno = ETIMEDOUT;
|
135
|
+
__redisSetError(c,REDIS_ERR_IO,NULL);
|
136
|
+
close(fd);
|
137
|
+
return REDIS_ERR;
|
138
|
+
}
|
139
|
+
|
140
|
+
err = 0;
|
141
|
+
errlen = sizeof(err);
|
142
|
+
if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1) {
|
143
|
+
__redisSetError(c,REDIS_ERR_IO,
|
144
|
+
sdscatprintf(sdsempty(), "getsockopt(SO_ERROR): %s", strerror(errno)));
|
145
|
+
close(fd);
|
146
|
+
return REDIS_ERR;
|
147
|
+
}
|
148
|
+
|
149
|
+
if (err) {
|
150
|
+
errno = err;
|
151
|
+
__redisSetError(c,REDIS_ERR_IO,NULL);
|
152
|
+
close(fd);
|
153
|
+
return REDIS_ERR;
|
154
|
+
}
|
155
|
+
|
156
|
+
return REDIS_OK;
|
157
|
+
}
|
158
|
+
|
159
|
+
__redisSetError(c,REDIS_ERR_IO,NULL);
|
160
|
+
close(fd);
|
161
|
+
return REDIS_ERR;
|
162
|
+
}
|
163
|
+
|
101
164
|
int redisContextSetTimeout(redisContext *c, struct timeval tv) {
|
102
165
|
if (setsockopt(c->fd,SOL_SOCKET,SO_RCVTIMEO,&tv,sizeof(tv)) == -1) {
|
103
166
|
__redisSetError(c,REDIS_ERR_IO,
|
@@ -112,14 +175,14 @@ int redisContextSetTimeout(redisContext *c, struct timeval tv) {
|
|
112
175
|
return REDIS_OK;
|
113
176
|
}
|
114
177
|
|
115
|
-
int redisContextConnectTcp(redisContext *c, const char *addr, int port) {
|
178
|
+
int redisContextConnectTcp(redisContext *c, const char *addr, int port, struct timeval *timeout) {
|
116
179
|
int s;
|
117
180
|
int blocking = (c->flags & REDIS_BLOCK);
|
118
181
|
struct sockaddr_in sa;
|
119
182
|
|
120
|
-
if ((s = redisCreateSocket(c,AF_INET))
|
183
|
+
if ((s = redisCreateSocket(c,AF_INET)) < 0)
|
121
184
|
return REDIS_ERR;
|
122
|
-
if (
|
185
|
+
if (redisSetBlocking(c,s,0) != REDIS_OK)
|
123
186
|
return REDIS_ERR;
|
124
187
|
|
125
188
|
sa.sin_family = AF_INET;
|
@@ -141,30 +204,31 @@ int redisContextConnectTcp(redisContext *c, const char *addr, int port) {
|
|
141
204
|
if (errno == EINPROGRESS && !blocking) {
|
142
205
|
/* This is ok. */
|
143
206
|
} else {
|
144
|
-
|
145
|
-
|
146
|
-
return REDIS_ERR;
|
207
|
+
if (redisContextWaitReady(c,s,timeout) != REDIS_OK)
|
208
|
+
return REDIS_ERR;
|
147
209
|
}
|
148
210
|
}
|
149
211
|
|
150
|
-
|
151
|
-
|
212
|
+
/* Reset socket to be blocking after connect(2). */
|
213
|
+
if (blocking && redisSetBlocking(c,s,1) != REDIS_OK)
|
214
|
+
return REDIS_ERR;
|
215
|
+
|
216
|
+
if (redisSetTcpNoDelay(c,s) != REDIS_OK)
|
152
217
|
return REDIS_ERR;
|
153
|
-
}
|
154
218
|
|
155
219
|
c->fd = s;
|
156
220
|
c->flags |= REDIS_CONNECTED;
|
157
221
|
return REDIS_OK;
|
158
222
|
}
|
159
223
|
|
160
|
-
int redisContextConnectUnix(redisContext *c, const char *path) {
|
224
|
+
int redisContextConnectUnix(redisContext *c, const char *path, struct timeval *timeout) {
|
161
225
|
int s;
|
162
226
|
int blocking = (c->flags & REDIS_BLOCK);
|
163
227
|
struct sockaddr_un sa;
|
164
228
|
|
165
|
-
if ((s = redisCreateSocket(c,AF_LOCAL))
|
229
|
+
if ((s = redisCreateSocket(c,AF_LOCAL)) < 0)
|
166
230
|
return REDIS_ERR;
|
167
|
-
if (
|
231
|
+
if (redisSetBlocking(c,s,0) != REDIS_OK)
|
168
232
|
return REDIS_ERR;
|
169
233
|
|
170
234
|
sa.sun_family = AF_LOCAL;
|
@@ -173,12 +237,15 @@ int redisContextConnectUnix(redisContext *c, const char *path) {
|
|
173
237
|
if (errno == EINPROGRESS && !blocking) {
|
174
238
|
/* This is ok. */
|
175
239
|
} else {
|
176
|
-
|
177
|
-
|
178
|
-
return REDIS_ERR;
|
240
|
+
if (redisContextWaitReady(c,s,timeout) != REDIS_OK)
|
241
|
+
return REDIS_ERR;
|
179
242
|
}
|
180
243
|
}
|
181
244
|
|
245
|
+
/* Reset socket to be blocking after connect(2). */
|
246
|
+
if (blocking && redisSetBlocking(c,s,1) != REDIS_OK)
|
247
|
+
return REDIS_ERR;
|
248
|
+
|
182
249
|
c->fd = s;
|
183
250
|
c->flags |= REDIS_CONNECTED;
|
184
251
|
return REDIS_OK;
|
data/vendor/hiredis/net.h
CHANGED
@@ -40,7 +40,7 @@
|
|
40
40
|
#endif
|
41
41
|
|
42
42
|
int redisContextSetTimeout(redisContext *c, struct timeval tv);
|
43
|
-
int redisContextConnectTcp(redisContext *c, const char *addr, int port);
|
44
|
-
int redisContextConnectUnix(redisContext *c, const char *path);
|
43
|
+
int redisContextConnectTcp(redisContext *c, const char *addr, int port, struct timeval *timeout);
|
44
|
+
int redisContextConnectUnix(redisContext *c, const char *path, struct timeval *timeout);
|
45
45
|
|
46
46
|
#endif
|
data/vendor/hiredis/sds.c
CHANGED
@@ -115,6 +115,25 @@ static sds sdsMakeRoomFor(sds s, size_t addlen) {
|
|
115
115
|
return newsh->buf;
|
116
116
|
}
|
117
117
|
|
118
|
+
/* Grow the sds to have the specified length. Bytes that were not part of
|
119
|
+
* the original length of the sds will be set to zero. */
|
120
|
+
sds sdsgrowzero(sds s, size_t len) {
|
121
|
+
struct sdshdr *sh = (void*)(s-(sizeof(struct sdshdr)));
|
122
|
+
size_t totlen, curlen = sh->len;
|
123
|
+
|
124
|
+
if (len <= curlen) return s;
|
125
|
+
s = sdsMakeRoomFor(s,len-curlen);
|
126
|
+
if (s == NULL) return NULL;
|
127
|
+
|
128
|
+
/* Make sure added region doesn't contain garbage */
|
129
|
+
sh = (void*)(s-(sizeof(struct sdshdr)));
|
130
|
+
memset(s+curlen,0,(len-curlen+1)); /* also set trailing \0 byte */
|
131
|
+
totlen = sh->len+sh->free;
|
132
|
+
sh->len = len;
|
133
|
+
sh->free = totlen-sh->len;
|
134
|
+
return s;
|
135
|
+
}
|
136
|
+
|
118
137
|
sds sdscatlen(sds s, const void *t, size_t len) {
|
119
138
|
struct sdshdr *sh;
|
120
139
|
size_t curlen = sdslen(s);
|
@@ -222,13 +241,16 @@ sds sdsrange(sds s, int start, int end) {
|
|
222
241
|
}
|
223
242
|
newlen = (start > end) ? 0 : (end-start)+1;
|
224
243
|
if (newlen != 0) {
|
225
|
-
if (start >= (signed)len)
|
226
|
-
|
227
|
-
|
244
|
+
if (start >= (signed)len) {
|
245
|
+
newlen = 0;
|
246
|
+
} else if (end >= (signed)len) {
|
247
|
+
end = len-1;
|
248
|
+
newlen = (start > end) ? 0 : (end-start)+1;
|
249
|
+
}
|
228
250
|
} else {
|
229
251
|
start = 0;
|
230
252
|
}
|
231
|
-
if (start
|
253
|
+
if (start && newlen) memmove(sh->buf, sh->buf+start, newlen);
|
232
254
|
sh->buf[newlen] = 0;
|
233
255
|
sh->free = sh->free+(sh->len-newlen);
|
234
256
|
sh->len = newlen;
|
@@ -477,3 +499,106 @@ err:
|
|
477
499
|
if (current) sdsfree(current);
|
478
500
|
return NULL;
|
479
501
|
}
|
502
|
+
|
503
|
+
#ifdef SDS_TEST_MAIN
|
504
|
+
#include <stdio.h>
|
505
|
+
|
506
|
+
int __failed_tests = 0;
|
507
|
+
int __test_num = 0;
|
508
|
+
#define test_cond(descr,_c) do { \
|
509
|
+
__test_num++; printf("%d - %s: ", __test_num, descr); \
|
510
|
+
if(_c) printf("PASSED\n"); else {printf("FAILED\n"); __failed_tests++;} \
|
511
|
+
} while(0);
|
512
|
+
#define test_report() do { \
|
513
|
+
printf("%d tests, %d passed, %d failed\n", __test_num, \
|
514
|
+
__test_num-__failed_tests, __failed_tests); \
|
515
|
+
if (__failed_tests) { \
|
516
|
+
printf("=== WARNING === We have failed tests here...\n"); \
|
517
|
+
} \
|
518
|
+
} while(0);
|
519
|
+
|
520
|
+
int main(void) {
|
521
|
+
{
|
522
|
+
sds x = sdsnew("foo"), y;
|
523
|
+
|
524
|
+
test_cond("Create a string and obtain the length",
|
525
|
+
sdslen(x) == 3 && memcmp(x,"foo\0",4) == 0)
|
526
|
+
|
527
|
+
sdsfree(x);
|
528
|
+
x = sdsnewlen("foo",2);
|
529
|
+
test_cond("Create a string with specified length",
|
530
|
+
sdslen(x) == 2 && memcmp(x,"fo\0",3) == 0)
|
531
|
+
|
532
|
+
x = sdscat(x,"bar");
|
533
|
+
test_cond("Strings concatenation",
|
534
|
+
sdslen(x) == 5 && memcmp(x,"fobar\0",6) == 0);
|
535
|
+
|
536
|
+
x = sdscpy(x,"a");
|
537
|
+
test_cond("sdscpy() against an originally longer string",
|
538
|
+
sdslen(x) == 1 && memcmp(x,"a\0",2) == 0)
|
539
|
+
|
540
|
+
x = sdscpy(x,"xyzxxxxxxxxxxyyyyyyyyyykkkkkkkkkk");
|
541
|
+
test_cond("sdscpy() against an originally shorter string",
|
542
|
+
sdslen(x) == 33 &&
|
543
|
+
memcmp(x,"xyzxxxxxxxxxxyyyyyyyyyykkkkkkkkkk\0",33) == 0)
|
544
|
+
|
545
|
+
sdsfree(x);
|
546
|
+
x = sdscatprintf(sdsempty(),"%d",123);
|
547
|
+
test_cond("sdscatprintf() seems working in the base case",
|
548
|
+
sdslen(x) == 3 && memcmp(x,"123\0",4) ==0)
|
549
|
+
|
550
|
+
sdsfree(x);
|
551
|
+
x = sdstrim(sdsnew("xxciaoyyy"),"xy");
|
552
|
+
test_cond("sdstrim() correctly trims characters",
|
553
|
+
sdslen(x) == 4 && memcmp(x,"ciao\0",5) == 0)
|
554
|
+
|
555
|
+
y = sdsrange(sdsdup(x),1,1);
|
556
|
+
test_cond("sdsrange(...,1,1)",
|
557
|
+
sdslen(y) == 1 && memcmp(y,"i\0",2) == 0)
|
558
|
+
|
559
|
+
sdsfree(y);
|
560
|
+
y = sdsrange(sdsdup(x),1,-1);
|
561
|
+
test_cond("sdsrange(...,1,-1)",
|
562
|
+
sdslen(y) == 3 && memcmp(y,"iao\0",4) == 0)
|
563
|
+
|
564
|
+
sdsfree(y);
|
565
|
+
y = sdsrange(sdsdup(x),-2,-1);
|
566
|
+
test_cond("sdsrange(...,-2,-1)",
|
567
|
+
sdslen(y) == 2 && memcmp(y,"ao\0",3) == 0)
|
568
|
+
|
569
|
+
sdsfree(y);
|
570
|
+
y = sdsrange(sdsdup(x),2,1);
|
571
|
+
test_cond("sdsrange(...,2,1)",
|
572
|
+
sdslen(y) == 0 && memcmp(y,"\0",1) == 0)
|
573
|
+
|
574
|
+
sdsfree(y);
|
575
|
+
y = sdsrange(sdsdup(x),1,100);
|
576
|
+
test_cond("sdsrange(...,1,100)",
|
577
|
+
sdslen(y) == 3 && memcmp(y,"iao\0",4) == 0)
|
578
|
+
|
579
|
+
sdsfree(y);
|
580
|
+
y = sdsrange(sdsdup(x),100,100);
|
581
|
+
test_cond("sdsrange(...,100,100)",
|
582
|
+
sdslen(y) == 0 && memcmp(y,"\0",1) == 0)
|
583
|
+
|
584
|
+
sdsfree(y);
|
585
|
+
sdsfree(x);
|
586
|
+
x = sdsnew("foo");
|
587
|
+
y = sdsnew("foa");
|
588
|
+
test_cond("sdscmp(foo,foa)", sdscmp(x,y) > 0)
|
589
|
+
|
590
|
+
sdsfree(y);
|
591
|
+
sdsfree(x);
|
592
|
+
x = sdsnew("bar");
|
593
|
+
y = sdsnew("bar");
|
594
|
+
test_cond("sdscmp(bar,bar)", sdscmp(x,y) == 0)
|
595
|
+
|
596
|
+
sdsfree(y);
|
597
|
+
sdsfree(x);
|
598
|
+
x = sdsnew("aar");
|
599
|
+
y = sdsnew("bar");
|
600
|
+
test_cond("sdscmp(bar,bar)", sdscmp(x,y) < 0)
|
601
|
+
}
|
602
|
+
test_report()
|
603
|
+
}
|
604
|
+
#endif
|