Permalink
Browse files

Implemented custom string copy functions

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...
1 parent 2c08e37 commit eeee01d0c04da96a213d777ebba9596f4af8bec5 @jbittel committed Dec 8, 2011
Showing with 64 additions and 22 deletions.
  1. +12 −10 format.c
  2. +11 −10 methods.c
  3. +1 −1 rate.c
  4. +38 −1 utility.c
  5. +2 −0 utility.h
View
@@ -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];
@@ -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);
@@ -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) {
@@ -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;
View
@@ -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);
@@ -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;
@@ -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;
View
2 rate.c
@@ -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;
View
@@ -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) {
@@ -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));
}
View
@@ -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.