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