]> git.xonotic.org Git - xonotic/gmqcc.git/blob - util.c
Indentation
[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         util_debug("MEM", "Memory information:\n\
65         Total allocations:   %llu\n\
66         Total deallocations: %llu\n\
67         Total allocated:     %llu (bytes)\n\
68         Total deallocated:   %llu (bytes)\n",
69                 mem_at, mem_dt,
70                 mem_ab, mem_db
71         );
72 }
73
74 //#ifndef mem_d
75 //#define mem_d(x) util_memory_d((x), __LINE__, __FILE__)
76 //#endif
77 //#ifndef mem_a
78 //#define mem_a(x) util_memory_a((x), __LINE__, __FILE__)
79 //#endif
80
81 /*
82  * Some string utility functions, because strdup uses malloc, and we want
83  * to track all memory (without replacing malloc).
84  */
85 char *util_strdup(const char *s) {
86     size_t  len = 0;
87     char   *ptr = NULL;
88     
89     if (!s)
90         return NULL;
91         
92     if ((len = strlen(s)) && (ptr = mem_a(len+1))) {
93         memcpy(ptr, s, len);
94         ptr[len] = '\0';
95     }
96     return ptr;
97 }
98
99 /*
100  * Remove quotes from a string, escapes from \ in string
101  * as well.  This function shouldn't be used to create a
102  * char array that is later freed (it uses pointer arith)
103  */
104 char *util_strrq(char *s) {
105     char *dst = s;
106     char *src = s;
107     char  chr;
108     while ((chr = *src++) != '\0') {
109         if (chr == '\\') {
110             *dst++ = chr;
111             if ((chr = *src++) == '\0')
112                 break;
113             *dst++ = chr;
114         } else if (chr != '"')
115             *dst++ = chr;
116     }
117     *dst = '\0';
118     return dst;
119 }
120
121 /*
122  * Remove newline from a string (if it exists).  This is
123  * done pointer wise instead of strlen(), and an array
124  * access.
125  */
126 char *util_strrnl(char *src) {
127     if (!src) return NULL;
128     char   *cpy = src;
129     while (*cpy && *cpy != '\n')
130         cpy++;
131         
132     *cpy = '\0';
133     return src;
134 }
135
136 void util_debug(const char *area, const char *ms, ...) {
137     va_list  va;
138     va_start(va, ms);
139     fprintf (stdout, "DEBUG: ");
140     fputc   ('[',  stdout);
141     fprintf(stdout, "%s", area);
142     fputs   ("] ", stdout);
143     vfprintf(stdout, ms, va);
144     va_end  (va);
145 }
146
147 /*
148  * Endianess swapping, all data must be stored little-endian.  This
149  * reorders by stride and length, much nicer than other functions for
150  * certian-sized types like short or int.
151  */
152 void util_endianswap(void *m, int s, int l) {
153     size_t w = 0;
154     size_t i = 0;
155
156     /* ignore if we're already LE */
157     if(*((char *)&s))
158         return;
159
160     for(; w < l; w++) {
161         for(;  i < s << 1; i++) {
162             unsigned char *p = (unsigned char *)m+w*s;
163             unsigned char  t = p[i];
164             p[i]             = p[s-i-1];
165             p[s-i-1]         = t;
166         }
167     }
168 }
169
170 /*
171  * Implements libc getline for systems that don't have it, which is 
172  * assmed all.  This works the same as getline().
173  */
174 int util_getline(char **lineptr, size_t *n, FILE *stream) {
175     int   chr;
176     int   ret;
177     char *pos;    
178
179     if (!lineptr || !n || !stream)
180         return -1;
181     if (!*lineptr) {
182         if (!(*lineptr = mem_a((*n = 64))))
183             return -1;
184     }
185
186     chr = *n;
187     pos = *lineptr;
188
189     for (;;) {
190         int c = getc(stream);
191         
192         if (chr < 2) {
193             char *tmp = mem_a((*n+=(*n>16)?*n:64));
194             if  (!tmp)
195                 return -1;
196             
197             chr = *n + *lineptr - pos;
198             strcpy(tmp,*lineptr);
199             if (!(*lineptr = tmp)) {
200                 mem_d (tmp);
201                 return -1;
202             } 
203             pos = *n - chr + *lineptr;
204         }
205
206         if (ferror(stream))
207             return -1;
208         if (c == EOF) {
209             if (pos == *lineptr)
210                 return -1;
211             else
212                 break;
213         }
214
215         *pos++ = c;
216          chr--;
217         if (c == '\n')
218             break;
219     }
220     *pos = '\0';
221     return (ret = pos - *lineptr);
222 }