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
string_startswith(const char * s1,const char * s2)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
count_char(const char * s,int ch)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 *
triml(char * s)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 *
trimr(char * s)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
swap(int * a,int * b)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
div_floor(int x,int y)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
mod(int x,int y)138 mod(int x, int y)
139 {
140 return x - y * div_floor(x, y);
141 }
142
143 static inline double
mod_f(double x,double y)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
mod1(int x,int y)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
mod3(int x,int a,int b)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
mod3_f(double x,double a,double b)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
sin_deg(double deg)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
cos_deg(double deg)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
tan_deg(double deg)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
arcsin_deg(double x)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
arccos_deg(double x)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
arctan_deg(double y,double x)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
angle2deg(int deg,int min,double sec)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