#include #include #include typedef unsigned char mystring_data_t; typedef struct mystring { mystring_data_t * data; size_t size; size_t length; } mystring_t; static void mystring_fail (const char * message, ...) { va_list args; va_start (args, message); vfprintf (stderr, message, args); va_end (args); fprintf (stderr, "\n"); exit (EXIT_FAILURE); } static void mystring_vprintf (mystring_t * mystring, const char * format, va_list arguments) { int printed_length; int remaining; mystring_data_t * write_point; /* If there is not enough allocated memory within "mystring" to print the required text of "format" and "arguments", we have to re-attempt the printing, thus we need to copy "arguments" for the case of a failure. */ va_list copy4fail; va_copy (copy4fail, arguments); write_point = mystring->data + mystring->length; /* Number of remaining characters. */ remaining = mystring->size - mystring->length; printf ("remaining = %d, size = %d\n", remaining, mystring->size); printed_length = vsnprintf ((char *) write_point, remaining, format, arguments); if (printed_length >= remaining - 1) { /* First attempt to print failed. Resize the mystring and try again. */ mystring->size = mystring->length + printed_length + 1; printf ("printed_length = %d, size = %d\n", printed_length, mystring->size); mystring->data = realloc (mystring->data, mystring->size); if (! mystring->data) { mystring_fail ("no memory"); } remaining = mystring->size - mystring->length; /* We need to get the write point again since the memory may have moved, due to realloc. */ write_point = mystring->data + mystring->length; printed_length = vsnprintf ((char *) write_point, remaining, format, copy4fail); /* If the printed length is still greater than the supposed remaining number of characters, there must have been an error, so end processing. */ if (printed_length > remaining) { mystring_fail ("Inconsistent printed length %d remaining %d", printed_length, remaining); } } mystring->length += (size_t) printed_length; va_end (copy4fail); } static void mystring_printf (mystring_t * mystring, char * format, ...) { va_list args; va_start (args, format); mystring_vprintf (mystring, format, args); va_end (args); } int main () { mystring_t mystring; mystring.size = 10; mystring.data = calloc (mystring.size, sizeof (mystring_data_t)); if (! mystring.data) { fprintf (stderr, "Memory failure.\n"); return -1; } mystring.data[0] = 'a'; mystring.data[1] = 'b'; mystring.length = 2; mystring_printf (& mystring, "supercallifragilisticexpialidocious %d %d %d", 99, 100, 101); printf ("'%s'\n", (char *) mystring.data); free (mystring.data); return 0; }