Skip to content

Commit

Permalink
Implemented custom string copy functions
Browse files Browse the repository at this point in the history
The str_copy() function is designed to copy a maximum number
of characters to a destination string and guarantee that the
destination string is terminated. The str_duplicate() function
is a wrapper that first allocates memory before copying the
string.
  • Loading branch information
jbittel committed Dec 12, 2011
1 parent 2c08e37 commit eeee01d
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 22 deletions.
22 changes: 12 additions & 10 deletions format.c
Expand Up @@ -39,7 +39,7 @@ struct format_node {
FORMAT_NODE *next, *list;
};

FORMAT_NODE *insert_field(char *str);
FORMAT_NODE *insert_field(char *str, size_t len);
FORMAT_NODE *get_field(char *str);

static FORMAT_NODE *fields[HASHSIZE];
Expand All @@ -49,26 +49,28 @@ static FORMAT_NODE *head = NULL;
void parse_format_string(char *str) {
char *name, *tmp, *i;
int num_nodes = 0;
size_t len;

#ifdef DEBUG
ASSERT(str);
#endif

if (strlen(str) == 0)
len = strlen(str);
if (len == 0)
LOG_DIE("Empty format string provided");

/* Make a temporary copy of the string so we don't modify the original */
if ((tmp = malloc(strlen(str) + 1)) == NULL)
if ((tmp = str_duplicate(str)) == NULL)
LOG_DIE("Cannot allocate memory for format string buffer");
strcpy(tmp, str);

for (i = tmp; (name = strtok(i, ",")); i = NULL) {
/* Normalize input field text */
name = str_strip_whitespace(name);
name = str_tolower(name);
len = strlen(name);

if (strlen(name) == 0) continue;
if (insert_field(name)) num_nodes++;
if (len == 0) continue;
if (insert_field(name, len)) num_nodes++;
}

free(tmp);
Expand Down Expand Up @@ -101,14 +103,14 @@ void parse_format_string(char *str) {
}

/* Insert a new node into the hash table */
FORMAT_NODE *insert_field(char *name) {
FORMAT_NODE *insert_field(char *name, size_t len) {
FORMAT_NODE *node;
static FORMAT_NODE *prev = NULL;
unsigned int hashval;

#ifdef DEBUG
ASSERT(name);
ASSERT(strlen(name) > 0);
ASSERT(len > 0);
#endif

if ((node = get_field(name)) == NULL) {
Expand All @@ -128,10 +130,10 @@ FORMAT_NODE *insert_field(char *name) {
return NULL;
}

if ((node->name = (char *) malloc(strlen(name) + 1)) == NULL)
if ((node->name = (char *) malloc(len + 1)) == NULL)
LOG_DIE("Cannot allocate memory for node name");
str_copy(node->name, name, len + 1);

strcpy(node->name, name);
node->value = NULL;
node->list = NULL;

Expand Down
21 changes: 11 additions & 10 deletions methods.c
Expand Up @@ -37,32 +37,33 @@ struct method_node {

static METHOD_NODE *methods = NULL;

int insert_method(char *str);
int insert_method(char *str, size_t len);
void free_node(METHOD_NODE *node);

/* Parse and insert methods from methods string */
void parse_methods_string(char *str) {
char *method, *tmp, *i;
int num_methods = 0;
size_t len;

#ifdef DEBUG
ASSERT(str);
#endif

if (strlen(str) == 0)
len = strlen(str);
if (len == 0)
LOG_DIE("Empty methods string provided");

/* Make a temporary copy of the string so we don't modify the original */
if ((tmp = malloc(strlen(str) + 1)) == NULL)
if ((tmp = str_duplicate(str)) == NULL)
LOG_DIE("Cannot allocate memory for methods string buffer");
strcpy(tmp, str);

for (i = tmp; (method = strtok(i, ",")); i = NULL) {
method = str_strip_whitespace(method);
method = str_tolower(method);
len = strlen(method);

if (strlen(method) == 0) continue;
if (insert_method(method)) num_methods++;
if (len == 0) continue;
if (insert_method(method, len)) num_methods++;
}

free(tmp);
Expand All @@ -74,7 +75,7 @@ void parse_methods_string(char *str) {
}

/* Insert a new method into the structure */
int insert_method(char *method) {
int insert_method(char *method, size_t len) {
METHOD_NODE **node = &methods;
int cmp;

Expand All @@ -100,11 +101,11 @@ int insert_method(char *method) {
LOG_DIE("Cannot allocate memory for method node");
}

if (((*node)->method = (char *) malloc(strlen(method) + 1)) == NULL) {
if (((*node)->method = (char *) malloc(len + 1)) == NULL) {
LOG_DIE("Cannot allocate memory for method string");
}
str_copy((*node)->method, method, len + 1);

strcpy((*node)->method, method);
(*node)->left = (*node)->right = NULL;

return 1;
Expand Down
2 changes: 1 addition & 1 deletion rate.c
Expand Up @@ -302,7 +302,7 @@ void update_host_stats(char *host, time_t t) {
ASSERT((hashval >= 0) && (hashval < HASHSIZE));
#endif

strncpy(node->host, host, MAX_HOST_LEN);
str_copy(node->host, host, MAX_HOST_LEN);
node->count = 0;
node->first_packet = t;

Expand Down
39 changes: 38 additions & 1 deletion utility.c
Expand Up @@ -70,6 +70,42 @@ int str_compare(const char *str1, const char *str2) {
return tolower(*str1) - *str2;
}

/* Copy at most len characters from src to dest, including
the end of string terminator. Returns the total number of
characters copied, not including the string terminator. */
int str_copy(char *dest, const char *src, size_t len) {
int i = 0;

if (len > 0) {
while ((*src != '\0') && --len) {
*dest++ = *src++;
i++;
}
*dest = '\0';
}

return i;
}

/* Wrapper function around str_copy() that first allocates
memory for the destination string and then copies the
parameter string into it. */
char *str_duplicate(const char *str) {
char *new;
size_t len = strlen(str);

if ((new = malloc(len + 1)) == NULL)
return NULL;

#ifdef DEBUG
ASSERT(str_copy(new, str, len + 1) <= (len + 1));
#else
str_copy(new, str, len + 1);
#endif

return new;
}

/* Implementation of Jenkins's One-at-a-Time hash, as described on
this page: http://www.burtleburtle.net/bob/hash/doobs.html */
unsigned int hash_str(char *str, unsigned int hashsize) {
Expand All @@ -90,6 +126,7 @@ unsigned int hash_str(char *str, unsigned int hashsize) {
hash ^= (hash >> 11);
hash += (hash << 15);

/* Restrict hash value to a maximum of hashsize */
/* Restrict hash value to a maximum of hashsize;
hashsize must be a power of 2 */
return (unsigned int) (hash & (hashsize - 1));
}
2 changes: 2 additions & 0 deletions utility.h
Expand Up @@ -14,6 +14,8 @@
char *str_strip_whitespace(char *str);
char *str_tolower(char *str);
int str_compare(const char *str1, const char *str2);
int str_copy(char *str1, const char *str2, size_t len);
char *str_duplicate(const char *str);
unsigned int hash_str(char *key, unsigned int hashsize);

#endif /* ! _HAVE_UTILITY_H */

0 comments on commit eeee01d

Please sign in to comment.