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