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