Commit | Line | Data |
---|---|---|
d44e3c4f | 1 | /****************************************************************************** |
2 | * Copyright (c) 2000-2016 Ericsson Telecom AB | |
3 | * All rights reserved. This program and the accompanying materials | |
4 | * are made available under the terms of the Eclipse Public License v1.0 | |
5 | * which accompanies this distribution, and is available at | |
6 | * http://www.eclipse.org/legal/epl-v10.html | |
7 | * | |
8 | * Contributors: | |
9 | * Balasko, Jeno | |
10 | * Lovassy, Arpad | |
11 | * Raduly, Csaba | |
12 | * Szabo, Janos Zoltan – initial implementation | |
13 | * | |
14 | ******************************************************************************/ | |
970ed795 EL |
15 | #ifndef _Common_memory_H |
16 | #define _Common_memory_H | |
17 | ||
18 | #include <stddef.h> | |
19 | #include <stdarg.h> | |
20 | ||
21 | #ifndef __GNUC__ | |
22 | /** If a C compiler other than GCC is used the macro below will substitute all | |
23 | * GCC-specific non-standard attributes with an empty string. */ | |
24 | #ifndef __attribute__ | |
25 | #define __attribute__(arg) | |
26 | #endif | |
27 | #endif | |
28 | ||
29 | #ifdef __cplusplus | |
30 | extern "C" { | |
31 | #endif | |
32 | ||
33 | /** | |
34 | * \defgroup mem Memory management and expstring functions | |
35 | * \brief Functions for memory management and string handling. | |
36 | * \author Janos Zoltan Szabo <Janos.Zoltan.Szabo@ericsson.com> | |
37 | * | |
38 | * Primarily used in the TTCN-3 Test Executor (TTCN-3, ASN.1 compilers and | |
39 | * runtime environment). | |
40 | * @{ | |
41 | */ | |
42 | ||
43 | /** | |
44 | * Same as the standard \c malloc(), but it never returns NULL. | |
45 | * It increases a malloc counter. If there is not enough memory, | |
46 | * it calls \c fatal_error(), which exits the application. | |
47 | * | |
48 | * @param size number of bytes to allocate | |
49 | * @return pointer to the beginning of the allocated memory, or | |
50 | * NULL if and only if \c size is 0 | |
51 | */ | |
52 | extern void *Malloc(size_t size); | |
53 | #ifdef MEMORY_DEBUG | |
54 | extern void *Malloc_dbg(const char *filename, int line, size_t size); | |
55 | #define Malloc(s) Malloc_dbg(__FILE__, __LINE__, s) | |
56 | #endif | |
57 | ||
58 | /** | |
59 | * Same as the standard \c realloc(), but it never returns NULL if \a size is | |
60 | * positive. It updates the malloc or free counters if necessary. | |
61 | * Exits if there is not enough memory. | |
62 | * | |
63 | * @param ptr pointer to a memory block allocated by Malloc(). If \p ptr | |
64 | * is NULL, calls Malloc(size) | |
65 | * @param size new size for the memory block. If \p size is 0, it calls | |
66 | * Free(ptr) and returns NULL. | |
67 | * @return pointer to the beginning of the re-allocated memory. | |
68 | * Will only be NULL if size==0. | |
69 | */ | |
70 | extern void *Realloc(void *ptr, size_t size); | |
71 | #ifdef MEMORY_DEBUG | |
72 | extern void *Realloc_dbg(const char *filename, int line, void *ptr, size_t size); | |
73 | #define Realloc(p,s) Realloc_dbg(__FILE__, __LINE__, p, s) | |
74 | #endif | |
75 | ||
76 | /** | |
77 | * Same as the standard \c free(). It increases the free counter if \a ptr | |
78 | * is not NULL. | |
79 | * | |
80 | * @param ptr pointer to a memory block allocated by Malloc(). If \p ptr | |
81 | * is NULL, this function does nothing. | |
82 | */ | |
83 | extern void Free(void *ptr); | |
84 | #ifdef MEMORY_DEBUG | |
85 | extern void Free_dbg(const char *filename, int line, void *ptr); | |
86 | #define Free(p) Free_dbg(__FILE__, __LINE__, p) | |
87 | #endif | |
88 | ||
89 | /** | |
90 | * Prints a warning message to stderr if the malloc and free counters | |
91 | * are not equals. It shall be called immediately before the end of | |
92 | * program run. | |
93 | */ | |
94 | extern void check_mem_leak(const char *program_name); | |
95 | ||
96 | #ifdef MEMORY_DEBUG | |
97 | /** | |
98 | * Checks all allocated blocks of the program. Prints an error message and | |
99 | * aborts if memory over-indexing is detected. | |
100 | */ | |
101 | extern void check_mem_corrupt(const char *program_name); | |
102 | ||
103 | #ifdef MEMORY_DEBUG_ADDRESS | |
104 | /** @brief Memory allocation checkpoint. | |
105 | ||
106 | If this variable is set to a nonzero value, allocations starting | |
107 | at that address will be logged to stderr. | |
108 | ||
109 | This can be used in conjunction with the output of check_mem_leak(). | |
110 | */ | |
111 | extern void * memory_debug_address; | |
112 | #endif | |
113 | #endif | |
114 | ||
115 | /** | |
116 | * Character string type with exponential buffer allocation. The size of | |
117 | * allocated buffer is always a power of 2. The terminating '\\0' character | |
118 | * is always present and the remaining bytes in the buffer are also set to | |
119 | * zero. This allows binary search for the end of string, which is | |
120 | * significantly faster than the linear one especially for long strings. | |
121 | * The spare bytes at the end make appending of small chunks very efficient. | |
122 | * | |
123 | * \warning If a function takes expstring_t as argument | |
124 | * you should not pass a regular string (or a static string literal) | |
125 | * to it. This may result in an unpredictable behaviour. You can | |
126 | * convert any regular string to expstring_t using mcopystr: | |
127 | * myexpstring = mcopystr(myregularstring); | |
128 | */ | |
129 | typedef char *expstring_t; | |
130 | ||
131 | /** | |
132 | * mprintf() takes its arguments like \c printf() and prints according | |
133 | * to the format string \a fmt into a string buffer. It allocates | |
134 | * enough memory for the resulting string and returns the pointer | |
135 | * to the result string. The result string is an exponential string. | |
136 | * mprintf() never returns NULL. | |
137 | */ | |
138 | extern expstring_t mprintf(const char *fmt, ...) | |
139 | __attribute__ ((__format__ (__printf__, 1, 2))); | |
140 | #ifdef MEMORY_DEBUG | |
141 | extern expstring_t mprintf_dbg(const char *filename, int line, const char *fmt, ...) | |
142 | __attribute__ ((__format__ (__printf__, 3, 4))); | |
143 | #if defined(__GNUC__) && __GNUC__ < 3 | |
144 | # define mprintf(f, args...) mprintf_dbg(__FILE__, __LINE__, f, ## args) | |
145 | #else | |
146 | # define mprintf(f,...) mprintf_dbg(__FILE__, __LINE__, f, __VA_ARGS__) | |
147 | #endif | |
148 | #endif | |
149 | ||
150 | /** | |
151 | * The same as \a mprintf(), but it takes the arguments as va_list. | |
152 | * It is useful in wrapper functions with printf style argument strings. | |
153 | */ | |
154 | extern expstring_t mprintf_va_list(const char *fmt, va_list pvar); | |
155 | #ifdef MEMORY_DEBUG | |
156 | extern expstring_t mprintf_va_list_dbg(const char *filename, int line, | |
157 | const char *fmt, va_list pvar); | |
158 | #define mprintf_va_list(f,v) mprintf_va_list_dbg(__FILE__, __LINE__, f, v) | |
159 | #endif | |
160 | ||
161 | /** | |
162 | * mputprintf() prints its additional arguments according to the | |
163 | * format string \a fmt at the end of \a str. The buffer of \a str is | |
164 | * increased if the appended bytes do not fit in it. The result | |
165 | * string, which is also an expstring, is returned. | |
166 | * mputprintf() never returns NULL. | |
167 | * \note If str is NULL it is equivalent to \a mprintf(). | |
168 | * \warning The first argument must be an exponential string, | |
169 | * otherwise its behaviour may be unpredictable. | |
170 | */ | |
171 | extern expstring_t mputprintf(expstring_t str, const char *fmt, ...) | |
172 | __attribute__ ((__format__ (__printf__, 2, 3))); | |
173 | ||
174 | /** | |
175 | * The same as \a mputprintf(), but it takes the arguments as va_list. | |
176 | * It is useful in wrapper functions with printf style argument strings. | |
177 | */ | |
178 | extern expstring_t mputprintf_va_list(expstring_t str, const char *fmt, | |
179 | va_list pvar); | |
180 | ||
181 | /** | |
182 | * memptystr() creates and returns a new empty exponential string. | |
183 | * The returned value is never NULL, | |
184 | * it shall be deallocated using \a Free(). | |
185 | */ | |
186 | extern expstring_t memptystr(void); | |
187 | #ifdef MEMORY_DEBUG | |
188 | extern expstring_t memptystr_dbg(const char *filename, int line); | |
189 | #define memptystr() memptystr_dbg(__FILE__, __LINE__) | |
190 | #endif | |
191 | ||
192 | ||
193 | /** | |
194 | * mcopystr() creates a new exponential string and copies the contents of | |
195 | * \a str into it. The resulting expstring is returned. | |
196 | * The regular string \a str will not be deallocated and it may be | |
197 | * a static string literal. | |
198 | * If \a str is NULL an empty exponential string is returned. | |
199 | * mcopystr() never returns NULL. | |
200 | */ | |
201 | extern expstring_t mcopystr(const char *str); | |
202 | #ifdef MEMORY_DEBUG | |
203 | extern expstring_t mcopystr_dbg(const char *filename, int line, const char *str); | |
204 | #define mcopystr(s) mcopystr_dbg(__FILE__, __LINE__, s) | |
205 | #endif | |
206 | ||
207 | /** | |
208 | * Create a new exponential string when the length is known. | |
209 | * Works exactly like mcopystr(), except the length is not measured; | |
210 | * the given length is used instead. | |
211 | * | |
212 | * @param str pointer to the original string; does not need to be 0-terminated | |
213 | * @param len number of characters to copy | |
214 | * @return the newly constructed string (it needs to be Free()-d) | |
215 | */ | |
216 | extern expstring_t mcopystrn(const char *str, size_t len); | |
217 | #ifdef MEMORY_DEBUG | |
218 | extern expstring_t mcopystrn_dbg(const char *filename, int line, const char *str, | |
219 | size_t len); | |
220 | #define mcopystrn(s, len) mcopystrn_dbg(__FILE__, __LINE__, s, len) | |
221 | #endif | |
222 | ||
223 | /** | |
224 | * mputstr() appends the regular string \a str2 to the end of | |
225 | * expstring \a str. The resulting expstring is returned. | |
226 | * The buffer of \a str is increased if necessary. | |
227 | * If \a str is NULL then \a str2 is copied into a new exponential string | |
228 | * (i.e. mputstr(NULL, str) is identical to mcopystr(str)). | |
229 | * If \a str2 is NULL then \a str is returned and remains unchanged | |
230 | * (i.e. mputstr(str, NULL) is identical to str, | |
231 | * mputstr(NULL, NULL) always returns NULL). | |
232 | * \warning The first argument must be an exponential string, | |
233 | * otherwise its behaviour may be unpredictable. | |
234 | */ | |
235 | extern expstring_t mputstr(expstring_t str, const char *str2); | |
236 | ||
237 | /** Appends \a len2 characters from the regular string \a str2 to the end of | |
238 | * expstring \a str. The resulting expstring is returned. @see mputstr() | |
239 | * @param str destination string | |
240 | * @param str2 pointer to characters; does not need to be 0-terminated | |
241 | * @param len2 number of characters to copy | |
242 | * @return the (possibly reallocated) str | |
243 | */ | |
244 | extern expstring_t mputstrn(expstring_t str, const char *str2, size_t len2); | |
245 | ||
246 | /** | |
247 | * mputc() appends the single character \a c to the end of | |
248 | * expstring \a str. The buffer of \a str is increased if necessary. | |
249 | * The resulting expstring is returned. | |
250 | * If \a str is NULL then \a c is converted to a new exponential string. | |
251 | * If \a c is '\\0' then \a str is returned. | |
252 | * mputc() never returns NULL. | |
253 | * \warning The first argument must be an exponential string, | |
254 | * otherwise its behaviour may be unpredictable. | |
255 | */ | |
256 | extern expstring_t mputc(expstring_t str, char c); | |
257 | ||
258 | /** | |
259 | * mtruncstr() truncates the expstring \a str by keeping only the first | |
260 | * \a newlen characters and returns the resulting string. | |
261 | * If the string is shorter than \a newlen it remains unchanged. | |
262 | * mtruncstr() may perform memory reallocation if necessary. | |
263 | * If \a str is NULL then a NULL pointer is returned. | |
264 | * If \a str is not an exponential string the behaviour of mtruncstr() may | |
265 | * be unpredictable. | |
266 | */ | |
267 | extern expstring_t mtruncstr(expstring_t str, size_t newlen); | |
268 | ||
269 | /** | |
270 | * mstrlen() returns the length of expstring \a str or zero if \a str is | |
271 | * NULL. If \a str is not NULL the function has identical result as libc's | |
272 | * strlen(), but operates significantly faster. The behaviour may be | |
273 | * unpredictable if \a str is not an exponential string. | |
274 | */ | |
275 | extern size_t mstrlen(const expstring_t str); | |
276 | ||
277 | /** @} end of mem group */ | |
278 | ||
279 | /** Return the string for the build number. | |
280 | * | |
281 | * @param b build number. | |
282 | * @return a string which must be Free()-d by the caller | |
283 | * @pre b > 0 and b <= 99, or else NULL is returned | |
284 | */ | |
285 | char * buildstr(int b); | |
286 | ||
287 | #ifdef __cplusplus | |
288 | /** Convert a patch level to the "Ericsson letter" */ | |
289 | inline char eri(unsigned int p) { /* p stands for patch level */ | |
290 | char i = (char)('A' + p); /* i stands for "if only it was that simple" */ | |
291 | return i + (i >= 'I') + 4 * (i >= 'N') + (i >= 'R'); | |
292 | } | |
293 | ||
294 | } /* extern "C" */ | |
295 | ||
296 | #endif | |
297 | ||
298 | #endif /* _Common_memory_H */ |