1 /* ################################################################### */
2 /* Copyright 2015, Pierre Gentile (p.gen.progs@gmail.com) */
4 /* This Source Code Form is subject to the terms of the Mozilla Public */
5 /* License, v. 2.0. If a copy of the MPL was not distributed with this */
6 /* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
7 /* ################################################################### */
9 /* ******************************** */
10 /* Various small utility functions. */
11 /* ******************************** */
27 /* ******************* */
28 /* Interval functions. */
29 /* ******************* */
31 /* ======================= */
32 /* Creates a new interval. */
33 /* ======================= */
37 return xmalloc(sizeof(interval_t
));
40 /* ======================================= */
41 /* Compares 2 intervals as integer couples */
42 /* same return values as for strcmp. */
43 /* ======================================= */
45 interval_comp(void const *a
, void const *b
)
47 interval_t
const *ia
= (interval_t
*)a
;
48 interval_t
const *ib
= (interval_t
*)b
;
50 if (ia
->low
< ib
->low
)
54 if (ia
->low
> ib
->low
)
58 if (ia
->high
< ib
->high
)
62 if (ia
->high
> ib
->high
)
70 /* ================================== */
71 /* Swaps the values of two intervals. */
72 /* ================================== */
74 interval_swap(void **a
, void **b
)
76 interval_t
*ia
= (interval_t
*)*a
;
77 interval_t
*ib
= (interval_t
*)*b
;
89 /* ====================================================================== */
90 /* Merges the intervals from an interval list in order to get the minimum */
91 /* number of intervals to consider. */
92 /* ====================================================================== */
94 optimize_an_interval_list(ll_t
*list
)
96 ll_node_t
*node1
, *node2
;
97 interval_t
*data1
, *data2
;
99 if (!list
|| list
->len
< 2)
102 /* Step 1: sort the intervals list. */
103 /* """""""""""""""""""""""""""""""" */
104 ll_sort(list
, interval_comp
, interval_swap
);
106 /* Step 2: merge the list by merging the consecutive intervals. */
107 /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */
113 data1
= (interval_t
*)(node1
->data
);
114 data2
= (interval_t
*)(node2
->data
);
116 if (data1
->high
>= data2
->low
- 1)
118 /* Interval 1 overlaps interval 2. */
119 /* ''''''''''''''''''''''''''''''' */
120 if (data2
->high
>= data1
->high
)
121 data1
->high
= data2
->high
;
122 ll_delete(list
, node2
);
136 /* ***************** */
137 /* String functions. */
138 /* ***************** */
140 /* ========================================================================= */
141 /* Allocates memory and safely concatenate strings. Stolen from a public */
142 /* domain implementation which can be found here: */
143 /* http://openwall.info/wiki/people/solar/software/public-domain-source-code */
144 /* ========================================================================= */
146 concat(const char *s1
, ...)
155 while ((s
= va_arg(args
, char *)))
162 if (s
|| m
>= INT_MAX
)
165 result
= (char *)xmalloc(m
+ 1);
167 memcpy(p
= result
, s1
, n
);
170 while ((s
= va_arg(args
, char *)))
173 if ((n
+= l
) < l
|| n
> m
)
179 if (s
|| m
!= n
|| p
!= result
+ n
)
189 /* =============================================== */
190 /* Is the string str2 a prefix of the string str1? */
191 /* Returns 1 if true, else 0. */
192 /* =============================================== */
194 strprefix(char *str1
, char *str2
)
196 while (*str1
!= '\0' && *str1
== *str2
)
202 return *str2
== '\0';
205 /* ========================= */
206 /* Trims leading characters. */
207 /* ========================= */
209 ltrim(char *str
, const char *trim_str
)
211 size_t len
= strlen(str
);
212 size_t begin
= strspn(str
, trim_str
);
215 for (size_t i
= begin
; i
<= len
; ++i
)
216 str
[i
- begin
] = str
[i
];
219 /* ==================================================================== */
220 /* Trims trailing characters. */
221 /* All (ASCII) characters in trim_str will be removed. */
222 /* The min argument guarantees that the length of the resulting string */
223 /* will not be smaller than this size if it was larger before, 0 is the */
224 /* usual value here. */
225 /* Note that when min is greater than 0, tail characters intended to be */
226 /* deleted may remain. */
227 /* ==================================================================== */
229 rtrim(char *str
, const char *trim_str
, size_t min
)
231 size_t len
= strlen(str
);
232 while (len
> min
&& strchr(trim_str
, str
[len
- 1]))
236 /* ========================================= */
237 /* Case insensitive strcmp. */
238 /* from http://c.snippets.org/code/stricmp.c */
239 /* ========================================= */
241 my_strcasecmp(const char *str1
, const char *str2
)
243 #ifdef HAVE_STRCASECMP
244 return strcasecmp(str1
, str2
);
250 retval
= tolower(*str1
++) - tolower(*str2
++);
264 /* ============================================= */
265 /* memmove based strcpy (tolerates overlapping). */
266 /* ============================================= */
268 my_strcpy(char *str1
, char *str2
)
270 if (str1
== NULL
|| str2
== NULL
)
273 memmove(str1
, str2
, strlen(str2
) + 1);
278 /* ================================ */
279 /* 7 bits aware version of isprint. */
280 /* ================================ */
284 return i
>= 0x20 && i
<= 0x7e;
287 /* ================================ */
288 /* 8 bits aware version of isprint. */
289 /* ================================ */
293 unsigned char c
= i
& (unsigned char)0xff;
295 return (c
>= 0x20 && c
< 0x7f) || (c
>= (unsigned char)0xa0);
298 /* ==================================================== */
299 /* Private implementation of wcscasecmp missing in c99. */
300 /* ==================================================== */
302 my_wcscasecmp(const wchar_t *s1
, const wchar_t *s2
)
312 return (int)(c1
- c2
);
320 /* ================================================================ */
321 /* Returns 1 if s can be converted into an int otherwise returns 0. */
322 /* ================================================================ */
324 is_integer(const char * const s
)
329 n
= strtol(s
, &endptr
, 10);
331 if (errno
!= ERANGE
&& n
>= INT_MIN
&& n
<= INT_MAX
&& *endptr
== '\0')
337 /* ===================================================== */
338 /* Exchanges the start and end part of a string. */
339 /* The first part goes from char 0 to size-1. */
340 /* The second part goes from char size to the end of *s. */
341 /* Returns 1 on success. */
342 /* ===================================================== */
344 swap_string_parts(char **s
, size_t first
)
349 if (*s
== NULL
|| **s
== '\0')
352 tmp
= xmalloc(strlen(*s
) * 2 + 1);
360 strncpy(*s
, tmp
+ first
, size
);
366 /* ================================================================ */
367 /* Substitute all the characters c1 by c2 in the string s in place. */
368 /* ================================================================ */
370 strrep(char *s
, const char c1
, const char c2
)
381 /* ================================================================== */
382 /* Allocates and returns a string similar to s but with non printable */
383 /* character changed by their ASCII hexadecimal notation. */
384 /* ================================================================== */
386 strprint(char const *s
)
388 size_t l
= strlen(s
);
389 char *new = xcalloc(1, 4 * l
+ 1);
398 sprintf(p
, "\\x%02X", (unsigned char)*s
++);
403 if (p
- new > (ptrdiff_t)l
)
404 new = xrealloc(new, p
- new + 1);
409 /* =============================================== */
410 /* Hexadecimal dump of part of a buffer to a file. */
412 /* buf : buffer to dump. */
413 /* fp : file to dump to. */
414 /* prefix: string to be printed before each line. */
415 /* size : length of the buffer to consider. */
416 /* =============================================== */
418 hexdump(const char *buf
, FILE *fp
, const char *prefix
, size_t size
)
429 for (b
= 0; b
< size
; b
++)
432 d
[b
% 16] = isprint(buf
[b
]) ? (unsigned char)buf
[b
] : '.';
439 fprintf(fp
, "%s: %04x:", prefix
, b
);
445 fprintf(fp
, " %02x", (unsigned char)buf
[b
]);
451 fprintf(fp
, " |%s|", d
);
458 for (unsigned int i
= 0; i
< mo
- o
; i
++)
459 fprintf(fp
, "%c", ' ');
461 fprintf(fp
, " |%s", d
);
463 for (unsigned int i
= 0; i
< 16 - strlen((char *)d
); i
++)
464 fprintf(fp
, "%c", ' ');
465 fprintf(fp
, "%c", '|');