1 //
2 /**************************************************************************************************
3 * IOWOW library
4 *
5 * MIT License
6 *
7 * Copyright (c) 2012-2022 Softmotions Ltd <info@softmotions.com>
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a copy
10 * of this software and associated documentation files (the "Software"), to deal
11 * in the Software without restriction, including without limitation the rights
12 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 * copies of the Software, and to permit persons to whom the Software is
14 * furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included in all
17 * copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 * SOFTWARE.
26 *************************************************************************************************/
27
28
29 #include "iwcfg.h"
30 #include "iwutils.h"
31 #include "iwlog.h"
32 #include "iwxstr.h"
33
34 #include <limits.h>
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <stdint.h>
38 #include <fcntl.h>
39 #include <unistd.h>
40 #include <string.h>
41 #include "mt19937ar.h"
42
43 #ifndef O_CLOEXEC
44 #define O_CLOEXEC 0
45 #endif
46
47 #define IWU_RAND_MAX 0xffffffff
48
iwu_init(void)49 iwrc iwu_init(void) {
50 init_mt19937ar();
51 return 0;
52 }
53
iwu_rand_seed(uint32_t seed)54 void iwu_rand_seed(uint32_t seed) {
55 init_genrand(seed);
56 }
57
iwu_rand_u32(void)58 uint32_t iwu_rand_u32(void) {
59 return genrand_int32();
60 }
61
iwu_rand_dnorm(double_t avg,double_t sd)62 double_t iwu_rand_dnorm(double_t avg, double_t sd) {
63 assert(sd >= 0.0);
64 return sqrt(-2.0 * log((genrand_int31() / (double_t) INT_MAX)))
65 * cos(2 * 3.141592653589793 * (genrand_int31() / (double_t) INT_MAX)) * sd + avg;
66 }
67
iwu_rand_range(uint32_t range)68 uint32_t iwu_rand_range(uint32_t range) {
69 return genrand_int32() % range;
70 }
71
iwu_rand_inorm(int range)72 uint32_t iwu_rand_inorm(int range) {
73 int num = (int) iwu_rand_dnorm(range >> 1, (double_t) range / 10.0);
74 return (num < 0 || num >= range) ? 0 : num;
75 }
76
iwlog2_32(uint32_t val)77 int iwlog2_32(uint32_t val) {
78 static const int tab32[32] = {
79 0, 9, 1, 10, 13, 21, 2, 29,
80 11, 14, 16, 18, 22, 25, 3, 30,
81 8, 12, 20, 28, 15, 17, 24, 7,
82 19, 27, 23, 6, 26, 5, 4, 31
83 };
84 val |= val >> 1;
85 val |= val >> 2;
86 val |= val >> 4;
87 val |= val >> 8;
88 val |= val >> 16;
89 return tab32[(val * 0x07C4ACDD) >> 27];
90 }
91
iwlog2_64(uint64_t val)92 int iwlog2_64(uint64_t val) {
93 static const int table[64] = {
94 0, 58, 1, 59, 47, 53, 2, 60, 39, 48, 27, 54, 33, 42, 3, 61,
95 51, 37, 40, 49, 18, 28, 20, 55, 30, 34, 11, 43, 14, 22, 4, 62,
96 57, 46, 52, 38, 26, 32, 41, 50, 36, 17, 19, 29, 10, 13, 21, 56,
97 45, 25, 31, 35, 16, 9, 12, 44, 24, 15, 8, 23, 7, 6, 5, 63
98 };
99 val |= val >> 1;
100 val |= val >> 2;
101 val |= val >> 4;
102 val |= val >> 8;
103 val |= val >> 16;
104 val |= val >> 32;
105 return table[(val * 0x03f6eaf2cd271461) >> 58];
106 }
107
iwu_crc32(const uint8_t * buf,int len,uint32_t init)108 uint32_t iwu_crc32(const uint8_t *buf, int len, uint32_t init) {
109 static const unsigned int crc32_table[] = {
110 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
111 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
112 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
113 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
114 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9,
115 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
116 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011,
117 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
118 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
119 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
120 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81,
121 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
122 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49,
123 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
124 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
125 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
126 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae,
127 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
128 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
129 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
130 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
131 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
132 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066,
133 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
134 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e,
135 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
136 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
137 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
138 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
139 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
140 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686,
141 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
142 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
143 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
144 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f,
145 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
146 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47,
147 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
148 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
149 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
150 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7,
151 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
152 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f,
153 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
154 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
155 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
156 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f,
157 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
158 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
159 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
160 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
161 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
162 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30,
163 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
164 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088,
165 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
166 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
167 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
168 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
169 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
170 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0,
171 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
172 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
173 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
174 };
175
176 uint32_t crc = init;
177 while (len--) {
178 crc = (crc << 8) ^ crc32_table[((crc >> 24) ^ *buf) & 255];
179 buf++;
180 }
181 return crc;
182 }
183
iwu_replace_char(char * data,char sch,char rch)184 char* iwu_replace_char(char *data, char sch, char rch) {
185 for (int i = 0; data[i]; ++i) {
186 if (data[i] == sch) {
187 data[i] = rch;
188 }
189 }
190 return data;
191 }
192
iwu_cmp_files(FILE * f1,FILE * f2,bool verbose)193 int iwu_cmp_files(FILE *f1, FILE *f2, bool verbose) {
194 if (!f1 && !f2) {
195 return 0;
196 }
197 if (!f1) {
198 return -1;
199 }
200 if (!f2) {
201 return 1;
202 }
203 fseek(f1, 0, SEEK_SET);
204 fseek(f2, 0, SEEK_SET);
205 int c1 = getc(f1);
206 int c2 = getc(f2);
207 int pos = 0, line = 1;
208 while (c1 != EOF && c2 != EOF) {
209 pos++;
210 if ((c1 == '\n') && (c2 == '\n')) {
211 line++;
212 pos = 0;
213 } else if (c1 != c2) {
214 if (verbose) {
215 fprintf(stderr, "\nDiff at: %d:%d\n", line, pos);
216 }
217 return (c1 - c2);
218 }
219 c1 = getc(f1);
220 c2 = getc(f2);
221 }
222 if ((c1 - c2) && verbose) { // -V793
223 fprintf(stderr, "\nDiff at: %d:%d\n", line, pos);
224 }
225 return (c1 - c2);
226 }
227
iwu_file_read_as_buf_len(const char * path,size_t * out_len)228 char* iwu_file_read_as_buf_len(const char *path, size_t *out_len) {
229 IWXSTR *xstr = iwxstr_new();
230 if (!xstr) {
231 *out_len = 0;
232 return 0;
233 }
234 ssize_t rb, rc = 0;
235 char buf[8192];
236 int fd = open(path, O_RDONLY | O_CLOEXEC);
237 if (fd < 0) {
238 iwxstr_destroy(xstr);
239 return 0;
240 }
241 while (1) {
242 rb = read(fd, buf, sizeof(buf));
243 if (rb > 0) {
244 if (iwxstr_cat(xstr, buf, rb)) {
245 goto error;
246 }
247 rc += rb;
248 } else if (rb < 0) {
249 if (errno != EINTR) {
250 goto error;
251 }
252 } else {
253 break;
254 }
255 }
256
257 *out_len = rc;
258 return iwxstr_destroy_keep_ptr(xstr);
259
260 error:
261 *out_len = 0;
262 iwxstr_destroy(xstr);
263 return 0;
264 }
265
iwu_file_read_as_buf(const char * path)266 char* iwu_file_read_as_buf(const char *path) {
267 size_t sz;
268 return iwu_file_read_as_buf_len(path, &sz);
269 }
270
iwu_x31_u32_hash(const char * s)271 uint32_t iwu_x31_u32_hash(const char *s) {
272 uint32_t h = (uint32_t) *s;
273 if (h) {
274 for (++s; *s; ++s) {
275 h = (h << 5) - h + (uint32_t) *s;
276 }
277 }
278 return h;
279 }
280
iwu_replace(IWXSTR ** result,const char * data,int datalen,const char * keys[],int keysz,iwu_replace_mapper mapper,void * mapper_op)281 iwrc iwu_replace(
282 IWXSTR **result,
283 const char *data,
284 int datalen,
285 const char *keys[],
286 int keysz,
287 iwu_replace_mapper mapper,
288 void *mapper_op
289 ) {
290 if (!result || !data || !keys || !mapper) {
291 return IW_ERROR_INVALID_ARGS;
292 }
293
294 if (keysz < 0) {
295 for (keysz = 0; keys[keysz] != 0; ++keysz);
296 }
297
298 iwrc rc = 0;
299 if ((datalen < 1) || (keysz < 1)) {
300 *result = iwxstr_new2(datalen < 1 ? 1 : datalen);
301 if (datalen > 0) {
302 rc = iwxstr_cat(*result, data, datalen);
303 }
304 return rc;
305 }
306
307 const char *start = data;
308 const char *ptr = start;
309
310 IWXSTR *bbuf = 0;
311 IWXSTR *inter = 0;
312 bbuf = iwxstr_new2(datalen);
313 RCA(bbuf, finish);
314 inter = iwxstr_new2(datalen);
315 RCA(inter, finish);
316
317 for (int i = 0; i < keysz; ++i) {
318 iwxstr_clear(bbuf);
319 const char *key = keys[i];
320 size_t klen = strlen(key);
321 while (true) {
322 const char *p = strstr(ptr, key);
323 if (!p) {
324 if (ptr != start) {
325 rc = iwxstr_cat(bbuf, ptr, datalen - (ptr - start));
326 RCGO(rc, finish);
327 }
328 break;
329 }
330 iwxstr_cat(bbuf, ptr, p - ptr);
331 const char *repl = mapper(key, mapper_op);
332 rc = iwxstr_cat2(bbuf, repl ? repl : key);
333 RCGO(rc, finish);
334 ptr = p + klen;
335 if (ptr - start >= datalen) {
336 break;
337 }
338 }
339 if (ptr != start) {
340 iwxstr_clear(inter);
341 rc = iwxstr_cat(inter, iwxstr_ptr(bbuf), iwxstr_size(bbuf));
342 RCGO(rc, finish);
343 ptr = iwxstr_ptr(inter);
344 start = ptr;
345 datalen = iwxstr_size(inter);
346 }
347 }
348
349 finish:
350 if (bbuf) {
351 iwxstr_destroy(bbuf);
352 }
353 if (!rc && (start == data)) {
354 rc = iwxstr_cat(inter, data, datalen);
355 }
356 if (rc) {
357 if (inter) {
358 iwxstr_destroy(inter);
359 }
360 } else {
361 *result = inter;
362 }
363 return rc;
364 }
365