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