Line | Count | Source (jump to first uncovered line) |
1 | | /* SDSLib 2.0 -- A C dynamic strings library |
2 | | * |
3 | | * Copyright (c) 2006-2015, Salvatore Sanfilippo <antirez at gmail dot com> |
4 | | * Copyright (c) 2015, Oran Agra |
5 | | * Copyright (c) 2015, Redis Labs, Inc |
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 __SDS_H |
34 | | #define __SDS_H |
35 | | |
36 | 10 | #define SDS_MAX_PREALLOC (1024*1024) |
37 | | #ifdef _MSC_VER |
38 | | typedef long long ssize_t; |
39 | | #define SSIZE_MAX (LLONG_MAX >> 1) |
40 | | #ifndef __clang__ |
41 | | #define __attribute__(x) |
42 | | #endif |
43 | | #endif |
44 | | |
45 | | #include <sys/types.h> |
46 | | #include <stdarg.h> |
47 | | #include <stdint.h> |
48 | | |
49 | | typedef char *sds; |
50 | | |
51 | | /* Note: sdshdr5 is never used, we just access the flags byte directly. |
52 | | * However is here to document the layout of type 5 SDS strings. */ |
53 | | struct __attribute__ ((__packed__)) sdshdr5 { |
54 | | unsigned char flags; /* 3 lsb of type, and 5 msb of string length */ |
55 | | char buf[]; |
56 | | }; |
57 | | struct __attribute__ ((__packed__)) sdshdr8 { |
58 | | uint8_t len; /* used */ |
59 | | uint8_t alloc; /* excluding the header and null terminator */ |
60 | | unsigned char flags; /* 3 lsb of type, 5 unused bits */ |
61 | | char buf[]; |
62 | | }; |
63 | | struct __attribute__ ((__packed__)) sdshdr16 { |
64 | | uint16_t len; /* used */ |
65 | | uint16_t alloc; /* excluding the header and null terminator */ |
66 | | unsigned char flags; /* 3 lsb of type, 5 unused bits */ |
67 | | char buf[]; |
68 | | }; |
69 | | struct __attribute__ ((__packed__)) sdshdr32 { |
70 | | uint32_t len; /* used */ |
71 | | uint32_t alloc; /* excluding the header and null terminator */ |
72 | | unsigned char flags; /* 3 lsb of type, 5 unused bits */ |
73 | | char buf[]; |
74 | | }; |
75 | | struct __attribute__ ((__packed__)) sdshdr64 { |
76 | | uint64_t len; /* used */ |
77 | | uint64_t alloc; /* excluding the header and null terminator */ |
78 | | unsigned char flags; /* 3 lsb of type, 5 unused bits */ |
79 | | char buf[]; |
80 | | }; |
81 | | |
82 | 25 | #define SDS_TYPE_5 0 |
83 | 841 | #define SDS_TYPE_8 1 |
84 | 664 | #define SDS_TYPE_16 2 |
85 | 0 | #define SDS_TYPE_32 3 |
86 | 0 | #define SDS_TYPE_64 4 |
87 | 1.96k | #define SDS_TYPE_MASK 7 |
88 | 0 | #define SDS_TYPE_BITS 3 |
89 | 481 | #define SDS_HDR_VAR(T,s) struct sdshdr##T *sh = (struct sdshdr##T *)((s)-(sizeof(struct sdshdr##T))); |
90 | 985 | #define SDS_HDR(T,s) ((struct sdshdr##T *)((s)-(sizeof(struct sdshdr##T)))) |
91 | 0 | #define SDS_TYPE_5_LEN(f) ((f)>>SDS_TYPE_BITS) |
92 | | |
93 | 496 | static inline size_t sdslen(const sds s) { |
94 | 496 | unsigned char flags = s[-1]; |
95 | 496 | switch(flags&SDS_TYPE_MASK) { |
96 | 0 | case SDS_TYPE_5: |
97 | 0 | return SDS_TYPE_5_LEN(flags); |
98 | 274 | case SDS_TYPE_8: |
99 | 274 | return SDS_HDR(8,s)->len; |
100 | 222 | case SDS_TYPE_16: |
101 | 222 | return SDS_HDR(16,s)->len; |
102 | 0 | case SDS_TYPE_32: |
103 | 0 | return SDS_HDR(32,s)->len; |
104 | 0 | case SDS_TYPE_64: |
105 | 0 | return SDS_HDR(64,s)->len; |
106 | 496 | } |
107 | 0 | return 0; |
108 | 496 | } Unexecuted instantiation: format_command_fuzzer.c:sdslen Line | Count | Source | 93 | 8 | static inline size_t sdslen(const sds s) { | 94 | 8 | unsigned char flags = s[-1]; | 95 | 8 | switch(flags&SDS_TYPE_MASK) { | 96 | 0 | case SDS_TYPE_5: | 97 | 0 | return SDS_TYPE_5_LEN(flags); | 98 | 4 | case SDS_TYPE_8: | 99 | 4 | return SDS_HDR(8,s)->len; | 100 | 4 | case SDS_TYPE_16: | 101 | 4 | return SDS_HDR(16,s)->len; | 102 | 0 | case SDS_TYPE_32: | 103 | 0 | return SDS_HDR(32,s)->len; | 104 | 0 | case SDS_TYPE_64: | 105 | 0 | return SDS_HDR(64,s)->len; | 106 | 8 | } | 107 | 0 | return 0; | 108 | 8 | } |
Line | Count | Source | 93 | 488 | static inline size_t sdslen(const sds s) { | 94 | 488 | unsigned char flags = s[-1]; | 95 | 488 | switch(flags&SDS_TYPE_MASK) { | 96 | 0 | case SDS_TYPE_5: | 97 | 0 | return SDS_TYPE_5_LEN(flags); | 98 | 270 | case SDS_TYPE_8: | 99 | 270 | return SDS_HDR(8,s)->len; | 100 | 218 | case SDS_TYPE_16: | 101 | 218 | return SDS_HDR(16,s)->len; | 102 | 0 | case SDS_TYPE_32: | 103 | 0 | return SDS_HDR(32,s)->len; | 104 | 0 | case SDS_TYPE_64: | 105 | 0 | return SDS_HDR(64,s)->len; | 106 | 488 | } | 107 | 0 | return 0; | 108 | 488 | } |
Unexecuted instantiation: async.c:sdslen Unexecuted instantiation: read.c:sdslen Unexecuted instantiation: net.c:sdslen |
109 | | |
110 | 478 | static inline size_t sdsavail(const sds s) { |
111 | 478 | unsigned char flags = s[-1]; |
112 | 478 | switch(flags&SDS_TYPE_MASK) { |
113 | 0 | case SDS_TYPE_5: { |
114 | 0 | return 0; |
115 | 0 | } |
116 | 260 | case SDS_TYPE_8: { |
117 | 260 | SDS_HDR_VAR(8,s); |
118 | 260 | return sh->alloc - sh->len; |
119 | 0 | } |
120 | 218 | case SDS_TYPE_16: { |
121 | 218 | SDS_HDR_VAR(16,s); |
122 | 218 | return sh->alloc - sh->len; |
123 | 0 | } |
124 | 0 | case SDS_TYPE_32: { |
125 | 0 | SDS_HDR_VAR(32,s); |
126 | 0 | return sh->alloc - sh->len; |
127 | 0 | } |
128 | 0 | case SDS_TYPE_64: { |
129 | 0 | SDS_HDR_VAR(64,s); |
130 | 0 | return sh->alloc - sh->len; |
131 | 0 | } |
132 | 478 | } |
133 | 0 | return 0; |
134 | 478 | } Unexecuted instantiation: format_command_fuzzer.c:sdsavail Unexecuted instantiation: hiredis.c:sdsavail Line | Count | Source | 110 | 478 | static inline size_t sdsavail(const sds s) { | 111 | 478 | unsigned char flags = s[-1]; | 112 | 478 | switch(flags&SDS_TYPE_MASK) { | 113 | 0 | case SDS_TYPE_5: { | 114 | 0 | return 0; | 115 | 0 | } | 116 | 260 | case SDS_TYPE_8: { | 117 | 260 | SDS_HDR_VAR(8,s); | 118 | 260 | return sh->alloc - sh->len; | 119 | 0 | } | 120 | 218 | case SDS_TYPE_16: { | 121 | 218 | SDS_HDR_VAR(16,s); | 122 | 218 | return sh->alloc - sh->len; | 123 | 0 | } | 124 | 0 | case SDS_TYPE_32: { | 125 | 0 | SDS_HDR_VAR(32,s); | 126 | 0 | return sh->alloc - sh->len; | 127 | 0 | } | 128 | 0 | case SDS_TYPE_64: { | 129 | 0 | SDS_HDR_VAR(64,s); | 130 | 0 | return sh->alloc - sh->len; | 131 | 0 | } | 132 | 478 | } | 133 | 0 | return 0; | 134 | 478 | } |
Unexecuted instantiation: async.c:sdsavail Unexecuted instantiation: read.c:sdsavail Unexecuted instantiation: net.c:sdsavail |
135 | | |
136 | 479 | static inline void sdssetlen(sds s, size_t newlen) { |
137 | 479 | unsigned char flags = s[-1]; |
138 | 479 | switch(flags&SDS_TYPE_MASK) { |
139 | 0 | case SDS_TYPE_5: |
140 | 0 | { |
141 | 0 | unsigned char *fp = ((unsigned char*)s)-1; |
142 | 0 | *fp = (unsigned char)(SDS_TYPE_5 | (newlen << SDS_TYPE_BITS)); |
143 | 0 | } |
144 | 0 | break; |
145 | 259 | case SDS_TYPE_8: |
146 | 259 | SDS_HDR(8,s)->len = (uint8_t)newlen; |
147 | 259 | break; |
148 | 220 | case SDS_TYPE_16: |
149 | 220 | SDS_HDR(16,s)->len = (uint16_t)newlen; |
150 | 220 | break; |
151 | 0 | case SDS_TYPE_32: |
152 | 0 | SDS_HDR(32,s)->len = (uint32_t)newlen; |
153 | 0 | break; |
154 | 0 | case SDS_TYPE_64: |
155 | 0 | SDS_HDR(64,s)->len = (uint64_t)newlen; |
156 | 0 | break; |
157 | 479 | } |
158 | 479 | } Unexecuted instantiation: format_command_fuzzer.c:sdssetlen Unexecuted instantiation: hiredis.c:sdssetlen Line | Count | Source | 136 | 479 | static inline void sdssetlen(sds s, size_t newlen) { | 137 | 479 | unsigned char flags = s[-1]; | 138 | 479 | switch(flags&SDS_TYPE_MASK) { | 139 | 0 | case SDS_TYPE_5: | 140 | 0 | { | 141 | 0 | unsigned char *fp = ((unsigned char*)s)-1; | 142 | 0 | *fp = (unsigned char)(SDS_TYPE_5 | (newlen << SDS_TYPE_BITS)); | 143 | 0 | } | 144 | 0 | break; | 145 | 259 | case SDS_TYPE_8: | 146 | 259 | SDS_HDR(8,s)->len = (uint8_t)newlen; | 147 | 259 | break; | 148 | 220 | case SDS_TYPE_16: | 149 | 220 | SDS_HDR(16,s)->len = (uint16_t)newlen; | 150 | 220 | break; | 151 | 0 | case SDS_TYPE_32: | 152 | 0 | SDS_HDR(32,s)->len = (uint32_t)newlen; | 153 | 0 | break; | 154 | 0 | case SDS_TYPE_64: | 155 | 0 | SDS_HDR(64,s)->len = (uint64_t)newlen; | 156 | 0 | break; | 157 | 479 | } | 158 | 479 | } |
Unexecuted instantiation: async.c:sdssetlen Unexecuted instantiation: read.c:sdssetlen Unexecuted instantiation: net.c:sdssetlen |
159 | | |
160 | 0 | static inline void sdsinclen(sds s, size_t inc) { |
161 | 0 | unsigned char flags = s[-1]; |
162 | 0 | switch(flags&SDS_TYPE_MASK) { |
163 | 0 | case SDS_TYPE_5: |
164 | 0 | { |
165 | 0 | unsigned char *fp = ((unsigned char*)s)-1; |
166 | 0 | unsigned char newlen = SDS_TYPE_5_LEN(flags)+(unsigned char)inc; |
167 | 0 | *fp = SDS_TYPE_5 | (newlen << SDS_TYPE_BITS); |
168 | 0 | } |
169 | 0 | break; |
170 | 0 | case SDS_TYPE_8: |
171 | 0 | SDS_HDR(8,s)->len += (uint8_t)inc; |
172 | 0 | break; |
173 | 0 | case SDS_TYPE_16: |
174 | 0 | SDS_HDR(16,s)->len += (uint16_t)inc; |
175 | 0 | break; |
176 | 0 | case SDS_TYPE_32: |
177 | 0 | SDS_HDR(32,s)->len += (uint32_t)inc; |
178 | 0 | break; |
179 | 0 | case SDS_TYPE_64: |
180 | 0 | SDS_HDR(64,s)->len += (uint64_t)inc; |
181 | 0 | break; |
182 | 0 | } |
183 | 0 | } Unexecuted instantiation: format_command_fuzzer.c:sdsinclen Unexecuted instantiation: hiredis.c:sdsinclen Unexecuted instantiation: sds.c:sdsinclen Unexecuted instantiation: async.c:sdsinclen Unexecuted instantiation: read.c:sdsinclen Unexecuted instantiation: net.c:sdsinclen |
184 | | |
185 | | /* sdsalloc() = sdsavail() + sdslen() */ |
186 | 0 | static inline size_t sdsalloc(const sds s) { |
187 | 0 | unsigned char flags = s[-1]; |
188 | 0 | switch(flags&SDS_TYPE_MASK) { |
189 | 0 | case SDS_TYPE_5: |
190 | 0 | return SDS_TYPE_5_LEN(flags); |
191 | 0 | case SDS_TYPE_8: |
192 | 0 | return SDS_HDR(8,s)->alloc; |
193 | 0 | case SDS_TYPE_16: |
194 | 0 | return SDS_HDR(16,s)->alloc; |
195 | 0 | case SDS_TYPE_32: |
196 | 0 | return SDS_HDR(32,s)->alloc; |
197 | 0 | case SDS_TYPE_64: |
198 | 0 | return SDS_HDR(64,s)->alloc; |
199 | 0 | } |
200 | 0 | return 0; |
201 | 0 | } Unexecuted instantiation: format_command_fuzzer.c:sdsalloc Unexecuted instantiation: hiredis.c:sdsalloc Unexecuted instantiation: sds.c:sdsalloc Unexecuted instantiation: async.c:sdsalloc Unexecuted instantiation: read.c:sdsalloc Unexecuted instantiation: net.c:sdsalloc |
202 | | |
203 | 10 | static inline void sdssetalloc(sds s, size_t newlen) { |
204 | 10 | unsigned char flags = s[-1]; |
205 | 10 | switch(flags&SDS_TYPE_MASK) { |
206 | 0 | case SDS_TYPE_5: |
207 | | /* Nothing to do, this type has no total allocation info. */ |
208 | 0 | break; |
209 | 9 | case SDS_TYPE_8: |
210 | 9 | SDS_HDR(8,s)->alloc = (uint8_t)newlen; |
211 | 9 | break; |
212 | 1 | case SDS_TYPE_16: |
213 | 1 | SDS_HDR(16,s)->alloc = (uint16_t)newlen; |
214 | 1 | break; |
215 | 0 | case SDS_TYPE_32: |
216 | 0 | SDS_HDR(32,s)->alloc = (uint32_t)newlen; |
217 | 0 | break; |
218 | 0 | case SDS_TYPE_64: |
219 | 0 | SDS_HDR(64,s)->alloc = (uint64_t)newlen; |
220 | 0 | break; |
221 | 10 | } |
222 | 10 | } Unexecuted instantiation: format_command_fuzzer.c:sdssetalloc Unexecuted instantiation: hiredis.c:sdssetalloc Line | Count | Source | 203 | 10 | static inline void sdssetalloc(sds s, size_t newlen) { | 204 | 10 | unsigned char flags = s[-1]; | 205 | 10 | switch(flags&SDS_TYPE_MASK) { | 206 | 0 | case SDS_TYPE_5: | 207 | | /* Nothing to do, this type has no total allocation info. */ | 208 | 0 | break; | 209 | 9 | case SDS_TYPE_8: | 210 | 9 | SDS_HDR(8,s)->alloc = (uint8_t)newlen; | 211 | 9 | break; | 212 | 1 | case SDS_TYPE_16: | 213 | 1 | SDS_HDR(16,s)->alloc = (uint16_t)newlen; | 214 | 1 | break; | 215 | 0 | case SDS_TYPE_32: | 216 | 0 | SDS_HDR(32,s)->alloc = (uint32_t)newlen; | 217 | 0 | break; | 218 | 0 | case SDS_TYPE_64: | 219 | 0 | SDS_HDR(64,s)->alloc = (uint64_t)newlen; | 220 | 0 | break; | 221 | 10 | } | 222 | 10 | } |
Unexecuted instantiation: async.c:sdssetalloc Unexecuted instantiation: read.c:sdssetalloc Unexecuted instantiation: net.c:sdssetalloc |
223 | | |
224 | | sds sdsnewlen(const void *init, size_t initlen); |
225 | | sds sdsnew(const char *init); |
226 | | sds sdsempty(void); |
227 | | sds sdsdup(const sds s); |
228 | | void sdsfree(sds s); |
229 | | sds sdsgrowzero(sds s, size_t len); |
230 | | sds sdscatlen(sds s, const void *t, size_t len); |
231 | | sds sdscat(sds s, const char *t); |
232 | | sds sdscatsds(sds s, const sds t); |
233 | | sds sdscpylen(sds s, const char *t, size_t len); |
234 | | sds sdscpy(sds s, const char *t); |
235 | | |
236 | | sds sdscatvprintf(sds s, const char *fmt, va_list ap); |
237 | | #ifdef __GNUC__ |
238 | | sds sdscatprintf(sds s, const char *fmt, ...) |
239 | | __attribute__((format(printf, 2, 3))); |
240 | | #else |
241 | | sds sdscatprintf(sds s, const char *fmt, ...); |
242 | | #endif |
243 | | |
244 | | sds sdscatfmt(sds s, char const *fmt, ...); |
245 | | sds sdstrim(sds s, const char *cset); |
246 | | int sdsrange(sds s, ssize_t start, ssize_t end); |
247 | | void sdsupdatelen(sds s); |
248 | | void sdsclear(sds s); |
249 | | int sdscmp(const sds s1, const sds s2); |
250 | | sds *sdssplitlen(const char *s, int len, const char *sep, int seplen, int *count); |
251 | | void sdsfreesplitres(sds *tokens, int count); |
252 | | void sdstolower(sds s); |
253 | | void sdstoupper(sds s); |
254 | | sds sdsfromlonglong(long long value); |
255 | | sds sdscatrepr(sds s, const char *p, size_t len); |
256 | | sds *sdssplitargs(const char *line, int *argc); |
257 | | sds sdsmapchars(sds s, const char *from, const char *to, size_t setlen); |
258 | | sds sdsjoin(char **argv, int argc, char *sep); |
259 | | sds sdsjoinsds(sds *argv, int argc, const char *sep, size_t seplen); |
260 | | |
261 | | /* Low level functions exposed to the user API */ |
262 | | sds sdsMakeRoomFor(sds s, size_t addlen); |
263 | | void sdsIncrLen(sds s, int incr); |
264 | | sds sdsRemoveFreeSpace(sds s); |
265 | | size_t sdsAllocSize(sds s); |
266 | | void *sdsAllocPtr(sds s); |
267 | | |
268 | | /* Export the allocator used by SDS to the program using SDS. |
269 | | * Sometimes the program SDS is linked to, may use a different set of |
270 | | * allocators, but may want to allocate or free things that SDS will |
271 | | * respectively free or allocate. */ |
272 | | void *sds_malloc(size_t size); |
273 | | void *sds_realloc(void *ptr, size_t size); |
274 | | void sds_free(void *ptr); |
275 | | |
276 | | #ifdef REDIS_TEST |
277 | | int sdsTest(int argc, char *argv[]); |
278 | | #endif |
279 | | |
280 | | #endif |