/*------------------------------------------------------------------------------ strings.c - Utilities for managing a variable length string type Create the string with new_string() or new_string_from_array(). When you are finished with the string, it must be deallocated with delete_string(). Other functions are: append_char() - Append a single character to a string append_char_array() - Append a character array to a string append_string() - Append a string to another string clear_string() - Remove the contents of the string clone_string() - Make a copy of a string get_character_array() - Return the contents of the string as a character array prefix_char() - Prefix a single character to a string substring() - Return a new string created from a portion of an existing string Version 1.0 2015-01-30 Brian B. McGuinness ------------------------------------------------------------------------------*/ #include #include #include "strings.h" #define INITIAL_CAPACITY 16 /*------------------------------------------------------------------------------ append_char - Append a single character to a string str = A pointer to the string to be extended c = The character to append ------------------------------------------------------------------------------*/ int append_char (string **str, character c) { if (((*str)->length + 1) >= (*str)->capacity) { int newsize = sizeof (string) + sizeof (character) * ((*str)->capacity << 1); string *new = realloc (*str, newsize); if (new == NULL) return FALSE; *str = new; (*str)->capacity <<= 1; } (*str)->text[(*str)->length++] = c; (*str)->text[(*str)->length] = '\0'; return TRUE; } /*------------------------------------------------------------------------------ append_char_array - Append a character array to a string str = A pointer to a pointer to the string to be extended s = The array to append ------------------------------------------------------------------------------*/ int append_char_array (string **str, character *s) { int length = STRLEN (s); int required = length + (*str)->length + 1; if ((*str)->capacity < required) { int newsize; for (newsize = (*str)->capacity << 1; newsize < required; newsize <<= 1); string *new = realloc (*str, sizeof (string) + sizeof (character) * newsize); if (new == NULL) return FALSE; *str = new; (*str)->capacity = newsize; } STRCOPY ((*str)->text + (*str)->length, s); (*str)->length += length; return TRUE; } /*------------------------------------------------------------------------------ append_string - Append a string to another string str = A pointer to a pointer to the string to be extended s = A pointer to the string to append ------------------------------------------------------------------------------*/ int append_string (string **str, string *s) { return append_char_array (str, s->text); } /*------------------------------------------------------------------------------ clear_string - Remove the contents of the string str = A pointer to the string to be cleared ------------------------------------------------------------------------------*/ void clear_string (string *str) { str->length = 0; str->text[0] = 0; } /*------------------------------------------------------------------------------ clone_string - Make a copy of a string str = A pointer to a pointer to the string to be cloned ------------------------------------------------------------------------------*/ string *clone_string (string *str) { string *result = NULL; if (str != NULL) { result = malloc (sizeof (string) + sizeof (character) * str->capacity); if (result != NULL) { result->capacity = str->capacity; result->length = str->length; STRCOPY (result->text, str->text); } } return result; } /*------------------------------------------------------------------------------ delete_string - Release the memory used by a string str = A pointer to the string to be deallocated ------------------------------------------------------------------------------*/ void delete_string (string *str) { if (str != NULL) free (str); } /*------------------------------------------------------------------------------ get_character_array - Return the contents of the string as a character array str = A pointer to the string to be cleared ------------------------------------------------------------------------------*/ character *get_character_array (string *str) { int length; character *text; if (str == NULL) { length = 0; text = ""; } else { length = str->length; text = str->text; } character *result = malloc (sizeof (character) * (length + 1)); STRCOPY (result, str->text); return result; } /*------------------------------------------------------------------------------ new_string - Create a new string The string must be deallocated with delete_string() when you are finished with it. ------------------------------------------------------------------------------*/ string *new_string () { string *result = malloc (sizeof (string) + sizeof (character) * INITIAL_CAPACITY); if (result != NULL) { result->capacity = INITIAL_CAPACITY; result->length = 0; result->text[0] = 0; } return result; } /*------------------------------------------------------------------------------ new_string_from_array - Create a new string from a character array s = The character array to be placed in a string The string must be deallocated with delete_string() when you are finished with it. ------------------------------------------------------------------------------*/ string *new_string_from_array (character *s) { int textlen = STRLEN (s); int capacity = textlen + 1; capacity += INITIAL_CAPACITY - capacity % INITIAL_CAPACITY; string *result = malloc (sizeof (string) + sizeof (character) * capacity); if (result != NULL) { result->capacity = capacity; result->length = textlen; STRCOPY (result->text, s); } return result; } /*------------------------------------------------------------------------------ prefix_char - Prefix a single character to a string str = A pointer to the string to be extended c = The character to prefix ------------------------------------------------------------------------------*/ int prefix_char (string **str, character c) { int i; if (((*str)->length + 1) >= (*str)->capacity) { int newsize = sizeof (string) + sizeof (character) * ((*str)->capacity << 1); string *new = realloc (*str, newsize); if (new == NULL) return FALSE; *str = new; (*str)->capacity <<= 1; } for (i = (*str)->length; i >= 0; i--) (*str)->text[i + 1] = (*str)->text[i]; (*str)->text[0] = c; (*str)->length++; return TRUE; } /*------------------------------------------------------------------------------ substring - Return a new string created from a portion of an existing string str = A pointer to the string to be deallocated start = The index where the copy is to begin (starting at 0) end = The index just past the end of the desired substring ------------------------------------------------------------------------------*/ string *substring (string *str, int start, int end) { int textlen = end - start; if (textlen < 1 || str == NULL) return new_string (); else { character temp[textlen + 1]; STRNCOPY (temp, str->text + start, textlen); temp[textlen] = '\0'; return new_string_from_array (temp); } }