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 | } |