X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?a=blobdiff_plain;f=lib%2Fvector.c;fp=lib%2Fvector.c;h=0000000000000000000000000000000000000000;hb=b7a32e2d73e3ab1add8208d3e157f7269a31ef4d;hp=7efecf27769aae4c8e9e5359cf9a3b8f654f236a;hpb=ac902a8299ff4469b356836f431ead31c3377377;p=innduct.git diff --git a/lib/vector.c b/lib/vector.c deleted file mode 100644 index 7efecf2..0000000 --- a/lib/vector.c +++ /dev/null @@ -1,409 +0,0 @@ -/* $Id: vector.c 6699 2004-04-07 06:47:44Z rra $ -** -** Vector handling (counted lists of char *'s). -** -** Written by Russ Allbery -** This work is hereby placed in the public domain by its author. -** -** A vector is a table for handling a list of strings with less overhead than -** linked list. The intention is for vectors, once allocated, to be reused; -** this saves on memory allocations once the array of char *'s reaches a -** stable size. -** -** There are two types of vectors. Standard vectors copy strings when -** they're inserted into the vector, whereas cvectors just accept pointers -** to external strings to store. There are therefore two entry points for -** every vector function, one for vectors and one for cvectors. -** -** There's a whole bunch of code duplication here. This would be a lot -** cleaner with C++ features (either inheritance or templates would -** probably help). One could probably in some places just cast a cvector -** to a vector and perform the same operations, but I'm leery of doing that -** as I'm not sure if it's a violation of the C type aliasing rules. -*/ - -#include "config.h" -#include "clibrary.h" -#include - -#include "inn/vector.h" -#include "libinn.h" - -/* -** Allocate a new, empty vector. -*/ -struct vector * -vector_new(void) -{ - struct vector *vector; - - vector = xmalloc(sizeof(struct vector)); - vector->count = 0; - vector->allocated = 0; - vector->strings = NULL; - return vector; -} - -struct cvector * -cvector_new(void) -{ - struct cvector *vector; - - vector = xmalloc(sizeof(struct cvector)); - vector->count = 0; - vector->allocated = 0; - vector->strings = NULL; - return vector; -} - - -/* -** Resize a vector (using realloc to resize the table). -*/ -void -vector_resize(struct vector *vector, size_t size) -{ - size_t i; - - if (vector->count > size) { - for (i = size; i < vector->count; i++) - free(vector->strings[i]); - vector->count = size; - } - if (size == 0) { - free(vector->strings); - vector->strings = NULL; - } else { - vector->strings = xrealloc(vector->strings, size * sizeof(char *)); - } - vector->allocated = size; -} - -void -cvector_resize(struct cvector *vector, size_t size) -{ - if (vector->count > size) - vector->count = size; - if (size == 0) { - free(vector->strings); - vector->strings = NULL; - } else { - vector->strings = - xrealloc(vector->strings, size * sizeof(const char *)); - } - vector->allocated = size; -} - - -/* -** Add a new string to the vector, resizing the vector as necessary. The -** vector is resized an element at a time; if a lot of resizes are expected, -** vector_resize should be called explicitly with a more suitable size. -*/ -void -vector_add(struct vector *vector, const char *string) -{ - size_t next = vector->count; - - if (vector->count == vector->allocated) - vector_resize(vector, vector->allocated + 1); - vector->strings[next] = xstrdup(string); - vector->count++; -} - -void -cvector_add(struct cvector *vector, const char *string) -{ - size_t next = vector->count; - - if (vector->count == vector->allocated) - cvector_resize(vector, vector->allocated + 1); - vector->strings[next] = string; - vector->count++; -} - - -/* -** Empty a vector but keep the allocated memory for the pointer table. -*/ -void -vector_clear(struct vector *vector) -{ - size_t i; - - for (i = 0; i < vector->count; i++) - free(vector->strings[i]); - vector->count = 0; -} - -void -cvector_clear(struct cvector *vector) -{ - vector->count = 0; -} - - -/* -** Free a vector completely. -*/ -void -vector_free(struct vector *vector) -{ - vector_clear(vector); - free(vector->strings); - free(vector); -} - -void -cvector_free(struct cvector *vector) -{ - cvector_clear(vector); - free(vector->strings); - free(vector); -} - - -/* -** Given a vector that we may be reusing, clear it out. If the first -** argument is NULL, allocate a new vector. Used by vector_split*. -*/ -static struct vector * -vector_reuse(struct vector *vector) -{ - if (vector == NULL) - return vector_new(); - else { - vector_clear(vector); - return vector; - } -} - -static struct cvector * -cvector_reuse(struct cvector *vector) -{ - if (vector == NULL) - return cvector_new(); - else { - cvector_clear(vector); - return vector; - } -} - - -/* -** Given a string and a separator character, count the number of strings -** that it will split into. -*/ -static size_t -split_count(const char *string, char separator) -{ - const char *p; - size_t count; - - if (*string == '\0') - return 1; - for (count = 1, p = string; *p; p++) - if (*p == separator) - count++; - return count; -} - - -/* -** Given a string and a separator character, form a vector by splitting the -** string at those separators. Do a first pass to size the vector, and if -** the third argument isn't NULL, reuse it. Otherwise, allocate a new one. -*/ -struct vector * -vector_split(const char *string, char separator, struct vector *vector) -{ - const char *p, *start; - size_t i, count; - - vector = vector_reuse(vector); - - count = split_count(string, separator); - if (vector->allocated < count) - vector_resize(vector, count); - - for (start = string, p = string, i = 0; *p; p++) - if (*p == separator) { - vector->strings[i++] = xstrndup(start, p - start); - start = p + 1; - } - vector->strings[i++] = xstrndup(start, p - start); - vector->count = i; - - return vector; -} - - -/* -** Given a modifiable string and a separator character, form a cvector by -** modifying the string in-place to add nuls at the separators and then -** building a vector of pointers into the string. Do a first pass to size -** the vector, and if the third argument isn't NULL, reuse it. Otherwise, -** allocate a new one. -*/ -struct cvector * -cvector_split(char *string, char separator, struct cvector *vector) -{ - char *p, *start; - size_t i, count; - - vector = cvector_reuse(vector); - - count = split_count(string, separator); - if (vector->allocated < count) - cvector_resize(vector, count); - - for (start = string, p = string, i = 0; *p; p++) - if (*p == separator) { - *p = '\0'; - vector->strings[i++] = start; - start = p + 1; - } - vector->strings[i++] = start; - vector->count = i; - - return vector; -} - - -/* -** Given a string, count the number of strings that it will split into when -** splitting on whitespace. -*/ -static size_t -split_space_count(const char *string) -{ - const char *p; - size_t count; - - if (*string == '\0') - return 0; - for (count = 1, p = string + 1; *p != '\0'; p++) - if ((*p == ' ' || *p == '\t') && !(p[-1] == ' ' || p[-1] == '\t')) - count++; - - /* If the string ends in whitespace, we've overestimated the number of - strings by one. */ - if (p[-1] == ' ' || p[-1] == '\t') - count--; - return count; -} - - -/* -** Given a string, split it at whitespace to form a vector, copying each -** string segment. If the fourth argument isn't NULL, reuse that vector; -** otherwise, allocate a new one. Any number of consecutive whitespace -** characters is considered a single separator. -*/ -struct vector * -vector_split_space(const char *string, struct vector *vector) -{ - const char *p, *start; - size_t i, count; - - vector = vector_reuse(vector); - - count = split_space_count(string); - if (vector->allocated < count) - vector_resize(vector, count); - - for (start = string, p = string, i = 0; *p; p++) - if (*p == ' ' || *p == '\t') { - if (start != p) - vector->strings[i++] = xstrndup(start, p - start); - start = p + 1; - } - if (start != p) - vector->strings[i++] = xstrndup(start, p - start); - vector->count = i; - - return vector; -} - - -/* -** Given a string, split it at whitespace to form a vector, destructively -** modifying the string to nul-terminate each segment. If the fourth -** argument isn't NULL, reuse that vector; otherwise, allocate a new one. -** Any number of consecutive whitespace characters is considered a single -** separator. -*/ -struct cvector * -cvector_split_space(char *string, struct cvector *vector) -{ - char *p, *start; - size_t i, count; - - vector = cvector_reuse(vector); - - count = split_space_count(string); - if (vector->allocated < count) - cvector_resize(vector, count); - - for (start = string, p = string, i = 0; *p; p++) - if (*p == ' ' || *p == '\t') { - if (start != p) { - *p = '\0'; - vector->strings[i++] = start; - } - start = p + 1; - } - if (start != p) - vector->strings[i++] = start; - vector->count = i; - - return vector; -} - - -/* -** Given a vector and a separator string, allocate and build a new string -** composed of all the strings in the vector separated from each other by the -** seperator string. Caller is responsible for freeing. -*/ -char * -vector_join(const struct vector *vector, const char *seperator) -{ - char *string; - size_t i, size, seplen; - - seplen = strlen(seperator); - for (size = 0, i = 0; i < vector->count; i++) - size += strlen(vector->strings[i]); - size += (vector->count - 1) * seplen + 1; - - string = xmalloc(size); - strlcpy(string, vector->strings[0], size); - for (i = 1; i < vector->count; i++) { - strlcat(string, seperator, size); - strlcat(string, vector->strings[i], size); - } - - return string; -} - -char * -cvector_join(const struct cvector *vector, const char *seperator) -{ - char *string; - size_t i, size, seplen; - - seplen = strlen(seperator); - for (size = 0, i = 0; i < vector->count; i++) - size += strlen(vector->strings[i]); - size += (vector->count - 1) * seplen + 1; - - string = xmalloc(size); - strlcpy(string, vector->strings[0], size); - for (i = 1; i < vector->count; i++) { - strlcat(string, seperator, size); - strlcat(string, vector->strings[i], size); - } - - return string; -}