summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/Makefile.am6
-rw-r--r--include/Makefile.in33
-rw-r--r--include/libHX/ctype_helper.h5
-rw-r--r--include/libHX/defs.h12
-rw-r--r--include/libHX/deque.h38
-rw-r--r--include/libHX/endian.h202
-rw-r--r--include/libHX/endian_float.h107
-rw-r--r--include/libHX/io.h3
-rw-r--r--include/libHX/list.h8
-rw-r--r--include/libHX/map.h4
-rw-r--r--include/libHX/misc.h12
-rw-r--r--include/libHX/option.h90
-rw-r--r--include/libHX/scope.hpp35
-rw-r--r--include/libHX/string.h22
14 files changed, 471 insertions, 106 deletions
diff --git a/include/Makefile.am b/include/Makefile.am
index 62ad527..e3d3f86 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -1,7 +1,9 @@
# -*- Makefile -*-
nobase_include_HEADERS = libHX.h libHX/cast.h \
- libHX/ctype_helper.h libHX/defs.h libHX/deque.h libHX/init.h \
+ libHX/ctype_helper.h libHX/defs.h libHX/deque.h \
+ libHX/endian.h libHX/endian_float.h libHX/init.h \
libHX/intdiff.hpp libHX/io.h libHX/list.h \
- libHX/map.h libHX/misc.h libHX/option.h libHX/proc.h libHX/socket.h libHX/string.h \
+ libHX/map.h libHX/misc.h libHX/option.h libHX/proc.h \
+ libHX/scope.hpp libHX/socket.h libHX/string.h \
libHX/libxml_helper.h libHX/wx_helper.hpp
diff --git a/include/Makefile.in b/include/Makefile.in
index 8e02ba6..3f3227d 100644
--- a/include/Makefile.in
+++ b/include/Makefile.in
@@ -1,7 +1,7 @@
-# Makefile.in generated by automake 1.16.5 from Makefile.am.
+# Makefile.in generated by automake 1.18.1 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994-2021 Free Software Foundation, Inc.
+# Copyright (C) 1994-2025 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -72,6 +72,8 @@ am__make_running_with_option = \
test $$has_opt = yes
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+am__rm_f = rm -f $(am__rm_f_notfound)
+am__rm_rf = rm -rf $(am__rm_f_notfound)
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
@@ -145,10 +147,9 @@ am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__uninstall_files_from_dir = { \
- test -z "$$files" \
- || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
- || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
- $(am__cd) "$$dir" && rm -f $$files; }; \
+ { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && echo $$files | $(am__xargs_n) 40 $(am__rm_f); }; \
}
am__installdirs = "$(DESTDIR)$(includedir)"
HEADERS = $(nobase_include_HEADERS)
@@ -252,8 +253,10 @@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
+am__rm_f_notfound = @am__rm_f_notfound@
am__tar = @am__tar@
am__untar = @am__untar@
+am__xargs_n = @am__xargs_n@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
@@ -304,9 +307,11 @@ top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
nobase_include_HEADERS = libHX.h libHX/cast.h \
- libHX/ctype_helper.h libHX/defs.h libHX/deque.h libHX/init.h \
+ libHX/ctype_helper.h libHX/defs.h libHX/deque.h \
+ libHX/endian.h libHX/endian_float.h libHX/init.h \
libHX/intdiff.hpp libHX/io.h libHX/list.h \
- libHX/map.h libHX/misc.h libHX/option.h libHX/proc.h libHX/socket.h libHX/string.h \
+ libHX/map.h libHX/misc.h libHX/option.h libHX/proc.h \
+ libHX/scope.hpp libHX/socket.h libHX/string.h \
libHX/libxml_helper.h libHX/wx_helper.hpp
all: all-am
@@ -423,6 +428,7 @@ cscopelist-am: $(am__tagged_files)
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
distdir: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) distdir-am
@@ -487,8 +493,8 @@ mostlyclean-generic:
clean-generic:
distclean-generic:
- -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
- -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+ -$(am__rm_f) $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || $(am__rm_f) $(CONFIG_CLEAN_VPATH_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@@ -581,3 +587,10 @@ uninstall-am: uninstall-nobase_includeHEADERS
# 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.
.NOEXPORT:
+
+# Tell GNU make to disable its built-in pattern rules.
+%:: %,v
+%:: RCS/%,v
+%:: RCS/%
+%:: s.%
+%:: SCCS/s.%
diff --git a/include/libHX/ctype_helper.h b/include/libHX/ctype_helper.h
index 2ba0a7a..0f42c4f 100644
--- a/include/libHX/ctype_helper.h
+++ b/include/libHX/ctype_helper.h
@@ -39,6 +39,11 @@ static __inline__ bool HX_isalpha(unsigned char c)
return isalpha(c);
}
+static __inline__ bool HX_isascii(unsigned char c)
+{
+ return isascii(c);
+}
+
static __inline__ bool HX_isdigit(unsigned char c)
{
return isdigit(c);
diff --git a/include/libHX/defs.h b/include/libHX/defs.h
index ba84b37..638ec15 100644
--- a/include/libHX/defs.h
+++ b/include/libHX/defs.h
@@ -12,7 +12,16 @@
# ifndef containerof
# include <cstddef>
# include <type_traits>
-# define containerof(var, T, member) reinterpret_cast<std::conditional<std::is_const<std::remove_pointer<decltype(var)>::type>::value, std::add_const<T>::type, T>::type *>(reinterpret_cast<std::conditional<std::is_const<std::remove_pointer<decltype(var)>::type>::value, const char, char>::type *>(var) - offsetof(T, member))
+namespace {
+template<typename Dst, typename Src> static inline auto containerof_cxx(Src *var, size_t ofs)
+{
+ using K = typename std::is_const<typename std::remove_pointer<Src>::type>;
+ using Ch = typename std::conditional<K::value, const char, char>::type;
+ using D2 = typename std::conditional<K::value, const Dst, Dst>::type;
+ return reinterpret_cast<D2 *>(reinterpret_cast<Ch *>(var) - ofs);
+}
+}
+# define containerof(var, D1, member) containerof_cxx<D1>(var, offsetof(D1, member))
# endif
#else
# define HXsizeof_member(type, member) sizeof(((type *)NULL)->member)
@@ -86,6 +95,7 @@
#define HXSIZEOF_Z32 sizeof("-4294967296")
/* 2^64 and -2^63 have same length */
#define HXSIZEOF_Z64 sizeof("18446744073709551616")
+#define HXSIZEOF_UNITSEC64 sizeof("584542046089y11months2weeks2d23h59min59s")
#define __HX_STRINGIFY_EXPAND(s) #s
#define HX_STRINGIFY(s) __HX_STRINGIFY_EXPAND(s)
diff --git a/include/libHX/deque.h b/include/libHX/deque.h
index f43def9..11fdd2a 100644
--- a/include/libHX/deque.h
+++ b/include/libHX/deque.h
@@ -25,7 +25,7 @@ struct HXdeque {
struct HXdeque_node *first;
void *ptr;
struct HXdeque_node *last;
- unsigned int items;
+ size_t items;
};
extern struct HXdeque *HXdeque_init(void);
@@ -39,7 +39,8 @@ extern void *HXdeque_get(struct HXdeque *, const void *);
extern void *HXdeque_del(struct HXdeque_node *);
extern void HXdeque_free(struct HXdeque *);
extern void HXdeque_genocide2(struct HXdeque *, void (*)(void *));
-extern void **HXdeque_to_vec(const struct HXdeque *, unsigned int *);
+extern void **HXdeque_to_vec(const struct HXdeque *, size_t *);
+extern void **HXdeque_to_vecx(const struct HXdeque *, size_t *);
static __inline__ void HXdeque_genocide(struct HXdeque *dq)
{
@@ -48,39 +49,6 @@ static __inline__ void HXdeque_genocide(struct HXdeque *dq)
#ifdef __cplusplus
} /* extern "C" */
-
-extern "C++" {
-
-template<typename type> static __inline__ type HXdeque_pop(struct HXdeque *dq)
-{
- return reinterpret_cast<type>(HXdeque_pop(dq));
-}
-
-template<typename type> static __inline__ type
-HXdeque_shift(struct HXdeque *dq)
-{
- return reinterpret_cast<type>(HXdeque_shift(dq));
-}
-
-template<typename type> static __inline__ type
-HXdeque_get(struct HXdeque *dq, const void *ptr)
-{
- return reinterpret_cast<type>(HXdeque_get(dq, ptr));
-}
-
-template<typename type> static __inline__ type
-HXdeque_del(struct HXdeque_node *nd)
-{
- return reinterpret_cast<type>(HXdeque_del(nd));
-}
-
-template<typename type> static __inline__ type *
-HXdeque_to_vec(struct HXdeque *dq, unsigned int *n)
-{
- return reinterpret_cast<type *>(HXdeque_to_vec(dq, n));
-}
-
-} /* extern "C++" */
#endif
#endif /* _LIBHX_DEQUE_H */
diff --git a/include/libHX/endian.h b/include/libHX/endian.h
new file mode 100644
index 0000000..b1a4b6a
--- /dev/null
+++ b/include/libHX/endian.h
@@ -0,0 +1,202 @@
+#ifndef _LIBHX_ENDIAN_H
+#define _LIBHX_ENDIAN_H 1
+/*
+ * See <https://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html>.
+ *
+ * be16p_to_cpu not optimized on LE before gcc-10.
+ * le16p_to_cpu not optimized away on LE before gcc-10.
+ * cpu_to_be{16,32,64}p not optimized on LE before gcc-8.
+ * cpu_to_le{16,32,64}p not optimized away on LE before gcc-8.
+ * cpu_to_le{16,32,64} not optimized away on LE before gcc-8.
+ * cpu_to_be16 not optimized on LE before gcc-9.
+ * cpu_to_be{32,64} not optimized on LE before gcc-8.
+ * be64_to_cpu not optimized on LE before gcc-10.
+ */
+#include <stdint.h>
+#ifndef LIBHX_DBG_INLINE
+# define LIBHX_DBG_INLINE static inline
+#endif
+#if !defined(LIBHX_OPT_O2) && defined(__GNUC__) && !defined(__clang__) && !defined(__llvm__)
+# define LIBHX_OPT_O2 __attribute__((optimize("-O2")))
+#else
+# define LIBHX_OPT_O2
+#endif
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBHX_DBG_INLINE uint16_t LIBHX_OPT_O2 be16p_to_cpu(const void *p)
+{
+ const uint8_t *q = (const uint8_t *)p;
+ typedef uint16_t T;
+ return (T)q[1] | ((T)q[0] << 8);
+}
+
+LIBHX_DBG_INLINE uint16_t LIBHX_OPT_O2 le16p_to_cpu(const void *p)
+{
+ const uint8_t *q = (const uint8_t *)p;
+ typedef uint16_t T;
+ return (T)q[0] | ((T)q[1] << 8);
+}
+
+LIBHX_DBG_INLINE uint32_t LIBHX_OPT_O2 be32p_to_cpu(const void *p)
+{
+ const uint8_t *q = (const uint8_t *)p;
+ typedef uint32_t T;
+ return (T)q[3] | ((T)q[2] << 8) | ((T)q[1] << 16) | ((T)q[0] << 24);
+}
+
+LIBHX_DBG_INLINE uint32_t LIBHX_OPT_O2 le32p_to_cpu(const void *p)
+{
+ const uint8_t *q = (const uint8_t *)p;
+ typedef uint32_t T;
+ return (T)q[0] | ((T)q[1] << 8) | ((T)q[2] << 16) | ((T)q[3] << 24);
+}
+
+LIBHX_DBG_INLINE uint64_t LIBHX_OPT_O2 be64p_to_cpu(const void *p)
+{
+ const uint8_t *q = (const uint8_t *)p;
+ typedef uint64_t T;
+ return (T)q[7] | ((T)q[6] << 8) | ((T)q[5] << 16) | ((T)q[4] << 24) | ((T)q[3] << 32) |
+ ((T)q[2] << 40) | ((T)q[1] << 48) | ((T)q[0] << 56);
+}
+
+LIBHX_DBG_INLINE uint64_t LIBHX_OPT_O2 le64p_to_cpu(const void *p)
+{
+ const uint8_t *q = (const uint8_t *)p;
+ typedef uint64_t T;
+ return (T)q[0] | ((T)q[1] << 8) | ((T)q[2] << 16) | ((T)q[3] << 24) | ((T)q[4] << 32) |
+ ((T)q[5] << 40) | ((T)q[6] << 48) | ((T)q[7] << 56);
+}
+
+LIBHX_DBG_INLINE void LIBHX_OPT_O2 cpu_to_be16p(void *p, uint16_t v)
+{
+ uint8_t *q = (uint8_t *)p;
+ q[1] = v;
+ q[0] = v >> 8;
+}
+
+LIBHX_DBG_INLINE void LIBHX_OPT_O2 cpu_to_le16p(void *p, uint16_t v)
+{
+ uint8_t *q = (uint8_t *)p;
+ q[0] = v;
+ q[1] = v >> 8;
+}
+
+LIBHX_DBG_INLINE void LIBHX_OPT_O2 cpu_to_be32p(void *p, uint32_t v)
+{
+ uint8_t *q = (uint8_t *)p;
+ q[3] = v;
+ q[2] = v >> 8;
+ q[1] = v >> 16;
+ q[0] = v >> 24;
+}
+
+LIBHX_DBG_INLINE void LIBHX_OPT_O2 cpu_to_le32p(void *p, uint32_t v)
+{
+ uint8_t *q = (uint8_t *)p;
+ q[0] = v;
+ q[1] = v >> 8;
+ q[2] = v >> 16;
+ q[3] = v >> 24;
+}
+
+LIBHX_DBG_INLINE void LIBHX_OPT_O2 cpu_to_be64p(void *p, uint64_t v)
+{
+ uint8_t *q = (uint8_t *)p;
+ q[7] = v;
+ q[6] = v >> 8;
+ q[5] = v >> 16;
+ q[4] = v >> 24;
+ q[3] = v >> 32;
+ q[2] = v >> 40;
+ q[1] = v >> 48;
+ q[0] = v >> 56;
+}
+
+LIBHX_DBG_INLINE void LIBHX_OPT_O2 cpu_to_le64p(void *p, uint64_t v)
+{
+ uint8_t *q = (uint8_t *)p;
+ q[0] = v;
+ q[1] = v >> 8;
+ q[2] = v >> 16;
+ q[3] = v >> 24;
+ q[4] = v >> 32;
+ q[5] = v >> 40;
+ q[6] = v >> 48;
+ q[7] = v >> 56;
+}
+
+/* This is in essence the same as htons/htonl/htonll/htonq */
+/* [Do we need to worry about trap representations?] */
+LIBHX_DBG_INLINE uint16_t LIBHX_OPT_O2 be16_to_cpu(uint16_t v)
+{
+ return be16p_to_cpu(&v);
+}
+
+LIBHX_DBG_INLINE uint32_t LIBHX_OPT_O2 be32_to_cpu(uint32_t v)
+{
+ return be32p_to_cpu(&v);
+}
+
+LIBHX_DBG_INLINE uint64_t LIBHX_OPT_O2 be64_to_cpu(uint64_t v)
+{
+ return be64p_to_cpu(&v);
+}
+
+LIBHX_DBG_INLINE uint16_t LIBHX_OPT_O2 le16_to_cpu(uint16_t v)
+{
+ return le16p_to_cpu(&v);
+}
+
+LIBHX_DBG_INLINE uint32_t LIBHX_OPT_O2 le32_to_cpu(uint32_t v)
+{
+ return le32p_to_cpu(&v);
+}
+
+LIBHX_DBG_INLINE uint64_t LIBHX_OPT_O2 le64_to_cpu(uint64_t v)
+{
+ return le64p_to_cpu(&v);
+}
+
+LIBHX_DBG_INLINE uint16_t LIBHX_OPT_O2 cpu_to_be16(uint16_t v)
+{
+ cpu_to_be16p(&v, v);
+ return v;
+}
+
+LIBHX_DBG_INLINE uint32_t LIBHX_OPT_O2 cpu_to_be32(uint32_t v)
+{
+ cpu_to_be32p(&v, v);
+ return v;
+}
+
+LIBHX_DBG_INLINE uint64_t LIBHX_OPT_O2 cpu_to_be64(uint64_t v)
+{
+ cpu_to_be64p(&v, v);
+ return v;
+}
+
+LIBHX_DBG_INLINE uint16_t LIBHX_OPT_O2 cpu_to_le16(uint16_t v)
+{
+ cpu_to_le16p(&v, v);
+ return v;
+}
+
+LIBHX_DBG_INLINE uint32_t LIBHX_OPT_O2 cpu_to_le32(uint32_t v)
+{
+ cpu_to_le32p(&v, v);
+ return v;
+}
+
+LIBHX_DBG_INLINE uint64_t LIBHX_OPT_O2 cpu_to_le64(uint64_t v)
+{
+ cpu_to_le64p(&v, v);
+ return v;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LIBHX_ENDIAN_H */
diff --git a/include/libHX/endian_float.h b/include/libHX/endian_float.h
new file mode 100644
index 0000000..f36e110
--- /dev/null
+++ b/include/libHX/endian_float.h
@@ -0,0 +1,107 @@
+#ifndef _LIBHX_ENDIAN_FLOAT_H
+#define _LIBHX_ENDIAN_FLOAT_H 1
+#include <string.h>
+#include <libHX/endian.h>
+
+/*
+ * While construction of integers from bytes was easy, it would be more work
+ * for floats — and compilers probably won't be able to optimize it.
+ *
+ * So then, we make some shortcuts/assumptions here in endian_float.h:
+ * - that the host platform uses the same byte order for integers as for floats
+ * - that the host platform is using IEEE754/IEC559
+ *
+ * This holds for the typical Linux on {arm gnueabi LE, arm gnueabi
+ * BE, aarch64 LE, aarch64 BE, i386, amd64, hppa, loongarch64, m68k,
+ * mips, ppc64, ppc64le, sparc, sparc64, riscv64, s390x}.
+ */
+
+/*
+ * Unlike cpu_to_be32, we will offer no float_cpu_to_be32. Values comprised of
+ * inverted bytes should probably not be passed around in memory.
+ */
+LIBHX_DBG_INLINE float LIBHX_OPT_O2 float_be32p_to_cpu(const void *p)
+{
+ uint32_t v = be32p_to_cpu(p);
+ float w;
+#ifdef __cplusplus
+ static_assert(sizeof(v) == sizeof(w));
+#endif
+ memcpy(&w, &v, sizeof(w));
+ return w;
+}
+
+LIBHX_DBG_INLINE double LIBHX_OPT_O2 float_le32p_to_cpu(const void *p)
+{
+ uint32_t v = le32p_to_cpu(p);
+ float w;
+#ifdef __cplusplus
+ static_assert(sizeof(v) == sizeof(w));
+#endif
+ memcpy(&w, &v, sizeof(w));
+ return w;
+}
+
+LIBHX_DBG_INLINE float LIBHX_OPT_O2 float_be64p_to_cpu(const void *p)
+{
+ uint64_t v = be64p_to_cpu(p);
+ double w;
+#ifdef __cplusplus
+ static_assert(sizeof(v) == sizeof(w));
+#endif
+ memcpy(&w, &v, sizeof(w));
+ return w;
+}
+
+LIBHX_DBG_INLINE double LIBHX_OPT_O2 float_le64p_to_cpu(const void *p)
+{
+ uint64_t v = le64p_to_cpu(p);
+ double w;
+#ifdef __cplusplus
+ static_assert(sizeof(v) == sizeof(w));
+#endif
+ memcpy(&w, &v, sizeof(w));
+ return w;
+}
+
+LIBHX_DBG_INLINE void LIBHX_OPT_O2 float_cpu_to_be32p(void *p, float v)
+{
+ uint32_t w;
+#ifdef __cplusplus
+ static_assert(sizeof(v) == sizeof(w));
+#endif
+ memcpy(&w, &v, sizeof(w));
+ cpu_to_be32p(p, w);
+}
+
+LIBHX_DBG_INLINE void LIBHX_OPT_O2 float_cpu_to_le32p(void *p, float v)
+{
+ uint32_t w;
+#ifdef __cplusplus
+ static_assert(sizeof(v) == sizeof(w));
+#endif
+ memcpy(&w, &v, sizeof(w));
+ cpu_to_le32p(p, w);
+}
+
+LIBHX_DBG_INLINE void LIBHX_OPT_O2 float_cpu_to_be64p(void *p, double v)
+{
+ uint64_t w;
+#ifdef __cplusplus
+ static_assert(sizeof(v) == sizeof(w));
+#endif
+ memcpy(&w, &v, sizeof(w));
+ cpu_to_be64p(p, w);
+}
+
+LIBHX_DBG_INLINE void LIBHX_OPT_O2 float_cpu_to_le64p(void *p, double v)
+{
+ uint64_t w;
+#ifdef __cplusplus
+ static_assert(sizeof(v) == sizeof(w));
+#endif
+ memcpy(&w, &v, sizeof(w));
+ cpu_to_le64p(p, w);
+}
+
+#endif /* _LIBHX_ENDIAN_FLOAT_H */
diff --git a/include/libHX/io.h b/include/libHX/io.h
index 7e0c7d3..e1d182d 100644
--- a/include/libHX/io.h
+++ b/include/libHX/io.h
@@ -33,6 +33,7 @@ extern void HXdir_close(struct HXdir *);
extern int HX_copy_dir(const char *, const char *, unsigned int, ...);
extern int HX_copy_file(const char *, const char *, unsigned int, ...);
extern int HX_mkdir(const char *, unsigned int);
+extern int HX_getcwd(hxmc_t **);
extern int HX_readlink(hxmc_t **, const char *);
extern int HX_realpath(hxmc_t **, const char *, unsigned int);
extern int HX_rrmdir(const char *);
@@ -44,7 +45,7 @@ extern ssize_t HXio_fullread(int, void *, size_t);
extern ssize_t HXio_fullwrite(int, const void *, size_t);
#ifndef HX_HEXDUMP_DECLARATION
#define HX_HEXDUMP_DECLARATION 1
-extern void HX_hexdump(FILE *, const void *, unsigned int);
+extern void HX_hexdump(FILE *, const void *, size_t);
#endif
#ifdef __cplusplus
diff --git a/include/libHX/list.h b/include/libHX/list.h
index f226bec..fc43e20 100644
--- a/include/libHX/list.h
+++ b/include/libHX/list.h
@@ -55,6 +55,12 @@ static __inline__ void HXlist_del(struct HXlist_head *entry)
entry->next->prev = entry->prev;
entry->next = NULL;
entry->prev = NULL;
+ /*
+ * The node is now not connected to any (true) list head, so setting
+ * ``entry->next = entry;`` does not make much sense. You can call
+ * HXlist_init if needed, and the compiler will optimize the extraneous
+ * assignemtns from HXlist_del away.
+ */
}
static __inline__ bool HXlist_empty(const struct HXlist_head *head)
@@ -104,7 +110,7 @@ struct HXclist_head {
struct HXlist_head *next, *prev;
};
};
- unsigned int items;
+ size_t items;
};
#define HXCLIST_HEAD_INIT(name) {{{&(name).list, &(name).list}}, 0}
diff --git a/include/libHX/map.h b/include/libHX/map.h
index ecbf703..d6e7a0c 100644
--- a/include/libHX/map.h
+++ b/include/libHX/map.h
@@ -73,7 +73,9 @@ struct HXmap_trav;
* @flags: flags for this map
*/
struct HXmap {
- unsigned int items, flags;
+ size_t items;
+ unsigned int flags;
+ /* extended by HXmap_private, check it too */
};
struct HXmap_ops {
diff --git a/include/libHX/misc.h b/include/libHX/misc.h
index ac381dc..b2d5de8 100644
--- a/include/libHX/misc.h
+++ b/include/libHX/misc.h
@@ -63,7 +63,7 @@ extern float HX_flprf(float, float);
extern double HX_flpr(double, double);
#ifndef HX_HEXDUMP_DECLARATION
#define HX_HEXDUMP_DECLARATION 1
-extern void HX_hexdump(FILE *, const void *, unsigned int);
+extern void HX_hexdump(FILE *, const void *, size_t);
#endif
extern bool HX_timespec_isneg(const struct timespec *);
extern struct timespec *HX_timespec_neg(struct timespec *,
@@ -104,16 +104,6 @@ static __inline__ unsigned int HX_zveclen(const char *const *args)
#ifdef __cplusplus
} /* extern "C" */
-
-extern "C++" {
-
-template<typename type> static __inline__ type
-HX_dlsym(void *handle, const char *symbol)
-{
- return reinterpret_cast<type>(HX_dlsym(handle, symbol));
-}
-
-} /* extern "C++" */
#endif
#endif /* _LIBHX_MISC_H */
diff --git a/include/libHX/option.h b/include/libHX/option.h
index ef9c626..9eff6a9 100644
--- a/include/libHX/option.h
+++ b/include/libHX/option.h
@@ -28,12 +28,9 @@ extern struct HXformat_map *HXformat_init(void);
extern void HXformat_free(struct HXformat_map *);
extern int HXformat_add(struct HXformat_map *, const char *, const void *,
unsigned int);
-#define HXformat_aprintf(a, b, c) HXformat3_aprintf((a), (b), (c))
-#define HXformat_fprintf(a, b, c) HXformat3_fprintf((a), (b), (c))
-#define HXformat_sprintf(a, b, c, d) HXformat3_sprintf((a), (b), (c), (d))
-extern ssize_t HXformat3_aprintf(const struct HXformat_map *, hxmc_t **, const char *);
-extern ssize_t HXformat3_fprintf(const struct HXformat_map *, FILE *, const char *);
-extern ssize_t HXformat3_sprintf(const struct HXformat_map *, char *, size_t, const char *);
+extern ssize_t HXformat_aprintf(const struct HXformat_map *, hxmc_t **, const char *);
+extern ssize_t HXformat_fprintf(const struct HXformat_map *, FILE *, const char *);
+extern ssize_t HXformat_sprintf(const struct HXformat_map *, char *, size_t, const char *);
/*
* OPT.C
@@ -60,7 +57,7 @@ extern ssize_t HXformat3_sprintf(const struct HXformat_map *, char *, size_t, co
* %HXTYPE_FLOAT: [fo] (float *) Read a floating point number
* %HXTYPE_DOUBLE: [fo] (double *) Read a floating point number
* %HXTYPE_STRING: [fo] (char **) Any string.
- * %HXTYPE_STRP: [f-] (const char *const *) A string.
+ * %HXTYPE_STRP: [fo] (const char *const *) A string.
* %HXTYPE_STRDQ: [-o] (struct HXdeque *) A string.
* %HXTYPE_UINT8: [-o] (uint8_t *) An integer.
* %HXTYPE_UINT16: [-o] (uint8_t *) An integer.
@@ -135,24 +132,32 @@ enum {
};
/**
- * Flags (4th arg) to HX_getopt.
- * %HXOPT_PTHRU: pass-through unknown options to new argv
- * %HXOPT_DESTROY_OLD: destroy old argv after parsing is successful
+ * Flags to HX_getopt.
* %HXOPT_QUIET: do not output any warnings to stderr
* %HXOPT_HELPONERR: print out help when a parsing error occurs
* %HXOPT_USAGEONERR: print out short usage when a parsing error occurs
- * %HXOPT_RQ_ORDER: require option order/POSIX mode:
- * first non-option terminates option processing
- * %HXOPT_KEEP_ARGV: do not replace argc/argv at all
+ * %HXOPT_RQ_ORDER: Options and non-options must not be mixed (first
+ * non-option stops parsing) and the environment variable
+ * POSIXLY_CORRECT is ignored.
+ * %HXOPT_ANY_ORDER: Options and non-options may be mixed and the
+ * environment variable POSIXLY_CORRECT is ignored.
+ * %HXOPT_CONST_INPUT: User declaration that elements in input argv can NOT
+ * be reordered by the parser.
+ * %HXOPT_ITER_OPTS: (HX_getopt6 only) Populate result.desc and .oarg.
+ * %HXOPT_ITER_ARGS: (HX_getopt6 only) Populate result.uarg.
+ * %HXOPT_DUP_ARGS: (HX_getopt6 only) Populate result.dup_argv.
*/
enum {
- HXOPT_PTHRU = 1 << 0,
- HXOPT_DESTROY_OLD = 1 << 1,
- HXOPT_QUIET = 1 << 2,
- HXOPT_HELPONERR = 1 << 3,
- HXOPT_USAGEONERR = 1 << 4,
- HXOPT_RQ_ORDER = 1 << 5,
- HXOPT_KEEP_ARGV = 1 << 6,
+ HXOPT_QUIET = 0x4U,
+ HXOPT_HELPONERR = 0x8U,
+ HXOPT_USAGEONERR = 0x10U,
+ HXOPT_RQ_ORDER = 0x20U,
+ HXOPT_ANY_ORDER = 0x80U,
+ HXOPT_CONST_INPUT = 0x100U,
+ HXOPT_ITER_OPTS = 0x200U,
+ HXOPT_ITER_ARGS = 0x400U,
+ HXOPT_ITER_OA = HXOPT_ITER_OPTS | HXOPT_ITER_ARGS,
+ HXOPT_DUP_ARGS = 0x800U,
};
/**
@@ -162,6 +167,7 @@ enum {
* %HXOPT_ERR_VOID: long option takes no value
* %HXOPT_ERR_MIS: option requires a value argument
* %HXOPT_ERR_AMBIG: long option abbreviation was ambiguous
+ * %HXOPT_ERR_FLAGS: illegal flag combination (API misuse)
*/
enum {
HXOPT_ERR_SUCCESS = 0,
@@ -169,6 +175,7 @@ enum {
HXOPT_ERR_VOID,
HXOPT_ERR_MIS,
HXOPT_ERR_AMBIG,
+ HXOPT_ERR_FLAGS,
};
/**
@@ -229,13 +236,28 @@ struct HXoption {
const char *help, *htyp;
};
-#ifndef LIBHX_ZVECFREE_DECLARATION
-#define LIBHX_ZVECFREE_DECLARATION
-extern void HX_zvecfree(char **);
-#endif
-extern int HX_getopt(const struct HXoption *, int *, char ***, unsigned int);
-extern int HX_getopt5(const struct HXoption *, char **argv, int *nargc, char ***nargv, unsigned int flags);
-#define HX_getopt(a, b, c, d) HX_getopt((a), (b), const_cast3(char ***, (c)), (d))
+/**
+ * @nopts: Number of options found.
+ * @nargs: Number of non-option arguments found.
+ * @desc: Under %HXOPT_ITER_OPTS, filled with pointers to options, else %nullptr.
+ * @oarg: Under %HXOPT_ITER_OPTS, filled with pointers to optargs, else %nullptr.
+ * @uarg: Under %HXOPT_ITER_ARGS, filled with pointers to non-opt args
+ * (always orig_argv, never dup_argv), else %nullptr.
+ * @dup_argc: String count for dup_argv.
+ * @dup_argv: Filled with copies of non-option arguments if %HXOPT_DUP_ARGS.
+ * dup_argv[0] will be the program name (useful for feeding to
+ * another HX_getopt6 call).
+ */
+struct HXopt6_result {
+ int nopts, nargs;
+ const struct HXoption **desc;
+ char **oarg, **uarg;
+ int dup_argc;
+ char **dup_argv;
+};
+
+extern int HX_getopt6(const struct HXoption *, int, char **argv, struct HXopt6_result *, unsigned int flags);
+extern void HX_getopt6_clean(struct HXopt6_result *);
extern void HX_getopt_help(const struct HXoptcb *, FILE *);
extern void HX_getopt_help_cb(const struct HXoptcb *);
extern void HX_getopt_usage(const struct HXoptcb *, FILE *);
@@ -265,6 +287,20 @@ extern void HX_shconfig_free(const struct HXoption *);
{"usage", 0, HXTYPE_NONE, NULL, NULL, HX_getopt_usage_cb, \
0, "Display brief usage message"}
# define HXOPT_TABLEEND {NULL, 0, HXTYPE_XSNTMARK}
+
+struct HXopt6_auto_result : public HXopt6_result {
+ HXopt6_auto_result() : HXopt6_result() {}
+ ~HXopt6_auto_result() { HX_getopt6_clean(this); }
+ /*
+ * Unlike the unique_tie class, no operator~ is provided for
+ * HXopt6_auto_result, because reusing a result is not outright
+ * possible;
+ * auto ret = HX_getopt6(&table, argc, argv, &result, HXOPT_ITER_ARGS);
+ * ret = HX_getopt6(&table, result.nargs, result.uarg, &~result, HXOPT_ITER_ARGS):
+ * would kill off result before nargs/uarg is loaded.
+ */
+};
+
#endif
#endif /* _LIBHX_OPTION_H */
diff --git a/include/libHX/scope.hpp b/include/libHX/scope.hpp
new file mode 100644
index 0000000..0c0c70d
--- /dev/null
+++ b/include/libHX/scope.hpp
@@ -0,0 +1,35 @@
+#pragma once
+#include <exception>
+#include <utility>
+
+namespace HX {
+
+/*
+ * Modeled upon the C++ standards proposal P0052r10 / Library Fundamentals v3.
+ * Not yet present in GNU stdlibc++ or clang libc++.
+ */
+template<typename F> class scope_exit {
+ private:
+ F m_func;
+ bool m_eod = false;
+
+ public:
+ explicit scope_exit(F &&f) : m_func(std::move(f)), m_eod(true) {}
+ scope_exit(scope_exit &&o) : m_func(std::move(o.m_func)), m_eod(o.m_eod) {
+ o.m_eod = false;
+ }
+ ~scope_exit() try {
+ if (m_eod)
+ m_func();
+ } catch (...) {
+ }
+ void operator=(scope_exit &&) = delete;
+ void release() noexcept { m_eod = false; }
+};
+
+template<typename F> scope_exit<F> make_scope_exit(F &&f)
+{
+ return scope_exit<F>(std::move(f));
+}
+
+} /* namespace */
diff --git a/include/libHX/string.h b/include/libHX/string.h
index 4da3619..707a2a9 100644
--- a/include/libHX/string.h
+++ b/include/libHX/string.h
@@ -26,8 +26,6 @@ enum {
HXQUOTE_LDAPRDN,
HXQUOTE_BASE64,
HXQUOTE_URIENC,
- HXQUOTE_SQLSQUOTE,
- HXQUOTE_SQLBQUOTE,
HXQUOTE_BASE64URL,
HXQUOTE_BASE64IMAP,
_HXQUOTE_MAX,
@@ -63,6 +61,10 @@ extern hxmc_t *HXmc_memins(hxmc_t **, size_t, const void *, size_t);
extern hxmc_t *HXmc_memdel(hxmc_t *, size_t, size_t);
extern void HXmc_free(hxmc_t *);
extern void HXmc_zvecfree(hxmc_t **);
+#ifndef LIBHX_ZVECFREE_DECLARATION
+#define LIBHX_ZVECFREE_DECLARATION
+extern void HX_zvecfree(char **);
+#endif
/*
* STRING.C
@@ -87,15 +89,12 @@ extern char *HX_strlcpy(char *, const char *, size_t);
extern char *HX_strlncat(char *, const char *, size_t, size_t);
extern char *HX_strlower(char *);
extern size_t HX_strltrim(char *);
-extern char *HX_stpltrim(const char *);
extern char *HX_strmid(const char *, long, long);
extern char *HX_strndup(const char *, size_t);
-extern size_t HX_strnlen(const char *, size_t);
extern char *HX_strquote(const char *, unsigned int, char **);
extern size_t HX_strrcspn(const char *, const char *);
extern char *HX_strrev(char *);
extern size_t HX_strrtrim(char *);
-extern char *HX_strsep(char **, const char *);
extern char *HX_strsep2(char **, const char *);
extern char *HX_strupper(char *);
extern double HX_strtod_unit(const char *, char **, unsigned int exponent);
@@ -104,6 +103,7 @@ extern char *HX_unit_size(char *out, size_t bufsize, unsigned long long size, un
extern char *HX_unit_size_cu(char *out, size_t bufsize, unsigned long long size, unsigned int divisor);
extern unsigned long long HX_strtoull_sec(const char *s, char **);
extern unsigned long long HX_strtoull_nsec(const char *s, char **);
+extern unsigned long long HX_strtoull8601p_sec(const char *s, char **);
extern char *HX_unit_seconds(char *out, size_t bufsize, unsigned long long seconds, unsigned int flags);
static __inline__ void *HX_memdup(const void *buf, size_t len)
@@ -118,16 +118,4 @@ static __inline__ void *HX_memdup(const void *buf, size_t len)
} /* extern "C" */
#endif
-#ifdef __cplusplus
-extern "C++" {
-
-template<typename type> static __inline__ type
-HX_memdup(const void *data, size_t n)
-{
- return reinterpret_cast<type>(HX_memdup(data, n));
-}
-
-} /* extern "C++" */
-#endif
-
#endif /* _LIBHX_STRING_H */