1 /* ########################################################### */
2 /* This Software is licensed under the GPL licensed Version 2, */
3 /* please read http://www.gnu.org/copyleft/gpl.html. */
4 /* ########################################################### */
5
6 /* ******************************** */
7 /* Various small utility functions. */
8 /* ******************************** */
9
10 #include "config.h"
11 #include <stdlib.h>
12 #include <limits.h>
13 #include <string.h>
14 #include <ctype.h>
15 #include <stdarg.h>
16 #include <wctype.h>
17 #include "xmalloc.h"
18 #include "list.h"
19 #include "utils.h"
20
21 /* ******************* */
22 /* Interval functions. */
23 /* ******************* */
24
25 /* ======================= */
26 /* Creates a new interval. */
27 /* ======================= */
28 interval_t *
interval_new(void)29 interval_new(void)
30 {
31 interval_t * ret = xmalloc(sizeof(interval_t));
32
33 return ret;
34 }
35
36 /* ======================================= */
37 /* Compares 2 intervals as integer couples */
38 /* same return values as for strcmp. */
39 /* ======================================= */
40 int
interval_comp(void * a,void * b)41 interval_comp(void * a, void * b)
42 {
43 interval_t * ia = (interval_t *)a;
44 interval_t * ib = (interval_t *)b;
45
46 if (ia->low < ib->low)
47 /* ia: [... */
48 /* ib: [... */
49 return -1;
50 if (ia->low > ib->low)
51 /* ia: [... */
52 /* ib: [... */
53 return 1;
54 if (ia->high < ib->high)
55 /* ia: ...] */
56 /* ib: ...] */
57 return -1;
58 if (ia->high > ib->high)
59 /* ia: ...] */
60 /* ib: ...] */
61 return 1;
62
63 return 0;
64 }
65
66 /* ================================== */
67 /* Swaps the values of two intervals. */
68 /* ================================== */
69 void
interval_swap(void * a,void * b)70 interval_swap(void * a, void * b)
71 {
72 interval_t * ia = (interval_t *)a;
73 interval_t * ib = (interval_t *)b;
74 long tmp;
75
76 tmp = ia->low;
77 ia->low = ib->low;
78 ib->low = tmp;
79
80 tmp = ia->high;
81 ia->high = ib->high;
82 ib->high = tmp;
83 }
84
85 /* ====================================================================== */
86 /* Merges the intervals from an interval list in order to get the minimum */
87 /* number of intervals to consider. */
88 /* ====================================================================== */
89 void
merge_intervals(ll_t * list)90 merge_intervals(ll_t * list)
91 {
92 ll_node_t * node1, *node2;
93 interval_t *data1, *data2;
94
95 if (!list || list->len < 2)
96 return;
97 else
98 {
99 /* Step 1: sort the intervals list. */
100 /* """""""""""""""""""""""""""""""" */
101 ll_sort(list, interval_comp, interval_swap);
102
103 /* Step 2: merge the list by merging the consecutive intervals. */
104 /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""" */
105 node1 = list->head;
106 node2 = node1->next;
107
108 while (node2)
109 {
110 data1 = (interval_t *)(node1->data);
111 data2 = (interval_t *)(node2->data);
112
113 if (data1->high >= data2->low - 1)
114 {
115 /* Interval 1 overlaps interval 2. */
116 /* ''''''''''''''''''''''''''''''' */
117 if (data2->high >= data1->high)
118 data1->high = data2->high;
119 ll_delete(list, node2);
120 free(data2);
121 node2 = node1->next;
122 }
123 else
124 {
125 /* No overlap. */
126 /* ''''''''''' */
127 node1 = node2;
128 node2 = node2->next;
129 }
130 }
131 }
132 }
133
134 /* ****************** */
135 /* Strings functions. */
136 /* ****************** */
137
138 /* ========================================================================= */
139 /* Allocates memory and safely concatenate strings. Stolen from a public */
140 /* domain implementation which can be found here: */
141 /* http://openwall.info/wiki/people/solar/software/public-domain-source-code */
142 /* ========================================================================= */
143 char *
concat(const char * s1,...)144 concat(const char * s1, ...)
145 {
146 va_list args;
147 const char * s;
148 char * p, *result;
149 size_t l, m, n;
150
151 m = n = strlen(s1);
152 va_start(args, s1);
153 while ((s = va_arg(args, char *)))
154 {
155 l = strlen(s);
156 if ((m += l) < l)
157 break;
158 }
159 va_end(args);
160 if (s || m >= INT_MAX)
161 return NULL;
162
163 result = (char *)xmalloc(m + 1);
164
165 memcpy(p = result, s1, n);
166 p += n;
167 va_start(args, s1);
168 while ((s = va_arg(args, char *)))
169 {
170 l = strlen(s);
171 if ((n += l) < l || n > m)
172 break;
173 memcpy(p, s, l);
174 p += l;
175 }
176 va_end(args);
177 if (s || m != n || p != result + n)
178 {
179 free(result);
180 return NULL;
181 }
182
183 *p = 0;
184 return result;
185 }
186
187 /* =============================================== */
188 /* Is the string str2 a prefix of the string str1? */
189 /* Returns 1 if true, else 0. */
190 /* =============================================== */
191 int
strprefix(char * str1,char * str2)192 strprefix(char * str1, char * str2)
193 {
194 while (*str1 != '\0' && *str1 == *str2)
195 {
196 str1++;
197 str2++;
198 }
199
200 return *str2 == '\0';
201 }
202
203 /* ========================= */
204 /* Trims leading characters. */
205 /* ========================= */
206 void
ltrim(char * str,const char * trim_str)207 ltrim(char * str, const char * trim_str)
208 {
209 size_t len = strlen(str);
210 size_t begin = strspn(str, trim_str);
211 size_t i;
212
213 if (begin > 0)
214 for (i = begin; i <= len; ++i)
215 str[i - begin] = str[i];
216 }
217
218 /* ==================================================================== */
219 /* Trims trailing characters. */
220 /* All (ASCII) characters in trim_str will be removed. */
221 /* The min argument guarantees that the length of the resulting string */
222 /* will not be smaller than this size if it was larger before, 0 is the */
223 /* usual value here. */
224 /* Note that when min is greater than 0, tail characters intended to be */
225 /* deleted may remain. */
226 /* ==================================================================== */
227 void
rtrim(char * str,const char * trim_str,size_t min)228 rtrim(char * str, const char * trim_str, size_t min)
229 {
230 size_t len = strlen(str);
231 while (len > min && strchr(trim_str, str[len - 1]))
232 str[--len] = '\0';
233 }
234
235 /* ========================================= */
236 /* Case insensitive strcmp. */
237 /* from http://c.snippets.org/code/stricmp.c */
238 /* ========================================= */
239 int
my_strcasecmp(const char * str1,const char * str2)240 my_strcasecmp(const char * str1, const char * str2)
241 {
242 #ifdef HAVE_STRCASECMP
243 return strcasecmp(str1, str2);
244 #else
245 int retval = 0;
246
247 while (1)
248 {
249 retval = tolower(*str1++) - tolower(*str2++);
250
251 if (retval)
252 break;
253
254 if (*str1 && *str2)
255 continue;
256 else
257 break;
258 }
259 return retval;
260 #endif
261 }
262
263 /* ============================================= */
264 /* memmove based strcpy (tolerates overlapping). */
265 /* ============================================= */
266 char *
my_strcpy(char * str1,char * str2)267 my_strcpy(char * str1, char * str2)
268 {
269 if (str1 == NULL || str2 == NULL)
270 return NULL;
271
272 memmove(str1, str2, strlen(str2) + 1);
273
274 return str1;
275 }
276
277 /* ================================ */
278 /* 7 bits aware version of isprint. */
279 /* ================================ */
280 int
isprint7(int i)281 isprint7(int i)
282 {
283 return (i >= 0x20 && i <= 0x7e);
284 }
285
286 /* ================================ */
287 /* 8 bits aware version of isprint. */
288 /* ================================ */
289 int
isprint8(int i)290 isprint8(int i)
291 {
292 unsigned char c = i & (unsigned char)0xff;
293
294 return (c >= 0x20 && c < 0x7f) || (c >= (unsigned char)0xa0);
295 }
296
297 /* ==================================================== */
298 /* Private implementation of wcscasecmp missing in c99. */
299 /* ==================================================== */
300 int
xwcscasecmp(const wchar_t * s1,const wchar_t * s2)301 xwcscasecmp(const wchar_t * s1, const wchar_t * s2)
302 {
303 wchar_t c1, c2;
304
305 while (*s1)
306 {
307 c1 = towlower(*s1);
308 c2 = towlower(*s2);
309
310 if (c1 != c2)
311 return (int)(c1 - c2);
312
313 s1++;
314 s2++;
315 }
316 return (-*s2);
317 }
318
319 /* ==================================================================== */
320 /* Returns 1 if s can be converted into an integer otherwise returns 0. */
321 /* ==================================================================== */
322 int
is_integer(const char * const s)323 is_integer(const char * const s)
324 {
325 long int n;
326
327 if (!s || (strspn(s, "0123456789 ") != strlen(s)))
328 return 0;
329
330 n = strtol(s, NULL, 10);
331
332 if (errno != ERANGE && n >= INT_MIN && n <= INT_MAX)
333 return 1;
334 else
335 return 0;
336 }
337