diff options
Diffstat (limited to 'sds.h')
| -rw-r--r-- | sds.h | 190 | 
1 files changed, 173 insertions, 17 deletions
| @@ -1,6 +1,6 @@ -/* SDS (Simple Dynamic Strings), A C dynamic strings library. +/* SDSLib, A C dynamic strings library   * - * Copyright (c) 2006-2014, Salvatore Sanfilippo <antirez at gmail dot com> + * Copyright (c) 2006-2010, Salvatore Sanfilippo <antirez at gmail dot com>   * All rights reserved.   *   * Redistribution and use in source and binary forms, with or without @@ -35,35 +35,188 @@  #include <sys/types.h>  #include <stdarg.h> -#ifdef _MSC_VER -#include "win32.h" -#endif +#include <stdint.h>  typedef char *sds; -struct sdshdr { -    int len; -    int free; +/* Note: sdshdr5 is never used, we just access the flags byte directly. + * However is here to document the layout of type 5 SDS strings. */ +struct __attribute__ ((__packed__)) sdshdr5 { +    unsigned char flags; /* 3 lsb of type, and 5 msb of string length */ +    char buf[]; +}; +struct __attribute__ ((__packed__)) sdshdr8 { +    uint8_t len; /* used */ +    uint8_t alloc; /* excluding the header and null terminator */ +    unsigned char flags; /* 3 lsb of type, 5 unused bits */ +    char buf[]; +}; +struct __attribute__ ((__packed__)) sdshdr16 { +    uint16_t len; /* used */ +    uint16_t alloc; /* excluding the header and null terminator */ +    unsigned char flags; /* 3 lsb of type, 5 unused bits */      char buf[];  }; +struct __attribute__ ((__packed__)) sdshdr32 { +    uint32_t len; /* used */ +    uint32_t alloc; /* excluding the header and null terminator */ +    unsigned char flags; /* 3 lsb of type, 5 unused bits */ +    char buf[]; +}; +struct __attribute__ ((__packed__)) sdshdr64 { +    uint64_t len; /* used */ +    uint64_t alloc; /* excluding the header and null terminator */ +    unsigned char flags; /* 3 lsb of type, 5 unused bits */ +    char buf[]; +}; + +#define SDS_TYPE_5  0 +#define SDS_TYPE_8  1 +#define SDS_TYPE_16 2 +#define SDS_TYPE_32 3 +#define SDS_TYPE_64 4 +#define SDS_TYPE_MASK 7 +#define SDS_TYPE_BITS 3 +#define SDS_HDR_VAR(T,s) struct sdshdr##T *sh = (void*)((s)-(sizeof(struct sdshdr##T))); +#define SDS_HDR(T,s) ((struct sdshdr##T *)((s)-(sizeof(struct sdshdr##T)))) +#define SDS_TYPE_5_LEN(f) ((f)>>SDS_TYPE_BITS)  static inline size_t sdslen(const sds s) { -    struct sdshdr *sh = (struct sdshdr *)(s-sizeof *sh); -    return sh->len; +    unsigned char flags = s[-1]; +    switch(flags&SDS_TYPE_MASK) { +        case SDS_TYPE_5: +            return SDS_TYPE_5_LEN(flags); +        case SDS_TYPE_8: +            return SDS_HDR(8,s)->len; +        case SDS_TYPE_16: +            return SDS_HDR(16,s)->len; +        case SDS_TYPE_32: +            return SDS_HDR(32,s)->len; +        case SDS_TYPE_64: +            return SDS_HDR(64,s)->len; +    } +    return 0;  }  static inline size_t sdsavail(const sds s) { -    struct sdshdr *sh = (struct sdshdr *)(s-sizeof *sh); -    return sh->free; +    unsigned char flags = s[-1]; +    switch(flags&SDS_TYPE_MASK) { +        case SDS_TYPE_5: { +            return 0; +        } +        case SDS_TYPE_8: { +            SDS_HDR_VAR(8,s); +            return sh->alloc - sh->len; +        } +        case SDS_TYPE_16: { +            SDS_HDR_VAR(16,s); +            return sh->alloc - sh->len; +        } +        case SDS_TYPE_32: { +            SDS_HDR_VAR(32,s); +            return sh->alloc - sh->len; +        } +        case SDS_TYPE_64: { +            SDS_HDR_VAR(64,s); +            return sh->alloc - sh->len; +        } +    } +    return 0; +} + +static inline void sdssetlen(sds s, size_t newlen) { +    unsigned char flags = s[-1]; +    switch(flags&SDS_TYPE_MASK) { +        case SDS_TYPE_5: +            { +                unsigned char *fp = ((unsigned char*)s)-1; +                *fp = SDS_TYPE_5 | (newlen << SDS_TYPE_BITS); +            } +            break; +        case SDS_TYPE_8: +            SDS_HDR(8,s)->len = newlen; +            break; +        case SDS_TYPE_16: +            SDS_HDR(16,s)->len = newlen; +            break; +        case SDS_TYPE_32: +            SDS_HDR(32,s)->len = newlen; +            break; +        case SDS_TYPE_64: +            SDS_HDR(64,s)->len = newlen; +            break; +    } +} + +static inline void sdsinclen(sds s, size_t inc) { +    unsigned char flags = s[-1]; +    switch(flags&SDS_TYPE_MASK) { +        case SDS_TYPE_5: +            { +                unsigned char *fp = ((unsigned char*)s)-1; +                unsigned char newlen = SDS_TYPE_5_LEN(flags)+inc; +                *fp = SDS_TYPE_5 | (newlen << SDS_TYPE_BITS); +            } +            break; +        case SDS_TYPE_8: +            SDS_HDR(8,s)->len += inc; +            break; +        case SDS_TYPE_16: +            SDS_HDR(16,s)->len += inc; +            break; +        case SDS_TYPE_32: +            SDS_HDR(32,s)->len += inc; +            break; +        case SDS_TYPE_64: +            SDS_HDR(64,s)->len += inc; +            break; +    } +} + +/* sdsalloc() = sdsavail() + sdslen() */ +static inline size_t sdsalloc(const sds s) { +    unsigned char flags = s[-1]; +    switch(flags&SDS_TYPE_MASK) { +        case SDS_TYPE_5: +            return SDS_TYPE_5_LEN(flags); +        case SDS_TYPE_8: +            return SDS_HDR(8,s)->alloc; +        case SDS_TYPE_16: +            return SDS_HDR(16,s)->alloc; +        case SDS_TYPE_32: +            return SDS_HDR(32,s)->alloc; +        case SDS_TYPE_64: +            return SDS_HDR(64,s)->alloc; +    } +    return 0; +} + +static inline void sdssetalloc(sds s, size_t newlen) { +    unsigned char flags = s[-1]; +    switch(flags&SDS_TYPE_MASK) { +        case SDS_TYPE_5: +            /* Nothing to do, this type has no total allocation info. */ +            break; +        case SDS_TYPE_8: +            SDS_HDR(8,s)->alloc = newlen; +            break; +        case SDS_TYPE_16: +            SDS_HDR(16,s)->alloc = newlen; +            break; +        case SDS_TYPE_32: +            SDS_HDR(32,s)->alloc = newlen; +            break; +        case SDS_TYPE_64: +            SDS_HDR(64,s)->alloc = newlen; +            break; +    }  }  sds sdsnewlen(const void *init, size_t initlen);  sds sdsnew(const char *init);  sds sdsempty(void); -size_t sdslen(const sds s);  sds sdsdup(const sds s);  void sdsfree(sds s); -size_t sdsavail(const sds s);  sds sdsgrowzero(sds s, size_t len);  sds sdscatlen(sds s, const void *t, size_t len);  sds sdscat(sds s, const char *t); @@ -80,7 +233,7 @@ sds sdscatprintf(sds s, const char *fmt, ...);  #endif  sds sdscatfmt(sds s, char const *fmt, ...); -void sdstrim(sds s, const char *cset); +sds sdstrim(sds s, const char *cset);  void sdsrange(sds s, int start, int end);  void sdsupdatelen(sds s);  void sdsclear(sds s); @@ -93,8 +246,7 @@ sds sdsfromlonglong(long long value);  sds sdscatrepr(sds s, const char *p, size_t len);  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, size_t seplen); -sds sdsjoinsds(sds *argv, int argc, const char *sep, size_t seplen); +sds sdsjoin(char **argv, int argc, char *sep);  /* Low level functions exposed to the user API */  sds sdsMakeRoomFor(sds s, size_t addlen); @@ -102,4 +254,8 @@ void sdsIncrLen(sds s, int incr);  sds sdsRemoveFreeSpace(sds s);  size_t sdsAllocSize(sds s); +#ifdef REDIS_TEST +int sdsTest(int argc, char *argv[]); +#endif +  #endif | 
