Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ruanhaishen
redis
Commits
aea80205
Commit
aea80205
authored
Jul 25, 2013
by
antirez
Browse files
Use latest sds.c in the hiredis library under deps.
parent
c3e1724a
Changes
4
Hide whitespace changes
Inline
Side-by-side
deps/hiredis/hiredis.c
View file @
aea80205
...
@@ -650,7 +650,7 @@ int redisReaderGetReply(redisReader *r, void **reply) {
...
@@ -650,7 +650,7 @@ int redisReaderGetReply(redisReader *r, void **reply) {
/* Discard part of the buffer when we've consumed at least 1k, to avoid
/* Discard part of the buffer when we've consumed at least 1k, to avoid
* doing unnecessary calls to memmove() in sds.c. */
* doing unnecessary calls to memmove() in sds.c. */
if
(
r
->
pos
>=
1024
)
{
if
(
r
->
pos
>=
1024
)
{
r
->
buf
=
sdsrange
(
r
->
buf
,
r
->
pos
,
-
1
);
sdsrange
(
r
->
buf
,
r
->
pos
,
-
1
);
r
->
pos
=
0
;
r
->
pos
=
0
;
r
->
len
=
sdslen
(
r
->
buf
);
r
->
len
=
sdslen
(
r
->
buf
);
}
}
...
@@ -1125,7 +1125,7 @@ int redisBufferWrite(redisContext *c, int *done) {
...
@@ -1125,7 +1125,7 @@ int redisBufferWrite(redisContext *c, int *done) {
sdsfree
(
c
->
obuf
);
sdsfree
(
c
->
obuf
);
c
->
obuf
=
sdsempty
();
c
->
obuf
=
sdsempty
();
}
else
{
}
else
{
c
->
obuf
=
sdsrange
(
c
->
obuf
,
nwritten
,
-
1
);
sdsrange
(
c
->
obuf
,
nwritten
,
-
1
);
}
}
}
}
}
}
...
...
deps/hiredis/sds.c
View file @
aea80205
/* SDSLib, A C dynamic strings library
/* SDSLib, A C dynamic strings library
*
*
* Copyright (c) 2006-201
0
, Salvatore Sanfilippo <antirez at gmail dot com>
* Copyright (c) 2006-201
2
, Salvatore Sanfilippo <antirez at gmail dot com>
* All rights reserved.
* All rights reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* Redistribution and use in source and binary forms, with or without
...
@@ -32,52 +32,76 @@
...
@@ -32,52 +32,76 @@
#include <stdlib.h>
#include <stdlib.h>
#include <string.h>
#include <string.h>
#include <ctype.h>
#include <ctype.h>
#include <assert.h>
#include "sds.h"
#include "sds.h"
#include "zmalloc.h"
#ifdef SDS_ABORT_ON_OOM
/* Create a new sds string with the content specified by the 'init' pointer
static
void
sdsOomAbort
(
void
)
{
* and 'initlen'.
fprintf
(
stderr
,
"SDS: Out Of Memory (SDS_ABORT_ON_OOM defined)
\n
"
);
* If NULL is used for 'init' the string is initialized with zero bytes.
abort
();
*
}
* The string is always null-termined (all the sds strings are, always) so
#endif
* even if you create an sds string with:
*
* mystring = sdsnewlen("abc",3");
*
* You can print the string with printf() as there is an implicit \0 at the
* end of the string. However the string is binary safe and can contain
* \0 characters in the middle, as the length is stored in the sds header. */
sds
sdsnewlen
(
const
void
*
init
,
size_t
initlen
)
{
sds
sdsnewlen
(
const
void
*
init
,
size_t
initlen
)
{
struct
sdshdr
*
sh
;
struct
sdshdr
*
sh
;
sh
=
malloc
(
sizeof
(
struct
sdshdr
)
+
initlen
+
1
);
if
(
init
)
{
#ifdef SDS_ABORT_ON_OOM
sh
=
zmalloc
(
sizeof
(
struct
sdshdr
)
+
initlen
+
1
);
if
(
sh
==
NULL
)
sdsOomAbort
();
}
else
{
#else
sh
=
zcalloc
(
sizeof
(
struct
sdshdr
)
+
initlen
+
1
);
}
if
(
sh
==
NULL
)
return
NULL
;
if
(
sh
==
NULL
)
return
NULL
;
#endif
sh
->
len
=
initlen
;
sh
->
len
=
initlen
;
sh
->
free
=
0
;
sh
->
free
=
0
;
if
(
initlen
)
{
if
(
initlen
&&
init
)
if
(
init
)
memcpy
(
sh
->
buf
,
init
,
initlen
);
memcpy
(
sh
->
buf
,
init
,
initlen
);
else
memset
(
sh
->
buf
,
0
,
initlen
);
}
sh
->
buf
[
initlen
]
=
'\0'
;
sh
->
buf
[
initlen
]
=
'\0'
;
return
(
char
*
)
sh
->
buf
;
return
(
char
*
)
sh
->
buf
;
}
}
/* Create an empty (zero length) sds string. Even in this case the string
* always has an implicit null term. */
sds
sdsempty
(
void
)
{
sds
sdsempty
(
void
)
{
return
sdsnewlen
(
""
,
0
);
return
sdsnewlen
(
""
,
0
);
}
}
/* Create a new sds string starting from a null termined C string. */
sds
sdsnew
(
const
char
*
init
)
{
sds
sdsnew
(
const
char
*
init
)
{
size_t
initlen
=
(
init
==
NULL
)
?
0
:
strlen
(
init
);
size_t
initlen
=
(
init
==
NULL
)
?
0
:
strlen
(
init
);
return
sdsnewlen
(
init
,
initlen
);
return
sdsnewlen
(
init
,
initlen
);
}
}
/* Duplicate an sds string. */
sds
sdsdup
(
const
sds
s
)
{
sds
sdsdup
(
const
sds
s
)
{
return
sdsnewlen
(
s
,
sdslen
(
s
));
return
sdsnewlen
(
s
,
sdslen
(
s
));
}
}
/* Free an sds string. No operation is performed if 's' is NULL. */
void
sdsfree
(
sds
s
)
{
void
sdsfree
(
sds
s
)
{
if
(
s
==
NULL
)
return
;
if
(
s
==
NULL
)
return
;
free
(
s
-
sizeof
(
struct
sdshdr
));
z
free
(
s
-
sizeof
(
struct
sdshdr
));
}
}
/* Set the sds string length to the length as obtained with strlen(), so
* considering as content only up to the first null term character.
*
* This function is useful when the sds string is hacked manually in some
* way, like in the following example:
*
* s = sdsnew("foobar");
* s[2] = '\0';
* sdsupdatelen(s);
* printf("%d\n", sdslen(s));
*
* The output will be "2", but if we comment out the call to sdsupdatelen()
* the output will be "6" as the string was modified but the logical length
* remains 6 bytes. */
void
sdsupdatelen
(
sds
s
)
{
void
sdsupdatelen
(
sds
s
)
{
struct
sdshdr
*
sh
=
(
void
*
)
(
s
-
(
sizeof
(
struct
sdshdr
)));
struct
sdshdr
*
sh
=
(
void
*
)
(
s
-
(
sizeof
(
struct
sdshdr
)));
int
reallen
=
strlen
(
s
);
int
reallen
=
strlen
(
s
);
...
@@ -85,7 +109,24 @@ void sdsupdatelen(sds s) {
...
@@ -85,7 +109,24 @@ void sdsupdatelen(sds s) {
sh
->
len
=
reallen
;
sh
->
len
=
reallen
;
}
}
static
sds
sdsMakeRoomFor
(
sds
s
,
size_t
addlen
)
{
/* Modify an sds string on-place to make it empty (zero length).
* However all the existing buffer is not discarded but set as free space
* so that next append operations will not require allocations up to the
* number of bytes previously available. */
void
sdsclear
(
sds
s
)
{
struct
sdshdr
*
sh
=
(
void
*
)
(
s
-
(
sizeof
(
struct
sdshdr
)));
sh
->
free
+=
sh
->
len
;
sh
->
len
=
0
;
sh
->
buf
[
0
]
=
'\0'
;
}
/* Enlarge the free space at the end of the sds string so that the caller
* is sure that after calling this function can overwrite up to addlen
* bytes after the end of the string, plus one more byte for nul term.
*
* Note: this does not change the *length* of the sds string as returned
* by sdslen(), but only the free buffer space we have. */
sds
sdsMakeRoomFor
(
sds
s
,
size_t
addlen
)
{
struct
sdshdr
*
sh
,
*
newsh
;
struct
sdshdr
*
sh
,
*
newsh
;
size_t
free
=
sdsavail
(
s
);
size_t
free
=
sdsavail
(
s
);
size_t
len
,
newlen
;
size_t
len
,
newlen
;
...
@@ -93,20 +134,84 @@ static sds sdsMakeRoomFor(sds s, size_t addlen) {
...
@@ -93,20 +134,84 @@ static sds sdsMakeRoomFor(sds s, size_t addlen) {
if
(
free
>=
addlen
)
return
s
;
if
(
free
>=
addlen
)
return
s
;
len
=
sdslen
(
s
);
len
=
sdslen
(
s
);
sh
=
(
void
*
)
(
s
-
(
sizeof
(
struct
sdshdr
)));
sh
=
(
void
*
)
(
s
-
(
sizeof
(
struct
sdshdr
)));
newlen
=
(
len
+
addlen
)
*
2
;
newlen
=
(
len
+
addlen
);
newsh
=
realloc
(
sh
,
sizeof
(
struct
sdshdr
)
+
newlen
+
1
);
if
(
newlen
<
SDS_MAX_PREALLOC
)
#ifdef SDS_ABORT_ON_OOM
newlen
*=
2
;
if
(
newsh
==
NULL
)
sdsOomAbort
();
else
#else
newlen
+=
SDS_MAX_PREALLOC
;
newsh
=
zrealloc
(
sh
,
sizeof
(
struct
sdshdr
)
+
newlen
+
1
);
if
(
newsh
==
NULL
)
return
NULL
;
if
(
newsh
==
NULL
)
return
NULL
;
#endif
newsh
->
free
=
newlen
-
len
;
newsh
->
free
=
newlen
-
len
;
return
newsh
->
buf
;
return
newsh
->
buf
;
}
}
/* Reallocate the sds string so that it has no free space at the end. The
* contained string remains not altered, but next concatenation operations
* will require a reallocation.
*
* After the call, the passed sds string is no longer valid and all the
* references must be substituted with the new pointer returned by the call. */
sds
sdsRemoveFreeSpace
(
sds
s
)
{
struct
sdshdr
*
sh
;
sh
=
(
void
*
)
(
s
-
(
sizeof
(
struct
sdshdr
)));
sh
=
zrealloc
(
sh
,
sizeof
(
struct
sdshdr
)
+
sh
->
len
+
1
);
sh
->
free
=
0
;
return
sh
->
buf
;
}
/* Return the total size of the allocation of the specifed sds string,
* including:
* 1) The sds header before the pointer.
* 2) The string.
* 3) The free buffer at the end if any.
* 4) The implicit null term.
*/
size_t
sdsAllocSize
(
sds
s
)
{
struct
sdshdr
*
sh
=
(
void
*
)
(
s
-
(
sizeof
(
struct
sdshdr
)));
return
sizeof
(
*
sh
)
+
sh
->
len
+
sh
->
free
+
1
;
}
/* Increment the sds length and decrements the left free space at the
* end of the string according to 'incr'. Also set the null term
* in the new end of the string.
*
* This function is used in order to fix the string length after the
* user calls sdsMakeRoomFor(), writes something after the end of
* the current string, and finally needs to set the new length.
*
* Note: it is possible to use a negative increment in order to
* right-trim the string.
*
* Usage example:
*
* Using sdsIncrLen() and sdsMakeRoomFor() it is possible to mount the
* following schema, to cat bytes coming from the kernel to the end of an
* sds string without copying into an intermediate buffer:
*
* oldlen = sdslen(s);
* s = sdsMakeRoomFor(s, BUFFER_SIZE);
* nread = read(fd, s+oldlen, BUFFER_SIZE);
* ... check for nread <= 0 and handle it ...
* sdsIncrLen(s, nread);
*/
void
sdsIncrLen
(
sds
s
,
int
incr
)
{
struct
sdshdr
*
sh
=
(
void
*
)
(
s
-
(
sizeof
(
struct
sdshdr
)));
assert
(
sh
->
free
>=
incr
);
sh
->
len
+=
incr
;
sh
->
free
-=
incr
;
assert
(
sh
->
free
>=
0
);
s
[
sh
->
len
]
=
'\0'
;
}
/* Grow the sds to have the specified length. Bytes that were not part of
/* Grow the sds to have the specified length. Bytes that were not part of
* the original length of the sds will be set to zero. */
* the original length of the sds will be set to zero.
*
* if the specified length is smaller than the current length, no operation
* is performed. */
sds
sdsgrowzero
(
sds
s
,
size_t
len
)
{
sds
sdsgrowzero
(
sds
s
,
size_t
len
)
{
struct
sdshdr
*
sh
=
(
void
*
)(
s
-
(
sizeof
(
struct
sdshdr
)));
struct
sdshdr
*
sh
=
(
void
*
)(
s
-
(
sizeof
(
struct
sdshdr
)));
size_t
totlen
,
curlen
=
sh
->
len
;
size_t
totlen
,
curlen
=
sh
->
len
;
...
@@ -124,6 +229,11 @@ sds sdsgrowzero(sds s, size_t len) {
...
@@ -124,6 +229,11 @@ sds sdsgrowzero(sds s, size_t len) {
return
s
;
return
s
;
}
}
/* Append the specified binary-safe string pointed by 't' of 'len' bytes to the
* end of the specified sds string 's'.
*
* After the call, the passed sds string is no longer valid and all the
* references must be substituted with the new pointer returned by the call. */
sds
sdscatlen
(
sds
s
,
const
void
*
t
,
size_t
len
)
{
sds
sdscatlen
(
sds
s
,
const
void
*
t
,
size_t
len
)
{
struct
sdshdr
*
sh
;
struct
sdshdr
*
sh
;
size_t
curlen
=
sdslen
(
s
);
size_t
curlen
=
sdslen
(
s
);
...
@@ -138,11 +248,25 @@ sds sdscatlen(sds s, const void *t, size_t len) {
...
@@ -138,11 +248,25 @@ sds sdscatlen(sds s, const void *t, size_t len) {
return
s
;
return
s
;
}
}
/* Append the specified null termianted C string to the sds string 's'.
*
* After the call, the passed sds string is no longer valid and all the
* references must be substituted with the new pointer returned by the call. */
sds
sdscat
(
sds
s
,
const
char
*
t
)
{
sds
sdscat
(
sds
s
,
const
char
*
t
)
{
return
sdscatlen
(
s
,
t
,
strlen
(
t
));
return
sdscatlen
(
s
,
t
,
strlen
(
t
));
}
}
sds
sdscpylen
(
sds
s
,
char
*
t
,
size_t
len
)
{
/* Append the specified sds 't' to the existing sds 's'.
*
* After the call, the modified sds string is no longer valid and all the
* references must be substituted with the new pointer returned by the call. */
sds
sdscatsds
(
sds
s
,
const
sds
t
)
{
return
sdscatlen
(
s
,
t
,
sdslen
(
t
));
}
/* Destructively modify the sds string 's' to hold the specified binary
* safe string pointed by 't' of length 'len' bytes. */
sds
sdscpylen
(
sds
s
,
const
char
*
t
,
size_t
len
)
{
struct
sdshdr
*
sh
=
(
void
*
)
(
s
-
(
sizeof
(
struct
sdshdr
)));
struct
sdshdr
*
sh
=
(
void
*
)
(
s
-
(
sizeof
(
struct
sdshdr
)));
size_t
totlen
=
sh
->
free
+
sh
->
len
;
size_t
totlen
=
sh
->
free
+
sh
->
len
;
...
@@ -159,37 +283,52 @@ sds sdscpylen(sds s, char *t, size_t len) {
...
@@ -159,37 +283,52 @@ sds sdscpylen(sds s, char *t, size_t len) {
return
s
;
return
s
;
}
}
sds
sdscpy
(
sds
s
,
char
*
t
)
{
/* Like sdscpylen() but 't' must be a null-termined string so that the length
* of the string is obtained with strlen(). */
sds
sdscpy
(
sds
s
,
const
char
*
t
)
{
return
sdscpylen
(
s
,
t
,
strlen
(
t
));
return
sdscpylen
(
s
,
t
,
strlen
(
t
));
}
}
/* Like sdscatpritf() but gets va_list instead of being variadic. */
sds
sdscatvprintf
(
sds
s
,
const
char
*
fmt
,
va_list
ap
)
{
sds
sdscatvprintf
(
sds
s
,
const
char
*
fmt
,
va_list
ap
)
{
va_list
cpy
;
va_list
cpy
;
char
*
buf
,
*
t
;
char
*
buf
,
*
t
;
size_t
buflen
=
16
;
size_t
buflen
=
16
;
while
(
1
)
{
while
(
1
)
{
buf
=
malloc
(
buflen
);
buf
=
zmalloc
(
buflen
);
#ifdef SDS_ABORT_ON_OOM
if
(
buf
==
NULL
)
sdsOomAbort
();
#else
if
(
buf
==
NULL
)
return
NULL
;
if
(
buf
==
NULL
)
return
NULL
;
#endif
buf
[
buflen
-
2
]
=
'\0'
;
buf
[
buflen
-
2
]
=
'\0'
;
va_copy
(
cpy
,
ap
);
va_copy
(
cpy
,
ap
);
vsnprintf
(
buf
,
buflen
,
fmt
,
cpy
);
vsnprintf
(
buf
,
buflen
,
fmt
,
cpy
);
if
(
buf
[
buflen
-
2
]
!=
'\0'
)
{
if
(
buf
[
buflen
-
2
]
!=
'\0'
)
{
free
(
buf
);
z
free
(
buf
);
buflen
*=
2
;
buflen
*=
2
;
continue
;
continue
;
}
}
break
;
break
;
}
}
t
=
sdscat
(
s
,
buf
);
t
=
sdscat
(
s
,
buf
);
free
(
buf
);
z
free
(
buf
);
return
t
;
return
t
;
}
}
/* Append to the sds string 's' a string obtained using printf-alike format
* specifier.
*
* After the call, the modified sds string is no longer valid and all the
* references must be substituted with the new pointer returned by the call.
*
* Example:
*
* s = sdsempty("Sum is: ");
* s = sdscatprintf(s,"%d+%d = %d",a,b,a+b).
*
* Often you need to create a string from scratch with the printf-alike
* format. When this is the need, just use sdsempty() as the target string:
*
* s = sdscatprintf(sdsempty(), "... your format ...", args);
*/
sds
sdscatprintf
(
sds
s
,
const
char
*
fmt
,
...)
{
sds
sdscatprintf
(
sds
s
,
const
char
*
fmt
,
...)
{
va_list
ap
;
va_list
ap
;
char
*
t
;
char
*
t
;
...
@@ -199,6 +338,20 @@ sds sdscatprintf(sds s, const char *fmt, ...) {
...
@@ -199,6 +338,20 @@ sds sdscatprintf(sds s, const char *fmt, ...) {
return
t
;
return
t
;
}
}
/* Remove the part of the string from left and from right composed just of
* contiguous characters found in 'cset', that is a null terminted C string.
*
* After the call, the modified sds string is no longer valid and all the
* references must be substituted with the new pointer returned by the call.
*
* Example:
*
* s = sdsnew("AA...AA.a.aa.aHelloWorld :::");
* s = sdstrim(s,"A. :");
* printf("%s\n", s);
*
* Output will be just "Hello World".
*/
sds
sdstrim
(
sds
s
,
const
char
*
cset
)
{
sds
sdstrim
(
sds
s
,
const
char
*
cset
)
{
struct
sdshdr
*
sh
=
(
void
*
)
(
s
-
(
sizeof
(
struct
sdshdr
)));
struct
sdshdr
*
sh
=
(
void
*
)
(
s
-
(
sizeof
(
struct
sdshdr
)));
char
*
start
,
*
end
,
*
sp
,
*
ep
;
char
*
start
,
*
end
,
*
sp
,
*
ep
;
...
@@ -216,11 +369,27 @@ sds sdstrim(sds s, const char *cset) {
...
@@ -216,11 +369,27 @@ sds sdstrim(sds s, const char *cset) {
return
s
;
return
s
;
}
}
sds
sdsrange
(
sds
s
,
int
start
,
int
end
)
{
/* Turn the string into a smaller (or equal) string containing only the
* substring specified by the 'start' and 'end' indexes.
*
* start and end can be negative, where -1 means the last character of the
* string, -2 the penultimate character, and so forth.
*
* The interval is inclusive, so the start and end characters will be part
* of the resulting string.
*
* The string is modified in-place.
*
* Example:
*
* s = sdsnew("Hello World");
* sdstrim(s,1,-1); => "ello Worl"
*/
void
sdsrange
(
sds
s
,
int
start
,
int
end
)
{
struct
sdshdr
*
sh
=
(
void
*
)
(
s
-
(
sizeof
(
struct
sdshdr
)));
struct
sdshdr
*
sh
=
(
void
*
)
(
s
-
(
sizeof
(
struct
sdshdr
)));
size_t
newlen
,
len
=
sdslen
(
s
);
size_t
newlen
,
len
=
sdslen
(
s
);
if
(
len
==
0
)
return
s
;
if
(
len
==
0
)
return
;
if
(
start
<
0
)
{
if
(
start
<
0
)
{
start
=
len
+
start
;
start
=
len
+
start
;
if
(
start
<
0
)
start
=
0
;
if
(
start
<
0
)
start
=
0
;
...
@@ -244,22 +413,34 @@ sds sdsrange(sds s, int start, int end) {
...
@@ -244,22 +413,34 @@ sds sdsrange(sds s, int start, int end) {
sh
->
buf
[
newlen
]
=
0
;
sh
->
buf
[
newlen
]
=
0
;
sh
->
free
=
sh
->
free
+
(
sh
->
len
-
newlen
);
sh
->
free
=
sh
->
free
+
(
sh
->
len
-
newlen
);
sh
->
len
=
newlen
;
sh
->
len
=
newlen
;
return
s
;
}
}
/* Apply tolower() to every character of the sds string 's'. */
void
sdstolower
(
sds
s
)
{
void
sdstolower
(
sds
s
)
{
int
len
=
sdslen
(
s
),
j
;
int
len
=
sdslen
(
s
),
j
;
for
(
j
=
0
;
j
<
len
;
j
++
)
s
[
j
]
=
tolower
(
s
[
j
]);
for
(
j
=
0
;
j
<
len
;
j
++
)
s
[
j
]
=
tolower
(
s
[
j
]);
}
}
/* Apply toupper() to every character of the sds string 's'. */
void
sdstoupper
(
sds
s
)
{
void
sdstoupper
(
sds
s
)
{
int
len
=
sdslen
(
s
),
j
;
int
len
=
sdslen
(
s
),
j
;
for
(
j
=
0
;
j
<
len
;
j
++
)
s
[
j
]
=
toupper
(
s
[
j
]);
for
(
j
=
0
;
j
<
len
;
j
++
)
s
[
j
]
=
toupper
(
s
[
j
]);
}
}
int
sdscmp
(
sds
s1
,
sds
s2
)
{
/* Compare two sds strings s1 and s2 with memcmp().
*
* Return value:
*
* 1 if s1 > s2.
* -1 if s1 < s2.
* 0 if s1 and s2 are exactly the same binary string.
*
* If two strings share exactly the same prefix, but one of the two has
* additional characters, the longer string is considered to be greater than
* the smaller one. */
int
sdscmp
(
const
sds
s1
,
const
sds
s2
)
{
size_t
l1
,
l2
,
minlen
;
size_t
l1
,
l2
,
minlen
;
int
cmp
;
int
cmp
;
...
@@ -287,14 +468,15 @@ int sdscmp(sds s1, sds s2) {
...
@@ -287,14 +468,15 @@ int sdscmp(sds s1, sds s2) {
* requires length arguments. sdssplit() is just the
* requires length arguments. sdssplit() is just the
* same function but for zero-terminated strings.
* same function but for zero-terminated strings.
*/
*/
sds
*
sdssplitlen
(
char
*
s
,
int
len
,
char
*
sep
,
int
seplen
,
int
*
count
)
{
sds
*
sdssplitlen
(
const
char
*
s
,
int
len
,
const
char
*
sep
,
int
seplen
,
int
*
count
)
{
int
elements
=
0
,
slots
=
5
,
start
=
0
,
j
;
int
elements
=
0
,
slots
=
5
,
start
=
0
,
j
;
sds
*
tokens
;
if
(
seplen
<
1
||
len
<
0
)
return
NULL
;
tokens
=
zmalloc
(
sizeof
(
sds
)
*
slots
);
if
(
tokens
==
NULL
)
return
NULL
;
sds
*
tokens
=
malloc
(
sizeof
(
sds
)
*
slots
);
#ifdef SDS_ABORT_ON_OOM
if
(
tokens
==
NULL
)
sdsOomAbort
();
#endif
if
(
seplen
<
1
||
len
<
0
||
tokens
==
NULL
)
return
NULL
;
if
(
len
==
0
)
{
if
(
len
==
0
)
{
*
count
=
0
;
*
count
=
0
;
return
tokens
;
return
tokens
;
...
@@ -305,26 +487,14 @@ sds *sdssplitlen(char *s, int len, char *sep, int seplen, int *count) {
...
@@ -305,26 +487,14 @@ sds *sdssplitlen(char *s, int len, char *sep, int seplen, int *count) {
sds
*
newtokens
;
sds
*
newtokens
;
slots
*=
2
;
slots
*=
2
;
newtokens
=
realloc
(
tokens
,
sizeof
(
sds
)
*
slots
);
newtokens
=
zrealloc
(
tokens
,
sizeof
(
sds
)
*
slots
);
if
(
newtokens
==
NULL
)
{
if
(
newtokens
==
NULL
)
goto
cleanup
;
#ifdef SDS_ABORT_ON_OOM
sdsOomAbort
();
#else
goto
cleanup
;
#endif
}
tokens
=
newtokens
;
tokens
=
newtokens
;
}
}
/* search the separator */
/* search the separator */
if
((
seplen
==
1
&&
*
(
s
+
j
)
==
sep
[
0
])
||
(
memcmp
(
s
+
j
,
sep
,
seplen
)
==
0
))
{
if
((
seplen
==
1
&&
*
(
s
+
j
)
==
sep
[
0
])
||
(
memcmp
(
s
+
j
,
sep
,
seplen
)
==
0
))
{
tokens
[
elements
]
=
sdsnewlen
(
s
+
start
,
j
-
start
);
tokens
[
elements
]
=
sdsnewlen
(
s
+
start
,
j
-
start
);
if
(
tokens
[
elements
]
==
NULL
)
{
if
(
tokens
[
elements
]
==
NULL
)
goto
cleanup
;
#ifdef SDS_ABORT_ON_OOM
sdsOomAbort
();
#else
goto
cleanup
;
#endif
}
elements
++
;
elements
++
;
start
=
j
+
seplen
;
start
=
j
+
seplen
;
j
=
j
+
seplen
-
1
;
/* skip the separator */
j
=
j
+
seplen
-
1
;
/* skip the separator */
...
@@ -332,35 +502,33 @@ sds *sdssplitlen(char *s, int len, char *sep, int seplen, int *count) {
...
@@ -332,35 +502,33 @@ sds *sdssplitlen(char *s, int len, char *sep, int seplen, int *count) {
}
}
/* Add the final element. We are sure there is room in the tokens array. */
/* Add the final element. We are sure there is room in the tokens array. */
tokens
[
elements
]
=
sdsnewlen
(
s
+
start
,
len
-
start
);
tokens
[
elements
]
=
sdsnewlen
(
s
+
start
,
len
-
start
);
if
(
tokens
[
elements
]
==
NULL
)
{
if
(
tokens
[
elements
]
==
NULL
)
goto
cleanup
;
#ifdef SDS_ABORT_ON_OOM
sdsOomAbort
();
#else
goto
cleanup
;
#endif
}
elements
++
;
elements
++
;
*
count
=
elements
;
*
count
=
elements
;
return
tokens
;
return
tokens
;
#ifndef SDS_ABORT_ON_OOM
cleanup:
cleanup:
{
{
int
i
;
int
i
;
for
(
i
=
0
;
i
<
elements
;
i
++
)
sdsfree
(
tokens
[
i
]);
for
(
i
=
0
;
i
<
elements
;
i
++
)
sdsfree
(
tokens
[
i
]);
free
(
tokens
);
zfree
(
tokens
);
*
count
=
0
;
return
NULL
;
return
NULL
;
}
}
#endif
}
}
/* Free the result returned by sdssplitlen(), or do nothing if 'tokens' is NULL. */
void
sdsfreesplitres
(
sds
*
tokens
,
int
count
)
{
void
sdsfreesplitres
(
sds
*
tokens
,
int
count
)
{
if
(
!
tokens
)
return
;
if
(
!
tokens
)
return
;
while
(
count
--
)
while
(
count
--
)
sdsfree
(
tokens
[
count
]);
sdsfree
(
tokens
[
count
]);
free
(
tokens
);
z
free
(
tokens
);
}
}
/* Create an sds string from a long long value. It is much faster than:
*
* sdscatprintf(sdsempty(),"%lld\n", value);
*/
sds
sdsfromlonglong
(
long
long
value
)
{
sds
sdsfromlonglong
(
long
long
value
)
{
char
buf
[
32
],
*
p
;
char
buf
[
32
],
*
p
;
unsigned
long
long
v
;
unsigned
long
long
v
;
...
@@ -376,10 +544,14 @@ sds sdsfromlonglong(long long value) {
...
@@ -376,10 +544,14 @@ sds sdsfromlonglong(long long value) {
return
sdsnewlen
(
p
,
32
-
(
p
-
buf
));
return
sdsnewlen
(
p
,
32
-
(
p
-
buf
));
}
}
sds
sdscatrepr
(
sds
s
,
char
*
p
,
size_t
len
)
{
/* Append to the sds string "s" an escaped string representation where
* all the non-printable characters (tested with isprint()) are turned into
* escapes in the form "\n\r\a...." or "\x<hex-number>".
*
* After the call, the modified sds string is no longer valid and all the
* references must be substituted with the new pointer returned by the call. */
sds
sdscatrepr
(
sds
s
,
const
char
*
p
,
size_t
len
)
{
s
=
sdscatlen
(
s
,
"
\"
"
,
1
);
s
=
sdscatlen
(
s
,
"
\"
"
,
1
);
if
(
s
==
NULL
)
return
NULL
;
while
(
len
--
)
{
while
(
len
--
)
{
switch
(
*
p
)
{
switch
(
*
p
)
{
case
'\\'
:
case
'\\'
:
...
@@ -399,27 +571,64 @@ sds sdscatrepr(sds s, char *p, size_t len) {
...
@@ -399,27 +571,64 @@ sds sdscatrepr(sds s, char *p, size_t len) {
break
;
break
;
}
}
p
++
;
p
++
;
if
(
s
==
NULL
)
return
NULL
;
}
}
return
sdscatlen
(
s
,
"
\"
"
,
1
);
return
sdscatlen
(
s
,
"
\"
"
,
1
);
}
}
/* Helper function for sdssplitargs() that returns non zero if 'c'
* is a valid hex digit. */
int
is_hex_digit
(
char
c
)
{
return
(
c
>=
'0'
&&
c
<=
'9'
)
||
(
c
>=
'a'
&&
c
<=
'f'
)
||
(
c
>=
'A'
&&
c
<=
'F'
);
}
/* Helper function for sdssplitargs() that converts an hex digit into an
* integer from 0 to 15 */
int
hex_digit_to_int
(
char
c
)
{
switch
(
c
)
{
case
'0'
:
return
0
;
case
'1'
:
return
1
;
case
'2'
:
return
2
;
case
'3'
:
return
3
;
case
'4'
:
return
4
;
case
'5'
:
return
5
;
case
'6'
:
return
6
;
case
'7'
:
return
7
;
case
'8'
:
return
8
;
case
'9'
:
return
9
;
case
'a'
:
case
'A'
:
return
10
;
case
'b'
:
case
'B'
:
return
11
;
case
'c'
:
case
'C'
:
return
12
;
case
'd'
:
case
'D'
:
return
13
;
case
'e'
:
case
'E'
:
return
14
;
case
'f'
:
case
'F'
:
return
15
;
default:
return
0
;
}
}
/* Split a line into arguments, where every argument can be in the
/* Split a line into arguments, where every argument can be in the
* following programming-language REPL-alike form:
* following programming-language REPL-alike form:
*
*
* foo bar "newline are supported\n" and "\xff\x00otherstuff"
* foo bar "newline are supported\n" and "\xff\x00otherstuff"
*
*
* The number of arguments is stored into *argc, and an array
* The number of arguments is stored into *argc, and an array
* of sds is returned. The caller should sdsfree() all the returned
* of sds is returned.
* strings and finally free() the array itself.
*
* The caller should free the resulting array of sds strings with
* sdsfreesplitres().
*
*
* Note that sdscatrepr() is able to convert back a string into
* Note that sdscatrepr() is able to convert back a string into
* a quoted string in the same format sdssplitargs() is able to parse.
* a quoted string in the same format sdssplitargs() is able to parse.
*
* The function returns the allocated tokens on success, even when the
* input string is empty, or NULL if the input contains unbalanced
* quotes or closed quotes followed by non space characters
* as in: "foo"bar or "foo'
*/
*/
sds
*
sdssplitargs
(
char
*
line
,
int
*
argc
)
{
sds
*
sdssplitargs
(
const
char
*
line
,
int
*
argc
)
{
char
*
p
=
line
;
const
char
*
p
=
line
;
char
*
current
=
NULL
;
char
*
current
=
NULL
;
char
**
vector
=
NULL
,
**
_vector
=
NULL
;
char
**
vector
=
NULL
;
*
argc
=
0
;
*
argc
=
0
;
while
(
1
)
{
while
(
1
)
{
...
@@ -427,17 +636,24 @@ sds *sdssplitargs(char *line, int *argc) {
...
@@ -427,17 +636,24 @@ sds *sdssplitargs(char *line, int *argc) {
while
(
*
p
&&
isspace
(
*
p
))
p
++
;
while
(
*
p
&&
isspace
(
*
p
))
p
++
;
if
(
*
p
)
{
if
(
*
p
)
{
/* get a token */
/* get a token */
int
inq
=
0
;
/* set to 1 if we are in "quotes" */
int
inq
=
0
;
/* set to 1 if we are in "quotes" */
int
insq
=
0
;
/* set to 1 if we are in 'single quotes' */
int
done
=
0
;
int
done
=
0
;
if
(
current
==
NULL
)
{
if
(
current
==
NULL
)
current
=
sdsempty
();
current
=
sdsempty
();
if
(
current
==
NULL
)
goto
err
;
}
while
(
!
done
)
{
while
(
!
done
)
{
if
(
inq
)
{
if
(
inq
)
{
if
(
*
p
==
'\\'
&&
*
(
p
+
1
))
{
if
(
*
p
==
'\\'
&&
*
(
p
+
1
)
==
'x'
&&
is_hex_digit
(
*
(
p
+
2
))
&&
is_hex_digit
(
*
(
p
+
3
)))
{
unsigned
char
byte
;
byte
=
(
hex_digit_to_int
(
*
(
p
+
2
))
*
16
)
+
hex_digit_to_int
(
*
(
p
+
3
));
current
=
sdscatlen
(
current
,(
char
*
)
&
byte
,
1
);
p
+=
3
;
}
else
if
(
*
p
==
'\\'
&&
*
(
p
+
1
))
{
char
c
;
char
c
;
p
++
;
p
++
;
...
@@ -451,7 +667,23 @@ sds *sdssplitargs(char *line, int *argc) {
...
@@ -451,7 +667,23 @@ sds *sdssplitargs(char *line, int *argc) {
}
}
current
=
sdscatlen
(
current
,
&
c
,
1
);
current
=
sdscatlen
(
current
,
&
c
,
1
);
}
else
if
(
*
p
==
'"'
)
{
}
else
if
(
*
p
==
'"'
)
{
/* closing quote must be followed by a space */
/* closing quote must be followed by a space or
* nothing at all. */
if
(
*
(
p
+
1
)
&&
!
isspace
(
*
(
p
+
1
)))
goto
err
;
done
=
1
;
}
else
if
(
!*
p
)
{
/* unterminated quotes */
goto
err
;
}
else
{
current
=
sdscatlen
(
current
,
p
,
1
);
}
}
else
if
(
insq
)
{
if
(
*
p
==
'\\'
&&
*
(
p
+
1
)
==
'\''
)
{
p
++
;
current
=
sdscatlen
(
current
,
"'"
,
1
);
}
else
if
(
*
p
==
'\''
)
{
/* closing quote must be followed by a space or
* nothing at all. */
if
(
*
(
p
+
1
)
&&
!
isspace
(
*
(
p
+
1
)))
goto
err
;
if
(
*
(
p
+
1
)
&&
!
isspace
(
*
(
p
+
1
)))
goto
err
;
done
=
1
;
done
=
1
;
}
else
if
(
!*
p
)
{
}
else
if
(
!*
p
)
{
...
@@ -472,23 +704,24 @@ sds *sdssplitargs(char *line, int *argc) {
...
@@ -472,23 +704,24 @@ sds *sdssplitargs(char *line, int *argc) {
case
'"'
:
case
'"'
:
inq
=
1
;
inq
=
1
;
break
;
break
;
case
'\''
:
insq
=
1
;
break
;
default:
default:
current
=
sdscatlen
(
current
,
p
,
1
);
current
=
sdscatlen
(
current
,
p
,
1
);
break
;
break
;
}
}
}
}
if
(
*
p
)
p
++
;
if
(
*
p
)
p
++
;
if
(
current
==
NULL
)
goto
err
;
}
}
/* add the token to the vector */
/* add the token to the vector */
_vector
=
realloc
(
vector
,((
*
argc
)
+
1
)
*
sizeof
(
char
*
));
vector
=
zrealloc
(
vector
,((
*
argc
)
+
1
)
*
sizeof
(
char
*
));
if
(
_vector
==
NULL
)
goto
err
;
vector
=
_vector
;
vector
[
*
argc
]
=
current
;
vector
[
*
argc
]
=
current
;
(
*
argc
)
++
;
(
*
argc
)
++
;
current
=
NULL
;
current
=
NULL
;
}
else
{
}
else
{
/* Even on empty input string return something not NULL. */
if
(
vector
==
NULL
)
vector
=
zmalloc
(
sizeof
(
void
*
));
return
vector
;
return
vector
;
}
}
}
}
...
@@ -496,30 +729,55 @@ sds *sdssplitargs(char *line, int *argc) {
...
@@ -496,30 +729,55 @@ sds *sdssplitargs(char *line, int *argc) {
err:
err:
while
((
*
argc
)
--
)
while
((
*
argc
)
--
)
sdsfree
(
vector
[
*
argc
]);
sdsfree
(
vector
[
*
argc
]);
if
(
vector
!=
NULL
)
free
(
vector
);
zfree
(
vector
);
if
(
current
!=
NULL
)
sdsfree
(
current
);
if
(
current
)
sdsfree
(
current
);
*
argc
=
0
;
return
NULL
;
return
NULL
;
}
}
/* Modify the string substituting all the occurrences of the set of
* characters specified in the 'from' string to the corresponding character
* in the 'to' array.
*
* For instance: sdsmapchars(mystring, "ho", "01", 2)
* will have the effect of turning the string "hello" into "0ell1".
*
* The function returns the sds string pointer, that is always the same
* as the input pointer since no resize is needed. */
sds
sdsmapchars
(
sds
s
,
const
char
*
from
,
const
char
*
to
,
size_t
setlen
)
{
size_t
j
,
i
,
l
=
sdslen
(
s
);
for
(
j
=
0
;
j
<
l
;
j
++
)
{
for
(
i
=
0
;
i
<
setlen
;
i
++
)
{
if
(
s
[
j
]
==
from
[
i
])
{
s
[
j
]
=
to
[
i
];
break
;
}
}
}
return
s
;
}
/* Join an array of C strings using the specified separator (also a C string).
* Returns the result as an sds string. */
sds
sdsjoin
(
char
**
argv
,
int
argc
,
char
*
sep
)
{
sds
join
=
sdsempty
();
int
j
;
for
(
j
=
0
;
j
<
argc
;
j
++
)
{
join
=
sdscat
(
join
,
argv
[
j
]);
if
(
j
!=
argc
-
1
)
join
=
sdscat
(
join
,
sep
);
}
return
join
;
}
#ifdef SDS_TEST_MAIN
#ifdef SDS_TEST_MAIN
#include <stdio.h>
#include <stdio.h>
#include "testhelp.h"
int
__failed_tests
=
0
;
int
__test_num
=
0
;
#define test_cond(descr,_c) do { \
__test_num++; printf("%d - %s: ", __test_num, descr); \
if(_c) printf("PASSED\n"); else {printf("FAILED\n"); __failed_tests++;} \
} while(0);
#define test_report() do { \
printf("%d tests, %d passed, %d failed\n", __test_num, \
__test_num-__failed_tests, __failed_tests); \
if (__failed_tests) { \
printf("=== WARNING === We have failed tests here...\n"); \
} \
} while(0);
int
main
(
void
)
{
int
main
(
void
)
{
{
{
struct
sdshdr
*
sh
;
sds
x
=
sdsnew
(
"foo"
),
y
;
sds
x
=
sdsnew
(
"foo"
),
y
;
test_cond
(
"Create a string and obtain the length"
,
test_cond
(
"Create a string and obtain the length"
,
...
@@ -599,7 +857,26 @@ int main(void) {
...
@@ -599,7 +857,26 @@ int main(void) {
x
=
sdsnew
(
"aar"
);
x
=
sdsnew
(
"aar"
);
y
=
sdsnew
(
"bar"
);
y
=
sdsnew
(
"bar"
);
test_cond
(
"sdscmp(bar,bar)"
,
sdscmp
(
x
,
y
)
<
0
)
test_cond
(
"sdscmp(bar,bar)"
,
sdscmp
(
x
,
y
)
<
0
)
{
int
oldfree
;
sdsfree
(
x
);
x
=
sdsnew
(
"0"
);
sh
=
(
void
*
)
(
x
-
(
sizeof
(
struct
sdshdr
)));
test_cond
(
"sdsnew() free/len buffers"
,
sh
->
len
==
1
&&
sh
->
free
==
0
);
x
=
sdsMakeRoomFor
(
x
,
1
);
sh
=
(
void
*
)
(
x
-
(
sizeof
(
struct
sdshdr
)));
test_cond
(
"sdsMakeRoomFor()"
,
sh
->
len
==
1
&&
sh
->
free
>
0
);
oldfree
=
sh
->
free
;
x
[
1
]
=
'1'
;
sdsIncrLen
(
x
,
1
);
test_cond
(
"sdsIncrLen() -- content"
,
x
[
0
]
==
'0'
&&
x
[
1
]
==
'1'
);
test_cond
(
"sdsIncrLen() -- len"
,
sh
->
len
==
2
);
test_cond
(
"sdsIncrLen() -- free"
,
sh
->
free
==
oldfree
-
1
);
}
}
}
test_report
()
test_report
()
return
0
;
}
}
#endif
#endif
deps/hiredis/sds.h
View file @
aea80205
...
@@ -31,6 +31,8 @@
...
@@ -31,6 +31,8 @@
#ifndef __SDS_H
#ifndef __SDS_H
#define __SDS_H
#define __SDS_H
#define SDS_MAX_PREALLOC (1024*1024)
#include <sys/types.h>
#include <sys/types.h>
#include <stdarg.h>
#include <stdarg.h>
...
@@ -54,16 +56,17 @@ static inline size_t sdsavail(const sds s) {
...
@@ -54,16 +56,17 @@ static inline size_t sdsavail(const sds s) {
sds
sdsnewlen
(
const
void
*
init
,
size_t
initlen
);
sds
sdsnewlen
(
const
void
*
init
,
size_t
initlen
);
sds
sdsnew
(
const
char
*
init
);
sds
sdsnew
(
const
char
*
init
);
sds
sdsempty
(
void
);
sds
sdsempty
();
size_t
sdslen
(
const
sds
s
);
size_t
sdslen
(
const
sds
s
);
sds
sdsdup
(
const
sds
s
);
sds
sdsdup
(
const
sds
s
);
void
sdsfree
(
sds
s
);
void
sdsfree
(
sds
s
);
size_t
sdsavail
(
sds
s
);
size_t
sdsavail
(
const
sds
s
);
sds
sdsgrowzero
(
sds
s
,
size_t
len
);
sds
sdsgrowzero
(
sds
s
,
size_t
len
);
sds
sdscatlen
(
sds
s
,
const
void
*
t
,
size_t
len
);
sds
sdscatlen
(
sds
s
,
const
void
*
t
,
size_t
len
);
sds
sdscat
(
sds
s
,
const
char
*
t
);
sds
sdscat
(
sds
s
,
const
char
*
t
);
sds
sdscpylen
(
sds
s
,
char
*
t
,
size_t
len
);
sds
sdscatsds
(
sds
s
,
const
sds
t
);
sds
sdscpy
(
sds
s
,
char
*
t
);
sds
sdscpylen
(
sds
s
,
const
char
*
t
,
size_t
len
);
sds
sdscpy
(
sds
s
,
const
char
*
t
);
sds
sdscatvprintf
(
sds
s
,
const
char
*
fmt
,
va_list
ap
);
sds
sdscatvprintf
(
sds
s
,
const
char
*
fmt
,
va_list
ap
);
#ifdef __GNUC__
#ifdef __GNUC__
...
@@ -74,15 +77,24 @@ sds sdscatprintf(sds s, const char *fmt, ...);
...
@@ -74,15 +77,24 @@ sds sdscatprintf(sds s, const char *fmt, ...);
#endif
#endif
sds
sdstrim
(
sds
s
,
const
char
*
cset
);
sds
sdstrim
(
sds
s
,
const
char
*
cset
);
sds
sdsrange
(
sds
s
,
int
start
,
int
end
);
void
sdsrange
(
sds
s
,
int
start
,
int
end
);
void
sdsupdatelen
(
sds
s
);
void
sdsupdatelen
(
sds
s
);
int
sdscmp
(
sds
s1
,
sds
s2
);
void
sdsclear
(
sds
s
);
sds
*
sdssplitlen
(
char
*
s
,
int
len
,
char
*
sep
,
int
seplen
,
int
*
count
);
int
sdscmp
(
const
sds
s1
,
const
sds
s2
);
sds
*
sdssplitlen
(
const
char
*
s
,
int
len
,
const
char
*
sep
,
int
seplen
,
int
*
count
);
void
sdsfreesplitres
(
sds
*
tokens
,
int
count
);
void
sdsfreesplitres
(
sds
*
tokens
,
int
count
);
void
sdstolower
(
sds
s
);
void
sdstolower
(
sds
s
);
void
sdstoupper
(
sds
s
);
void
sdstoupper
(
sds
s
);
sds
sdsfromlonglong
(
long
long
value
);
sds
sdsfromlonglong
(
long
long
value
);
sds
sdscatrepr
(
sds
s
,
char
*
p
,
size_t
len
);
sds
sdscatrepr
(
sds
s
,
const
char
*
p
,
size_t
len
);
sds
*
sdssplitargs
(
char
*
line
,
int
*
argc
);
sds
*
sdssplitargs
(
const
char
*
line
,
int
*
argc
);
sds
sdsmapchars
(
sds
s
,
const
char
*
from
,
const
char
*
to
,
size_t
setlen
);
sds
sdsjoin
(
char
**
argv
,
int
argc
,
char
*
sep
);
/* Low level functions exposed to the user API */
sds
sdsMakeRoomFor
(
sds
s
,
size_t
addlen
);
void
sdsIncrLen
(
sds
s
,
int
incr
);
sds
sdsRemoveFreeSpace
(
sds
s
);
size_t
sdsAllocSize
(
sds
s
);
#endif
#endif
deps/hiredis/zmalloc.h
0 → 100644
View file @
aea80205
/* Drop in replacement for zmalloc.h in order to just use libc malloc without
* any wrappering. */
#ifndef ZMALLOC_H
#define ZMALLOC_H
#define zmalloc malloc
#define zrealloc realloc
#define zcalloc(x) calloc(x,1)
#define zfree free
#define zstrdup strdup
#endif
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment