Skip to content

Commit

Permalink
Different implementation for DSTR.
Browse files Browse the repository at this point in the history
Use less space for empty strings using only a single pointer to a
structure instead of a structure with length and a pointer.

Signed-off-by: Frediano Ziglio <freddy77@gmail.com>
  • Loading branch information
freddy77 committed Feb 19, 2014
1 parent ce8fe69 commit 90e6e9f
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 49 deletions.
10 changes: 5 additions & 5 deletions include/freetds/string.h
Expand Up @@ -26,7 +26,7 @@
#pragma GCC visibility push(hidden)
#endif

extern const char tds_str_empty[1];
extern const struct tds_dstr tds_str_empty;

/* TODO do some function and use inline if available */

Expand All @@ -42,15 +42,15 @@ size_t tds_dstr_len(DSTR * s);
#else
/** init a string with empty */
#define tds_dstr_init(s) \
do { DSTR *_tds_s = (s); _tds_s->dstr_size = 0; _tds_s->dstr_s = (char*) tds_str_empty; } while(0)
do { *(s) = (struct tds_dstr*) &tds_str_empty; } while(0)

/** test if string is empty */
#define tds_dstr_isempty(s) \
((s)->dstr_size == 0)
((*(s))->dstr_size == 0)
#define tds_dstr_buf(s) \
((s)->dstr_s)
((*(s))->dstr_s)
#define tds_dstr_len(s) \
((s)->dstr_size)
((*(s))->dstr_size)
#endif

#define tds_dstr_cstr(s) \
Expand Down
4 changes: 2 additions & 2 deletions include/freetds/tds.h
Expand Up @@ -93,9 +93,9 @@ typedef struct tds_compiletime_settings
* There should be always a buffer.
*/
typedef struct tds_dstr {
char *dstr_s;
size_t dstr_size;
} DSTR;
char dstr_s[1];
} *DSTR;

/**
* @file tds.h
Expand Down
76 changes: 34 additions & 42 deletions src/tds/tdsstring.c
Expand Up @@ -49,7 +49,8 @@ TDS_RCSID(var, "$Id: tdsstring.c,v 1.21 2011-05-16 08:51:40 freddy77 Exp $");
*/

/* This is in a separate module because we use the pointer to discriminate allocated and not allocated */
const char tds_str_empty[1] = "";
const struct tds_dstr tds_str_empty = { 0, "" };
#define EMPTY ((struct tds_dstr*) &tds_str_empty)

/**
* \addtogroup dstring
Expand All @@ -60,17 +61,16 @@ const char tds_str_empty[1] = "";
void
tds_dstr_zero(DSTR * s)
{
memset(s->dstr_s, 0, s->dstr_size);
memset((*s)->dstr_s, 0, (*s)->dstr_size);
}

/** free string */
void
tds_dstr_free(DSTR * s)
{
if (s->dstr_s != tds_str_empty)
free(s->dstr_s);
s->dstr_size = 0;
s->dstr_s = (char*) tds_str_empty;
if (*s != EMPTY)
free(*s);
*s = EMPTY;
}

/**
Expand All @@ -84,21 +84,20 @@ DSTR*
tds_dstr_copyn(DSTR * s, const char *src, size_t length)
{
if (!length) {
if (s->dstr_s != tds_str_empty) {
free(s->dstr_s);
s->dstr_s = (char *) tds_str_empty;
s->dstr_size = 0;
if (*s != EMPTY) {
free(*s);
*s = EMPTY;
}
} else {
char *p = (char *) malloc(length + 1);
struct tds_dstr *p = (struct tds_dstr *) malloc(length + TDS_OFFSET(struct tds_dstr, dstr_s) + 1);
if (TDS_UNLIKELY(!p))
return NULL;
memcpy(p, src, length);
p[length] = 0;
if (s->dstr_s != tds_str_empty)
free(s->dstr_s);
s->dstr_s = p;
s->dstr_size = length;
memcpy(p->dstr_s, src, length);
p->dstr_s[length] = 0;
p->dstr_size = length;
if (*s != EMPTY)
free(*s);
*s = p;
}
return s;
}
Expand All @@ -114,16 +113,10 @@ tds_dstr_copyn(DSTR * s, const char *src, size_t length)
DSTR*
tds_dstr_set(DSTR * s, char *src)
{
size_t len = strlen(src);

if (s->dstr_s != tds_str_empty)
free(s->dstr_s);

s->dstr_s = len ? src : (char *) tds_str_empty;
if (!len)
DSTR *res = tds_dstr_copy(s, src);
if (TDS_LIKELY(res != NULL))
free(src);
s->dstr_size = len;
return s;
return res;
}

/**
Expand All @@ -141,7 +134,7 @@ tds_dstr_copy(DSTR * s, const char *src)
DSTR*
tds_dstr_dup(DSTR * s, const DSTR * src)
{
return tds_dstr_copyn(s, src->dstr_s, src->dstr_size);
return tds_dstr_copyn(s, (*src)->dstr_s, (*src)->dstr_size);
}

/**
Expand All @@ -153,12 +146,12 @@ DSTR*
tds_dstr_setlen(DSTR *s, size_t length)
{
#if ENABLE_EXTRA_CHECKS
assert(s->dstr_size >= length);
assert((*s)->dstr_size >= length);
#endif
/* test required for empty strings */
if (s->dstr_size >= length && s->dstr_s != tds_str_empty) {
s->dstr_size = length;
s->dstr_s[length] = 0;
if ((*s)->dstr_size >= length && *s != EMPTY) {
(*s)->dstr_size = length;
(*s)->dstr_s[length] = 0;
}
return s;
}
Expand All @@ -172,42 +165,41 @@ tds_dstr_setlen(DSTR *s, size_t length)
DSTR*
tds_dstr_alloc(DSTR *s, size_t length)
{
char *p = (char *) malloc(length + 1);
struct tds_dstr *p = (struct tds_dstr *) malloc(length + TDS_OFFSET(struct tds_dstr, dstr_s) + 1);
if (TDS_UNLIKELY(!p))
return NULL;

if (s->dstr_s != tds_str_empty)
free(s->dstr_s);
s->dstr_s = p;
s->dstr_s[0] = 0;
s->dstr_size = length;
if (*s != EMPTY)
free(*s);
p->dstr_s[0] = 0;
p->dstr_size = length;
*s = p;
return s;
}

#if ENABLE_EXTRA_CHECKS
void
tds_dstr_init(DSTR * s)
{
s->dstr_s = (char *) tds_str_empty;
s->dstr_size = 0;
*s = EMPTY;
}

int
tds_dstr_isempty(DSTR * s)
{
return s->dstr_size == 0;
return (*s)->dstr_size == 0;
}

char *
tds_dstr_buf(DSTR * s)
{
return s->dstr_s;
return (*s)->dstr_s;
}

size_t
tds_dstr_len(DSTR * s)
{
return s->dstr_size;
return (*s)->dstr_size;
}
#endif

Expand Down

0 comments on commit 90e6e9f

Please sign in to comment.