nrelease - fix/improve livecd
[dragonfly.git] / usr.bin / calendar / utils.h
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