%% options copyright owner = Dirk Krause copyright year = 2015-xxxx license = bsd %% header /** @file Additional string functions for wchar_t strings. Although some of the functions in this module duplicate functionality from the C runtime library on Windows, you should use the functions from this module. With DK4DK4_WIN_AVOID_CRT or DK4_WIN_DENY_CRT defined to non-zero these functions call Windows API functions like lstrcmpW() ... instead of CRT functions. */ #ifndef DK4CONF_H_INCLUDED #include "dk4conf.h" #endif #ifndef DK4TYPES_H_INCLUDED #include "dk4types.h" #endif #ifndef DK4ERROR_H_INCLUDED #include "dk4error.h" #endif #ifndef STDLIB_H_INCLUDED #include #define STDLIB_H_INCLUDED 1 #endif #if DK4_HAVE_WCHAR_H #ifndef WCHAR_H_INCLUDED #include #define WCHAR_H_INCLUDED 1 #endif #endif #ifdef __cplusplus extern "C" { #endif /** Copy string, check destination buffer size. CRT on Windows: Optional. @param dst Destination buffer address. @param sz Destination buffer size. @param src Source string. @param erp Error report, may be NULL. @return 1 on success, 0 on error. Error codes: - DK4_E_INVALID_ARGUMENTS
if dst or src is NULL or sz is 0, - DK4_E_BUFFER_TOO_SMALL
if the dst buffer is too small. */ int dk4strw_cpy_s(wchar_t *dst, size_t sz, const wchar_t *src, dk4_er_t *erp); /** Concatenate strings, check destination buffer size. CRT on Windows: Optional. @param dst Destination buffer address. @param sz Destination buffer size. @param src Source string. @param erp Error report, may be NULL. @return 1 on success, 0 on error. Error codes: - DK4_E_INVALID_ARGUMENTS
if dst or src is NULL or sz is 0, - DK4_E_MATH_OVERFLOW
if a mathematical overflow occured in size calculation, - DK4_E_BUFFER_TOO_SMALL
if the concatenated string doest not fit into the buffer. */ int dk4strw_cat_s(wchar_t *dst, size_t sz, const wchar_t *src, dk4_er_t *erp); /** Copy characters within a string from right to left. This copy operation is intended for moving characters within one string from right to left, making the string shorter as is. This function does not check buffer size or report any error. For normal string copy operations, use the dk4strw_cpy_s() function instead. CRT on Windows: Not used. @param dst Destination buffer address. @param src Source string. */ void dk4strw_cpy_to_left(wchar_t *dst, const wchar_t *src); /** Find string length. CRT on Windows: Optional, disabling CRT reduces functionality to strings with length fitting to int. @param src Source string. @return String length. */ size_t dk4strw_len(const wchar_t *src); /** Compare two strings. CRT on Windows: Optional. @param s1 Left string, may be NULL. @param s2 Right string, may be NULL. @return 1 if s1>s2, 0 if s1==s2, -1 if s1s2, 0 if s1==s2, -1 if s1s2, 0 if s1==s2, -1 if s1s2, 0 if s1==s2, -1 if s1 for invalid function arguments, - DK4_E_BUFFER_TOO_SMALL
with dt.mem.nelem set to the number of tokens in string if the dpp array is too short. */ size_t dk4strw_tokenize( wchar_t **dpp, size_t szdpp, wchar_t *src, const wchar_t *delim, dk4_er_t *erp ); /** Normalize a string (remove leading and trailing delimiters, replace delimiter sequences by just one delimiter). CRT on Windows: Optional, disabling CRT degrades performance. @param src Buffer containing the string to normalize. @param delim String containing delimiter characters, may be NULL to use the default delimiter set. */ void dk4strw_normalize(wchar_t *src, const wchar_t *delim); /** Find index of a string in an array of strings. CRT on Windows: Optional. @param arr Array of strings. @param str String to find in array. @param cs Flag: Case-sensitive search (0=no, other=yes). @return Non-negative index value on success, -1 on error. */ int dk4strw_array_index(const wchar_t * const *arr, const wchar_t *str, int cs); /** Find index of a string in an array of strings. CRT on windows: Optional, disabling CRT degrades performance for case-insensitive comparisons. @param arr Array of strings allowing abbreviation. @param spec Special character indicating start of optional text. @param str String to find in array. @param cs Flag: Case-sensitive search (0=no, other=yes). @return Non-negative index value on success, -1 on error. */ int dk4strw_abbr_index( const wchar_t * const *arr, wchar_t spec, const wchar_t *str, int cs ); /** Check whether a text matches a pattern, the text may be abbreviated. CRT on windows: Optional, disabling CRT degrades performance for case-insensitive comparisons. @param str Text to check. @param pattern Pattern for comparison. @param spec Special character marking the abbreviation in the pattern. @param cs Flag: Case sensitive (1) or not (0). @return 1 for a match, 0 otherwise. */ int dk4strw_is_abbr(const wchar_t *str,const wchar_t *pattern,wchar_t spec,int cs); /** Check whether a string represents a boolean value. CRT on windows: Optional, disabling CRT degrades performance. @param str String to check. @return 1 if str represents a boolean value, 0 otherwise. */ int dk4strw_is_bool(const wchar_t *str); /** Check whether a string represents the boolean value TRUE. CRT on windows: Optional, disabling CRT degrades performance. @param str String to check. @return 1 if str represents the boolean value TRUE, 0 otherwise. */ int dk4strw_is_on(const wchar_t *str); #if (defined(_WIN32) && DK4_USE_WINDOWS_LOCAL_ALLOC) \ || (DK4_HAVE_MALLOC && DK4_HAVE_FREE) /** Duplicate string in dynamically allocated memory. CRT on Windows: Optional, disabling CRT reduces functionality to strings with length fitting to int and overall size in bytes - including finalizer - fitting into a DWORD. @param src String to duplicate. @param erp Error report, may be NULL. @return Pointer to string in new memory on succes, NULL on error. Use dk4mem_free() to release the memory after usage. Error codes: - DK4_E_INVALID_ARGUMENTS
if src is a NULL pointer, - DK4_E_MATH_OVERFLOW
on mathematical overflow in size calculation, - DK4_E_MEMORY
if no memory is available. */ wchar_t * dk4strw_dup(const wchar_t *src, dk4_er_t *erp); #endif /* if (defined(_WIN32) ... */ /** Remove trailing white spaces. CRT on Windows: Optional, disabling CRT degrades performance. @param str String to remove white spaces from. @param whsp White spaces set. */ void dk4strw_rtwh(wchar_t *str, const wchar_t *whsp); /** Remove trailing newline from line. @param lptr Line pointer. */ void dk4strw_delnl(wchar_t *lptr); /** Skip the first text words in a line, return pointer to start of next word. @param line Line to process. @param skip Number of words to skip. @return Pointer to next word on success, NULL on error. */ const wchar_t * dk4strw_skip(const wchar_t *line, size_t skip); /** Sanitize string (overwrite using 0). @param str Address of string to sanitize. @return 1 on success, 0 on error. */ int dk4strw_sanitize(wchar_t *str); /** Sanitize string buffer (overwrite using 0 bytes). @param str Address of string buffer. @param sz Size of string buffer (number of wchar_t). @return 1 on success, 0 on error. */ int dk4strw_buffer_sanitize(wchar_t *str, size_t sz); /** Sanitize dynamically allocated memory and release it. @param str Address of string to sanitize and release. @return 1 on success, 0 on error. */ int dk4strw_free_sanitized(wchar_t *str); #ifdef __cplusplus } #endif /** Sanitize string and release it, set pointer to NULL. @param p Pointer to string to release. */ #define dk4strw_release_sanitized(p) \ do { if (NULL != p) { (void)dk4strw_free_sanitized(p); } p = NULL; } while (0) %% module #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 $!trace-include /** Constant strings used in the module. */ static const wchar_t * const dk4strw_modkw[] = { $!string-table prefix=L # # 0 Default delimiters. # \t\r\n $!end }; /** 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[] = { $!string-table prefix=L # # 0...4 false # - 0 n$o of$f f$alse # # 5... true # + 1 y$es on t$rue ok $!end }; /** 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; $? "+ dk4strw_sep \"%ls\" \"%ls\"", TR_LSTR(*stringp), TR_LSTR(delim) 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; } } } $? "- dk4strw_sep \"%ls\"", TR_LSTR(back) 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; $? "+ dk4strw_is_abbr str=\"%ls\" pattern=\"%ls\"", TR_LSTR(str), TR_LSTR(pattern) 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; } } } } } $? "- dk4strw_is_abbr %d", back 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 */ $? "+ dk4strw_abbr_index" if ((NULL != arr) && (NULL != str)) { while ((NULL != *arr) && (-1 == back)) { if (0 != dk4strw_is_abbr(str, *arr, spec, cs)) { back = cand; } arr++; cand++; } } $? "- dk4strw_abbr_index %d", back 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; $? "+ dk4strw_is_on" if (NULL != str) { back = dk4strw_abbr_index(dk4strw_boolkw, L'$', str, 0); if (-1 < back) { if (DK4STRW_FIRST_TRUE <= back) { back = 1; $? ". true" } else { back = 0; $? ". false" } } else { back = 0; $? ". not found" } } $? "- dk4strw_is_on %d", back 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; }