summaryrefslogtreecommitdiff
path: root/support/dktools/dk4str8.ctr
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /support/dktools/dk4str8.ctr
Initial commit
Diffstat (limited to 'support/dktools/dk4str8.ctr')
-rw-r--r--support/dktools/dk4str8.ctr1305
1 files changed, 1305 insertions, 0 deletions
diff --git a/support/dktools/dk4str8.ctr b/support/dktools/dk4str8.ctr
new file mode 100644
index 0000000000..8b5bcd1fa5
--- /dev/null
+++ b/support/dktools/dk4str8.ctr
@@ -0,0 +1,1305 @@
+%% options
+
+copyright owner = Dirk Krause
+copyright year = 2015-xxxx
+license = bsd
+
+
+
+%% header
+
+/** @file
+ Additional string functions for
+ 8 bit characters.
+
+ Although some of the functions in this module duplicate
+ functionality from string.h functions, 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
+ lstrcmpA() ... 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 <stdlib.h>
+#define STDLIB_H_INCLUDED 1
+#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<br>
+ if dst or src is NULL or sz is 0,
+ - DK4_E_BUFFER_TOO_SMALL<br>
+ if the dst buffer is too small.
+*/
+int
+dk4str8_cpy_s(char *dst, size_t sz, const char *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<br>
+ if dst or src is NULL or sz is 0,
+ - DK4_E_MATH_OVERFLOW<br>
+ if a mathematical overflow occured in size calculation,
+ - DK4_E_BUFFER_TOO_SMALL<br>
+ if the concatenated string doest not fit into the buffer.
+*/
+int
+dk4str8_cat_s(char *dst, size_t sz, const char *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 dk4str8_cpy_s()
+ function instead.
+
+ CRT on Windows: Not used.
+ @param dst Destination buffer address.
+ @param src Source string.
+*/
+void
+dk4str8_cpy_to_left(char *dst, const char *src);
+
+/** Find string length.
+
+ CRT on Windows: Optional.
+ @param src Source string.
+ @return String length.
+*/
+size_t
+dk4str8_len(const char *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 s1<s2.
+*/
+int
+dk4str8_cmp(const char *s1, const char *s2);
+
+/** Compare two strings.
+
+ CRT on Windows: Optional, disabling CRT probably degrades performance.
+ @param s1 Left string, may be NULL.
+ @param s2 Right string, may be NULL.
+ @param n Maximum number of characters to compare.
+ @return 1 if s1>s2, 0 if s1==s2, -1 if s1<s2.
+*/
+int
+dk4str8_ncmp(const char *s1, const char *s2, size_t n);
+
+/** Compare two strings, case-insensitive comparison.
+
+ 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 s1<s2.
+*/
+int
+dk4str8_casecmp(const char *s1, const char *s2);
+
+/** Compare two file path names.
+
+ 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 s1<s2.
+*/
+int
+dk4str8_pathcmp(const char *s1, const char *s2);
+
+/** Find first occurance of character c in string s.
+
+ CRT on Windows: Optional, disabling CRT degrades performance.
+ @param s String to search for c.
+ @param c Character to find.
+ @return Pointer to first occurance if found, NULL otherwise.
+*/
+char *
+dk4str8_chr(const char *s, char c);
+
+/** Find last occurance of character c in string s.
+
+ CRT on Windows: Optional, disabling CRT degrades performance.
+ @param s String to search for c.
+ @param c Character to find.
+ @return Pointer to last occurance if found, NULL otherwise.
+*/
+char *
+dk4str8_rchr(const char *s, char c);
+
+/** Retrieve first token from *stringp.
+
+ CRT on Windows: Optional, disabling CRT degrades performance.
+ @param stringp Adress of string pointer.
+ @param delim String containing the delimiter set,
+ my be NULL to use the default delimiter
+ set (space, tabulator, carriage return and newline).
+ @return Pointer to first token on success, NULL if no (further)
+ token found.
+*/
+char *
+dk4str8_sep(char **stringp, const char *delim);
+
+/** Find first token in string.
+
+ CRT on Windows: Optional, disabling CRT degrades performance.
+ @param src String to search for tokens.
+ @param delim String containing the delimiter characters,
+ may be NULL to use the default delimiter set.
+ @return Pointer to first token if found, NULL otherwise.
+*/
+char *
+dk4str8_start(const char *src, const char *delim);
+
+/** Cut string after first token, find start of second token in string.
+
+ CRT on Windows: Optional, disabling CRT degrades performance.
+ @param src String to search for tokens,
+ normally the result of dk4str8_start() or a
+ previous dk4str8_next() call.
+ @param delim String containing the delimiter characters,
+ may be NULL to use the default delimiter set.
+ @return Pointer to second token if found, NULL otherwise.
+*/
+char *
+dk4str8_next(char *src, const char *delim);
+
+/** Split a string into tokens.
+
+ CRT on Windows: Optional, disabling CRT degrades performance.
+ @param dpp Pointer to string pointer array.
+ @param szdpp Size of destination string pointer array.
+ @param src Source string to process.
+ @param delim String containing delimiter characters,
+ may be NULL to use the default delimiter set.
+ @param erp Error report, may be NULL.
+ @return Number of tokens found on success, 0 if no token
+ found or on error.
+
+ Error codes:
+ - DK4_E_INVALID_ARGUMENTS<br>
+ for invalid function arguments,
+ - DK4_E_BUFFER_TOO_SMALL<br>
+ with dt.mem.nelem set to the number of tokens in string if the dpp
+ array is too short.
+*/
+size_t
+dk4str8_tokenize(
+ char **dpp, size_t szdpp, char *src, const char *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
+dk4str8_normalize(char *src, const char *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
+dk4str8_array_index(const char * const *arr, const char *str, int cs);
+
+/** Find index of a string in an array of strings.
+
+ CRT on Windows: Optional, disabling CRT degrades performances
+ and reduces to upper-case conversion to characters 'a' to 'z'.
+ @param arr Array of string allowing abbreviations.
+ @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
+dk4str8_abbr_index(const char * const *arr, char spec, const char *str, int cs);
+
+/** Check whether a text matches a pattern, the text may be abbreviated.
+
+ CRT on Windows: Optional, disabling CRT degrades performances
+ and reduces to upper-case conversion to characters 'a' to 'z'
+ in 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
+dk4str8_is_abbr(const char *str, const char *pattern, char spec, int cs);
+
+/** Check whether a string represents a boolean value.
+
+ CRT on Windows: Optional, disabling CRT degrades performances.
+ @param str String to check.
+ @return 1 if str represents a boolean value, 0 otherwise.
+*/
+int
+dk4str8_is_bool(const char *str);
+
+/** Check whether a string represents the boolean value TRUE.
+
+ CRT on Windows: Optional, disabling CRT degrades performances.
+ @param str String to check.
+ @return 1 if str represents the boolean value TRUE, 0 otherwise.
+*/
+int
+dk4str8_is_on(const char *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<br>
+ if src is a NULL pointer,
+ - DK4_E_MATH_OVERFLOW<br>
+ on mathematical overflow in size calculation,
+ - DK4_E_MEMORY<br>
+ if no memory is available.
+*/
+char *
+dk4str8_dup(const char *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
+dk4str8_rtwh(char *str, const char *whsp);
+
+/** Convert character to uppercase.
+
+ CRT on Windows: Optional, disabling CRT degrades performances
+ and reduces functionality to characters 'a' to 'z'.
+ @param c Character to convert.
+ @return Conversion result.
+*/
+char
+dk4str8_toupper(char c);
+
+/** Convert character to lowercase.
+
+ CRT on Windows: Optional, disabling CRT degrades performances
+ and reduces functionality to characters 'A' to 'Z'.
+ @param c Character to convert.
+ @return Conversion result.
+*/
+char
+dk4str8_tolower(char c);
+
+/** Remove trailing newline from line.
+ @param lptr Line pointer.
+*/
+void
+dk4str8_delnl(char *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 char *
+dk4str8_skip(const char *line, size_t skip);
+
+/** Sanitize string (overwrite using 0 bytes).
+ @param str Address of string to sanitize.
+ @return 1 on success, 0 on error.
+*/
+int
+dk4str8_sanitize(char *str);
+
+/** Sanitize string buffer (overwrite using 0 bytes).
+ @param str Address of string buffer.
+ @param sz Size of string buffer (number of elements).
+ @return 1 on success, 0 on error.
+*/
+int
+dk4str8_buffer_sanitize(char *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
+dk4str8_free_sanitized(char *str);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+/** Sanitize string and release it, set pointer to NULL.
+ @param p Pointer to string to release.
+*/
+#define dk4str8_release_sanitized(p) \
+do { if (NULL != p) { (void)dk4str8_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 <windows.h>
+#define WINDOWS_H_INCLUDED 1
+#endif
+#endif
+
+#include "dk4str8.h"
+
+#if DK4_HAVE_STRING_H
+#ifndef STRING_H_INCLUDED
+#include <string.h>
+#define STRING_H_INCLUDED 1
+#endif
+#endif
+
+#if DK4_HAVE_CTYPE_H
+#ifndef CTYPE_H_INCLUDED
+#include <ctype.h>
+#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
+
+
+$!trace-include
+
+
+
+/** Constant strings used in the module.
+*/
+static const char * const dk4str8_modkw[] = {
+$!string-table
+#
+# 0 Default delimiters.
+#
+ \t\r\n
+$!end
+};
+
+
+
+/** 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[] = {
+$!string-table
+#
+# 0...4 false
+#
+-
+0
+n$o
+of$f
+f$alse
+#
+# 5... true
+#
++
+1
+y$es
+on
+t$rue
+ok
+$!end
+};
+
+
+
+/** 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;
+ $? "+ dk4str8_sep \"%!8s\" \"%!8s\"", TR_8STR(*stringp), TR_8STR(delim)
+ 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;
+ }
+ }
+ } $? "- dk4str8_sep \"%!8s\"", TR_8STR(back)
+ 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;
+ $? "+ dk4str8_is_abbr \"%!8s\" \"%!8s\" \"%!8c\"", pattern, str, spec
+ 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; }
+ }
+ }
+ }
+ } $? "- dk4str8_is_abbr %d", back
+ return back;
+}
+
+
+
+int
+dk4str8_abbr_index(const char * const *arr, char spec, const char *str, int cs)
+{
+ int back = -1;
+ int cand = 0;
+ $? "+ dk4str8_abbr_index"
+ if ((NULL != arr) && (NULL != str)) {
+ while ((NULL != *arr) && (-1 == back)) {
+ if (0 != dk4str8_is_abbr(str, *arr, spec, cs)) {
+ back = cand;
+ }
+ arr++; cand++;
+ }
+ }
+ $? "- dk4str8_abbr_index %d", back
+ 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;
+ $? "+ dk4str8_is_on"
+ 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;
+ }
+ }
+ $? "- dk4str8_is_on %d", back
+ 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;
+}
+