Subversion Repositories Games.Chess Giants

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. // safelib.cpp
  2.  
  3. #include "common.h"
  4.  
  5.  
  6. // prototypes
  7. void *SAFE_malloc (int count, size_t element_size, bool cleanup);
  8. void *SAFE_realloc (void *allocation, int old_count, int new_count, size_t element_size, bool cleanup);
  9. void SAFE_free (void **address_of_pointer_to_allocation);
  10. char *SAFE_strncpy (char *destination, const char *source, size_t buffer_size);
  11. int SAFE_snprintf (char *destination, size_t buffer_size, const char *fmt, ...);
  12. int SAFE_vsnprintf (char *destination, size_t buffer_size, const char *fmt, va_list argptr);
  13. char *SAFE_strncatf (char *destination, size_t buffer_size, const char *fmt, ...);
  14.  
  15.  
  16. void *SAFE_malloc (int count, size_t element_size, bool cleanup)
  17. {
  18.    // handy wrapper for things we always forget, like checking malloc's returned pointer and
  19.    // ensuring the allocated space is zeroed out.
  20.  
  21.    // here we are guaranteed to have some correctly allocated space
  22.    return (SAFE_realloc (NULL, 0, count, element_size, cleanup));
  23. }
  24.  
  25.  
  26. //#pragma warning(disable: 4723) // for zero divide
  27. void *SAFE_realloc (void *allocation, int old_count, int new_count, size_t element_size, bool cleanup)
  28. {
  29.    // handy wrapper for things we always forget, like checking malloc's returned pointer and
  30.    // ensuring the extra allocated space is zeroed out if necessary.
  31.  
  32.    void *new_allocation;
  33.  
  34.    // do we want to reallocate a void space ?
  35.    if (new_count == 0)
  36.    {
  37.       SAFE_free (&allocation); // free it if needed
  38.       return (NULL); // and return an empty pointer
  39.    }
  40.  
  41.    // do we NOT actually need to reallocate ?
  42.    if (old_count == new_count)
  43.       return (allocation); // allocation is well-suited for the purpose already
  44.  
  45.    // try re allocating the requested size
  46.    if (allocation == NULL)
  47.       new_allocation = malloc (new_count * element_size);
  48.    else
  49.       new_allocation = realloc (allocation, new_count * element_size);
  50.    if (new_allocation == NULL)
  51.       (void *) (1 / (new_count - new_count)); // divide by zero so that the program crashes here
  52.  
  53.    // zero out extra allocated content if necessary
  54.    if (cleanup && (new_count > old_count))
  55.       memset ((void *) ((unsigned char *) new_allocation + (old_count * element_size)), 0, (new_count - old_count) * element_size);
  56.  
  57.    return (new_allocation); // here we are guaranteed to have some correctly reallocated space
  58. }
  59. //#pragma warning(default: 4723)
  60.  
  61.  
  62. void SAFE_free (void **address_of_pointer_to_allocation)
  63. {
  64.    // handy wrapper for things we always forget, like checking the buffer pointer's validity
  65.    // before freeing it and nulling it out after it has been freed.
  66.  
  67.    if (address_of_pointer_to_allocation == NULL)
  68.       return; // consistency check
  69.  
  70.    // is it a valid block pointer ?
  71.    if (*address_of_pointer_to_allocation != NULL)
  72.       free (*address_of_pointer_to_allocation); // only free valid block pointers
  73.    *address_of_pointer_to_allocation = NULL; // reset the pointer (ensures it won't get freed twice)
  74.  
  75.    return; // finished
  76. }
  77.  
  78.  
  79. char *SAFE_strncpy (char *destination, const char *source, size_t buffer_size)
  80. {
  81.    // handy wrapper for operations we always forget, like checking for string terminations
  82.  
  83.    unsigned int buffer_index;
  84.  
  85.    if ((buffer_size <= 0) || (destination == NULL))
  86.       return (destination); // consistency checks
  87.  
  88.    // for each character we find up to buffer_size...
  89.    for (buffer_index = 0; buffer_index < buffer_size; buffer_index++)
  90.    {
  91.       destination[buffer_index] = source[buffer_index]; // copy everything
  92.       if (destination[buffer_index] == 0)
  93.          return (destination); // finished, string is copied AND terminated (and it fits)
  94.    }
  95.  
  96.    destination[buffer_size - 1] = 0; // string overflown, let us set the terminator zero ourselves
  97.    return (destination); // finished, string is copied AND terminated (even if it overflown)
  98. }
  99.  
  100.  
  101. int SAFE_snprintf (char *destination, size_t buffer_size, const char *fmt, ...)
  102. {
  103.    // handy wrapper for operations we always forget, like checking for string terminations.
  104.    // This function should return the number of characters that would be written if there had
  105.    // been enough buffer space to be C99 compatible.
  106.  
  107.    va_list argptr;
  108.    int result;
  109.  
  110.    if ((buffer_size <= 0) || (destination == NULL))
  111.       return (0); // consistency checks
  112.  
  113.    // concatenate all the arguments in the destination string...
  114.    va_start (argptr, fmt);
  115.    result = vsnprintf_s (destination, buffer_size, _TRUNCATE, fmt, argptr);
  116.    va_end (argptr);
  117.  
  118.    if (result < 0)
  119.       destination[buffer_size - 1] = 0; // ...but let us set the terminator zero ourselves
  120.  
  121.    return (result); // finished
  122. }
  123.  
  124.  
  125. int SAFE_vsnprintf (char *destination, size_t buffer_size, const char *fmt, va_list argptr)
  126. {
  127.    // handy wrapper for operations we always forget, like checking for string terminations.
  128.    // This function should return the number of characters that would be written if there had
  129.    // been enough buffer space to be C99 compatible.
  130.  
  131.    int result;
  132.  
  133.    if ((buffer_size <= 0) || (destination == NULL))
  134.       return (0); // consistency checks
  135.  
  136.    // concatenate all the arguments in the destination string...
  137.    result = vsnprintf_s (destination, buffer_size, _TRUNCATE, fmt, argptr);
  138.    if (result < 0)
  139.       destination[buffer_size - 1] = 0; // ...but let us set the terminator zero ourselves
  140.  
  141.    return (result); // finished
  142. }
  143.  
  144.  
  145. char *SAFE_strncatf (char *destination, size_t buffer_size, const char *fmt, ...)
  146. {
  147.    // handy wrapper for operations we always forget, like checking for string terminations.
  148.    // This function adds variable arguments to strcat(), printf()-style.
  149.  
  150.    va_list argptr;
  151.    char *message; // mallocated, can't be larger than buffer_size
  152.    int start_index;
  153.    int result;
  154.    unsigned int pos;
  155.    unsigned int amount_to_copy;
  156.  
  157.    if ((buffer_size <= 0) || (destination == NULL))
  158.       return (destination); // consistency checks
  159.  
  160.    // allocate a buffer large enough for the formatted string
  161.    message = (char *) malloc (buffer_size);
  162.    if (message == NULL)
  163.       return (NULL); // out of memory ?
  164.  
  165.    // concatenate all the arguments in one string
  166.    va_start (argptr, fmt);
  167.    result = vsnprintf_s (message, buffer_size, _TRUNCATE, fmt, argptr);
  168.    va_end (argptr);
  169.    if (result < 0)
  170.       message[buffer_size - 1] = 0; // ...but let us set the terminator zero ourselves
  171.  
  172.    // get the destination string end position
  173.    start_index = strlen (destination);
  174.  
  175.    // see how much data we can copy
  176.    amount_to_copy = strlen (message);
  177.    if (amount_to_copy > buffer_size - start_index)
  178.       amount_to_copy = buffer_size - start_index; // don't copy more than the space left
  179.  
  180.    // and finally append ourselves the right number of characters, not to overflow
  181.    for (pos = 0; pos < amount_to_copy; pos++)
  182.    {
  183.       destination[start_index + pos] = message[pos]; // append message to destination string
  184.       if (destination[start_index + pos] == 0)
  185.       {
  186.          free (message); // free the mallocated memory
  187.          return (destination); // don't copy beyond the end of source
  188.       }
  189.    }
  190.    destination[start_index + amount_to_copy] = 0; // ...but let us set the terminator zero ourselves
  191.    free (message); // free the mallocated memory
  192.    return (destination); // finished
  193. }
  194.