/* 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: dk4strw.ctr */ /** @file dk4strw.c The dk4strw module. */ #line 432 "dk4strw.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 "dk4strw.h" #include "dk4mem.h" #include "dk4numco.h" #if DK4_HAVE_WCTYPE_H #ifndef WCTYPE_H_INCLUDED #include #define WCTYPE_H_INCLUDED 1 #endif #endif #if DK4_HAVE_ASSERT_H #ifndef ASSERT_H_INCLUDED #include #define ASSERT_H_INCLUDED 1 #endif #endif #ifndef DK4MEMRS_H_INCLUDED #include "dk4memrs.h" #endif #line 472 "dk4strw.ctr" /** Constant strings used in the module. */ static const wchar_t * const dk4strw_modkw[] = { /* 0 */ L" \t\r\n", NULL #line 484 "dk4strw.ctr" }; /** First index of a keyword indicating true in the dk4str8_boolkw array below. */ #define DK4STRW_FIRST_TRUE 5 /** Keywords for boolean values. */ static const wchar_t * const dk4strw_boolkw[] = { /* 0 */ L"-", /* 1 */ L"0", /* 2 */ L"n$o", /* 3 */ L"of$f", /* 4 */ L"f$alse", /* 5 */ L"+", /* 6 */ L"1", /* 7 */ L"y$es", /* 8 */ L"on", /* 9 */ L"t$rue", /* 10 */ L"ok", NULL #line 515 "dk4strw.ctr" }; #if 0 /** Number of significant digits when printing a double. */ static const int dk4strw_dbl_digits = DK4_DBL_DIGITS; #endif void dk4strw_cpy_to_left(wchar_t *dst, const wchar_t *src) { register wchar_t *dptr; register const wchar_t *sptr; #if DK4_USE_ASSERT assert(NULL != dst); assert(NULL != src); #endif if ((NULL != dst) && (NULL != src)) { dptr = dst; sptr = src; while(L'\0' != *sptr) { *(dptr++) = *(sptr++); } *dptr = L'\0'; } } size_t dk4strw_len(const wchar_t *src) { if (NULL == src) { return 0; } #if DK4_ON_WINDOWS /* +++ Windows */ #if DK4_WIN_AVOID_CRT || DK4_WIN_DENY_CRT return ((size_t)lstrlenW(src)); #else return (wcslen(src)); #endif /* --- Windows */ #else /* +++ Windows */ #if DK4_HAVE_WCSLEN return (wcslen(src)); #else size_t back = 0; while(L'\0' != *src) { src++; back++; } return back; #endif /* --- Windows */ #endif } wchar_t * dk4strw_chr(const wchar_t *s, wchar_t c) { if (NULL == s) { return NULL; } #if DK4_ON_WINDOWS /* +++ Windows */ #if DK4_WIN_DENY_CRT { wchar_t *back = NULL; while ((L'\0' != *s) && (NULL == back)) { if (c == *s) { back = (wchar_t *)s; } s++; } return back; } #else #ifdef __cplusplus return ((wchar_t *)wcschr(s, c)); #else return (wcschr(s, c)); #endif #endif /* --- Windows */ #else /* +++ non-Windows */ #if DK4_HAVE_WCSCHR #ifdef __cplusplus return ((wchar_t *)wcschr(s, c)); #else return (wcschr(s, c)); #endif #else { wchar_t *back = NULL; while ((L'\0' != *s) && (NULL == back)) { if (c == *s) { back = (wchar_t *)s; } s++; } return back; } #endif /* --- non-Windows */ #endif } wchar_t * dk4strw_rchr(const wchar_t *s, wchar_t c) { if (NULL == s) { return NULL; } #if DK4_ON_WINDOWS /* +++ Windows */ #if DK4_WIN_DENY_CRT { wchar_t *back = NULL; while (L'\0' != *s) { if (c == *s) { back = (wchar_t *)s; } s++; } return back; } #else #ifdef __cplusplus return ((wchar_t *)wcsrchr(s, c)); #else return (wcsrchr(s, c)); #endif #endif /* --- Windows */ #else /* +++ non-Windows */ #if DK4_HAVE_WCSRCHR #ifdef __cplusplus return ((wchar_t *)wcsrchr(s, c)); #else return (wcsrchr(s, c)); #endif #else { wchar_t *back = NULL; while (L'\0' != *s) { if (c == *s) { back = (wchar_t *)s; } s++; } return back; } #endif /* --- non-Windows */ #endif } wchar_t dk4strw_toupper(wchar_t c) { #if DK4_ON_WINDOWS /* +++ Windows */ #if DK4_WIN_DENY_CRT if ((L'a' <= c) && (L'z' >= c)) { return (L'A' + (c - L'a')); } else { return c; } #else return (towupper(c)); #endif /* --- Windows */ #else /* +++ non-Windows */ return (towupper(c)); /* --- non-Windows */ #endif } wchar_t dk4strw_tolower(wchar_t c) { #if DK4_ON_WINDOWS /* +++ Windows */ #if DK4_WIN_DENY_CRT if ((L'A' <= c) && (L'Z' >= c)) { return (L'a' + (c - L'A')); } else { return c; } #else return (towlower(c)); #endif /* --- Windows */ #else /* +++ non-Windows */ return (towlower(c)); /* --- non-Windows */ #endif } int dk4strw_cpy_s(wchar_t *dst, size_t sz, const wchar_t *src, dk4_er_t *erp) { int back = 0; size_t sl; #if DK4_USE_ASSERT assert(NULL != dst); assert(0 < sz); #endif if ((NULL != dst) && (0 < sz)) { *dst = L'\0'; if (NULL != src) { sl = dk4strw_len(src); if (sz > sl) { #if DK4_ON_WINDOWS /* +++ Windows */ #if DK4_WIN_AVOID_CRT || DK4_WIN_DENY_CRT (void)lstrcpyW(dst, (wchar_t *)src); #else #if DK4_USE_PRAGMA_WARNING_DISABLE #pragma warning( push ) #pragma warning( disable: 4996 ) #endif (void)wcscpy(dst, src); #if DK4_USE_PRAGMA_WARNING_DISABLE #pragma warning( pop ) #endif #endif /* --- Windows */ #else /* +++ non-Windows */ #if DK4_HAVE_WCSCPY (void)wcscpy(dst, src); #else size_t nbytes; dk4_er_t er; dk4error_init(&er); if ((SIZE_MAX - 1) < sl) { dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW); } else { if ((SIZE_MAX / sizeof(wchar_t)) < (sl + 1)) { dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW); } else { nbytes = sizeof(wchar_t) * (sl + 1); } } if (DK4_E_NONE == er.ec) { DK4_MEMCPY(dst, src, nbytes); } else { dk4strw_cpy_to_left(dst, src); } #endif /* --- 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_INVALID_ARGUMENTS); } } else { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); } return back; } int dk4strw_cat_s(wchar_t *dst, size_t sz, const wchar_t *src, dk4_er_t *erp) { size_t la; /* Size of string in destination buffer */ size_t lb; /* Source string size */ int back = 0; #if DK4_USE_ASSERT assert(NULL != dst); assert(0 < sz); #endif if ((NULL != dst) && (0 < sz) && (NULL != src)) { la = dk4strw_len(dst); lb = dk4strw_len(src); if (sz > (la + lb)) { #if DK4_ON_WINDOWS /* +++ Windows */ #if DK4_WIN_AVOID_CRT || DK4_WIN_DENY_CRT (void)lstrcatW(dst, src); #else #if DK4_USE_PRAGMA_WARNING_DISABLE #pragma warning( push ) #pragma warning( disable: 4996 ) #endif (void)wcscat(dst, src); #if DK4_USE_PRAGMA_WARNING_DISABLE #pragma warning( pop ) #endif #endif /* --- Windows */ #else /* +++ non-Windows */ #if DK4_HAVE_WCSCAT (void)wcscat(dst, src); #else size_t nb; dk4_er_t er; dk4error_init(&er); if ((SIZE_MAX - 1) < lb) { dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW); } else { if ((SIZE_MAX / sizeof(wchar_t)) < (lb + 1)) { dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW); } else { nb = sizeof(wchar_t) * (lb + 1); } } if (DK4_E_NONE == er.ec) { DK4_MEMCPY(&(dst[la]), src, nb); } else { dk4strw_cpy_to_left(&(dst[la]), src); } #endif /* --- 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_INVALID_ARGUMENTS); } return back; } int dk4strw_cmp(const wchar_t *s1, const wchar_t *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 = lstrcmpW(s1, s2); if (0 > back) back = -1; if (0 < back) back = 1; #else back = wcscmp(s1, s2); if (0 > back) back = -1; if (0 < back) back = 1; #endif /* --- Windows */ #else /* +++ non-Windows */ #if DK4_HAVE_WCSCMP back = wcscmp(s1, s2); if (0 > back) back = -1; if (0 < back) back = 1; #else #if DK4_HAVE__WCSCMP back = _wcscmp(s1, s2); if (0 > back) back = -1; if (0 < back) back = 1; #else do { if (*s1 > *s2) { back = 1; } else { if (*s1 < *s2) { back = -1; } else { if (L'\0' != *s1) { s1++; s2++; } } } } while((0 == back) && (L'\0' != *s1)); #endif #endif /* --- non-Windows */ #endif } else { back = 1; } } else { if (NULL != s2) { back = -1; } } return back; } int dk4strw_ncmp(const wchar_t *s1, const wchar_t *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 (L'\0' == *s1) { if (L'\0' == *s2) { n = 0; } else { back = -1; } } else { if (L'\0' == *s2) { back = 1; } else { if (*s1 < *s2) { back = -1; } else { if (*s1 > *s2) { back = 1; } else { s1++; s2++; } } } } } #else #if DK4_HAVE_WCSNCMP back = wcsncmp(s1, s2, n); #else back = _wcsncmp(s1, s2, n); #endif if (-1 > back) back = -1; if ( 1 < back) back = 1; #endif } else { back = 1; } } else { if (NULL != s2) { back = -1; } } return back; } int dk4strw_casecmp(const wchar_t *s1, const wchar_t *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 = lstrcmpiW(s1, s2); if (0 > back) back = -1; if (0 < back) back = 1; #else back =_wcsicmp(s1, s2); if (0 > back) back = -1; if (0 < back) back = 1; #endif /* --- Windows */ #else /* +++ non-Windows */ #if DK4_HAVE_WCSCASECMP back = wcscasecmp(s1, s2); if (0 > back) back = -1; if (0 < back) back = 1; #else #if DK4_HAVE__WCSCASECMP back = _wcscasecmp(s1, s2); if (0 > back) back = -1; if (0 < back) back = 1; #else #if DK4_HAVE__WCSICMP back = _wcsicmp(s1, s2); if (0 > back) back = -1; if (0 < back) back = 1; #else #if DK4_HAVE_WCSICMP back = wcsicmp(s1, s2); if (0 > back) back = -1; if (0 < back) back = 1; #else wchar_t c1; wchar_t c2; c1 = dk4strw_toupper(*s1); c2 = dk4strw_toupper(*s2); do { if (c1 > c2) { back = 1; } else { if (c1 < c2) { back = -1; } else { if (L'\0' != *s1) { s1++; s2++; } } } } while((0 == back) && (L'\0' != *s1)); #endif #endif #endif #endif /* --- non-Windows */ #endif } else { back = 1; } } else { if (NULL != s2) { back = -1; } } return back; } #if (DK4_ON_WINDOWS) || (DK4_HAVE_MALLOC && DK4_HAVE_FREE) wchar_t * dk4strw_dup(const wchar_t *src, dk4_er_t *erp) { wchar_t *back = NULL; size_t lgt; if (NULL != src) { lgt = dk4strw_len(src); if (SIZE_MAX > lgt) { back = dk4mem_new(wchar_t,(lgt+1),erp); if (NULL != back) { (void)dk4strw_cpy_s(back, (lgt+1), 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 #if !DK4_HAVE_WCSCHR /** Find first occurance of character in string. @param src String to search for character. @param c Character to find. @return Pointer to first occurance on success, NULL on error. */ static const wchar_t * dk4strw_i_wcschr(const wchar_t *src, wchar_t c) { const wchar_t *back = NULL; while ((L'\0' != *src) && (NULL == back)) { if (*src == c) { back = src; } else { src++; } } return back; } #endif wchar_t * dk4strw_start(const wchar_t *src, const wchar_t *delim) { wchar_t *back = NULL; if (NULL != src) { if (NULL == delim) { delim = dk4strw_modkw[0]; } while((L'\0' != *src) && (NULL == back)) { if (NULL != dk4strw_chr(delim, *src)) { src++; } else { back = (wchar_t *)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 wchar_t * dk4strw_i_next(wchar_t *src, const wchar_t *delim) { wchar_t *back = NULL; if (NULL != src) { if (NULL == delim) { delim = dk4strw_modkw[0]; } while ((L'\0' != *src) && (NULL == back)) { if (NULL != dk4strw_chr(delim, *src)) { back = src; } else { src++; } } if (NULL != back) { *(back++) = L'\0'; back = dk4strw_start(back, delim); } } return back; } wchar_t * dk4strw_next(wchar_t *src, const wchar_t *delim) { wchar_t *back = NULL; if (NULL != src) { back = dk4strw_start(src, delim); if (NULL != back) { back = dk4strw_i_next(back, delim); } } return back; } wchar_t * dk4strw_sep(wchar_t **stringp, const wchar_t *delim) { wchar_t *back = NULL; #line 1168 "dk4strw.ctr" #if DK4_USE_ASSERT assert(NULL != stringp); #endif if (NULL != stringp) { if (NULL != *stringp) { if (NULL == delim) { delim = dk4strw_modkw[0]; } back = dk4strw_start(*stringp, delim); if (NULL != back) { *stringp = dk4strw_next(back, delim); } else { *stringp = NULL; } } } #line 1182 "dk4strw.ctr" return back; } size_t dk4strw_tokenize( wchar_t **dpp, size_t szdpp, wchar_t *src, const wchar_t *delim, dk4_er_t *erp ) { wchar_t *context; wchar_t *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 = dk4strw_modkw[0]; } context = src; while (NULL != (token = dk4strw_sep(&context, delim))) { if (back < szdpp) { dpp[back] = token; } back++; } if (back >= szdpp) { /* Too many tokens found */ 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 dk4strw_normalize(wchar_t *src, const wchar_t *delim) { wchar_t *p1; /* Pointer to traverse text. */ wchar_t *p2; /* Start of next token. */ int cc; /* Flag: Can continue. */ if (NULL != src) { if (NULL == delim) { delim = dk4strw_modkw[0]; } p1 = src; cc = 0; if (L'\0' != *p1) { if (NULL != dk4strw_chr(delim, *p1)) { p2 = dk4strw_start(p1, delim); if (NULL != p2) { dk4strw_cpy_to_left(p1, p2); cc = 1; } else { *p1 = L'\0'; } } else { cc = 1; } } while (0 != cc) { if (L'\0' == *p1) { cc = 0; } else { if (NULL != dk4strw_chr(delim, *p1)) { *p1 = *delim; if (L'\0' == p1[1]) { *p1 = L'\0'; cc = 0; } else { if (NULL != dk4strw_chr(delim, p1[1])) { p2 = dk4strw_start(p1, delim); if (NULL != p2) { dk4strw_cpy_to_left(++p1, p2); } else { *p1 = L'\0'; cc = 0; } } else { p1++; } } } else { p1++; } } } } } int dk4strw_array_index(const wchar_t * const *arr, const wchar_t *str, int cs) { int back = -1; int cand = 0; #if DK4_USE_ASSERT assert(NULL != arr); #endif while ((NULL != *arr) && (-1 == back)) { if (0 != cs) { if (0 == dk4strw_cmp(*arr, str)) { back = cand; } } else { if (0 == dk4strw_casecmp(*arr, str)) { back = cand; } } arr++; cand++; } return back; } int dk4strw_is_abbr(const wchar_t *str,const wchar_t *pattern,wchar_t spec,int cs) { const wchar_t *lptr = NULL; /* Pointer to traverse string */ const wchar_t *pptr = NULL; /* Pointer to traverse pattern */ int back = 0; /* Function result */ int fspec = 0; /* Flag: spec was found */ int cc = 1; /* Flag: Can continue */ wchar_t cl; wchar_t cp; #line 1312 "dk4strw.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 (L'\0' != *lptr) { cl = *lptr; cp = *pptr; if (0 == cs) { cl = dk4strw_toupper(cl); cp = dk4strw_toupper(cp); } if (cl == cp) { lptr++; pptr++; } else { cc = 0; } } else { cc = 0; if ((L'\0' == *pptr) || (0 != fspec)) { back = 1; } } } } } #line 1342 "dk4strw.ctr" return back; } int dk4strw_abbr_index( const wchar_t * const *arr, wchar_t spec, const wchar_t *str, int cs ) { int back = -1; int cand = 0; /* Traverse array */ #line 1358 "dk4strw.ctr" #if DK4_USE_ASSERT assert(NULL != arr); #endif if ((NULL != arr) && (NULL != str)) { while ((NULL != *arr) && (-1 == back)) { if (0 != dk4strw_is_abbr(str, *arr, spec, cs)) { back = cand; } arr++; cand++; } } #line 1370 "dk4strw.ctr" return back; } int dk4strw_is_bool(const wchar_t *str) { int back = 0; if (NULL != str) { if (-1 < dk4strw_abbr_index(dk4strw_boolkw, L'$', str, 0)) { back = 1; } } return back; } int dk4strw_is_on(const wchar_t *str) { int back = 0; #line 1394 "dk4strw.ctr" if (NULL != str) { back = dk4strw_abbr_index(dk4strw_boolkw, L'$', str, 0); if (-1 < back) { if (DK4STRW_FIRST_TRUE <= back) { back = 1; #line 1399 "dk4strw.ctr" } else { back = 0; #line 1401 "dk4strw.ctr" } } else { back = 0; #line 1404 "dk4strw.ctr" } } #line 1407 "dk4strw.ctr" return back; } int dk4strw_pathcmp(const wchar_t *s1, const wchar_t *s2) { #if DK4_HAVE_CASE_INSENSITIVE_PATHNAMES return (dk4strw_casecmp(s1, s2)); #else return (dk4strw_cmp(s1, s2)); #endif } void dk4strw_rtwh(wchar_t *str, const wchar_t *whsp) { wchar_t *ptr = NULL; /* Pointer to first whitespace */ if (NULL == whsp) { whsp = dk4strw_modkw[0]; } if (NULL != str) { while (L'\0' != *str) { if (NULL != dk4strw_chr(whsp, *str)) { if (NULL == ptr) { ptr = str; } } else { ptr = NULL; } str++; } if (NULL != ptr) { *ptr = L'\0'; } } } void dk4strw_delnl(wchar_t *lptr) { if (NULL != lptr) { while (L'\0' != *lptr) { if (L'\n' == *lptr) { *lptr = L'\0'; } else { if (L'\r' == *lptr) { if (L'\n' == lptr[1]) { *lptr = L'\0'; } else { if (L'\0' == lptr[1]) { *lptr = L'\0'; } else { lptr++; } } } else { lptr++; } } } } } const wchar_t * dk4strw_skip(const wchar_t *line, size_t skip) { const wchar_t *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) && (L'\0' != *line)) { if (L' ' == *line) { lwt = 0; } else { if (L'\t' == *line) { lwt = 0; } else { if (L'\n' == *line) { lwt = 0; } else { if (L'\r' == *line) { lwt = 0; } else { if (0 == lwt) { if (++words > skip) { back = line; } } lwt = 1; } } } } line++; } } else { back = dk4strw_start(line, NULL); } } return back; } int dk4strw_buffer_sanitize(wchar_t *str, size_t sz) { size_t i; int back = 0; #if DK4_USE_ASSERT assert(NULL != str); assert(0 < sz); #endif if (NULL != str) { if (0 < sz) { if ((SIZE_MAX / sizeof(wchar_t)) >= sz) { back = dk4mem_reset_secure(str, (sz * sizeof(wchar_t)), NULL); } else { for (i = 0; i < sz; i++) { str[i] = L'\0'; } back = 1; for (i = 0; i < sz; i++) { if (L'\0' != str[i]) { back = 0; } } } } else { back = 1; } } return back; } int dk4strw_sanitize(wchar_t *str) { int back = 0; if (NULL != str) { back = dk4strw_buffer_sanitize(str, dk4strw_len(str)); } return back; } int dk4strw_free_sanitized(wchar_t *str) { int back = 0; if (NULL != str) { back = dk4strw_sanitize(str); dk4mem_free(str); } return back; }