Fix redundant glTexEnv calls
[neverball] / share / common.c
1 /*
2  *  Copyright (C) 2007  Neverball authors
3  *
4  *  This  program is  free software;  you can  redistribute  it and/or
5  *  modify it  under the  terms of the  GNU General Public  License as
6  *  published by the Free Software Foundation; either version 2 of the
7  *  License, or (at your option) any later version.
8  *
9  *  This program  is distributed in the  hope that it  will be useful,
10  *  but  WITHOUT ANY WARRANTY;  without even  the implied  warranty of
11  *  MERCHANTABILITY or FITNESS FOR  A PARTICULAR PURPOSE.  See the GNU
12  *  General Public License for more details.
13  *
14  *  You should have received a  copy of the GNU General Public License
15  *  along  with this  program;  if  not, write  to  the Free  Software
16  *  Foundation,  Inc.,   59  Temple  Place,  Suite   330,  Boston,  MA
17  *  02111-1307 USA
18  */
19
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <time.h>
24 #include <ctype.h>
25 #include <stdarg.h>
26 #include <assert.h>
27
28 #include "common.h"
29 #include "fs.h"
30
31 #define MAXSTR 256
32
33 /*---------------------------------------------------------------------------*/
34
35 int read_line(char **dst, fs_file fin)
36 {
37     char buff[MAXSTR];
38
39     char *line, *new;
40     size_t len0, len1;
41
42     line = NULL;
43
44     while (fs_gets(buff, sizeof (buff), fin))
45     {
46         /* Append to data read so far. */
47
48         if (line)
49         {
50             new  = concat_string(line, buff, NULL);
51             free(line);
52             line = new;
53         }
54         else
55         {
56             line = strdup(buff);
57         }
58
59         /* Strip newline, if any. */
60
61         len0 = strlen(line);
62         strip_newline(line);
63         len1 = strlen(line);
64
65         if (len1 != len0)
66         {
67             /* We hit a newline, clean up and break. */
68             line = realloc(line, len1 + 1);
69             break;
70         }
71     }
72
73     return (*dst = line) ? 1 : 0;
74 }
75
76 char *strip_newline(char *str)
77 {
78     char *c = str + strlen(str) - 1;
79
80     while (c >= str && (*c == '\n' || *c =='\r'))
81         *c-- = '\0';
82
83     return str;
84 }
85
86 char *dupe_string(const char *src)
87 {
88     char *dst = NULL;
89
90     if (src && (dst = malloc(strlen(src) + 1)))
91         strcpy(dst, src);
92
93     return dst;
94 }
95
96 char *concat_string(const char *first, ...)
97 {
98     char *full;
99
100     if ((full = strdup(first)))
101     {
102         const char *part;
103         va_list ap;
104
105         va_start(ap, first);
106
107         while ((part = va_arg(ap, const char *)))
108         {
109             char *new;
110
111             if ((new = realloc(full, strlen(full) + strlen(part) + 1)))
112             {
113                 full = new;
114                 strcat(full, part);
115             }
116             else
117             {
118                 free(full);
119                 full = NULL;
120                 break;
121             }
122         }
123
124         va_end(ap);
125     }
126
127     return full;
128 }
129
130 time_t make_time_from_utc(struct tm *tm)
131 {
132     struct tm local, *utc;
133     time_t t;
134
135     t = mktime(tm);
136
137     local = *localtime(&t);
138     utc   =  gmtime(&t);
139
140     local.tm_year += local.tm_year - utc->tm_year;
141     local.tm_mon  += local.tm_mon  - utc->tm_mon ;
142     local.tm_mday += local.tm_mday - utc->tm_mday;
143     local.tm_hour += local.tm_hour - utc->tm_hour;
144     local.tm_min  += local.tm_min  - utc->tm_min ;
145     local.tm_sec  += local.tm_sec  - utc->tm_sec ;
146
147     return mktime(&local);
148 }
149
150 const char *date_to_str(time_t i)
151 {
152     static char str[sizeof ("YYYY-mm-dd HH:MM:SS")];
153     strftime(str, sizeof (str), "%Y-%m-%d %H:%M:%S", localtime(&i));
154     return str;
155 }
156
157 int file_exists(const char *name)
158 {
159     FILE *fp;
160
161     if ((fp = fopen(name, "r")))
162     {
163         fclose(fp);
164         return 1;
165     }
166     return 0;
167 }
168
169 int file_rename(const char *src, const char *dst)
170 {
171 #ifdef _WIN32
172     if (file_exists(dst))
173         remove(dst);
174 #endif
175     return rename(src, dst);
176 }
177
178 void file_copy(FILE *fin, FILE *fout)
179 {
180     char   buff[MAXSTR];
181     size_t size;
182
183     while ((size = fread(buff, 1, sizeof (buff), fin)) > 0)
184         fwrite(buff, 1, size, fout);
185 }
186
187 /*---------------------------------------------------------------------------*/
188
189 int path_is_sep(int c)
190 {
191 #ifdef _WIN32
192     return c == '/' || c == '\\';
193 #else
194     return c == '/';
195 #endif
196 }
197
198 int path_is_abs(const char *path)
199 {
200     if (path_is_sep(path[0]))
201         return 1;
202
203 #ifdef _WIN32
204     if (isalpha(path[0]) && path[1] == ':' && path_is_sep(path[2]))
205         return 1;
206 #endif
207
208     return 0;
209 }
210
211 char *path_join(const char *head, const char *tail)
212 {
213     return *head ? concat_string(head, "/", tail, NULL) : strdup(tail);
214 }
215
216 const char *path_last_sep(const char *path)
217 {
218     const char *sep;
219
220     sep = strrchr(path, '/');
221
222 #ifdef _WIN32
223     if (!sep)
224     {
225         sep = strrchr(path, '\\');
226     }
227     else
228     {
229         const char *tmp;
230
231         if ((tmp = strrchr(path, '\\')) && sep < tmp)
232             sep = tmp;
233     }
234 #endif
235
236     return sep;
237 }
238
239 const char *path_next_sep(const char *path)
240 {
241     size_t skip;
242
243 #ifdef _WIN32
244     skip = strcspn(path, "/\\");
245 #else
246     skip = strcspn(path, "/");
247 #endif
248
249     return *(path + skip) ? path + skip : NULL;
250 }
251
252 const char *base_name_sans(const char *name, const char *suffix)
253 {
254     static char base[MAXSTR];
255     size_t blen, slen;
256
257     if (!name)
258         return NULL;
259     if (!suffix)
260         return base_name(name);
261
262     /* Remove the directory part. */
263
264     SAFECPY(base, base_name(name));
265
266     /* Remove the suffix. */
267
268     blen = strlen(base);
269     slen = strlen(suffix);
270
271     if (blen >= slen && strcmp(base + blen - slen, suffix) == 0)
272         base[blen - slen] = '\0';
273
274     return base;
275 }
276
277 const char *base_name(const char *name)
278 {
279     const char *sep;
280     return (name && (sep = path_last_sep(name))) ? sep + 1 : name;
281 }
282
283 const char *dir_name(const char *name)
284 {
285     static char buff[MAXSTR];
286
287     char *sep;
288
289     SAFECPY(buff, name);
290
291     if ((sep = (char *) path_last_sep(buff)))
292     {
293         if (sep == buff)
294             return "/";
295
296         *sep = '\0';
297
298         return buff;
299     }
300
301     return ".";
302 }
303
304 /*---------------------------------------------------------------------------*/
305
306 int rand_between(int low, int high)
307 {
308     return low + rand() / (RAND_MAX / (high - low + 1) + 1);
309 }
310
311 /*---------------------------------------------------------------------------*/