/* 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: dk4str8.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 dk4str8.c The dk4str8 module. */ #line 402 "dk4str8.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 "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 #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 442 "dk4str8.ctr" /** Constant strings used in the module. */ static const char * const dk4str8_modkw[] = { /* 0 */ " \t\r\n", NULL #line 454 "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 485 "dk4str8.ctr" }; /** Number of significant digits. */ static const int dk4str8_dbl_digits = DK4_DBL_DIGITS; void dk4str8_cpy_to_left(char *dst, const char *src) { register char *dptr; register const char *sptr; 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 return (strchr(s, (int)((unsigned char)c))); #endif /* --- Windows */ #else /* +++ non-Windows */ return (strchr(s, (int)((unsigned char)c))); /* --- 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 return (strrchr(s, (int)((unsigned char)c))); #endif #else return (strrchr(s, (int)((unsigned char)c))); #endif } int dk4str8_cpy_s(char *dst, size_t sz, const char *src, dk4_er_t *erp) { int back = 0; 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 #pragma warning (disable:4996) (void)strcpy(dst, src); #pragma warning (default:4996) #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 ((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 #pragma warning (disable:4996) (void)strcat(dst, src); #pragma warning (default:4996) #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 (defined(_WIN32) && DK4_USE_WINDOWS_LOCAL_ALLOC) \ || (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 = 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 /* if (defined(_WIN32) ... */ 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 942 "dk4str8.ctr" 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 953 "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 ((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 ((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 1085 "dk4str8.ctr" 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 1111 "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 1122 "dk4str8.ctr" if ((NULL != arr) && (NULL != str)) { while ((NULL != *arr) && (-1 == back)) { if (0 != dk4str8_is_abbr(str, *arr, spec, cs)) { back = cand; } arr++; cand++; } } #line 1131 "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 1155 "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 1168 "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 (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, strlen(str)); } return back; } int dk4str8_free_sanitized(char *str) { int back = 0; if (NULL != str) { back = dk4str8_sanitize(str); dk4mem_free(str); } return back; }