From 2b2c09f5de666e8feb2dcdec448dfc7b574fb0cb Mon Sep 17 00:00:00 2001 From: scottmk Date: Sat, 12 Sep 2009 16:47:12 +0000 Subject: [PATCH] In osrfStringArrayRemove(): fixed a bug whereby we would decrement the size member even if no string was actually removed. Added Doxygen-style comments to document everything. Removed a few comments in the header so that they wouldn't override comments in the implementation file. git-svn-id: svn://svn.open-ils.org/OpenSRF/trunk@1776 9efc2488-bf62-4759-914b-345cdb29e865 --- include/opensrf/string_array.h | 29 +++++++--- src/libopensrf/string_array.c | 98 ++++++++++++++++++++++++++++++---- 2 files changed, 109 insertions(+), 18 deletions(-) diff --git a/include/opensrf/string_array.h b/include/opensrf/string_array.h index e321444..33d62a0 100644 --- a/include/opensrf/string_array.h +++ b/include/opensrf/string_array.h @@ -1,3 +1,12 @@ +/** + @file string_array.h + @brief Header for osrfStringArray, a vector of strings. + + An osrfStringArray manages an array of character pointers pointing to nul-terminated + strings. New entries are added at the end. When a string is removed, entries above + it are shifted down to fill in the gap. +*/ + #ifndef STRING_ARRAY_H #define STRING_ARRAY_H @@ -11,13 +20,25 @@ extern "C" { #endif +/** + @brief Maximum number of strings in an osrfStringArray. + + This ostensible limit is not enforced. If you exceed it, you'll get an error message, + but only as a slap on the wrist. You'll still get your big list of strings. +*/ #define STRING_ARRAY_MAX_SIZE 4096 +/** @brief Macro version of osrfStringArrayFree() */ #define OSRF_STRING_ARRAY_FREE(arr) osrfListFree( (osrfList*) (arr) ) +/** + @brief Structure of an osrfStringArray. +*/ typedef struct { + /** @brief The underlying container of pointers. */ osrfList list; - int size; // redundant with osrfList.size + /** @brief The number of strings stored. */ + int size; // redundant with list.size } osrfStringArray; osrfStringArray* osrfNewStringArray( int size ); @@ -26,7 +47,6 @@ void osrfStringArrayAdd( osrfStringArray*, const char* str ); char* osrfStringArrayGetString( osrfStringArray* arr, int index ); -/* returns true if this array contains the given string */ int osrfStringArrayContains( const osrfStringArray* arr, const char* string ); @@ -34,11 +54,6 @@ void osrfStringArrayFree( osrfStringArray* ); void osrfStringArrayRemove( osrfStringArray* arr, const char* str ); -/** - Parse a string into tokens separated by a specified delimiter, - as if by strtok() or strtok_r(). Load the tokens into an - osrfStringArray. - */ osrfStringArray* osrfStringArrayTokenize( const char* src, char delim ); #ifdef __cplusplus diff --git a/src/libopensrf/string_array.c b/src/libopensrf/string_array.c index 428ff84..0f2824d 100644 --- a/src/libopensrf/string_array.c +++ b/src/libopensrf/string_array.c @@ -1,5 +1,27 @@ +/** + @file string_array.c + @brief Implement osrfStringArray, a vector of character strings. + + An osrfStringArray is implemented as a thin wrapper around an osrfList. The latter is + incorporated bodily in the osrfStringArray structure, not as a pointer, so as to avoid + a layer of malloc() and free(). + + Operations on the osrfList are restricted so as not to leave NULL pointers in the middle. +*/ + #include +/** + @brief Create and initialize an osrfStringArray. + @param size How many strings to allow space for initially. + @return Pointer to a newly created osrfStringArray. + + If the size parameter is zero, osrfNewStringArray uses a default value. If the initial + allocation isn't big enough, more space will be added as needed. + + The calling code is responsible for freeing the osrfStringArray by calling + osrfStringArrayFree(). +*/ osrfStringArray* osrfNewStringArray(int size) { if(size > STRING_ARRAY_MAX_SIZE) osrfLogError( OSRF_LOG_MARK, "osrfNewStringArray size is too large"); @@ -27,6 +49,15 @@ osrfStringArray* osrfNewStringArray(int size) { return arr; } +/** + @brief Add a string to the end of an osrfStringArray. + @param arr Pointer to the osrfStringArray to which the string will be added. + @param string Pointer to the character string to be added. + + The string stored is a copy; the original is not affected. + + If either parameter is NULL, nothing happens. +*/ void osrfStringArrayAdd( osrfStringArray* arr, const char* string ) { if(arr == NULL || string == NULL ) return; if( arr->list.size > STRING_ARRAY_MAX_SIZE ) @@ -35,11 +66,25 @@ void osrfStringArrayAdd( osrfStringArray* arr, const char* string ) { arr->size = arr->list.size; } +/** + @brief Return a pointer to the string stored at a specified position in an osrfStringArray. + @param arr Pointer to the osrfStringArray. + @param index A zero-based index into the array + @return A pointer to the string stored at the specified position. if it exists; + or else NULL. + + The calling code should treat the returned pointer as if it were const. Some day, + maybe it will be. +*/ char* osrfStringArrayGetString( osrfStringArray* arr, int index ) { if(!arr) return NULL; return OSRF_LIST_GET_INDEX(&arr->list, index); } +/** + @brief Free an osrfStringArray, and all the strings inside it. + @param arr Pointer to the osrfStringArray to be freed. +*/ void osrfStringArrayFree(osrfStringArray* arr) { // This function is a sleazy hack designed to avoid the @@ -55,42 +100,60 @@ void osrfStringArrayFree(osrfStringArray* arr) { // // If these facts ever cease to be true, we'll have to // revisit this function. - + osrfListFree( (osrfList*) arr ); } +/** + @brief Determine whether an osrfStringArray contains a specified string. + @param arr Pointer to the osrfStringArray. + @param string Pointer to the string to be sought. + @return A boolean: 1 if the string is present in the osrfStringArray, or 0 if it isn't. + + The search is case-sensitive. +*/ int osrfStringArrayContains( const osrfStringArray* arr, const char* string ) { if(!(arr && string)) return 0; int i; for( i = 0; i < arr->size; i++ ) { char* str = OSRF_LIST_GET_INDEX(&arr->list, i); - if(str && !strcmp(str, string)) + if(str && !strcmp(str, string)) return 1; } return 0; } +/** + @brief Remove the first occurrence, if any, of a specified string from an osrfStringArray. + @param arr Pointer to the osrfStringArray. + @param tstr Pointer to a string to be removed. +*/ void osrfStringArrayRemove( osrfStringArray* arr, const char* tstr ) { if(!(arr && tstr)) return; int i; char* str; + int removed = 0; // boolean for( i = 0; i < arr->size; i++ ) { - /* find and remove the string */ - str = OSRF_LIST_GET_INDEX(&arr->list, i); + /* find and remove the string */ + str = OSRF_LIST_GET_INDEX(&arr->list, i); if(str && !strcmp(str, tstr)) { - osrfListRemove(&arr->list, i); + osrfListRemove(&arr->list, i); + removed = 1; break; } } - /* disable automatic item freeing on delete and shift - * items up in the array to fill in the gap + if( ! removed ) + return; // Nothing was removed + + /* disable automatic item freeing on delete, and shift + * items down in the array to fill in the gap */ arr->list.freeItem = NULL; - for( ; i < arr->size - 1; i++ ) + for( ; i < arr->size - 1; i++ ) osrfListSet(&arr->list, OSRF_LIST_GET_INDEX(&arr->list, i+1), i); /* remove the last item since it was shifted up */ @@ -101,14 +164,27 @@ void osrfStringArrayRemove( osrfStringArray* arr, const char* tstr ) { arr->size--; } +/** + @brief Tokenize a string into an array of substrings separated by a specified delimiter. + @param src A pointer to the string to be parsed. + @param delim The delimiter character. + @return Pointer to a newly constructed osrfStringArray containing the tokens. + + A series of consecutive delimiter characters is treated as a single separator. + + The input string is left unchanged. + + The calling code is responsible for freeing the osrfStringArray by calling + osrfStringArrayFree(). +*/ osrfStringArray* osrfStringArrayTokenize( const char* src, char delim ) { // Take the length so that we know how big a buffer we need, - // in the worst case. Esitimate the number of tokens, assuming + // in the worst case. Estimate the number of tokens, assuming // 5 characters per token, and add a few for a pad. if( NULL == src || '\0' == *src ) // Got nothing? - return osrfNewStringArray( 1 ); // Retrun empty array + return osrfNewStringArray( 1 ); // Return empty array size_t src_len = strlen( src ); size_t est_count = src_len / 6 + 5; @@ -147,6 +223,6 @@ osrfStringArray* osrfStringArrayTokenize( const char* src, char delim ) } } } - + return arr; } -- 2.43.2