diff options
Diffstat (limited to 'include')
| -rw-r--r-- | include/Makefile.am | 6 | ||||
| -rw-r--r-- | include/Makefile.in | 33 | ||||
| -rw-r--r-- | include/libHX/ctype_helper.h | 5 | ||||
| -rw-r--r-- | include/libHX/defs.h | 12 | ||||
| -rw-r--r-- | include/libHX/deque.h | 38 | ||||
| -rw-r--r-- | include/libHX/endian.h | 202 | ||||
| -rw-r--r-- | include/libHX/endian_float.h | 107 | ||||
| -rw-r--r-- | include/libHX/io.h | 3 | ||||
| -rw-r--r-- | include/libHX/list.h | 8 | ||||
| -rw-r--r-- | include/libHX/map.h | 4 | ||||
| -rw-r--r-- | include/libHX/misc.h | 12 | ||||
| -rw-r--r-- | include/libHX/option.h | 90 | ||||
| -rw-r--r-- | include/libHX/scope.hpp | 35 | ||||
| -rw-r--r-- | include/libHX/string.h | 22 |
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 */ |
