C++ wrapper classes for SDS
Former-commit-id: 45817db8c3a86815945359113dcbccfde4257ce5
This commit is contained in:
parent
1790b02984
commit
20e529c441
43
src/sds.c
43
src/sds.c
@ -53,11 +53,18 @@ static inline int sdsHdrSize(char type) {
|
|||||||
return sizeof(struct sdshdr32);
|
return sizeof(struct sdshdr32);
|
||||||
case SDS_TYPE_64:
|
case SDS_TYPE_64:
|
||||||
return sizeof(struct sdshdr64);
|
return sizeof(struct sdshdr64);
|
||||||
|
case SDS_TYPE_REFCOUNTED:
|
||||||
|
return sizeof(struct sdshdrrefcount);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline char sdsReqType(size_t string_size) {
|
static inline char sdsReqType(ssize_t string_size) {
|
||||||
|
if (string_size < 0){
|
||||||
|
string_size = -string_size;
|
||||||
|
if (string_size < 1<<16)
|
||||||
|
return SDS_TYPE_REFCOUNTED;
|
||||||
|
}
|
||||||
if (string_size < 1<<5)
|
if (string_size < 1<<5)
|
||||||
return SDS_TYPE_5;
|
return SDS_TYPE_5;
|
||||||
if (string_size < 1<<8)
|
if (string_size < 1<<8)
|
||||||
@ -86,10 +93,12 @@ static inline char sdsReqType(size_t string_size) {
|
|||||||
* You can print the string with printf() as there is an implicit \0 at the
|
* 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
|
* 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. */
|
* \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, ssize_t initlen) {
|
||||||
void *sh;
|
void *sh;
|
||||||
sds s;
|
sds s;
|
||||||
char type = sdsReqType(initlen);
|
char type = sdsReqType(initlen);
|
||||||
|
if (initlen < 0)
|
||||||
|
initlen = -initlen;
|
||||||
/* Empty strings are usually created in order to append. Use type 8
|
/* Empty strings are usually created in order to append. Use type 8
|
||||||
* since type 5 is not good at this. */
|
* since type 5 is not good at this. */
|
||||||
if (type == SDS_TYPE_5 && initlen == 0) type = SDS_TYPE_8;
|
if (type == SDS_TYPE_5 && initlen == 0) type = SDS_TYPE_8;
|
||||||
@ -137,6 +146,13 @@ sds sdsnewlen(const void *init, size_t initlen) {
|
|||||||
*fp = type;
|
*fp = type;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case SDS_TYPE_REFCOUNTED: {
|
||||||
|
SDS_HDR_VAR_REFCOUNTED(s);
|
||||||
|
sh->len = initlen;
|
||||||
|
sh->refcount = 1;
|
||||||
|
*fp = type;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (initlen && init)
|
if (initlen && init)
|
||||||
memcpy(s, init, initlen);
|
memcpy(s, init, initlen);
|
||||||
@ -161,9 +177,25 @@ sds sdsdup(const char *s) {
|
|||||||
return sdsnewlen(s, sdslen(s));
|
return sdsnewlen(s, sdslen(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sds sdsdupshared(const char *s) {
|
||||||
|
unsigned char flags = s[-1];
|
||||||
|
if ((flags & SDS_TYPE_MASK) != SDS_TYPE_REFCOUNTED)
|
||||||
|
return sdsnewlen(s, -sdslen(s));
|
||||||
|
SDS_HDR_VAR_REFCOUNTED(s);
|
||||||
|
__atomic_fetch_add(&sh->refcount, 1, __ATOMIC_RELAXED);
|
||||||
|
return (sds)s;
|
||||||
|
}
|
||||||
|
|
||||||
/* Free an sds string. No operation is performed if 's' is NULL. */
|
/* Free an sds string. No operation is performed if 's' is NULL. */
|
||||||
void sdsfree(const char *s) {
|
void sdsfree(const char *s) {
|
||||||
if (s == NULL) return;
|
if (s == NULL) return;
|
||||||
|
unsigned char flags = s[-1];
|
||||||
|
if ((flags & SDS_TYPE_MASK) == SDS_TYPE_REFCOUNTED)
|
||||||
|
{
|
||||||
|
SDS_HDR_VAR_REFCOUNTED(s);
|
||||||
|
if (__atomic_fetch_sub(&sh->refcount, 1, __ATOMIC_RELAXED) > 1)
|
||||||
|
return;
|
||||||
|
}
|
||||||
s_free((char*)s-sdsHdrSize(s[-1]));
|
s_free((char*)s-sdsHdrSize(s[-1]));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -368,6 +400,11 @@ void sdsIncrLen(sds s, ssize_t incr) {
|
|||||||
len = (sh->len += incr);
|
len = (sh->len += incr);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case SDS_TYPE_REFCOUNTED: {
|
||||||
|
SDS_HDR_VAR_REFCOUNTED(s);
|
||||||
|
len = (sh->len += incr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default: len = 0; /* Just to avoid compilation warnings. */
|
default: len = 0; /* Just to avoid compilation warnings. */
|
||||||
}
|
}
|
||||||
s[len] = '\0';
|
s[len] = '\0';
|
||||||
@ -787,7 +824,7 @@ void sdstoupper(sds s) {
|
|||||||
* If two strings share exactly the same prefix, but one of the two has
|
* 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
|
* additional characters, the longer string is considered to be greater than
|
||||||
* the smaller one. */
|
* the smaller one. */
|
||||||
int sdscmp(const sds s1, const sds s2) {
|
int sdscmp(const char *s1, const char *s2) {
|
||||||
size_t l1, l2, minlen;
|
size_t l1, l2, minlen;
|
||||||
int cmp;
|
int cmp;
|
||||||
|
|
||||||
|
138
src/sds.h
138
src/sds.h
@ -91,15 +91,27 @@ struct __attribute__ ((__packed__)) sdshdr64 {
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct __attribute__ ((__packed__)) sdshdrrefcount {
|
||||||
|
uint64_t len; /* used */
|
||||||
|
uint16_t refcount;
|
||||||
|
unsigned char flags; /* 3 lsb of type, 5 unused bits */
|
||||||
|
#ifndef __cplusplus
|
||||||
|
char buf[];
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
#define SDS_TYPE_5 0
|
#define SDS_TYPE_5 0
|
||||||
#define SDS_TYPE_8 1
|
#define SDS_TYPE_8 1
|
||||||
#define SDS_TYPE_16 2
|
#define SDS_TYPE_16 2
|
||||||
#define SDS_TYPE_32 3
|
#define SDS_TYPE_32 3
|
||||||
#define SDS_TYPE_64 4
|
#define SDS_TYPE_64 4
|
||||||
|
#define SDS_TYPE_REFCOUNTED 5
|
||||||
#define SDS_TYPE_MASK 7
|
#define SDS_TYPE_MASK 7
|
||||||
#define SDS_TYPE_BITS 3
|
#define SDS_TYPE_BITS 3
|
||||||
#define SDS_HDR_VAR(T,s) struct sdshdr##T *sh = (struct sdshdr##T *)(((void*)((s)-(sizeof(struct sdshdr##T)))));
|
#define SDS_HDR_VAR(T,s) struct sdshdr##T *sh = (struct sdshdr##T *)(((void*)((s)-(sizeof(struct sdshdr##T)))));
|
||||||
|
#define SDS_HDR_VAR_REFCOUNTED(s) struct sdshdrrefcount *sh = (struct sdshdrrefcount *)(((void*)((s)-(sizeof(struct sdshdrrefcount)))));
|
||||||
#define SDS_HDR(T,s) ((struct sdshdr##T *)((s)-(sizeof(struct sdshdr##T))))
|
#define SDS_HDR(T,s) ((struct sdshdr##T *)((s)-(sizeof(struct sdshdr##T))))
|
||||||
|
#define SDS_HDR_REFCOUNTED(s) ((struct sdshdrrefcount *)((s)-(sizeof(struct sdshdrrefcount))))
|
||||||
#define SDS_TYPE_5_LEN(f) ((f)>>SDS_TYPE_BITS)
|
#define SDS_TYPE_5_LEN(f) ((f)>>SDS_TYPE_BITS)
|
||||||
|
|
||||||
static inline size_t sdslen(const char *s) {
|
static inline size_t sdslen(const char *s) {
|
||||||
@ -121,6 +133,8 @@ static inline size_t sdslen(const char *s) {
|
|||||||
return SDS_HDR(32,s)->len;
|
return SDS_HDR(32,s)->len;
|
||||||
case SDS_TYPE_64:
|
case SDS_TYPE_64:
|
||||||
return SDS_HDR(64,s)->len;
|
return SDS_HDR(64,s)->len;
|
||||||
|
case SDS_TYPE_REFCOUNTED:
|
||||||
|
return SDS_HDR_REFCOUNTED(s)->len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -148,6 +162,9 @@ static inline size_t sdsavail(const char * s) {
|
|||||||
SDS_HDR_VAR(64,s);
|
SDS_HDR_VAR(64,s);
|
||||||
return sh->alloc - sh->len;
|
return sh->alloc - sh->len;
|
||||||
}
|
}
|
||||||
|
case SDS_TYPE_REFCOUNTED: {
|
||||||
|
return 0; // immutable
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -173,6 +190,9 @@ static inline void sdssetlen(sds s, size_t newlen) {
|
|||||||
case SDS_TYPE_64:
|
case SDS_TYPE_64:
|
||||||
SDS_HDR(64,s)->len = newlen;
|
SDS_HDR(64,s)->len = newlen;
|
||||||
break;
|
break;
|
||||||
|
case SDS_TYPE_REFCOUNTED:
|
||||||
|
SDS_HDR_REFCOUNTED(s)->len = newlen;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,6 +218,9 @@ static inline void sdsinclen(sds s, size_t inc) {
|
|||||||
case SDS_TYPE_64:
|
case SDS_TYPE_64:
|
||||||
SDS_HDR(64,s)->len += inc;
|
SDS_HDR(64,s)->len += inc;
|
||||||
break;
|
break;
|
||||||
|
case SDS_TYPE_REFCOUNTED:
|
||||||
|
SDS_HDR_REFCOUNTED(s)->len += inc;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -215,6 +238,8 @@ static inline size_t sdsalloc(const sds s) {
|
|||||||
return SDS_HDR(32,s)->alloc;
|
return SDS_HDR(32,s)->alloc;
|
||||||
case SDS_TYPE_64:
|
case SDS_TYPE_64:
|
||||||
return SDS_HDR(64,s)->alloc;
|
return SDS_HDR(64,s)->alloc;
|
||||||
|
case SDS_TYPE_REFCOUNTED:
|
||||||
|
return SDS_HDR_REFCOUNTED(s)->len;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -237,13 +262,22 @@ static inline void sdssetalloc(sds s, size_t newlen) {
|
|||||||
case SDS_TYPE_64:
|
case SDS_TYPE_64:
|
||||||
SDS_HDR(64,s)->alloc = newlen;
|
SDS_HDR(64,s)->alloc = newlen;
|
||||||
break;
|
break;
|
||||||
|
case SDS_TYPE_REFCOUNTED:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sds sdsnewlen(const void *init, size_t initlen);
|
static inline int sdsisshared(const char *s)
|
||||||
|
{
|
||||||
|
unsigned char flags = s[-1];
|
||||||
|
return ((flags & SDS_TYPE_MASK) == SDS_TYPE_REFCOUNTED);
|
||||||
|
}
|
||||||
|
|
||||||
|
sds sdsnewlen(const void *init, ssize_t initlen);
|
||||||
sds sdsnew(const char *init);
|
sds sdsnew(const char *init);
|
||||||
sds sdsempty(void);
|
sds sdsempty(void);
|
||||||
sds sdsdup(const char *s);
|
sds sdsdup(const char *s);
|
||||||
|
sds sdsdupshared(const char *s);
|
||||||
void sdsfree(const char *s);
|
void sdsfree(const char *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);
|
||||||
@ -265,7 +299,7 @@ sds sdstrim(sds s, const char *cset);
|
|||||||
void sdsrange(sds s, ssize_t start, ssize_t end);
|
void sdsrange(sds s, ssize_t start, ssize_t end);
|
||||||
void sdsupdatelen(sds s);
|
void sdsupdatelen(sds s);
|
||||||
void sdsclear(sds s);
|
void sdsclear(sds s);
|
||||||
int sdscmp(const sds s1, const sds s2);
|
int sdscmp(const char *s1, const char *s2);
|
||||||
sds *sdssplitlen(const char *s, ssize_t len, const char *sep, int seplen, int *count);
|
sds *sdssplitlen(const char *s, ssize_t 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);
|
||||||
@ -298,6 +332,106 @@ int sdsTest(int argc, char *argv[]);
|
|||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class sdsview
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
sds m_str = nullptr;
|
||||||
|
|
||||||
|
sdsview() = default; // Not allowed to create a sdsview directly with a nullptr
|
||||||
|
public:
|
||||||
|
sdsview(sds str)
|
||||||
|
: m_str(str)
|
||||||
|
{}
|
||||||
|
|
||||||
|
sdsview(const char *str)
|
||||||
|
: m_str((sds)str)
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool operator<(const sdsview &other) const
|
||||||
|
{
|
||||||
|
return sdscmp(m_str, other.m_str) < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const sdsview &other) const
|
||||||
|
{
|
||||||
|
return sdscmp(m_str, other.m_str) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const char *other) const
|
||||||
|
{
|
||||||
|
return sdscmp(m_str, other) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
char operator[](size_t idx) const
|
||||||
|
{
|
||||||
|
return m_str[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size() const
|
||||||
|
{
|
||||||
|
return sdslen(m_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *get() const { return m_str; }
|
||||||
|
|
||||||
|
explicit operator const char*() const { return m_str; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class sdsstring : public sdsview
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
sdsstring() = default;
|
||||||
|
explicit sdsstring(sds str)
|
||||||
|
: sdsview(str)
|
||||||
|
{}
|
||||||
|
|
||||||
|
sdsstring(const sdsstring &other)
|
||||||
|
: sdsview(sdsdup(other.m_str))
|
||||||
|
{}
|
||||||
|
|
||||||
|
sdsstring(sdsstring &&other)
|
||||||
|
: sdsview(other.m_str)
|
||||||
|
{
|
||||||
|
other.m_str = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
~sdsstring()
|
||||||
|
{
|
||||||
|
sdsfree(m_str);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class sdsimmutablestring : public sdsstring
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
sdsimmutablestring() = default;
|
||||||
|
explicit sdsimmutablestring(sds str)
|
||||||
|
: sdsstring(str)
|
||||||
|
{}
|
||||||
|
|
||||||
|
explicit sdsimmutablestring(const char *str)
|
||||||
|
: sdsstring((sds)str)
|
||||||
|
{}
|
||||||
|
|
||||||
|
sdsimmutablestring(const sdsimmutablestring &other)
|
||||||
|
: sdsstring(sdsdupshared(other.m_str))
|
||||||
|
{}
|
||||||
|
|
||||||
|
sdsimmutablestring(sdsimmutablestring &&other)
|
||||||
|
: sdsstring(other.m_str)
|
||||||
|
{
|
||||||
|
other.m_str = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto &operator=(const sdsimmutablestring &other)
|
||||||
|
{
|
||||||
|
sdsfree(m_str);
|
||||||
|
m_str = sdsdupshared(other.m_str);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user