reorganizing hio-utl.h with hio-utl.h.m4

This commit is contained in:
hyung-hwan 2021-08-14 05:23:57 +00:00
parent 37a3bb5ea8
commit 3c7f72b795
7 changed files with 2236 additions and 816 deletions

View File

@ -8,7 +8,7 @@ CPPFLAGS_ALL_COMMON = \
CFLAGS_ALL_COMMON =
LDFLAGS_ALL_COMMON = -L$(abs_builddir) -L$(libdir)
EXTRA_DIST = utl-str.c.m4
EXTRA_DIST = hio-utl.h.m4 utl-str.c.m4
##################################################
# MAIN LIBRARY
@ -132,5 +132,9 @@ install-data-hook:
uninstall-hook:
@rm -f "$(DESTDIR)$(includedir)/hio-cfg.h"
utl-str.c: utl-str.c.m4
m4 $(abs_srcdir)/utl-str.c.m4 > $(abs_srcdir)/utl-str.c
$(srcdir)/hio-utl.h: utl-str.m4 hio-utl.h.m4
m4 -I$(srcdir) $(srcdir)/hio-utl.h.m4 > $(srcdir)/hio-utl.h
utl-str.c: utl-str.m4 utl-str.c.m4
m4 -I$(srcdir) $(srcdir)/utl-str.c.m4 > $(srcdir)/utl-str.c

View File

@ -426,7 +426,7 @@ CPPFLAGS_ALL_COMMON = \
CFLAGS_ALL_COMMON =
LDFLAGS_ALL_COMMON = -L$(abs_builddir) -L$(libdir)
EXTRA_DIST = utl-str.c.m4
EXTRA_DIST = hio-utl.h.m4 utl-str.c.m4
##################################################
# MAIN LIBRARY
@ -1248,8 +1248,11 @@ install-data-hook:
uninstall-hook:
@rm -f "$(DESTDIR)$(includedir)/hio-cfg.h"
utl-str.c: utl-str.c.m4
m4 $(abs_srcdir)/utl-str.c.m4 > $(abs_srcdir)/utl-str.c
$(srcdir)/hio-utl.h: utl-str.m4 hio-utl.h.m4
m4 -I$(srcdir) $(srcdir)/hio-utl.h.m4 > $(srcdir)/hio-utl.h
utl-str.c: utl-str.m4 utl-str.c.m4
m4 -I$(srcdir) $(srcdir)/utl-str.c.m4 > $(srcdir)/utl-str.c
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.

View File

