- // safelib.cpp 
-   
- #include "common.h" 
-   
-   
- // prototypes 
- void *SAFE_malloc (int count, size_t element_size, bool cleanup); 
- void *SAFE_realloc (void *allocation, int old_count, int new_count, size_t element_size, bool cleanup); 
- void SAFE_free (void **address_of_pointer_to_allocation); 
- char *SAFE_strncpy (char *destination, const char *source, size_t buffer_size); 
- int SAFE_snprintf (char *destination, size_t buffer_size, const char *fmt, ...); 
- int SAFE_vsnprintf (char *destination, size_t buffer_size, const char *fmt, va_list argptr); 
- char *SAFE_strncatf (char *destination, size_t buffer_size, const char *fmt, ...); 
-   
-   
- void *SAFE_malloc (int count, size_t element_size, bool cleanup) 
- { 
-    // handy wrapper for things we always forget, like checking malloc's returned pointer and 
-    // ensuring the allocated space is zeroed out. 
-   
-    // here we are guaranteed to have some correctly allocated space 
-    return (SAFE_realloc (NULL, 0, count, element_size, cleanup)); 
- } 
-   
-   
- //#pragma warning(disable: 4723) // for zero divide 
- void *SAFE_realloc (void *allocation, int old_count, int new_count, size_t element_size, bool cleanup) 
- { 
-    // handy wrapper for things we always forget, like checking malloc's returned pointer and 
-    // ensuring the extra allocated space is zeroed out if necessary. 
-   
-    void *new_allocation; 
-   
-    // do we want to reallocate a void space ? 
-    if (new_count == 0) 
-    { 
-       SAFE_free (&allocation); // free it if needed 
-       return (NULL); // and return an empty pointer 
-    } 
-   
-    // do we NOT actually need to reallocate ? 
-    if (old_count == new_count) 
-       return (allocation); // allocation is well-suited for the purpose already 
-   
-    // try re allocating the requested size 
-    if (allocation == NULL) 
-       new_allocation = malloc (new_count * element_size); 
-    else 
-       new_allocation = realloc (allocation, new_count * element_size); 
-    if (new_allocation == NULL) 
-       (void *) (1 / (new_count - new_count)); // divide by zero so that the program crashes here 
-   
-    // zero out extra allocated content if necessary 
-    if (cleanup && (new_count > old_count)) 
-       memset ((void *) ((unsigned char *) new_allocation + (old_count * element_size)), 0, (new_count - old_count) * element_size); 
-   
-    return (new_allocation); // here we are guaranteed to have some correctly reallocated space 
- } 
- //#pragma warning(default: 4723) 
-   
-   
- void SAFE_free (void **address_of_pointer_to_allocation) 
- { 
-    // handy wrapper for things we always forget, like checking the buffer pointer's validity 
-    // before freeing it and nulling it out after it has been freed. 
-   
-    if (address_of_pointer_to_allocation == NULL) 
-       return; // consistency check 
-   
-    // is it a valid block pointer ? 
-    if (*address_of_pointer_to_allocation != NULL) 
-       free (*address_of_pointer_to_allocation); // only free valid block pointers 
-    *address_of_pointer_to_allocation = NULL; // reset the pointer (ensures it won't get freed twice) 
-   
-    return; // finished 
- } 
-   
-   
- char *SAFE_strncpy (char *destination, const char *source, size_t buffer_size) 
- { 
-    // handy wrapper for operations we always forget, like checking for string terminations 
-   
-    unsigned int buffer_index; 
-   
-    if ((buffer_size <= 0) || (destination == NULL)) 
-       return (destination); // consistency checks 
-   
-    // for each character we find up to buffer_size... 
-    for (buffer_index = 0; buffer_index < buffer_size; buffer_index++) 
-    { 
-       destination[buffer_index] = source[buffer_index]; // copy everything 
-       if (destination[buffer_index] == 0) 
-          return (destination); // finished, string is copied AND terminated (and it fits) 
-    } 
-   
-    destination[buffer_size - 1] = 0; // string overflown, let us set the terminator zero ourselves 
-    return (destination); // finished, string is copied AND terminated (even if it overflown) 
- } 
-   
-   
- int SAFE_snprintf (char *destination, size_t buffer_size, const char *fmt, ...) 
- { 
-    // handy wrapper for operations we always forget, like checking for string terminations. 
-    // This function should return the number of characters that would be written if there had 
-    // been enough buffer space to be C99 compatible. 
-   
-    va_list argptr; 
-    int result; 
-   
-    if ((buffer_size <= 0) || (destination == NULL)) 
-       return (0); // consistency checks 
-   
-    // concatenate all the arguments in the destination string... 
-    va_start (argptr, fmt); 
-    result = vsnprintf_s (destination, buffer_size, _TRUNCATE, fmt, argptr); 
-    va_end (argptr); 
-   
-    if (result < 0) 
-       destination[buffer_size - 1] = 0; // ...but let us set the terminator zero ourselves 
-   
-    return (result); // finished 
- } 
-   
-   
- int SAFE_vsnprintf (char *destination, size_t buffer_size, const char *fmt, va_list argptr) 
- { 
-    // handy wrapper for operations we always forget, like checking for string terminations. 
-    // This function should return the number of characters that would be written if there had 
-    // been enough buffer space to be C99 compatible. 
-   
-    int result; 
-   
-    if ((buffer_size <= 0) || (destination == NULL)) 
-       return (0); // consistency checks 
-   
-    // concatenate all the arguments in the destination string... 
-    result = vsnprintf_s (destination, buffer_size, _TRUNCATE, fmt, argptr); 
-    if (result < 0) 
-       destination[buffer_size - 1] = 0; // ...but let us set the terminator zero ourselves 
-   
-    return (result); // finished 
- } 
-   
-   
- char *SAFE_strncatf (char *destination, size_t buffer_size, const char *fmt, ...) 
- { 
-    // handy wrapper for operations we always forget, like checking for string terminations. 
-    // This function adds variable arguments to strcat(), printf()-style. 
-   
-    va_list argptr; 
-    char *message; // mallocated, can't be larger than buffer_size 
-    int start_index; 
-    int result; 
-    unsigned int pos; 
-    unsigned int amount_to_copy; 
-   
-    if ((buffer_size <= 0) || (destination == NULL)) 
-       return (destination); // consistency checks 
-   
-    // allocate a buffer large enough for the formatted string 
-    message = (char *) malloc (buffer_size); 
-    if (message == NULL) 
-       return (NULL); // out of memory ? 
-   
-    // concatenate all the arguments in one string 
-    va_start (argptr, fmt); 
-    result = vsnprintf_s (message, buffer_size, _TRUNCATE, fmt, argptr); 
-    va_end (argptr); 
-    if (result < 0) 
-       message[buffer_size - 1] = 0; // ...but let us set the terminator zero ourselves 
-   
-    // get the destination string end position 
-    start_index = strlen (destination); 
-   
-    // see how much data we can copy 
-    amount_to_copy = strlen (message); 
-    if (amount_to_copy > buffer_size - start_index) 
-       amount_to_copy = buffer_size - start_index; // don't copy more than the space left 
-   
-    // and finally append ourselves the right number of characters, not to overflow 
-    for (pos = 0; pos < amount_to_copy; pos++) 
-    { 
-       destination[start_index + pos] = message[pos]; // append message to destination string 
-       if (destination[start_index + pos] == 0) 
-       { 
-          free (message); // free the mallocated memory 
-          return (destination); // don't copy beyond the end of source 
-       } 
-    } 
-    destination[start_index + amount_to_copy] = 0; // ...but let us set the terminator zero ourselves 
-    free (message); // free the mallocated memory 
-    return (destination); // finished 
- } 
-