Permalink
Browse files

Different implementation for DSTR.

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...
1 parent ce8fe69 commit 90e6e9f4f15e282aaf09be8b8529825fc13eb491 @freddy77 freddy77 committed Feb 13, 2014
Showing with 41 additions and 49 deletions.
  1. +5 −5 include/freetds/string.h
  2. +2 −2 include/freetds/tds.h
  3. +34 −42 src/tds/tdsstring.c
View
@@ -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 */
@@ -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) \
View
@@ -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
View
@@ -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
@@ -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;
}
/**
@@ -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;
}
@@ -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;
}
/**
@@ -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);
}
/**
@@ -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;
}
@@ -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

0 comments on commit 90e6e9f

Please sign in to comment.