@ -22,12 +22,52 @@
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Do NOT edit hio-utl.h. Edit hio-utl.h.m4 instead.
*
* Generate hio-utl.h.m4 with m4
* $ m4 hio-utl.h.m4 > hio-utl.h
*/
#ifndef _HIO_UTL_H_
#define _HIO_UTL_H_
#include <hio-cmn.h>
#include <stdarg.h>
/* =========================================================================
* ENDIAN CHANGE OF A CONSTANT
* ========================================================================= */
@ -608,41 +648,53 @@ HIO_EXPORT hio_oow_t hio_byte_to_bcstr (
);
/* ------------------------------------------------------------------------- */
#define HIO_OOCHARS_TO_INTMAX_MAKE_OPTION(e,ltrim,rtrim,base) (((!!(e)) << 0) | ((!!(ltrim)) << 2) | ((!!(rtrim)) << 3) | ((base) << 8))
#define HIO_OOCHARS_TO_INTMAX_GET_OPTION_E(option) ((option) & 1)
#define HIO_OOCHARS_TO_INTMAX_GET_OPTION_LTRIM(option) ((option) & 4)
#define HIO_OOCHARS_TO_INTMAX_GET_OPTION_RTRIM(option) ((option) & 8)
#define HIO_OOCHARS_TO_INTMAX_GET_OPTION_BASE(option) ((option) >> 8)
#define HIO_CHARS_TO_INTMAX_MAKE_OPTION(e,ltrim,rtrim,base) (((!!(e)) << 0) | ((!!(ltrim)) << 2) | ((!!(rtrim)) << 3) | ((base) << 8))
#define HIO_CHARS_TO_INTMAX_GET_OPTION_E(option) ((option) & 1)
#define HIO_CHARS_TO_INTMAX_GET_OPTION_LTRIM(option) ((option) & 4)
#define HIO_CHARS_TO_INTMAX_GET_OPTION_RTRIM(option) ((option) & 8)
#define HIO_CHARS_TO_INTMAX_GET_OPTION_BASE(option) ((option) >> 8)
#define HIO_OOCHARS_TO_UINTMAX_MAKE_OPTION(e,ltrim,rtrim,base) (((!!(e)) << 0) | ((!!(ltrim)) << 2) | ((!!(rtrim)) << 3) | ((base) << 8))
#define HIO_OOCHARS_TO_UINTMAX_GET_OPTION_E(option) ((option) & 1)
#define HIO_OOCHARS_TO_UINTMAX_GET_OPTION_LTRIM(option) ((option) & 4)
#define HIO_OOCHARS_TO_UINTMAX_GET_OPTION_RTRIM(option) ((option) & 8)
#define HIO_OOCHARS_TO_UINTMAX_GET_OPTION_BASE(option) ((option) >> 8)
#define HIO_CHARS_TO_UINTMAX_MAKE_OPTION(e,ltrim,rtrim,base) (((!!(e)) << 0) | ((!!(ltrim)) << 2) | ((!!(rtrim)) << 3) | ((base) << 8))
#define HIO_CHARS_TO_UINTMAX_GET_OPTION_E(option) ((option) & 1)
#define HIO_CHARS_TO_UINTMAX_GET_OPTION_LTRIM(option) ((option) & 4)
#define HIO_CHARS_TO_UINTMAX_GET_OPTION_RTRIM(option) ((option) & 8)
#define HIO_CHARS_TO_UINTMAX_GET_OPTION_BASE(option) ((option) >> 8)
#define HIO_UCHARS_TO_INTMAX_MAKE_OPTION(e,ltrim,rtrim,base) HIO_OOCHARS_TO_INTMAX_MAKE_OPTION(e,ltrim,rtrim,base)
#define HIO_UCHARS_TO_INTMAX_GET_OPTION_E(option) HIO_OOCHARS_TO_INTMAX_GET_OPTION_E(option)
#define HIO_UCHARS_TO_INTMAX_GET_OPTION_LTRIM(option) HIO_OOCHARS_TO_INTMAX_GET_OPTION_LTRIM(option)
#define HIO_UCHARS_TO_INTMAX_GET_OPTION_RTRIM(option) HIO_OOCHARS_TO_INTMAX_GET_OPTION_RTRIM(option)
#define HIO_UCHARS_TO_INTMAX_GET_OPTION_BASE(option) HIO_OOCHARS_TO_INTMAX_GET_OPTION_BASE(option)
#define HIO_OOCHARS_TO_INTMAX_MAKE_OPTION(e,ltrim,rtrim,base) HIO_CHARS_TO_INTMAX_MAKE_OPTION(e,ltrim,rtrim,base)
#define HIO_OOCHARS_TO_INTMAX_GET_OPTION_E(option) HIO_CHARS_TO_INTMAX_GET_OPTION_E(option)
#define HIO_OOCHARS_TO_INTMAX_GET_OPTION_LTRIM(option) HIO_CHARS_TO_INTMAX_GET_OPTION_LTRIM(option)
#define HIO_OOCHARS_TO_INTMAX_GET_OPTION_RTRIM(option) HIO_CHARS_TO_INTMAX_GET_OPTION_RTRIM(option)
#define HIO_OOCHARS_TO_INTMAX_GET_OPTION_BASE(option) HIO_CHARS_TO_INTMAX_GET_OPTION_BASE(option)
#define HIO_BCHARS_TO_INTMAX_MAKE_OPTION(e,ltrim,rtrim,base) HIO_OOCHARS_TO_INTMAX_MAKE_OPTION(e,ltrim,rtrim,base)
#define HIO_BCHARS_TO_INTMAX_GET_OPTION_E(option) HIO_OOCHARS_TO_INTMAX_GET_OPTION_E(option)
#define HIO_BCHARS_TO_INTMAX_GET_OPTION_LTRIM(option) HIO_OOCHARS_TO_INTMAX_GET_OPTION_LTRIM(option)
#define HIO_BCHARS_TO_INTMAX_GET_OPTION_RTRIM(option) HIO_OOCHARS_TO_INTMAX_GET_OPTION_RTRIM(option)
#define HIO_BCHARS_TO_INTMAX_GET_OPTION_BASE(option) HIO_OOCHARS_TO_INTMAX_GET_OPTION_BASE(option)
#define HIO_OOCHARS_TO_UINTMAX_MAKE_OPTION(e,ltrim,rtrim,base) HIO_CHARS_TO_UINTMAX_MAKE_OPTION(e,ltrim,rtrim,base)
#define HIO_OOCHARS_TO_UINTMAX_GET_OPTION_E(option) HIO_CHARS_TO_UINTMAX_GET_OPTION_E(option)
#define HIO_OOCHARS_TO_UINTMAX_GET_OPTION_LTRIM(option) HIO_CHARS_TO_UINTMAX_GET_OPTION_LTRIM(option)
#define HIO_OOCHARS_TO_UINTMAX_GET_OPTION_RTRIM(option) HIO_CHARS_TO_UINTMAX_GET_OPTION_RTRIM(option)
#define HIO_OOCHARS_TO_UINTMAX_GET_OPTION_BASE(option) HIO_CHARS_TO_UINTMAX_GET_OPTION_BASE(option)
#define HIO_UCHARS_TO_UINTMAX_MAKE_OPTION(e,ltrim,rtrim,base) HIO_OOCHARS_TO_UINTMAX_MAKE_OPTION(e,ltrim,rtrim,base)
#define HIO_UCHARS_TO_UINTMAX_GET_OPTION_E(option) HIO_OOCHARS_TO_UINTMAX_GET_OPTION_E(option)
#define HIO_UCHARS_TO_UINTMAX_GET_OPTION_LTRIM(option) HIO_OOCHARS_TO_UINTMAX_GET_OPTION_LTRIM(option)
#define HIO_UCHARS_TO_UINTMAX_GET_OPTION_RTRIM(option) HIO_OOCHARS_TO_UINTMAX_GET_OPTION_RTRIM(option)
#define HIO_UCHARS_TO_UINTMAX_GET_OPTION_BASE(option) HIO_OOCHARS_TO_UINTMAX_GET_OPTION_BASE(option)
#define HIO_UCHARS_TO_INTMAX_MAKE_OPTION(e,ltrim,rtrim,base) HIO_CHARS_TO_INTMAX_MAKE_OPTION(e,ltrim,rtrim,base)
#define HIO_UCHARS_TO_INTMAX_GET_OPTION_E(option) HIO_CHARS_TO_INTMAX_GET_OPTION_E(option)
#define HIO_UCHARS_TO_INTMAX_GET_OPTION_LTRIM(option) HIO_CHARS_TO_INTMAX_GET_OPTION_LTRIM(option)
#define HIO_UCHARS_TO_INTMAX_GET_OPTION_RTRIM(option) HIO_CHARS_TO_INTMAX_GET_OPTION_RTRIM(option)
#define HIO_UCHARS_TO_INTMAX_GET_OPTION_BASE(option) HIO_CHARS_TO_INTMAX_GET_OPTION_BASE(option)
#define HIO_BCHARS_TO_UINTMAX_MAKE_OPTION(e,ltrim,rtrim,base) HIO_OOCHARS_TO_UINTMAX_MAKE_OPTION(e,ltrim,rtrim,base)
#define HIO_BCHARS_TO_UINTMAX_GET_OPTION_E(option) HIO_OOCHARS_TO_UINTMAX_GET_OPTION_E(option)
#define HIO_BCHARS_TO_UINTMAX_GET_OPTION_LTRIM(option) HIO_OOCHARS_TO_UINTMAX_GET_OPTION_LTRIM(option)
#define HIO_BCHARS_TO_UINTMAX_GET_OPTION_RTRIM(option) HIO_OOCHARS_TO_UINTMAX_GET_OPTION_RTRIM(option)
#define HIO_BCHARS_TO_UINTMAX_GET_OPTION_BASE(option) HIO_OOCHARS_TO_UINTMAX_GET_OPTION_BASE(option)
#define HIO_BCHARS_TO_INTMAX_MAKE_OPTION(e,ltrim,rtrim,base) HIO_CHARS_TO_INTMAX_MAKE_OPTION(e,ltrim,rtrim,base)
#define HIO_BCHARS_TO_INTMAX_GET_OPTION_E(option) HIO_CHARS_TO_INTMAX_GET_OPTION_E(option)
#define HIO_BCHARS_TO_INTMAX_GET_OPTION_LTRIM(option) HIO_CHARS_TO_INTMAX_GET_OPTION_LTRIM(option)
#define HIO_BCHARS_TO_INTMAX_GET_OPTION_RTRIM(option) HIO_CHARS_TO_INTMAX_GET_OPTION_RTRIM(option)
#define HIO_BCHARS_TO_INTMAX_GET_OPTION_BASE(option) HIO_CHARS_TO_INTMAX_GET_OPTION_BASE(option)
#define HIO_UCHARS_TO_UINTMAX_MAKE_OPTION(e,ltrim,rtrim,base) HIO_CHARS_TO_UINTMAX_MAKE_OPTION(e,ltrim,rtrim,base)
#define HIO_UCHARS_TO_UINTMAX_GET_OPTION_E(option) HIO_CHARS_TO_UINTMAX_GET_OPTION_E(option)
#define HIO_UCHARS_TO_UINTMAX_GET_OPTION_LTRIM(option) HIO_CHARS_TO_UINTMAX_GET_OPTION_LTRIM(option)
#define HIO_UCHARS_TO_UINTMAX_GET_OPTION_RTRIM(option) HIO_CHARS_TO_UINTMAX_GET_OPTION_RTRIM(option)
#define HIO_UCHARS_TO_UINTMAX_GET_OPTION_BASE(option) HIO_CHARS_TO_UINTMAX_GET_OPTION_BASE(option)
#define HIO_BCHARS_TO_UINTMAX_MAKE_OPTION(e,ltrim,rtrim,base) HIO_CHARS_TO_UINTMAX_MAKE_OPTION(e,ltrim,rtrim,base)
#define HIO_BCHARS_TO_UINTMAX_GET_OPTION_E(option) HIO_CHARS_TO_UINTMAX_GET_OPTION_E(option)
#define HIO_BCHARS_TO_UINTMAX_GET_OPTION_LTRIM(option) HIO_CHARS_TO_UINTMAX_GET_OPTION_LTRIM(option)
#define HIO_BCHARS_TO_UINTMAX_GET_OPTION_RTRIM(option) HIO_CHARS_TO_UINTMAX_GET_OPTION_RTRIM(option)
#define HIO_BCHARS_TO_UINTMAX_GET_OPTION_BASE(option) HIO_CHARS_TO_UINTMAX_GET_OPTION_BASE(option)
HIO_EXPORT hio_intmax_t hio_uchars_to_intmax (
const hio_uch_t* str,
@ -1079,4 +1131,235 @@ HIO_EXPORT void hio_sip_hash_24 (
}
#endif
/* Some C++ utilities below */
#if defined(__cplusplus)
template<CHAR_TYPE, INT_TYPE>
INT_TYPE hio_chars_to_uint (const CHAR_TYPE* str, hio_oow_t len, int option, const CHAR_TYPE** endptr, int* is_sober)
{
INT_TYPE n = 0;
const CHAR_TYPE* p, * pp;
const CHAR_TYPE* end;
hio_oow_t rem;
int digit, negative = 0;
int base = HIO_CHARS_TO_INTMAX_GET_OPTION_BASE(option);
p = str;
end = str + len;
if (HIO_CHARS_TO_INTMAX_GET_OPTION_LTRIM(option))
{
/* strip off leading spaces */
while (p < end && hio_is_bch_space(*p)) p++;
}
/* check for a sign */
while (p < end)
{
if (*p == '-')
{
negative = ~negative;
p++;
}
else if (*p == '+') p++;
else break;
}
/* check for a binary/octal/hexadecimal notation */
rem = end - p;
if (base == 0)
{
if (rem >= 1 && *p == '0')
{
p++;
if (rem == 1) base = 8;
else if (*p == 'x' || *p == 'X')
{
p++; base = 16;
}
else if (*p == 'b' || *p == 'B')
{
p++; base = 2;
}
else base = 8;
}
else base = 10;
}
else if (rem >= 2 && base == 16)
{
if (*p == '0' &&
(*(p + 1) == 'x' || *(p + 1) == 'X')) p += 2;
}
else if (rem >= 2 && base == 2)
{
if (*p == '0' &&
(*(p + 1) == 'b' || *(p + 1) == 'B')) p += 2;
}
/* process the digits */
pp = p;
while (p < end)
{
digit = HIO_ZDIGIT_TO_NUM(*p, base);
if (digit >= base) break;
n = n * base + digit;
p++;
}
if (HIO_CHARS_TO_INTMAX_GET_OPTION_E(option))
{
if (*p == 'E' || *p == 'e')
{
INT_TYPE e = 0, i;
int e_neg = 0;
p++;
if (*p == '+')
{
p++;
}
else if (*p == '-')
{
p++; e_neg = 1;
}
while (p < end)
{
digit = HIO_ZDIGIT_TO_NUM(*p, base);
if (digit >= base) break;
e = e * base + digit;
p++;
}
if (e_neg)
for (i = 0; i < e; i++) n /= 10;
else
for (i = 0; i < e; i++) n *= 10;
}
}
/* base 8: at least a zero digit has been seen.
* other case: p > pp to be able to have at least 1 meaningful digit. */
if (is_sober) *is_sober = (base == 8 || p > pp);
if (HIO_CHARS_TO_INTMAX_GET_OPTION_RTRIM(option))
{
/* consume trailing spaces */
while (p < end && hio_is_bch_space(*p)) p++;
}
if (endptr) *endptr = p;
return (negative)? -n: n;
}
template<CHAR_TYPE, UINT_TYPE>
UINT_TYPE hio_chars_to_uint (const CHAR_TYPE* str, hio_oow_t len, int option, const CHAR_TYPE** endptr, int* is_sober)
{
UINT_TYPE n = 0;
const CHAR_TYPE* p, * pp;
const CHAR_TYPE* end;
hio_oow_t rem;
int digit;
int base = HIO_CHARS_TO_UINTMAX_GET_OPTION_BASE(option);
p = str;
end = str + len;
if (HIO_CHARS_TO_UINTMAX_GET_OPTION_LTRIM(option))
{
/* strip off leading spaces */
while (p < end && hio_is_bch_space(*p)) p++;
}
/* check for a sign */
while (p < end)
{
if (*p == '+') p++;
else break;
}
/* check for a binary/octal/hexadecimal notation */
rem = end - p;
if (base == 0)
{
if (rem >= 1 && *p == '0')
{
p++;
if (rem == 1) base = 8;
else if (*p == 'x' || *p == 'X')
{
p++; base = 16;
}
else if (*p == 'b' || *p == 'B')
{
p++; base = 2;
}
else base = 8;
}
else base = 10;
}
else if (rem >= 2 && base == 16)
{
if (*p == '0' &&
(*(p + 1) == 'x' || *(p + 1) == 'X')) p += 2;
}
else if (rem >= 2 && base == 2)
{
if (*p == '0' &&
(*(p + 1) == 'b' || *(p + 1) == 'B')) p += 2;
}
/* process the digits */
pp = p;
while (p < end)
{
digit = HIO_ZDIGIT_TO_NUM(*p, base);
if (digit >= base) break;
n = n * base + digit;
p++;
}
if (HIO_CHARS_TO_UINTMAX_GET_OPTION_E(option))
{
if (*p == 'E' || *p == 'e')
{
UINT_TYPE e = 0, i;
int e_neg = 0;
p++;
if (*p == '+')
{
p++;
}
else if (*p == '-')
{
p++; e_neg = 1;
}
while (p < end)
{
digit = HIO_ZDIGIT_TO_NUM(*p, base);
if (digit >= base) break;
e = e * base + digit;
p++;
}
if (e_neg)
for (i = 0; i < e; i++) n /= 10;
else
for (i = 0; i < e; i++) n *= 10;
}
}
/* base 8: at least a zero digit has been seen.
* other case: p > pp to be able to have at least 1 meaningful digit. */
if (is_sober) *is_sober = (base == 8 || p > pp);
if (HIO_CHARS_TO_UINTMAX_GET_OPTION_RTRIM(option))
{
/* consume trailing spaces */
while (p < end && hio_is_bch_space(*p)) p++;
}
if (endptr) *endptr = p;
return n;
}
#endif
#endif

1111
hio/lib/hio-utl.h.m4 Normal file

File diff suppressed because it is too large Load Diff

View File

@ -23,7 +23,7 @@
*/
/*
* Do NOT edit utl-str.c.
* Do NOT edit utl-str.c. Edit utl-str.c.m4 instead.
*
* Generate utl-str.c with m4
* $ m4 utl-str.c.m4 > utl-str.c
@ -36,6 +36,36 @@
hio_oow_t hio_count_ucstr (const hio_uch_t* str)
{
const hio_uch_t* ptr = str;
@ -53,7 +83,6 @@ hio_oow_t hio_count_bcstr (const hio_bch_t* str)
int hio_equal_uchars (const hio_uch_t* str1, const hio_uch_t* str2, hio_oow_t len)
{
hio_oow_t i;
@ -87,7 +116,6 @@ int hio_equal_bchars (const hio_bch_t* str1, const hio_bch_t* str2, hio_oow_t le
int hio_comp_uchars (const hio_uch_t* str1, hio_oow_t len1, const hio_uch_t* str2, hio_oow_t len2, int ignorecase)
{
hio_uchu_t c1, c2;
@ -171,8 +199,6 @@ int hio_comp_bchars (const hio_bch_t* str1, hio_oow_t len1, const hio_bch_t* str
int hio_comp_ucstr (const hio_uch_t* str1, const hio_uch_t* str2, int ignorecase)
{
if (ignorecase)
@ -224,7 +250,6 @@ int hio_comp_bcstr (const hio_bch_t* str1, const hio_bch_t* str2, int ignorecase
int hio_comp_ucstr_limited (const hio_uch_t* str1, const hio_uch_t* str2, hio_oow_t maxlen, int ignorecase)
{
if (maxlen == 0) return 0;
@ -279,8 +304,6 @@ int hio_comp_bcstr_limited (const hio_bch_t* str1, const hio_bch_t* str2, hio_oo
}
hio_oow_t hio_concat_uchars_to_ucstr (hio_uch_t* buf, hio_oow_t bsz, const hio_uch_t* str, hio_oow_t len)
{
hio_uch_t* p, * p2;
@ -352,6 +375,7 @@ int hio_comp_bcstr_limited (const hio_bch_t* str1, const hio_bch_t* str2, hio_oo
return p - buf;
}
hio_oow_t hio_concat_bcstr (hio_bch_t* buf, hio_oow_t bsz, const hio_bch_t* str)
{
hio_bch_t* p, * p2;
@ -375,8 +399,6 @@ int hio_comp_bcstr_limited (const hio_bch_t* str1, const hio_bch_t* str2, hio_oo
void hio_fill_uchars (hio_uch_t* dst, hio_uch_t ch, hio_oow_t len)
{
hio_oow_t i;
@ -392,7 +414,6 @@ void hio_fill_bchars (hio_bch_t* dst, hio_bch_t ch, hio_oow_t len)
hio_uch_t* hio_find_uchar (const hio_uch_t* ptr, hio_oow_t len, hio_uch_t c)
{
const hio_uch_t* end;
@ -424,7 +445,6 @@ hio_bch_t* hio_find_bchar (const hio_bch_t* ptr, hio_oow_t len, hio_bch_t c)
hio_uch_t* hio_rfind_uchar (const hio_uch_t* ptr, hio_oow_t len, hio_uch_t c)
{
const hio_uch_t* cur;
@ -456,8 +476,6 @@ hio_bch_t* hio_rfind_bchar (const hio_bch_t* ptr, hio_oow_t len, hio_bch_t c)
hio_uch_t* hio_find_uchar_in_ucstr (const hio_uch_t* ptr, hio_uch_t c)
{
while (*ptr != '\0')
@ -483,8 +501,6 @@ hio_bch_t* hio_find_bchar_in_bcstr (const hio_bch_t* ptr, hio_bch_t c)
hio_uch_t* hio_trim_uchars (const hio_uch_t* str, hio_oow_t* len, int flags)
{
const hio_uch_t* p = str, * end = str + *len;
@ -572,8 +588,6 @@ hio_bch_t* hio_trim_bchars (const hio_bch_t* str, hio_oow_t* len, int flags)
int hio_split_ucstr (hio_uch_t* s, const hio_uch_t* delim, hio_uch_t lquote, hio_uch_t rquote, hio_uch_t escape)
{
hio_uch_t* p = s, *d;
@ -1053,7 +1067,6 @@ exit_point:
hio_intmax_t hio_uchars_to_intmax (const hio_uch_t* str, hio_oow_t len, int option, const hio_uch_t** endptr, int* is_sober)
{
hio_intmax_t n = 0;
@ -1287,9 +1300,6 @@ hio_intmax_t hio_bchars_to_intmax (const hio_bch_t* str, hio_oow_t len, int opti
hio_uintmax_t hio_uchars_to_uintmax (const hio_uch_t* str, hio_oow_t len, int option, const hio_uch_t** endptr, int* is_sober)
{
hio_uintmax_t n = 0;

View File

@ -1,6 +1,4 @@
/*
* $Id$
*
Copyright (c) 2016-2020 Chung, Hyung-Hwan. All rights reserved.
Redistribution and use in source and binary forms, with or without
@ -25,7 +23,7 @@
*/
/*
* Do NOT edit utl-str.c.
* Do NOT edit utl-str.c. Edit utl-str.c.m4 instead.
*
* Generate utl-str.c with m4
* $ m4 utl-str.c.m4 > utl-str.c
@ -35,796 +33,50 @@
#include <hio-chr.h>
dnl ---------------------------------------------------------------------------
changequote(`[[', `]]')
include(`utl-str.m4')
dnl ---------------------------------------------------------------------------
define([[fn_count_cstr]], [[ define([[fn_name]], $1) define([[char_type]], $2)
hio_oow_t fn_name (const char_type* str)
{
const char_type* ptr = str;
while (*ptr != '\0') ptr++;
return ptr - str;
}
]])
fn_count_cstr(hio_count_ucstr, hio_uch_t)
fn_count_cstr(hio_count_bcstr, hio_bch_t)
dnl ---------------------------------------------------------------------------
define([[fn_equal_chars]], [[ define([[fn_name]], $1) define([[char_type]], $2)
int fn_name (const char_type* str1, const char_type* str2, hio_oow_t len)
{
hio_oow_t i;
/* NOTE: you should call this function after having ensured that
* str1 and str2 are in the same length */
for (i = 0; i < len; i++)
{
if (str1[i] != str2[i]) return 0;
}
return 1;
}
]])
fn_equal_chars(hio_equal_uchars, hio_uch_t)
fn_equal_chars(hio_equal_bchars, hio_bch_t)
dnl ---------------------------------------------------------------------------
define([[fn_comp_chars]], [[ define([[fn_name]], $1) define([[char_type]], $2) define([[chau_type]], $3)
int fn_name (const char_type* str1, hio_oow_t len1, const char_type* str2, hio_oow_t len2, int ignorecase)
{
chau_type c1, c2;
const char_type* end1 = str1 + len1;
const char_type* end2 = str2 + len2;
if (ignorecase)
{
while (str1 < end1)
{
c1 = $4(*str1);
if (str2 < end2)
{
c2 = $4(*str2);
if (c1 > c2) return 1;
if (c1 < c2) return -1;
}
else return 1;
str1++; str2++;
}
}
else
{
while (str1 < end1)
{
c1 = *str1;
if (str2 < end2)
{
c2 = *str2;
if (c1 > c2) return 1;
if (c1 < c2) return -1;
}
else return 1;
str1++; str2++;
}
}
return (str2 < end2)? -1: 0;
}
]])
fn_comp_chars(hio_comp_uchars, hio_uch_t, hio_uchu_t, hio_to_uch_lower)
fn_comp_chars(hio_comp_bchars, hio_bch_t, hio_bchu_t, hio_to_bch_lower)
dnl ---------------------------------------------------------------------------
define([[fn_comp_cstr]], [[ define([[fn_name]], $1) define([[char_type]], $2) define([[chau_type]], $3)
int fn_name (const char_type* str1, const char_type* str2, int ignorecase)
{
if (ignorecase)
{
while ($4(*str1) == $4(*str2))
{
if (*str1 == '\0') return 0;
str1++; str2++;
}
return ((chau_type)$4(*str1) > (chau_type)$4(*str2))? 1: -1;
}
else
{
while (*str1 == *str2)
{
if (*str1 == '\0') return 0;
str1++; str2++;
}
return ((chau_type)*str1 > (chau_type)*str2)? 1: -1;
}
}
]])
fn_comp_cstr(hio_comp_ucstr, hio_uch_t, hio_uchu_t, hio_to_uch_lower)
fn_comp_cstr(hio_comp_bcstr, hio_bch_t, hio_bchu_t, hio_to_bch_lower)
dnl ---------------------------------------------------------------------------
define([[fn_comp_cstr_limited]], [[ define([[fn_name]], $1) define([[char_type]], $2) define([[chau_type]], $3)
int fn_name (const char_type* str1, const char_type* str2, hio_oow_t maxlen, int ignorecase)
{
if (maxlen == 0) return 0;
if (ignorecase)
{
while ($4(*str1) == $4(*str2))
{
if (*str1 == '\0' || maxlen == 1) return 0;
str1++; str2++; maxlen--;
}
return ((chau_type)$4(*str1) > (chau_type)$4(*str2))? 1: -1;
}
else
{
while (*str1 == *str2)
{
if (*str1 == '\0' || maxlen == 1) return 0;
str1++; str2++; maxlen--;
}
return ((chau_type)*str1 > (chau_type)*str2)? 1: -1;
}
}
]])
fn_comp_cstr_limited(hio_comp_ucstr_limited, hio_uch_t, hio_uchu_t, hio_to_uch_lower)
fn_comp_cstr_limited(hio_comp_bcstr_limited, hio_bch_t, hio_bchu_t, hio_to_bch_lower)
dnl ---------------------------------------------------------------------------
define([[fn_concat_chars_to_cstr]], [[ define([[fn_name]], $1) define([[char_type]], $2) dnl: $3 count_str
hio_oow_t fn_name (char_type* buf, hio_oow_t bsz, const char_type* str, hio_oow_t len)
{
char_type* p, * p2;
const char_type* end;
hio_oow_t blen;
blen = $3(buf);
if (blen >= bsz) return blen; /* something wrong */
p = buf + blen;
p2 = buf + bsz - 1;
end = str + len;
while (p < p2)
{
if (str >= end) break;
*p++ = *str++;
}
if (bsz > 0) *p = '\0';
return p - buf;
}
]])
fn_concat_chars_to_cstr(hio_concat_uchars_to_ucstr, hio_uch_t, hio_count_ucstr)
fn_concat_chars_to_cstr(hio_concat_bchars_to_bcstr, hio_bch_t, hio_count_bcstr)
dnl ---------------------------------------------------------------------------
define([[fn_concat_cstr]], [[ define([[fn_name]], $1) define([[char_type]], $2) dnl: $3 count_str
hio_oow_t fn_name (char_type* buf, hio_oow_t bsz, const char_type* str)
{
char_type* p, * p2;
hio_oow_t blen;
blen = $3(buf);
if (blen >= bsz) return blen; /* something wrong */
p = buf + blen;
p2 = buf + bsz - 1;
while (p < p2)
{
if (*str == '\0') break;
*p++ = *str++;
}
if (bsz > 0) *p = '\0';
return p - buf;
}
]])
fn_concat_cstr(hio_concat_ucstr, hio_uch_t, hio_count_ucstr)
fn_concat_cstr(hio_concat_bcstr, hio_bch_t, hio_count_bcstr)
dnl ---------------------------------------------------------------------------
define([[fn_fill_chars]], [[ define([[fn_name]], $1) define([[char_type]], $2)
void fn_name (char_type* dst, char_type ch, hio_oow_t len)
{
hio_oow_t i;
for (i = 0; i < len; i++) dst[i] = ch;
}
]])
fn_fill_chars(hio_fill_uchars, hio_uch_t)
fn_fill_chars(hio_fill_bchars, hio_bch_t)
dnl ---------------------------------------------------------------------------
define([[fn_find_char]], [[ define([[fn_name]], $1) define([[char_type]], $2)
char_type* fn_name (const char_type* ptr, hio_oow_t len, char_type c)
{
const char_type* end;
end = ptr + len;
while (ptr < end)
{
if (*ptr == c) return (char_type*)ptr;
ptr++;
}
return HIO_NULL;
}
]])
fn_find_char(hio_find_uchar, hio_uch_t)
fn_find_char(hio_find_bchar, hio_bch_t)
dnl ---------------------------------------------------------------------------
define([[fn_rfind_char]], [[ define([[fn_name]], $1) define([[char_type]], $2)
char_type* fn_name (const char_type* ptr, hio_oow_t len, char_type c)
{
const char_type* cur;
cur = ptr + len;
while (cur > ptr)
{
--cur;
if (*cur == c) return (char_type*)cur;
}
return HIO_NULL;
}
]])
fn_rfind_char(hio_rfind_uchar, hio_uch_t)
fn_rfind_char(hio_rfind_bchar, hio_bch_t)
dnl ---------------------------------------------------------------------------
define([[fn_find_char_in_cstr]], [[ define([[fn_name]], $1) define([[char_type]], $2)
char_type* fn_name (const char_type* ptr, char_type c)
{
while (*ptr != '\0')
{
if (*ptr == c) return (char_type*)ptr;
ptr++;
}
return HIO_NULL;
}
]])
fn_find_char_in_cstr(hio_find_uchar_in_ucstr, hio_uch_t)
fn_find_char_in_cstr(hio_find_bchar_in_bcstr, hio_bch_t)
dnl ---------------------------------------------------------------------------
define([[fn_trim_chars]], [[define([[fn_name]], $1) define([[char_type]], $2) dnl $3: is_space $4: prefix for option values
char_type* fn_name (const char_type* str, hio_oow_t* len, int flags)
{
const char_type* p = str, * end = str + *len;
if (p < end)
{
const char_type* s = HIO_NULL, * e = HIO_NULL;
do
{
if (!$3(*p))
{
if (s == HIO_NULL) s = p;
e = p;
}
p++;
}
while (p < end);
if (e)
{
if (flags & $4_RIGHT)
{
*len -= end - e - 1;
}
if (flags & $4_LEFT)
{
*len -= s - str;
str = s;
}
}
else
{
/* the entire string need to be deleted */
if ((flags & $4_RIGHT) ||
(flags & $4_LEFT)) *len = 0;
}
}
return (char_type*)str;
}
]])
fn_trim_chars(hio_trim_uchars, hio_uch_t, hio_is_uch_space, HIO_TRIM_UCHARS)
fn_trim_chars(hio_trim_bchars, hio_bch_t, hio_is_bch_space, HIO_TRIM_BCHARS)
dnl ---------------------------------------------------------------------------
define([[fn_split_cstr]], [[ define([[fn_name]], $1) define([[char_type]], $2) dnl: $3 is_space $4: copy_str_unlimited
int fn_name (char_type* s, const char_type* delim, char_type lquote, char_type rquote, char_type escape)
{
char_type* p = s, *d;
char_type* sp = HIO_NULL, * ep = HIO_NULL;
int delim_mode;
int cnt = 0;
if (delim == HIO_NULL) delim_mode = 0;
else
{
delim_mode = 1;
for (d = (char_type*)delim; *d != '\0'; d++)
if (!$3(*d)) delim_mode = 2;
}
if (delim_mode == 0)
{
/* skip preceding space characters */
while ($3(*p)) p++;
/* when 0 is given as "delim", it has an effect of cutting
preceding and trailing space characters off "s". */
if (lquote != '\0' && *p == lquote)
{
$4 (p, p + 1);
for (;;)
{
if (*p == '\0') return -1;
if (escape != '\0' && *p == escape)
{
$4 (p, p + 1);
}
else
{
if (*p == rquote)
{
p++;
break;
}
}
if (sp == 0) sp = p;
ep = p;
p++;
}
while ($3(*p)) p++;
if (*p != '\0') return -1;
if (sp == 0 && ep == 0) s[0] = '\0';
else
{
ep[1] = '\0';
if (s != (char_type*)sp) $4 (s, sp);
cnt++;
}
}
else
{
while (*p)
{
if (!$3(*p))
{
if (sp == 0) sp = p;
ep = p;
}
p++;
}
if (sp == 0 && ep == 0) s[0] = '\0';
else
{
ep[1] = '\0';
if (s != (char_type*)sp) $4 (s, sp);
cnt++;
}
}
}
else if (delim_mode == 1)
{
char_type* o;
while (*p)
{
o = p;
while ($3(*p)) p++;
if (o != p) { $4 (o, p); p = o; }
if (lquote != '\0' && *p == lquote)
{
$4 (p, p + 1);
for (;;)
{
if (*p == '\0') return -1;
if (escape != '\0' && *p == escape)
{
$4 (p, p + 1);
}
else
{
if (*p == rquote)
{
*p++ = '\0';
cnt++;
break;
}
}
p++;
}
}
else
{
o = p;
for (;;)
{
if (*p == '\0')
{
if (o != p) cnt++;
break;
}
if ($3(*p))
{
*p++ = '\0';
cnt++;
break;
}
p++;
}
}
}
}
else /* if (delim_mode == 2) */
{
char_type* o;
int ok;
while (*p != '\0')
{
o = p;
while ($3(*p)) p++;
if (o != p) { $4 (o, p); p = o; }
if (lquote != '\0' && *p == lquote)
{
$4 (p, p + 1);
for (;;)
{
if (*p == '\0') return -1;
if (escape != '\0' && *p == escape)
{
$4 (p, p + 1);
}
else
{
if (*p == rquote)
{
*p++ = '\0';
cnt++;
break;
}
}
p++;
}
ok = 0;
while ($3(*p)) p++;
if (*p == '\0') ok = 1;
for (d = (char_type*)delim; *d != '\0'; d++)
{
if (*p == *d)
{
ok = 1;
$4 (p, p + 1);
break;
}
}
if (ok == 0) return -1;
}
else
{
o = p; sp = ep = 0;
for (;;)
{
if (*p == '\0')
{
if (ep)
{
ep[1] = '\0';
p = &ep[1];
}
cnt++;
break;
}
for (d = (char_type*)delim; *d != '\0'; d++)
{
if (*p == *d)
{
if (sp == HIO_NULL)
{
$4 (o, p); p = o;
*p++ = '\0';
}
else
{
$4 (&ep[1], p);
$4 (o, sp);
o[ep - sp + 1] = '\0';
p = &o[ep - sp + 2];
}
cnt++;
/* last empty field after delim */
if (*p == '\0') cnt++;
goto exit_point;
}
}
if (!$3(*p))
{
if (sp == HIO_NULL) sp = p;
ep = p;
}
p++;
}
exit_point:
;
}
}
}
return cnt;
}
]])
fn_split_cstr(hio_split_ucstr, hio_uch_t, hio_is_uch_space, hio_copy_ucstr_unlimited)
fn_split_cstr(hio_split_bcstr, hio_bch_t, hio_is_bch_space, hio_copy_bcstr_unlimited)
dnl ---------------------------------------------------------------------------
define([[fn_chars_to_int]], [[ define([[fn_name]], $1) define([[char_type]], $2) define([[int_type]], $3)
int_type fn_name (const char_type* str, hio_oow_t len, int option, const char_type** endptr, int* is_sober)
{
int_type n = 0;
const char_type* p, * pp;
const char_type* end;
hio_oow_t rem;
int digit, negative = 0;
int base = $5_GET_OPTION_BASE(option);
p = str;
end = str + len;
if ($5_GET_OPTION_LTRIM(option))
{
/* strip off leading spaces */
while (p < end && $4(*p)) p++;
}
/* check for a sign */
while (p < end)
{
if (*p == '-')
{
negative = ~negative;
p++;
}
else if (*p == '+') p++;
else break;
}
/* check for a binary/octal/hexadecimal notation */
rem = end - p;
if (base == 0)
{
if (rem >= 1 && *p == '0')
{
p++;
if (rem == 1) base = 8;
else if (*p == 'x' || *p == 'X')
{
p++; base = 16;
}
else if (*p == 'b' || *p == 'B')
{
p++; base = 2;
}
else base = 8;
}
else base = 10;
}
else if (rem >= 2 && base == 16)
{
if (*p == '0' &&
(*(p + 1) == 'x' || *(p + 1) == 'X')) p += 2;
}
else if (rem >= 2 && base == 2)
{
if (*p == '0' &&
(*(p + 1) == 'b' || *(p + 1) == 'B')) p += 2;
}
/* process the digits */
pp = p;
while (p < end)
{
digit = HIO_ZDIGIT_TO_NUM(*p, base);
if (digit >= base) break;
n = n * base + digit;
p++;
}
if ($5_GET_OPTION_E(option))
{
if (*p == 'E' || *p == 'e')
{
int_type e = 0, i;
int e_neg = 0;
p++;
if (*p == '+')
{
p++;
}
else if (*p == '-')
{
p++; e_neg = 1;
}
while (p < end)
{
digit = HIO_ZDIGIT_TO_NUM(*p, base);
if (digit >= base) break;
e = e * base + digit;
p++;
}
if (e_neg)
for (i = 0; i < e; i++) n /= 10;
else
for (i = 0; i < e; i++) n *= 10;
}
}
/* base 8: at least a zero digit has been seen.
* other case: p > pp to be able to have at least 1 meaningful digit. */
if (is_sober) *is_sober = (base == 8 || p > pp);
if ($5_GET_OPTION_RTRIM(option))
{
/* consume trailing spaces */
while (p < end && $4(*p)) p++;
}
if (endptr) *endptr = p;
return (negative)? -n: n;
}
]])
fn_chars_to_int(hio_uchars_to_intmax, hio_uch_t, hio_intmax_t, hio_is_uch_space, HIO_UCHARS_TO_INTMAX)
fn_chars_to_int(hio_bchars_to_intmax, hio_bch_t, hio_intmax_t, hio_is_bch_space, HIO_BCHARS_TO_INTMAX)
dnl ---------------------------------------------------------------------------
define([[fn_chars_to_uint]], [[ define([[fn_name]], $1) define([[char_type]], $2) define([[int_type]], $3)
int_type fn_name (const char_type* str, hio_oow_t len, int option, const char_type** endptr, int* is_sober)
{
int_type n = 0;
const char_type* p, * pp;
const char_type* end;
hio_oow_t rem;
int digit;
int base = $5_GET_OPTION_BASE(option);
p = str;
end = str + len;
if ($5_GET_OPTION_LTRIM(option))
{
/* strip off leading spaces */
while (p < end && $4(*p)) p++;
}
/* check for a sign */
while (p < end)
{
if (*p == '+') p++;
else break;
}
/* check for a binary/octal/hexadecimal notation */
rem = end - p;
if (base == 0)
{
if (rem >= 1 && *p == '0')
{
p++;
if (rem == 1) base = 8;
else if (*p == 'x' || *p == 'X')
{
p++; base = 16;
}
else if (*p == 'b' || *p == 'B')
{
p++; base = 2;
}
else base = 8;
}
else base = 10;
}
else if (rem >= 2 && base == 16)
{
if (*p == '0' &&
(*(p + 1) == 'x' || *(p + 1) == 'X')) p += 2;
}
else if (rem >= 2 && base == 2)
{
if (*p == '0' &&
(*(p + 1) == 'b' || *(p + 1) == 'B')) p += 2;
}
/* process the digits */
pp = p;
while (p < end)
{
digit = HIO_ZDIGIT_TO_NUM(*p, base);
if (digit >= base) break;
n = n * base + digit;
p++;
}
if ($5_GET_OPTION_E(option))
{
if (*p == 'E' || *p == 'e')
{
int_type e = 0, i;
int e_neg = 0;
p++;
if (*p == '+')
{
p++;
}
else if (*p == '-')
{
p++; e_neg = 1;
}
while (p < end)
{
digit = HIO_ZDIGIT_TO_NUM(*p, base);
if (digit >= base) break;
e = e * base + digit;
p++;
}
if (e_neg)
for (i = 0; i < e; i++) n /= 10;
else
for (i = 0; i < e; i++) n *= 10;
}
}
/* base 8: at least a zero digit has been seen.
* other case: p > pp to be able to have at least 1 meaningful digit. */
if (is_sober) *is_sober = (base == 8 || p > pp);
if ($5_GET_OPTION_RTRIM(option))
{
/* consume trailing spaces */
while (p < end && $4(*p)) p++;
}
if (endptr) *endptr = p;
return n;
}
]])
fn_chars_to_uint(hio_uchars_to_uintmax, hio_uch_t, hio_uintmax_t, hio_is_uch_space, HIO_UCHARS_TO_UINTMAX)
fn_chars_to_uint(hio_bchars_to_uintmax, hio_bch_t, hio_uintmax_t, hio_is_bch_space, HIO_BCHARS_TO_UINTMAX)

