• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #pragma once
2 #ifndef IWUTILS_H
3 #define IWUTILS_H
4 
5 /**************************************************************************************************
6  * IOWOW library
7  *
8  * MIT License
9  *
10  * Copyright (c) 2012-2022 Softmotions Ltd <info@softmotions.com>
11  *
12  * Permission is hereby granted, free of charge, to any person obtaining a copy
13  * of this software and associated documentation files (the "Software"), to deal
14  * in the Software without restriction, including without limitation the rights
15  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16  *  copies of the Software, and to permit persons to whom the Software is
17  * furnished to do so, subject to the following conditions:
18  *
19  * The above copyright notice and this permission notice shall be included in all
20  * copies or substantial portions of the Software.
21  *
22  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28  * SOFTWARE.
29  *************************************************************************************************/
30 /**
31  * @file
32  * @author Anton Adamansky (adamansky@softmotions.com)
33  */
34 
35 #include "basedefs.h"
36 #include "iwxstr.h"
37 #include <math.h>
38 #include <assert.h>
39 #include <stdbool.h>
40 #include <stdio.h>
41 
42 IW_EXTERN_C_START
43 
44 #define IW_RANGES_OVERLAP(IW_s1_, IW_e1_, IW_s2_, IW_e2_) \
45   (  ((IW_e1_) > (IW_s2_) && (IW_e1_) <= (IW_e2_))          \
46   || ((IW_s1_) >= (IW_s2_) && (IW_s1_) < (IW_e2_))          \
47   || ((IW_s1_) <= (IW_s2_) && (IW_e1_) >= (IW_e2_)))
48 
49 ///////////////////////////////////////////////////////////////////////////
50 //                    Variable length number encoding                    //
51 ///////////////////////////////////////////////////////////////////////////
52 
53 /* set a buffer for a variable length 32 bit number */
54 #define IW_SETVNUMBUF(len_, buf_, num_) \
55   do { \
56     int32_t _num_ = (num_); \
57     if (_num_ == 0) { \
58       ((signed char*) (buf_))[0] = 0; \
59       (len_) = 1; \
60     } else { \
61       (len_) = 0; \
62       while (_num_ > 0) { \
63         int _rem_ = _num_ & 0x7f; \
64         _num_ >>= 7; \
65         if (_num_ > 0) { \
66           ((signed char*) (buf_))[(len_)] = ~(_rem_); \
67         } else { \
68           ((signed char*) (buf_))[(len_)] = _rem_; \
69         } \
70         (len_)++; \
71       } \
72     } \
73   } while (0)
74 
75 /* set a buffer for a variable length 64 number */
76 #define IW_SETVNUMBUF64(len_, buf_, num_) \
77   do { \
78     int64_t _num_ = (num_); \
79     if (_num_ == 0) { \
80       ((signed char*) (buf_))[0] = 0; \
81       (len_) = 1; \
82     } else { \
83       (len_) = 0; \
84       while (_num_ > 0) { \
85         int _rem_ = _num_ & 0x7f; \
86         _num_ >>= 7; \
87         if (_num_ > 0) { \
88           ((signed char*) (buf_))[(len_)] = ~(_rem_); \
89         } else { \
90           ((signed char*) (buf_))[(len_)] = _rem_; \
91         } \
92         (len_)++; \
93       } \
94     } \
95   } while (0)
96 
97 
98 /* read a 32 bit variable length buffer */
99 #define IW_READVNUMBUF(buf_, num_, step_) \
100   do { \
101     (num_) = 0; \
102     int32_t _base_ = 1; \
103     int _i_ = 0; \
104     while (1) { \
105       if (((const signed char*) (buf_))[_i_] >= 0) { \
106         (num_) += _base_ * ((const signed char*) (buf_))[_i_]; \
107         break; \
108       } \
109       (num_) += _base_ * ~(((const signed char*) (buf_))[_i_]); \
110       _base_ <<= 7; \
111       _i_++; \
112     } \
113     (step_) = _i_ + 1; \
114   } while (0)
115 
116 /* read a 64 bit variable length buffer */
117 #define IW_READVNUMBUF64(buf_, num_, step_) \
118   do { \
119     (num_) = 0; \
120     int64_t _base_ = 1; \
121     int _i_ = 0; \
122     while (1) { \
123       if (((const signed char*) (buf_))[_i_] >= 0) { \
124         (num_) += _base_ * ((const signed char*) (buf_))[_i_]; \
125         break; \
126       } \
127       (num_) += _base_ * ~(((const signed char*) (buf_))[_i_]); \
128       _base_ <<= 7; \
129       _i_++; \
130     } \
131     (step_) = _i_ + 1; \
132   } while (0)
133 
134 
135 /* read a 64 bit variable length buffer */
136 #define IW_READVNUMBUF64_2(buf_, num_) \
137   do { \
138     (num_) = 0; \
139     int64_t _base_ = 1; \
140     int _i_ = 0; \
141     while (1) { \
142       if (((const signed char*) (buf_))[_i_] >= 0) { \
143         (num_) += _base_ * ((const signed char*) (buf_))[_i_]; \
144         break; \
145       } \
146       (num_) += _base_ * ~(((const signed char*) (buf_))[_i_]); \
147       _base_ <<= 7; \
148       _i_++; \
149     } \
150   } while (0)
151 
152 
153 #define IW_VNUMBUFSZ 10
154 
155 #define IW_VNUMSIZE32(num_) \
156   ((num_) < 0x80ULL ? 1   \
157    : (num_) < 0x4000ULL ? 2   \
158    : (num_) < 0x200000ULL ? 3   \
159    : (num_) < 0x10000000ULL ? 4 : 5)
160 
161 /* Size of variable number in bytes */
162 #ifdef IW_32
163 #define IW_VNUMSIZE IW_VNUMSIZE32
164 #else
165 #define IW_VNUMSIZE(num_) \
166   ((num_) < 0x80ULL ? 1   \
167    : (num_) < 0x4000ULL ? 2   \
168    : (num_) < 0x200000ULL ? 3   \
169    : (num_) < 0x10000000ULL ? 4   \
170    : (num_) < 0x800000000ULL ? 5   \
171    : (num_) < 0x40000000000ULL ? 6   \
172    : (num_) < 0x2000000000000ULL ? 7   \
173    : (num_) < 0x100000000000000ULL ? 8   \
174    : (num_) < 0x8000000000000000ULL ? 9 : 10)
175 #endif
176 
177 /* Lexicographic comparison of values */
178 #define IW_CMP(rv_, vp1_, vp1sz_, vp2_, vp2sz_) \
179   do { \
180     (rv_) = 0; \
181     int min_ = (vp1sz_) < (vp2sz_) ? (vp1sz_) : (vp2sz_); \
182     for (int i = 0; i < min_; i++) { \
183       (rv_) = (int) (((const uint8_t*) (vp1_))[i] - ((const uint8_t*) (vp2_))[i]); \
184       if (rv_) { \
185         break; \
186       } \
187     } \
188     if ((rv_) == 0) (rv_) = (vp1sz_) - (vp2sz_); \
189   } while (0)
190 
191 
192 /* Lexicographic comparison common prefix of values */
193 #define IW_CMP2(rv_, vp1_, vp1sz_, vp2_, vp2sz_) \
194   do { \
195     (rv_) = 0; \
196     int min_ = (vp1sz_) < (vp2sz_) ? (vp1sz_) : (vp2sz_); \
197     for (int i = 0; i < min_; i++) { \
198       (rv_) = (int) (((const uint8_t*) (vp1_))[i] - ((const uint8_t*) (vp2_))[i]); \
199       if (rv_) { \
200         break; \
201       } \
202     } \
203   } while (0)
204 
205 IW_EXPORT iwrc iwu_init(void);
206 
207 /**
208  * @brief Set seed to random generator
209  */
210 IW_EXPORT void iwu_rand_seed(uint32_t seed);
211 
212 /**
213  * @brief Generate random in [0, 0xffffffff]
214  */
215 IW_EXPORT uint32_t iwu_rand_u32(void);
216 
217 /**
218  * @brief Create normal distributed random number.
219  * @param avg Distribution pivot
220  * @param sd Avg square deviation
221  */
222 IW_EXPORT double_t iwu_rand_dnorm(double_t avg, double_t sd);
223 
224 /**
225  * @brief Create uniform distributed integer random number in: `[0, range)`
226  */
227 IW_EXPORT uint32_t iwu_rand_range(uint32_t range);
228 
229 /**
230  * @brief Create normal distributed integer random number.
231  */
232 IW_EXPORT uint32_t iwu_rand_inorm(int range);
233 
234 IW_EXPORT int iwlog2_32(uint32_t val);
235 
236 IW_EXPORT int iwlog2_64(uint64_t val);
237 
238 IW_EXPORT uint32_t iwu_crc32(const uint8_t *buf, int len, uint32_t init);
239 
240 /**
241  * @brief Replaces a char @a sch with @a rch in a null terminated @a data char buffer.
242  */
243 IW_EXPORT char* iwu_replace_char(char *data, char sch, char rch);
244 
245 /**
246  * @brief Returns `\0` terminated string as replacement
247  * of given `key`.
248  */
249 typedef const char* (*iwu_replace_mapper)(const char *key, void *op);
250 
251 /**
252  * @brief Replaces all occurriences of `keys`
253  * in `data` using `mapper` function.
254  *
255  * @param [out] result Resulting xstr buffer.
256  * @param data   Data to search
257  * @param datalen Length of data buffer
258  * @param keys   Array of keys to search
259  * @param keysz  Number of elements in keys array.
260  *               Negative for NULL terminated arrays.
261  * @param mapper Replacement mapper
262  * @param mapper_op Replacement mapper opaque data
263  */
264 IW_EXPORT iwrc iwu_replace(
265   IWXSTR           **result,
266   const char        *data,
267   int                datalen,
268   const char        *keys[],
269   int                keysz,
270   iwu_replace_mapper mapper,
271   void              *mapper_op);
272 
273 IW_EXPORT int iwu_cmp_files(FILE *f1, FILE *f2, bool verbose);
274 
275 IW_EXPORT char* iwu_file_read_as_buf(const char *path);
276 
277 IW_EXPORT char* iwu_file_read_as_buf_len(const char *path, size_t *out_len);
278 
279 /**
280  * @brief Create X31 hash value.
281  */
282 IW_EXPORT uint32_t iwu_x31_u32_hash(const char *data);
283 
284 IW_EXTERN_C_END
285 
286 #endif
287