]> wimlib.net Git - wimlib/blob - src/util.c
util.c: Simplify wimlib_aligned_malloc()
[wimlib] / src / util.c
1 /*
2  * util.c - utility functions
3  */
4
5 /*
6  * Copyright (C) 2012, 2013, 2014 Eric Biggers
7  *
8  * This file is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU Lesser General Public License as published by the Free
10  * Software Foundation; either version 3 of the License, or (at your option) any
11  * later version.
12  *
13  * This file is distributed in the hope that it will be useful, but WITHOUT
14  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15  * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with this file; if not, see http://www.gnu.org/licenses/.
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #  include "config.h"
24 #endif
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29
30 #include "wimlib.h"
31 #include "wimlib/assert.h"
32 #include "wimlib/timestamp.h"
33 #include "wimlib/util.h"
34 #include "wimlib/xml.h"
35
36 /*******************
37  * Memory allocation
38  *******************/
39
40 static void *(*wimlib_malloc_func) (size_t)         = malloc;
41 static void  (*wimlib_free_func)   (void *)         = free;
42 static void *(*wimlib_realloc_func)(void *, size_t) = realloc;
43
44 void *
45 wimlib_malloc(size_t size)
46 {
47         void *ptr;
48
49 retry:
50         ptr = (*wimlib_malloc_func)(size);
51         if (unlikely(!ptr)) {
52                 if (size == 0) {
53                         size = 1;
54                         goto retry;
55                 }
56         }
57         return ptr;
58 }
59
60 void
61 wimlib_free_memory(void *ptr)
62 {
63         (*wimlib_free_func)(ptr);
64 }
65
66 void *
67 wimlib_realloc(void *ptr, size_t size)
68 {
69         if (size == 0)
70                 size = 1;
71         return (*wimlib_realloc_func)(ptr, size);
72 }
73
74 void *
75 wimlib_calloc(size_t nmemb, size_t size)
76 {
77         size_t total_size = nmemb * size;
78         void *p = MALLOC(total_size);
79         if (p)
80                 p = memset(p, 0, total_size);
81         return p;
82 }
83
84 char *
85 wimlib_strdup(const char *str)
86 {
87         size_t size;
88         char *p;
89
90         size = strlen(str);
91         p = MALLOC(size + 1);
92         if (p)
93                 p = memcpy(p, str, size + 1);
94         return p;
95 }
96
97 #ifdef __WIN32__
98 wchar_t *
99 wimlib_wcsdup(const wchar_t *str)
100 {
101         size_t size;
102         wchar_t *p;
103
104         size = wcslen(str);
105         p = MALLOC((size + 1) * sizeof(wchar_t));
106         if (p)
107                 p = wmemcpy(p, str, size + 1);
108         return p;
109 }
110 #endif
111
112 void *
113 wimlib_aligned_malloc(size_t size, size_t alignment)
114 {
115         wimlib_assert(alignment != 0 && is_power_of_2(alignment) &&
116                       alignment <= 4096);
117
118         const uintptr_t mask = alignment - 1;
119         char *ptr = NULL;
120         char *raw_ptr;
121
122         raw_ptr = MALLOC(mask + sizeof(size_t) + size);
123         if (raw_ptr) {
124                 ptr = (char *)raw_ptr + sizeof(size_t);
125                 ptr = (void *)(((uintptr_t)ptr + mask) & ~mask);
126                 *((size_t *)ptr - 1) = ptr - raw_ptr;
127         }
128         return ptr;
129 }
130
131 void
132 wimlib_aligned_free(void *ptr)
133 {
134         if (ptr)
135                 FREE((char *)ptr - *((size_t *)ptr - 1));
136 }
137
138 void *
139 memdup(const void *mem, size_t size)
140 {
141         void *ptr = MALLOC(size);
142         if (ptr)
143                 ptr = memcpy(ptr, mem, size);
144         return ptr;
145 }
146
147 /* API function documented in wimlib.h  */
148 WIMLIBAPI int
149 wimlib_set_memory_allocator(void *(*malloc_func)(size_t),
150                             void (*free_func)(void *),
151                             void *(*realloc_func)(void *, size_t))
152 {
153         wimlib_malloc_func  = malloc_func  ? malloc_func  : malloc;
154         wimlib_free_func    = free_func    ? free_func    : free;
155         wimlib_realloc_func = realloc_func ? realloc_func : realloc;
156
157         xml_set_memory_allocator(wimlib_malloc_func, wimlib_free_func,
158                                  wimlib_realloc_func);
159         return 0;
160 }
161
162 /*******************
163  * String utilities
164  *******************/
165
166 #ifndef HAVE_MEMPCPY
167 void *mempcpy(void *dst, const void *src, size_t n)
168 {
169         return memcpy(dst, src, n) + n;
170 }
171 #endif
172
173 size_t
174 utf16le_strlen(const utf16lechar *s)
175 {
176         const utf16lechar *p = s;
177         while (*p)
178                 p++;
179         return (p - s) * sizeof(utf16lechar);
180 }
181
182 static bool seeded = false;
183
184 static void
185 seed_random(void)
186 {
187         srand(now_as_wim_timestamp());
188         seeded = true;
189 }
190
191 /* Fills @n characters pointed to by @p with random alphanumeric characters. */
192 void
193 randomize_char_array_with_alnum(tchar *p, size_t n)
194 {
195         if (!seeded)
196                 seed_random();
197         while (n--) {
198                 int r = rand() % 62;
199                 if (r < 26)
200                         *p++ = r + 'a';
201                 else if (r < 52)
202                         *p++ = r - 26 + 'A';
203                 else
204                         *p++ = r - 52 + '0';
205         }
206 }
207
208 /* Fills @n bytes pointer to by @p with random numbers. */
209 void
210 randomize_byte_array(u8 *p, size_t n)
211 {
212         if (!seeded)
213                 seed_random();
214         while (n--)
215                 *p++ = rand();
216 }