2015-07-25 17:50:47 +02:00
/* SDSLib 2.0 -- A C dynamic strings library
2010-11-03 16:03:04 +01:00
*
2015-07-25 17:50:47 +02:00
* Copyright ( c ) 2006 - 2015 , Salvatore Sanfilippo < antirez at gmail dot com >
* Copyright ( c ) 2015 , Oran Agra
* Copyright ( c ) 2015 , Redis Labs , Inc
2010-11-03 16:03:04 +01:00
* All rights reserved .
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions are met :
*
* * Redistributions of source code must retain the above copyright notice ,
* this list of conditions and the following disclaimer .
* * Redistributions in binary form must reproduce the above copyright
* notice , this list of conditions and the following disclaimer in the
* documentation and / or other materials provided with the distribution .
* * Neither the name of Redis nor the names of its contributors may be used
* to endorse or promote products derived from this software without
* specific prior written permission .
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS " AS IS "
* AND ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED . IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT , INDIRECT , INCIDENTAL , SPECIAL , EXEMPLARY , OR
* CONSEQUENTIAL DAMAGES ( INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS
* INTERRUPTION ) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY , WHETHER IN
* CONTRACT , STRICT LIABILITY , OR TORT ( INCLUDING NEGLIGENCE OR OTHERWISE )
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE , EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE .
*/
# ifndef __SDS_H
# define __SDS_H
2013-07-25 10:32:19 +02:00
# define SDS_MAX_PREALLOC (1024*1024)
2010-11-03 16:03:04 +01:00
# include <sys/types.h>
# include <stdarg.h>
2015-07-25 17:50:47 +02:00
# include <stdint.h>
2010-11-03 16:03:04 +01:00
typedef char * sds ;
2015-07-25 17:50:47 +02:00
/* 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 */
2010-11-03 16:03:04 +01:00
char buf [ ] ;
} ;
2015-07-25 17:50:47 +02:00
# 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)
2011-04-19 23:07:36 +02:00
static inline size_t sdslen ( const sds s ) {
2015-07-25 17:50:47 +02:00
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 ;
2011-04-19 23:07:36 +02:00
}
static inline size_t sdsavail ( const sds s ) {
2015-07-25 17:50:47 +02:00
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 ;
}
2011-04-19 23:07:36 +02:00
}
2010-11-03 16:03:04 +01:00
sds sdsnewlen ( const void * init , size_t initlen ) ;
sds sdsnew ( const char * init ) ;
2013-08-12 11:38:21 +02:00
sds sdsempty ( void ) ;
2010-11-03 16:03:04 +01:00
sds sdsdup ( const sds s ) ;
void sdsfree ( sds s ) ;
2011-04-19 23:07:36 +02:00
sds sdsgrowzero ( sds s , size_t len ) ;
2010-11-03 16:03:04 +01:00
sds sdscatlen ( sds s , const void * t , size_t len ) ;
sds sdscat ( sds s , const char * t ) ;
2013-07-25 10:32:19 +02:00
sds sdscatsds ( sds s , const sds t ) ;
sds sdscpylen ( sds s , const char * t , size_t len ) ;
sds sdscpy ( sds s , const char * t ) ;
2010-11-03 16:03:04 +01:00
sds sdscatvprintf ( sds s , const char * fmt , va_list ap ) ;
# ifdef __GNUC__
sds sdscatprintf ( sds s , const char * fmt , . . . )
__attribute__ ( ( format ( printf , 2 , 3 ) ) ) ;
# else
sds sdscatprintf ( sds s , const char * fmt , . . . ) ;
# endif
2014-06-23 11:42:47 +02:00
sds sdscatfmt ( sds s , char const * fmt , . . . ) ;
sds sdstrim ( sds s , const char * cset ) ;
2013-07-25 10:32:19 +02:00
void sdsrange ( sds s , int start , int end ) ;
2010-11-03 16:03:04 +01:00
void sdsupdatelen ( sds s ) ;
2013-07-25 10:32:19 +02:00
void sdsclear ( sds s ) ;
int sdscmp ( const sds s1 , const sds s2 ) ;
sds * sdssplitlen ( const char * s , int len , const char * sep , int seplen , int * count ) ;
2010-11-03 16:03:04 +01:00
void sdsfreesplitres ( sds * tokens , int count ) ;
void sdstolower ( sds s ) ;
void sdstoupper ( sds s ) ;
sds sdsfromlonglong ( long long value ) ;
2013-07-25 10:32:19 +02:00
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 ) ;
2014-06-23 11:42:47 +02:00
sds sdsjoin ( char * * argv , int argc , char * sep ) ;
2015-07-25 17:50:47 +02:00
sds sdsjoinsds ( sds * argv , int argc , const char * sep , size_t seplen ) ;
2013-07-25 10:32:19 +02:00
/* 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 ) ;
2015-07-25 17:50:47 +02:00
void * sdsAllocPtr ( sds s ) ;
2015-11-16 10:29:35 +01:00
/* Export the allocator used by SDS to the program using SDS.
* Sometimes the program SDS is linked to , may use a different set of
* allocators , but may want to allocate or free things that SDS will
* respectively free or allocate . */
void * sds_malloc ( size_t size ) ;
void * sds_realloc ( void * ptr , size_t size ) ;
void sds_free ( void * ptr ) ;
2015-07-25 17:50:47 +02:00
# ifdef REDIS_TEST
int sdsTest ( int argc , char * argv [ ] ) ;
# endif
2010-11-03 16:03:04 +01:00
# endif