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