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
39 int vasprintf(char **strp
, const char *fmt
, va_list ap
);
41 extern char *program_invocation_short_name
;
44 st_malloc (size_t size
)
49 if (ST_UNLIKELY (ptr
== NULL
))
56 st_malloc0 (size_t size
)
60 ptr
= calloc (1, size
);
61 if (ST_UNLIKELY (ptr
== NULL
))
68 st_realloc (st_pointer mem
, size_t size
)
72 ptr
= realloc (mem
, size
);
73 if (ST_UNLIKELY (ptr
== NULL
))
80 st_free (st_pointer mem
)
82 if (ST_UNLIKELY (mem
!= NULL
))
87 st_file_get_contents (const char *filename
,
96 st_assert (filename
!= NULL
);
100 if (stat (filename
, &info
) != 0) {
101 fprintf (stderr
, "%s: error: `%s': %s\n", program_invocation_short_name
, filename
, strerror (errno
));
105 if (!S_ISREG (info
.st_mode
)) {
106 fprintf (stderr
, "%s: error: `%s': Not a regular file\n", program_invocation_short_name
, filename
);
110 fd
= open (filename
, O_RDONLY
);
112 fprintf (stderr
, "%s: error: `%s': %s\n", program_invocation_short_name
, filename
, strerror (errno
));
117 temp
= st_malloc (info
.st_size
+ 1);
118 while (total
< info
.st_size
) {
119 count
= read (fd
, temp
+ total
, info
.st_size
- total
);
121 fprintf (stderr
, "%s: error: %s: %s\n", program_invocation_short_name
, filename
, strerror (errno
));
131 temp
[info
.st_size
] = 0;
137 /* Derived from eglib (part of Mono)
138 * Copyright (C) 2006 Novell, Inc.
141 st_strdup (const char *string
)
146 st_assert (string
!= NULL
);
148 size
= strlen (string
);
149 copy
= st_malloc (size
+ 1);
150 strcpy (copy
, string
);
155 /* Derived from eglib (part of Mono)
156 * Copyright (C) 2006 Novell, Inc.
159 st_strdup_vprintf (const char *format
, va_list args
)
164 n
= vasprintf (&ret
, format
, args
);
171 /* Derived from eglib (part of Mono)
172 * Copyright (C) 2006 Novell, Inc.
175 st_strdup_printf (const char *format
, ...)
181 va_start (args
, format
);
182 n
= vasprintf (&ret
, format
, args
);
190 /* Derived from eglib (part of Mono)
191 * Copyright (C) 2006 Novell, Inc.
194 st_strconcat (const char *first
, ...)
200 total
+= strlen (first
);
201 va_start (args
, first
);
202 for (s
= va_arg (args
, char *); s
!= NULL
; s
= va_arg(args
, char *)){
207 ret
= st_malloc (total
+ 1);
213 va_start (args
, first
);
214 for (s
= va_arg (args
, char *); s
!= NULL
; s
= va_arg(args
, char *)){
224 st_timespec_to_double_seconds (struct timespec
*interval
)
226 /* print in seconds */
227 return interval
->tv_sec
+ (interval
->tv_nsec
/ 1.e9
);
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
;
237 diff
->tv_sec
= end
->tv_sec
- start
->tv_sec
;
238 diff
->tv_nsec
= end
->tv_nsec
- start
->tv_nsec
;
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;
249 result
->tv_sec
= t1
->tv_sec
+ t2
->tv_sec
;
250 result
->tv_nsec
= t1
->tv_nsec
+ t2
->tv_nsec
;
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
;
276 st_list_prepend (st_list
*list
, st_pointer data
)
280 new_list
= st_new (st_list
);
281 new_list
->data
= data
;
282 new_list
->next
= list
;
288 st_list_reverse (st_list
*list
)
290 st_list
*next
, *prev
= NULL
;
305 st_list_concat (st_list
*list1
, st_list
*list2
)
324 st_list_length (st_list
*list
)
329 for (; l
; l
= l
->next
)
336 st_list_foreach (st_list
*list
, st_list_foreach_func func
)
338 for (st_list
*l
= list
; l
; l
= l
->next
)
343 st_list_destroy (st_list
*list
)
345 st_list
*next
, *current
;
350 next
= current
->next
;
356 /* Derived from eglib (part of Mono)
357 * Copyright (C) 2006 Novell, Inc.
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.
373 st_strsplit (const char *string
, const char *delimiter
, int max_tokens
)
376 char *token
, **vector
;
379 if (strncmp (string
, delimiter
, strlen (delimiter
)) == 0) {
380 vector
= (char **)st_malloc (2 * sizeof(vector
));
381 vector
[0] = st_strdup ("");
383 string
+= strlen (delimiter
);
388 while (*string
&& !(max_tokens
> 0 && size
>= max_tokens
)) {
390 if (strncmp (string
, delimiter
, strlen (delimiter
)) == 0) {
391 token
= st_strdup ("");
392 string
+= strlen (delimiter
);
394 while (*string
&& strncmp (string
, delimiter
, strlen (delimiter
)) != 0) {
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
406 if (strcmp (string
, delimiter
) != 0) {
407 string
+= strlen (delimiter
);
410 token
= st_strdup (c
);
414 add_to_vector (&vector
, size
, token
);
419 /* Add the rest of the string as the last element */
420 add_to_vector (&vector
, size
, st_strdup (string
));
424 if (vector
== NULL
) {
425 vector
= (char **) st_malloc (2 * sizeof (vector
));
427 } else if (size
> 0) {
428 vector
[size
- 1] = NULL
;
434 /* Derived from eglib (part of Mono)
435 * Copyright (C) 2006 Novell, Inc.
438 st_strfreev (char **str_array
)
440 char **orig
= str_array
;
441 if (str_array
== NULL
)
443 while (*str_array
!= NULL
){
444 st_free (*str_array
);
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 */
456 st_strndup (const char *str
, size_t n
)
459 return strndup (str
, n
);
462 char *retval
= malloc(n
+1);
464 strncpy(retval
, str
, n
)[n
] = 0;
473 st_string_hash (const char *string
)
475 const signed char *p
= (signed char *) string
;
482 h
= (h
<< 5) - h
+ *p
++;
489 st_log (const char * restrict domain
, const char * restrict format
, ...)
494 st_assert (domain
!= NULL
);
495 if (!st_get_verbose_mode ())
498 fmt
= st_strconcat ("** ", domain
, ": ", format
, "\n", NULL
);
500 va_start (args
, format
);
501 vfprintf (stderr
, fmt
, args
);