Add missing credit for Esperanto translation
[neverball.git] / share / common.c
blob00fe8e1f9ec316cc26dce7e8b1f8b8ec39a92f2a
1 /*
2 * Copyright (C) 2007 Neverball authors
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.
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.
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
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>
28 #include "common.h"
29 #include "fs.h"
31 #define MAXSTR 256
33 /*---------------------------------------------------------------------------*/
35 int read_line(char **dst, fs_file fin)
37 char buff[MAXSTR];
39 char *line, *new;
40 size_t len0, len1;
42 line = NULL;
44 while (fs_gets(buff, sizeof (buff), fin))
46 /* Append to data read so far. */
48 if (line)
50 new = concat_string(line, buff, NULL);
51 free(line);
52 line = new;
54 else
56 line = strdup(buff);
59 /* Strip newline, if any. */
61 len0 = strlen(line);
62 strip_newline(line);
63 len1 = strlen(line);
65 if (len1 != len0)
67 /* We hit a newline, clean up and break. */
68 line = realloc(line, len1 + 1);
69 break;
73 return (*dst = line) ? 1 : 0;
76 char *strip_newline(char *str)
78 char *c = str + strlen(str) - 1;
80 while (c >= str && (*c == '\n' || *c =='\r'))
81 *c-- = '\0';
83 return str;
86 char *dupe_string(const char *src)
88 char *dst = NULL;
90 if (src && (dst = malloc(strlen(src) + 1)))
91 strcpy(dst, src);
93 return dst;
96 char *concat_string(const char *first, ...)
98 char *full;
100 if ((full = strdup(first)))
102 const char *part;
103 va_list ap;
105 va_start(ap, first);
107 while ((part = va_arg(ap, const char *)))
109 char *new;
111 if ((new = realloc(full, strlen(full) + strlen(part) + 1)))
113 full = new;
114 strcat(full, part);
116 else
118 free(full);
119 full = NULL;
120 break;
124 va_end(ap);
127 return full;
130 time_t make_time_from_utc(struct tm *tm)
132 struct tm local, *utc;
133 time_t t;
135 t = mktime(tm);
137 local = *localtime(&t);
138 utc = gmtime(&t);
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 ;
147 return mktime(&local);
150 const char *date_to_str(time_t i)
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;
157 int file_exists(const char *name)
159 FILE *fp;
161 if ((fp = fopen(name, "r")))
163 fclose(fp);
164 return 1;
166 return 0;
169 int file_rename(const char *src, const char *dst)
171 #ifdef _WIN32
172 if (file_exists(dst))
173 remove(dst);
174 #endif
175 return rename(src, dst);
178 void file_copy(FILE *fin, FILE *fout)
180 char buff[MAXSTR];
181 size_t size;
183 while ((size = fread(buff, 1, sizeof (buff), fin)) > 0)
184 fwrite(buff, 1, size, fout);
187 /*---------------------------------------------------------------------------*/
189 int path_is_sep(int c)
191 #ifdef _WIN32
192 return c == '/' || c == '\\';
193 #else
194 return c == '/';
195 #endif
198 int path_is_abs(const char *path)
200 if (path_is_sep(path[0]))
201 return 1;
203 #ifdef _WIN32
204 if (isalpha(path[0]) && path[1] == ':' && path_is_sep(path[2]))
205 return 1;
206 #endif
208 return 0;
211 char *path_join(const char *head, const char *tail)
213 return *head ? concat_string(head, "/", tail, NULL) : strdup(tail);
216 const char *path_last_sep(const char *path)
218 const char *sep;
220 sep = strrchr(path, '/');
222 #ifdef _WIN32
223 if (!sep)
225 sep = strrchr(path, '\\');
227 else
229 const char *tmp;
231 if ((tmp = strrchr(path, '\\')) && sep < tmp)
232 sep = tmp;
234 #endif
236 return sep;
239 const char *path_next_sep(const char *path)
241 size_t skip;
243 #ifdef _WIN32
244 skip = strcspn(path, "/\\");
245 #else
246 skip = strcspn(path, "/");
247 #endif
249 return *(path + skip) ? path + skip : NULL;
252 char *path_normalize(char *path)
254 char *sep = path;
256 while ((sep = (char *) path_next_sep(sep)))
257 *sep++ = '/';
259 return path;
262 const char *base_name_sans(const char *name, const char *suffix)
264 static char base[MAXSTR];
265 size_t blen, slen;
267 if (!name)
268 return NULL;
269 if (!suffix)
270 return base_name(name);
272 /* Remove the directory part. */
274 SAFECPY(base, base_name(name));
276 /* Remove the suffix. */
278 blen = strlen(base);
279 slen = strlen(suffix);
281 if (blen >= slen && strcmp(base + blen - slen, suffix) == 0)
282 base[blen - slen] = '\0';
284 return base;
287 const char *base_name(const char *name)
289 const char *sep;
290 return (name && (sep = path_last_sep(name))) ? sep + 1 : name;
293 const char *dir_name(const char *name)
295 static char buff[MAXSTR];
297 char *sep;
299 SAFECPY(buff, name);
301 if ((sep = (char *) path_last_sep(buff)))
303 if (sep == buff)
304 return "/";
306 *sep = '\0';
308 return buff;
311 return ".";
314 /*---------------------------------------------------------------------------*/
316 int rand_between(int low, int high)
318 return low + rand() / (RAND_MAX / (high - low + 1) + 1);
321 /*---------------------------------------------------------------------------*/
323 #ifdef _WIN32
325 /* MinGW hides this from ANSI C. MinGW-w64 doesn't. */
326 _CRTIMP int _putenv(const char *envstring);
328 int set_env_var(const char *name, const char *value)
330 if (name)
332 char str[MAXSTR];
334 if (value)
335 sprintf(str, "%s=%s", name, value);
336 else
337 sprintf(str, "%s=", name);
339 return (_putenv(str) == 0);
341 return 0;
344 #else
346 extern int setenv(const char *name, const char *value, int overwrite);
347 extern int unsetenv(const char *name);
349 int set_env_var(const char *name, const char *value)
351 if (name)
353 if (value)
354 return (setenv(name, value, 1) == 0);
355 else
356 return (unsetenv(name) == 0);
358 return 0;
361 #endif
363 /*---------------------------------------------------------------------------*/