/* Copyright (C) 2015-2020, Dirk Krause SPDX-License-Identifier: BSD-3-Clause */ /* WARNING: This file was generated by the dkct program (see http://dktools.sourceforge.net/ for details). Changes you make here will be lost if dkct is run again! You should modify the original source and run dkct on it. Original source: dk4str8.ctr */ /** @file dk4str8.c The dk4str8 module. */ #line 423 "dk4str8.ctr" #include "dk4conf.h" #ifndef DK4USE_H_INCLUDED #include "dk4use.h" #endif #if DK4_ON_WINDOWS && (DK4_WIN_AVOID_CRT || DK4_WIN_DENY_CRT) #ifndef WINDOWS_H_INCLUDED #include #define WINDOWS_H_INCLUDED 1 #endif #endif #include "dk4str8.h" #if DK4_HAVE_STRING_H #ifndef STRING_H_INCLUDED #include #define STRING_H_INCLUDED 1 #endif #endif #if DK4_HAVE_CTYPE_H #ifndef CTYPE_H_INCLUDED #include #define CTYPE_H_INCLUDED 1 #endif #endif #if DK4_HAVE_ASSERT_H #ifndef ASSERT_H_INCLUDED #include #define ASSERT_H_INCLUDED 1 #endif #endif #ifndef DK4NUMCO_H_INCLUDED #include "dk4numco.h" #endif #ifndef DK4MEM_H_INCLUDED #include "dk4mem.h" #endif #ifndef DK4MEMRS_H_INCLUDED #include "dk4memrs.h" #endif #line 475 "dk4str8.ctr" /** Constant strings used in the module. */ static const char * const dk4str8_modkw[] = { /* 0 */ " \t\r\n", NULL #line 487 "dk4str8.ctr" }; /** First index of a keyword indicating true in the dk4str8_boolkw array below. */ #define DK4STR8_FIRST_TRUE 5 /** Keywords for boolean values. */ static const char * const dk4str8_boolkw[] = { /* 0 */ "-", /* 1 */ "0", /* 2 */ "n$o", /* 3 */ "of$f", /* 4 */ "f$alse", /* 5 */ "+", /* 6 */ "1", /* 7 */ "y$es", /* 8 */ "on", /* 9 */ "t$rue", /* 10 */ "ok", NULL #line 518 "dk4str8.ctr" }; #if 0 /** Number of significant digits. */ static const int dk4str8_dbl_digits = DK4_DBL_DIGITS; #endif void dk4str8_cpy_to_left(char *dst, const char *src) { register char *dptr; register const char *sptr; #if DK4_USE_ASSERT assert(NULL != dst); assert(NULL != src); #endif if (NULL != dst) { *dst = '\0'; if (NULL != src) { dptr = dst; sptr = src; while('\0' != *sptr) { *(dptr++) = *(sptr++); } *dptr = '\0'; } } } size_t dk4str8_len(const char *src) { if (NULL == src) { return 0; } #if DK4_ON_WINDOWS /* +++ Windows */ #if DK4_WIN_AVOID_CRT || DK4_WIN_DENY_CRT return ((size_t)lstrlenA(src)); #else return (strlen(src)); #endif /* --- Windows */ #else /* +++ non-Windows */ return (strlen(src)); /* --- non-Windows */ #endif } char dk4str8_toupper(char c) { #if DK4_ON_WINDOWS #if DK4_WIN_DENY_CRT char back; back = c; if (('a' <= c) && ('z' >= c)) { back = 'A' + (c - 'a'); } return back; #else return (char)toupper((unsigned char)c); #endif #else return (char)toupper((unsigned char)c); #endif } char dk4str8_tolower(char c) { #if DK4_ON_WINDOWS #if DK4_WIN_DENY_CRT char back; back = c; if (('A' <= c) && ('Z' >= c)) { back = 'a' + (c - 'A'); } return back; #else return (char)tolower((unsigned char)c); #endif #else return (char)tolower((unsigned char)c); #endif } char * dk4str8_chr(const char *s, char c) { if (NULL == s) { return NULL; } #if DK4_ON_WINDOWS /* +++ Windows */ #if DK4_WIN_DENY_CRT { char *back = NULL; while (('\0' != *s) && (NULL == back)) { if (c == *s) { back = (char *)s; } else { s++; } } return back; } #else #ifdef __cplusplus return ((char *)strchr(s, (int)((unsigned char)c))); #else return (strchr(s, (int)((unsigned char)c))); #endif #endif /* --- Windows */ #else /* +++ non-Windows */ #ifdef __cplusplus return ((char *)strchr(s, (int)((unsigned char)c))); #else return (strchr(s, (int)((unsigned char)c))); #endif /* --- non-Windows */ #endif } char * dk4str8_rchr(const char *s, char c) { if (NULL == s) { return NULL; } #if DK4_ON_WINDOWS #if DK4_WIN_DENY_CRT { char *back = NULL; while ('\0' != *s) { if (c == *s) { back = (char *)s; } s++; } return back; } #else #ifdef __cplusplus return ((char *)strrchr(s, (int)((unsigned char)c))); #else return (strrchr(s, (int)((unsigned char)c))); #endif #endif #else #ifdef __cplusplus return ((char *)strrchr(s, (int)((unsigned char)c))); #else return (strrchr(s, (int)((unsigned char)c))); #endif #endif } int dk4str8_cpy_s(char *dst, size_t sz, const char *src, dk4_er_t *erp) { int back = 0; #if DK4_USE_ASSERT assert(NULL != dst); assert(0 < sz); #endif if ((NULL != dst) && (0 < sz)) { *dst = '\0'; if (NULL != src) { if (dk4str8_len(src) < sz) { #if DK4_ON_WINDOWS /* +++ Windows */ #if DK4_WIN_AVOID_CRT || DK4_WIN_DENY_CRT (void)lstrcpyA(dst, (char *)src); #else #if DK4_USE_PRAGMA_WARNING_DISABLE #pragma warning( push ) #pragma warning( disable: 4996 ) #endif (void)strcpy(dst, src); #if DK4_USE_PRAGMA_WARNING_DISABLE #pragma warning( pop ) #endif #endif /* --- Windows */ #else /* +++ non-Windows */ (void)strcpy(dst, src); /* --- non-Windows */ #endif back = 1; } else { *dst = '\0'; dk4error_set_simple_error_code(erp, DK4_E_BUFFER_TOO_SMALL); } } else { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); } } else { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); } return back; } int dk4str8_cat_s(char *dst, size_t sz, const char *src, dk4_er_t *erp) { size_t la; size_t lb; int back = 0; #if DK4_USE_ASSERT assert(NULL != dst); assert(0 < sz); #endif if ((NULL != dst) && (0 < sz) && (NULL != src)) { la = dk4str8_len(dst); lb = dk4str8_len(src); if ((SIZE_MAX - la) >= lb) { if ((la + lb) < sz) { #if DK4_ON_WINDOWS /* +++ Windows */ #if DK4_WIN_AVOID_CRT || DK4_WIN_DENY_CRT (void)lstrcatA(dst, (char *)src); #else #if DK4_USE_PRAGMA_WARNING_DISABLE #pragma warning( push ) #pragma warning( disable: 4996 ) #endif (void)strcat(dst, src); #if DK4_USE_PRAGMA_WARNING_DISABLE #pragma warning( pop ) #endif #endif /* --- Windows */ #else /* +++ non-Windows */ (void)strcat(dst, src); /* --- non-Windows */ #endif back = 1; } else { dk4error_set_simple_error_code(erp, DK4_E_BUFFER_TOO_SMALL); } } else { dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW); } } else { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); } return back; } int dk4str8_cmp(const char *s1, const char *s2) { int back = 0; if (NULL != s1) { if (NULL != s2) { #if DK4_ON_WINDOWS /* +++ Windows */ #if DK4_WIN_AVOID_CRT || DK4_WIN_DENY_CRT back = lstrcmpA(s1, s2); #else back = strcmp(s1, s2); #endif /* --- Windows */ #else /* +++ non-Windows */ back = strcmp(s1, s2); /* --- non-Windows */ #endif if (0 > back) back = -1; if (0 < back) back = 1; } else { back = 1; } } else { if (NULL != s2) { back = -1; } } return back; } int dk4str8_ncmp(const char *s1, const char *s2, size_t n) { int back = 0; if (NULL != s1) { if (NULL != s2) { #if (DK4_ON_WINDOWS && (DK4_WIN_AVOID_CRT || DK4_WIN_DENY_CRT) ) \ || (!(DK4_HAVE_WCSNCMP)) || (!(DK4_HAVE__WCSNCMP)) while((0 < n--) && (0 == back)) { if ('\0' == *s1) { if ('\0' == *s2) { n = 0; } else { back = -1; } } else { if ('\0' == *s2) { back = 1; } else { if (*s1 > *s2) { back = 1; } else { if (*s1 < *s2) { back = -1; } else { s1++; s2++; } } } } } #else back = strncmp(s1, s2, n); if (-1 > back) back = -1; if ( 1 < back) back = 1; #endif } else { back = 1; } } else { if (NULL != s2) { back = -1; } } return back; } int dk4str8_casecmp(const char *s1, const char *s2) { int back = 0; if (NULL != s1) { if (NULL != s2) { #if DK4_ON_WINDOWS /* +++ Windows */ #if DK4_WIN_AVOID_CRT || DK4_WIN_DENY_CRT back = lstrcmpiA(s1, s2); #else back = _stricmp(s1, s2); #endif /* --- non-Windows */ #else /* +++ non-Windows */ #if DK4_HAVE_STRCASECMP back = strcasecmp(s1, s2); #else #if DK4_HAVE__STRICMP back = _stricmp(s1, s2); #else #if DK4_HAVE_STRICMP back = stricmp(s1, s2); #else #error No function for case-insensitive comparison available! #endif #endif #endif /* --- non-Windows */ #endif if (0 > back) back = -1; if (0 < back) back = 1; } else { back = 1; } } else { if (NULL != s2) { back = -1; } } return back; } #if (DK4_ON_WINDOWS) || (DK4_HAVE_MALLOC && DK4_HAVE_FREE) char * dk4str8_dup(const char *src, dk4_er_t *erp) { char *back = NULL; size_t lgt; if (NULL != src) { lgt = dk4str8_len(src); if (SIZE_MAX > lgt) { back = (char *)dk4mem_malloc_bytes((1+lgt), erp); if (NULL != back) { (void)dk4str8_cpy_s(back, (1+lgt), src, erp); } } else { dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW); } } else { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); } return back; } #endif char * dk4str8_start(const char *src, const char *delim) { char *back = NULL; if (NULL != src) { if (NULL == delim) { delim = dk4str8_modkw[0]; } while (('\0' != *src) && (NULL == back)) { if (NULL != dk4str8_chr(delim, (unsigned char)(*src))) { src++; } else { back = (char *)src; } } } return back; } /** Internal function for next token search. CRT on Windows: Optional, disabling CRT degrades performance. @param src String containing tokens, must be set to the start of a token. @param delim Delimiter set. @return Pointer to next token on success, NULL on error. */ static char * dk4str8_i_next(char *src, const char *delim) { char *back = NULL; if (NULL != src) { if (NULL == delim) { delim = dk4str8_modkw[0]; } while (('\0' != *src) && (NULL == back)) { if (NULL != dk4str8_chr(delim, (unsigned char)(*src))) { back = src; } else { src++; } } if (NULL != back) { *(back++) = '\0'; back = dk4str8_start(back, delim); } } return back; } char * dk4str8_next(char *src, const char *delim) { char *back = NULL; if (NULL != src) { back = dk4str8_start(src, delim); if (NULL != back) { back = dk4str8_i_next(back, delim); } } return back; } char * dk4str8_sep(char **stringp, const char *delim) { char *back = NULL; #line 1013 "dk4str8.ctr" #if DK4_USE_ASSERT assert(NULL != stringp); #endif if (NULL != stringp) { if (NULL != *stringp) { if (NULL == delim) { delim = dk4str8_modkw[0]; } back = dk4str8_start(*stringp, delim); if (NULL != back) { *stringp = dk4str8_next(back, delim); } else { *stringp = NULL; } } } #line 1027 "dk4str8.ctr" return back; } size_t dk4str8_tokenize( char **dpp, size_t szdpp, char *src, const char *delim, dk4_er_t *erp ) { char *context; char *token; size_t back = 0; #if DK4_USE_ASSERT assert(NULL != dpp); assert(0 < szdpp); #endif if ((NULL != dpp) && (0 < szdpp) && (NULL != src)) { if (NULL == delim) { delim = dk4str8_modkw[0]; } context = src; while (NULL != (token = dk4str8_sep(&context, delim))) { if (back < szdpp) { dpp[back] = token; } back++; } if (back >= szdpp) { dk4error_set_elsize_nelem( erp, DK4_E_BUFFER_TOO_SMALL, sizeof(DK4_PCHAR), back ); back = 0; } } else { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); } return back; } void dk4str8_normalize(char *src, const char *delim) { char *p1; /* Pointer to traverse text. */ char *p2; /* Start of next token. */ int cc; /* Flag: Can continue. */ if (NULL != src) { /* Set up delimiter set, correct if necessary. */ if (NULL == delim) { delim = dk4str8_modkw[0]; } /* Remove leading delimiters. */ p1 = src; cc = 0; if ('\0' != *p1) { if (NULL != dk4str8_chr(delim, (unsigned char)(*p1))) { p2 = dk4str8_start(p1, delim); if (NULL != p2) { dk4str8_cpy_to_left(p1, p2); cc = 1; } else { *p1 = '\0'; } } else { cc = 1; } } /* Now traverse the string. */ while (0 != cc) { if ('\0' == *p1) { cc = 0; } else { if (NULL != dk4str8_chr(delim, (unsigned char)(*p1))) { *p1 = *delim; if ('\0' == p1[1]) { *p1 = '\0'; cc = 0; } else { if (NULL != dk4str8_chr(delim, (unsigned char)(p1[1]))) { p2 = dk4str8_start(p1, delim); if (NULL != p2) { dk4str8_cpy_to_left(++p1, p2); } else { *p1 = '\0'; cc = 0; } } else { p1++; } } } else { p1++; } } } } } int dk4str8_array_index(const char * const *arr, const char *str, int cs) { int back = -1; int cand = 0; #if DK4_USE_ASSERT assert(NULL != arr); #endif if ((NULL != arr) && (NULL != str)) { while((NULL != *arr) && (-1 == back)) { if (0 != cs) { if (0 == dk4str8_cmp(*arr, str)) { back = cand; } } else { if (0 == dk4str8_casecmp(*arr, str)) { back = cand; } } arr++; cand++; } } return back; } int dk4str8_is_abbr(const char *str, const char *pattern, char spec, int cs) { const char *lptr = NULL; /* Pointer to traverse string */ const char *pptr = NULL; /* Pointer to traverse pattern */ int back = 0; /* Function result */ int fspec = 0; /* Flag: spec was found */ int cc = 1; /* Flag: Can continue */ char cl; char cp; #line 1165 "dk4str8.ctr" #if DK4_USE_ASSERT assert(NULL != pattern); #endif if ((NULL != str) && (NULL != pattern)) { lptr = str; pptr = pattern; while (0 != cc) { if ((0 == fspec) && (*pptr == spec)) { fspec = 1; pptr++; } else { if ('\0' != *lptr) { cl = *lptr; cp = *pptr; if (0 == cs) { cl = dk4str8_toupper(cl); cp = dk4str8_toupper(cp); } if (cl == cp) { lptr++; pptr++; } else { cc = 0; } } else { cc = 0; if (('\0' == *pptr) || (0 != fspec)) { back = 1; } } } } } #line 1194 "dk4str8.ctr" return back; } int dk4str8_abbr_index(const char * const *arr, char spec, const char *str, int cs) { int back = -1; int cand = 0; #line 1205 "dk4str8.ctr" #if DK4_USE_ASSERT assert(NULL != arr); #endif if ((NULL != arr) && (NULL != str)) { while ((NULL != *arr) && (-1 == back)) { if (0 != dk4str8_is_abbr(str, *arr, spec, cs)) { back = cand; } arr++; cand++; } } #line 1217 "dk4str8.ctr" return back; } int dk4str8_is_bool(const char *str) { int back = 0; if (NULL != str) { if (-1 < dk4str8_abbr_index(dk4str8_boolkw, '$', str, 0)) { back = 1; } } return back; } int dk4str8_is_on(const char *str) { int back = 0; #line 1241 "dk4str8.ctr" if (NULL != str) { back = dk4str8_abbr_index(dk4str8_boolkw, '$', str, 0); if (-1 < back) { if (DK4STR8_FIRST_TRUE <= back) { back = 1; } else { back = 0; } } else { back = 0; } } #line 1254 "dk4str8.ctr" return back; } int dk4str8_pathcmp(const char *s1, const char *s2) { #if DK4_HAVE_CASE_INSENSITIVE_PATHNAMES return (dk4str8_casecmp(s1, s2)); #else return (dk4str8_cmp(s1, s2)); #endif } void dk4str8_rtwh(char *str, const char *whsp) { char *ptr = NULL; if (NULL == whsp) { whsp = dk4str8_modkw[0]; } if (NULL != str) { while ('\0' != *str) { if (NULL != dk4str8_chr(whsp, *str)) { if (NULL == ptr) { ptr = str; } } else { ptr = NULL; } str++; } if (NULL != ptr) { *ptr = '\0'; } } } void dk4str8_delnl(char *lptr) { if (NULL != lptr) { while ('\0' != *lptr) { if ('\n' == *lptr) { *lptr = '\0'; } else { if ('\r' == *lptr) { if ('\n' == lptr[1]) { *lptr = '\0'; } else { if ('\0' == lptr[1]) { *lptr = '\0'; } else { lptr++; } } } else { lptr++; } } } } } const char * dk4str8_skip(const char *line, size_t skip) { const char *back = NULL; size_t words = 0; /* Number of words already found */ int lwt = 0; /* Flag: Last char was text */ if (NULL != line) { if (0 < skip) { while((NULL == back) && ('\0' != *line)) { switch (*line) { case ' ': case '\t': case '\n': case '\r': { lwt = 0; } break; default: { if (0 == lwt) { if (++words > skip) { back = line; } } lwt = 1; } break; } line++; } } else { back = dk4str8_start(line, NULL); } } return back; } int dk4str8_buffer_sanitize(char *str, size_t sz) { int back = 0; #if DK4_USE_ASSERT assert(NULL != str); assert(0 < sz); #endif if (NULL != str) { if (0 < sz) { back = dk4mem_reset_secure(str, sz, NULL); } else { back = 1; } } return back; } int dk4str8_sanitize(char *str) { int back = 0; if (NULL != str) { back = dk4str8_buffer_sanitize(str, dk4str8_len(str)); } return back; } int dk4str8_free_sanitized(char *str) { int back = 0; if (NULL != str) { back = dk4str8_sanitize(str); dk4mem_free(str); } return back; }