/* WARNING: This file was generated by dkct. 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 */ /* Copyright (C) 2015-2017, Dirk Krause Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above opyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the author nor the names of contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @file dk4strw.c The dk4strw module. */ #line 413 "dk4strw.ctr" #include "dk4conf.h" #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 #ifndef DK4MEMRS_H_INCLUDED #include "dk4memrs.h" #endif #line 442 "dk4strw.ctr" /** Constant strings used in the module. */ static const wchar_t * const dk4strw_modkw[] = { /* 0 */ L" \t\r\n", NULL #line 454 "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 485 "dk4strw.ctr" }; /** Number of significant digits when printing a double. */ static const int dk4strw_dbl_digits = DK4_DBL_DIGITS; void dk4strw_cpy_to_left(wchar_t *dst, const wchar_t *src) { register wchar_t *dptr; register const wchar_t *sptr; 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 return (wcschr(s, c)); #endif /* --- Windows */ #else /* +++ non-Windows */ #if DK4_HAVE_WCSCHR return (wcschr(s, c)); #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 return (wcsrchr(s, c)); #endif /* --- Windows */ #else /* +++ non-Windows */ #if DK4_HAVE_WCSRCHR return (wcsrchr(s, c)); #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 ((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 #pragma warning (disable:4996) (void)wcscpy(dst, src); #pragma warning (default:4996) #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 ((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 #pragma warning (disable:4996) (void)wcscat(dst, src); #pragma warning (default:4996) #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 (defined(_WIN32) && DK4_USE_WINDOWS_LOCAL_ALLOC) \ || (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 (defined(_WIN32) ... */ #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 1101 "dk4strw.ctr" 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 1112 "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 ((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; 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 1235 "dk4strw.ctr" 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 1262 "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 1278 "dk4strw.ctr" if ((NULL != arr) && (NULL != str)) { while ((NULL != *arr) && (-1 == back)) { if (0 != dk4strw_is_abbr(str, *arr, spec, cs)) { back = cand; } arr++; cand++; } } #line 1287 "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 1311 "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 1316 "dk4strw.ctr" } else { back = 0; #line 1318 "dk4strw.ctr" } } else { back = 0; #line 1321 "dk4strw.ctr" } } #line 1324 "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 (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; }