• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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