Subversion Repositories Games.Chess Giants

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 pmbaty 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
}