- add solv_strdup(), rename repo_freeallrepos() to pool_freeallrepos()
[platform/upstream/libsolv.git] / src / util.c
1 /*
2  * Copyright (c) 2007, Novell Inc.
3  *
4  * This program is licensed under the BSD license, read LICENSE.BSD
5  * for further information
6  */
7
8 #define _GNU_SOURCE
9
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <unistd.h>
13 #include <string.h>
14 #include <sys/time.h>
15
16 #include "util.h"
17
18 void
19 solv_oom(size_t num, size_t len)
20 {
21   if (num)
22     fprintf(stderr, "Out of memory allocating %zu*%zu bytes!\n", num, len);
23   else
24     fprintf(stderr, "Out of memory allocating %zu bytes!\n", len);
25   abort();
26   exit(1);
27 }
28
29 void *
30 solv_malloc(size_t len)
31 {
32   void *r = malloc(len ? len : 1);
33   if (!r)
34     solv_oom(0, len);
35   return r;
36 }
37
38 void *
39 solv_malloc2(size_t num, size_t len)
40 {
41   if (len && (num * len) / len != num)
42     solv_oom(num, len);
43   return solv_malloc(num * len);
44 }
45
46 void *
47 solv_realloc(void *old, size_t len)
48 {
49   if (old == 0)
50     old = malloc(len ? len : 1);
51   else
52     old = realloc(old, len ? len : 1);
53   if (!old)
54     solv_oom(0, len);
55   return old;
56 }
57
58 void *
59 solv_realloc2(void *old, size_t num, size_t len)
60 {
61   if (len && (num * len) / len != num)
62     solv_oom(num, len);
63   return solv_realloc(old, num * len);
64 }
65
66 void *
67 solv_calloc(size_t num, size_t len)
68 {
69   void *r;
70   if (num == 0 || len == 0)
71     r = malloc(1);
72   else
73     r = calloc(num, len);
74   if (!r)
75     solv_oom(num, len);
76   return r;
77 }
78
79 void *
80 solv_free(void *mem)
81 {
82   if (mem)
83     free(mem);
84   return 0;
85 }
86
87 char *
88 solv_strdup(const char *s)
89 {
90   char *r;
91   if (!s)
92     return 0;
93   r = strdup(s);
94   if (!r)
95     solv_oom(0, strlen(s));
96   return r;
97 }
98
99 unsigned int
100 solv_timems(unsigned int subtract)
101 {
102   struct timeval tv;
103   unsigned int r;
104
105   if (gettimeofday(&tv, 0))
106     return 0;
107   r = (((unsigned int)tv.tv_sec >> 16) * 1000) << 16;
108   r += ((unsigned int)tv.tv_sec & 0xffff) * 1000;
109   r += (unsigned int)tv.tv_usec / 1000;
110   return r - subtract;
111 }
112
113 /* bsd's qsort_r has different arguments, so we define our
114    own version in case we need to do some clever mapping
115
116    see also: http://sources.redhat.com/ml/libc-alpha/2008-12/msg00003.html
117  */
118 #if defined(__GLIBC__)
119
120 # if HAVE_QSORT_R || HAVE___QSORT_R
121 void
122 solv_sort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *, void *), void *compard)
123 {
124 # if HAVE_QSORT_R
125   qsort_r(base, nmemb, size, compar, compard);
126 # else
127   /* backported for SLE10-SP2 */
128   __qsort_r(base, nmemb, size, compar, compard);
129 # endif
130
131 }
132 #else /* qsort_r or __qsort_r on glibc */
133 /* use own version of qsort if none available */
134 #include "qsort_r.c"
135 #endif
136
137 #else /* not glibc */
138
139 struct solv_sort_data {
140   int (*compar)(const void *, const void *, void *);
141   void *compard;
142 };
143
144 static int
145 solv_sort_helper(void *compard, const void *a, const void *b)
146 {
147   struct solv_sort_data *d = compard;
148   return (*d->compar)(a, b, d->compard);
149 }
150
151 void
152 solv_sort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *, void *), void *compard)
153 {
154   struct solv_sort_data d;
155   d.compar = compar;
156   d.compard = compard;
157   qsort_r(base, nmemb, size, &d, solv_sort_helper);
158 }
159
160 #endif
161
162 char *
163 solv_dupjoin(const char *str1, const char *str2, const char *str3)
164 {
165   int l1, l2, l3;
166   char *s, *str;
167   l1 = str1 ? strlen(str1) : 0;
168   l2 = str2 ? strlen(str2) : 0;
169   l3 = str3 ? strlen(str3) : 0;
170   s = str = solv_malloc(l1 + l2 + l3 + 1);
171   if (l1)
172     {
173       strcpy(s, str1);
174       s += l1;
175     }
176   if (l2)
177     {
178       strcpy(s, str2);
179       s += l2;
180     }
181   if (l3)
182     {
183       strcpy(s, str3);
184       s += l3;
185     }
186   *s = 0;
187   return str;
188 }
189
190 char *
191 solv_dupappend(const char *str1, const char *str2, const char *str3)
192 {
193   char *str = solv_dupjoin(str1, str2, str3);
194   solv_free((void *)str1);
195   return str;
196 }
197
198 int
199 solv_hex2bin(const char **strp, unsigned char *buf, int bufl)
200 {
201   const char *str = *strp;
202   int i;
203
204   for (i = 0; i < bufl; i++)
205     {
206       int c = *str;
207       int d;
208       if (c >= '0' && c <= '9')
209         d = c - '0';
210       else if (c >= 'a' && c <= 'f')
211         d = c - ('a' - 10);
212       else if (c >= 'A' && c <= 'F')
213         d = c - ('A' - 10);
214       else
215         break;
216       c = *++str;
217       d <<= 4;
218       if (c >= '0' && c <= '9')
219         d |= c - '0';
220       else if (c >= 'a' && c <= 'f')
221         d |= c - ('a' - 10);
222       else if (c >= 'A' && c <= 'F')
223         d |= c - ('A' - 10);
224       else
225         break;
226       buf[i] = d;
227       ++str;
228     }
229   *strp = str;
230   return i;
231 }
232
233 char *
234 solv_bin2hex(const unsigned char *buf, int l, char *str)
235 {
236   int i;
237   for (i = 0; i < l; i++, buf++)
238     {
239       int c = *buf >> 4;
240       *str++ = c < 10 ? c + '0' : c + ('a' - 10);
241       c = *buf & 15;
242       *str++ = c < 10 ? c + '0' : c + ('a' - 10);
243     }
244   *str = 0;
245   return str;
246 }
247
248