1 /*- 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright (c) 2019-2020 The DragonFly Project. All rights reserved. 5 * 6 * This code is derived from software contributed to The DragonFly Project 7 * by Aaron LI <aly@aaronly.me> 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in 17 * the documentation and/or other materials provided with the 18 * distribution. 19 * 3. Neither the name of The DragonFly Project nor the names of its 20 * contributors may be used to endorse or promote products derived 21 * from this software without specific, prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 26 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 27 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 28 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 29 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 30 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 31 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 32 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 33 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 */ 36 37 #ifndef UTILS_H_ 38 #define UTILS_H_ 39 40 #include <ctype.h> 41 #include <err.h> 42 #include <errno.h> 43 #include <math.h> 44 #include <stdbool.h> 45 #include <stddef.h> 46 #include <string.h> 47 48 #ifndef nitems 49 #define nitems(x) (sizeof(x) / sizeof((x)[0])) 50 #endif 51 52 53 /* 54 * Return true if string $s1 starts with the string $s2. 55 */ 56 static inline bool 57 string_startswith(const char *s1, const char *s2) 58 { 59 return (s1 && s2 && strncmp(s1, s2, strlen(s2)) == 0); 60 } 61 62 /* 63 * Count the number of character $ch in string $s. 64 */ 65 static inline size_t 66 count_char(const char *s, int ch) 67 { 68 size_t count = 0; 69 70 for ( ; *s; s++) { 71 if (*s == ch) 72 count++; 73 } 74 75 return count; 76 } 77 78 /* 79 * Trim the leading whitespaces of the given string $s 80 * and return the trimed string. 81 */ 82 static inline char * 83 triml(char *s) 84 { 85 while (isspace((unsigned char)*s)) 86 s++; 87 88 return s; 89 } 90 91 /* 92 * Trim the trailing whitespaces of the given string $s 93 * and return the trimed string. 94 */ 95 static inline char * 96 trimr(char *s) 97 { 98 size_t l = strlen(s); 99 100 while (l > 0 && isspace((unsigned char) s[l-1])) 101 l--; 102 s[l] = '\0'; 103 104 return s; 105 } 106 107 108 /* 109 * Swap the values of two integers. 110 */ 111 static inline void 112 swap(int *a, int *b) 113 { 114 int tmp = *a; 115 *a = *b; 116 *b = tmp; 117 } 118 119 /* 120 * Divide integer $x by integer $y, rounding towards minus infinity. 121 */ 122 static inline int 123 div_floor(int x, int y) 124 { 125 int q = x / y; 126 int r = x % y; 127 if ((r != 0) && ((r < 0) != (y < 0))) 128 q--; 129 return q; 130 } 131 132 /* 133 * Calculate the remainder of $x divided by $y; the result has the same 134 * sign as $y. 135 * Ref: Sec.(1.7), Eq.(1.17) 136 */ 137 static inline int 138 mod(int x, int y) 139 { 140 return x - y * div_floor(x, y); 141 } 142 143 static inline double 144 mod_f(double x, double y) 145 { 146 return x - y * floor(x / y); 147 } 148 149 /* 150 * Return the value of ($x % $y) with $y instead of 0, i.e., with value 151 * range being [1, $y]. 152 */ 153 static inline int 154 mod1(int x, int y) 155 { 156 return y + mod(x, -y); 157 } 158 159 /* 160 * Calculate the interval modulus of $x, i.e., shifted into the range 161 * [$a, $b). Return $x if $a = $b. 162 * Ref: Sec.(1.7), Eq.(1.24) 163 */ 164 static inline int 165 mod3(int x, int a, int b) 166 { 167 if (a == b) 168 return x; 169 else 170 return a + mod(x - a, b - a); 171 } 172 173 static inline double 174 mod3_f(double x, double a, double b) 175 { 176 static const double eps = 1e-6; 177 178 if (fabs(a - b) < eps) 179 return x; 180 else 181 return a + mod_f(x - a, b - a); 182 } 183 184 185 /* 186 * Calculate the sine value of degree $deg. 187 */ 188 static inline double 189 sin_deg(double deg) 190 { 191 return sin(M_PI * deg / 180.0); 192 } 193 194 /* 195 * Calculate the cosine value of degree $deg. 196 */ 197 static inline double 198 cos_deg(double deg) 199 { 200 return cos(M_PI * deg / 180.0); 201 } 202 203 /* 204 * Calculate the tangent value of degree $deg. 205 */ 206 static inline double 207 tan_deg(double deg) 208 { 209 return tan(M_PI * deg / 180.0); 210 } 211 212 /* 213 * Calculate the arc sine value (in degrees) of $x. 214 */ 215 static inline double 216 arcsin_deg(double x) 217 { 218 return asin(x) * 180.0 / M_PI; 219 } 220 221 /* 222 * Calculate the arc cosine value (in degrees) of $x. 223 */ 224 static inline double 225 arccos_deg(double x) 226 { 227 return acos(x) * 180.0 / M_PI; 228 } 229 230 /* 231 * Calculate the arc tangent value (in degrees from 0 to 360) of $y / $x. 232 * Error if $x and $y are both zero. 233 */ 234 static inline double 235 arctan_deg(double y, double x) 236 { 237 errno = 0; 238 double v = atan2(y, x); 239 if (errno == EDOM) 240 errx(10, "%s(%g, %g) invalid!", __func__, y, x); 241 return mod_f(v * 180.0 / M_PI, 360); 242 } 243 244 /* 245 * Convert angle in (degree, arcminute, arcsecond) to degree. 246 */ 247 static inline double 248 angle2deg(int deg, int min, double sec) 249 { 250 return deg + min/60.0 + sec/3600.0; 251 } 252 253 254 double poly(double x, const double *coefs, size_t n); 255 double invert_angular(double (*f)(double), double y, double a, double b); 256 257 void * xmalloc(size_t size); 258 void * xcalloc(size_t number, size_t size); 259 void * xrealloc(void *ptr, size_t size); 260 char * xstrdup(const char *str); 261 262 struct node; 263 struct node * list_newnode(char *name, void *data); 264 struct node * list_addfront(struct node *listp, struct node *newp); 265 bool list_lookup(struct node *listp, const char *name, 266 int (*cmp)(const char *, const char *), 267 void **data_out); 268 void list_freeall(struct node *listp, void (*free_name)(void *), 269 void (*free_data)(void *)); 270 271 #endif 272