757
hio/lib/utl-str.m4 Normal file
View File

@ -0,0 +1,757 @@
dnl ---------------------------------------------------------------------------
changequote(`[[', `]]')
dnl ---------------------------------------------------------------------------
define([[fn_count_cstr]], [[ define([[_fn_name_]], $1) define([[_char_type_]], $2)
hio_oow_t _fn_name_ (const _char_type_* str)
{
const _char_type_* ptr = str;
while (*ptr != '\0') ptr++;
return ptr - str;
}
]])
dnl ---------------------------------------------------------------------------
define([[fn_equal_chars]], [[ define([[_fn_name_]], $1) define([[_char_type_]], $2)
int _fn_name_ (const _char_type_* str1, const _char_type_* str2, hio_oow_t len)
{
hio_oow_t i;
/* NOTE: you should call this function after having ensured that
* str1 and str2 are in the same length */
for (i = 0; i < len; i++)
{
if (str1[i] != str2[i]) return 0;
}
return 1;
}
]])
dnl ---------------------------------------------------------------------------
define([[fn_comp_chars]], [[ define([[_fn_name_]], $1) define([[_char_type_]], $2) define([[_chau_type_]], $3)
int _fn_name_ (const _char_type_* str1, hio_oow_t len1, const _char_type_* str2, hio_oow_t len2, int ignorecase)
{
_chau_type_ c1, c2;
const _char_type_* end1 = str1 + len1;
const _char_type_* end2 = str2 + len2;
if (ignorecase)
{
while (str1 < end1)
{
c1 = $4(*str1);
if (str2 < end2)
{
c2 = $4(*str2);
if (c1 > c2) return 1;
if (c1 < c2) return -1;
}
else return 1;
str1++; str2++;
}
}
else
{
while (str1 < end1)
{
c1 = *str1;
if (str2 < end2)
{
c2 = *str2;
if (c1 > c2) return 1;
if (c1 < c2) return -1;
}
else return 1;
str1++; str2++;
}
}
return (str2 < end2)? -1: 0;
}
]])
dnl ---------------------------------------------------------------------------
define([[fn_comp_cstr]], [[ define([[_fn_name_]], $1) define([[_char_type_]], $2) define([[_chau_type_]], $3)
int _fn_name_ (const _char_type_* str1, const _char_type_* str2, int ignorecase)
{
if (ignorecase)
{
while ($4(*str1) == $4(*str2))
{
if (*str1 == '\0') return 0;
str1++; str2++;
}
return ((_chau_type_)$4(*str1) > (_chau_type_)$4(*str2))? 1: -1;
}
else
{
while (*str1 == *str2)
{
if (*str1 == '\0') return 0;
str1++; str2++;
}
return ((_chau_type_)*str1 > (_chau_type_)*str2)? 1: -1;
}
}
]])
dnl ---------------------------------------------------------------------------
define([[fn_comp_cstr_limited]], [[ define([[_fn_name_]], $1) define([[_char_type_]], $2) define([[_chau_type_]], $3)
int _fn_name_ (const _char_type_* str1, const _char_type_* str2, hio_oow_t maxlen, int ignorecase)
{
if (maxlen == 0) return 0;
if (ignorecase)
{
while ($4(*str1) == $4(*str2))
{
if (*str1 == '\0' || maxlen == 1) return 0;
str1++; str2++; maxlen--;
}
return ((_chau_type_)$4(*str1) > (_chau_type_)$4(*str2))? 1: -1;
}
else
{
while (*str1 == *str2)
{
if (*str1 == '\0' || maxlen == 1) return 0;
str1++; str2++; maxlen--;
}
return ((_chau_type_)*str1 > (_chau_type_)*str2)? 1: -1;
}
}
]])
dnl ---------------------------------------------------------------------------
define([[fn_concat_chars_to_cstr]], [[ define([[_fn_name_]], $1) define([[_char_type_]], $2) dnl: $3 count_str
hio_oow_t _fn_name_ (_char_type_* buf, hio_oow_t bsz, const _char_type_* str, hio_oow_t len)
{
_char_type_* p, * p2;
const _char_type_* end;
hio_oow_t blen;
blen = $3(buf);
if (blen >= bsz) return blen; /* something wrong */
p = buf + blen;
p2 = buf + bsz - 1;
end = str + len;
while (p < p2)
{
if (str >= end) break;
*p++ = *str++;
}
if (bsz > 0) *p = '\0';
return p - buf;
}
]])
dnl ---------------------------------------------------------------------------
dnl $3: count_str
define([[fn_concat_cstr]], [[ define([[_fn_name_]], $1) define([[_char_type_]], $2)
hio_oow_t _fn_name_ (_char_type_* buf, hio_oow_t bsz, const _char_type_* str)
{
_char_type_* p, * p2;
hio_oow_t blen;
blen = $3(buf);
if (blen >= bsz) return blen; /* something wrong */
p = buf + blen;
p2 = buf + bsz - 1;
while (p < p2)
{
if (*str == '\0') break;
*p++ = *str++;
}
if (bsz > 0) *p = '\0';
return p - buf;
}
]])
dnl ---------------------------------------------------------------------------
define([[fn_fill_chars]], [[ define([[_fn_name_]], $1) define([[_char_type_]], $2)
void _fn_name_ (_char_type_* dst, _char_type_ ch, hio_oow_t len)
{
hio_oow_t i;
for (i = 0; i < len; i++) dst[i] = ch;
}
]])
dnl ---------------------------------------------------------------------------
define([[fn_find_char]], [[ define([[_fn_name_]], $1) define([[_char_type_]], $2)
_char_type_* _fn_name_ (const _char_type_* ptr, hio_oow_t len, _char_type_ c)
{
const _char_type_* end;
end = ptr + len;
while (ptr < end)
{
if (*ptr == c) return (_char_type_*)ptr;
ptr++;
}
return HIO_NULL;
}
]])
dnl ---------------------------------------------------------------------------
define([[fn_rfind_char]], [[ define([[_fn_name_]], $1) define([[_char_type_]], $2)
_char_type_* _fn_name_ (const _char_type_* ptr, hio_oow_t len, _char_type_ c)
{
const _char_type_* cur;
cur = ptr + len;
while (cur > ptr)
{
--cur;
if (*cur == c) return (_char_type_*)cur;
}
return HIO_NULL;
}
]])
dnl ---------------------------------------------------------------------------
define([[fn_find_char_in_cstr]], [[ define([[_fn_name_]], $1) define([[_char_type_]], $2)
_char_type_* _fn_name_ (const _char_type_* ptr, _char_type_ c)
{
while (*ptr != '\0')
{
if (*ptr == c) return (_char_type_*)ptr;
ptr++;
}
return HIO_NULL;
}
]])
dnl ---------------------------------------------------------------------------
dnl $3: is_space $4: prefix for option values
define([[fn_trim_chars]], [[define([[_fn_name_]], $1) define([[_char_type_]], $2)
_char_type_* _fn_name_ (const _char_type_* str, hio_oow_t* len, int flags)
{
const _char_type_* p = str, * end = str + *len;
if (p < end)
{
const _char_type_* s = HIO_NULL, * e = HIO_NULL;
do
{
if (!$3(*p))
{
if (s == HIO_NULL) s = p;
e = p;
}
p++;
}
while (p < end);
if (e)
{
if (flags & $4_RIGHT)
{
*len -= end - e - 1;
}
if (flags & $4_LEFT)
{
*len -= s - str;
str = s;
}
}
else
{
/* the entire string need to be deleted */
if ((flags & $4_RIGHT) ||
(flags & $4_LEFT)) *len = 0;
}
}
return (_char_type_*)str;
}
]])
dnl ---------------------------------------------------------------------------
dnl $3 is_space $4: copy_str_unlimited
define([[fn_split_cstr]], [[ define([[_fn_name_]], $1) define([[_char_type_]], $2)
int _fn_name_ (_char_type_* s, const _char_type_* delim, _char_type_ lquote, _char_type_ rquote, _char_type_ escape)
{
_char_type_* p = s, *d;
_char_type_* sp = HIO_NULL, * ep = HIO_NULL;
int delim_mode;
int cnt = 0;
if (delim == HIO_NULL) delim_mode = 0;
else
{
delim_mode = 1;
for (d = (_char_type_*)delim; *d != '\0'; d++)
if (!$3(*d)) delim_mode = 2;
}
if (delim_mode == 0)
{
/* skip preceding space characters */
while ($3(*p)) p++;
/* when 0 is given as "delim", it has an effect of cutting
preceding and trailing space characters off "s". */
if (lquote != '\0' && *p == lquote)
{
$4 (p, p + 1);
for (;;)
{
if (*p == '\0') return -1;
if (escape != '\0' && *p == escape)
{
$4 (p, p + 1);
}
else
{
if (*p == rquote)
{
p++;
break;
}
}
if (sp == 0) sp = p;
ep = p;
p++;
}
while ($3(*p)) p++;
if (*p != '\0') return -1;
if (sp == 0 && ep == 0) s[0] = '\0';
else
{
ep[1] = '\0';
if (s != (_char_type_*)sp) $4 (s, sp);
cnt++;
}
}
else
{
while (*p)
{
if (!$3(*p))
{
if (sp == 0) sp = p;
ep = p;
}
p++;
}
if (sp == 0 && ep == 0) s[0] = '\0';
else
{
ep[1] = '\0';
if (s != (_char_type_*)sp) $4 (s, sp);
cnt++;
}
}
}
else if (delim_mode == 1)
{
_char_type_* o;
while (*p)
{
o = p;
while ($3(*p)) p++;
if (o != p) { $4 (o, p); p = o; }
if (lquote != '\0' && *p == lquote)
{
$4 (p, p + 1);
for (;;)
{
if (*p == '\0') return -1;
if (escape != '\0' && *p == escape)
{
$4 (p, p + 1);
}
else
{
if (*p == rquote)
{
*p++ = '\0';
cnt++;
break;
}
}
p++;
}
}
else
{
o = p;
for (;;)
{
if (*p == '\0')
{
if (o != p) cnt++;
break;
}
if ($3(*p))
{
*p++ = '\0';
cnt++;
break;
}
p++;
}
}
}
}
else /* if (delim_mode == 2) */
{
_char_type_* o;
int ok;
while (*p != '\0')
{
o = p;
while ($3(*p)) p++;
if (o != p) { $4 (o, p); p = o; }
if (lquote != '\0' && *p == lquote)
{
$4 (p, p + 1);
for (;;)
{
if (*p == '\0') return -1;
if (escape != '\0' && *p == escape)
{
$4 (p, p + 1);
}
else
{
if (*p == rquote)
{
*p++ = '\0';
cnt++;
break;
}
}
p++;
}
ok = 0;
while ($3(*p)) p++;
if (*p == '\0') ok = 1;
for (d = (_char_type_*)delim; *d != '\0'; d++)
{
if (*p == *d)
{
ok = 1;
$4 (p, p + 1);
break;
}
}
if (ok == 0) return -1;
}
else
{
o = p; sp = ep = 0;
for (;;)
{
if (*p == '\0')
{
if (ep)
{
ep[1] = '\0';
p = &ep[1];
}
cnt++;
break;
}
for (d = (_char_type_*)delim; *d != '\0'; d++)
{
if (*p == *d)
{
if (sp == HIO_NULL)
{
$4 (o, p); p = o;
*p++ = '\0';
}
else
{
$4 (&ep[1], p);
$4 (o, sp);
o[ep - sp + 1] = '\0';
p = &o[ep - sp + 2];
}
cnt++;
/* last empty field after delim */
if (*p == '\0') cnt++;
goto exit_point;
}
}
if (!$3(*p))
{
if (sp == HIO_NULL) sp = p;
ep = p;
}
p++;
}
exit_point:
;
}
}
}
return cnt;
}
]])
dnl ---------------------------------------------------------------------------
define([[fn_chars_to_int]], [[ define([[_fn_name_]], $1) define([[_char_type_]], $2) define([[_int_type_]], $3)
_int_type_ _fn_name_ (const _char_type_* str, hio_oow_t len, int option, const _char_type_** endptr, int* is_sober)
{
_int_type_ n = 0;
const _char_type_* p, * pp;
const _char_type_* end;
hio_oow_t rem;
int digit, negative = 0;
int base = $5_GET_OPTION_BASE(option);
p = str;
end = str + len;
if ($5_GET_OPTION_LTRIM(option))
{
/* strip off leading spaces */
while (p < end && $4(*p)) p++;
}
/* check for a sign */
while (p < end)
{
if (*p == '-')
{
negative = ~negative;
p++;
}
else if (*p == '+') p++;
else break;
}
/* check for a binary/octal/hexadecimal notation */
rem = end - p;
if (base == 0)
{
if (rem >= 1 && *p == '0')
{
p++;
if (rem == 1) base = 8;
else if (*p == 'x' || *p == 'X')
{
p++; base = 16;
}
else if (*p == 'b' || *p == 'B')
{
p++; base = 2;
}
else base = 8;
}
else base = 10;
}
else if (rem >= 2 && base == 16)
{
if (*p == '0' &&
(*(p + 1) == 'x' || *(p + 1) == 'X')) p += 2;
}
else if (rem >= 2 && base == 2)
{
if (*p == '0' &&
(*(p + 1) == 'b' || *(p + 1) == 'B')) p += 2;
}
/* process the digits */
pp = p;
while (p < end)
{
digit = HIO_ZDIGIT_TO_NUM(*p, base);
if (digit >= base) break;
n = n * base + digit;
p++;
}
if ($5_GET_OPTION_E(option))
{
if (*p == 'E' || *p == 'e')
{
_int_type_ e = 0, i;
int e_neg = 0;
p++;
if (*p == '+')
{
p++;
}
else if (*p == '-')
{
p++; e_neg = 1;
}
while (p < end)
{
digit = HIO_ZDIGIT_TO_NUM(*p, base);
if (digit >= base) break;
e = e * base + digit;
p++;
}
if (e_neg)
for (i = 0; i < e; i++) n /= 10;
else
for (i = 0; i < e; i++) n *= 10;
}
}
/* base 8: at least a zero digit has been seen.
* other case: p > pp to be able to have at least 1 meaningful digit. */
if (is_sober) *is_sober = (base == 8 || p > pp);
if ($5_GET_OPTION_RTRIM(option))
{
/* consume trailing spaces */
while (p < end && $4(*p)) p++;
}
if (endptr) *endptr = p;
return (negative)? -n: n;
}
]])
dnl ---------------------------------------------------------------------------
define([[fn_chars_to_uint]], [[ define([[_fn_name_]], $1) define([[_char_type_]], $2) define([[_int_type_]], $3)
_int_type_ _fn_name_ (const _char_type_* str, hio_oow_t len, int option, const _char_type_** endptr, int* is_sober)
{
_int_type_ n = 0;
const _char_type_* p, * pp;
const _char_type_* end;
hio_oow_t rem;
int digit;
int base = $5_GET_OPTION_BASE(option);
p = str;
end = str + len;
if ($5_GET_OPTION_LTRIM(option))
{
/* strip off leading spaces */
while (p < end && $4(*p)) p++;
}
/* check for a sign */
while (p < end)
{
if (*p == '+') p++;
else break;
}
/* check for a binary/octal/hexadecimal notation */
rem = end - p;
if (base == 0)
{
if (rem >= 1 && *p == '0')
{
p++;
if (rem == 1) base = 8;
else if (*p == 'x' || *p == 'X')
{
p++; base = 16;
}
else if (*p == 'b' || *p == 'B')
{
p++; base = 2;
}
else base = 8;
}
else base = 10;
}
else if (rem >= 2 && base == 16)
{
if (*p == '0' &&
(*(p + 1) == 'x' || *(p + 1) == 'X')) p += 2;
}
else if (rem >= 2 && base == 2)
{
if (*p == '0' &&
(*(p + 1) == 'b' || *(p + 1) == 'B')) p += 2;
}
/* process the digits */
pp = p;
while (p < end)
{
digit = HIO_ZDIGIT_TO_NUM(*p, base);
if (digit >= base) break;
n = n * base + digit;
p++;
}
if ($5_GET_OPTION_E(option))
{
if (*p == 'E' || *p == 'e')
{
_int_type_ e = 0, i;
int e_neg = 0;
p++;
if (*p == '+')
{
p++;
}
else if (*p == '-')
{
p++; e_neg = 1;
}
while (p < end)
{
digit = HIO_ZDIGIT_TO_NUM(*p, base);
if (digit >= base) break;
e = e * base + digit;
p++;
}
if (e_neg)
for (i = 0; i < e; i++) n /= 10;
else
for (i = 0; i < e; i++) n *= 10;
}
}
/* base 8: at least a zero digit has been seen.
* other case: p > pp to be able to have at least 1 meaningful digit. */
if (is_sober) *is_sober = (base == 8 || p > pp);
if ($5_GET_OPTION_RTRIM(option))
{
/* consume trailing spaces */
while (p < end && $4(*p)) p++;
}
if (endptr) *endptr = p;
return n;
}
]])