methodmissing_hiredis 0.4.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,47 @@
1
+ /* Extracted from anet.c to work properly with Hiredis error reporting.
2
+ *
3
+ * Copyright (c) 2006-2011, Salvatore Sanfilippo <antirez at gmail dot com>
4
+ * Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>
5
+ *
6
+ * All rights reserved.
7
+ *
8
+ * Redistribution and use in source and binary forms, with or without
9
+ * modification, are permitted provided that the following conditions are met:
10
+ *
11
+ * * Redistributions of source code must retain the above copyright notice,
12
+ * this list of conditions and the following disclaimer.
13
+ * * Redistributions in binary form must reproduce the above copyright
14
+ * notice, this list of conditions and the following disclaimer in the
15
+ * documentation and/or other materials provided with the distribution.
16
+ * * Neither the name of Redis nor the names of its contributors may be used
17
+ * to endorse or promote products derived from this software without
18
+ * specific prior written permission.
19
+ *
20
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30
+ * POSSIBILITY OF SUCH DAMAGE.
31
+ */
32
+
33
+ #ifndef __NET_H
34
+ #define __NET_H
35
+
36
+ #include "hiredis.h"
37
+
38
+ #if defined(__sun)
39
+ #define AF_LOCAL AF_UNIX
40
+ #endif
41
+
42
+ int redisCheckSocketError(redisContext *c, int fd);
43
+ int redisContextSetTimeout(redisContext *c, struct timeval tv);
44
+ int redisContextConnectTcp(redisContext *c, const char *addr, int port, struct timeval *timeout);
45
+ int redisContextConnectUnix(redisContext *c, const char *path, struct timeval *timeout);
46
+
47
+ #endif
@@ -0,0 +1,605 @@
1
+ /* SDSLib, A C dynamic strings library
2
+ *
3
+ * Copyright (c) 2006-2010, Salvatore Sanfilippo <antirez at gmail dot com>
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ *
9
+ * * Redistributions of source code must retain the above copyright notice,
10
+ * this list of conditions and the following disclaimer.
11
+ * * Redistributions in binary form must reproduce the above copyright
12
+ * notice, this list of conditions and the following disclaimer in the
13
+ * documentation and/or other materials provided with the distribution.
14
+ * * Neither the name of Redis nor the names of its contributors may be used
15
+ * to endorse or promote products derived from this software without
16
+ * specific prior written permission.
17
+ *
18
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28
+ * POSSIBILITY OF SUCH DAMAGE.
29
+ */
30
+
31
+ #include <stdio.h>
32
+ #include <stdlib.h>
33
+ #include <string.h>
34
+ #include <ctype.h>
35
+ #include "sds.h"
36
+
37
+ #ifdef SDS_ABORT_ON_OOM
38
+ static void sdsOomAbort(void) {
39
+ fprintf(stderr,"SDS: Out Of Memory (SDS_ABORT_ON_OOM defined)\n");
40
+ abort();
41
+ }
42
+ #endif
43
+
44
+ sds sdsnewlen(const void *init, size_t initlen) {
45
+ struct sdshdr *sh;
46
+
47
+ sh = malloc(sizeof(struct sdshdr)+initlen+1);
48
+ #ifdef SDS_ABORT_ON_OOM
49
+ if (sh == NULL) sdsOomAbort();
50
+ #else
51
+ if (sh == NULL) return NULL;
52
+ #endif
53
+ sh->len = initlen;
54
+ sh->free = 0;
55
+ if (initlen) {
56
+ if (init) memcpy(sh->buf, init, initlen);
57
+ else memset(sh->buf,0,initlen);
58
+ }
59
+ sh->buf[initlen] = '\0';
60
+ return (char*)sh->buf;
61
+ }
62
+
63
+ sds sdsempty(void) {
64
+ return sdsnewlen("",0);
65
+ }
66
+
67
+ sds sdsnew(const char *init) {
68
+ size_t initlen = (init == NULL) ? 0 : strlen(init);
69
+ return sdsnewlen(init, initlen);
70
+ }
71
+
72
+ sds sdsdup(const sds s) {
73
+ return sdsnewlen(s, sdslen(s));
74
+ }
75
+
76
+ void sdsfree(sds s) {
77
+ if (s == NULL) return;
78
+ free(s-sizeof(struct sdshdr));
79
+ }
80
+
81
+ void sdsupdatelen(sds s) {
82
+ struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));
83
+ int reallen = strlen(s);
84
+ sh->free += (sh->len-reallen);
85
+ sh->len = reallen;
86
+ }
87
+
88
+ static sds sdsMakeRoomFor(sds s, size_t addlen) {
89
+ struct sdshdr *sh, *newsh;
90
+ size_t free = sdsavail(s);
91
+ size_t len, newlen;
92
+
93
+ if (free >= addlen) return s;
94
+ len = sdslen(s);
95
+ sh = (void*) (s-(sizeof(struct sdshdr)));
96
+ newlen = (len+addlen)*2;
97
+ newsh = realloc(sh, sizeof(struct sdshdr)+newlen+1);
98
+ #ifdef SDS_ABORT_ON_OOM
99
+ if (newsh == NULL) sdsOomAbort();
100
+ #else
101
+ if (newsh == NULL) return NULL;
102
+ #endif
103
+
104
+ newsh->free = newlen - len;
105
+ return newsh->buf;
106
+ }
107
+
108
+ /* Grow the sds to have the specified length. Bytes that were not part of
109
+ * the original length of the sds will be set to zero. */
110
+ sds sdsgrowzero(sds s, size_t len) {
111
+ struct sdshdr *sh = (void*)(s-(sizeof(struct sdshdr)));
112
+ size_t totlen, curlen = sh->len;
113
+
114
+ if (len <= curlen) return s;
115
+ s = sdsMakeRoomFor(s,len-curlen);
116
+ if (s == NULL) return NULL;
117
+
118
+ /* Make sure added region doesn't contain garbage */
119
+ sh = (void*)(s-(sizeof(struct sdshdr)));
120
+ memset(s+curlen,0,(len-curlen+1)); /* also set trailing \0 byte */
121
+ totlen = sh->len+sh->free;
122
+ sh->len = len;
123
+ sh->free = totlen-sh->len;
124
+ return s;
125
+ }
126
+
127
+ sds sdscatlen(sds s, const void *t, size_t len) {
128
+ struct sdshdr *sh;
129
+ size_t curlen = sdslen(s);
130
+
131
+ s = sdsMakeRoomFor(s,len);
132
+ if (s == NULL) return NULL;
133
+ sh = (void*) (s-(sizeof(struct sdshdr)));
134
+ memcpy(s+curlen, t, len);
135
+ sh->len = curlen+len;
136
+ sh->free = sh->free-len;
137
+ s[curlen+len] = '\0';
138
+ return s;
139
+ }
140
+
141
+ sds sdscat(sds s, const char *t) {
142
+ return sdscatlen(s, t, strlen(t));
143
+ }
144
+
145
+ sds sdscpylen(sds s, char *t, size_t len) {
146
+ struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));
147
+ size_t totlen = sh->free+sh->len;
148
+
149
+ if (totlen < len) {
150
+ s = sdsMakeRoomFor(s,len-sh->len);
151
+ if (s == NULL) return NULL;
152
+ sh = (void*) (s-(sizeof(struct sdshdr)));
153
+ totlen = sh->free+sh->len;
154
+ }
155
+ memcpy(s, t, len);
156
+ s[len] = '\0';
157
+ sh->len = len;
158
+ sh->free = totlen-len;
159
+ return s;
160
+ }
161
+
162
+ sds sdscpy(sds s, char *t) {
163
+ return sdscpylen(s, t, strlen(t));
164
+ }
165
+
166
+ sds sdscatvprintf(sds s, const char *fmt, va_list ap) {
167
+ va_list cpy;
168
+ char *buf, *t;
169
+ size_t buflen = 16;
170
+
171
+ while(1) {
172
+ buf = malloc(buflen);
173
+ #ifdef SDS_ABORT_ON_OOM
174
+ if (buf == NULL) sdsOomAbort();
175
+ #else
176
+ if (buf == NULL) return NULL;
177
+ #endif
178
+ buf[buflen-2] = '\0';
179
+ va_copy(cpy,ap);
180
+ vsnprintf(buf, buflen, fmt, cpy);
181
+ if (buf[buflen-2] != '\0') {
182
+ free(buf);
183
+ buflen *= 2;
184
+ continue;
185
+ }
186
+ break;
187
+ }
188
+ t = sdscat(s, buf);
189
+ free(buf);
190
+ return t;
191
+ }
192
+
193
+ sds sdscatprintf(sds s, const char *fmt, ...) {
194
+ va_list ap;
195
+ char *t;
196
+ va_start(ap, fmt);
197
+ t = sdscatvprintf(s,fmt,ap);
198
+ va_end(ap);
199
+ return t;
200
+ }
201
+
202
+ sds sdstrim(sds s, const char *cset) {
203
+ struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));
204
+ char *start, *end, *sp, *ep;
205
+ size_t len;
206
+
207
+ sp = start = s;
208
+ ep = end = s+sdslen(s)-1;
209
+ while(sp <= end && strchr(cset, *sp)) sp++;
210
+ while(ep > start && strchr(cset, *ep)) ep--;
211
+ len = (sp > ep) ? 0 : ((ep-sp)+1);
212
+ if (sh->buf != sp) memmove(sh->buf, sp, len);
213
+ sh->buf[len] = '\0';
214
+ sh->free = sh->free+(sh->len-len);
215
+ sh->len = len;
216
+ return s;
217
+ }
218
+
219
+ sds sdsrange(sds s, int start, int end) {
220
+ struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));
221
+ size_t newlen, len = sdslen(s);
222
+
223
+ if (len == 0) return s;
224
+ if (start < 0) {
225
+ start = len+start;
226
+ if (start < 0) start = 0;
227
+ }
228
+ if (end < 0) {
229
+ end = len+end;
230
+ if (end < 0) end = 0;
231
+ }
232
+ newlen = (start > end) ? 0 : (end-start)+1;
233
+ if (newlen != 0) {
234
+ if (start >= (signed)len) {
235
+ newlen = 0;
236
+ } else if (end >= (signed)len) {
237
+ end = len-1;
238
+ newlen = (start > end) ? 0 : (end-start)+1;
239
+ }
240
+ } else {
241
+ start = 0;
242
+ }
243
+ if (start && newlen) memmove(sh->buf, sh->buf+start, newlen);
244
+ sh->buf[newlen] = 0;
245
+ sh->free = sh->free+(sh->len-newlen);
246
+ sh->len = newlen;
247
+ return s;
248
+ }
249
+
250
+ void sdstolower(sds s) {
251
+ int len = sdslen(s), j;
252
+
253
+ for (j = 0; j < len; j++) s[j] = tolower(s[j]);
254
+ }
255
+
256
+ void sdstoupper(sds s) {
257
+ int len = sdslen(s), j;
258
+
259
+ for (j = 0; j < len; j++) s[j] = toupper(s[j]);
260
+ }
261
+
262
+ int sdscmp(sds s1, sds s2) {
263
+ size_t l1, l2, minlen;
264
+ int cmp;
265
+
266
+ l1 = sdslen(s1);
267
+ l2 = sdslen(s2);
268
+ minlen = (l1 < l2) ? l1 : l2;
269
+ cmp = memcmp(s1,s2,minlen);
270
+ if (cmp == 0) return l1-l2;
271
+ return cmp;
272
+ }
273
+
274
+ /* Split 's' with separator in 'sep'. An array
275
+ * of sds strings is returned. *count will be set
276
+ * by reference to the number of tokens returned.
277
+ *
278
+ * On out of memory, zero length string, zero length
279
+ * separator, NULL is returned.
280
+ *
281
+ * Note that 'sep' is able to split a string using
282
+ * a multi-character separator. For example
283
+ * sdssplit("foo_-_bar","_-_"); will return two
284
+ * elements "foo" and "bar".
285
+ *
286
+ * This version of the function is binary-safe but
287
+ * requires length arguments. sdssplit() is just the
288
+ * same function but for zero-terminated strings.
289
+ */
290
+ sds *sdssplitlen(char *s, int len, char *sep, int seplen, int *count) {
291
+ int elements = 0, slots = 5, start = 0, j;
292
+
293
+ sds *tokens = malloc(sizeof(sds)*slots);
294
+ #ifdef SDS_ABORT_ON_OOM
295
+ if (tokens == NULL) sdsOomAbort();
296
+ #endif
297
+ if (seplen < 1 || len < 0 || tokens == NULL) return NULL;
298
+ if (len == 0) {
299
+ *count = 0;
300
+ return tokens;
301
+ }
302
+ for (j = 0; j < (len-(seplen-1)); j++) {
303
+ /* make sure there is room for the next element and the final one */
304
+ if (slots < elements+2) {
305
+ sds *newtokens;
306
+
307
+ slots *= 2;
308
+ newtokens = realloc(tokens,sizeof(sds)*slots);
309
+ if (newtokens == NULL) {
310
+ #ifdef SDS_ABORT_ON_OOM
311
+ sdsOomAbort();
312
+ #else
313
+ goto cleanup;
314
+ #endif
315
+ }
316
+ tokens = newtokens;
317
+ }
318
+ /* search the separator */
319
+ if ((seplen == 1 && *(s+j) == sep[0]) || (memcmp(s+j,sep,seplen) == 0)) {
320
+ tokens[elements] = sdsnewlen(s+start,j-start);
321
+ if (tokens[elements] == NULL) {
322
+ #ifdef SDS_ABORT_ON_OOM
323
+ sdsOomAbort();
324
+ #else
325
+ goto cleanup;
326
+ #endif
327
+ }
328
+ elements++;
329
+ start = j+seplen;
330
+ j = j+seplen-1; /* skip the separator */
331
+ }
332
+ }
333
+ /* Add the final element. We are sure there is room in the tokens array. */
334
+ tokens[elements] = sdsnewlen(s+start,len-start);
335
+ if (tokens[elements] == NULL) {
336
+ #ifdef SDS_ABORT_ON_OOM
337
+ sdsOomAbort();
338
+ #else
339
+ goto cleanup;
340
+ #endif
341
+ }
342
+ elements++;
343
+ *count = elements;
344
+ return tokens;
345
+
346
+ #ifndef SDS_ABORT_ON_OOM
347
+ cleanup:
348
+ {
349
+ int i;
350
+ for (i = 0; i < elements; i++) sdsfree(tokens[i]);
351
+ free(tokens);
352
+ return NULL;
353
+ }
354
+ #endif
355
+ }
356
+
357
+ void sdsfreesplitres(sds *tokens, int count) {
358
+ if (!tokens) return;
359
+ while(count--)
360
+ sdsfree(tokens[count]);
361
+ free(tokens);
362
+ }
363
+
364
+ sds sdsfromlonglong(long long value) {
365
+ char buf[32], *p;
366
+ unsigned long long v;
367
+
368
+ v = (value < 0) ? -value : value;
369
+ p = buf+31; /* point to the last character */
370
+ do {
371
+ *p-- = '0'+(v%10);
372
+ v /= 10;
373
+ } while(v);
374
+ if (value < 0) *p-- = '-';
375
+ p++;
376
+ return sdsnewlen(p,32-(p-buf));
377
+ }
378
+
379
+ sds sdscatrepr(sds s, char *p, size_t len) {
380
+ s = sdscatlen(s,"\"",1);
381
+ if (s == NULL) return NULL;
382
+
383
+ while(len--) {
384
+ switch(*p) {
385
+ case '\\':
386
+ case '"':
387
+ s = sdscatprintf(s,"\\%c",*p);
388
+ break;
389
+ case '\n': s = sdscatlen(s,"\\n",2); break;
390
+ case '\r': s = sdscatlen(s,"\\r",2); break;
391
+ case '\t': s = sdscatlen(s,"\\t",2); break;
392
+ case '\a': s = sdscatlen(s,"\\a",2); break;
393
+ case '\b': s = sdscatlen(s,"\\b",2); break;
394
+ default:
395
+ if (isprint(*p))
396
+ s = sdscatprintf(s,"%c",*p);
397
+ else
398
+ s = sdscatprintf(s,"\\x%02x",(unsigned char)*p);
399
+ break;
400
+ }
401
+ p++;
402
+ if (s == NULL) return NULL;
403
+ }
404
+ return sdscatlen(s,"\"",1);
405
+ }
406
+
407
+ /* Split a line into arguments, where every argument can be in the
408
+ * following programming-language REPL-alike form:
409
+ *
410
+ * foo bar "newline are supported\n" and "\xff\x00otherstuff"
411
+ *
412
+ * The number of arguments is stored into *argc, and an array
413
+ * of sds is returned. The caller should sdsfree() all the returned
414
+ * strings and finally free() the array itself.
415
+ *
416
+ * Note that sdscatrepr() is able to convert back a string into
417
+ * a quoted string in the same format sdssplitargs() is able to parse.
418
+ */
419
+ sds *sdssplitargs(char *line, int *argc) {
420
+ char *p = line;
421
+ char *current = NULL;
422
+ char **vector = NULL, **_vector = NULL;
423
+
424
+ *argc = 0;
425
+ while(1) {
426
+ /* skip blanks */
427
+ while(*p && isspace(*p)) p++;
428
+ if (*p) {
429
+ /* get a token */
430
+ int inq=0; /* set to 1 if we are in "quotes" */
431
+ int done=0;
432
+
433
+ if (current == NULL) {
434
+ current = sdsempty();
435
+ if (current == NULL) goto err;
436
+ }
437
+
438
+ while(!done) {
439
+ if (inq) {
440
+ if (*p == '\\' && *(p+1)) {
441
+ char c;
442
+
443
+ p++;
444
+ switch(*p) {
445
+ case 'n': c = '\n'; break;
446
+ case 'r': c = '\r'; break;
447
+ case 't': c = '\t'; break;
448
+ case 'b': c = '\b'; break;
449
+ case 'a': c = '\a'; break;
450
+ default: c = *p; break;
451
+ }
452
+ current = sdscatlen(current,&c,1);
453
+ } else if (*p == '"') {
454
+ /* closing quote must be followed by a space */
455
+ if (*(p+1) && !isspace(*(p+1))) goto err;
456
+ done=1;
457
+ } else if (!*p) {
458
+ /* unterminated quotes */
459
+ goto err;
460
+ } else {
461
+ current = sdscatlen(current,p,1);
462
+ }
463
+ } else {
464
+ switch(*p) {
465
+ case ' ':
466
+ case '\n':
467
+ case '\r':
468
+ case '\t':
469
+ case '\0':
470
+ done=1;
471
+ break;
472
+ case '"':
473
+ inq=1;
474
+ break;
475
+ default:
476
+ current = sdscatlen(current,p,1);
477
+ break;
478
+ }
479
+ }
480
+ if (*p) p++;
481
+ if (current == NULL) goto err;
482
+ }
483
+ /* add the token to the vector */
484
+ _vector = realloc(vector,((*argc)+1)*sizeof(char*));
485
+ if (_vector == NULL) goto err;
486
+
487
+ vector = _vector;
488
+ vector[*argc] = current;
489
+ (*argc)++;
490
+ current = NULL;
491
+ } else {
492
+ return vector;
493
+ }
494
+ }
495
+
496
+ err:
497
+ while((*argc)--)
498
+ sdsfree(vector[*argc]);
499
+ if (vector != NULL) free(vector);
500
+ if (current != NULL) sdsfree(current);
501
+ return NULL;
502
+ }
503
+
504
+ #ifdef SDS_TEST_MAIN
505
+ #include <stdio.h>
506
+
507
+ int __failed_tests = 0;
508
+ int __test_num = 0;
509
+ #define test_cond(descr,_c) do { \
510
+ __test_num++; printf("%d - %s: ", __test_num, descr); \
511
+ if(_c) printf("PASSED\n"); else {printf("FAILED\n"); __failed_tests++;} \
512
+ } while(0);
513
+ #define test_report() do { \
514
+ printf("%d tests, %d passed, %d failed\n", __test_num, \
515
+ __test_num-__failed_tests, __failed_tests); \
516
+ if (__failed_tests) { \
517
+ printf("=== WARNING === We have failed tests here...\n"); \
518
+ } \
519
+ } while(0);
520
+
521
+ int main(void) {
522
+ {
523
+ sds x = sdsnew("foo"), y;
524
+
525
+ test_cond("Create a string and obtain the length",
526
+ sdslen(x) == 3 && memcmp(x,"foo\0",4) == 0)
527
+
528
+ sdsfree(x);
529
+ x = sdsnewlen("foo",2);
530
+ test_cond("Create a string with specified length",
531
+ sdslen(x) == 2 && memcmp(x,"fo\0",3) == 0)
532
+
533
+ x = sdscat(x,"bar");
534
+ test_cond("Strings concatenation",
535
+ sdslen(x) == 5 && memcmp(x,"fobar\0",6) == 0);
536
+
537
+ x = sdscpy(x,"a");
538
+ test_cond("sdscpy() against an originally longer string",
539
+ sdslen(x) == 1 && memcmp(x,"a\0",2) == 0)
540
+
541
+ x = sdscpy(x,"xyzxxxxxxxxxxyyyyyyyyyykkkkkkkkkk");
542
+ test_cond("sdscpy() against an originally shorter string",
543
+ sdslen(x) == 33 &&
544
+ memcmp(x,"xyzxxxxxxxxxxyyyyyyyyyykkkkkkkkkk\0",33) == 0)
545
+
546
+ sdsfree(x);
547
+ x = sdscatprintf(sdsempty(),"%d",123);
548
+ test_cond("sdscatprintf() seems working in the base case",
549
+ sdslen(x) == 3 && memcmp(x,"123\0",4) ==0)
550
+
551
+ sdsfree(x);
552
+ x = sdstrim(sdsnew("xxciaoyyy"),"xy");
553
+ test_cond("sdstrim() correctly trims characters",
554
+ sdslen(x) == 4 && memcmp(x,"ciao\0",5) == 0)
555
+
556
+ y = sdsrange(sdsdup(x),1,1);
557
+ test_cond("sdsrange(...,1,1)",
558
+ sdslen(y) == 1 && memcmp(y,"i\0",2) == 0)
559
+
560
+ sdsfree(y);
561
+ y = sdsrange(sdsdup(x),1,-1);
562
+ test_cond("sdsrange(...,1,-1)",
563
+ sdslen(y) == 3 && memcmp(y,"iao\0",4) == 0)
564
+
565
+ sdsfree(y);
566
+ y = sdsrange(sdsdup(x),-2,-1);
567
+ test_cond("sdsrange(...,-2,-1)",
568
+ sdslen(y) == 2 && memcmp(y,"ao\0",3) == 0)
569
+
570
+ sdsfree(y);
571
+ y = sdsrange(sdsdup(x),2,1);
572
+ test_cond("sdsrange(...,2,1)",
573
+ sdslen(y) == 0 && memcmp(y,"\0",1) == 0)
574
+
575
+ sdsfree(y);
576
+ y = sdsrange(sdsdup(x),1,100);
577
+ test_cond("sdsrange(...,1,100)",
578
+ sdslen(y) == 3 && memcmp(y,"iao\0",4) == 0)
579
+
580
+ sdsfree(y);
581
+ y = sdsrange(sdsdup(x),100,100);
582
+ test_cond("sdsrange(...,100,100)",
583
+ sdslen(y) == 0 && memcmp(y,"\0",1) == 0)
584
+
585
+ sdsfree(y);
586
+ sdsfree(x);
587
+ x = sdsnew("foo");
588
+ y = sdsnew("foa");
589
+ test_cond("sdscmp(foo,foa)", sdscmp(x,y) > 0)
590
+
591
+ sdsfree(y);
592
+ sdsfree(x);
593
+ x = sdsnew("bar");
594
+ y = sdsnew("bar");
595
+ test_cond("sdscmp(bar,bar)", sdscmp(x,y) == 0)
596
+
597
+ sdsfree(y);
598
+ sdsfree(x);
599
+ x = sdsnew("aar");
600
+ y = sdsnew("bar");
601
+ test_cond("sdscmp(bar,bar)", sdscmp(x,y) < 0)
602
+ }
603
+ test_report()
604
+ }
605
+ #endif