]> git.xonotic.org Git - xonotic/gmqcc.git/blob - util.c
Implemented support for multiple element (with assisted length) insertion on VECTOR_...
[xonotic/gmqcc.git] / util.c
1 /*
2  * Copyright (C) 2012
3  *     Dale Weiler
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a copy of
6  * this software and associated documentation files (the "Software"), to deal in
7  * the Software without restriction, including without limitation the rights to
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
9  * of the Software, and to permit persons to whom the Software is furnished to do
10  * so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in all
13  * copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21  * SOFTWARE.
22  */
23 #include <stdarg.h>
24 #include <errno.h>
25 #include "gmqcc.h"
26
27 unsigned long long mem_ab = 0;
28 unsigned long long mem_db = 0;
29 unsigned long long mem_at = 0;
30 unsigned long long mem_dt = 0;
31
32 struct memblock_t {
33     const char  *file;
34     unsigned int line;
35     unsigned int byte;
36 };
37
38 void *util_memory_a(unsigned int byte, unsigned int line, const char *file) {
39     struct memblock_t *info = malloc(sizeof(struct memblock_t) + byte);
40     void              *data =(void*)((uintptr_t)info+sizeof(struct memblock_t));
41     if (!data) return NULL;
42     info->line = line;
43     info->byte = byte;
44     info->file = file;
45
46     util_debug("MEM", "allocation: % 8u (bytes) address 0x%08X @ %s:%u\n", byte, data, file, line);
47     mem_at++;
48     mem_ab += info->byte;
49     return data;
50 }
51
52 void util_memory_d(void *ptrn, unsigned int line, const char *file) {
53     if (!ptrn) return;
54     void              *data = (void*)((uintptr_t)ptrn-sizeof(struct memblock_t));
55     struct memblock_t *info = (struct memblock_t*)data;
56
57     util_debug("MEM", "released:   % 8u (bytes) address 0x%08X @ %s:%u\n", info->byte, data, file, line);
58     mem_db += info->byte;
59     mem_dt++;
60     free(data);
61 }
62
63 void util_meminfo() {
64     if (!opts_memchk)
65         return;
66
67     util_debug("MEM", "Memory information:\n\
68         Total allocations:   %llu\n\
69         Total deallocations: %llu\n\
70         Total allocated:     %llu (bytes)\n\
71         Total deallocated:   %llu (bytes)\n\
72         Leaks found:         lost %llu (bytes) in %d allocations\n",
73             mem_at,   mem_dt,
74             mem_ab,   mem_db,
75            (mem_ab -  mem_db),
76            (mem_at -  mem_dt)
77     );
78 }
79
80 /*
81  * Some string utility functions, because strdup uses malloc, and we want
82  * to track all memory (without replacing malloc).
83  */
84 char *util_strdup(const char *s) {
85     size_t  len = 0;
86     char   *ptr = NULL;
87
88     if (!s)
89         return NULL;
90
91     if ((len = strlen(s)) && (ptr = mem_a(len+1))) {
92         memcpy(ptr, s, len);
93         ptr[len] = '\0';
94     }
95     return ptr;
96 }
97
98 /*
99  * Remove quotes from a string, escapes from \ in string
100  * as well.  This function shouldn't be used to create a
101  * char array that is later freed (it uses pointer arith)
102  */
103 char *util_strrq(char *s) {
104     char *dst = s;
105     char *src = s;
106     char  chr;
107     while ((chr = *src++) != '\0') {
108         if (chr == '\\') {
109             *dst++ = chr;
110             if ((chr = *src++) == '\0')
111                 break;
112             *dst++ = chr;
113         } else if (chr != '"')
114             *dst++ = chr;
115     }
116     *dst = '\0';
117     return dst;
118 }
119
120 /*
121  * Remove newline from a string (if it exists).  This is
122  * done pointer wise instead of strlen(), and an array
123  * access.
124  */
125 char *util_strrnl(char *src) {
126     if (!src) return NULL;
127     char   *cpy = src;
128     while (*cpy && *cpy != '\n')
129         cpy++;
130
131     *cpy = '\0';
132     return src;
133 }
134
135 void util_debug(const char *area, const char *ms, ...) {
136     if (!opts_debug)
137         return;
138
139     va_list  va;
140     va_start(va, ms);
141     fprintf (stdout, "DEBUG: ");
142     fputc   ('[',  stdout);
143     fprintf(stdout, "%s", area);
144     fputs   ("] ", stdout);
145     vfprintf(stdout, ms, va);
146     va_end  (va);
147 }
148
149 /*
150  * Endianess swapping, all data must be stored little-endian.  This
151  * reorders by stride and length, much nicer than other functions for
152  * certian-sized types like short or int.
153  */
154 void util_endianswap(void *m, int s, int l) {
155     size_t w = 0;
156     size_t i = 0;
157
158     /* ignore if we're already LE */
159     if(*((char *)&s))
160         return;
161
162     for(; w < l; w++) {
163         for(;  i < s << 1; i++) {
164             unsigned char *p = (unsigned char *)m+w*s;
165             unsigned char  t = p[i];
166             p[i]             = p[s-i-1];
167             p[s-i-1]         = t;
168         }
169     }
170 }
171
172 /*
173  * This is an implementation of CRC32 & CRC16. The polynomials have been
174  * offline computed for faster generation at the cost of larger code size.
175  *
176  * CRC32 Polynomial: 0xEDB88320
177  * CRC16 Polynomial: 0x00001021
178  */
179 static const uint32_t util_crc32_table[] = {
180     0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F,
181     0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
182     0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,
183     0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
184     0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9,
185     0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
186     0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
187     0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
188     0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
189     0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
190     0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106,
191     0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
192     0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
193     0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
194     0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
195     0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
196     0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7,
197     0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
198     0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA,
199     0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
200     0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
201     0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
202     0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84,
203     0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
204     0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB,
205     0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
206     0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E,
207     0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
208     0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55,
209     0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
210     0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28,
211     0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
212     0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,
213     0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
214     0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
215     0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
216     0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69,
217     0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
218     0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
219     0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
220     0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693,
221     0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
222     0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
223 };
224 static const uint16_t util_crc16_table[] = {
225     0x0000,     0x1021,     0x2042,     0x3063,     0x4084,     0x50A5,
226     0x60C6,     0x70E7,     0x8108,     0x9129,     0xA14A,     0xB16B,
227     0xC18C,     0xD1AD,     0xE1CE,     0xF1EF,     0x1231,     0x0210,
228     0x3273,     0x2252,     0x52B5,     0x4294,     0x72F7,     0x62D6,
229     0x9339,     0x8318,     0xB37B,     0xA35A,     0xD3BD,     0xC39C,
230     0xF3FF,     0xE3DE,     0x2462,     0x3443,     0x0420,     0x1401,
231     0x64E6,     0x74C7,     0x44A4,     0x5485,     0xA56A,     0xB54B,
232     0x8528,     0x9509,     0xE5EE,     0xF5CF,     0xC5AC,     0xD58D,
233     0x3653,     0x2672,     0x1611,     0x0630,     0x76D7,     0x66F6,
234     0x5695,     0x46B4,     0xB75B,     0xA77A,     0x9719,     0x8738,
235     0xF7DF,     0xE7FE,     0xD79D,     0xC7BC,     0x48C4,     0x58E5,
236     0x6886,     0x78A7,     0x0840,     0x1861,     0x2802,     0x3823,
237     0xC9CC,     0xD9ED,     0xE98E,     0xF9AF,     0x8948,     0x9969,
238     0xA90A,     0xB92B,     0x5AF5,     0x4AD4,     0x7AB7,     0x6A96,
239     0x1A71,     0x0A50,     0x3A33,     0x2A12,     0xDBFD,     0xCBDC,
240     0xFBBF,     0xEB9E,     0x9B79,     0x8B58,     0xBB3B,     0xAB1A,
241     0x6CA6,     0x7C87,     0x4CE4,     0x5CC5,     0x2C22,     0x3C03,
242     0x0C60,     0x1C41,     0xEDAE,     0xFD8F,     0xCDEC,     0xDDCD,
243     0xAD2A,     0xBD0B,     0x8D68,     0x9D49,     0x7E97,     0x6EB6,
244     0x5ED5,     0x4EF4,     0x3E13,     0x2E32,     0x1E51,     0x0E70,
245     0xFF9F,     0xEFBE,     0xDFDD,     0xCFFC,     0xBF1B,     0xAF3A,
246     0x9F59,     0x8F78,     0x9188,     0x81A9,     0xB1CA,     0xA1EB,
247     0xD10C,     0xC12D,     0xF14E,     0xE16F,     0x1080,     0x00A1,
248     0x30C2,     0x20E3,     0x5004,     0x4025,     0x7046,     0x6067,
249     0x83B9,     0x9398,     0xA3FB,     0xB3DA,     0xC33D,     0xD31C,
250     0xE37F,     0xF35E,     0x02B1,     0x1290,     0x22F3,     0x32D2,
251     0x4235,     0x5214,     0x6277,     0x7256,     0xB5EA,     0xA5CB,
252     0x95A8,     0x8589,     0xF56E,     0xE54F,     0xD52C,     0xC50D,
253     0x34E2,     0x24C3,     0x14A0,     0x0481,     0x7466,     0x6447,
254     0x5424,     0x4405,     0xA7DB,     0xB7FA,     0x8799,     0x97B8,
255     0xE75F,     0xF77E,     0xC71D,     0xD73C,     0x26D3,     0x36F2,
256     0x0691,     0x16B0,     0x6657,     0x7676,     0x4615,     0x5634,
257     0xD94C,     0xC96D,     0xF90E,     0xE92F,     0x99C8,     0x89E9,
258     0xB98A,     0xA9AB,     0x5844,     0x4865,     0x7806,     0x6827,
259     0x18C0,     0x08E1,     0x3882,     0x28A3,     0xCB7D,     0xDB5C,
260     0xEB3F,     0xFB1E,     0x8BF9,     0x9BD8,     0xABBB,     0xBB9A,
261     0x4A75,     0x5A54,     0x6A37,     0x7A16,     0x0AF1,     0x1AD0,
262     0x2AB3,     0x3A92,     0xFD2E,     0xED0F,     0xDD6C,     0xCD4D,
263     0xBDAA,     0xAD8B,     0x9DE8,     0x8DC9,     0x7C26,     0x6C07,
264     0x5C64,     0x4C45,     0x3CA2,     0x2C83,     0x1CE0,     0x0CC1,
265     0xEF1F,     0xFF3E,     0xCF5D,     0xDF7C,     0xAF9B,     0xBFBA,
266     0x8FD9,     0x9FF8,     0x6E17,     0x7E36,     0x4E55,     0x5E74,
267     0x2E93,     0x3EB2,     0x0ED1,     0x1EF0
268 };
269     
270 /*
271  * Implements a CRC function for X worth bits using (uint[X]_t)
272  * as type. and util_crc[X]_table.
273  */
274 #define CRC(X) \
275 uint##X##_t util_crc##X(const char *k, int len, const short clamp) {  \
276     register uint##X##_t h= (uint##X##_t)0xFFFFFFFF;                  \
277     for (; len; --len, ++k)                                           \
278         h = util_crc##X##_table[(h^((unsigned char)*k))&0xFF]^(h>>8); \
279     return (~h)%clamp;                                                \
280 }
281 CRC(32)
282 CRC(16)
283 #undef CRC
284
285 /*
286  * Implements libc getline for systems that don't have it, which is
287  * assmed all.  This works the same as getline().
288  */
289 int util_getline(char **lineptr, size_t *n, FILE *stream) {
290     int   chr;
291     int   ret;
292     char *pos;
293
294     if (!lineptr || !n || !stream)
295         return -1;
296     if (!*lineptr) {
297         if (!(*lineptr = mem_a((*n=64))))
298             return -1;
299     }
300
301     chr = *n;
302     pos = *lineptr;
303
304     for (;;) {
305         int c = getc(stream);
306
307         if (chr < 2) {
308             char *tmp = mem_a((*n+=(*n>16)?*n:64));
309             if  (!tmp)
310                 return -1;
311
312             chr = *n + *lineptr - pos;
313             strcpy(tmp,*lineptr);
314             if (!(*lineptr = tmp)) {
315                 mem_d (tmp);
316                 return -1;
317             }
318             pos = *n - chr + *lineptr;
319         }
320
321         if (ferror(stream))
322             return -1;
323         if (c == EOF) {
324             if (pos == *lineptr)
325                 return -1;
326             else
327                 break;
328         }
329
330         *pos++ = c;
331         chr--;
332         if (c == '\n')
333             break;
334     }
335     *pos = '\0';
336     return (ret = pos - *lineptr);
337 }
338
339 /*
340  * Strechy string buffer (for easy string creation) -- this is fast, just
341  * say no to strict aliasing.
342  */
343 //#define util_stringbuf_add(a,v) ((((a)==0 ||((int*)(a)-2)[1]+(1)>=((int*)(a)-2)[0])?util_stringbuf_grow((void**)&(a),(1),sizeof(*(a))):0),(a)[((int*)(a)-2)[1]++]=(v))
344 //#define util_stringbuf_len(a)   ((a)?       ((int*)(a)-2)[1]:0)
345 //#define util_stringbuf_del(a)   ((a)?free  (((int*)(a)-2)),0:0)
346 void *util_stringbuf_grow(void **a, int in, int it) {
347     int m = *a ? 2 * ((int*)(*a)-2)[0]+in : in+1;
348     void *p = realloc(*a ? ((int*)(*a)-2) : 0, it * m + sizeof(int)*2);
349     if (p) {
350         if (!*a) ((int*)p)[1] = 0;
351         *a = (void*)((int*)p+2);
352         ((int*)(*a)-2)[0] = m;
353     }
354     return *a;
355 }