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 *next, *list;
}; };


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


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


#ifdef DEBUG #ifdef DEBUG
ASSERT(str); ASSERT(str);
#endif #endif


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


/* Make a temporary copy of the string so we don't modify the original */ /* 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"); LOG_DIE("Cannot allocate memory for format string buffer");
strcpy(tmp, str);


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


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


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


/* Insert a new node into the hash table */ /* 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; FORMAT_NODE *node;
static FORMAT_NODE *prev = NULL; static FORMAT_NODE *prev = NULL;
unsigned int hashval; unsigned int hashval;


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


if ((node = get_field(name)) == NULL) { if ((node = get_field(name)) == NULL) {
Expand All @@ -128,10 +130,10 @@ FORMAT_NODE *insert_field(char *name) {
return NULL; 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"); LOG_DIE("Cannot allocate memory for node name");
str_copy(node->name, name, len + 1);


strcpy(node->name, name);
node->value = NULL; node->value = NULL;
node->list = 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; static METHOD_NODE *methods = NULL;


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


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


#ifdef DEBUG #ifdef DEBUG
ASSERT(str); ASSERT(str);
#endif #endif

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


/* Make a temporary copy of the string so we don't modify the original */ /* 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"); LOG_DIE("Cannot allocate memory for methods string buffer");
strcpy(tmp, str);


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


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


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


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


Expand All @@ -100,11 +101,11 @@ int insert_method(char *method) {
LOG_DIE("Cannot allocate memory for method node"); 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"); LOG_DIE("Cannot allocate memory for method string");
} }
str_copy((*node)->method, method, len + 1);


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


return 1; 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)); ASSERT((hashval >= 0) && (hashval < HASHSIZE));
#endif #endif


strncpy(node->host, host, MAX_HOST_LEN); str_copy(node->host, host, MAX_HOST_LEN);
node->count = 0; node->count = 0;
node->first_packet = t; 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; 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 /* Implementation of Jenkins's One-at-a-Time hash, as described on
this page: http://www.burtleburtle.net/bob/hash/doobs.html */ this page: http://www.burtleburtle.net/bob/hash/doobs.html */
unsigned int hash_str(char *str, unsigned int hashsize) { 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 >> 11);
hash += (hash << 15); 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)); 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_strip_whitespace(char *str);
char *str_tolower(char *str); char *str_tolower(char *str);
int str_compare(const char *str1, const char *str2); 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); unsigned int hash_str(char *key, unsigned int hashsize);


#endif /* ! _HAVE_UTILITY_H */ #endif /* ! _HAVE_UTILITY_H */

0 comments on commit eeee01d

Please sign in to comment.