30#ifndef _ACF_UTILS_HELPERS_H_
31#define _ACF_UTILS_HELPERS_H_
49#define _LACF_GETLINE_INCLUDED
51#define _LACF_PARSER_FUNCS_INCLUDED
77#define IS_VALID_GEO_POS3(pos) \
78 (is_valid_lat((pos).lat) && is_valid_lon((pos).lon) && \
79 is_valid_elev((pos).elev))
86#define IS_VALID_GEO_POS2(pos) \
87 (is_valid_lat((pos).lat) && is_valid_lon((pos).lon))
95 return (!isnan(lat) && fabs(lat) <= 90);
104 return (!isnan(lat) && fabs(lat) <= 90);
113 return (!isnan(lon) && fabs(lon) <= 180.0);
125 return (!isnan(elev) && elev >= MIN_ELEV && elev <= MAX_ELEV);
128#ifdef LACF_ENABLE_LEGACY_IS_VALID_ALT
129#define is_valid_alt(alt) is_valid_alt_ft(alt)
141 return (!isnan(alt_ft) && alt_ft >= MIN_ALT && alt_ft <= MAX_ALT);
151 return (!isnan(alt_m) && alt_m >= MIN_ALT / 3.2808398950131 &&
152 alt_m <= MAX_ALT / 3.2808398950131);
162 return (!isnan(spd) && spd >= 0.0 && spd <= MAX_SPD);
171 return (!isnan(hdg) && hdg >= 0.0 && hdg <= 360.0);
198#define rel_hdg(hdg1, hdg2) rel_hdg_impl(hdg1, hdg2, __FILE__, __LINE__)
199API_EXPORT
double rel_hdg_impl(
double hdg1,
double hdg2,
const char *file,
219 hdg = fmod(hdg, 360);
224 if (hdg <= 0.0 || hdg > 360.0) {
225 hdg =
clamp(hdg, 0, 360);
248 if (isnan(hdg_rad)) {
251 hdg_rad = fmod(hdg_rad, 360);
254 hdg_rad += 2.0 * M_PI;
257 if (hdg_rad <= 0.0 || hdg_rad > 2.0 * M_PI) {
258 hdg_rad =
clamp(hdg_rad, 0, 2.0 * M_PI);
260 if (hdg_rad == -0.0) {
285 return (
clamp(lon, -180, 180));
350API_EXPORT
void copy_rwy_ID(
const char *src,
char dst[4]);
356 time_t *cycle_end_p);
389#if defined(ACFUTILS_BUILD) || defined(ACFUTILS_GZIP_PARSER)
397#if defined(ACFUTILS_BUILD) || defined(ACFUTILS_GZIP_PARSER)
402parser_get_next_gzline(
void *gz_fp,
char **linep,
size_t *linecap,
421API_EXPORT ssize_t
explode_line(
char *line,
char delim,
char **comps,
424 PRINTF_FORMAT(
const char *format), ...) PRINTF_ATTR(3);
436 for (
int i = 0, n = strlen(str); i < n; i++) {
443API_EXPORT
char **
strsplit(
const char *input,
const char *sep,
444 bool_t skip_empty,
size_t *num);
450#define DESTROY_STRLIST(comps, num) \
452 free_strlist((comps), (num)); \
459API_EXPORT
char *
mkpathname(
const char *comp, ...) SENTINEL_ATTR;
460API_EXPORT
char *
mkpathname_v(const
char *comp, va_list ap);
465API_EXPORT
char *
path_ext_subst(const
char *path, const
char *ext);
468API_EXPORT
char *
file2str(const
char *comp, ...) SENTINEL_ATTR;
469API_EXPORT
char *
file2str_ext(
long *len_p, const
char *comp, ...) SENTINEL_ATTR;
470API_EXPORT
char *
file2str_name(
long *len_p, const
char *filename);
471API_EXPORT
void *
file2buf(const
char *filename,
size_t *bufsz);
472API_EXPORT ssize_t
filesz(const
char *filename);
481#define strlcpy lacf_strlcpy
483API_EXPORT
void lacf_strlcpy(
char *restrict dest,
const char *restrict src,
490static inline const char *
493 const char *sep = strrchr(str, DIRSEP);
496 const char *sep2 = strrchr(str,
'/');
513#if defined(ACFUTILS_BUILD) || defined(ACFUTILS_GZIP_PARSER)
520#if IBM && !defined(__cplusplus) && \
521 (defined(_GNU_SOURCE) || defined(_POSIX_C_SOURCE))
522#define getline lacf_getline
549 l = vsnprintf(NULL, 0, fmt, ap2);
554 (void)vsnprintf(str, l + 1, fmt, ap);
571PRINTF_ATTR(1) static inline
char *
596 enum { STACKBUFSZ_LIM = 1024 };
604 if (l1 < STACKBUFSZ_LIM && l2 < STACKBUFSZ_LIM) {
605 char s1_lower[STACKBUFSZ_LIM], s2_lower[STACKBUFSZ_LIM];
611 res = strncmp(s1_lower, s2_lower, n);
620 res = strncmp(s1_lower, s2_lower, n);
649 enum { STACKBUFSZ_LIM = 1024 };
654 l1 = strlen(haystack);
657 if (l1 < STACKBUFSZ_LIM && l2 < STACKBUFSZ_LIM) {
658 char haystack_lower[STACKBUFSZ_LIM];
659 char needle_lower[STACKBUFSZ_LIM];
661 lacf_strlcpy(haystack_lower, haystack,
sizeof (haystack_lower));
662 lacf_strlcpy(needle_lower, needle,
sizeof (needle_lower));
665 res = strstr(haystack_lower, needle_lower);
667 res = (
char *)haystack + (res - haystack_lower);
669 char *haystack_lower = (
char *)
safe_malloc(l1 + 1);
676 res = strstr(haystack_lower, needle_lower);
678 res = (
char *)haystack + (res - haystack_lower);
679 free(haystack_lower);
720 if (x > -1e-10 && x < 1e-10)
721 return (MAX(digits - 1, 0));
726 digits = MAX(digits - 1, 0);
727 return (
clampi(digits - ceil(log10(x)), 0, digits));
736#define P2ROUNDUP(x) (-(-(x) & -(1 << highbit64(x))))
741 return (round(x / y) * y);
747 return (floor(x / y) * y);
779#define SET_BITFIELD_1(out_var, bit_mask, bit_value) \
782 (out_var) |= (bit_mask); \
784 (out_var) &= ~(bit_mask); \
788API_EXPORT bool_t
file_exists(
const char *path, bool_t *isdir);
792API_EXPORT bool_t
remove_file(
const char *filename, bool_t notfound_ok);
796#if IBM && (defined(_GNU_SOURCE) || defined(_POSIX_C_SOURCE))
804 WIN32_FIND_DATA find_data;
809API_EXPORT DIR *opendir(
const char *path);
810API_EXPORT
struct dirent *readdir(DIR *dirp);
811API_EXPORT
void closedir(DIR *dirp);
813#define sleep(x) SleepEx((x) * 1000, FALSE)
814#define usleep(x) SleepEx((x) / 1000, FALSE)
820API_EXPORT
void win_perror(DWORD err, PRINTF_FORMAT(
const char *fmt), ...)
825API_EXPORT
void lacf_qsort_r(
void *base,
size_t nmemb,
size_t size,
826 int (*compar)(
const void *,
const void *,
void *),
void *arg);
848#if defined(__STDC_LIB_EXT1__) || IBM
849 return (_gmtime64_s(tm, tim) == 0);
851 return (gmtime_r(tim, tm) != NULL);
char * file2str_name(long *len_p, const char *filename)
static int fixed_decimals(double x, int digits)
char * lacf_dirname(const char *filename)
char ** strsplit(const char *input, const char *sep, bool_t skip_empty, size_t *num)
static bool_t is_valid_spd(double spd)
ssize_t filesz(const char *filename)
void unescape_percent(char *str)
int airac_time2cycle(time_t t)
static ssize_t lacf_getline(char **lineptr, size_t *n, FILE *stream)
void fix_pathsep(char *str)
char * mkpathname(const char *comp,...)
void strtoupper(char *str)
char * path_ext_subst(const char *path, const char *ext)
void copy_rwy_ID(const char *src, char dst[4])
char * file2str(const char *comp,...)
bool_t remove_directory(const char *dirname)
bool_t is_valid_icao_code(const char *icao)
ssize_t explode_line(char *line, char delim, char **comps, size_t capacity)
void path_normalize(char *path)
static bool_t lacf_gmtime_r(const time_t *tim, struct tm *tm)
size_t utf8_get_num_chars(const char *str)
static bool_t is_valid_loc_freq_khz(uint32_t freq_khz)
static int lacf_strncasecmp(const char *s1, const char *s2, size_t n)
static bool_t is_valid_alt_ft(double alt_ft)
bool_t is_valid_loc_freq(double freq_mhz)
static ssize_t parser_get_next_line(FILE *fp, char **linep, size_t *linecap, unsigned *linenum)
char * file2str_ext(long *len_p, const char *comp,...)
const char * extract_icao_country_code(const char *icao)
static bool_t is_valid_elev(double elev)
static bool_t is_valid_vor_freq_khz(uint32_t freq_khz)
bool_t is_valid_vor_freq(double freq_mhz)
bool_t is_valid_ndb_freq(double freq_khz)
static bool_t is_valid_hdg(double hdg)
static char * sprintf_alloc(const char *fmt,...)
const char * airac_cycle2eff_date(int cycle)
bool_t create_directory(const char *dirname)
bool_t is_valid_tacan_freq(double freq_mhz)
void * file2buf(const char *filename, size_t *bufsz)
static char * vsprintf_alloc(const char *fmt, va_list ap)
bool_t airac_cycle2exp_date(int cycle, char buf[16], time_t *cycle_end_p)
static double normalize_hdg(double hdg)
static int lacf_strcasecmp(const char *s1, const char *s2)
static const char * lacf_basename(const char *str)
void append_format(char **str, size_t *sz, const char *format,...)
void lacf_qsort_r(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *, void *), void *arg)
void lacf_strlcpy(char *dest, const char *src, size_t cap)
void free_strlist(char **comps, size_t num)
double rel_hdg_impl(double hdg1, double hdg2, const char *file, int line)
size_t utf8_char_get_num_bytes(const char *str)
bool_t create_directory_recursive(const char *dirname)
bool_t is_valid_rwy_ID(const char *rwy_ID)
static void normalize_whitespace(char *str)
char * path_last_comp(const char *path)
void strtolower(char *str)
static bool_t is_valid_lat(double lat)
bool_t remove_file(const char *filename, bool_t notfound_ok)
time_t airac_cycle2eff_date2(int cycle)
static double normalize_lon(double lon)
bool_t is_valid_xpdr_code(int code)
static bool_t is_valid_ndb_freq_hz(uint32_t freq_hz)
static bool_t is_valid_alt_m(double alt_m)
static bool_t is_valid_vor_freq_hz(uint32_t freq_hz)
static char * parser_get_next_quoted_str(FILE *fp)
static bool_t is_valid_lat_polar(double lat)
static double roundmul(double x, double y)
char * mkpathname_v(const char *comp, va_list ap)
bool_t file_exists(const char *path, bool_t *isdir)
static bool_t is_valid_lon(double lon)
static double normalize_hdg_rad(double hdg_rad)
bool_t is_valid_iata_code(const char *iata)
char * path_last_comp_subst(const char *path, const char *replace)
static double floormul(double x, double y)
static bool_t is_valid_loc_freq_hz(uint32_t freq_hz)
static char * lacf_strcasestr(const char *haystack, const char *needle)
static ssize_t lacf_getline_impl(char **line_p, size_t *cap_p, void *fp)
static double clamp(double x, double min_val, double max_val)
static int clampi(int x, int min_val, int max_val)
static char * parser_get_next_quoted_str2(FILE *fp, int *linep)
static ssize_t parser_get_next_line_impl(void *fp, char **linep, size_t *linecap, unsigned *linenum)
static void * safe_malloc(size_t size)