Removed the notion of a "large" context. For simplicity, all contexts
[panda.git] / src / st-utils.c
blob0c8973cb0044fa1fb14c69e220c1b548704fd37f
1 /*
2 * st-utils.c
4 * Copyright (C) 2008 Vincent Geddes
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
25 #include "st-utils.h"
27 #include <sys/stat.h>
28 #include <string.h>
29 #include <stdio.h>
30 #include <errno.h>
31 #include <error.h>
32 #include <stdint.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <fcntl.h>
36 #include <unistd.h>
37 #include <stdarg.h>
39 int vasprintf(char **strp, const char *fmt, va_list ap);
41 extern char *program_invocation_short_name;
43 st_pointer
44 st_malloc (size_t size)
46 void *ptr;
48 ptr = malloc (size);
49 if (ST_UNLIKELY (ptr == NULL))
50 abort ();
52 return ptr;
55 st_pointer
56 st_malloc0 (size_t size)
58 void *ptr;
60 ptr = calloc (1, size);
61 if (ST_UNLIKELY (ptr == NULL))
62 abort ();
64 return ptr;
67 st_pointer
68 st_realloc (st_pointer mem, size_t size)
70 void *ptr;
72 ptr = realloc (mem, size);
73 if (ST_UNLIKELY (ptr == NULL))
74 abort ();
76 return ptr;
79 void
80 st_free (st_pointer mem)
82 if (ST_UNLIKELY (mem != NULL))
83 free (mem);
86 bool
87 st_file_get_contents (const char *filename,
88 char **buffer)
90 struct stat info;
91 size_t total;
92 ssize_t count;
93 char *temp;
94 int fd;
96 st_assert (filename != NULL);
98 *buffer = NULL;
100 if (stat (filename, &info) != 0) {
101 fprintf (stderr, "%s: error: `%s': %s\n", program_invocation_short_name, filename, strerror (errno));
102 return false;
105 if (!S_ISREG (info.st_mode)) {
106 fprintf (stderr, "%s: error: `%s': Not a regular file\n", program_invocation_short_name, filename);
107 return false;
110 fd = open (filename, O_RDONLY);
111 if (fd < 0) {
112 fprintf (stderr, "%s: error: `%s': %s\n", program_invocation_short_name, filename, strerror (errno));
113 return false;
116 total = 0;
117 temp = st_malloc (info.st_size + 1);
118 while (total < info.st_size) {
119 count = read (fd, temp + total, info.st_size - total);
120 if (count < 0) {
121 fprintf (stderr, "%s: error: %s: %s\n", program_invocation_short_name, filename, strerror (errno));
122 st_free (temp);
123 close (fd);
124 return false;
126 total += count;
129 close (fd);
131 temp[info.st_size] = 0;
132 *buffer = temp;
134 return true;
137 /* Derived from eglib (part of Mono)
138 * Copyright (C) 2006 Novell, Inc.
140 char *
141 st_strdup (const char *string)
143 size_t size;
144 char *copy;
146 st_assert (string != NULL);
148 size = strlen (string);
149 copy = st_malloc (size + 1);
150 strcpy (copy, string);
152 return copy;
155 /* Derived from eglib (part of Mono)
156 * Copyright (C) 2006 Novell, Inc.
158 char *
159 st_strdup_vprintf (const char *format, va_list args)
161 int n;
162 char *ret;
164 n = vasprintf (&ret, format, args);
165 if (n == -1)
166 return NULL;
168 return ret;
171 /* Derived from eglib (part of Mono)
172 * Copyright (C) 2006 Novell, Inc.
174 char *
175 st_strdup_printf (const char *format, ...)
177 char *ret;
178 va_list args;
179 int n;
181 va_start (args, format);
182 n = vasprintf (&ret, format, args);
183 va_end (args);
184 if (n == -1)
185 return NULL;
187 return ret;
190 /* Derived from eglib (part of Mono)
191 * Copyright (C) 2006 Novell, Inc.
193 char *
194 st_strconcat (const char *first, ...)
196 va_list args;
197 size_t total = 0;
198 char *s, *ret;
200 total += strlen (first);
201 va_start (args, first);
202 for (s = va_arg (args, char *); s != NULL; s = va_arg(args, char *)){
203 total += strlen (s);
205 va_end (args);
207 ret = st_malloc (total + 1);
208 if (ret == NULL)
209 return NULL;
211 ret [total] = 0;
212 strcpy (ret, first);
213 va_start (args, first);
214 for (s = va_arg (args, char *); s != NULL; s = va_arg(args, char *)){
215 strcat (ret, s);
217 va_end (args);
219 return ret;
223 double
224 st_timespec_to_double_seconds (struct timespec *interval)
226 /* print in seconds */
227 return interval->tv_sec + (interval->tv_nsec / 1.e9);
230 void
231 st_timespec_difference (struct timespec *start, struct timespec *end, struct timespec *diff)
233 if ((end->tv_nsec - start->tv_nsec) < 0) {
234 diff->tv_sec = end->tv_sec - start->tv_sec - 1;
235 diff->tv_nsec = 1000000000 + end->tv_nsec - start->tv_nsec;
236 } else {
237 diff->tv_sec = end->tv_sec - start->tv_sec;
238 diff->tv_nsec = end->tv_nsec - start->tv_nsec;
242 void
243 st_timespec_add (struct timespec *t1, struct timespec *t2, struct timespec *result)
245 if ((t1->tv_nsec + t2->tv_nsec) >= 1000000000) {
246 result->tv_sec = t1->tv_sec + t2->tv_sec + 1;
247 result->tv_nsec = t1->tv_nsec + t2->tv_nsec - 1000000000;
248 } else {
249 result->tv_sec = t1->tv_sec + t2->tv_sec;
250 result->tv_nsec = t1->tv_nsec + t2->tv_nsec;
254 st_list *
255 st_list_append (st_list *list, st_pointer data)
257 st_list *new_list, *l;
259 new_list = st_new (st_list);
260 new_list->data = data;
261 new_list->next = NULL;
263 if (list == NULL)
264 return new_list;
266 l = list;
267 while (l->next)
268 l = l->next;
270 l->next = new_list;
272 return list;
275 st_list *
276 st_list_prepend (st_list *list, st_pointer data)
278 st_list *new_list;
280 new_list = st_new (st_list);
281 new_list->data = data;
282 new_list->next = list;
284 return new_list;
287 st_list *
288 st_list_reverse (st_list *list)
290 st_list *next, *prev = NULL;
292 while (list) {
293 next = list->next;
295 list->next = prev;
297 prev = list;
298 list = next;
301 return prev;
304 st_list *
305 st_list_concat (st_list *list1, st_list *list2)
307 st_list *l;
309 if (list1 == NULL)
310 return list2;
312 if (list2 == NULL)
313 return list1;
315 l = list1;
316 while (l->next)
317 l = l->next;
318 l->next = list2;
320 return list1;
323 st_uint
324 st_list_length (st_list *list)
326 st_list *l = list;
327 st_uint len = 0;
329 for (; l; l = l->next)
330 ++len;
332 return len;
335 void
336 st_list_foreach (st_list *list, st_list_foreach_func func)
338 for (st_list *l = list; l; l = l->next)
339 func (l->data);
342 void
343 st_list_destroy (st_list *list)
345 st_list *next, *current;
347 current = list;
349 while (current) {
350 next = current->next;
351 st_free (current);
352 current = next;
356 /* Derived from eglib (part of Mono)
357 * Copyright (C) 2006 Novell, Inc.
359 static void
360 add_to_vector (char ***vector, int size, char *token)
362 *vector = *vector == NULL ?
363 (char **)st_malloc(2 * sizeof(*vector)) :
364 (char **)st_realloc(*vector, (size + 1) * sizeof(*vector));
366 (*vector)[size - 1] = token;
369 /* Derived from eglib (part of Mono)
370 * Copyright (C) 2006 Novell, Inc.
372 char **
373 st_strsplit (const char *string, const char *delimiter, int max_tokens)
375 const char *c;
376 char *token, **vector;
377 int size = 1;
379 if (strncmp (string, delimiter, strlen (delimiter)) == 0) {
380 vector = (char **)st_malloc (2 * sizeof(vector));
381 vector[0] = st_strdup ("");
382 size++;
383 string += strlen (delimiter);
384 } else {
385 vector = NULL;
388 while (*string && !(max_tokens > 0 && size >= max_tokens)) {
389 c = string;
390 if (strncmp (string, delimiter, strlen (delimiter)) == 0) {
391 token = st_strdup ("");
392 string += strlen (delimiter);
393 } else {
394 while (*string && strncmp (string, delimiter, strlen (delimiter)) != 0) {
395 string++;
398 if (*string) {
399 size_t toklen = (string - c);
400 token = st_strndup (c, toklen);
402 /* Need to leave a trailing empty
403 * token if the delimiter is the last
404 * part of the string
406 if (strcmp (string, delimiter) != 0) {
407 string += strlen (delimiter);
409 } else {
410 token = st_strdup (c);
414 add_to_vector (&vector, size, token);
415 size++;
418 if (*string) {
419 /* Add the rest of the string as the last element */
420 add_to_vector (&vector, size, st_strdup (string));
421 size++;
424 if (vector == NULL) {
425 vector = (char **) st_malloc (2 * sizeof (vector));
426 vector [0] = NULL;
427 } else if (size > 0) {
428 vector[size - 1] = NULL;
431 return vector;
434 /* Derived from eglib (part of Mono)
435 * Copyright (C) 2006 Novell, Inc.
437 void
438 st_strfreev (char **str_array)
440 char **orig = str_array;
441 if (str_array == NULL)
442 return;
443 while (*str_array != NULL){
444 st_free (*str_array);
445 str_array++;
447 st_free (orig);
451 /* Derived from eglib (part of Mono)
452 * Copyright (C) 2006 Novell, Inc.
454 /* This is not a macro, because I dont want to put _GNU_SOURCE in the glib.h header */
455 char *
456 st_strndup (const char *str, size_t n)
458 #ifdef HAVE_STRNDUP
459 return strndup (str, n);
460 #else
461 if (str) {
462 char *retval = malloc(n+1);
463 if (retval) {
464 strncpy(retval, str, n)[n] = 0;
466 return retval;
468 return NULL;
469 #endif
472 st_uint
473 st_string_hash (const char *string)
475 const signed char *p = (signed char *) string;
476 st_uint h = *p;
478 if (*p == 0)
479 return h;
481 while (*p) {
482 h = (h << 5) - h + *p++;
485 return h;
488 void
489 st_log (const char * restrict domain, const char * restrict format, ...)
491 char *fmt;
492 va_list args;
494 st_assert (domain != NULL);
495 if (!st_get_verbose_mode ())
496 return;
498 fmt = st_strconcat ("** ", domain, ": ", format, "\n", NULL);
500 va_start (args, format);
501 vfprintf (stderr, fmt, args);
502 va_end (args);
503 st_free (fmt);