summaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
authorJörg Frings-Fürst <debian@jff-webhosting.net>2022-10-24 21:04:00 +0200
committerJörg Frings-Fürst <debian@jff-webhosting.net>2022-10-24 21:04:00 +0200
commit3422d8db505630a70bc89a4eee7db927b8e5ec2f (patch)
treef0c6e1ba7db9991f2bd38c9169f9921bfe5e61d8 /doc
parentdf5167db909a88fb8e16dd20b37442495a6ac059 (diff)
parentaab49e5a013c53ae812a143fe41add74e0677a61 (diff)
Merge branch 'feature/upstream' into develop
Diffstat (limited to 'doc')
-rw-r--r--doc/.gitignore2
-rw-r--r--doc/Makefile.am16
-rw-r--r--doc/Makefile.in518
-rw-r--r--doc/api.rst374
-rw-r--r--doc/api.txt353
-rw-r--r--doc/bitmaps.rst49
-rw-r--r--doc/changelog.rst140
-rw-r--r--doc/changelog.txt556
-rw-r--r--doc/dirstamp.rst7
-rw-r--r--doc/dirstamp.txt4
-rw-r--r--doc/files_and_dirs.rst190
-rwxr-xr-xdoc/generate19
-rw-r--r--doc/helper_headers.rst128
-rw-r--r--doc/history.rst22
-rw-r--r--doc/init.rst17
-rw-r--r--doc/inline_clist.rst59
-rw-r--r--doc/inline_list.rst253
-rw-r--r--doc/install.rst50
-rw-r--r--doc/libHX_Documentation.lyx24663
-rw-r--r--doc/libHX_Documentation.pdfbin522656 -> 0 bytes
-rw-r--r--doc/libHX_Documentation.rst142
-rw-r--r--doc/linked_list.rst171
-rw-r--r--doc/macros.rst149
-rw-r--r--doc/maps.rst525
-rw-r--r--doc/memory_container.rst197
-rw-r--r--doc/misc_functions.rst35
-rw-r--r--doc/option_parsing.rst587
-rw-r--r--doc/process_management.rst233
-rw-r--r--doc/random_numbers.rst32
-rw-r--r--doc/shconfig.rst116
-rw-r--r--doc/slurp.c38
-rw-r--r--doc/socket_functions.rst16
-rw-r--r--doc/string_formatter.rst210
-rw-r--r--doc/string_ops.rst569
-rw-r--r--doc/strlcpy-timing.rst111
-rw-r--r--doc/strlcpy-timing.txt109
-rw-r--r--doc/time_functions.rst125
-rw-r--r--doc/typecheck_casts.rst178
-rw-r--r--doc/ux-file.rst31
-rw-r--r--doc/ux-file.txt30
-rw-r--r--doc/ux-mmap.rst27
-rw-r--r--doc/ux-mmap.txt26
42 files changed, 4743 insertions, 26334 deletions
diff --git a/doc/.gitignore b/doc/.gitignore
deleted file mode 100644
index 2789f42..0000000
--- a/doc/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-*.lyx~
-*.pdf
diff --git a/doc/Makefile.am b/doc/Makefile.am
deleted file mode 100644
index 14eba9f..0000000
--- a/doc/Makefile.am
+++ /dev/null
@@ -1,16 +0,0 @@
-# -*- Makefile -*-
-
-if BUILD_DOCS
-dist_doc_DATA = libHX_Documentation.pdf
-endif
-
-libHX_Documentation.pdf: libHX_Documentation.lyx
- srcdir="${srcdir}" ${srcdir}/generate;
-
-EXTRA_DIST = libHX_Documentation.lyx api.txt changelog.txt
-
-install-data-local:
- if test -e libHX_Documentation.pdf; then \
- ${MKDIR_P} "${DESTDIR}${docdir}" || exit 1; \
- ${INSTALL_DATA} libHX_Documentation.pdf "${DESTDIR}${docdir}" || exit $$?; \
- fi
diff --git a/doc/Makefile.in b/doc/Makefile.in
deleted file mode 100644
index e3d240c..0000000
--- a/doc/Makefile.in
+++ /dev/null
@@ -1,518 +0,0 @@
-# Makefile.in generated by automake 1.15.1 from Makefile.am.
-# @configure_input@
-
-# Copyright (C) 1994-2017 Free Software Foundation, Inc.
-
-# This Makefile.in is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
-# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-# PARTICULAR PURPOSE.
-
-@SET_MAKE@
-
-# -*- Makefile -*-
-
-VPATH = @srcdir@
-am__is_gnu_make = { \
- if test -z '$(MAKELEVEL)'; then \
- false; \
- elif test -n '$(MAKE_HOST)'; then \
- true; \
- elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
- true; \
- else \
- false; \
- fi; \
-}
-am__make_running_with_option = \
- case $${target_option-} in \
- ?) ;; \
- *) echo "am__make_running_with_option: internal error: invalid" \
- "target option '$${target_option-}' specified" >&2; \
- exit 1;; \
- esac; \
- has_opt=no; \
- sane_makeflags=$$MAKEFLAGS; \
- if $(am__is_gnu_make); then \
- sane_makeflags=$$MFLAGS; \
- else \
- case $$MAKEFLAGS in \
- *\\[\ \ ]*) \
- bs=\\; \
- sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
- | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
- esac; \
- fi; \
- skip_next=no; \
- strip_trailopt () \
- { \
- flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
- }; \
- for flg in $$sane_makeflags; do \
- test $$skip_next = yes && { skip_next=no; continue; }; \
- case $$flg in \
- *=*|--*) continue;; \
- -*I) strip_trailopt 'I'; skip_next=yes;; \
- -*I?*) strip_trailopt 'I';; \
- -*O) strip_trailopt 'O'; skip_next=yes;; \
- -*O?*) strip_trailopt 'O';; \
- -*l) strip_trailopt 'l'; skip_next=yes;; \
- -*l?*) strip_trailopt 'l';; \
- -[dEDm]) skip_next=yes;; \
- -[JT]) skip_next=yes;; \
- esac; \
- case $$flg in \
- *$$target_option*) has_opt=yes; break;; \
- esac; \
- done; \
- 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))
-pkgdatadir = $(datadir)/@PACKAGE@
-pkgincludedir = $(includedir)/@PACKAGE@
-pkglibdir = $(libdir)/@PACKAGE@
-pkglibexecdir = $(libexecdir)/@PACKAGE@
-am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
-install_sh_DATA = $(install_sh) -c -m 644
-install_sh_PROGRAM = $(install_sh) -c
-install_sh_SCRIPT = $(install_sh) -c
-INSTALL_HEADER = $(INSTALL_DATA)
-transform = $(program_transform_name)
-NORMAL_INSTALL = :
-PRE_INSTALL = :
-POST_INSTALL = :
-NORMAL_UNINSTALL = :
-PRE_UNINSTALL = :
-POST_UNINSTALL = :
-build_triplet = @build@
-host_triplet = @host@
-subdir = doc
-ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4/gcc4_visibility.m4 \
- $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
- $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
- $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
-am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
- $(ACLOCAL_M4)
-DIST_COMMON = $(srcdir)/Makefile.am $(am__dist_doc_DATA_DIST) \
- $(am__DIST_COMMON)
-mkinstalldirs = $(install_sh) -d
-CONFIG_HEADER = $(top_builddir)/config.h
-CONFIG_CLEAN_FILES =
-CONFIG_CLEAN_VPATH_FILES =
-AM_V_P = $(am__v_P_@AM_V@)
-am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
-am__v_P_0 = false
-am__v_P_1 = :
-AM_V_GEN = $(am__v_GEN_@AM_V@)
-am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
-am__v_GEN_0 = @echo " GEN " $@;
-am__v_GEN_1 =
-AM_V_at = $(am__v_at_@AM_V@)
-am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
-am__v_at_0 = @
-am__v_at_1 =
-SOURCES =
-DIST_SOURCES =
-am__can_run_installinfo = \
- case $$AM_UPDATE_INFO_DIR in \
- n|no|NO) false;; \
- *) (install-info --version) >/dev/null 2>&1;; \
- esac
-am__dist_doc_DATA_DIST = libHX_Documentation.pdf
-am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
-am__vpath_adj = case $$p in \
- $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
- *) f=$$p;; \
- esac;
-am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
-am__install_max = 40
-am__nobase_strip_setup = \
- srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
-am__nobase_strip = \
- for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
-am__nobase_list = $(am__nobase_strip_setup); \
- for p in $$list; do echo "$$p $$p"; done | \
- sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
- $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
- if (++n[$$2] == $(am__install_max)) \
- { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
- END { for (dir in files) print dir, files[dir] }'
-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; }; \
- }
-am__installdirs = "$(DESTDIR)$(docdir)"
-DATA = $(dist_doc_DATA)
-am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
-am__DIST_COMMON = $(srcdir)/Makefile.in
-DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
-ACLOCAL = @ACLOCAL@
-AMTAR = @AMTAR@
-AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
-AR = @AR@
-AUTOCONF = @AUTOCONF@
-AUTOHEADER = @AUTOHEADER@
-AUTOMAKE = @AUTOMAKE@
-AWK = @AWK@
-CC = @CC@
-CCDEPMODE = @CCDEPMODE@
-CFLAGS = @CFLAGS@
-CPP = @CPP@
-CPPFLAGS = @CPPFLAGS@
-CXX = @CXX@
-CXXCPP = @CXXCPP@
-CXXDEPMODE = @CXXDEPMODE@
-CXXFLAGS = @CXXFLAGS@
-CYGPATH_W = @CYGPATH_W@
-DEFS = @DEFS@
-DEPDIR = @DEPDIR@
-DLLTOOL = @DLLTOOL@
-DSYMUTIL = @DSYMUTIL@
-DUMPBIN = @DUMPBIN@
-ECHO_C = @ECHO_C@
-ECHO_N = @ECHO_N@
-ECHO_T = @ECHO_T@
-EGREP = @EGREP@
-EXEEXT = @EXEEXT@
-FGREP = @FGREP@
-GREP = @GREP@
-INSTALL = @INSTALL@
-INSTALL_DATA = @INSTALL_DATA@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@
-INSTALL_SCRIPT = @INSTALL_SCRIPT@
-INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
-LD = @LD@
-LDFLAGS = @LDFLAGS@
-LIBOBJS = @LIBOBJS@
-LIBS = @LIBS@
-LIBTOOL = @LIBTOOL@
-LIPO = @LIPO@
-LN_S = @LN_S@
-LTLIBOBJS = @LTLIBOBJS@
-LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
-LYX = @LYX@
-MAKEINFO = @MAKEINFO@
-MANIFEST_TOOL = @MANIFEST_TOOL@
-MKDIR_P = @MKDIR_P@
-NM = @NM@
-NMEDIT = @NMEDIT@
-OBJDUMP = @OBJDUMP@
-OBJEXT = @OBJEXT@
-OTOOL = @OTOOL@
-OTOOL64 = @OTOOL64@
-PACKAGE = @PACKAGE@
-PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
-PACKAGE_NAME = @PACKAGE_NAME@
-PACKAGE_STRING = @PACKAGE_STRING@
-PACKAGE_TARNAME = @PACKAGE_TARNAME@
-PACKAGE_URL = @PACKAGE_URL@
-PACKAGE_VERSION = @PACKAGE_VERSION@
-PATH_SEPARATOR = @PATH_SEPARATOR@
-RANLIB = @RANLIB@
-SED = @SED@
-SET_MAKE = @SET_MAKE@
-SHELL = @SHELL@
-STRIP = @STRIP@
-VERSION = @VERSION@
-abs_builddir = @abs_builddir@
-abs_srcdir = @abs_srcdir@
-abs_top_builddir = @abs_top_builddir@
-abs_top_srcdir = @abs_top_srcdir@
-ac_ct_AR = @ac_ct_AR@
-ac_ct_CC = @ac_ct_CC@
-ac_ct_CXX = @ac_ct_CXX@
-ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
-am__include = @am__include@
-am__leading_dot = @am__leading_dot@
-am__quote = @am__quote@
-am__tar = @am__tar@
-am__untar = @am__untar@
-bindir = @bindir@
-build = @build@
-build_alias = @build_alias@
-build_cpu = @build_cpu@
-build_os = @build_os@
-build_vendor = @build_vendor@
-builddir = @builddir@
-datadir = @datadir@
-datarootdir = @datarootdir@
-docdir = @docdir@
-dvidir = @dvidir@
-exec_prefix = @exec_prefix@
-host = @host@
-host_alias = @host_alias@
-host_cpu = @host_cpu@
-host_os = @host_os@
-host_vendor = @host_vendor@
-htmldir = @htmldir@
-includedir = @includedir@
-infodir = @infodir@
-install_sh = @install_sh@
-libdir = @libdir@
-libdl_LIBS = @libdl_LIBS@
-libexecdir = @libexecdir@
-libpthread_LIBS = @libpthread_LIBS@
-librt_LIBS = @librt_LIBS@
-libsocket_LIBS = @libsocket_LIBS@
-localedir = @localedir@
-localstatedir = @localstatedir@
-mandir = @mandir@
-mkdir_p = @mkdir_p@
-oldincludedir = @oldincludedir@
-pdfdir = @pdfdir@
-pkgconfigdir = @pkgconfigdir@
-prefix = @prefix@
-program_transform_name = @program_transform_name@
-psdir = @psdir@
-regular_CFLAGS = @regular_CFLAGS@
-regular_CPPFLAGS = @regular_CPPFLAGS@
-regular_CXXFLAGS = @regular_CXXFLAGS@
-sbindir = @sbindir@
-sharedstatedir = @sharedstatedir@
-srcdir = @srcdir@
-sysconfdir = @sysconfdir@
-target_alias = @target_alias@
-top_build_prefix = @top_build_prefix@
-top_builddir = @top_builddir@
-top_srcdir = @top_srcdir@
-@BUILD_DOCS_TRUE@dist_doc_DATA = libHX_Documentation.pdf
-EXTRA_DIST = libHX_Documentation.lyx api.txt changelog.txt
-all: all-am
-
-.SUFFIXES:
-$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
- @for dep in $?; do \
- case '$(am__configure_deps)' in \
- *$$dep*) \
- ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
- && { if test -f $@; then exit 0; else break; fi; }; \
- exit 1;; \
- esac; \
- done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign doc/Makefile'; \
- $(am__cd) $(top_srcdir) && \
- $(AUTOMAKE) --foreign doc/Makefile
-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
- @case '$?' in \
- *config.status*) \
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
- *) \
- echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
- cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
- esac;
-
-$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-
-$(top_srcdir)/configure: $(am__configure_deps)
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-$(ACLOCAL_M4): $(am__aclocal_m4_deps)
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-$(am__aclocal_m4_deps):
-
-mostlyclean-libtool:
- -rm -f *.lo
-
-clean-libtool:
- -rm -rf .libs _libs
-install-dist_docDATA: $(dist_doc_DATA)
- @$(NORMAL_INSTALL)
- @list='$(dist_doc_DATA)'; test -n "$(docdir)" || list=; \
- if test -n "$$list"; then \
- echo " $(MKDIR_P) '$(DESTDIR)$(docdir)'"; \
- $(MKDIR_P) "$(DESTDIR)$(docdir)" || exit 1; \
- fi; \
- for p in $$list; do \
- if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
- echo "$$d$$p"; \
- done | $(am__base_list) | \
- while read files; do \
- echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(docdir)'"; \
- $(INSTALL_DATA) $$files "$(DESTDIR)$(docdir)" || exit $$?; \
- done
-
-uninstall-dist_docDATA:
- @$(NORMAL_UNINSTALL)
- @list='$(dist_doc_DATA)'; test -n "$(docdir)" || list=; \
- files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
- dir='$(DESTDIR)$(docdir)'; $(am__uninstall_files_from_dir)
-tags TAGS:
-
-ctags CTAGS:
-
-cscope cscopelist:
-
-
-distdir: $(DISTFILES)
- @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
- topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
- list='$(DISTFILES)'; \
- dist_files=`for file in $$list; do echo $$file; done | \
- sed -e "s|^$$srcdirstrip/||;t" \
- -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
- case $$dist_files in \
- */*) $(MKDIR_P) `echo "$$dist_files" | \
- sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
- sort -u` ;; \
- esac; \
- for file in $$dist_files; do \
- if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
- if test -d $$d/$$file; then \
- dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
- if test -d "$(distdir)/$$file"; then \
- find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
- fi; \
- if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
- cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
- find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
- fi; \
- cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
- else \
- test -f "$(distdir)/$$file" \
- || cp -p $$d/$$file "$(distdir)/$$file" \
- || exit 1; \
- fi; \
- done
-check-am: all-am
-check: check-am
-all-am: Makefile $(DATA)
-installdirs:
- for dir in "$(DESTDIR)$(docdir)"; do \
- test -z "$$dir" || $(MKDIR_P) "$$dir"; \
- done
-install: install-am
-install-exec: install-exec-am
-install-data: install-data-am
-uninstall: uninstall-am
-
-install-am: all-am
- @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
-
-installcheck: installcheck-am
-install-strip:
- if test -z '$(STRIP)'; then \
- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
- install; \
- else \
- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
- "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
- fi
-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)
-
-maintainer-clean-generic:
- @echo "This command is intended for maintainers to use"
- @echo "it deletes files that may require special tools to rebuild."
-clean: clean-am
-
-clean-am: clean-generic clean-libtool mostlyclean-am
-
-distclean: distclean-am
- -rm -f Makefile
-distclean-am: clean-am distclean-generic
-
-dvi: dvi-am
-
-dvi-am:
-
-html: html-am
-
-html-am:
-
-info: info-am
-
-info-am:
-
-install-data-am: install-data-local install-dist_docDATA
-
-install-dvi: install-dvi-am
-
-install-dvi-am:
-
-install-exec-am:
-
-install-html: install-html-am
-
-install-html-am:
-
-install-info: install-info-am
-
-install-info-am:
-
-install-man:
-
-install-pdf: install-pdf-am
-
-install-pdf-am:
-
-install-ps: install-ps-am
-
-install-ps-am:
-
-installcheck-am:
-
-maintainer-clean: maintainer-clean-am
- -rm -f Makefile
-maintainer-clean-am: distclean-am maintainer-clean-generic
-
-mostlyclean: mostlyclean-am
-
-mostlyclean-am: mostlyclean-generic mostlyclean-libtool
-
-pdf: pdf-am
-
-pdf-am:
-
-ps: ps-am
-
-ps-am:
-
-uninstall-am: uninstall-dist_docDATA
-
-.MAKE: install-am install-strip
-
-.PHONY: all all-am check check-am clean clean-generic clean-libtool \
- cscopelist-am ctags-am distclean distclean-generic \
- distclean-libtool distdir dvi dvi-am html html-am info info-am \
- install install-am install-data install-data-am \
- install-data-local install-dist_docDATA install-dvi \
- install-dvi-am install-exec install-exec-am install-html \
- install-html-am install-info install-info-am install-man \
- install-pdf install-pdf-am install-ps install-ps-am \
- install-strip installcheck installcheck-am installdirs \
- maintainer-clean maintainer-clean-generic mostlyclean \
- mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
- tags-am uninstall uninstall-am uninstall-dist_docDATA
-
-.PRECIOUS: Makefile
-
-
-libHX_Documentation.pdf: libHX_Documentation.lyx
- srcdir="${srcdir}" ${srcdir}/generate;
-
-install-data-local:
- if test -e libHX_Documentation.pdf; then \
- ${MKDIR_P} "${DESTDIR}${docdir}" || exit 1; \
- ${INSTALL_DATA} libHX_Documentation.pdf "${DESTDIR}${docdir}" || exit $$?; \
- fi
-
-# 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:
diff --git a/doc/api.rst b/doc/api.rst
new file mode 100644
index 0000000..deb815f
--- /dev/null
+++ b/doc/api.rst
@@ -0,0 +1,374 @@
+Function reference
+==================
+
+* R column: Recommend version number to use in ``PKG_CONFIG_CHECK`` in
+ projects using libHX. Includes important bugfixes.
+* M column: Lowest possible version with the same function signature.
+* F column: Function first seen in version, possibly with different API.
+
+====== ====== ====== ========================================
+RMV MinVer FirstA Name
+====== ====== ====== ========================================
+4.7 4.7 4.7 HXQUOTE_BASE64IMAP
+4.7 4.7 4.7 HXQUOTE_BASE64URL
+4.3 4.3 4.3 HX_unit_seconds
+4.3 4.3 4.3 HX_strtoull_sec
+4.2 4.2 4.2 HX_unit_size
+4.2 4.2 4.2 HX_unit_size_cu
+4.2 4.2 4.2 HX_strtod_unit
+4.2 4.2 4.2 HX_strtoull_unit
+3.27 3.27 3.27 HXOPT_KEEP_ARGV
+3.27 3.27 3.27 HXproc_top_fd
+3.27 3.27 3.27 HXproc_switch_user
+3.27 3.27 3.27 HXPROC_SU_SUCCESS
+3.27 3.27 3.27 HXPROC_SU_NOOP
+3.27 3.27 3.27 HXPROC_USER_NOT_FOUND
+3.27 3.27 3.27 HXPROC_GROUP_NOT_FOUND
+3.27 3.27 3.27 HXPROC_SETUID_FAILED
+3.27 3.27 3.27 HXPROC_SETGID_FAILED
+3.27 3.27 3.27 HXPROC_INITGROUPS_FAILED
+3.27 3.27 3.27 HX_slurp_fd
+3.27 3.27 3.27 HX_slurp_file
+3.25 3.25 3.25 HX_split_fixed
+3.25 3.25 3.25 HX_split_inplace
+3.22 3.22 3.22 HXQUOTE_SQLBQUOTE
+3.21 3.21 3.21 xml_getnsprop
+3.19 3.19 3.19 HXQUOTE_SQLSQUOTE
+3.18 3.18 3.18 HX_stpltrim
+3.17 3.17 3.17 HX_LONGLONG_FMT
+3.17 3.17 3.17 HX_SIZET_FMT
+3.16 3.16 3.16 container_of
+3.16 3.16 3.16 wxCDF
+3.16 3.16 3.16 wxDSPAN
+3.15 3.15 3.15 HXQUOTE_URIENC
+3.15 3.15 3.15 HX_strchr2
+3.13 3.13 3.13 DEMOTE_TO_PTR
+3.13 3.13 3.13 HXTYPE_SIZE_T
+3.13 3.13 3.13 HX_TIMESPEC_EXP
+3.13 3.13 3.13 HX_TIMESPEC_FMT
+3.13 3.13 3.13 HX_TIMEVAL_EXP
+3.13 3.13 3.13 HX_TIMEVAL_FMT
+3.13 3.13 3.13 HX_timespec_add
+3.13 3.13 3.13 HX_timespec_isneg
+3.13 3.13 3.13 HX_timespec_mul
+3.13 3.13 3.13 HX_timespec_mulf
+3.13 3.13 3.13 HX_timespec_neg
+3.13 3.13 3.13 HX_timespec_sub
+3.13 3.13 3.13 HX_timeval_sub
+3.12 3.12 1.10.0 HX_mkdir
+3.12 3.12 3.12 HX_strndup
+3.12 3.12 3.12 HX_strnlen
+3.12 3.0 3.0 HXMAP_CDATA
+3.12 3.0 3.0 HXMAP_CKEY
+3.12 3.0 3.0 HXMAP_SCDATA
+3.12 3.0 3.0 HXMAP_SCKEY
+3.12 3.0 3.0 HXMAP_SDATA
+3.12 3.0 3.0 HXMAP_SINGULAR
+3.12 3.0 3.0 HXMAP_SKEY
+3.12 3.12 3.12 HXOPT_ERR_SUCCESS
+3.12 3.12 3.12 HXOPT_ERR_SYS
+3.12 3.12 3.12 HXOPTCB_BY_LONG
+3.12 3.12 3.12 HXOPTCB_BY_SHORT
+3.12 3.0 1.10.0 HXformat_aprintf
+3.12 3.0 1.10.0 HXformat_fprintf
+3.12 3.0 1.10.0 HXformat_sprintf
+3.11 3.11 3.11 HXQUOTE_BASE64
+3.10 3.10 3.10 BUILD_BUG_ON_EXPR
+3.10 3.10 3.10 HX_readlink
+3.10 3.10 3.10 HX_realpath
+3.9.1 3.9 3.9 HXio_fullread
+3.9.1 3.9 3.9 HXio_fullwrite
+3.9 3.9 3.9 HXMAP_NONE
+3.7 3.7 3.7 HXlist_for_each_rev
+3.7 3.7 3.7 HXlist_for_each_rev_safe
+3.7 3.7 1.22 xml_newnode
+3.7 1.15 1.15 HXclist_pop
+3.7 1.15 1.15 HXclist_shift
+3.7 1.10.0 1.10.0 HX_ffs
+3.7 1.10.0 1.10.0 HX_zveclen
+3.7 1.10.0 1.10.0 HXdir_close
+3.7 1.10.0 1.10.0 HXdir_open
+3.7 1.10.0 1.10.0 HXdir_read
+3.6 3.6 3.1 HXbitmap_clear
+3.6 3.6 3.1 HXbitmap_set
+3.6 3.6 3.1 HXbitmap_test
+3.6 1.10.0 1.10.0 HX_split
+3.5 3.5 3.5 HXMAP_NOFLAGS
+3.5 3.5 3.5 HXQUOTE_LDAPFLT
+3.5 3.5 3.5 HXQUOTE_LDAPRDN
+3.5 3.5 3.5 HXSIZEOF_Z16
+3.5 2.2 2.2 HXproc_run_async
+3.5 2.2 2.2 HXproc_run_sync
+3.4 3.4 3.4 HX_exit
+3.4 3.4 3.4 HX_init
+3.4 3.4 3.4 HX_memmem
+3.4 3.4 3.4 HXlist_empty
+3.3 3.3 3.3 HX_drand
+3.3 3.3 3.3 HX_shconfig_map
+3.3 3.3 3.3 HXdeque_genocide2
+3.3 3.3 3.3 HXmc_zvecfree
+3.3 1.10.0 1.10.0 HX_shconfig
+3.3 1.10.0 1.10.0 HX_shconfig_pv
+3.2 3.2 3.2 HXQUOTE_DQUOTE
+3.2 3.2 3.2 HXQUOTE_HTML
+3.2 3.2 3.2 HXQUOTE_SQUOTE
+3.2 3.2 3.2 HXTYPE_MCSTR
+3.2 3.2 3.2 HX_strquote
+3.1 3.1 3.1 HXbitmap_size
+3.1 1.25 1.25 HXmc_strcpy
+3.0.1 3.0 3.0 HXmap_add
+3.0.1 3.0 3.0 HXmap_del
+3.0.1 3.0 3.0 HXmap_del<>
+3.0.1 3.0 3.0 HXmap_find
+3.0.1 3.0 3.0 HXmap_get
+3.0.1 3.0 3.0 HXmap_get<>
+3.0.1 3.0 3.0 HXmap_qfe
+3.0.1 3.0 3.0 HXmap_traverse
+3.0.1 3.0 3.0 HXmap_travinit
+3.0 3.0 3.0 HXMAPT_DEFAULT
+3.0 3.0 3.0 HXMAPT_HASH
+3.0 3.0 3.0 HXMAPT_ORDERED
+3.0 3.0 3.0 HXMAPT_RBTREE
+3.0 3.0 3.0 HXMAP_DTRAV
+3.0 3.0 3.0 HXMAP_NOREPLACE
+3.0 3.0 3.0 HXhash_djb2
+3.0 3.0 3.0 HXhash_jlookup3
+3.0 3.0 3.0 HXhash_jlookup3s
+3.0 3.0 3.0 HXmap_free
+3.0 3.0 3.0 HXmap_init
+3.0 3.0 3.0 HXmap_init5
+3.0 3.0 3.0 HXmap_keysvalues
+3.0 3.0 3.0 HXmap_travfree
+3.0 3.0 3.0 HXsizeof_member
+3.0 3.0 3.0 HXtypeof_member
+3.0 3.0 1.10.0 HXformat_add
+3.0 3.0 1.10.0 HXformat_free
+3.0 3.0 1.10.0 HXformat_init
+2.9 2.9 2.9 HX_basename_exact
+2.9 2.2 2.2 HX_split4
+2.9 1.10.0 1.10.0 HX_basename
+2.8 2.8 2.8 HXPROC_NULL_STDERR
+2.8 2.8 2.8 HXPROC_NULL_STDIN
+2.8 2.8 2.8 HXPROC_NULL_STDOUT
+2.6 2.6 2.6 HX_fls
+2.6 2.6 2.6 wxACV
+2.6 2.6 2.6 wxDPOS
+2.6 2.6 2.6 wxDSIZE
+2.6 2.6 2.6 wxfu8
+2.6 2.6 2.6 wxfv8
+2.6 2.6 2.6 wxtu8
+2.6 2.6 2.6 xml_strcasecmp
+2.3 1.25 1.25 HXmc_length
+2.2 2.2 2.2 HXPROC_A0
+2.2 2.2 2.2 HXPROC_EXECV
+2.2 2.2 2.2 HXPROC_STDERR
+2.2 2.2 2.2 HXPROC_STDIN
+2.2 2.2 2.2 HXPROC_STDOUT
+2.2 2.2 2.2 HXPROC_VERBOSE
+2.2 2.2 2.2 HXSIZEOF_Z32
+2.2 2.2 2.2 HXSIZEOF_Z64
+2.2 2.2 2.2 HX_STRINGIFY
+2.2 2.2 2.2 HXproc_wait
+2.2 2.0 2.0 const_cast1
+2.2 2.0 2.0 const_cast2
+2.2 2.0 2.0 const_cast3
+2.1 2.0 2.0 static_cast
+2.0 2.0 2.0 HX_isalnum
+2.0 2.0 2.0 HX_isalpha
+2.0 2.0 2.0 HX_isdigit
+2.0 2.0 2.0 HX_islower
+2.0 2.0 2.0 HX_isprint
+2.0 2.0 2.0 HX_isspace
+2.0 2.0 2.0 HX_isupper
+2.0 2.0 2.0 HX_isxdigit
+2.0 2.0 2.0 HX_tolower
+2.0 2.0 2.0 HX_toupper
+2.0 2.0 2.0 HXmc_setlen
+2.0 2.0 2.0 const_cast
+2.0 2.0 2.0 containerof
+2.0 2.0 2.0 reinterpret_cast
+2.0 2.0 2.0 signed_cast<>
+2.0 1.23 1.23 signed_cast
+2.0 1.10.0 1.10.0 HX_strmid
+1.28 1.28 1.28 HXTYPE_INT16
+1.28 1.28 1.28 HXTYPE_INT32
+1.28 1.28 1.28 HXTYPE_INT64
+1.28 1.28 1.28 HXTYPE_INT8
+1.28 1.28 1.28 HXTYPE_UINT16
+1.28 1.28 1.28 HXTYPE_UINT32
+1.28 1.28 1.28 HXTYPE_UINT64
+1.28 1.28 1.28 HXTYPE_UINT8
+1.26 1.26 1.26 HX_hexdump
+1.26 1.26 1.26 HX_time_compare
+1.25 1.25 1.25 HX_getl
+1.25 1.25 1.25 HXmc_free
+1.25 1.25 1.25 HXmc_memcat
+1.25 1.25 1.25 HXmc_memcpy
+1.25 1.25 1.25 HXmc_memdel
+1.25 1.25 1.25 HXmc_meminit
+1.25 1.25 1.25 HXmc_memins
+1.25 1.25 1.25 HXmc_mempcat
+1.25 1.25 1.25 HXmc_strcat
+1.25 1.25 1.25 HXmc_strinit
+1.25 1.25 1.25 HXmc_strins
+1.25 1.25 1.25 HXmc_strpcat
+1.25 1.25 1.25 HXmc_trunc
+1.23 1.23 1.23 ARRAY_SIZE
+1.23 1.23 1.23 BUILD_BUG_ON
+1.23 1.23 1.23 O_BINARY
+1.23 1.23 1.23 S_IRUGO
+1.23 1.23 1.23 S_IRWXUGO
+1.23 1.23 1.23 S_IWUGO
+1.23 1.23 1.23 S_IXUGO
+1.22 1.22 1.22 xml_getprop
+1.22 1.22 1.22 xml_newprop
+1.22 1.22 1.22 xml_strcmp
+1.18 1.18 1.18 HXlist_for_each_entry_rev
+1.17 1.17 1.17 HXclist_del
+1.17 1.17 1.17 HXlist_entry
+1.17 1.17 1.17 HXlist_for_each_entry_safe
+1.17 1.17 1.17 HXlist_for_each_safe
+1.17 1.17 1.15 HXclist_init
+1.17 1.17 1.15 HXlist_init
+1.15 1.15 1.15 HXCLIST_HEAD
+1.15 1.15 1.15 HXCLIST_HEAD_INIT
+1.15 1.15 1.15 HXLIST_HEAD
+1.15 1.15 1.15 HXLIST_HEAD_INIT
+1.15 1.15 1.15 HXclist_push
+1.15 1.15 1.15 HXclist_unshift
+1.15 1.15 1.15 HXlist_add
+1.15 1.15 1.15 HXlist_add_tail
+1.15 1.15 1.15 HXlist_del
+1.15 1.15 1.15 HXlist_for_each
+1.15 1.15 1.15 HXlist_for_each_entry
+1.10.0 1.10.0 1.10.0 HXFORMAT_IMMED
+1.10.0 1.10.0 1.10.0 HXF_GID
+1.10.0 1.10.0 1.10.0 HXF_KEEP
+1.10.0 1.10.0 1.10.0 HXF_UID
+1.10.0 1.10.0 1.10.0 HXOPT_AND
+1.10.0 1.10.0 1.10.0 HXOPT_AUTOHELP
+1.10.0 1.10.0 1.10.0 HXOPT_DEC
+1.10.0 1.10.0 1.10.0 HXOPT_DESTROY_OLD
+1.10.0 1.10.0 1.10.0 HXOPT_ERR_MIS
+1.10.0 1.10.0 1.10.0 HXOPT_ERR_UNKN
+1.10.0 1.10.0 1.10.0 HXOPT_ERR_VOID
+1.10.0 1.10.0 1.10.0 HXOPT_HELPONERR
+1.10.0 1.10.0 1.10.0 HXOPT_INC
+1.10.0 1.10.0 1.10.0 HXOPT_NOT
+1.10.0 1.10.0 1.10.0 HXOPT_OPTIONAL
+1.10.0 1.10.0 1.10.0 HXOPT_OR
+1.10.0 1.10.0 1.10.0 HXOPT_PTHRU
+1.10.0 1.10.0 1.10.0 HXOPT_QUIET
+1.10.0 1.10.0 1.10.0 HXOPT_TABLEEND
+1.10.0 1.10.0 1.10.0 HXOPT_USAGEONERR
+1.10.0 1.10.0 1.10.0 HXOPT_XOR
+1.10.0 1.10.0 1.10.0 HXTYPE_BOOL
+1.10.0 1.10.0 1.10.0 HXTYPE_CHAR
+1.10.0 1.10.0 1.10.0 HXTYPE_DOUBLE
+1.10.0 1.10.0 1.10.0 HXTYPE_FLOAT
+1.10.0 1.10.0 1.10.0 HXTYPE_INT
+1.10.0 1.10.0 1.10.0 HXTYPE_LLONG
+1.10.0 1.10.0 1.10.0 HXTYPE_LONG
+1.10.0 1.10.0 1.10.0 HXTYPE_NONE
+1.10.0 1.10.0 1.10.0 HXTYPE_SHORT
+1.10.0 1.10.0 1.10.0 HXTYPE_STRDQ
+1.10.0 1.10.0 1.10.0 HXTYPE_STRING
+1.10.0 1.10.0 1.10.0 HXTYPE_STRP
+1.10.0 1.10.0 1.10.0 HXTYPE_SVAL
+1.10.0 1.10.0 1.10.0 HXTYPE_UCHAR
+1.10.0 1.10.0 1.10.0 HXTYPE_UINT
+1.10.0 1.10.0 1.10.0 HXTYPE_ULLONG
+1.10.0 1.10.0 1.10.0 HXTYPE_ULONG
+1.10.0 1.10.0 1.10.0 HXTYPE_USHORT
+1.10.0 1.10.0 1.10.0 HXTYPE_VAL
+1.10.0 1.10.0 1.10.0 HX_chomp
+1.10.0 1.10.0 1.10.0 HX_copy_dir
+1.10.0 1.10.0 1.10.0 HX_copy_file
+1.10.0 1.10.0 1.10.0 HX_dirname
+1.10.0 1.10.0 1.10.0 HX_dlclose
+1.10.0 1.10.0 1.10.0 HX_dlerror
+1.10.0 1.10.0 1.10.0 HX_dlopen
+1.10.0 1.10.0 1.10.0 HX_dlsym
+1.10.0 1.10.0 1.10.0 HX_dlsym<>
+1.10.0 1.10.0 1.10.0 HX_getopt
+1.10.0 1.10.0 1.10.0 HX_getopt_help
+1.10.0 1.10.0 1.10.0 HX_getopt_usage
+1.10.0 1.10.0 1.10.0 HX_irand
+1.10.0 1.10.0 1.10.0 HX_memdup
+1.10.0 1.10.0 1.10.0 HX_memdup<>
+1.10.0 1.10.0 1.10.0 HX_rand
+1.10.0 1.10.0 1.10.0 HX_rrmdir
+1.10.0 1.10.0 1.10.0 HX_shconfig_free
+1.10.0 1.10.0 1.10.0 HX_split5
+1.10.0 1.10.0 1.10.0 HX_strbchr
+1.10.0 1.10.0 1.10.0 HX_strclone
+1.10.0 1.10.0 1.10.0 HX_strdup
+1.10.0 1.10.0 1.10.0 HX_strlcat
+1.10.0 1.10.0 1.10.0 HX_strlcpy
+1.10.0 1.10.0 1.10.0 HX_strlncat
+1.10.0 1.10.0 1.10.0 HX_strlower
+1.10.0 1.10.0 1.10.0 HX_strltrim
+1.10.0 1.10.0 1.10.0 HX_strrcspn
+1.10.0 1.10.0 1.10.0 HX_strrev
+1.10.0 1.10.0 1.10.0 HX_strrtrim
+1.10.0 1.10.0 1.10.0 HX_strsep
+1.10.0 1.10.0 1.10.0 HX_strsep2
+1.10.0 1.10.0 1.10.0 HX_strupper
+1.10.0 1.10.0 1.10.0 HX_zvecfree
+1.10.0 1.10.0 1.10.0 HXdeque_del
+1.10.0 1.10.0 1.10.0 HXdeque_find
+1.10.0 1.10.0 1.10.0 HXdeque_free
+1.10.0 1.10.0 1.10.0 HXdeque_get
+1.10.0 1.10.0 1.10.0 HXdeque_init
+1.10.0 1.10.0 1.10.0 HXdeque_move
+1.10.0 1.10.0 1.10.0 HXdeque_pop
+1.10.0 1.10.0 1.10.0 HXdeque_push
+1.10.0 1.10.0 1.10.0 HXdeque_shift
+1.10.0 1.10.0 1.10.0 HXdeque_to_vec
+1.10.0 1.10.0 1.10.0 HXdeque_to_vec<>
+1.10.0 1.10.0 1.10.0 HXdeque_unshift
+1.10.0 1.10.0 1.10.0 SHCONF_ONE
+====== ====== ====== ========================================
+
+
+Struct reference
+================
+
+====== ====== ================================================
+MinVer FirstA
+====== ====== ================================================
+2.0 2.0 struct HXdeque_node.sptr
+1.10.0 1.10.0 struct HXdeque_node
+1.10.0 1.10.0 struct HXdeque
+1.15 1.15 struct HXclist_head
+1.15 1.15 struct HXlist_head
+3.0 3.0 struct HXmap
+3.0 3.0 struct HXmap_ops
+3.0 3.0 struct HXmap_node
+3.12 1.10.0 struct HXoptcb
+3.12 1.10.0 struct HXoption
+2.2 2.2 struct HXproc_ops
+2.2 2.2 struct HXproc
+====== ====== ================================================
+
+
+Header reference
+================
+
+====== ===================================
+MinVer Name
+====== ===================================
+3.9 libHX/io.h
+3.4 libHX/init.h
+3.0 libHX/map.h
+2.6 libHX/wx_helper.hpp
+2.2 libHX/proc.h
+2.0 libHX/ctype_helper.h
+1.23 libHX/misc.h
+1.23 libHX/defs.h
+1.22 libHX/xml_helper.h
+1.15 libHX/string.h
+1.15 libHX/option.h
+1.15 libHX/list.h
+1.15 libHX/deque.h
+====== ===================================
diff --git a/doc/api.txt b/doc/api.txt
deleted file mode 100644
index 4649515..0000000
--- a/doc/api.txt
+++ /dev/null
@@ -1,353 +0,0 @@
-
-Table of contents
-=================
-1. Symbol reference
-2. Header reference
-
-
-Function reference
-==================
-
-R column: Recommend version number to use in PKG_CONFIG_CHECK in
-projects using libHX. Includes important bugfixes.
-M column: Lowest possible version with the same function signature.
-F column: Function first seen in version, possibly with different API.
-
-RMV MinVer FirstA Name
-----------------------------------------------------------------------
-3.25 3.25 3.25 HX_split_fixed
-3.25 3.25 3.25 HX_split_inplace
-3.22 3.22 3.22 HXQUOTE_SQLBQUOTE
-3.21 3.21 3.21 xml_getnsprop
-3.19 3.19 3.19 HXQUOTE_SQLSQUOTE
-3.18 3.18 3.18 HX_stpltrim
-3.17 3.17 3.17 HX_LONGLONG_FMT
-3.17 3.17 3.17 HX_SIZET_FMT
-3.16 3.16 3.16 container_of
-3.16 3.16 3.16 wxCDF
-3.16 3.16 3.16 wxDSPAN
-3.15 3.15 3.15 HXQUOTE_URIENC
-3.15 3.15 3.15 HX_strchr2
-3.13 3.13 3.13 DEMOTE_TO_PTR
-3.13 3.13 3.13 HXTYPE_SIZE_T
-3.13 3.13 3.13 HX_TIMESPEC_EXP
-3.13 3.13 3.13 HX_TIMESPEC_FMT
-3.13 3.13 3.13 HX_TIMEVAL_EXP
-3.13 3.13 3.13 HX_TIMEVAL_FMT
-3.13 3.13 3.13 HX_timespec_add
-3.13 3.13 3.13 HX_timespec_isneg
-3.13 3.13 3.13 HX_timespec_mul
-3.13 3.13 3.13 HX_timespec_mulf
-3.13 3.13 3.13 HX_timespec_neg
-3.13 3.13 3.13 HX_timespec_sub
-3.13 3.13 3.13 HX_timeval_sub
-3.12 3.12 1.10.0 HX_mkdir
-3.12 3.12 3.12 HX_strndup
-3.12 3.12 3.12 HX_strnlen
-3.12 3.0 3.0 HXMAP_CDATA
-3.12 3.0 3.0 HXMAP_CKEY
-3.12 3.0 3.0 HXMAP_SCDATA
-3.12 3.0 3.0 HXMAP_SCKEY
-3.12 3.0 3.0 HXMAP_SDATA
-3.12 3.0 3.0 HXMAP_SINGULAR
-3.12 3.0 3.0 HXMAP_SKEY
-3.12 3.12 3.12 HXOPT_ERR_SUCCESS
-3.12 3.12 3.12 HXOPT_ERR_SYS
-3.12 3.12 3.12 HXOPTCB_BY_LONG
-3.12 3.12 3.12 HXOPTCB_BY_SHORT
-3.12 3.0 1.10.0 HXformat_aprintf
-3.12 3.0 1.10.0 HXformat_fprintf
-3.12 3.0 1.10.0 HXformat_sprintf
-3.11 3.11 3.11 HXQUOTE_BASE64
-3.10 3.10 3.10 BUILD_BUG_ON_EXPR
-3.10 3.10 3.10 HX_readlink
-3.10 3.10 3.10 HX_realpath
-3.9.1 3.9 3.9 HXio_fullread
-3.9.1 3.9 3.9 HXio_fullwrite
-3.9 3.9 3.9 HXMAP_NONE
-3.7 3.7 3.7 HXlist_for_each_rev
-3.7 3.7 3.7 HXlist_for_each_rev_safe
-3.7 3.7 1.22 xml_newnode
-3.7 1.15 1.15 HXclist_pop
-3.7 1.15 1.15 HXclist_shift
-3.7 1.10.0 1.10.0 HX_ffs
-3.7 1.10.0 1.10.0 HX_zveclen
-3.7 1.10.0 1.10.0 HXdir_close
-3.7 1.10.0 1.10.0 HXdir_open
-3.7 1.10.0 1.10.0 HXdir_read
-3.6 3.6 3.1 HXbitmap_clear
-3.6 3.6 3.1 HXbitmap_set
-3.6 3.6 3.1 HXbitmap_test
-3.6 1.10.0 1.10.0 HX_split
-3.5 3.5 3.5 HXMAP_NOFLAGS
-3.5 3.5 3.5 HXQUOTE_LDAPFLT
-3.5 3.5 3.5 HXQUOTE_LDAPRDN
-3.5 3.5 3.5 HXSIZEOF_Z16
-3.5 2.2 2.2 HXproc_run_async
-3.5 2.2 2.2 HXproc_run_sync
-3.4 3.4 3.4 HX_exit
-3.4 3.4 3.4 HX_init
-3.4 3.4 3.4 HX_memmem
-3.4 3.4 3.4 HXlist_empty
-3.3 3.3 3.3 HX_drand
-3.3 3.3 3.3 HX_shconfig_map
-3.3 3.3 3.3 HXdeque_genocide2
-3.3 3.3 3.3 HXmc_zvecfree
-3.3 1.10.0 1.10.0 HX_shconfig
-3.3 1.10.0 1.10.0 HX_shconfig_pv
-3.2 3.2 3.2 HXQUOTE_DQUOTE
-3.2 3.2 3.2 HXQUOTE_HTML
-3.2 3.2 3.2 HXQUOTE_SQUOTE
-3.2 3.2 3.2 HXTYPE_MCSTR
-3.2 3.2 3.2 HX_strquote
-3.1 3.1 3.1 HXbitmap_size
-3.1 1.25 1.25 HXmc_strcpy
-3.0.1 3.0 3.0 HXmap_add
-3.0.1 3.0 3.0 HXmap_del
-3.0.1 3.0 3.0 HXmap_del<>
-3.0.1 3.0 3.0 HXmap_find
-3.0.1 3.0 3.0 HXmap_get
-3.0.1 3.0 3.0 HXmap_get<>
-3.0.1 3.0 3.0 HXmap_qfe
-3.0.1 3.0 3.0 HXmap_traverse
-3.0.1 3.0 3.0 HXmap_travinit
-3.0 3.0 3.0 HXMAPT_DEFAULT
-3.0 3.0 3.0 HXMAPT_HASH
-3.0 3.0 3.0 HXMAPT_ORDERED
-3.0 3.0 3.0 HXMAPT_RBTREE
-3.0 3.0 3.0 HXMAP_DTRAV
-3.0 3.0 3.0 HXMAP_NOREPLACE
-3.0 3.0 3.0 HXhash_djb2
-3.0 3.0 3.0 HXhash_jlookup3
-3.0 3.0 3.0 HXhash_jlookup3s
-3.0 3.0 3.0 HXmap_free
-3.0 3.0 3.0 HXmap_init
-3.0 3.0 3.0 HXmap_init5
-3.0 3.0 3.0 HXmap_keysvalues
-3.0 3.0 3.0 HXmap_travfree
-3.0 3.0 3.0 HXsizeof_member
-3.0 3.0 3.0 HXtypeof_member
-3.0 3.0 1.10.0 HXformat_add
-3.0 3.0 1.10.0 HXformat_free
-3.0 3.0 1.10.0 HXformat_init
-2.9 2.9 2.9 HX_basename_exact
-2.9 2.2 2.2 HX_split4
-2.9 1.10.0 1.10.0 HX_basename
-2.8 2.8 2.8 HXPROC_NULL_STDERR
-2.8 2.8 2.8 HXPROC_NULL_STDIN
-2.8 2.8 2.8 HXPROC_NULL_STDOUT
-2.6 2.6 2.6 HX_fls
-2.6 2.6 2.6 wxACV
-2.6 2.6 2.6 wxDPOS
-2.6 2.6 2.6 wxDSIZE
-2.6 2.6 2.6 wxfu8
-2.6 2.6 2.6 wxfv8
-2.6 2.6 2.6 wxtu8
-2.6 2.6 2.6 xml_strcasecmp
-2.3 1.25 1.25 HXmc_length
-2.2 2.2 2.2 HXPROC_A0
-2.2 2.2 2.2 HXPROC_EXECV
-2.2 2.2 2.2 HXPROC_STDERR
-2.2 2.2 2.2 HXPROC_STDIN
-2.2 2.2 2.2 HXPROC_STDOUT
-2.2 2.2 2.2 HXPROC_VERBOSE
-2.2 2.2 2.2 HXSIZEOF_Z32
-2.2 2.2 2.2 HXSIZEOF_Z64
-2.2 2.2 2.2 HX_STRINGIFY
-2.2 2.2 2.2 HXproc_wait
-2.2 2.0 2.0 const_cast1
-2.2 2.0 2.0 const_cast2
-2.2 2.0 2.0 const_cast3
-2.1 2.0 2.0 static_cast
-2.0 2.0 2.0 HX_isalnum
-2.0 2.0 2.0 HX_isalpha
-2.0 2.0 2.0 HX_isdigit
-2.0 2.0 2.0 HX_islower
-2.0 2.0 2.0 HX_isprint
-2.0 2.0 2.0 HX_isspace
-2.0 2.0 2.0 HX_isupper
-2.0 2.0 2.0 HX_isxdigit
-2.0 2.0 2.0 HX_tolower
-2.0 2.0 2.0 HX_toupper
-2.0 2.0 2.0 HXmc_setlen
-2.0 2.0 2.0 const_cast
-2.0 2.0 2.0 containerof
-2.0 2.0 2.0 reinterpret_cast
-2.0 2.0 2.0 signed_cast<>
-2.0 1.23 1.23 signed_cast
-2.0 1.10.0 1.10.0 HX_strmid
-1.28 1.28 1.28 HXTYPE_INT16
-1.28 1.28 1.28 HXTYPE_INT32
-1.28 1.28 1.28 HXTYPE_INT64
-1.28 1.28 1.28 HXTYPE_INT8
-1.28 1.28 1.28 HXTYPE_UINT16
-1.28 1.28 1.28 HXTYPE_UINT32
-1.28 1.28 1.28 HXTYPE_UINT64
-1.28 1.28 1.28 HXTYPE_UINT8
-1.26 1.26 1.26 HX_hexdump
-1.26 1.26 1.26 HX_time_compare
-1.25 1.25 1.25 HX_getl
-1.25 1.25 1.25 HXmc_free
-1.25 1.25 1.25 HXmc_memcat
-1.25 1.25 1.25 HXmc_memcpy
-1.25 1.25 1.25 HXmc_memdel
-1.25 1.25 1.25 HXmc_meminit
-1.25 1.25 1.25 HXmc_memins
-1.25 1.25 1.25 HXmc_mempcat
-1.25 1.25 1.25 HXmc_strcat
-1.25 1.25 1.25 HXmc_strinit
-1.25 1.25 1.25 HXmc_strins
-1.25 1.25 1.25 HXmc_strpcat
-1.25 1.25 1.25 HXmc_trunc
-1.23 1.23 1.23 ARRAY_SIZE
-1.23 1.23 1.23 BUILD_BUG_ON
-1.23 1.23 1.23 O_BINARY
-1.23 1.23 1.23 S_IRUGO
-1.23 1.23 1.23 S_IRWXUGO
-1.23 1.23 1.23 S_IWUGO
-1.23 1.23 1.23 S_IXUGO
-1.22 1.22 1.22 xml_getprop
-1.22 1.22 1.22 xml_newprop
-1.22 1.22 1.22 xml_strcmp
-1.18 1.18 1.18 HXlist_for_each_entry_rev
-1.17 1.17 1.17 HXclist_del
-1.17 1.17 1.17 HXlist_entry
-1.17 1.17 1.17 HXlist_for_each_entry_safe
-1.17 1.17 1.17 HXlist_for_each_safe
-1.17 1.17 1.15 HXclist_init
-1.17 1.17 1.15 HXlist_init
-1.15 1.15 1.15 HXCLIST_HEAD
-1.15 1.15 1.15 HXCLIST_HEAD_INIT
-1.15 1.15 1.15 HXLIST_HEAD
-1.15 1.15 1.15 HXLIST_HEAD_INIT
-1.15 1.15 1.15 HXclist_push
-1.15 1.15 1.15 HXclist_unshift
-1.15 1.15 1.15 HXlist_add
-1.15 1.15 1.15 HXlist_add_tail
-1.15 1.15 1.15 HXlist_del
-1.15 1.15 1.15 HXlist_for_each
-1.15 1.15 1.15 HXlist_for_each_entry
-1.10.0 1.10.0 1.10.0 HXFORMAT_IMMED
-1.10.0 1.10.0 1.10.0 HXF_GID
-1.10.0 1.10.0 1.10.0 HXF_KEEP
-1.10.0 1.10.0 1.10.0 HXF_UID
-1.10.0 1.10.0 1.10.0 HXOPT_AND
-1.10.0 1.10.0 1.10.0 HXOPT_AUTOHELP
-1.10.0 1.10.0 1.10.0 HXOPT_DEC
-1.10.0 1.10.0 1.10.0 HXOPT_DESTROY_OLD
-1.10.0 1.10.0 1.10.0 HXOPT_ERR_MIS
-1.10.0 1.10.0 1.10.0 HXOPT_ERR_UNKN
-1.10.0 1.10.0 1.10.0 HXOPT_ERR_VOID
-1.10.0 1.10.0 1.10.0 HXOPT_HELPONERR
-1.10.0 1.10.0 1.10.0 HXOPT_INC
-1.10.0 1.10.0 1.10.0 HXOPT_NOT
-1.10.0 1.10.0 1.10.0 HXOPT_OPTIONAL
-1.10.0 1.10.0 1.10.0 HXOPT_OR
-1.10.0 1.10.0 1.10.0 HXOPT_PTHRU
-1.10.0 1.10.0 1.10.0 HXOPT_QUIET
-1.10.0 1.10.0 1.10.0 HXOPT_TABLEEND
-1.10.0 1.10.0 1.10.0 HXOPT_USAGEONERR
-1.10.0 1.10.0 1.10.0 HXOPT_XOR
-1.10.0 1.10.0 1.10.0 HXTYPE_BOOL
-1.10.0 1.10.0 1.10.0 HXTYPE_CHAR
-1.10.0 1.10.0 1.10.0 HXTYPE_DOUBLE
-1.10.0 1.10.0 1.10.0 HXTYPE_FLOAT
-1.10.0 1.10.0 1.10.0 HXTYPE_INT
-1.10.0 1.10.0 1.10.0 HXTYPE_LLONG
-1.10.0 1.10.0 1.10.0 HXTYPE_LONG
-1.10.0 1.10.0 1.10.0 HXTYPE_NONE
-1.10.0 1.10.0 1.10.0 HXTYPE_SHORT
-1.10.0 1.10.0 1.10.0 HXTYPE_STRDQ
-1.10.0 1.10.0 1.10.0 HXTYPE_STRING
-1.10.0 1.10.0 1.10.0 HXTYPE_STRP
-1.10.0 1.10.0 1.10.0 HXTYPE_SVAL
-1.10.0 1.10.0 1.10.0 HXTYPE_UCHAR
-1.10.0 1.10.0 1.10.0 HXTYPE_UINT
-1.10.0 1.10.0 1.10.0 HXTYPE_ULLONG
-1.10.0 1.10.0 1.10.0 HXTYPE_ULONG
-1.10.0 1.10.0 1.10.0 HXTYPE_USHORT
-1.10.0 1.10.0 1.10.0 HXTYPE_VAL
-1.10.0 1.10.0 1.10.0 HX_chomp
-1.10.0 1.10.0 1.10.0 HX_copy_dir
-1.10.0 1.10.0 1.10.0 HX_copy_file
-1.10.0 1.10.0 1.10.0 HX_dirname
-1.10.0 1.10.0 1.10.0 HX_dlclose
-1.10.0 1.10.0 1.10.0 HX_dlerror
-1.10.0 1.10.0 1.10.0 HX_dlopen
-1.10.0 1.10.0 1.10.0 HX_dlsym
-1.10.0 1.10.0 1.10.0 HX_dlsym<>
-1.10.0 1.10.0 1.10.0 HX_getopt
-1.10.0 1.10.0 1.10.0 HX_getopt_help
-1.10.0 1.10.0 1.10.0 HX_getopt_usage
-1.10.0 1.10.0 1.10.0 HX_irand
-1.10.0 1.10.0 1.10.0 HX_memdup
-1.10.0 1.10.0 1.10.0 HX_memdup<>
-1.10.0 1.10.0 1.10.0 HX_rand
-1.10.0 1.10.0 1.10.0 HX_rrmdir
-1.10.0 1.10.0 1.10.0 HX_shconfig_free
-1.10.0 1.10.0 1.10.0 HX_split5
-1.10.0 1.10.0 1.10.0 HX_strbchr
-1.10.0 1.10.0 1.10.0 HX_strclone
-1.10.0 1.10.0 1.10.0 HX_strdup
-1.10.0 1.10.0 1.10.0 HX_strlcat
-1.10.0 1.10.0 1.10.0 HX_strlcpy
-1.10.0 1.10.0 1.10.0 HX_strlncat
-1.10.0 1.10.0 1.10.0 HX_strlower
-1.10.0 1.10.0 1.10.0 HX_strltrim
-1.10.0 1.10.0 1.10.0 HX_strrcspn
-1.10.0 1.10.0 1.10.0 HX_strrev
-1.10.0 1.10.0 1.10.0 HX_strrtrim
-1.10.0 1.10.0 1.10.0 HX_strsep
-1.10.0 1.10.0 1.10.0 HX_strsep2
-1.10.0 1.10.0 1.10.0 HX_strupper
-1.10.0 1.10.0 1.10.0 HX_zvecfree
-1.10.0 1.10.0 1.10.0 HXdeque_del
-1.10.0 1.10.0 1.10.0 HXdeque_find
-1.10.0 1.10.0 1.10.0 HXdeque_free
-1.10.0 1.10.0 1.10.0 HXdeque_get
-1.10.0 1.10.0 1.10.0 HXdeque_init
-1.10.0 1.10.0 1.10.0 HXdeque_move
-1.10.0 1.10.0 1.10.0 HXdeque_pop
-1.10.0 1.10.0 1.10.0 HXdeque_push
-1.10.0 1.10.0 1.10.0 HXdeque_shift
-1.10.0 1.10.0 1.10.0 HXdeque_to_vec
-1.10.0 1.10.0 1.10.0 HXdeque_to_vec<>
-1.10.0 1.10.0 1.10.0 HXdeque_unshift
-1.10.0 1.10.0 1.10.0 SHCONF_ONE
-
-
-Struct reference
-================
-MinVer FirstA
-2.0 2.0 struct HXdeque_node.sptr
-1.10.0 1.10.0 struct HXdeque_node
-1.10.0 1.10.0 struct HXdeque
-1.15 1.15 struct HXclist_head
-1.15 1.15 struct HXlist_head
-3.0 3.0 struct HXmap
-3.0 3.0 struct HXmap_ops
-3.0 3.0 struct HXmap_node
-3.12 1.10.0 struct HXoptcb
-3.12 1.10.0 struct HXoption
-2.2 2.2 struct HXproc_ops
-2.2 2.2 struct HXproc
-
-
-Header reference
-================
-
-MinVer Name
--------------------------------------------
-3.9 libHX/io.h
-3.4 libHX/init.h
-3.0 libHX/map.h
-2.6 libHX/wx_helper.hpp
-2.2 libHX/proc.h
-2.0 libHX/ctype_helper.h
-1.23 libHX/misc.h
-1.23 libHX/defs.h
-1.22 libHX/xml_helper.h
-1.15 libHX/string.h
-1.15 libHX/option.h
-1.15 libHX/list.h
-1.15 libHX/deque.h
diff --git a/doc/bitmaps.rst b/doc/bitmaps.rst
new file mode 100644
index 0000000..18a992d
--- /dev/null
+++ b/doc/bitmaps.rst
@@ -0,0 +1,49 @@
+=======
+Bitmaps
+=======
+
+.. code-block:: c
+
+ #include <libHX/misc.h>
+
+ size_t HXbitmap_size(type array, unsigned int bits);
+ void HXbitmap_set(type *bmap, unsigned int bit);
+ void HXbitmap_clear(type *bmap, unsigned int bit);
+ bool HXbitmap_test(type *bmap, unsigned int bit);
+
+All of these four are implemented as macros, so they can be used with any
+integer type that is desired to be used.
+
+``HXbitmap_size``
+ Returns the amount of ``type``-based integers that would be needed to
+ hold an array of the requested amount of bits.
+
+``HXbitmap_set``
+ Sets the specific bit in the bitmap.
+
+``HXbitmap_clear``
+ Clears the specific bit in this bitmap.
+
+``HXbitmap_test``
+ Tests for the specific bit and returns true if it is set, otherwise
+ false.
+
+
+Example
+=======
+
+.. code-block:: c
+
+ #include <stdlib.h>
+ #include <string.h>
+ #include <libHX/misc.h>
+
+ int main(void)
+ {
+ unsigned long bitmap[HXbitmap_size(unsigned long, 128)];
+
+ memset(bitmap, 0, sizeof(bitmap));
+ HXbitmap_set(bitmap, 49);
+ return HXbitmap_get(bitmap, HX_irand(0, 128)) ?
+ EXIT_SUCCESS : EXIT_FAILURE;
+ }
diff --git a/doc/changelog.rst b/doc/changelog.rst
new file mode 100644
index 0000000..16b92fd
--- /dev/null
+++ b/doc/changelog.rst
@@ -0,0 +1,140 @@
+v4.7 (2022-10-21)
+=================
+
+Enhancements:
+
+* string: new quoting modes HXQUOTE_BASE64URL & HXQUOTE_BASE64IMAP
+
+Fixes:
+
+* socket: make HX_socket_from_env functional on OpenBSD
+
+
+v4.6 (2022-06-27)
+=================
+
+Enhancements:
+
+* HX_slurp_fd/HX_slurp_file now supports reading from files reporting their
+ own size as 0 (e.g. ttys, /proc special files).
+
+
+v4.5 (2022-04-10)
+=================
+
+Fixes:
+
+* Resolve a number of cov-scan reported warnings.
+
+
+v4.4 (2022-03-15)
+=================
+
+Fixes:
+
+* Build fixes for the mingw environment.
+
+
+v4.3 (2022-03-14)
+=================
+
+Enhancements:
+
+* string: New functions ``HX_strtoull_sec``, ``HX_unit_seconds`` for converting
+ between second-based time durations and human-readable durations like
+ 129600 <-> 1d12h.
+* io: New function ``HX_sendfile``.
+* io: raise buffer size for ``HX_copy_file`` from 1 kiB to 64 kiB
+
+
+v4.2 (2021-10-17)
+=================
+
+Enhancements:
+
+* string: New functions ``HX_strtod_unit``, ``HX_strtoull_unit``,
+ ``HX_unit_size``, ``HX_unit_size_cu`` for converting between
+ sizes and human-readable sizes like 1457664 <-> "1.45M"/"1.39M".
+
+
+v4.1 (2021-10-13)
+=================
+
+Fixes:
+
+* io: fix a use-after-free in conjunction with HX_realpath /
+ fix missing NULLing of a pointer within HX_readlink
+
+
+v4.0 (2021-10-03)
+=================
+
+Enhancements:
+
+* lib: add ``HX_slurp_fd``, ``HX_slurp_file``
+* proc: add ``HXproc_switch_user``
+* proc: add ``HXproc_top_fd``
+* socket: add ``HX_socket_from_env``
+* opt: add ``HXOPT_KEEP_ARGV`` flag
+
+Fixes:
+
+* proc: re-close pipes when ``HXproc_build_pipes`` failed
+
+
+v3.26 (2021-08-03)
+==================
+
+Fixes:
+
+* io: cure a potential infinite loop on EOF with HXio_fullread()
+* io: HXio_fullread() now returns actual bytes read rather than bytes requested
+* time: rectified HX_timeval_sub producing wrong results
+
+Changes:
+
+* nullptr checks were added to HXshconfig_free, HXformat_free, HXdeque_free and
+ HXmap_free to make their behavior be in line with free(3).
+* Documentation has been switched to reStructured Text.
+
+
+v3.25 (2020-05-14)
+==================
+
+Fixes:
+
+* string: fix out-of-bounds access when calling ``HX_strlcpy(x,y,0)``
+
+Changes:
+
+* string: ``HX_split4`` renamed to ``HX_split_inplace``
+* string: ``HX_split5`` renamed to ``HX_split_fixed``
+* defs.h: removed partially implementation of ``FIELD_SIZEOF``
+* defs.h: removed custom ``offsetof`` definition; you will need to include
+ ``<stddef.h>`` or ``<cstddef>`` now.
+
+
+v3.24 (2018-10-17)
+==================
+
+Fixes:
+
+* defs: avoid compiler warning when using ``HX_list_for_each`` in C++
+* opt: synchronize ``HXOPT_AUTOHELP`` C behavior to C++ mode
+
+
+v3.23 (2018-08-28)
+==================
+
+Enhancements:
+
+* opt: the option parser now recognizes long option abbreviations
+* io: use modern ``readdir`` rather than ``readdir_r``
+
+
+v3.22 (2014-08-25)
+==================
+
+Enhancements:
+
+* string: add the ``HXQUOTE_SQLBQUOTE`` quoting variant
diff --git a/doc/changelog.txt b/doc/changelog.txt
deleted file mode 100644
index ffe75c1..0000000
--- a/doc/changelog.txt
+++ /dev/null
@@ -1,556 +0,0 @@
-
-v3.25 (2020-05-14)
-==================
-Fixes:
-* string: fix out-of-bounds access when calling HX_strlcpy(x,y,0)
-Changes:
-* string: HX_split4 renamed to HX_split_inplace
-* string: HX_split5 renamed to HX_split_fixed
-* defs.h: removed partially implementation of FIELD_SIZEOF
-* defs.h: removed custom offsetof definition; you will need to include
- <stddef.h> or <cstddef> now.
-
-
-v3.24 (2018-10-17)
-==================
-Fixes:
-- defs: avoid compiler warning when using HX_list_for_each when used in C++
-- opt: synchronize HXOPT_AUTOHELP C behavior to C++ mode
-
-
-v3.23 (2018-08-28)
-==================
-Enhancements:
-- opt: the option parser now recognizes long option abbreviations
-- io: use modern readdir rather than readdir_r
-
-
-v3.22 (2014-08-25)
-==================
-Enhancements:
-- string: add the HXQUOTE_SQLBQUOTE quoting variant
-
-
-v3.21 (2014-06-02)
-==================
-Enhancements:
-- HXformat_add() now supports HXTYPE_MCSTR objects (with and without
- HXTYPE_IMMED)
-- libxml_helper: New xml_getnsprop() function that gets the value of a
- property (element attribute) by namespace prefix
-
-
-v3.20 (2014-04-18)
-==================
-Enhancements:
-- resolve some link errors when built with Solaris ld
-
-
-v3.19 (2014-02-21)
-==================
-Enhancements:
-- string: add the HXQUOTE_SQLSQUOTE quoting variant
-Internal changes:
-- format: rework function calling code to support extending with functions
-
-
-v3.18 (2014-03-01)
-==================
-Enhancements:
-- string: add the HX_stpltrim function
-Fixes:
-- Make HX_strltrim move the correct number of bytes
-Changes:
-- remove wxCFF from wx_helper.hpp
-
-
-v3.17 (2013-11-16)
-==================
-Enhancements:
-- defs: add HX_SIZET_FMT and HX_LONGLONG_FMT
-- support for Win64
-Fixes:
-- compile warnings on mingw were addressed
-
-
-v3.16 (2013-09-29)
-==================
-Enhancements:
-- format: remove 256-char format key length limit
-Fixes:
-- compile errors on mingw were addressed
-
-
-v3.15 (2013-03-07)
-==================
-Enhancements:
-- string: add HX_strchr2
-- string: add HXQUOTE_URIENC mechanism for HX_strquote
-Changes:
-- defs: HXsizeof_member becomes FIELD_SIZEOF
- (to match the Linux kernel's macro name)
-
-
-v3.14.1 (2012-12-31)
-====================
-Fixes:
-- Restore forward-sorting order of ordered maps
- (revert "map: always have needle as second argument")
-
-
-v3.14 (2012-11-14)
-==================
-Fixes:
-- io: use pathconf(3) to determine dirent size for dir traversal
-- rand: avoid division by zero when calling HX_irand with lo==hi
-- time: use C++ static_cast syntax for C++ mode
-- headers: improve operability with C89 compile mode
-
-
-v3.13 (2012-07-28)
-==================
-Enhancements:
-- defs: add DEMOTE_TO_PTR
-- option: new HXOPT_RQ_ORDER flag, allows unconditional POSIX-style parsing
- (parsing terminates at first non-option encountered)
-- option: add HXTYPE_SIZE_T
-- time: add functions and macros for arithmetic and handling of timespec
- with support for negative time values
- * time: add HX_TIMESPEC_{EXP,FMT}
- * time: add HX_TIMEVAL_{EXP,FMT}
- * time: add the HX_timespec_isneg function
- * time: add the HX_timespec_neg function
- * time: add the HX_timespec_add function
- * time: add the HX_timespec_mul function
- * time: add the HX_timespec_mulf function
-Changes:
-- io: remove HX_REALPATH_SYMLINK
-- time: rename HX_diff_timespec to HX_timespec_sub (old ABI kept)
-- time: rename HX_diff_timeval to HX_timeval_sub (old ABI kept)
-- string: make HX_memmem consider the special case of search_length=0
-- string: optimize search_length=1 case in HX_memmem
-- string: speed up HX_memmem searches for search_length >=2
-
-
-v3.12.1 (2011-12-15)
-====================
-Fixes:
-- build: make build error-free when using -Wl,--no-undefined
-- string: make HX_strdup(NULL) valid again
-
-
-v3.12 (2010-12-03)
-==================
-Fixes:
-- defs: resolve warning for users of const_cast*() when using -Wextra
-- format: error handling for HXformat2_aprintf
-- option: do not omit dashes when passthru'ing unknown two-part long opts
-- option: do not omit arg following unknown unknown two-part long opts in pthru
-- option: do run callback on HXTYPE_BOOL
-- option: correct passthrough of squashed unknown short options
-- option: do not stop early when printing help/usage
-- option: avoid crash when passing an empty argv
-- option: avoid crash when passing NULL for struct HXoptcb.arg0
-Enhancements:
-- build: deactivate type-checking of the *_cast() macros for clang due to a
- compiler bug involving nested structs-in-typeofs
-- option: allow argc=NULL on HX_getopt
-- option: error handling for HX_getopt
-- option: support POSIXLY_CORRECT environment variable
-- string: add a HX_strndup function
-- string: add a HX_strnlen function
-- mc: use an implicit minimum allocated length
-Changes:
-- format: renamed HXformat2_[afs]printf back to HXformat_[afs]printf
-- io: add mode argument to HX_mkdir
-- map: avoid 1<<31 in constants
-- option: remove struct HXoptcb.arg0
-- option: remove struct HXoptcb.match_{ln,sh} by .flags
-- option: let HX_getopt return code indicate system failure states
-- option: remove struct HXoption.sval (replaced by .uptr)
-- string: unline HX_strdup, HX_strlcat, HX_strlcpy, HX_strnlcat
-
-
-v3.11 (2011-07-25)
-==================
-Enhancements:
-- A LD_PRELOAD-able library libHX_rtcheck.so that adds global state correctness
- checks, was added.
-- add a HXQUOTE_BASE64 to HX_strquote
-Changes:
-- HX_strquote will return NULL for unknown types now instead of just
- returning the input pointer
-
-
-v3.10.1 (2011-04-06)
-====================
-Fixes:
-- defs: BUILD_BUG_ON_EXPR had erroneously returned 1
-
-
-v3.10 (2011-04-05)
-==================
-Fixes:
-- build: resolve autoconf-2.68 warnings
-- format: do not split arguments in %(lower) and %(upper)
-Changes:
-- defs: add array type checking in ARRAY_SIZE
-- opt: use non-zero sentinel marker
-- string: make HX_getl more resilient against errors
-Enhancements:
-- defs: add BUILD_BUG_ON_EXPR
-- format: provide a %(substr) function
-- io: add HX_readlink (zero-terminating mc-output readlink)
-- io: add HX_realpath (supports relative-path output)
-
-
-v3.9.1 (2011-01-17)
-===================
-Fixes:
-- libHX/io.h was not copied on `make install`, which has been fixed
-
-
-v3.9 (2011-01-15)
-=================
-Fixes:
-- Added missing __cplusplus guards to libHX/io.h
-- Added missing includes to libHX/string.h
-- Use __typeof__ in includes
-Changes:
-- For filesystem/filehandle-related functions, io.h should now be included
- in userspace programs instead of misc.h
-- libHX.so is now built with a symvers map file
-Enhancements:
-- hxdirstamp: new development helper program for library users
- (Note to distros: should be in libHX-devel; it is only used during builds)
-- io: new functions HXio_full{read,write}
-
-
-v3.8 (2010-12-01)
-=================
-This was supposed to go into 3.7 but I forgot to merge in time..
-Changes:
-- hexdump: colorize characters 0x00 thru 0x1F in tty mode
-
-
-v3.7 (2010-12-01)
-=================
-Changes:
-- libxml_helper: redo xml_newnode to take a parent and value string
-- list: unify naming of reverse-direction functions
-- misc: HX_zveclen now returns unsigned from (previous: int)
-- dir: HXdir functions now work with struct HXdir * instead of void *
-Fixes:
-- list: avoid potential shadow warning when using HXclist_{shift,pop}
-Enhancements:
-- doc: add doc/api.txt that lists the minimum required versions for symbols
-
-
-v3.6 (2010-08-16)
-=================
-Fixed:
-- bitmap: set/clear/test had no effect due to wrong type selection
-- bitmap: avoid left-shift larger than type on 64-bit
-- string: fixed buffer overflow in HX_split when too few fields were present
- in the input
-
-
-v3.5 (2010-08-01)
-=================
-Fixed:
-- format2: failure to skip escaped char in "%(echo foo\ bar)" was corrected
-- proc: properly check for HXPROC_STDx--HXPROC_STDx_NULL overlap
-- strquote: do not cause allocation with invalid format numbers
-Enhancements:
-- format2: add the %(exec) function
-- format2: add the %(shell) function
-- format2: security feature for %(exec) and %(shell)
-- format2: add the %(snl) function
-- string: HX_strquote gained HXQUOTE_LDAPFLT (LDAP search filter) support
-- string: HX_strquote gained HXQUOTE_LDAPRDN (LDAP relative DN) support
-Changes:
-- format1: removed older formatter in favor of format2
-- format2: add check for empty key
-- format2: function-specific delimiters
-- format2: do nest-counting even with normal parentheses
-- format2: check for zero-argument function calls
-- hashmap: do not needlessy change TID when no reshape was done
-- string: HX_basename (the fast variant) now recognizes the root directory
-- string: HX_basename now returns the trailing component with slashes
- instead of everything after the last slash (which may have been nothing)
-
-
-v3.4 (2010-04-03)
-=================
-Changes:
-- add explicit initialize/deinitialize functions HX_init, HX_exit
-Enhancements:
-- add the HX_memmem function
-- add the HXlist_empty function
-- documentation updates: HXlist traversal
-
-
-v3.3 (2010-01-20)
-=================
-Bug fixes:
-- format: fix incorrect copying of non-expanded % strings
-- proc: avoid calling close(-1) to not trip up valgrind
-- shconfig: fix incorrect parsing of "\'"
-- shconfig: fix incorrect processing of "\"\\\0BCD"
-- shconfig: be more strict with syntax
-Enhancements:
-- deque: add HXdeque_genocide2
-- format2: new format string (make-style) support
-- mc: add HXmc_zvecfree
-- shconfig: add HX_shconfig_map to return all entries of a shconfig file
-- rand: add HX_drand ('double'-type bounds and return value)
-- rand: avoid some function call overhead in HX_irand
-
-
-v3.2 (2009-10-11)
-=================
-Enhancements:
-- opt: add HXTYPE_MCSTR for storing into hxmc_t *s
-- string: add HX_strquote
-
-
-v3.1 (2009-09-13)
-=================
-Enhancements:
-- added HXbitmap_* functions
-Fixes:
-- mc: HXmc_strcpy produced a zero-length string when NULL was copied
-
-
-v3.0.1 (2009-08-31)
-===================
-Fixes:
-- map: avoid underflow in value-based tree comparison
-
-
-v3.0 (2009-08-27)
-=================
-Changes:
-- automatically skip building testcases if C++ compiler not available
- (reminder: libHX itself does not require a C++ compiler)
-- arbtree: HXbtree was removed in favor of the new HXmap
-- clist: clist.h moved into list.h
-- format: HXformat_* now uses struct HXformat_map,
- so that it does not tie itself to HXbtree
-- mc: fix an alignment-induced overallocation
-- rand: use faster modulo-based variant for numbers within RAND_MAX range
-- rand: use libc rand() almost exclusively, only use /dev/urandom for seed
-Enhancements:
-- defs: add HXsizeof_member and HXtypeof_member
-- map: new map API, with hash-based maps and classic rbtree-based maps
-- time: add time delta functions (HX_diff_timeval/HX_diff_timespec)
-Fixes:
-- format: memory leaks fixes in HXformat
-
-
-v2.9 (2009-07-11)
-=================
-Fixes:
-- string: fixed number of fields and trailing NULL in HX_split4
-Enhancements:
-- string: add HX_basename_exact
-
-
-v2.8 (2009-07-01)
-=================
-Enhancements:
-- HXproc now knows about HXPROC_NULL_*, which can be used to discard I/O
-- HXproc: expressly prohibit HXPROC_STD* for HXproc_run_sync
-
-
-v2.7 (2009-04-08)
-=================
-Fixes:
-- install missing wx_helper.hpp
-
-
-v2.6 (2009-03-28)
-=================
-Documentation:
-- install documentation
-- update project URLs
-- add section about Miscellaneous functions
-Changes:
-- arbtree: add "flat view" operation
-- misc: added HX_fls
-- misc: make HX_time_compare otime-capable
-- add wx_helper.hpp
-
-
-v2.5 (2009-02-11)
-=================
-Fixes:
-- proc: fix fd setup when the standard channels are already closed
-
-
-v2.4 (2009-02-05)
-=================
-Documentation updates. A few internal cleanups, nothing user-visible.
-
-
-v2.3 (2009-01-13)
-=================
-Fixes:
-- defs: only use __builtin_offsetof with GCC >= 4
-- misc: fix time_compare on FreeBSD to actually use mtimespec
-- mc: handle HXmc_length(NULL)
-- dir: do not cause directory traversal to restart after 2^32 entries
-
-
-v2.2 (2009-01-01)
-=================
-Fixes:
-- defs/cast: avoid warning between conversion from type[] to type *
-- defs/cast: add fallback defs for const_castN()
-- arbtree: correctly set errno (to ENOENT) in HXbtree_find and _get
-- string: document behavior details of HX_basename
-
-Changes:
-- removed old HX_vfsystem
-
-Enhancements:
-- defs: add HXSIZEOF_Z*
-- defs: add HX_STRINGIFY
-- proc: initial code
-- string: add HX_split4 function
-
-
-v2.1 (2008-12-23)
-=================
-- defs: fix bogus offsetof macro for non-GCC
-- defs: add a pair of guarding parentheses in static_cast()
-- doc: generate PDF file from LyX document
-
-
-v2.0 (2008-12-23)
-=================
-Fixes:
-- arbtree: reject illegal flag combinations
-- arbtree: correctly set errno in HXbtree_find and HXbtree_get
-- arbtree: do not return dangling pointer in HXbtree_del
-- defs: add a working offsetof() and containerof() for C++ mode
-- defs: use GCC's __builtin_offsetof
-- defs: resolve warnings with signed_cast() for char* -> const char* conversions
-- dir: HX_rrmdir: do not stop on error
-- opt: fix interpretation of strings during conversion to bool
- (all strings that were not empty and not 0 were interpreted as "true",
- and this included the strings "no", "off" and "false", which should
- actually have mapped to, well, "false".)
-- rand: use autoconf to detect presence of unix functions
-- string: replace HX_strrev implementation by one that does not allocate
-
-
-New feature: Type-checking casts.
-- defs: enable type-checking signed_cast()
-- defs: add signed_cast<> for C++ mode
-- defs: rewrite static_cast() to not cause -Wshadow warnings when nested
-- defs: rewrite const_cast() to do type checking
- (actually, const_cast1(), cosnt_cast2() and const_cast3() were introduced.
- const_cast() is kept to not break program compilation.)
-
-
-New misc code:
-- ctype_helper: initial version
-- deque: add struct HXdeque_node->char *sptr as a typed variant for ptr
-- mc: add HXmc_setlen()
-- opt: HXTYPE_BOOL and HXTYPE_NONE now take int * (instead of unsigned int *)
-
-
-New arbtree code:
-- arbtree: add struct HXbtree_node->char *skey and char *sdata
-- arbtree: support arbitrary key/data duplication
-- arbtree: add HXbtree_init2
-
-
-Removals:
-- mc: remove HXmc_dup
- [you can use HXmc_meminit(old, HXmc_length(old))]
-- string: HX_strmid behavior changed for length=0
- [no more "remaining string", now returns a zero-length string]
-
-
-v1.28 (2008-11-18)
-==================
-- add HXTYPE_{U,}INT{8,16,32,64}
-- add includedir to cflags (libHX.pc)
-
-
-v1.27 (2008-12-23)
-==================
-No functional changes for Linux platforms.
-
-- build: fixed compile errors with i586-mingw32msvc cross compile
-- regenerated the Makefile.in files in the tarball with an updated
- version of automake-tranquility so that they are now
- POSIX-compliant and work with BSD make
-
-
-v1.26 (2008-10-12)
-==================
-- add HX_hexdump() for debugging within programs
-- fix double free in the error path of HX_getopt() when a long option preceded
- a short option of which the latter had problems (i.e. missing argument)
-- add actual typechecking to signed_cast()
-- add typechecking to static_cast(),
- (but this is normally disabled to avoid compile interruption)
-
-
-v1.25 (2008-09-07)
-==================
-- install missing misc.h
-- HXmc: pointer was not automatically updated after hmc_trunc()
-- HXmc: rename functions and put them into the HX* namespace (API change)
-- HXmc: make code resistant to memory allocation failure
-
-
-v1.23 (2008-09-02)
-==================
-- code cleanup: misc.h has been split off libHX.h
-- add defs.h
-
-
-v1.22 (2008-07-16)
-==================
-- need to use lstat() on directory operations such as mkdir and rrmdir
-- use RTLD_LAZY when opening dynamic libraries
-- add libxml_helper
-
-
-v1.18 (2008-06-10)
-==================
-- implement reverse iterating through HXlist
-- remove deprecated HXlist_init_head() and HXclist_init_head()
- [replaced by HXlist_init() and HXclist_init()]
-- added HX_ffs()
-
-
-v1.17 (2008-05-08)
-==================
-- HXlist: added HXlist_for_each_safe, HXlist_for_each_entry_safe
-- HXclist: added HXclist_del
-
-
-v1.15 (2008-04-04)
-==================
-- HXformat: add %(ifempty) and %(ifnempty) tags
-- libHX.h: split into {arbtree,deque,option,string}.h (and libHX.h)
-- Add inline-doubly-linked-list data structures
-
-
-v1.10.2 (2007-12-06)
-====================
-- [r105]: pass up NULL from memory allocation error
-- [r108]: only return success on EEXIST when HXF_KEEP was given
-- [r112]: HX_dirname() incorrectly computed the path
-
-
-v1.10.1 (2007-09-17)
-====================
-- [r96]: Fix output of line-wrapped help text
-- tarball: in libHX 1.10.0 I forgot to provide the configure - sorry
- (but you could regenerate it using ./autogen.sh if you have autotools)
diff --git a/doc/dirstamp.rst b/doc/dirstamp.rst
new file mode 100644
index 0000000..fe69d26
--- /dev/null
+++ b/doc/dirstamp.rst
@@ -0,0 +1,7 @@
+Improved dirstamp
+=================
+
+.. code-block:: makefile
+
+ dirstamp.lst:
+ [ ! -e $@ -o -n "$(find dir/ -newer $@ -print -quit)" ] && touch $@ || :;
diff --git a/doc/dirstamp.txt b/doc/dirstamp.txt
deleted file mode 100644
index 92c1696..0000000
--- a/doc/dirstamp.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-Improved dirstamp:
-
-dirstamp.lst:
- [ ! -e $@ -o -n "$(find dir/ -newer $@ -print -quit)" ] && touch $@ || :;
diff --git a/doc/files_and_dirs.rst b/doc/files_and_dirs.rst
new file mode 100644
index 0000000..a4fdc59
--- /dev/null
+++ b/doc/files_and_dirs.rst
@@ -0,0 +1,190 @@
+===========================
+File and directory handling
+===========================
+
+
+Directory traversal
+===================
+
+libHX provides a minimal readdir-style wrapper for cross-platform directory
+traversal. This is needed because the Win32 platforms does not have readdir,
+and there is some housekeeping to do on Unixish platforms, since the dirent
+structure needs allocation of a path-specific size.
+
+.. code-block:: c
+
+ #include <libHX/io.h>
+
+ struct HXdir *HXdir_open(const char *directory);
+ const char *HXdir_read(struct HXdir *handle);
+ void HXdir_close(struct HXdir *handle);
+
+``HXdir_open`` returns a pointer to its private data area, or ``NULL`` upon
+failure, in which case ``errno`` is preserved from the underlying system calls.
+``HXdir_read`` causes the next entry from the directory to be fetched. The
+pointer returned by ``HXdir_read`` must not be freed, and the data is
+overwritten in subsequent calls to the same handle. If you want to keep it
+around, you will have to duplicate it yourself. ``HXdir_close`` will close the
+directory and free the private data it held.
+
+
+Example
+-------
+
+.. code-block:: c
+
+ #include <errno.h>
+ #include <stdio.h>
+ #include <libHX/io.h>
+
+ struct HXdir *dh;
+ if ((dh = HXdir_open(".")) == NULL) {
+ fprintf(stderr, "Could not open directory: %s\n", strerror(errno));
+ return;
+ }
+ while ((dentry = HXdir_read(dh)) != NULL)
+ printf("%s\n", dentry);
+ HXdir_close(dh);
+
+This sample will open the current directory, and print out all entries as it
+iterates over them.
+
+
+Operation on directory entries
+==============================
+
+.. code-block:: c
+
+ #include <libHX/io.h>
+
+ int HX_readlink(hxmc_t **buf, const char *path);
+ int HX_realpath(hxmc_t **buf, const char *path, unsigned int flags);
+
+``HX_readlink`` calls through to readlink to read the target of a symbolic
+link, and stores the result in the memory container referenced by ``*buf``
+(similar to ``HX_getl`` semantics). If ``*buf`` is ``NULL``, a new container
+will be allocated and a pointer to it stored in ``*buf``. The container's
+content is naturally zero-terminated automatically. The return value of the
+function will be the length of the link target, or negative to indicate the
+system error value.
+
+``HX_realpath`` will normalize the given path by transforming various path
+components into alternate descriptions. The flags parameter controls its
+actions:
+
+``HX_REALPATH_DEFAULT``
+ A mnemonic for a set of standard flags: ``HX_REALPATH_SELF |
+ HX_REALPATH_PARENT``. Note that ``HX_REALPATH_ABSOLUTE``, which would
+ also be required to get libc's ``realpath``(3) behavior, is not
+ included in the set.
+
+``HX_REALPATH_ABSOLUTE``
+ Requests that the output path shall be absolute. In the absence of this
+ flag, an absolute output path will only be produced if the input path
+ is also absolute.
+
+``HX_REALPATH_SELF``
+ Request resolution of `.` path components.
+
+``HX_REALPATH_PARENT`
+ Request resolution of `..` path components.
+
+The result is stored in a memory container whose pointer is returned through
+``*buf``. The return value of the function will be negative to indicate a
+possible system error, or be positive non-zero for success.
+
+
+Operations on directories
+=========================
+
+.. code-block:: c
+
+ #include <libHX/io.h>
+
+ int HX_mkdir(const char *path, unsigned int mode);
+ int HX_rrmdir(const char *path);
+
+``HX_mkdir`` will create the directory given by path and all its parents that
+do not exist yet using the given mode. It is equivalent to the ``mkdir -p``
+shell command. It will return >0 for success, or ``-errno`` on error.
+
+``HX_rrmdir`` also maps to an operation commonly done on the shell, ``rm -Rf``,
+deleting the directory given by path, including all files within it and its
+subdirectories. Errors during deletion are ignored, but if there was any, the
+errno value of the first one is returned negated.
+
+
+Operations on files
+===================
+
+.. code-block:: c
+
+ #include <libHX/io.h>
+
+ #define HXF_KEEP ...
+ #define HXF_UID ...
+ #define HXF_GID ...
+
+ int HX_copy_file(const char *src, const char *dest, unsigned int flags, ...);
+ int HX_copy_dir(const char *src, const char *dest, unsigned int flags, ...);
+ char *HX_slurp_fd(int fd, size_t *outsize);
+ char *HX_slurp_file(const char *file, size_t *outsize);
+
+``HX_copy_file``
+ Copies one named file to a new location. Possible ``flags`` are
+ ``HXF_KEEP``, ``HXF_UID`` and ``HXF_GID``. Error checking by
+ ``HX_copy_file`` is flakey. ``HX_copy_file`` will return >0 on success,
+ or ``-errno`` on failure. Errors can arise from the use of the syscalls
+ ``open``, ``read`` and ``write``. The return value of ``fchmod``, which
+ is used to set the UID and GID, is actually ignored, which means
+ verifying that the owner has been set cannot be detected with
+ ``HX_copy_file`` alone (historic negligience?).
+
+``HXF_KEEP``
+ Do not overwrite existing files.
+
+``HXF_UID``
+ Change the new file's owner to the UID given in the varargs section
+ (...). ``HXF_UID`` is processed before ``HXF_GID``.
+
+``HXF_GID``
+ Change the new file's group owner to the GID given in the varargs
+ section. This is processed after ``HXF_UID``.
+
+``HX_copy_dir``
+ Copies one named directory to a new location, recursively.
+ (Uses ``HX_copy_file`` and ``HX_copy_dir``.) Error checking by
+ ``HX_copy_dir`` is flakey.
+
+``HX_slurp_fd``
+ Reads all remaining bytes from the given filedescriptor ``fd`` and
+ returns a pointer to a newly-allocated content buffer. If ``outsize``
+ is not ``NULL``, the size of the buffer will be written to it. The
+ buffer is always terminated by a gratuitious NUL (not counted in
+ ``outsize``). Once no longer needed, the buffer should be released with
+ ``free``.
+
+``HX_slurp_file``
+ Reads all bytes from the given filename and returns a pointer to the
+ content buffer. Inherits all the characteristics from ``HX_slurp_fd``.
+
+
+Filedescriptor helpers
+======================
+
+.. code-block:: c
+
+ #include <libHX/io.h>
+
+ ssize_t HXio_fullread(int fd, void *buf, size_t size, unsigned int flags);
+ ssize_t HXio_fullwrite(int fd, const void *buf, size_t size, unsigned int flags);
+ ssize_t HX_sendfile(int dst, int src, size_t count);
+
+Since plain ``read``(2) and ``write``(2) may process only part of the buffer —
+even more likely so with sockets —, libHX provides two functions that calls
+these in a loop to retry said operations until the full amount has been
+processed. Since read and write can also be used with socket file descriptors,
+so can these.
+
+``HX_sendfile`` wraps ``sendfile``(2) for the same reason; in addition, it
+falls back to a read-write loop on platforms which do not offer sendfile.
diff --git a/doc/generate b/doc/generate
deleted file mode 100755
index 3fd48cf..0000000
--- a/doc/generate
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/bin/sh -ex
-
-if [ -z "$srcdir" ]; then
- srcdir=".";
-fi;
-rm -f libHX_Documentation.pdf
-lyx -e pdf2 "$srcdir/libHX_Documentation.lyx" || :
-# lyx-2.3.2 does not work with texlive-babel-2017.135.3
-# """
-# Package babel Error: You haven't specified a language option.
-# ...ry to proceed from here, type x to quit.)
-#
-# You need to specify a language, either as a global option
-# or as an optional argument to the \usepackage command;
-# You shouldn't try to proceed form here, type x to quit.
-# """
-# babel you so stupid for breaking backward comapt.
-
-test -e libHX_Documentation.pdf
diff --git a/doc/helper_headers.rst b/doc/helper_headers.rst
new file mode 100644
index 0000000..7b4c083
--- /dev/null
+++ b/doc/helper_headers.rst
@@ -0,0 +1,128 @@
+==============
+Helper headers
+==============
+
+ctype helpers
+=============
+
+Functions from the ``<ctype.h>`` header, including, but not limited to,
+``isalpha``, ``tolower``, and so forth, are defined to take an ``int`` as first
+argument. C strings consist of ``char``s, which may either be ``signed`` or
+``unsigned``. It does not matter for *characters_* but since ``char``s are
+implicitly convertible to *numbers*, one needs to explicitly cast chars to
+unsigned before feeding them to ``isalpha``.
+
+.. code-block:: c
+
+ /* “hyvää yötä”, UTF-8 encoded */
+
+ const char h[] = {'h', 'y', 'v', 0xc3, 0xa4, 0xc3, 0xa4, ' ',
+ 'y', 0xc3, 0xb6, 't', 0xc3, 0xa4};
+
+libHX's ctype_helper.h therefore provides wrappers with a different function
+signature that does the intended test. It does so by always taking ``unsigned
+char``. The implication is that EOF cannot be passed to ``HX_isalpha`` — not
+that there is a good reason to do so in the first place.
+
+.. code-block:: c
+
+ #include <libHX/ctype_helper.h>
+
+ bool HX_isalnum(unsigned char c);
+ bool HX_isalpha(unsigned char c);
+ bool HX_isdigit(unsigned char c);
+ bool HX_islower(unsigned char c);
+ bool HX_isprint(unsigned char c);
+ bool HX_isspace(unsigned char c);
+ bool HX_isupper(unsigned char c);
+ bool HX_isxdigit(unsigned char c);
+ unsigned char HX_tolower(unsigned char c);
+ unsigned char HX_toupper(unsigned char c);
+
+The ``HX_is*`` functions also differ from ctype's in that they return ``bool``
+instead of ``int``. Not all functions from ``ctype.h`` are present either;
+``isascii``, ``isblank``, ``iscntrl``, ``isgraph``, ``ispunct`` and
+``isxdigit`` have been omitted as the author has never needed them to this
+date.
+
+
+libxml2 helpers
+===============
+
+libxml2 defines a type called ``xmlChar`` for use within its strings.
+``xmlChar`` is typedef'ed to ``unsigned char`` by libxml2, causing compiler warnings related to
+differing signedness whenever interacting with strings from the
+outside world, which are usually just a pointer to char. Because
+casting is a real chore, ``libxml_helper.h`` will do it by
+providing some wrappers with better argument types.
+
+.. code-block:: c
+
+ #include <libHX/libxml_helper.h>
+
+ int xml_strcmp(const xmlChar *a, const char *b);
+ int xml_strcasecmp(const xmlChar *a, const char *b);
+
+ char *xml_getprop(xmlNode *node, const char *attr);
+ char *xml_getnsprop(xmlNode *node, const char *nsprefix, const char *attr);
+ xmlAttr *xml_newprop(xmlNode *node, const char *attr);
+ xmlNode *xml_newnode(xmlNode *parent, const char *name, const char *value);
+ xmlAttr *xml_setprop(xmlNode *node, const char *name, const char *value);
+
+The functions map to ``strcmp``, ``strcasecmp``, ``xmlGetProp``,
+``xmlNewPropxmlNewProp``, ``xmlNewTextNodexmlNewTextNode`` and
+``xmlSetPropxmlSetProp``, respectively.
+
+``xml_getnsprop`` works similar to ``xmlGetNsProp``, but instead of taking a
+namespace URI, it does a lookup by namespace prefix. The argument order is also
+different compared to ``xmlGetNsProp``.
+
+
+wxWidgets
+=========
+
+.. code-block:: c++
+
+ #include <libHX/wx_helper.hpp>
+
+Shortcut macros
+---------------
+
+``wxACV``
+ Expands to ``wxALIGN_CENTER_VERTICAL``.
+
+``wxCDF``
+ Expands to a set of common dialog flags for wxDialogs, which includes
+ ``wxDEFAULT_FRAME_STYLE`` and a flag such that the dialog does not
+ create a new window in the task bar (``wxFRAME_NO_TASKBAR``).
+
+``wxDPOS``
+ Expands to ``wxDefaultPosition``.
+
+``wxDSIZE``
+ Expands to ``wxDefaultSize``.
+
+``wxDSPAN``
+ Expands to ``wxDefaultSpan``.
+
+String conversion
+-----------------
+
+.. code-block:: c++
+
+ wxString wxfu8(const char *);
+ wxString wxfv8(const char *);
+ const char *wxtu8(const wxString &);
+
+``wxfu8``
+ Converts a UTF-8 string to a ``wxString`` object.
+
+``wxfv8``
+ Converts a UTF-8 string to an entity usable by ``wxPrintf``.
+
+``wxtu8``
+ Converts a wxString to a pointer to char usable by ``printf``. Note
+ that the validity of the pointer is very limited and usually does not
+ extend beyond the statement in which it is used. Hence, storing the
+ pointer in a variable (``const char *p = wxtu8(s);``) will make ``p``
+ dangling as soon as the assignment has been completed.
diff --git a/doc/history.rst b/doc/history.rst
new file mode 100644
index 0000000..674b39f
--- /dev/null
+++ b/doc/history.rst
@@ -0,0 +1,22 @@
+History
+=======
+
+The origins of libHX trace back, even crossing a language boundary, to when the
+author started on using Perl in 1999. Some tasks were just too damn useful to
+be open-coded every time. Two such examples are what is these days known as
+``HX_basename`` and ``HX_mkdir``. The name does not relate to anyone's
+initials; it is a result of a truncation of the author's nick used years ago.
+
+Around the beginning of 2003, the author also started on the C programming
+language and soon the small library was converted from Perl to C. The libHX
+library as of today is the result of working with C ever since, and naturally
+grew from there to support whatever the author was in need of.
+
+The “correct” name for libHX is with an uppercase “H” and uppercase “X”, and
+the same is used for filenames, such as “libHX.so”[#lowercase]
+
+.. [#lowercase] Software projects may choose to entirely lowercase the project
+ name for use in filenames, such as the Linux kernel which is
+ released as ``linux-${version}.tar.bz2``, or the project may
+ choose to keep the name for filenames, like Mesa and SDL do.
+ libHX is of the latter.
diff --git a/doc/init.rst b/doc/init.rst
new file mode 100644
index 0000000..ebaa4d8
--- /dev/null
+++ b/doc/init.rst
@@ -0,0 +1,17 @@
+Initialization
+==============
+
+.. code-block:: c
+
+ #include <libHX/init.h>
+
+ int HX_init(void);
+ void HX_exit(void);
+
+Before using the library's functions, ``HX_init`` must be called. This function
+will initialize any needed state libHX needs for itself, if any. It is designed
+to be invoked multiple times, such as for example, from different libraries
+linking to libHX itself, and will refcount. On success, >0 is returned. If
+there was an error, it will return a negative error code or zero. ``HX_exit``
+is the logical counterpart of notifying that the library is no longer used.
+
diff --git a/doc/inline_clist.rst b/doc/inline_clist.rst
new file mode 100644
index 0000000..f7bf138
--- /dev/null
+++ b/doc/inline_clist.rst
@@ -0,0 +1,59 @@
+=================================
+Counted inline doubly-linked list
+=================================
+
+clist is the inline doubly-linked list cousin of the inline doubly-linked list,
+extended by a counter to retrieve the number of elements in the list in O(1)
+time. This is also why all operations always require the list head. For
+traversal of clists, use the corresponding HXlist macros.
+
+Synopsis
+========
+
+.. code-block:: c
+
+ #include <libHX/list.h>
+
+ struct HXclist_head {
+ /* public readonly: */
+ unsigned int items;
+ /* Undocumented fields are considered “private” */
+ };
+
+ HXCLIST_HEAD_INIT(name);
+ HXCLIST_HEAD(name);
+ void HXclist_init(struct HXclist_head *head);
+ void HXclist_unshift(struct HXclist_head *head, struct HXlist_head *new_node);
+ void HXclist_push(struct HXclist_head *head, struct HXlist_head *new_node);
+ type HXclist_pop(struct HXclist_head *head, type, member);
+ type HXclist_shift(struct HXclist_head *head, type, member);
+ void HXclist_del(struct HXclist_head *head, struct HXlist_chead *node);
+
+``HXCLIST_HEAD_INIT``
+ Macro that expands to the static initializer for a clist.
+
+``HXCLIST_HEAD``
+ Macro that expands to the definition of a clist head, with
+ initialization.
+
+``HXclist_init``
+ Initializes a clist. This function is generally used when the head has
+ been allocated from the heap.
+
+``HXclist_unshift``
+ Adds the node to the front of the list.
+
+``HXclist_push``
+ Adds the node to the end of the list.
+
+``HXclist_pop``
+ Removes the last node in the list and returns it.
+
+``HXclist_shift``
+ Removes the first node in the list and returns it.
+
+``HXclist_del``
+ Deletes the node from the list.
+
+The list count in the clist head is updated whenever a modification is done on
+the clist through these functions.
diff --git a/doc/inline_list.rst b/doc/inline_list.rst
new file mode 100644
index 0000000..e60e89f
--- /dev/null
+++ b/doc/inline_list.rst
@@ -0,0 +1,253 @@
+=========================
+Inline doubly-linked list
+=========================
+
+Classical linked-list implementations, such as HXdeque, either store the actual
+data within a node, or indirectly through a pointer, but the “inline
+doubly-linked list” instead does it reverse and has the list head within the
+data structure.
+
+A classic linked-list implementations with direct/indirect data blocks may look
+like so:
+
+.. code-block:: c
+
+ struct package_desc {
+ char *package_name;
+ int version;
+
+ };
+
+ struct classic_direct_node {
+ struct classic_direct_node *next, *prev;
+ struct package_desc direct_data;
+ };
+ struct classic_indirect_node {
+ struct classic_indirect_node *next, *prev;
+ void *indirect_data;
+ };
+
+Whereas in an inline list, the list head (next,prev pointers) inlined into the data
+block:
+
+.. code-block:: c
+
+ struct package_desc {
+ struct HXlist_head list;
+ char *package_name;
+ int version;
+ };
+
+At first glance, an inline list does not look much different from ``struct
+classic_direct_data``, it is mostly a viewpoint decision which struct is in the
+foreground.
+
+
+Synopsis
+========
+
+.. code-block:: c
+
+ #include <libHX/list.h>
+
+ struct HXlist_head {struct HXlist_head
+ /* All fields considered private */
+ };
+
+ HXLIST_HEAD_INIT(name);
+ HXLIST_HEAD(name);
+ void HXlist_init(struct HXlist_head *list);
+ void HXlist_add(struct HXlist_head *list, struct HXlist_head *elem);
+ void HXlist_add_tail(struct HXlist_head *list, struct HXlist_head *elem);
+ void HXlist_del(struct HXlist_head *element);
+ bool HXlist_empty(const struct HXlist_head *list);
+
+``HXLIST_HEAD_INIT``
+ This macro expands to the static initializer for a list head.
+
+``HXLIST_HEAD``
+ This macro expands to the definition of a list head (i.e. ``struct
+ HXlist_head name = HXLIST_HEAD_INIT;``).
+
+``HXlist_init``
+ Initializes the list head. This function is generally used when the
+ list head is on the heap where the static initializer cannot be used.
+
+``HXlist_add``
+ Adds ``elem`` to the front of the list.
+
+``HXlist_add_tail``
+ Adds ``elem`` to the end of the list.
+
+``HXlist_del``
+ Deletes the given element from the list.
+
+``HXlist_empty``
+ Tests whether the list is empty. (Note: For clists, you could also use
+ ``clist->items == 0``).
+
+
+Traversal
+=========
+
+Traversal is implemented using macros that expand to ``for()`` statements which
+can syntactically be used like them, i.e. curly braces may be omitted if only
+a single statement is in the body of the loop.
+
+The head parameter specifies the list head (``struct HXlist_head``), ``pos``
+specifies an iterator, also of type ``struct HXlist_head``. Lists can either be
+traversed in forward direction, or, using the ``*_rev`` variants, in reverse
+direction. The ``*_safe`` variants use a temporary ``n`` to hold the next
+object in the list, which is needed when ``pos`` itself is going to be
+inaccessible at the end of the block, through, for example, freeing its
+encompassing object.
+
+.. code-block:: c
+
+ HXlist_for_each(pos, head)
+ HXlist_for_each_rev(pos, head)
+ HXlist_for_each_safe(pos, n, head)
+ HXlist_for_each_rev_safe(pos, n, head)
+
+``HXlist_for_each``
+ Forward iteration over the list heads.
+
+``HXlist_for_each_rev``
+ Reverse iteration over the list heads.
+
+``HXlist_for_each_safe``
+ Forward iteration over the list heads that is safe against freeing pos.
+
+``HXlist_for_each_rev_safe``
+ Reverse iteration over the list heads that is safe against freeing pos.
+
+The ``*_entry`` variants use an iterator ``pos`` of the type of the
+encompassing object (e.g. ``struct item`` in below's example), so that the
+manual ``HXlist_entry`` invocation is not needed. ``member`` is the name of the
+list structure embedded into the item.
+
+.. code-block:: c
+
+ HXlist_for_each_entry(pos, head, member)HXlist_for_each_entry
+ HXlist_for_each_entry_rev(pos, head, member)HXlist_for_each_entry_rev
+ HXlist_for_each_entry_safe(pos, n, head, member)HXlist_for_each_entry_safe
+
+``HXlist_for_each_entry``
+ Forward iteration over the list elements.
+
+``HXlist_for_each_entry_rev``
+ Reverse iteration over the list elements.
+
+``HXlist_for_each_entry_safe``
+ Forward iteration over the list elements that is safe against freeing
+ ``pos``.
+
+
+Examples
+========
+
+.. code-block:: c
+
+ struct item {
+ struct HXlist_head anchor;
+ char name[32];
+ };
+
+ struct HXlist_head *e;
+ struct item *i, *j;
+ HXLIST_HEAD(list);
+
+ i = malloc(sizeof(*i));
+ HXlist_init(&e->anchor);
+ strcpy(i->name, "foo");
+ HXlist_add_tail(&list, &i->anchor);
+
+ i = malloc(sizeof(*i));
+ HXlist_init(&e->anchor);
+ strcpy(i->name, "bar");
+ HXlist_add_tail(&list, &i->anchor);
+
+ HXlist_for_each(e, &list) {
+ i = HXlist_entry(e, typeof(*i), anchor);
+ printf("e=%p i=%p name=%s\n", e, i, i->name);
+ }
+
+ HXlist_for_each_entry(i, &list, anchor)
+ printf("i=%p name=%s\n", i, i->name);
+
+ HXlist_for_each_entry_rev(i, &list, anchor)
+ printf("i=%p name=%s\n", i, i->name);
+
+ HXlist_for_each_entry_safe(i, j, &list, anchor) {
+ printf("i=%p name=%s\n", i, i->name);
+ free(i);
+ }
+
+
+When to use HXdeque/HXlist
+==========================
+
+The choice whether to use HXdeque or HXlist/HXclist depends on whether one
+wants the list head handling on the developer or on the library. Especially for
+“atomic” and “small” data, it might be easier to just let HXdeque do the
+management. Compare the following two code examples to store strings in a
+HXdeque:
+
+.. code-block:: c
+
+ int main(int argc, const char **argv)
+ {
+ struct HXdeque *dq = HXdeque_init();
+ while (--argc)
+ HXdeque_push(dq, ++argv);
+ return 0;
+ }
+
+...and to store strings in a HXlist:
+
+.. code-block:: c
+
+ struct element {
+ struct HXlist_head list;
+ char *data;
+ };
+
+ int main(int main, const char **argv)
+ {
+ HXLIST_HEAD(lh);
+ while (--argc) {
+ struct element *e = malloc(sizeof(*e));
+ e->data = *++argv;
+ HXlist_init(&e->list);
+ HXlist_add_tail(&e->list);
+ }
+ return 0;
+ }
+
+These examples assume that ``argv`` is persistent, which, for the sample, is
+true.
+
+With HXlist, one needs to have a struct with a ``HXlist_head`` in it, and if
+one does not already have such a struct, e.g. by means of wanting to store more
+than just one value, one will need to create it first, as shown, and this may
+lead to an expansion of code.
+
+This however does not mean that HXlist is the better solution over HXdeque for
+data already available in a struct. As each struct has a ``list_head`` that is
+unique to the node, it is not possible to share this data. Trying to add a
+HXlist_head to another list is not going to end well, while HXdeque has no
+problem with this as list heads are detached from the actual data in HXdeque.
+
+Data can be added multiple times in a HXdeque without ill effects:
+
+.. code-block:: c
+
+ struct point p = {15, 30};
+ HXdeque_push(dq, &p);
+ HXdeque_push(dq, &p);
+
+To support this, an extra allocation is needed on the other hand. In a HXlist,
+to store *n* elements of compound data (e.g. ``struct point``), *n* allocations
+are needed, assuming the list head is a stack object, and the points are not.
+HXdeque will need at least *2n+1* allocations, *n* for the nodes, *n* for the
+points and another for the head.
diff --git a/doc/install.rst b/doc/install.rst
new file mode 100644
index 0000000..a0931b4
--- /dev/null
+++ b/doc/install.rst
@@ -0,0 +1,50 @@
+============
+Installation
+============
+
+libHX uses GNU autotools as a build environment, which means that
+all you have to run as a end-user is the configure with any
+options that you need, plus the usual make and make install as
+desired.
+
+Pay attention to multi-lib Linux distributions where you most
+likely need to specify a different libdir instead of using the
+default “lib”. In case of the Debian-style multi-arch/multi-lib
+proposal (http://wiki.debian.org/Multiarch)::
+
+.. code-block:: sh
+
+ ./configure --libdir='${prefix}/lib/x86_64-linux-gnu'
+
+and the classic-style 32-64 2-lib distributions::
+
+.. code-block:: sh
+
+ ./configure --libdir='${prefix}/lib64'
+
+Requirements
+------------
+
+* GNU C Compiler 3.3.5 or newer. Other compilers (non-GCC) have
+ not been tested in months — use at your own risk.
+
+* approximately 80–160 KB of disk space on Linux for the shared
+ library (depends on platform) and header files.
+
+A C++ compiler is only needed if you want to build the C++ test
+programs that come with libHX. By default, if there is no C++
+compiler present, these will not be built.
+
+* No external libraries are needed for compilation of libHX.
+ Helper files, like libxml_helper.h, may reference their include
+ files, but they are not used during compilation.
+
+
+Portability notice
+==================
+
+libHX runs on contemporary versions of Linux and Windows. It ought to work on
+Solaris and the BSD distributions, but this is not build-tested at this time.
+
+C99 is mandatory. The integer type ``int`` should at best have 32 bits at
+least.
diff --git a/doc/libHX_Documentation.lyx b/doc/libHX_Documentation.lyx
deleted file mode 100644
index 9e2e9f5..0000000
--- a/doc/libHX_Documentation.lyx
+++ /dev/null
@@ -1,24663 +0,0 @@
-#LyX 2.3 created this file. For more info see http://www.lyx.org/
-\lyxformat 544
-\begin_document
-\begin_header
-\save_transient_properties true
-\origin unavailable
-\textclass article
-\use_default_options true
-\maintain_unincluded_children false
-\language english
-\language_package default
-\inputencoding utf8
-\fontencoding global
-\font_roman "lmodern" "default"
-\font_sans "lmss" "default"
-\font_typewriter "lmtt" "default"
-\font_math "auto" "auto"
-\font_default_family default
-\use_non_tex_fonts false
-\font_sc false
-\font_osf false
-\font_sf_scale 100 100
-\font_tt_scale 100 100
-\use_microtype false
-\use_dash_ligatures true
-\graphics default
-\default_output_format default
-\output_sync 0
-\bibtex_command default
-\index_command default
-\paperfontsize 12
-\spacing single
-\use_hyperref true
-\pdf_bookmarks false
-\pdf_bookmarksnumbered false
-\pdf_bookmarksopen false
-\pdf_bookmarksopenlevel 1
-\pdf_breaklinks false
-\pdf_pdfborder true
-\pdf_colorlinks false
-\pdf_backref page
-\pdf_pdfusetitle true
-\papersize a4paper
-\use_geometry true
-\use_package amsmath 1
-\use_package amssymb 1
-\use_package cancel 1
-\use_package esint 1
-\use_package mathdots 1
-\use_package mathtools 1
-\use_package mhchem 1
-\use_package stackrel 1
-\use_package stmaryrd 1
-\use_package undertilde 1
-\cite_engine natbib
-\cite_engine_type numerical
-\biblio_style plainnat
-\use_bibtopic false
-\use_indices false
-\paperorientation portrait
-\suppress_date false
-\justification true
-\use_refstyle 0
-\use_minted 0
-\index Index
-\shortcut idx
-\color #008000
-\end_index
-\leftmargin 2cm
-\topmargin 2cm
-\rightmargin 2cm
-\bottommargin 2cm
-\secnumdepth 3
-\tocdepth 1
-\paragraph_separation indent
-\paragraph_indentation default
-\is_math_indent 0
-\math_numbering_side default
-\quotes_style english
-\dynamic_quotes 0
-\papercolumns 1
-\papersides 1
-\paperpagestyle default
-\tracking_changes false
-\output_changes false
-\html_math_output 0
-\html_css_as_file 0
-\html_be_strict false
-\end_header
-
-\begin_body
-
-\begin_layout Title
-libHX 3.25
-\begin_inset Newline newline
-\end_inset
-
-Documentation
-\end_layout
-
-\begin_layout Standard
-\begin_inset VSpace defskip
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-\begin_inset CommandInset toc
-LatexCommand tableofcontents
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-\begin_inset Newpage clearpage
-\end_inset
-
-
-\end_layout
-
-\begin_layout Section
-Introduction
-\end_layout
-
-\begin_layout Standard
-libHX collects many useful day-to-day functions, intended to reduce the
- amount of otherwise repeatedly open-coded instructions.
-\end_layout
-
-\begin_layout Section
-Overview
-\end_layout
-
-\begin_layout Itemize
-Maps (key-value pairs) (section
-\begin_inset space ~
-\end_inset
-
-
-\begin_inset CommandInset ref
-LatexCommand ref
-reference "sec:maps"
-
-\end_inset
-
-)
-\begin_inset Newline newline
-\end_inset
-
-Originally created to provide a data structure like Perl's associative arrays.
- Different map types and characteristics are available, such as hash-based
- or the traditional rbtree.
-\end_layout
-
-\begin_layout Itemize
-Deques (section
-\begin_inset space ~
-\end_inset
-
-
-\begin_inset CommandInset ref
-LatexCommand ref
-reference "sec:deque"
-
-\end_inset
-
-)
-\begin_inset Newline newline
-\end_inset
-
-Double-ended queues, implemented as a doubly-linked list with sentinels,
- are suitable for both providing stack and queue functionality.
-\end_layout
-
-\begin_layout Itemize
-Inline doubly-linked list, uncounted and counted (sections
-\begin_inset space ~
-\end_inset
-
-
-\begin_inset CommandInset ref
-LatexCommand ref
-reference "sec:list"
-
-\end_inset
-
- and
-\begin_inset space ~
-\end_inset
-
-
-\begin_inset CommandInset ref
-LatexCommand ref
-reference "sec:clist"
-
-\end_inset
-
-)
-\begin_inset Newline newline
-\end_inset
-
-Light-weight linked lists as used in the Linux kernel.
-\end_layout
-
-\begin_layout Itemize
-Common string operations (section
-\begin_inset space ~
-\end_inset
-
-
-\begin_inset CommandInset ref
-LatexCommand ref
-reference "sec:strings"
-
-\end_inset
-
-)
-\begin_inset Newline newline
-\end_inset
-
-basename, chomp, dirname, getl(ine), split, strlcat/strlcpy, strlower/-upper,
- str*trim, strsep, etc.
-\end_layout
-
-\begin_layout Itemize
-Memory containers, auto-sizing string operations (section
-\begin_inset space ~
-\end_inset
-
-
-\begin_inset CommandInset ref
-LatexCommand ref
-reference "sec:mc"
-
-\end_inset
-
-)
-\begin_inset Newline newline
-\end_inset
-
-Scripting-like invocation for string handling
-\begin_inset space ~
-\end_inset
-
-— automatically doing (re)allocations as needed.
-\end_layout
-
-\begin_layout Itemize
-String formatter (section
-\begin_inset space ~
-\end_inset
-
-
-\begin_inset CommandInset ref
-LatexCommand ref
-reference "sec:format"
-
-\end_inset
-
-)
-\begin_inset Newline newline
-\end_inset
-
-HXfmt is a small template system for by-name variable expansion.
- It can be used to substitute placeholders in format strings supplied by
- the user by appropriate expanded values defined by the program.
-\end_layout
-
-\begin_layout Itemize
-Directory creation, traversal, removal, and file copying (sections
-\begin_inset space ~
-\end_inset
-
-
-\begin_inset CommandInset ref
-LatexCommand ref
-reference "sec:dir-ops1"
-
-\end_inset
-
-,
-\begin_inset CommandInset ref
-LatexCommand ref
-reference "sec:dir-ops2"
-
-\end_inset
-
- and
-\begin_inset space ~
-\end_inset
-
-
-\begin_inset CommandInset ref
-LatexCommand ref
-reference "sec:file-ops"
-
-\end_inset
-
-)
-\end_layout
-
-\begin_layout Itemize
-Option parsing (section
-\begin_inset space ~
-\end_inset
-
-
-\begin_inset CommandInset ref
-LatexCommand ref
-reference "sec:option"
-
-\end_inset
-
-)
-\begin_inset Newline newline
-\end_inset
-
-Table-/callback-based option parser that works similar to Perl's
-\family typewriter
-Getopt::Long
-\family default
-
-\begin_inset space ~
-\end_inset
-
-— no open-coding but a single
-\begin_inset Quotes eld
-\end_inset
-
-atomic
-\begin_inset Quotes erd
-\end_inset
-
- invocation.
-\end_layout
-
-\begin_layout Itemize
-Shell-style config parser (section
-\begin_inset space ~
-\end_inset
-
-
-\begin_inset CommandInset ref
-LatexCommand ref
-reference "sec:shconf"
-
-\end_inset
-
-)
-\begin_inset Newline newline
-\end_inset
-
-Configuration file reader for Shell-style
-\begin_inset Quotes eld
-\end_inset
-
-configuration
-\begin_inset Quotes erd
-\end_inset
-
- files with key-value pairs, as usually foudn in
-\family typewriter
-/etc\SpecialChar breakableslash
-sysconfig
-\family default
-.
-\end_layout
-
-\begin_layout Itemize
-Random number gathering (section
-\begin_inset space ~
-\end_inset
-
-
-\begin_inset CommandInset ref
-LatexCommand ref
-reference "sec:random"
-
-\end_inset
-
-)
-\begin_inset Newline newline
-\end_inset
-
-Convenient wrapper that uses kernel-provided RNG devices when available.
-\end_layout
-
-\begin_layout Itemize
-External process invocation (section
-\begin_inset space ~
-\end_inset
-
-
-\begin_inset CommandInset ref
-LatexCommand ref
-reference "sec:proc"
-
-\end_inset
-
-)
-\begin_inset Newline newline
-\end_inset
-
-Setting up pipes for the standard file descriptors for sending/capturing
- data to/from a program.
-\end_layout
-
-\begin_layout Itemize
-
-\shape italic
-a bit more beyond that ...
- Miscellaneous
-\end_layout
-
-\begin_layout Section
-Resources
-\end_layout
-
-\begin_layout Standard
-As of this writing, the repository is located at
-\end_layout
-
-\begin_layout Itemize
-\begin_inset Flex URL
-status open
-
-\begin_layout Plain Layout
-
-git://libhx.git.sf.net/gitroot/libhx/libhx
-\end_layout
-
-\end_inset
-
-
-\begin_inset space ~
-\end_inset
-
-— clone URL
-\end_layout
-
-\begin_layout Itemize
-\begin_inset Flex URL
-status open
-
-\begin_layout Plain Layout
-
-http://libhx.git.sf.net/
-\end_layout
-
-\end_inset
-
-
-\begin_inset space ~
-\end_inset
-
-— gitweb interface
-\end_layout
-
-\begin_layout Itemize
-\begin_inset Flex URL
-status open
-
-\begin_layout Plain Layout
-
-http://libhx.sf.net/
-\end_layout
-
-\end_inset
-
-
-\begin_inset space ~
-\end_inset
-
-— home page (and link to tarballs)
-\end_layout
-
-\begin_layout Itemize
-\begin_inset Flex URL
-status open
-
-\begin_layout Plain Layout
-
-http://freecode.com/projects/libhx/
-\end_layout
-
-\end_inset
-
-
-\begin_inset space ~
-\end_inset
-
-— Freecode page (useful for automatic notification of new releases)
-\end_layout
-
-\begin_layout Section
-Installation
-\end_layout
-
-\begin_layout Standard
-libHX uses GNU autotools as a build environment, which means that all you
- have to run as a end-user is the
-\family typewriter
-configure
-\family default
- with any options that you need, plus the usual
-\family typewriter
-make
-\family default
- and
-\family typewriter
-make install
-\family default
- as desired.
-\end_layout
-
-\begin_layout Standard
-Pay attention to multi-lib Linux distributions where you most likely need
- to specify a different libdir instead of using the default
-\begin_inset Quotes eld
-\end_inset
-
-lib
-\begin_inset Quotes erd
-\end_inset
-
-.
- In case of the Debian-style multi-arch/multi-lib proposal (
-\begin_inset Flex URL
-status collapsed
-
-\begin_layout Plain Layout
-
-http://wiki.debian.org/Multiarch
-\end_layout
-
-\end_inset
-
-):
-\end_layout
-
-\begin_layout LyX-Code
-$
-\series bold
-./configure --libdir='${prefix}/lib/x86_64-linux-gnu'
-\end_layout
-
-\begin_layout Standard
-and the classic-style 32-64 2-lib distributions:
-\end_layout
-
-\begin_layout LyX-Code
-$
-\series bold
-./configure --libdir='${prefix}/lib64'
-\end_layout
-
-\begin_layout Subsection
-Requirements
-\end_layout
-
-\begin_layout Itemize
-GNU C Compiler 3.3.5 or newer.
- Other compilers (non-GCC) have not been tested in months
-\begin_inset space ~
-\end_inset
-
-— use at your own risk.
-\end_layout
-
-\begin_layout Itemize
-approximately 80–160
-\begin_inset space ~
-\end_inset
-
-KB of disk space on Linux for the shared library (depends on platform) and
- header files.
-\end_layout
-
-\begin_layout Standard
-A C++ compiler is only needed if you want to build the C++ test programs
- that come with libHX.
- By default, if there is no C++ compiler present, these will not be built.
-\end_layout
-
-\begin_layout Itemize
-No external libraries are needed for compilation of libHX.
- Helper files, like
-\family typewriter
-libxml_\SpecialChar softhyphen
-helper.h
-\family default
-, may reference their include files, but they are not used during compilation.
-\end_layout
-
-\begin_layout Section
-Portability notice
-\end_layout
-
-\begin_layout Standard
-libHX runs on contemporary versions of Linux, Solaris and the three BSD
- distributions.
- It might even work on Microsoft Windows, but this is not tested very often,
- if at all.
- Overly old systems, especially Unices, are not within focus.
- While AIX
-\begin_inset space ~
-\end_inset
-
-5.3 might still classify as contemporary, strangelets like
-\begin_inset Quotes eld
-\end_inset
-
-Ultrix
-\begin_inset Quotes erd
-\end_inset
-
- or
-\begin_inset Quotes eld
-\end_inset
-
-Dynix
-\begin_inset Quotes erd
-\end_inset
-
- you can find in the autotools-related file
-\family typewriter
-config.guess
-\family default
- are some that are definitely not.
-\end_layout
-
-\begin_layout Standard
-Furthermore, a compiler that understands the C99 or GNU89 standard is required.
- The integer type
-\begin_inset Quotes eld
-\end_inset
-
-int
-\begin_inset Quotes erd
-\end_inset
-
- should at best have 32 bits at least.
- There is no ultra-portable version as of this writing, but feel free to
- start one akin to the
-\begin_inset Quotes eld
-\end_inset
-
-p
-\begin_inset Quotes erd
-\end_inset
-
- variants of OpenBSD software such as OpenSSH.
-\end_layout
-
-\begin_layout Section
-History
-\end_layout
-
-\begin_layout Standard
-The origins of libHX trace back, even crossing a language boundary, to when
- the author started on using Perl in 1999.
- Some tasks were just too damn useful to be open-coded every time.
- Two such examples are what is these days known as
-\family typewriter
-HX_basename
-\family default
- and
-\family typewriter
-HX_mkdir
-\family default
-.
- The name does not relate to anyone's initials; it is a result of a truncation
- of the author's nick used years ago.
-\end_layout
-
-\begin_layout Standard
-Around the beginning of 2003, the author also started on the C programming
- language and soon the small library was converted from Perl to C.
- The libHX library as of today is the result of working with C ever since,
- and naturally grew from there to support whatever the author was in need
- of.
-\end_layout
-
-\begin_layout Standard
-The
-\begin_inset Quotes eld
-\end_inset
-
-correct
-\begin_inset Quotes erd
-\end_inset
-
- name for libHX is with an uppercase
-\begin_inset Quotes eld
-\end_inset
-
-H
-\begin_inset Quotes erd
-\end_inset
-
- and uppercase
-\begin_inset Quotes eld
-\end_inset
-
-X
-\begin_inset Quotes erd
-\end_inset
-
-, and the same is used for filenames, such as
-\begin_inset Quotes eld
-\end_inset
-
-libHX.so
-\begin_inset Quotes erd
-\end_inset
-
-
-\begin_inset Foot
-status open
-
-\begin_layout Plain Layout
-Software projects may choose to entirely lowercase the project name for
- use in filenames, such as the Linux kernel which is released as
-\family typewriter
-linux-${
-\family default
-\shape italic
-version
-\family typewriter
-\shape default
-}.tar.bz2
-\family default
-, or the project may choose to keep the name for filenames, like Mesa and
- SDL do.
- libHX is of the latter.
-\end_layout
-
-\end_inset
-
-.
-\end_layout
-
-\begin_layout Standard
-\begin_inset Newpage clearpage
-\end_inset
-
-
-\end_layout
-
-\begin_layout Part
-General
-\end_layout
-
-\begin_layout Standard
-Many functions are prefixed with
-\begin_inset Quotes eld
-\end_inset
-
-
-\family typewriter
-HX_
-\family default
-
-\begin_inset Quotes erd
-\end_inset
-
- or
-\begin_inset Quotes eld
-\end_inset
-
-
-\family typewriter
-HXsubsys_
-\family default
-
-\begin_inset Quotes erd
-\end_inset
-
-, as are structures (sometimes without underscores, be sure to check the
- syntax and names), to avoid name clashes with possibly existing files.
- Functions that are not tied to a specific data structure such as most of
- the string functions (see chapter
-\begin_inset space ~
-\end_inset
-
-
-\begin_inset CommandInset ref
-LatexCommand ref
-reference "sec:strings"
-
-\end_inset
-
-) use the subsystem-less prefix,
-\begin_inset Quotes eld
-\end_inset
-
-
-\family typewriter
-HX_
-\family default
-
-\begin_inset Quotes erd
-\end_inset
-
-.
- Functions from a clearly-defined subsystem, such as map or deque, augment
- the base prefix by a suffix, forming e.
-\begin_inset space \thinspace{}
-\end_inset
-
-g.
-\begin_inset space \space{}
-\end_inset
-
-
-\begin_inset Quotes eld
-\end_inset
-
-
-\family typewriter
-HXmap_
-\family default
-
-\begin_inset Quotes erd
-\end_inset
-
-.
-\end_layout
-
-\begin_layout Section
-Initialization
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-#include
-\series default
- <libHX/init.h>
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-int
-\series default
- HX_init(
-\series bold
-void
-\series default
-);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-libHX_init
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-void
-\series default
- HX_exit(
-\series bold
-void
-\series default
-);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-libHX_exit
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-Before using the library's functions,
-\family typewriter
-HX_init
-\family default
- must be called.
- This function will initialize any needed state libHX needs for itself,
- if any.
- It is designed to be invoked multiple times, such as for example, from
- different libraries linking to libHX itself, and will refcount.
- On success, >0 is returned.
- If there was an error, it will return a negative error code or zero.
-
-\family typewriter
-HX_exit
-\family default
- is the logical counterpart of notifying that the library is no longer used.
-\end_layout
-
-\begin_layout Section
-Type-checking casts
-\end_layout
-
-\begin_layout Standard
-The C++ language provides so-called
-\begin_inset Quotes eld
-\end_inset
-
-new-style casts
-\begin_inset Quotes erd
-\end_inset
-
-, referring to the four template-looking invocations
-\family typewriter
-static_cast<>
-\family default
-,
-\family typewriter
-const_cast<>
-\family default
-,
-\family typewriter
-reinterpret_cast<>
-\family default
- and
-\family typewriter
-dynamic_cast<>
-\family default
-.
- No such blessing was given to the C language, but still, even using macros
- that expand to the olde cast make it much easier to find casts in source
- code and annotate why something was casted, which is already an improvement.
-\begin_inset space ~
-\end_inset
-
-— Actually, it
-\shape italic
-is
-\shape default
- possible to do a some type checking, using some GCC extensions, which augments
- these macros from their documentary nature to an actual safety measure.
-\end_layout
-
-\begin_layout Subsection
-
-\family typewriter
-reinterpret_cast
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-reinterpret_cast
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-
-\family typewriter
-reinterpret_cast()
-\family default
- maps directly to the old-style typecast,
-\family typewriter
-(type)(expr)
-\family default
-, and causes the bit pattern for the expr rvalue to be
-\begin_inset Quotes eld
-\end_inset
-
-reinterpreted
-\begin_inset Quotes erd
-\end_inset
-
- as a new type.
- You will notice that
-\begin_inset Quotes eld
-\end_inset
-
-reinterpret
-\begin_inset Quotes erd
-\end_inset
-
- is the longest of all the
-\family typewriter
-*_cast
-\family default
- names, and can easily cause your line to grow to 80 columns (the good maximum
- in many style guides).
- As a side effect, it is a good indicator that something potentially dangerous
- might be going on, for example converting intergers from/to pointer.
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-#include
-\series default
- <libHX/defs.h>
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-libHX/defs.h
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-
-\begin_inset Newline newline
-\end_inset
-
-int
-\series default
- i;
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-/*
-\family roman
-\series default
-\shape italic
-Tree with numeric keys
-\family default
-\series bold
-\shape default
- */
-\series default
-
-\begin_inset Newline newline
-\end_inset
-
-tree = HXhashmap_init(0);
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-for
-\series default
- (i = 0; i < 6; ++i)
-\begin_inset Newline newline
-\end_inset
-
- HXmap_add(tree,
-\series bold
-reinterpret_cast
-\series default
-(
-\series bold
-void *
-\series default
-,
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-static_cast
-\series default
-(
-\series bold
-long
-\series default
-, i)), my_data);
-\end_layout
-
-\begin_layout Subsection
-
-\family typewriter
-signed_cast
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-signed_cast
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-This tag is for annotating that the cast was solely done to change the signednes
-s of pointers to char
-\begin_inset space ~
-\end_inset
-
-— and only those.
- No integers etc.
- The intention is to facilitate working with libraries that use
-\family typewriter
-unsigned char
-\begin_inset space ~
-\end_inset
-
-*
-\family default
- pointers, such as libcrypto and libssl (from the OpenSSL project) or libxml2,
- for example.
- See table
-\begin_inset space ~
-\end_inset
-
-
-\begin_inset CommandInset ref
-LatexCommand ref
-reference "tab:defs-signed_cast"
-
-\end_inset
-
- for the allowed conversions.
- C++ does
-\shape italic
-not
-\shape default
- actually have a
-\family typewriter
-signed_cast<>
-\family default
-, and one would have to use
-\family typewriter
-reinterpret_cast<>
-\family default
- to do the conversion, because
-\family typewriter
-static_cast<>
-\family default
- does not allow conversion from
-\family typewriter
-const char
-\begin_inset space ~
-\end_inset
-
-*
-\family default
- to
-\family typewriter
-const unsigned char
-\begin_inset space ~
-\end_inset
-
-*
-\family default
-, for example.
- (libHX's
-\family typewriter
-static_cast()
-\family default
- would also throw at least a compiler warning about the different signedness.)
- libHX does provide a
-\family typewriter
-signed_cast<>
-\family default
- for C++ though.
- This is where
-\family typewriter
-signed_cast
-\family default
- comes in.
-\end_layout
-
-\begin_layout Standard
-\begin_inset Float table
-wide false
-sideways false
-status open
-
-\begin_layout Plain Layout
-\align center
-\begin_inset Tabular
-<lyxtabular version="3" rows="7" columns="7">
-<features tabularvalignment="middle">
-<column alignment="center" valignment="top">
-<column alignment="center" valignment="top">
-<column alignment="center" valignment="top">
-<column alignment="center" valignment="top">
-<column alignment="center" valignment="top">
-<column alignment="center" valignment="top">
-<column alignment="center" valignment="top">
-<row>
-<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\series bold
-From
-\backslash
- To
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\series bold
-c*
-\series default
-section
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\series bold
-sc*
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\series bold
-uc*
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\series bold
-Cc*
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\series bold
-Csc*
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\series bold
-Cuc*
-\end_layout
-
-\end_inset
-</cell>
-</row>
-<row>
-<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\family typewriter
-\series bold
-char *
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-\begin_inset Formula $\checkmark$
-\end_inset
-
-
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-\begin_inset Formula $\checkmark$
-\end_inset
-
-
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-\begin_inset Formula $\checkmark$
-\end_inset
-
-
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-\begin_inset Formula $\checkmark$
-\end_inset
-
-
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-\begin_inset Formula $\checkmark$
-\end_inset
-
-
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-\begin_inset Formula $\checkmark$
-\end_inset
-
-
-\end_layout
-
-\end_inset
-</cell>
-</row>
-<row>
-<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\family typewriter
-\series bold
-signed char *
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-\begin_inset Formula $\checkmark$
-\end_inset
-
-
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-\begin_inset Formula $\checkmark$
-\end_inset
-
-
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-\begin_inset Formula $\checkmark$
-\end_inset
-
-
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-\begin_inset Formula $\checkmark$
-\end_inset
-
-
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-\begin_inset Formula $\checkmark$
-\end_inset
-
-
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-\begin_inset Formula $\checkmark$
-\end_inset
-
-
-\end_layout
-
-\end_inset
-</cell>
-</row>
-<row>
-<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\family typewriter
-\series bold
-unsigned char *
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-\begin_inset Formula $\checkmark$
-\end_inset
-
-
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-\begin_inset Formula $\checkmark$
-\end_inset
-
-
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-\begin_inset Formula $\checkmark$
-\end_inset
-
-
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-\begin_inset Formula $\checkmark$
-\end_inset
-
-
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-\begin_inset Formula $\checkmark$
-\end_inset
-
-
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-\begin_inset Formula $\checkmark$
-\end_inset
-
-
-\end_layout
-
-\end_inset
-</cell>
-</row>
-<row>
-<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\family typewriter
-\series bold
-const char *
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-–
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-–
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-–
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-\begin_inset Formula $\checkmark$
-\end_inset
-
-
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-\begin_inset Formula $\checkmark$
-\end_inset
-
-
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-\begin_inset Formula $\checkmark$
-\end_inset
-
-
-\end_layout
-
-\end_inset
-</cell>
-</row>
-<row>
-<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\family typewriter
-\series bold
-const signed char *
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-–
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-–
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-–
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-\begin_inset Formula $\checkmark$
-\end_inset
-
-
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-\begin_inset Formula $\checkmark$
-\end_inset
-
-
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-\begin_inset Formula $\checkmark$
-\end_inset
-
-
-\end_layout
-
-\end_inset
-</cell>
-</row>
-<row>
-<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\family typewriter
-\series bold
-const unsigned char *
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-–
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-–
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-–
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-\begin_inset Formula $\checkmark$
-\end_inset
-
-
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-\begin_inset Formula $\checkmark$
-\end_inset
-
-
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-\begin_inset Formula $\checkmark$
-\end_inset
-
-
-\end_layout
-
-\end_inset
-</cell>
-</row>
-</lyxtabular>
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Plain Layout
-\begin_inset Caption Standard
-
-\begin_layout Plain Layout
-\begin_inset CommandInset label
-LatexCommand label
-name "tab:defs-signed_cast"
-
-\end_inset
-
-Accepted conversions for
-\family typewriter
-signed_cast()
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Subsection
-
-\family typewriter
-static_cast
-\begin_inset CommandInset label
-LatexCommand label
-name "subsec:defs-static_cast"
-
-\end_inset
-
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-static_cast
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-Just like C++'s
-\family typewriter
-static_cast<>
-\family default
-, libHX's
-\family typewriter
-static_cast()
-\family default
- verifies that
-\family typewriter
-expr
-\family default
- can be implicitly converted to the new type (by a simple
-\family typewriter
-b
-\begin_inset space ~
-\end_inset
-
-=
-\begin_inset space ~
-\end_inset
-
-a
-\family default
-).
- Such is mainly useful for forcing a specific type, as is needed in varargs
- functions such as
-\family typewriter
-printf
-\family default
-, and where the conversion actually incurs other side effects, such as truncatio
-n or promotion:
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-/*
-\family roman
-\series default
-\shape italic
-Convert to a type printf knows about
-\family default
-\series bold
-\shape default
- */
-\begin_inset Newline newline
-\end_inset
-
-uint64_t
-\series default
- x = something;
-\begin_inset Newline newline
-\end_inset
-
-printf("%llu
-\backslash
-n",
-\series bold
-static_cast
-\series default
-(
-\series bold
-unsigned long long
-\series default
-, x));
-\end_layout
-
-\begin_layout Standard
-Because there is no format specifier for
-\family typewriter
-uint64_t
-\family default
- for
-\family typewriter
-printf
-\family default
-, a conversion to an accepted type is necessary to not cause undefined behavior.
- The author has seen code that did, for example,
-\family typewriter
-printf("%u")
-\family default
- on a
-\begin_inset Quotes eld
-\end_inset
-
-long
-\begin_inset Quotes erd
-\end_inset
-
-, which only works on architectures where
-\family typewriter
-sizeof(unsigned int)
-\family default
- happens to equal
-\family typewriter
-sizeof(unsigned long)
-\family default
-, such as x86_32.
- On x86_64, an
-\family typewriter
-unsigned long
-\family default
- is usually twice as big as an
-\family typewriter
-unsigned int
-\family default
-, so that 8 bytes are pushed onto the stack, but
-\family typewriter
-printf
-\family default
- only unshifts 4 bytes because the developer used
-\begin_inset Quotes eld
-\end_inset
-
-
-\family typewriter
-%u
-\family default
-
-\begin_inset Quotes erd
-\end_inset
-
-, leading to misreading the next variable on the stack.
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-/*
-\family roman
-\series default
-\shape italic
-Force promotion
-\family default
-\series bold
-\shape default
- */
-\series default
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-double
-\series default
- a_quarter =
-\series bold
-static_cast
-\series default
-(
-\series bold
-double
-\series default
-, 1) / 4;
-\end_layout
-
-\begin_layout Standard
-Were
-\begin_inset Quotes eld
-\end_inset
-
-1
-\begin_inset Quotes erd
-\end_inset
-
- not promoted to double, the result in
-\family typewriter
-q
-\family default
- would be zero because 1/4 is just an integer division, yielding zero.
- By making one of the operands a floating-point quantity, the compiler will
- instruct the FPU to compute the result.
- Of course, one could have also written
-\begin_inset Quotes eld
-\end_inset
-
-
-\family typewriter
-1.0
-\family default
-
-\begin_inset Quotes erd
-\end_inset
-
- instead of
-\family typewriter
-static_cast(double, 1)
-\family default
-, but this is left for the programmer to decide which style s/he prefers.
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-/*
-\family roman
-\series default
-\shape italic
-Force truncation before invoking second sqrt
-\family default
-\series bold
-\shape default
- */
-\series default
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-double
-\series default
- f = sqrt(
-\series bold
-static_cast
-\series default
-(
-\series bold
-int
-\series default
-, 10 * sqrt(3.0 / 4)));
-\end_layout
-
-\begin_layout Standard
-And here, the conversion from
-\family typewriter
-double
-\family default
- to
-\family typewriter
-int
-\family default
- incurs a (wanted) truncation of the decimal fraction, that is, rounding
- down for positive numbers, and rounding up for negative numbers.
-\end_layout
-
-\begin_layout Subsubsection
-Allowed conversions
-\end_layout
-
-\begin_layout Itemize
-
-\series bold
-Numbers
-\series default
-
-\begin_inset Newline newline
-\end_inset
-
-Conversion between numeric types, such as
-\family typewriter
-char
-\family default
-,
-\family typewriter
-short
-\family default
-,
-\family typewriter
-int
-\family default
-,
-\family typewriter
-long
-\family default
-,
-\family typewriter
-long long
-\family default
-,
-\family typewriter
-int
-\shape italic
-N
-\shape default
-_t
-\family default
-, both their signed and unsigned variants,
-\family typewriter
-float
-\family default
- and
-\family typewriter
-double
-\family default
-.
-\end_layout
-
-\begin_layout Itemize
-
-\series bold
-Generic Pointer
-\series default
-
-\begin_inset Newline newline
-\end_inset
-
-Conversion from
-\family typewriter
-type
-\begin_inset space ~
-\end_inset
-
-*
-\family default
- to and from
-\family typewriter
-void
-\begin_inset space ~
-\end_inset
-
-*
-\family default
-.
- (Where
-\family typewriter
-type
-\family default
- may very well be a type with further indirection.)
-\end_layout
-
-\begin_layout Itemize
-
-\series bold
-Generic Pointer (const)
-\begin_inset Newline newline
-\end_inset
-
-
-\series default
-Conversion from
-\family typewriter
-const type
-\begin_inset space ~
-\end_inset
-
-*
-\family default
- to and from
-\family typewriter
-const void
-\begin_inset space ~
-\end_inset
-
-*
-\family default
-.
-\end_layout
-
-\begin_layout Subsection
-
-\family typewriter
-const_cast
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-const_cast
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-
-\family typewriter
-const_cast
-\family default
- allows to add or remove
-\begin_inset Quotes eld
-\end_inset
-
-const
-\begin_inset Quotes erd
-\end_inset
-
- qualifiers from the type a pointer is pointing to.
- Due to technical limitations, it could not be implemented to support arbitrary
- indirection.
- Instead,
-\family typewriter
-const_cast
-\family default
- comes in three variants, to be used for indirection levels of 1 to 3:
-\end_layout
-
-\begin_layout Itemize
-
-\family typewriter
-\series bold
-const_cast
-\series default
-1(
-\series bold
-type
-\begin_inset space ~
-\end_inset
-
-*
-\series default
-, expr)
-\family default
- with
-\family typewriter
-\series bold
-typeof
-\series default
-(expr)
-\begin_inset space ~
-\end_inset
-
-=
-\series bold
-type
-\begin_inset space ~
-\end_inset
-
-*
-\family default
-\series default
-.
- (Similarly for any combinations of const.)
-\end_layout
-
-\begin_layout Itemize
-
-\family typewriter
-\series bold
-const_cast
-\series default
-2(
-\series bold
-type
-\begin_inset space ~
-\end_inset
-
-**
-\series default
-, expr) with
-\series bold
-typeof
-\series default
-(expr)
-\begin_inset space ~
-\end_inset
-
-=
-\series bold
-type
-\begin_inset space ~
-\end_inset
-
-**
-\family default
-\series default
- (and all combinations of const in all possible locations).
-\end_layout
-
-\begin_layout Itemize
-
-\family typewriter
-\series bold
-const_cast
-\series default
-3(
-\series bold
-type
-\begin_inset space ~
-\end_inset
-
-***
-\series default
-, expr) with
-\series bold
-typeof
-\series default
-(expr)
-\begin_inset space ~
-\end_inset
-
-=
-\series bold
-type
-\begin_inset space ~
-\end_inset
-
-***
-\family default
-\series default
- (and all combinations...).
-\end_layout
-
-\begin_layout Standard
-As indirection levels above 3 are really unlikely
-\begin_inset Foot
-status open
-
-\begin_layout Plain Layout
-See
-\begin_inset Quotes eld
-\end_inset
-
-Three Star Programmer
-\begin_inset Quotes erd
-\end_inset
-
-
-\end_layout
-
-\end_inset
-
-, having only these three type-checking cast macros was deemed sufficient.
- The only place where libHX even uses a level\SpecialChar nobreakdash
-3 indirection is in the option
- parser.
-\end_layout
-
-\begin_layout Standard
-\begin_inset Float table
-placement H
-wide false
-sideways false
-status open
-
-\begin_layout Plain Layout
-\align center
-\begin_inset Tabular
-<lyxtabular version="3" rows="2" columns="2">
-<features tabularvalignment="middle">
-<column alignment="center" valignment="top">
-<column alignment="center" valignment="top">
-<row>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\family typewriter
-int **
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\family typewriter
-int *const *
-\end_layout
-
-\end_inset
-</cell>
-</row>
-<row>
-<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\family typewriter
-const int **
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\family typewriter
-const int *const *
-\end_layout
-
-\end_inset
-</cell>
-</row>
-</lyxtabular>
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Plain Layout
-\begin_inset Caption Standard
-
-\begin_layout Plain Layout
-Accepted expr/target types for
-\family typewriter
-const_cast2
-\family default
-; example for the
-\begin_inset Quotes eld
-\end_inset
-
-int
-\begin_inset Quotes erd
-\end_inset
-
- type
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Plain Layout
-\align center
-Conversion is permitted when expression and target type are from the table.
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-It is currently not possible to use
-\family typewriter
-const_cast
-\family default
-1/2/3 on pointers to structures whose member structure is unknown.
-\end_layout
-
-\begin_layout Standard
-\begin_inset Newpage clearpage
-\end_inset
-
-
-\end_layout
-
-\begin_layout Section
-Macros
-\end_layout
-
-\begin_layout Standard
-All macros in this section are available through
-\family typewriter
-#include <libHX/defs.h>
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-libHX/defs.h
-\end_layout
-
-\end_inset
-
-.
-\end_layout
-
-\begin_layout Subsection
-Preprocessor
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-#define
-\series default
- HX_STRINGIFY(s)
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HX_STRINGIFY
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-Transforms the expansion of the argument
-\family typewriter
-s
-\family default
- into a C string.
-\end_layout
-
-\begin_layout Subsection
-Sizes
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-#define
-\series default
- HXSIZEOF_Z16
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXSIZEOF_Z16
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-#define
-\series default
- HXSIZEOF_Z32
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXSIZEOF_Z32
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-#define
-\series default
- HXSIZEOF_Z64
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXSIZEOF_Z64
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-Expands to the size needed for a buffer (including '
-\family typewriter
-
-\backslash
-0
-\family default
-') to hold the base-10 string representation of a 16\SpecialChar nobreakdash
-, 32\SpecialChar nobreakdash
- or 64\SpecialChar nobreakdash
-bit integer.
-\end_layout
-
-\begin_layout Subsection
-Locators
-\end_layout
-
-\begin_layout LyX-Code
-output_type
-\series bold
-*
-\series default
-containerof(
-\series bold
-input_type *
-\series default
-ptr, output_type, member);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-containerof
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-size_t
-\series default
- HXsizeof_member(struct_type, member);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXsizeof_member
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-output_type HXtypeof_member(struct_type, member);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXtypeof_member
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-
-\family typewriter
-containerof
-\family default
- will return a pointer to the struct in which
-\family typewriter
-ptr
-\family default
- is contained as the given member.
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-struct
-\series default
- foo {
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-int
-\series default
- bar;
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-int
-\series default
- baz;
-\begin_inset Newline newline
-\end_inset
-
-};
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-static void
-\series default
- test(
-\series bold
-int *
-\series default
-ptr)
-\begin_inset Newline newline
-\end_inset
-
-{
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-struct
-\series default
- foo
-\series bold
-*
-\series default
-self = containerof(baz,
-\series bold
-struct
-\series default
- foo, baz);
-\begin_inset Newline newline
-\end_inset
-
-}
-\end_layout
-
-\begin_layout Standard
-
-\family typewriter
-HXsizeof_member
-\family default
- and
-\family typewriter
-HXtypeof_member
-\family default
- are shortcuts (mainly for the C language) to get the size or type of a
- named member in a given struct:
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-char
-\series default
- padding[FIELD_SIZEOF(
-\series bold
-struct
-\series default
- foo, baz)];
-\end_layout
-
-\begin_layout Standard
-In C++, one can simply use
-\family typewriter
-sizeof(foo::baz)
-\family default
- and
-\family typewriter
-decltype(foo::baz)
-\family default
-.
-\end_layout
-
-\begin_layout Subsection
-Array size
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-size_t
-\series default
- ARRAY_SIZE(
-\series bold
-type
-\series default
- array
-\series bold
-[]
-\series default
-);
-\series bold
-/*
-\family roman
-\series default
-\shape italic
-implemented as a macro
-\family default
-\series bold
-\shape default
- */
-\series default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-ARRAY_SIZE
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-Returns the number of elements in
-\family typewriter
-array
-\family default
-.
- This only works with true arrays (
-\family typewriter
-type[]
-\family default
-), and will not output a meaningful value when used with a pointer-to-element
- (
-\family typewriter
-type
-\begin_inset space ~
-\end_inset
-
-*
-\family default
-), which is often used for array access too.
-\end_layout
-
-\begin_layout Subsection
-Compile-time build checks
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-int
-\series default
- BUILD_BUG_ON_EXPR(
-\series bold
-bool
-\series default
- condition);
-\series bold
-/*
-\family roman
-\series default
-\shape italic
-implemented as a macro
-\family default
-\series bold
-\shape default
- */
-\series default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-BUILD_BUG_ON_EXPR
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-void
-\series default
- BUILD_BUG_ON(
-\series bold
-bool
-\series default
- condition);
-\series bold
-/*
-\family roman
-\series default
-\shape italic
-implemented as a macro
-\family default
-\series bold
-\shape default
- */
-\series default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-BUILD_BUG_ON
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-Causes the compiler to fail when
-\family typewriter
-condition
-\family default
- evaluates to true.
- If not implemented for a compiler, it will be a no-op.
-
-\family typewriter
-BUILD_BUG_ON
-\family default
- is meant to be used as a standalone statement, while
-\family typewriter
-BUILD_\SpecialChar softhyphen
-BUG_\SpecialChar softhyphen
-ON_\SpecialChar softhyphen
-EXPR
-\family default
- is for when a check is to occur within an expression, that latter of which
- is useful for within macros when one cannot, or does not want to use multiple
- statements.
-\end_layout
-
-\begin_layout LyX-Code
-type DEMOTE_TO_PTR(type expr);
-\series bold
-/*
-\family roman
-\series default
-\shape italic
-macro
-\family default
-\series bold
-\shape default
- */
-\end_layout
-
-\begin_layout Standard
-Changes the type of expr to pointer type: If
-\family typewriter
-expr
-\family default
- of array type class, changes it to a pointer to the first element.
- If
-\family typewriter
-expr
-\family default
- of function type class, changes it to a pointer to the function.
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-int
-\series default
- main(
-\series bold
-void
-\series default
-);
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-int (*
-\series default
-fp
-\series bold
-)
-\series default
-(
-\series bold
-void
-\series default
-);
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-char
-\series default
- a
-\series bold
-[
-\series default
-123
-\series bold
-]
-\series default
-;
-\begin_inset Newline newline
-\end_inset
-
-DEMOTE_TO_PTR(main);
-\series bold
-/*
-\family roman
-\series default
-\shape italic
-yields
-\series bold
-int (*)
-\series default
-(
-\series bold
-void
-\series default
-);
-\family default
-\series bold
-\shape default
- */
-\series default
-
-\begin_inset Newline newline
-\end_inset
-
-DEMOTE_TO_PTR(fp);
-\series bold
-/*
-\series default
-also yields
-\family roman
-\series bold
-\shape italic
-int (*)
-\series default
-(
-\series bold
-void
-\series default
-);
-\family default
-\series bold
-\shape default
- */
-\series default
-
-\begin_inset Newline newline
-\end_inset
-
-DEMOTE_TO_PTR(a);
-\series bold
-/*
-\series default
-yields
-\family roman
-\series bold
-\shape italic
-char *
-\family default
-\shape default
- */
-\end_layout
-
-\begin_layout Subsection
-UNIX file modes
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-#define
-\series default
- S_IRUGO (S_IRUSR | S_IRGRP | S_IROTH)
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-S_IRUGO
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-#define
-\series default
- S_IWUGO (S_IWUSR | S_IWGRP | S_IWOTH)
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-S_IWUGO
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-#define
-\series default
- S_IXUGO (S_IXUSR | S_IXGRP | S_IXOTH)
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-S_IXUGO
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-#define
-\series default
- S_IRWXUGO (S_IRUGO | S_IWUGO | S_IXUGO)
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-S_IRWXUGO
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-The defines make it vastly easier to specify permissions for large group
- of users.
- For example, if one wanted to create a file with the permissions
-\family typewriter
-rw-r--r--
-\family default
- (ignoring the umask in this description),
-\family typewriter
-S_IRUSR
-\begin_inset space ~
-\end_inset
-
-| S_IWUSR
-\family default
- can now be used instead of the longer
-\family typewriter
-S_IRUSR
-\begin_inset space ~
-\end_inset
-
-| S_IWUSR
-\begin_inset space ~
-\end_inset
-
-| S_IRGRP
-\begin_inset space ~
-\end_inset
-
-| S_IROTH
-\family default
-.
-\end_layout
-
-\begin_layout Subsection
-VC runtime format specifiers
-\end_layout
-
-\begin_layout Standard
-The Microsoft Visual C runtime (a weak libc) uses non-standard format specifiers
- for certain types.
- Whereas C99 specifies
-\begin_inset Quotes eld
-\end_inset
-
-z
-\begin_inset Quotes erd
-\end_inset
-
- for
-\family typewriter
-size_t
-\family default
- and
-\begin_inset Quotes eld
-\end_inset
-
-ll
-\begin_inset Quotes erd
-\end_inset
-
- for long long, MSVCRT users must use
-\begin_inset Quotes eld
-\end_inset
-
-I
-\begin_inset Quotes erd
-\end_inset
-
- and
-\begin_inset Quotes eld
-\end_inset
-
-I64
-\begin_inset Quotes erd
-\end_inset
-
- (forming
-\family typewriter
-%Id
-\family default
- instead of
-\family typewriter
-%zd
-\family default
- for
-\family typewriter
-ssize_t
-\family default
-, for example).
- libHX provides two convenience macros for this:
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-#define
-\series default
- HX_SIZET_FMT "z"
-\family roman
-\shape italic
- or
-\family default
-\shape default
-"I"
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-HX_SIZET_FMT
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-#define
-\series default
- HX_LONGLONG_FMT "ll"
-\family roman
-\shape italic
- or
-\family default
-\shape default
-"I64"
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-HX_LONGLONG_FMT
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-These may be used together with printf or scanf:
-\end_layout
-
-\begin_layout LyX-Code
-printf("struct timespec is of size %" HX_SIZET_FMT "u
-\backslash
-n",
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-sizeof
-\series default
-(struct timespec));
-\end_layout
-
-\begin_layout Standard
-\begin_inset Newpage clearpage
-\end_inset
-
-
-\end_layout
-
-\begin_layout Section
-Miscellaneous functions
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-#include
-\series default
- <libHX/misc.h>
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-libHX/misc.h
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-int
-\series default
- HX_ffs(
-\series bold
-unsigned long
-\series default
- z);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HX_ffs
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-int
-\series default
- HX_fls(
-\series bold
-unsigned long
-\series default
- z);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HX_fls
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-void
-\series default
- HX_hexdump(
-\series bold
-FILE *
-\series default
-fp,
-\series bold
-const void *
-\series default
-ptr,
-\series bold
-unsigned int
-\series default
- len);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HX_hexdump
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-void
-\series default
- HX_zvecfree(
-\series bold
-char **
-\series default
-);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HX_zvecfree
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-unsigned int
-\series default
- HX_zveclen(
-\series bold
-const char *const *
-\series default
-);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HX_zveclen
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HX_ffs
-\family default
- Finds the first (lowest-significant) bit in a value and returns its position,
- or -1 to indicate failure.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HX_fls
-\family default
- Finds the last (most-significant) bit in a value and returns its position,
- or -1 to indicate failure.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HX_hexdump
-\family default
- Outputs a nice pretty-printed hex and ASCII dump to the filedescriptor
-
-\family typewriter
-fp
-\family default
-.
-
-\family typewriter
-ptr
-\family default
- is the memory area, of which
-\family typewriter
-len
-\family default
- bytes will be dumped.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HX_zvecfree
-\family default
- Frees the supplied Z-vector array.
- (Frees all array elements from the first element to (excluding) the first
-
-\family typewriter
-NULL
-\family default
- element.)
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HX_zveclen
-\family default
- Counts the number of array elements until the first
-\family typewriter
-NULL
-\family default
- array element is seen, and returns this number.
-\end_layout
-
-\begin_layout Section
-Time functions
-\end_layout
-
-\begin_layout Standard
-Time in POSIX systems is represented in
-\family typewriter
-struct timespec
-\family default
-.
- This structure is composed of two members: one integer for the number of
- full seconds in the time value, and one integer for the number of nanoseconds
- that remain when subtracting the full seconds from the time value.
- POSIX leaves it unspecified how negative time is to be represented with
- this structure, so I have devised an algebra for use with the same struct
- that gives negative time support.
-\end_layout
-
-\begin_layout Standard
-Since integers often cannot store negative zero (due to e.
-\begin_inset space \thinspace{}
-\end_inset
-
-g.
-\begin_inset space \space{}
-\end_inset
-
-use of 2s complements in the language implementation), we will store the
- minus sign in the nanosecond member if the integral second part is zero.
- This gives us the property that we can test for negative time by looking
- for whether at least one member of the structure is negative.
- Also, we want to avoid storing the minus in both members to somewhat aid
- the pretty-printing construct often seen,
-\end_layout
-
-\begin_layout LyX-Code
-printf("%ld.%09ld
-\backslash
-n", (long)ts.tv_sec, ts.tv_nsec);
-\end_layout
-
-\begin_layout Standard
-The number of combinations of a (non-zero) negative number, zero and a (non-zero
-) positive number is small, so we can actually just exhaustively list them
- all.
-\begin_inset Separator latexpar
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-\noindent
-\align center
-\begin_inset Tabular
-<lyxtabular version="3" rows="4" columns="6">
-<features tabularvalignment="middle">
-<column alignment="center" valignment="top">
-<column alignment="center" valignment="top">
-<column alignment="center" valignment="top">
-<column alignment="center" valignment="top">
-<column alignment="center" valignment="top">
-<column alignment="center" valignment="top">
-<row>
-<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-Representation
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-Time value
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-R
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-T
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-R
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-T
-\end_layout
-
-\end_inset
-</cell>
-</row>
-<row>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-\begin_inset Formula $\left\{ -1,-1\right\} $
-\end_inset
-
-
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-illegal
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-\begin_inset Formula $\left\{ 0,-1\right\} $
-\end_inset
-
-
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
--0.1
-\begin_inset space \thinspace{}
-\end_inset
-
-s
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-\begin_inset Formula $\left\{ 1,-1\right\} $
-\end_inset
-
-
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-illegal
-\end_layout
-
-\end_inset
-</cell>
-</row>
-<row>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-\begin_inset Formula $\left\{ -1,0\right\} $
-\end_inset
-
-
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
--1.0
-\begin_inset space \thinspace{}
-\end_inset
-
-s
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-\begin_inset Formula $\left\{ 0,0\right\} $
-\end_inset
-
-
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-0.0
-\begin_inset space \thinspace{}
-\end_inset
-
-s
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-\begin_inset Formula $\left\{ 1,0\right\} $
-\end_inset
-
-
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-1.0
-\begin_inset space \thinspace{}
-\end_inset
-
-s
-\end_layout
-
-\end_inset
-</cell>
-</row>
-<row>
-<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-\begin_inset Formula $\left\{ -1,1\right\} $
-\end_inset
-
-
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
--1.1
-\begin_inset space \thinspace{}
-\end_inset
-
-s
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-\begin_inset Formula $\left\{ 0,1\right\} $
-\end_inset
-
-
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-0.1
-\begin_inset space \thinspace{}
-\end_inset
-
-s
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-\begin_inset Formula $\left\{ 1,1\right\} $
-\end_inset
-
-
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-1.1
-\begin_inset space \thinspace{}
-\end_inset
-
-s
-\end_layout
-
-\end_inset
-</cell>
-</row>
-</lyxtabular>
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-The set of so-extended valid timespecs is therefore:
-\end_layout
-
-\begin_layout Standard
-\begin_inset Formula
-\[
-K=\left\{ \left(i,f\right):i,f\in\mathbb{Z}\wedge i\neq0\wedge0\leq f<10^{9}\right\} \cup\left\{ \left(i,f\right):i=0\wedge f\in\mathbb{Z}\wedge-10^{9}<f<10^{9}\right\}
-\]
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Subsection
-Function list
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-#include
-\series default
- <libHX/misc.h>
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-bool
-\series default
- HX_timespec_isneg(
-\series bold
-const struct
-\series default
- timespec
-\series bold
-*
-\series default
-p);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-HX_timespec_isneg
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-struct
-\series default
- timespec
-\series bold
-*
-\series default
-HX_timespec_neg(
-\series bold
-struct
-\series default
- timespec
-\series bold
-*
-\series default
-result,
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-const struct
-\series default
- timespec
-\series bold
-*
-\series default
-p);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-HX_timespec_neg
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-struct
-\series default
- timespec
-\series bold
-*
-\series default
-HX_timespec_add(
-\series bold
-struct
-\series default
- timespec
-\series bold
-*
-\series default
-result,
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-const struct
-\series default
- timespec
-\series bold
-*
-\series default
-p,
-\series bold
-const struct
-\series default
- timespec
-\series bold
-*
-\series default
-q);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-HX_timespec_add
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-struct
-\series default
- timespec
-\series bold
-*
-\series default
-HX_timespec_sub(
-\series bold
-struct
-\series default
- timespec
-\series bold
-*
-\series default
-delta,
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-const struct
-\series default
- timespec
-\series bold
-*
-\series default
-p,
-\series bold
-const struct
-\series default
- timespec
-\series bold
-*
-\series default
-q);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HX_timespec_sub
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-struct
-\series default
- timespec
-\series bold
-*
-\series default
-HX_timespec_mul(
-\series bold
-struct
-\series default
- timespec
-\series bold
-*
-\series default
-delta,
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-const struct
-\series default
- timespec
-\series bold
-*
-\series default
-p,
-\series bold
-int
-\series default
- f);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-HX_timespec_mul
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-struct
-\series default
- timespec
-\series bold
-*
-\series default
-HX_timespec_mulf(
-\series bold
-struct
-\series default
- timespec
-\series bold
-*
-\series default
-delta,
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-const struct
-\series default
- timespec
-\series bold
-*
-\series default
-p,
-\series bold
-double
-\series default
- f);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-HX_timespec_mulf
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-struct
-\series default
- timeval
-\series bold
-*
-\series default
-HX_timeval_sub(
-\series bold
-struct
-\series default
- timeval
-\series bold
-*
-\series default
-delta,
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-const struct
-\series default
- timeval
-\series bold
-*
-\series default
-p,
-\series bold
-const struct
-\series default
- timeval
-\series bold
-*
-\series default
-q);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HX_timeval_sub
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-int
-\series default
- HX_time_compare(
-\series bold
-const struct
-\series default
- stat
-\series bold
-*
-\series default
-a,
-\series bold
-const struct
-\series default
- stat
-\series bold
-*
-\series default
-b,
-\series bold
-int
-\series default
- mode);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HX_time_compare
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HX_timespec_isneg
-\family default
- Determines whether a timespec structure represents (non-zero) negative
- time.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HX_timespec_neg
-\family default
- Computes the negation of the time specified by
-\family typewriter
-p
-\family default
-.
-
-\family typewriter
-result
-\family default
- and
-\family typewriter
-p
-\family default
- may point to the same structure.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HX_timespec_add
-\family default
- Calculates the sum of the two times specified by
-\family typewriter
-p
-\family default
- and
-\family typewriter
-q
-\family default
-, which are of type
-\family typewriter
-struct timespec
-\family default
-.
- Any of
-\family typewriter
-result
-\family default
-,
-\family typewriter
-p
-\family default
- and
-\family typewriter
-q
-\family default
- may point to the same structure.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HX_timespec_sub
-\family default
- Calculates the difference between the two timepoints p and q, which are
- of type
-\family typewriter
-struct timespec
-\family default
- (nanosecond granularity).
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HX_timespec_mul
-\family default
- Multiplies the time quantum in
-\family typewriter
-p
-\family default
- by
-\family typewriter
-f
-\family default
-.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HX_timespec_mulf
-\family default
- Multiplies the time quantum in
-\family typewriter
-p
-\family default
- by
-\family typewriter
-f
-\family default
-.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HX_timeval_sub
-\family default
- Calculates the difference between the two timepoints p and q, which are
- of type
-\family typewriter
-struct timeval
-\family default
- (microsecnod granularity).
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HX_time_compare
-\family default
- Compares the timestamps from two
-\family typewriter
-struct stat
-\family default
-s.
-
-\family typewriter
-mode
-\family default
- indicates which field is compared, which can either be
-\family typewriter
-'a'
-\family default
- for the access time,
-\family typewriter
-'c'
-\family default
- for the inode change time,
-\family typewriter
-'m'
-\family default
- for the modification time, or
-\family typewriter
-'o'
-\family default
- for the creation time (where available).
- Returns a negative number if the time in
-\family typewriter
-a
-\family default
- is less than
-\family typewriter
-b
-\family default
-, zero when they are equal, or a positive number greater than zero if
-\family typewriter
-a
-\family default
- is greater than
-\family typewriter
-b
-\family default
-.
-\end_layout
-
-\begin_layout Standard
-The macros
-\family typewriter
-HX_TIMESPEC_FMT
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HX_TIMESPEC_FMT
-\end_layout
-
-\end_inset
-
- and
-\family typewriter
-HX_TIMESPEC_EXP
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HX_TIMESPEC_EXP
-\end_layout
-
-\end_inset
-
- can be used for passing and printing a
-\family typewriter
-struct timespec
-\family default
- using the *
-\family typewriter
-printf
-\family default
- function family:
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-struct
-\series default
- timespec p;
-\begin_inset Newline newline
-\end_inset
-
-clock_gettime(CLOCK_MONOTONIC, &p);
-\begin_inset Newline newline
-\end_inset
-
-printf("Now: " HX_TIMESPEC_FMT, HX_TIMESPEC_EXP(&p));
-\end_layout
-
-\begin_layout Standard
-Similarly,
-\family typewriter
-HX_TIMEVAL_FMT
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HX_TIMEVAL_FMT
-\end_layout
-
-\end_inset
-
- and
-\family typewriter
-HX_TIMEVAL_EXP
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HX_TIMEVAL_EXP
-\end_layout
-
-\end_inset
-
- exist for the older
-\family typewriter
-struct timeval
-\family default
-.
-\end_layout
-
-\begin_layout Standard
-\begin_inset Newpage clearpage
-\end_inset
-
-
-\end_layout
-
-\begin_layout Section
-Bitmaps
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-#include
-\series default
- <libHX/misc.h>
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-size_t
-\series default
- HXbitmap_size(
-\series bold
-type
-\series default
- array,
-\series bold
-unsigned int
-\series default
- bits);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXbitmap_size
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-void
-\series default
- HXbitmap_set(
-\series bold
-type *
-\series default
-bmap,
-\series bold
-unsigned int
-\series default
- bit);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXbitmap_set
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-void
-\series default
- HXbitmap_clear(
-\series bold
-type *
-\series default
-bmap,
-\series bold
-unsigned int
-\series default
- bit);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXbitmap_clear
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-bool
-\series default
- HXbitmap_test(
-\series bold
-type *
-\series default
-bmap,
-\series bold
-unsigned int
-\series default
- bit);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXbitmap_test
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-All of these four are implemented as macros, so they can be used with any
- integer type that is desired to be used.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXbitmap_size
-\family default
- Returns the amount of
-\begin_inset Quotes eld
-\end_inset
-
-type
-\begin_inset Quotes erd
-\end_inset
-
--based integers that would be needed to hold an array of the requested amount
- of bits.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXbitmap_set
-\family default
- Set the specific bit in the bitmap.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXbitmap_clear
-\family default
- Clear the specific bit in this bitmap.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXbitmap_test
-\family default
- Test for the specific bit and returns
-\family typewriter
-true
-\family default
- if it is set, otherwise
-\family typewriter
-false
-\family default
-.
-\end_layout
-
-\begin_layout Subsubsection
-Example
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-#include
-\series default
- <stdlib.h>
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-#include
-\series default
- <string.h>
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-#include
-\series default
- <libHX/misc.h>
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-int
-\series default
- main(
-\series bold
-void
-\series default
-)
-\begin_inset Newline newline
-\end_inset
-
-{
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-unsigned long
-\series default
- bitmap
-\series bold
-[
-\series default
-HXbitmap_size(
-\series bold
-unsigned long
-\series default
-, 128)
-\series bold
-]
-\series default
-;
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
- memset(bitmap, 0, sizeof(bitmap));
-\begin_inset Newline newline
-\end_inset
-
- HXbitmap_set(bitmap, 49);
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-return
-\series default
- HXbitmap_get(bitmap, HX_irand(0, 128)) ?
-\begin_inset Newline newline
-\end_inset
-
- EXIT_SUCCESS : EXIT_FAILURE;
-\begin_inset Newline newline
-\end_inset
-
-}
-\end_layout
-
-\begin_layout Standard
-\begin_inset Newpage clearpage
-\end_inset
-
-
-\end_layout
-
-\begin_layout Part
-Data structures
-\end_layout
-
-\begin_layout Section
-Maps
-\begin_inset CommandInset label
-LatexCommand label
-name "sec:maps"
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-A map is a collection of key-value pairs.
- (Some languages, such as Perl, also call them
-\begin_inset Quotes eld
-\end_inset
-
-associative array
-\begin_inset Quotes erd
-\end_inset
-
- or just
-\begin_inset Quotes eld
-\end_inset
-
-hash
-\begin_inset Quotes erd
-\end_inset
-
-, however, the underlying storage mechanism may not be an array or a hash,
- however.) Each key is unique and has an associated value.
- Keys can be any data desired; HXmap allows to specify your own key and
- data handling functions so they can be strings, raw pointers, or complex
- structures.
-\end_layout
-
-\begin_layout Standard
-To access any map-related functions,
-\family typewriter
-#include <libHX\SpecialChar breakableslash
-map.h>
-\family default
-.
-\end_layout
-
-\begin_layout Subsection
-Structural definition
-\begin_inset CommandInset label
-LatexCommand label
-name "subsec:maps-def"
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-The
-\family typewriter
-HXmap
-\family default
- structure is a near-opaque type.
- Unlike the predecessor map implementation
-\family typewriter
-struct HXbtree
-\family default
- from libHX 2.x, the 3.x API exposes much less fields.
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-struct
-\series default
- HXmap {
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-struct HXmap
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-unsigned int
-\series default
- items, flags;
-\begin_inset Newline newline
-\end_inset
-
-};
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-items
-\family default
- The number of items in the tree.
- This field tracks the number of items in the map and is used to report
- the number of elements to the user, and is updated whenever an element
- is inserted or removed from the map.
- The field must not be changed by user.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-flags
-\family default
- The current behavior flags for the map.
- While implementation-private bits are exposed, only
-\family typewriter
-HXMAP_NOREPLACE
-\family default
- is currently allowed to be (un)set by the developer while a map exists.
-\end_layout
-
-\begin_layout Standard
-For retrieving elements from a tree, some functions work with
-\family typewriter
-struct HXmap_node
-\family default
-, which is defined as follows:
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-struct
-\series default
- HXmap_node {
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-struct HXmap_node
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-union
-\series default
- {
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-void *
-\series default
-key;
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-const char *const
-\series default
- skey;
-\begin_inset Newline newline
-\end_inset
-
- };
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-union
-\series default
- {
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-void *
-\series default
-data;
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-char *
-\series default
-sdata;
-\begin_inset Newline newline
-\end_inset
-
- };
-\begin_inset Newline newline
-\end_inset
-
-};
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-key
-\family default
- The so-called primary key, which uniquely identifies an element (a key-value
- pair) in the map.
- The memory portions that make up the key must not be modified.
- (If the key changes, so does its hash value and/or position index, and
- without taking that into account, writing to the key directly is going
- to end up with an inconsistent state.
- To change the key, you will need to delete the element and reinsert it
- with its new key.)
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-skey
-\family default
- A convenience type field for when the map's keys are C strings.
- It is useful for use with e.
-\begin_inset space \thinspace{}
-\end_inset
-
-g.
-\begin_inset space \space{}
-\end_inset
-
-
-\family typewriter
-printf
-\family default
- or other varargs function, which would otherwise require casting of the
-
-\family typewriter
-void
-\begin_inset space ~
-\end_inset
-
-*key
-\family default
- member to
-\family typewriter
-const char
-\begin_inset space ~
-\end_inset
-
-*
-\family default
- first.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-data
-\family default
- The data associated with the key.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-sdata
-\family default
- Convenience type field.
-\end_layout
-
-\begin_layout Subsection
-Map initialization
-\end_layout
-
-\begin_layout Standard
-During initialization, you specify the underlying storage type by selecting
- a given constructor function.
- All further operations are done through the unified HXmap API which uses
- a form of virtual calls internally.
-\end_layout
-
-\begin_layout Standard
-Currently, there are two distinct map types in libHX.
- There are a handful of selectable symbols, though.
- Abstract types are:
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXMAPT_DEFAULT
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXMAPT_DEFAULT
-\end_layout
-
-\end_inset
-
- No further preferences or guarantees; selects any map type that the libHX
- maintainer deemed fast.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXMAPT_ORDERED
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXMAPT_ORDERED
-\end_layout
-
-\end_inset
-
- The map shall use a data structure that provides ordered traversal.
-\end_layout
-
-\begin_layout Standard
-Specific types include:
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXMAPT_HASH
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HX_MAPT_HASH
-\end_layout
-
-\end_inset
-
- Hash-based map
-\begin_inset space ~
-\end_inset
-
-– Amortized
-\begin_inset Formula $\mathcal{O}\left(1\right)$
-\end_inset
-
- insertion, lookup and deletion; unordered.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXMAPT_RBTREE
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HX_MAPT_RBTREE
-\end_layout
-
-\end_inset
-
- Red-black binary tree
-\begin_inset space ~
-\end_inset
-
-–
-\begin_inset Formula $\mathcal{O}\left(\log\left(n\right)\right)$
-\end_inset
-
- insertion, lookup and deletion; ordered.
-\end_layout
-
-\begin_layout Standard
-These can then be used with the initialization functions:
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-struct
-\series default
- HXmap
-\series bold
-*
-\series default
-HXmap_init(
-\series bold
-unsigned int
-\series default
- type,
-\series bold
-unsigned int
-\series default
- flags);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXmap_init
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-struct
-\series default
- HXmap
-\series bold
-*
-\series default
-HXmap_init5(
-\series bold
-unsigned int
-\series default
- type,
-\series bold
-unsigned int
-\series default
- flags,
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-const struct
-\series default
- HXmap_ops
-\series bold
-*
-\series default
-ops,
-\series bold
-size_t
-\series default
- key_size,
-\series bold
-size_t
-\series default
- data_size);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXmap_init5
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-Both the
-\family typewriter
-*_init
-\family default
- and
-\family typewriter
-*_init5
-\family default
- variant creates a new map; the latter function allows to specify the operations
- in detail as well as key and data size, which may become necessary when
- using data sets which have their own way of being managed.
- The
-\family typewriter
-flags
-\family default
- parameter can contain any of the following:
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXMAP_NONE
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXMAP_NONE
-\end_layout
-
-\end_inset
-
- This is just a mnemonic for the value 0, indicating no flags.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXMAP_NOREPLACE
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXMAP_NOREPLACE
-\end_layout
-
-\end_inset
-
- If a key already exists and another add operation is attempted, the key's
- associated value will be replaced by the new value.
- If this flag is absent,
-\family typewriter
--EEXIST
-\family default
- is returned.
- This flag is allowed to be subsequently changed by the developer if so
- desired, using bit logic such as
-\family typewriter
-map->flags &= ~HXMAP_NOREPLACE;
-\family default
-.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXMAP_SKEY
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXMAP_SKEY
-\end_layout
-
-\end_inset
-
- Notifies the constructor that keys will be C-style strings.
- The flag presets the
-\family typewriter
-k_compare
-\family default
- operation to use
-\family typewriter
-strcmp
-\family default
-.
- In the flag's absence, direct value comparison will be used if the key
- size is specified as zero (e.
-\begin_inset space \thinspace{}
-\end_inset
-
-g.
-\begin_inset space \space{}
-\end_inset
-
-with the
-\family typewriter
-HXhashmap_\SpecialChar softhyphen
-init4
-\family default
- function call), or
-\family typewriter
-memcmp
-\family default
- if the key size is non-zero.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXMAP_CKEY
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXMAP_CKEY
-\end_layout
-
-\end_inset
-
- Instructs the map to make copies of keys when they are added to the map.
- This is required when the buffer holding the key changes or goes out of
- scope.
- The flag presets the
-\family typewriter
-k_clone
-\family default
- and
-\family typewriter
-k_free
-\family default
- operations to
-\family typewriter
-HX_memdup
-\family default
- and
-\family typewriter
-free
-\family default
-, and as such, the
-\family typewriter
-key_size
-\family default
- parameter must not be zero.
- If however,
-\family typewriter
-HXMAP_SKEY
-\family default
- is also specified,
-\family typewriter
-HX_strdup
-\family default
- and
-\family typewriter
-free
-\family default
- will be used and
-\family typewriter
-key_size
-\family default
- must be zero.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXMAP_SDATA
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXMAP_SDATA
-\end_layout
-
-\end_inset
-
- Notifies the constructor that data will be C-style strings.
- This sets up the
-\family typewriter
-d_clone
-\family default
- and
-\family typewriter
-d_free
-\family default
- operations.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXMAP_CDATA
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXMAP_CDATA
-\end_layout
-
-\end_inset
-
- Instructs the map to make copies of the data when new entries are added
- to the map.
- This is required when the buffer holding the data either goes out of scope,
- or you want to keep the original contents instead of just a pointer.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXMAP_SCKEY
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXMAP_SCKEY
-\end_layout
-
-\end_inset
-
- Mnemonic for the combination of
-\family typewriter
-HXMAP_\SpecialChar softhyphen
-SKEY
-\family default
- OR'ed with
-\family typewriter
-HXMAP_\SpecialChar softhyphen
-CKEY
-\family default
-.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXMAP_SCDATA
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXMAP_SCDATA
-\end_layout
-
-\end_inset
-
- Mnemonic for the combination of
-\family typewriter
-HXMAP_\SpecialChar softhyphen
-SDATA
-\family default
- OR'ed with
-\family typewriter
-HXMAP_\SpecialChar softhyphen
-SDATA
-\family default
-.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXMAP_SINGULAR
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXMAP_SINGULAR
-\end_layout
-
-\end_inset
-
- Specifies that the
-\begin_inset Quotes eld
-\end_inset
-
-map
-\begin_inset Quotes erd
-\end_inset
-
- is only used as a set, i.
-\begin_inset space \thinspace{}
-\end_inset
-
-e.
-\begin_inset space \space{}
-\end_inset
-
-it does not store any values, only keys.
- Henceforth, the
-\family typewriter
-value
-\family default
- argument to
-\family typewriter
-HXmap_add
-\family default
- must always be
-\family typewriter
-NULL
-\family default
-.
-\end_layout
-
-\begin_layout Subsection
-Flag combinations
-\end_layout
-
-\begin_layout Standard
-This subsection highlights the way
-\family typewriter
-HXMAP_SKEY
-\family default
- interacts with
-\family typewriter
-HXMAP_CKEY
-\family default
- and the key size.
- The copy semantics are the same for
-\family typewriter
-HXMAP_SDATA
-\family default
- and
-\family typewriter
-HXMAP_CDATA
-\family default
-.
-\end_layout
-
-\begin_layout Subsubsection*
-
-\family typewriter
-HXMAP_SKEY
-\family default
- is unset,
-\family typewriter
-HXMAP_CKEY
-\family default
- is unset
-\end_layout
-
-\begin_layout Standard
-The
-\family typewriter
-key_size
-\family default
- parameter at the time of map construction is ignored.
- The pointer value of the
-\family typewriter
-key
-\family default
- parameter for the
-\family typewriter
-HXmap_add
-\family default
- call is directly stored in the tree, and this is the key that uniquely
- identifies the map entry and which is used for comparisons.
- This may be used if you intend to directly map pointer values.
-\end_layout
-
-\begin_layout LyX-Code
-static struct something *x = ..., *y = ...;
-\begin_inset Newline newline
-\end_inset
-
-HXmap_add(map, &x[0], "foo");
-\begin_inset Newline newline
-\end_inset
-
-HXmap_add(map, &x[1], "bar");
-\end_layout
-
-\begin_layout Subsubsection*
-
-\family typewriter
-HXMAP_SKEY
-\family default
- is set,
-\family typewriter
-HXMAP_CKEY
-\family default
- is unset
-\end_layout
-
-\begin_layout Standard
-The
-\family typewriter
-key_size
-\family default
- parameter at the time of map construction is ignored.
- The pointer value of the
-\family typewriter
-key
-\family default
- parameter for the
-\family typewriter
-HXmap_add
-\family default
- call is directly stored in the tree, but it is the C string
-\shape italic
-pointed to
-\shape default
- by the
-\family typewriter
-key
-\family default
- parameter that serves as the key.
-\end_layout
-
-\begin_layout Subsubsection*
-
-\family typewriter
-HXMAP_SKEY
-\family default
- is set,
-\family typewriter
-HXMAP_CKEY
-\family default
- is set
-\end_layout
-
-\begin_layout Standard
-The
-\family typewriter
-key_size
-\family default
- parameter at the time of map construction is ignored.
- The string pointed to by the key parameter will be duplicated, and the
- resulting pointer will be stored in the tree.
- Again, it is the pointed-to string that is the key.
-\end_layout
-
-\begin_layout Subsubsection*
-
-\family typewriter
-HXMAP_SKEY
-\family default
- is unset,
-\family typewriter
-HXMAP_CKEY
-\family default
- is set
-\end_layout
-
-\begin_layout Standard
-The memory block pointed to by the key parameter will be duplicated.
- The
-\family typewriter
-key_size
-\family default
- parameter must be non-zero for this to successfully work.
-\end_layout
-
-\begin_layout Subsubsection*
-With separate ops
-\end_layout
-
-\begin_layout Standard
-However, when a custom
-\family typewriter
-struct HXmap_ops
-\family default
- is provided in the call to
-\family typewriter
-HXmap_init5
-\family default
-, any of these semantics can be overridden.
- Particularly, since your own ops can practically ignore
-\family typewriter
-key_size
-\family default
-, it could be set to any value.
-\end_layout
-
-\begin_layout Subsection
-Key-data operations
-\end_layout
-
-\begin_layout Standard
-The
-\family typewriter
-HXMAP_SKEY
-\family default
-\SpecialChar breakableslash
-
-\family typewriter
-CKEY
-\family default
-\SpecialChar breakableslash
-
-\family typewriter
-SDATA
-\family default
-\SpecialChar breakableslash
-
-\family typewriter
-CDATA
-\family default
- flags are generally sufficient to set up common maps where keys and/or
- data are C strings or simple binary data where
-\family typewriter
-memdup
-\family default
-/
-\family typewriter
-memcmp
-\family default
- is enough.
- Where the provided mechanisms are not cutting it, an extra
-\family typewriter
-HXmap_ops
-\family default
- structure with functions specialized in handling the keys and/or data has
- to be used as an argument to the initialization function call.
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-struct
-\series default
- HXmap_ops {
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-struct HXmap_ops
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-int (*
-\series default
-k_compare
-\series bold
-)
-\series default
-(
-\series bold
-const void *
-\series default
-,
-\series bold
-const void *
-\series default
-,
-\series bold
-size_t
-\series default
-);
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-void *(*
-\series default
-k_clone
-\series bold
-)
-\series default
-(
-\series bold
-const void *
-\series default
-,
-\series bold
-size_t
-\series default
-);
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-void (*
-\series default
-k_free
-\series bold
-)
-\series default
-(
-\series bold
-void *
-\series default
-);
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-void *(*
-\series default
-d_clone
-\series bold
-)
-\series default
-(
-\series bold
-const void *
-\series default
-,
-\series bold
-size_t
-\series default
-);
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-void (*
-\series default
-d_free
-\series bold
-)
-\series default
-(
-\series bold
-void *
-\series default
-);
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-unsigned long (*
-\series default
-k_hash
-\series bold
-)
-\series default
-(
-\series bold
-const void *
-\series default
-,
-\series bold
-size_t
-\series default
-);
-\begin_inset Newline newline
-\end_inset
-
-};
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-k_compare
-\family default
- Function to compare two keys.
- The return value is the same as that of
-\family typewriter
-memcmp
-\family default
- or
-\family typewriter
-strcmp
-\family default
-: negative values indicate that the first key is
-\begin_inset Quotes eld
-\end_inset
-
-less than
-\begin_inset Quotes erd
-\end_inset
-
- the second, zero indicates that both keys are equal, and positive values
- indicate that the first key is
-\begin_inset Quotes eld
-\end_inset
-
-greater than
-\begin_inset Quotes erd
-\end_inset
-
- the second.
- The size argument in third position is provided so that
-\family typewriter
-memcmp
-\family default
-, which wants a size parameter, can directly be used without having to write
- an own function.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-k_clone
-\family default
- Function that will clone (duplicate) a key.
- This is used for keys that will be added to the tree, and potentially also
- for state-keeping during traversal of the map.
- It is valid that this clone function simply returns the value of the pointer
- it was actually passed; this is used by default for maps without
-\family typewriter
-HXMAP_CKEY
-\family default
- for example.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-k_free
-\family default
- Function to free a key.
- In most cases it defaults to
-\family typewriter
-free
-\family default
-(3), but in case you are using complex structs, more cleanup may be needed.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-d_clone
-\family default
- Same as
-\family typewriter
-k_clone
-\family default
-, but for data.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-d_free
-\family default
- Same as
-\family typewriter
-k_free
-\family default
-, but for data.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-k_hash
-\family default
- Specifies an alternate hash function.
- Only to be used with hash-based maps.
- Hashmaps default to using the DJB2 string hash function when
-\family typewriter
-HXMAP_SKEY
-\family default
- is given, or otherwise the Jenkins' lookup3 hash function.
-\end_layout
-
-\begin_layout Standard
-libHX exports two hash functions that you can select for
-\family typewriter
-struct HXmap_ops
-\family default
-'s
-\family typewriter
-k_hash
-\family default
- if the default for a given flag combination is not to your liking.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXhash_jlookup3
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXhash_jlookup3
-\end_layout
-
-\end_inset
-
- Bob Jenkins's lookup3 hash.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXhash_djb2
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXhash_djb2
-\end_layout
-
-\end_inset
-
- DJB2 string hash.
-\end_layout
-
-\begin_layout Subsection
-Map operations
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-int
-\series default
- HXmap_add(
-\series bold
-struct
-\series default
- HXmap
-\series bold
-*
-\series default
-,
-\series bold
-const void *
-\series default
-key,
-\series bold
-const void *
-\series default
-value);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXmap_add
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-const struct
-\series default
- HXmap_node
-\series bold
-*
-\series default
-HXmap_find(
-\series bold
-const struct
-\series default
- HXmap
-\series bold
-*
-\series default
-,
-\series bold
-const void *
-\series default
-key);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXmap_find
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-void *
-\series default
-HXmap_get(
-\series bold
-const struct
-\series default
- HXmap
-\series bold
-*
-\series default
-,
-\series bold
-const void *
-\series default
-key);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXmap_get
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-void *
-\series default
-HXmap_del(
-\series bold
-struct
-\series default
- HXmap
-\series bold
-*
-\series default
-,
-\series bold
-const void *
-\series default
-key);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXmap_del
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-void
-\series default
- HXmap_free(
-\series bold
-struct
-\series default
- HXmap
-\series bold
-*
-\series default
-);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXmap_free
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-struct
-\series default
- HXmap_node
-\series bold
-*
-\series default
-HXmap_keysvalues(
-\series bold
-const struct
-\series default
- HXmap
-\series bold
-*
-\series default
-);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXmap_keysvalues
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXmap_add
-\family default
-
-\family typewriter
-A
-\family default
-dds a new node to the tree using the given key and data.
- When an element is in the map, the key may not be modified, as doing so
- could possibly invalidate the internal location of the element, or its
- ordering with respect to other elements.
- If you need to change the key, you will have to delete the element from
- the tree and re-insert it.
- On error,
-\family typewriter
--errno
-\family default
- will be returned.
-\begin_inset Newline newline
-\end_inset
-
-When
-\family typewriter
-HXMAP_SINGULAR
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXMAP_SINGULAR
-\end_layout
-
-\end_inset
-
- is in effect,
-\family typewriter
-value
-\family default
- must be
-\family typewriter
-NULL
-\family default
-, or
-\family typewriter
--EINVAL
-\family default
- is returned.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXmap_find
-\family default
- Finds the node for the given key.
- The key can be read from the node using
-\family typewriter
-node->key
-\family default
- or
-\family typewriter
-node->skey
-\family default
- (convenience alias for
-\family typewriter
-key
-\family default
-, but with a type of
-\family typewriter
-const char
-\begin_inset space ~
-\end_inset
-
-*
-\family default
-), and the data by using
-\family typewriter
-node->data
-\family default
- or
-\family typewriter
-node->sdata
-\family default
-.
- (see section
-\begin_inset space ~
-\end_inset
-
-
-\begin_inset CommandInset ref
-LatexCommand ref
-reference "subsec:maps-def"
-
-\end_inset
-
-).
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXmap_get
-\family default
- Get is a find operation directly returning
-\family typewriter
-node->data
-\family default
- instead of the node itself.
- Since
-\family typewriter
-HXmap_get
-\family default
- may legitimately return
-\family typewriter
-NULL
-\family default
- if
-\family typewriter
-NULL
-\family default
- was stored in the tree as the data for a given key, only
-\family typewriter
-errno
-\family default
- will really tell whether the node was found or not; in the latter case,
-
-\family typewriter
-errno
-\family default
- is set to
-\family typewriter
-ENOENT
-\family default
-.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXmap_del
-\family default
- Removes an element from the map and returns the data value that was associated
- with it.
- When an error occurred, or the element was not found,
-\family typewriter
-NULL
-\family default
- is returned.
- Because
-\family typewriter
-NULL
-\family default
- can be a valid data value,
-\family typewriter
-errno
-\family default
- can be checked for non-zero.
-
-\family typewriter
-errno
-\family default
- will be
-\family typewriter
--ENOENT
-\family default
- if the element was not found, or zero when everything was ok.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXmap_free
-\family default
- The function will delete all elements in the map and free memory it holds.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXmap_keysvalues
-\family default
- Returns all key-value-pairs in an array of the size as many items were
- in the map (
-\family typewriter
-map->items
-\family default
-) at the time it was called.
- The memory must be freed using
-\family typewriter
-free
-\family default
-(3) when it is no longer needed.
- The order elements in the array follows the traverser notes (see below),
- unless otherwise specified.
-\end_layout
-
-\begin_layout Subsection
-Map traversal
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-struct
-\series default
- HXmap_trav
-\series bold
-*
-\series default
-HXmap_travinit(
-\series bold
-const struct
-\series default
- HXmap
-\series bold
-*
-\series default
-);
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-const struct
-\series default
- HXmap_node
-\series bold
-*
-\series default
-HXmap_traverse(
-\series bold
-struct
-\series default
- HXmap_trav
-\series bold
-*
-\series default
-iterator);
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-void
-\series default
- HXmap_travfree(
-\series bold
-struct
-\series default
- HXmap_trav
-\series bold
-*
-\series default
-iterator);
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-void
-\series default
- HXmap_qfe(
-\series bold
-const struct
-\series default
- HXmap
-\series bold
-*
-\series default
-,
-\series bold
-bool (*
-\series default
-fn
-\series bold
-)
-\series default
-(
-\series bold
-const struct
-\series default
- HXmap_node
-\series bold
-*
-\series default
-,
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-void *
-\series default
-arg),
-\series bold
-void *
-\series default
-arg);
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXmap_travinit
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXmap_travinit
-\end_layout
-
-\end_inset
-
- Initializes a traverser (a.
-\begin_inset space \thinspace{}
-\end_inset
-
-k.
-\begin_inset space \thinspace{}
-\end_inset
-
-a.
-\begin_inset space \space{}
-\end_inset
-
-iterator) for the map, and returns a pointer to it.
-
-\family typewriter
-NULL
-\family default
- will be returned in case of an error, such as memory allocation failure.
- Traversers are returned even if the map has zero elements.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXmap_traverse
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXmap_traverse
-\end_layout
-
-\end_inset
-
- Returns a pointer to a
-\family typewriter
-struct HXmap_node
-\family default
- for the next element
-\begin_inset space ~
-\end_inset
-
-\SpecialChar breakableslash
- key-value pair from the map, or
-\family typewriter
-NULL
-\family default
- if there are no more entries.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXmap_travfree
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXmap_travfree
-\end_layout
-
-\end_inset
-
- Release the memory associated with a traverser.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXmap_qfe
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXmap_qfe
-\end_layout
-
-\end_inset
-
- The
-\begin_inset Quotes eld
-\end_inset
-
-quick foreach
-\begin_inset Quotes erd
-\end_inset
-
-.
- Iterates over all map elements in the fastest possible manner, but has
- the restriction that no modifications to the map are allowed.
- Furthermore, a separate function to handle each visited node, is required.
- (Hence this is also called
-\begin_inset Quotes eld
-\end_inset
-
-closed traversal
-\begin_inset Quotes erd
-\end_inset
-
-, because one cannot access the stack frame of the original function which
- called
-\family typewriter
-HXmap_qfe
-\family default
-.) The user-defined function returns a bool which indicates whether traversal
- shall continue or not.
-\end_layout
-
-\begin_layout Standard
-Flags for
-\family typewriter
-HXmap_travinit
-\family default
-:
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXMAP_NOFLAGS
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXMAP_NOFLAGS
-\end_layout
-
-\end_inset
-
- A mnemonic for no flags, and is defined to be
-\family typewriter
-0
-\family default
-.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXMAP_DTRAV
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXMAP_DTRAV
-\end_layout
-
-\end_inset
-
- Enable support for deletion during traversal.
- As it can make traversal slower, it needs to be explicitly specified for
- cases where it is needed, to not penalize cases where it is not.
-\end_layout
-
-\begin_layout Standard
-WARNING: Modifying the map while a traverser is active is implementation-specifi
-c behavior! libHX generally ensures that there will be no undefined behavior
- (e.
-\begin_inset space \thinspace{}
-\end_inset
-
-g.
-\begin_inset space \space{}
-\end_inset
-
-crashes), but there is no guarantee that elements will be returned exactly
- once.
- There are fundamental cases that one should be aware of:
-\end_layout
-
-\begin_layout Itemize
-An element is inserted before where the traverser is currently positioned
- at.
- The element may not be returned in subsequent calls to
-\family typewriter
-HXmap_traverse
-\family default
- on an already-active traverser.
-\end_layout
-
-\begin_layout Itemize
-Insertion or deletion may cause internal data structure to re-layout.
-\begin_inset Separator latexpar
-\end_inset
-
-
-\end_layout
-
-\begin_deeper
-\begin_layout Itemize
-Traversers of ordered data structures may choose to rebuild their state.
-\end_layout
-
-\begin_layout Itemize
-Traversers of unordered data structures would run risk to return more than
- once, or not at all.
-\end_layout
-
-\end_deeper
-\begin_layout Standard
-Descriptions for different map types follow.
-\end_layout
-
-\begin_layout Description
-Hashmaps On
-\family typewriter
-HXmap_add
-\family default
-, an element may be inserted in a position that is before where the traverser
- is currently positioned.
- Such elements will not be returned in the remaining calls to
-\family typewriter
-HXmap_traverse
-\family default
-.
- The insertion or deletion of an element may cause the internal data structure
- to re-layout itself.
- When this happens, the traverser will stop, so as to not return entries
- twice.
-\end_layout
-
-\begin_layout Description
-Binary
-\begin_inset space ~
-\end_inset
-
-trees Elements may be added before the traverser's position.
- These elements will not be returned in subsequent traversion calls.
- If the data structure changes as a result of an addition or deletion, the
- traverser will rebuild its state and continue traversal transparently.
- Because elements in a binary tree are ordered, that is, element positions
- may not change with respect to another when the tree is rebalanced, there
- is no risk of returning entries more than once.
- Nor will elements that are sorted after the current traverser's position
- not be returned (=
-\begin_inset space ~
-\end_inset
-
-they will be returned, because they cannot get reordered to before the traverser
- like in a hash map).
- The HX rbtree implementation also has proper handling for when the node
- which is currently visiting is deleted.
-\end_layout
-
-\begin_layout Subsection
-RB-tree Limitations
-\end_layout
-
-\begin_layout Standard
-The implementation has a theoretical minimum on the maximum number of nodes,
-
-\begin_inset Formula $2^{24}=16{,}777{,}216$
-\end_inset
-
-.
- A worst-case tree with this many elements already has a height of 48 (
-\family typewriter
-RBT_MAXDEP
-\family default
-), which is the maximum height currently supported.
- The larger the height is that HXrbtree is supposed to handle, the more
- memory (linear increase) it needs.
- All functions that build or keep a path reserve memory for
-\family typewriter
-RBT_MAXDEP
-\family default
- nodes; on x86_64 this is 9 bytes per
-\begin_inset Formula $\langle$
-\end_inset
-
-node, direction
-\begin_inset Formula $\rangle$
-\end_inset
-
- pair, amounting to 432 bytes for path tracking alone.
- It may not sound like a lot to many, but given that kernel people can limit
- their stack usage to 4096 bytes is impressive alone
-\end_layout
-
-\begin_layout Standard
-\begin_inset Foot
-status open
-
-\begin_layout Plain Layout
-Not always of course.
- Linux kernels are often configured to use an 8K stack because some components
- still use a lot of stack space, but even 8K is still damn good.
-\end_layout
-
-\end_inset
-
-.
-\end_layout
-
-\begin_layout Subsection
-Examples
-\end_layout
-
-\begin_layout Subsubsection
-Case-insensitive ordering
-\end_layout
-
-\begin_layout Standard
-The correct way:
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-static int
-\series default
- my_strcasecmp(
-\series bold
-const void *
-\series default
-a,
-\series bold
-const void *
-\series default
-b,
-\series bold
-size_t
-\series default
- z)
-\begin_inset Newline newline
-\end_inset
-
-{
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-return
-\series default
- strcasecmp(a, b);
-\begin_inset Newline newline
-\end_inset
-
-}
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-static const struct
-\series default
- HXmap_ops icase = {
-\begin_inset Newline newline
-\end_inset
-
- .k_compare = my_strcasecmp,
-\begin_inset Newline newline
-\end_inset
-
-};
-\begin_inset Newline newline
-\end_inset
-
-HXmap_init5(HXMAPT_RBTREE, HXMAP_SKEY, &icase, 0,
-\shape italic
-dsize
-\shape default
-);
-\end_layout
-
-\begin_layout Standard
-A hackish way (which wholly depends on the C implementation and use of extra
- safeguards is a must):
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-static const struct
-\series default
- HXmap_ops icase = {
-\begin_inset Newline newline
-\end_inset
-
- .k_compare = (
-\series bold
-void *
-\series default
-)strcasecmp,
-\begin_inset Newline newline
-\end_inset
-
-};
-\begin_inset Newline newline
-\end_inset
-
-BUILD_BUG_ON(
-\series bold
-sizeof
-\series default
-(DEMOTE_TO_PTR(strcasecmp)) >
-\series bold
-sizeof
-\series default
-(void *));
-\begin_inset Newline newline
-\end_inset
-
-BUILD_BUG_ON(
-\series bold
-sizeof
-\series default
-(DEMOTE_TO_PTR(strcasecmp)) >
-\series bold
-sizeof
-\series default
-(icase.k_compare));
-\begin_inset Newline newline
-\end_inset
-
-HXmap_init5(HXMAPT_RBTREE, HXMAP_SKEY, &icase, 0,
-\shape italic
-dsize
-\shape default
-);
-\end_layout
-
-\begin_layout Subsubsection
-Reverse sorting order
-\end_layout
-
-\begin_layout Standard
-Any function that behaves like
-\family typewriter
-strcmp
-\family default
- can be used.
- It merely has to return negative when
-\begin_inset Formula $a<b$
-\end_inset
-
-, zero on
-\begin_inset Formula $a=b$
-\end_inset
-
-, and positive non-zero when
-\begin_inset Formula $a>b$
-\end_inset
-
-.
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-static int
-\series default
- strcmp_rev(
-\series bold
-const void *
-\series default
-a,
-\series bold
-const void *
-\series default
-b,
-\series bold
-size_t
-\series default
- z)
-\begin_inset Newline newline
-\end_inset
-
-{
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-/*
-\family roman
-\series default
-\shape italic
-z is provided for cases when things are raw memory blocks.
-
-\family default
-\series bold
-\shape default
- */
-\series default
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-return
-\series default
- strcmp(b, a);
-\begin_inset Newline newline
-\end_inset
-
-}
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-static const struct
-\series default
- HXmap_ops rev = {
-\begin_inset Newline newline
-\end_inset
-
- .k_compare = strcmp_rev,
-\begin_inset Newline newline
-\end_inset
-
-};
-\begin_inset Newline newline
-\end_inset
-
-HXmap_init5(HXMAPT_RBTREE, HXMAP_SKEY, &rev, 0,
-\shape italic
-dsize
-\shape default
-);
-\end_layout
-
-\begin_layout Subsubsection
-Keys with non-unique data
-\begin_inset CommandInset label
-LatexCommand label
-name "subsec:maps-examples-bigkey"
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-Keys can actually store non-unique data, as long as this extra fields does
- not actually contribute to the logical key
-\begin_inset space ~
-\end_inset
-
-— the parts that do uniquely identify it.
- In the following example, the
-\family typewriter
-notes
-\family default
- member may be part of struct package, which is the key as far as HXmap
- is concerned, but still, only the name and versions are used to identify
- it.
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-struct
-\series default
- package {
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-char *
-\series default
-name;
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-unsigned int
-\series default
- major_version;
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-unsigned int
-\series default
- minor_version;
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-char
-\series default
- notes
-\series bold
-[
-\series default
-64
-\series bold
-]
-\series default
-;
-\begin_inset Newline newline
-\end_inset
-
-};
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-static int
-\series default
- package_cmp(
-\series bold
-const void *
-\series default
-a,
-\series bold
-const void *
-\series default
-b)
-\begin_inset Newline newline
-\end_inset
-
-{
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-const struct
-\series default
- package
-\series bold
-*
-\series default
-p = a,
-\series bold
-*
-\series default
-q = b;
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-int
-\series default
- ret;
-\begin_inset Newline newline
-\end_inset
-
- ret = strcmp(p->name, q->name);
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-if
-\series default
- (ret != 0)
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-return
-\series default
- ret;
-\begin_inset Newline newline
-\end_inset
-
- ret = p->major_version - q->major_version;
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-if
-\series default
- (ret != 0)
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-return
-\series default
- ret;
-\begin_inset Newline newline
-\end_inset
-
- ret = p->minor_version - q->minor_version;
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-if
-\series default
- (ret != 0)
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-return
-\series default
- ret;
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-return
-\series default
- 0;
-\begin_inset Newline newline
-\end_inset
-
-}
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-static const struct
-\series default
- HXmap_ops package_ops = {
-\begin_inset Newline newline
-\end_inset
-
- .k_compare = package_cmp,
-\begin_inset Newline newline
-\end_inset
-
-};
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-HXmap_init5(HXMAPT_RBTREE,
-\shape italic
-flags
-\shape default
-, &package_ops,
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-sizeof
-\series default
-(
-\series bold
-struct
-\series default
- package),
-\shape italic
-dsize
-\shape default
-);
-\end_layout
-
-\begin_layout Standard
-\begin_inset Newpage clearpage
-\end_inset
-
-
-\end_layout
-
-\begin_layout Section
-Doubly-linked list
-\begin_inset CommandInset label
-LatexCommand label
-name "sec:deque"
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-HXdeque is a data structure for a doubly-linked non-circular
-\family typewriter
-NULL
-\family default
--sentineled list.
- Despite being named a deque, which is short for double-ended queue, and
- which may be implemented using an array, HXdeque is in fact using a linked
- list to provide its deque functionality.
- Furthermore, a dedicated root structure and decidated node structures with
- indirect data referencing are used.
-\end_layout
-
-\begin_layout Subsection
-Structural definition
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-#include
-\series default
- <libHX/deque.h>
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-libHX/deque.h
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-struct
-\series default
- HXdeque {
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-struct HXdeque
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-struct
-\series default
- HXdeque_node
-\series bold
-*
-\series default
-first,
-\series bold
-*
-\series default
-last;
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-unsigned int
-\series default
- items;
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-void *
-\series default
-ptr;
-\begin_inset Newline newline
-\end_inset
-
-};
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-struct
-\series default
- HXdeque_node {
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-struct HXdeque_node
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-struct
-\series default
- HXdeque_node
-\series bold
-*
-\series default
-next,
-\series bold
-*
-\series default
-prev;
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-struct
-\series default
- HXdeque
-\series bold
-*
-\series default
-parent;
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-void *
-\series default
-ptr;
-\begin_inset Newline newline
-\end_inset
-
-};
-\end_layout
-
-\begin_layout Standard
-The
-\family typewriter
-ptr
-\family default
- member in
-\family typewriter
-struct HXdeque
-\family default
- provides room for an arbitrary custom user-supplied pointer.
-
-\family typewriter
-items
-\family default
- will reflect the number of elements in the list, and must not be modified.
-
-\family typewriter
-first
-\family default
- and
-\family typewriter
-last
-\family default
- provide entrypoints to the list's ends.
-\end_layout
-
-\begin_layout Standard
-
-\family typewriter
-ptr
-\family default
- within
-\family typewriter
-struct HXdeque_node
-\family default
- is the pointer to the user's data.
- It may be modified and used at will by the user.
- See example section
-\begin_inset space ~
-\end_inset
-
-.
-\end_layout
-
-\begin_layout Subsection
-Constructor, destructors
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-struct
-\series default
- HXdeque
-\series bold
-*
-\series default
-HXdeque_init(
-\series bold
-void
-\series default
-);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXdeque_init
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-void
-\series default
- HXdeque_free(
-\series bold
-struct
-\series default
- HXdeque
-\series bold
-*
-\series default
-dq);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXdeque_free
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-void
-\series default
- HXdeque_genocide(
-\series bold
-struct
-\series default
- HXdeque
-\series bold
-*
-\series default
-dq);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXdeque_genocide
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-void
-\series default
- HXdeque_genocide2(
-\series bold
-struct
-\series default
- HXdeque
-\series bold
-*
-\series default
-dq,
-\series bold
-void (*
-\series default
-xfree
-\series bold
-)
-\series default
-(
-\series bold
-void *
-\series default
-));
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXdeque_genocide2
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-void **
-\series default
-HXdeque_to_vec(
-\series bold
-struct
-\series default
- HXdeque
-\series bold
-*
-\series default
-dq,
-\series bold
-unsigned int *
-\series default
-num);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXdeque_to_vec
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-To allocate a new empty list, use
-\family typewriter
-HXdeque_init
-\family default
-.
-
-\family typewriter
-HXdeque_free
-\family default
- will free the list (including all nodes owned by the list), but not the
- data pointers.
-\end_layout
-
-\begin_layout Standard
-
-\family typewriter
-HXdeque_genocide
-\family default
- is a variant that will not only destroy the list, but also calls a freeing
- function
-\family typewriter
-free()
-\family default
- on all stored data pointers.
- This puts a number of restrictions on the characteristics of the list:
- all data pointers must have been obtained with
-\family typewriter
-malloc
-\family default
-,
-\family typewriter
-calloc
-\family default
- or
-\family typewriter
-realloc
-\family default
- before, and no data pointer must exist twice in the list.
- The function is more efficient than an open-coded loop over all nodes calling
-
-\family typewriter
-HXdeque_del
-\family default
-.
-\end_layout
-
-\begin_layout Standard
-A generic variant is available with
-\family typewriter
-HXdeque_genocide2
-\family default
-, which takes a pointer to an appropriate freeing function.
-
-\family typewriter
-HXdeque_genocide
-\family default
- is thus equivalent to
-\family typewriter
-HXdeque_genocide2(dq, free)
-\family default
-.
-\end_layout
-
-\begin_layout Standard
-To convert a linked list to a
-\family typewriter
-NULL
-\family default
--terminated array,
-\family typewriter
-HXdeque_to_vec
-\family default
- can be used.
- If
-\family typewriter
-num
-\family default
- is not
-\family typewriter
-NULL
-\family default
-, the number of elements excluding the
-\family typewriter
-NULL
-\family default
- sentinel, is stored in
-\family typewriter
-*num
-\family default
-.
-\end_layout
-
-\begin_layout Subsection
-Addition and removal
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-struct
-\series default
- HXdeque_node
-\series bold
-*
-\series default
-HXdeque_push(
-\series bold
-struct
-\series default
- HXdeque
-\series bold
-*
-\series default
-dq,
-\series bold
-void *
-\series default
-ptr);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXdeque_push
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-struct
-\series default
- HXdeque_node
-\series bold
-*
-\series default
-HXdeque_unshift(
-\series bold
-struct
-\series default
- HXdeque
-\series bold
-*
-\series default
-dq,
-\series bold
-void *
-\series default
-ptr);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXdeque_unshift
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-void *
-\series default
-HXdeque_pop(
-\series bold
-struct
-\series default
- HXdeque
-\series bold
-*
-\series default
-dq);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXdeque_pop
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-void *
-\series default
-HXdeque_shift(
-\series bold
-struct
-\series default
- HXdeque
-\series bold
-*
-\series default
-dq);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXdeque_shift
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-struct
-\series default
- HXdeque
-\series bold
-*
-\series default
-HXdeque_move(
-\series bold
-struct
-\series default
- HXdeque_node
-\series bold
-*
-\series default
-target,
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-struct
-\series default
- HXdeque_node
-\series bold
-*
-\series default
-node);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXdeque_move
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-void *
-\series default
-HXdeque_del(
-\series bold
-struct
-\series default
- HXdeque_node
-\series bold
-*
-\series default
-node);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXdeque_del
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-
-\family typewriter
-HXdeque_\SpecialChar softhyphen
-push
-\family default
- and
-\family typewriter
-HXdeque_\SpecialChar softhyphen
-unshift
-\family default
- add the data item in a new node at the end (
-\begin_inset Quotes eld
-\end_inset
-
-push
-\begin_inset Quotes erd
-\end_inset
-
-) or as the new first element (
-\begin_inset Quotes eld
-\end_inset
-
-unshift
-\begin_inset Quotes erd
-\end_inset
-
- as Perl calls it), respectively.
- The functions will return the new node on success, or
-\family typewriter
-NULL
-\family default
- on failure and
-\family typewriter
-errno
-\family default
- will be set.
- The node is owned by the list.
-\end_layout
-
-\begin_layout Standard
-
-\family typewriter
-HXdeque_\SpecialChar softhyphen
-pop
-\family default
- and
-\family typewriter
-HXdeque_\SpecialChar softhyphen
-shift
-\family default
- remove the last (
-\begin_inset Quotes eld
-\end_inset
-
-pop
-\begin_inset Quotes erd
-\end_inset
-
-) or first (
-\begin_inset Quotes eld
-\end_inset
-
-shift
-\begin_inset Quotes erd
-\end_inset
-
-) node, respectively, and return the data pointer that was stored in the
- data.
-\end_layout
-
-\begin_layout Standard
-
-\family typewriter
-HXdeque_\SpecialChar softhyphen
-move
-\family default
- will unlink a node from its list, and reinsert it after the given target
- node, which may be in a different list.
-\end_layout
-
-\begin_layout Standard
-Deleting a node is accomplished by calling
-\family typewriter
-HXdeque_del
-\family default
- on it.
- The data pointer stored in the node is not freed, but returned.
-\end_layout
-
-\begin_layout Subsection
-Iteration
-\end_layout
-
-\begin_layout Standard
-Iterating over a HXdeque linked list is done manually and without additional
- overhead of function calls:
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-const struct
-\series default
- HXdeque_node
-\series bold
-*
-\series default
-node;
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-for
-\series default
- (node = dq->first; node != NULL; node = node->next)
-\begin_inset Newline newline
-\end_inset
-
- do_something(node->ptr);
-\end_layout
-
-\begin_layout Subsection
-Searching
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-struct
-\series default
- HXdeque_node
-\series bold
-*
-\series default
-HXdeque_find(
-\series bold
-struct
-\series default
- HXdeque
-\series bold
-*
-\series default
-dq,
-\series bold
-const void *
-\series default
-ptr);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXdeque_find
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-void *
-\series default
-HXdeque_get(
-\series bold
-struct
-\series default
- HXdeque
-\series bold
-*
-\series default
-dq,
-\series bold
-void *
-\series default
-ptr);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXdeque_get
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-
-\family typewriter
-HXdeque_find
-\family default
- searches for the node which contains
-\family typewriter
-ptr
-\family default
-, and does so by beginning at the start of the list.
- If no node is found,
-\family typewriter
-NULL
-\family default
- is returned.
- If a pointer is more than once in the list, any node may be returned.
-\end_layout
-
-\begin_layout Standard
-
-\family typewriter
-HXdeque_get
-\family default
- will further return the data pointer stored in the node
-\begin_inset space ~
-\end_inset
-
-— however, since that is just what the
-\family typewriter
-ptr
-\family default
- argument is, the function practically only checks for existence of
-\family typewriter
-ptr
-\family default
- in the list.
-\end_layout
-
-\begin_layout Subsection
-Examples
-\end_layout
-
-\begin_layout Standard
-
-\series bold
-\begin_inset Float figure
-placement h
-wide false
-sideways false
-status open
-
-\begin_layout LyX-Code
-
-\series bold
-#include
-\series default
- <stdio.h>
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-#include
-\series default
- <stdlib.h>
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-#include
-\series default
- <string.h>
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-#include
-\series default
- <libHX/defs.h>
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-#include
-\series default
- <libHX/deque.h>
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-#include
-\series default
- <libHX/string.h>
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-#include
-\series default
- <pwd.h>
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-
-\begin_inset Newline newline
-\end_inset
-
-int
-\series default
- main(
-\series bold
-void
-\series default
-)
-\begin_inset Newline newline
-\end_inset
-
-{
-\series bold
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series default
-
-\series bold
-struct
-\series default
- HXdeque
-\series bold
-*
-\series default
-dq = HXdeque_init();
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-struct
-\series default
- passwd *pw;
-\begin_inset Newline newline
-\end_inset
-
-
-\family typewriter
-\series bold
-unsigned int
-\series default
- elem;
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-char **
-\series default
-users;
-\family default
-
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
- setpwent();
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-while
-\series default
- ((pw = getpwent()) != NULL)
-\begin_inset Newline newline
-\end_inset
-
- HXdeque_push(dq, HX_strdup(pw->pw_name));
-\begin_inset Newline newline
-\end_inset
-
- endpwent();
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
- users =
-\series bold
-reinterpret_cast
-\series default
-(
-\series bold
-char **
-\series default
-, HXdeque_to_vec(dq, &elem));
-\begin_inset Newline newline
-\end_inset
-
- HXdeque_free(dq);
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
- qsort(users, elem,
-\series bold
-sizeof
-\series default
-(*users),
-\series bold
-static_cast
-\series default
-(
-\series bold
-void *
-\series default
-, strcmp));
-\begin_inset Newline newline
-\end_inset
-
- return 0;
-\begin_inset Newline newline
-\end_inset
-
-}
-\end_layout
-
-\begin_layout Plain Layout
-\begin_inset Caption Standard
-
-\begin_layout Plain Layout
-Example use of HXdeque to store and sort a list
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-In this example, all usernames are obtained from NSS, and put into a list.
-
-\family typewriter
-HX_strdup
-\family default
- is used, because
-\family typewriter
-getpwent
-\family default
- will overwrite the buffer it uses to store its results.
- The list is then converted to an array, and the list is freed (because
- it is not need it anymore).
-
-\family typewriter
-HXdeque_genocide
-\family default
- must not be used here, because it would free all the data pointers (strings
- here) that were just inserted into the list.
- Finally, the list is sorted using the well-known
-\family typewriter
-qsort
-\family default
- function.
- Because
-\family typewriter
-strcmp
-\family default
- takes two
-\family typewriter
-const char
-\begin_inset space ~
-\end_inset
-
-*
-\family default
- arguments, but
-\family typewriter
-qsort
-\family default
- mandates a function taking two
-\family typewriter
-const void
-\begin_inset space ~
-\end_inset
-
-*
-\family default
-, a cast can be used to silence the compiler.
- This only works because we know that the array consists of a bunch of
-\family typewriter
-char
-\begin_inset space ~
-\end_inset
-
-*
-\family default
- pointers, so
-\family typewriter
-strcmp
-\family default
- will work.
-\end_layout
-
-\begin_layout Standard
-\begin_inset Newpage clearpage
-\end_inset
-
-
-\end_layout
-
-\begin_layout Section
-Inline doubly-linked list
-\begin_inset CommandInset label
-LatexCommand label
-name "sec:list"
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-Classical linked-list implementations, such as HXdeque, either store the
- actual data within a node, or indirectly through a pointer, but the
-\begin_inset Quotes eld
-\end_inset
-
-inline doubly-linked list
-\begin_inset Quotes erd
-\end_inset
-
- instead does it reverse and has the list head within the data structure.
-\end_layout
-
-\begin_layout Standard
-\begin_inset Float figure
-placement h
-wide false
-sideways false
-status open
-
-\begin_layout LyX-Code
-
-\series bold
-struct
-\series default
- package_desc {
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-char *
-\series default
-package_name;
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-int
-\series default
- version;
-\end_layout
-
-\begin_layout LyX-Code
-};
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-struct
-\series default
- classic_direct_node {
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-struct
-\series default
- classic_direct_node
-\series bold
-*
-\series default
-next,
-\series bold
-*
-\series default
-prev;
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-struct
-\series default
- package_desc direct_data;
-\begin_inset Newline newline
-\end_inset
-
-};
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-struct
-\series default
- classic_indirect_node {
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-struct
-\series default
- classic_indirect_node
-\series bold
-*
-\series default
-next,
-\series bold
-*
-\series default
-prev;
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-void *
-\series default
-indirect_data;
-\begin_inset Newline newline
-\end_inset
-
-};
-\end_layout
-
-\begin_layout Plain Layout
-\begin_inset Caption Standard
-
-\begin_layout Plain Layout
-Classic linked-list implementations with direct/indirect data blocks.
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-\begin_inset Float figure
-placement H
-wide false
-sideways false
-status open
-
-\begin_layout LyX-Code
-
-\series bold
-struct
-\series default
- package_desc {
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-struct
-\series default
- HXlist_head list;
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-char *
-\series default
-package_name;
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-int
-\series default
- version;
-\begin_inset Newline newline
-\end_inset
-
-};
-\end_layout
-
-\begin_layout Plain Layout
-\begin_inset Caption Standard
-
-\begin_layout Plain Layout
-List head (next,prev pointers) inlined into the data block
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-At first glance, an inline list does not look much different from
-\family typewriter
-struct classic_\SpecialChar softhyphen
-direct_\SpecialChar softhyphen
-data
-\family default
-, it is mostly a viewpoint decision which struct is in the foreground.
-\end_layout
-
-\begin_layout Subsection
-Synopsis
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-#include
-\series default
- <libHX/list.h>
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-libHX/list.h
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-struct
-\series default
- HXlist_head {
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-struct HXlist_head
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-/*
-\family roman
-\series default
-\shape italic
-All fields considered private
-\family default
-\series bold
-\shape default
- */
-\series default
-
-\begin_inset Newline newline
-\end_inset
-
-};
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-HXLIST_HEAD_INIT(name);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXLIST_HEAD_INIT
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-HXLIST_HEAD(name);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXLIST_HEAD
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-void
-\series default
- HXlist_init(
-\series bold
-struct
-\series default
- HXlist_head
-\series bold
-*
-\series default
-list);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXlist_init
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-void
-\series default
- HXlist_add(
-\series bold
-struct
-\series default
- HXlist_head
-\series bold
-*
-\series default
-list,
-\series bold
-struct
-\series default
- HXlist_head
-\series bold
-*
-\series default
-elem);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXlist_add
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-void
-\series default
- HXlist_add_tail(
-\series bold
-struct
-\series default
- HXlist_head
-\series bold
-*
-\series default
-list,
-\series bold
-struct
-\series default
- HXlist_head
-\series bold
-*
-\series default
-elem);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXlist_add_tail
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-void
-\series default
- HXlist_del(
-\series bold
-struct
-\series default
- HXlist_head
-\series bold
-*
-\series default
-element);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXlist_del
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-bool
-\series default
- HXlist_empty(
-\series bold
-const struct
-\series default
- HXlist_head
-\series bold
-*
-\series default
-list);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXlist_empty
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXLIST_HEAD_INIT
-\family default
- This macro expands to the static initializer for a list head.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXLIST_HEAD
-\family default
- This macro expands to the definition of a list head (i.
-\begin_inset space \thinspace{}
-\end_inset
-
-e.
-\begin_inset space \space{}
-\end_inset
-
-
-\family typewriter
-struct HXlist_head name = HXLIST_HEAD_INIT;
-\family default
-)
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXlist_init
-\family default
- Initializes the list head.
- This function is generally used when the list head is on the heap where
- the static initializer cannot be used.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXlist_add
-\family default
- Adds
-\family typewriter
-elem
-\family default
- to the front of the list.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXlist_add_tail
-\family default
- Adds
-\family typewriter
-elem
-\family default
- to the end of the list.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXlist_del
-\family default
- Deletes the given element from the list.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXlist_empty
-\family default
- Tests whether the list is empty.
- Note: For clists, you could also use
-\family typewriter
-clist->items == 0
-\family default
-.
-\end_layout
-
-\begin_layout Subsection
-Traversal
-\end_layout
-
-\begin_layout Standard
-Traversal is implemented using macros that expand to for() statements which
- can syntactically be used like them, i.
-\begin_inset space \thinspace{}
-\end_inset
-
-e.
-\begin_inset space \space{}
-\end_inset
-
-curly braces may be omitted if only a single statement is in the body of
- the loop.
-\end_layout
-
-\begin_layout Standard
-The
-\family typewriter
-head
-\family default
- parameter specifies the list head (
-\family typewriter
-struct HXlist_head
-\family default
-),
-\family typewriter
-pos
-\family default
- specifies an iterator, also of type
-\family typewriter
-struct HXlist_head
-\family default
-.
- Lists can either be traversed in forward direction, or, using the
-\family typewriter
-_rev
-\family default
- variants, in reverse direction.
- The
-\family typewriter
-_safe
-\family default
- variants use a temporary
-\family typewriter
-n
-\family default
- to hold the next object in the list, which is needed when pos itself is
- going to be inaccessible at the end of the block, through, for example,
- freeing its encompassing object.
-\end_layout
-
-\begin_layout LyX-Code
-HXlist_for_each(pos, head)
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXlist_for_each
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-HXlist_for_each_rev(pos, head)
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXlist_for_each_rev
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-HXlist_for_each_safe(pos, n, head)
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXlist_for_each_safe
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-HXlist_for_each_rev_safe(pos, n, head)
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXlist_for_each_rev_safe
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXlist_for_each
-\family default
- Forward iteration over the list heads.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXlist_for_each_rev
-\family default
- Reverse iteration over the list heads.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXlist_for_each_safe
-\family default
- Forward iteration over the list heads that is safe against freeing
-\family typewriter
-pos
-\family default
-.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXlist_for_each_rev_safe
-\family default
- Reverse iteration over the list heads that is safe against freeing
-\family typewriter
-pos
-\family default
-.
-\end_layout
-
-\begin_layout Standard
-The
-\family typewriter
-_entry
-\family default
- variants use an iterator
-\family typewriter
-pos
-\family default
- of the type of the encompassing object (e.
-\begin_inset space \thinspace{}
-\end_inset
-
-g.
-\begin_inset space \space{}
-\end_inset
-
-
-\family typewriter
-struct item
-\family default
- in below's example), so that the manual
-\family typewriter
-HXlist_entry
-\family default
- invocation is not needed.
-
-\family typewriter
-member
-\family default
- is the name of the list structure embedded into the item.
-\end_layout
-
-\begin_layout LyX-Code
-HXlist_for_each_entry(pos, head, member)
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXlist_for_each_entry
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-HXlist_for_each_entry_rev(pos, head, member)
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXlist_for_each_entry_rev
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-HXlist_for_each_entry_safe(pos, n, head, member)
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXlist_for_each_entry_safe
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXlist_for_each_entry
-\family default
- Forward iteration over the list elements.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXlist_for_each_entry_rev
-\family default
- Reverse iteration over the list elements.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXlist_for_each_entry_safe
-\family default
- Forward iteration over the list elements that is safe against freeing
-\family typewriter
-pos
-\family default
-.
-\end_layout
-
-\begin_layout Subsection
-Examples
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-struct
-\series default
- item {
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-struct
-\series default
- HXlist_head anchor;
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-char
-\series default
- name
-\series bold
-[
-\series default
-32
-\series bold
-]
-\series default
-;
-\begin_inset Newline newline
-\end_inset
-
-};
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-struct
-\series default
- HXlist_head
-\series bold
-*
-\series default
-e;
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-struct
-\series default
- item
-\series bold
-*
-\series default
-i,
-\series bold
-*
-\series default
-j;
-\begin_inset Newline newline
-\end_inset
-
-HXLIST_HEAD(list);
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-i = malloc(
-\series bold
-sizeof
-\series default
-(
-\series bold
-*
-\series default
-i));
-\begin_inset Newline newline
-\end_inset
-
-HXlist_init(&e->anchor);
-\begin_inset Newline newline
-\end_inset
-
-strcpy(i->name, "foo");
-\begin_inset Newline newline
-\end_inset
-
-HXlist_add_tail(&list, &i->anchor);
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-i = malloc(
-\series bold
-sizeof
-\series default
-(
-\series bold
-*
-\series default
-i));
-\begin_inset Newline newline
-\end_inset
-
-HXlist_init(&e->anchor);
-\begin_inset Newline newline
-\end_inset
-
-strcpy(i->name, "bar");
-\begin_inset Newline newline
-\end_inset
-
-HXlist_add_tail(&list, &i->anchor);
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-HXlist_for_each(e, &list) {
-\begin_inset Newline newline
-\end_inset
-
- i = HXlist_entry(e,
-\series bold
-typeof
-\series default
-(
-\series bold
-*
-\series default
-i), anchor);
-\begin_inset Newline newline
-\end_inset
-
- printf("e=%p i=%p name=%s
-\backslash
-n", e, i, i->name);
-\begin_inset Newline newline
-\end_inset
-
-}
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-HXlist_for_each_entry(i, &list, anchor)
-\begin_inset Newline newline
-\end_inset
-
- printf("i=%p name=%s
-\backslash
-n", i, i->name);
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-HXlist_for_each_entry_rev(i, &list, anchor)
-\begin_inset Newline newline
-\end_inset
-
- printf("i=%p name=%s
-\backslash
-n", i, i->name);
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-HXlist_for_each_entry_safe(i, j, &list, anchor) {
-\begin_inset Newline newline
-\end_inset
-
- printf("i=%p name=%s
-\backslash
-n", i, i->name);
-\begin_inset Newline newline
-\end_inset
-
- free(i);
-\begin_inset Newline newline
-\end_inset
-
-}
-\end_layout
-
-\begin_layout Subsection
-When to use HXdeque/HXlist
-\end_layout
-
-\begin_layout Standard
-The choice whether to use HXdeque or HXlist/HXclist depends on whether one
- wants the list head handling on the developer or on the library.
- Especially for
-\begin_inset Quotes eld
-\end_inset
-
-atomic
-\begin_inset Quotes erd
-\end_inset
-
- and
-\begin_inset Quotes eld
-\end_inset
-
-small
-\begin_inset Quotes erd
-\end_inset
-
- data, it might be easier to just let HXdeque do the management.
- Compare the following two code examples to store strings:
-\end_layout
-
-\begin_layout Standard
-\begin_inset Float figure
-placement H
-wide false
-sideways false
-status open
-
-\begin_layout LyX-Code
-
-\series bold
-int
-\series default
- main(
-\family typewriter
-\series bold
-int
-\series default
- argc,
-\series bold
-const char **
-\series default
-argv)
-\begin_inset Newline newline
-\end_inset
-
-{
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-struct
-\series default
- HXdeque
-\series bold
-*
-\series default
-dq = HXdeque_init();
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-while
-\series default
- (--argc)
-\begin_inset Newline newline
-\end_inset
-
- HXdeque_push(dq, ++argv);
-\begin_inset Newline newline
-\end_inset
-
-
-\family default
-\series bold
-return
-\family typewriter
-\series default
- 0;
-\begin_inset Newline newline
-\end_inset
-
-}
-\end_layout
-
-\begin_layout Plain Layout
-\begin_inset Caption Standard
-
-\begin_layout Plain Layout
-Storing strings in a HXdeque
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-\begin_inset Float figure
-placement H
-wide false
-sideways false
-status open
-
-\begin_layout LyX-Code
-
-\series bold
-struct
-\series default
- element {
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-struct
-\series default
- HXlist_head list;
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-char *
-\family typewriter
-\series default
-data;
-\begin_inset Newline newline
-\end_inset
-
-};
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-int
-\series default
- main(
-\series bold
-int
-\series default
- main,
-\series bold
-const char **
-\series default
-argv)
-\begin_inset Newline newline
-\end_inset
-
-{
-\begin_inset Newline newline
-\end_inset
-
- HXLIST_HEAD(lh);
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-while
-\series default
- (--argc) {
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-struct
-\series default
- element
-\series bold
-*
-\series default
-e = malloc(
-\family default
-\series bold
-sizeof
-\family typewriter
-\series default
-(*e));
-\begin_inset Newline newline
-\end_inset
-
- e->data = *++argv;
-\begin_inset Newline newline
-\end_inset
-
- HXlist_init(&e->list);
-\begin_inset Newline newline
-\end_inset
-
- HXlist_add_tail(&e->list);
-\begin_inset Newline newline
-\end_inset
-
- }
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-return
-\series default
- 0;
-\begin_inset Newline newline
-\end_inset
-
-}
-\end_layout
-
-\begin_layout Plain Layout
-\begin_inset Caption Standard
-
-\begin_layout Plain Layout
-Storing strings in a HXlist
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-These examples assume that
-\family typewriter
-argv
-\family default
- is persistent, which, for the sample, is true.
-\end_layout
-
-\begin_layout Standard
-With HXlist, one needs to have a struct with a HXlist_head in it, and if
- one does not already have such a struct
-\begin_inset space ~
-\end_inset
-
-—e.
-\begin_inset space \thinspace{}
-\end_inset
-
-g.
-\begin_inset space \space{}
-\end_inset
-
-by means of wanting to store more than just one value
-\begin_inset space ~
-\end_inset
-
-— one will need to create it first, as shown, and this may lead to an expansion
- of code.
-\end_layout
-
-\begin_layout Standard
-This however does not mean that HXlist is the better solution over HXdeque
- for data already available in a struct.
- As each struct has a list_head that is unique to the node, it is not possible
- to share this data.
- Trying to add a HXlist_head to another list is not going to end well, while
- HXdeque has no problem with this as list heads are detached from the actual
- data in HXdeque.
-\end_layout
-
-\begin_layout Standard
-\begin_inset Float figure
-placement H
-wide false
-sideways false
-status open
-
-\begin_layout LyX-Code
-
-\series bold
-struct
-\series default
- point p = {15, 30};
-\begin_inset Newline newline
-\end_inset
-
-HXdeque_push(dq, &p);
-\begin_inset Newline newline
-\end_inset
-
-HXdeque_push(dq, &p);
-\end_layout
-
-\begin_layout Plain Layout
-\begin_inset Caption Standard
-
-\begin_layout Plain Layout
-Data can be added multiple times in a HXdeque without ill effects
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-To support this, an extra allocation is needed on the other hand.
- In a HXlist, to store
-\begin_inset Formula $n$
-\end_inset
-
- elements of compound data (e.
-\begin_inset space \thinspace{}
-\end_inset
-
-g.
-\begin_inset space \space{}
-\end_inset
-
-
-\family typewriter
-struct point
-\family default
-),
-\begin_inset Formula $n$
-\end_inset
-
- allocations are needed, assuming the list head is a stack object, and the
- points are not.
- HXdeque will need at least
-\begin_inset Formula $2n+1$
-\end_inset
-
- allocations,
-\begin_inset Formula $n$
-\end_inset
-
- for the nodes,
-\begin_inset Formula $n$
-\end_inset
-
- for the points and another for the head.
-\end_layout
-
-\begin_layout Standard
-\begin_inset Newpage clearpage
-\end_inset
-
-
-\end_layout
-
-\begin_layout Section
-Counted inline doubly-linked list
-\begin_inset CommandInset label
-LatexCommand label
-name "sec:clist"
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-clist is the inline doubly-linked list from chapter
-\begin_inset space ~
-\end_inset
-
-
-\begin_inset CommandInset ref
-LatexCommand ref
-reference "sec:list"
-
-\end_inset
-
-, extended by a counter to retrieve the number of elements in the list in
-
-\begin_inset Formula $\mathcal{O}\left(1\right)$
-\end_inset
-
- time.
- This is also why all operations always require the list head.
- For traversal of clists, use the corresponding HXlist macros.
-\end_layout
-
-\begin_layout Subsection
-Synopsis
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-#include
-\series default
- <libHX/list.h>
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-libHX/list.h
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-struct
-\series default
- HXclist_head {
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-struct HXclist_head
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-/*
-\family roman
-\series default
-\shape italic
-public readonly:
-\family default
-\series bold
-\shape default
- */
-\series default
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-unsigned int
-\series default
- items;
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-/*
-\family roman
-\series default
-\shape italic
-Undocumented fields are considered
-\begin_inset Quotes eld
-\end_inset
-
-private
-\begin_inset Quotes erd
-\end_inset
-
-
-\family default
-\series bold
-\shape default
- */
-\series default
-
-\begin_inset Newline newline
-\end_inset
-
-};
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-HXCLIST_HEAD_INIT(name);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXCLIST_HEAD_INIT
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-HXCLIST_HEAD(name);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXCLIST_HEAD
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-void
-\series default
- HXclist_init(
-\series bold
-struct
-\series default
- HXclist_head
-\series bold
-*
-\series default
-head);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXclist_init
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-void
-\series default
- HXclist_unshift(
-\series bold
-struct
-\series default
- HXclist_head
-\series bold
-*
-\series default
-head,
-\series bold
-struct
-\series default
- HXlist_head
-\series bold
-*
-\series default
-new_node);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXclist_unshift
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-void
-\series default
- HXclist_push(
-\series bold
-struct
-\series default
- HXclist_head
-\series bold
-*
-\series default
-head,
-\series bold
-struct
-\series default
- HXlist_head
-\series bold
-*
-\series default
-new_node);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXclist_push
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-type
-\series default
- HXclist_pop(
-\series bold
-struct
-\series default
- HXclist_head
-\series bold
-*
-\series default
-head,
-\series bold
-type
-\series default
-, member);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXclist_pop
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-type
-\series default
- HXclist_shift(
-\series bold
-struct
-\series default
- HXclist_head
-\series bold
-*
-\series default
-head,
-\series bold
-type
-\series default
-, member);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXclist_shift
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-void
-\series default
- HXclist_del(
-\series bold
-struct
-\series default
- HXclist_head
-\series bold
-*
-\series default
-head,
-\series bold
-struct
-\series default
-HXlist_chead
-\series bold
-*
-\series default
-node);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXclist_del
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXCLIST_HEAD_INIT
-\family default
- Macro that expands to the static initializer for a clist.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXCLIST_HEAD
-\family default
- Macro that expands to the definition of a clist head, with initialization.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXclist_init
-\family default
- Initializes a clist.
- This function is generally used when the head has been allocated from the
- heap.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXclist_unshift
-\family default
- Adds the node to the front of the list.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXclist_push
-\family default
- Adds the node to the end of the list.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXclist_pop
-\family default
- Removes the last node in the list and returns it.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXclist_shift
-\family default
- Removes the first node in the list and returns it.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXclist_del
-\family default
- Deletes the node from the list.
-\end_layout
-
-\begin_layout Standard
-The list count in the clist head is updated whenever a modification is done
- on the clist through these functions.
-\end_layout
-
-\begin_layout Standard
-\begin_inset Newpage clearpage
-\end_inset
-
-
-\end_layout
-
-\begin_layout Part
-Strings and memory
-\end_layout
-
-\begin_layout Section
-String operations
-\begin_inset CommandInset label
-LatexCommand label
-name "sec:strings"
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-Some string functions are merely present in libHX because they are otherwise
- unportable; some are only in the C libraries of the BSDs, some only in
- GNU libc.
-\end_layout
-
-\begin_layout Subsection
-Locating chars
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-#include
-\series default
- <libHX/string.h>
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-libHX/string.h
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-void *
-\series default
-HX_memmem(
-\series bold
-const void *
-\series default
-haystack,
-\series bold
-size_t
-\series default
- hsize,
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-const void *
-\series default
-needle,
-\series bold
-size_t
-\series default
- nsize);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HX_memmem
-\end_layout
-
-\end_inset
-
-
-\series bold
-
-\begin_inset Newline newline
-\end_inset
-
-char *
-\series default
-HX_strbchr(
-\series bold
-const char *
-\series default
-start,
-\series bold
-const char *
-\series default
-now,
-\series bold
-char
-\series default
- delimiter);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HX_strbchr
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-char *
-\series default
-HX_strchr2(
-\series bold
-const char *
-\series default
-s,
-\series bold
-const char *
-\series default
-accept);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-HX_strchr2
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-size_t
-\series default
- HX_strrcspn(
-\series bold
-const char *
-\series default
-s,
-\series bold
-const char *
-\series default
-reject);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HX_strccspn
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HX_memmem
-\family default
- Analogous to
-\family typewriter
-strstr
-\family default
-(3),
-\family typewriter
-memmem
-\family default
- tries to locate the memory block pointed to by
-\family typewriter
-needle
-\family default
- (which is of length
-\family typewriter
-nsize
-\family default
-) in the block pointed to by
-\family typewriter
-haystack
-\family default
- (which is of size
-\family typewriter
-hsize
-\family default
-).
- It returns a pointer to the first occurrence in
-\family typewriter
-haystack
-\family default
-, or
-\family typewriter
-NULL
-\family default
- when it was not found.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HX_strbchr
-\family default
- Searches the character specified by
-\family typewriter
-delimiter
-\family default
- in the range from
-\family typewriter
-now
-\family default
- to
-\family typewriter
-start
-\family default
-.
- It works like
-\family typewriter
-strrchr
-\family default
-(3)
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-strrchr
-\end_layout
-
-\end_inset
-
-, but begins at
-\family typewriter
-now
-\family default
- rather than the end of the string.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HX_strchr2
-\family default
- This function searches the string
-\family typewriter
-s
-\family default
- for any set of bytes that are not specified in the second argument,
-\family typewriter
-n
-\family default
-.
- In this regard, the function is the opposite to
-\family typewriter
-strpbrk
-\family default
-(3)
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-strpbrk
-\end_layout
-
-\end_inset
-
-.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HX_strrcspn
-\family default
- Works like
-\family typewriter
-strcspn
-\family default
-(3)
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\size normal
-\color none
-strcspn
-\end_layout
-
-\end_inset
-
-, but processes the string from end to start.
-\end_layout
-
-\begin_layout Subsection
-Extraction
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-#include
-\series default
- <libHX/string.h>
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-libHX/string.h
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-char *
-\series default
-HX_basename(
-\series bold
-const char *
-\series default
-s);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HX_basename
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-char *
-\series default
-HX_basename_exact(
-\series bold
-const char *
-\series default
-s);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HX_basename_exact
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-char *
-\series default
-HX_dirname(
-\series bold
-const char *
-\series default
-s);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\size normal
-\color none
-HX_dirname
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-char *
-\series default
-HX_strmid(
-\series bold
-const char *
-\series default
-s,
-\series bold
-long
-\series default
- offset,
-\series bold
-long
-\series default
- length);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\size normal
-\color none
-HX_strmid
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HX_basename
-\family default
- Returns a pointer to the basename portion of the supplied path
-\family typewriter
-s
-\family default
-.
- The result of this function is never
-\family typewriter
-NULL
-\family default
-, and must never be freed either.
- Trailing slashes are not stripped, to avoid having to do an allocation.
- In other words,
-\family typewriter
-basename("/mnt/")
-\family default
- will return
-\begin_inset Quotes eld
-\end_inset
-
-
-\family typewriter
-mnt/
-\family default
-
-\begin_inset Quotes erd
-\end_inset
-
-.
- If you need to have the slashes stripped, use
-\family typewriter
-HX_basename_exact
-\family default
-.
- A possible use for this function is, for example, to derive a logging prefix
- from
-\family typewriter
-argv[0]
-\family default
-.
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-int
-\series default
- main(
-\series bold
-int
-\series default
- argc,
-\series bold
-const char **
-\series default
-argv)
-\begin_inset Newline newline
-\end_inset
-
-{
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-if
-\series default
- (foo())
-\end_layout
-
-\begin_layout LyX-Code
- fprintf(stderr, "%s: Special condition occurred.
-\backslash
-n",
-\begin_inset Newline newline
-\end_inset
-
- HX_basename(argv[0]));
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-return
-\series default
- 0;
-\begin_inset Newline newline
-\end_inset
-
-}
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HX_basename_exact
-\family default
- The accurate and safe version of
-\family typewriter
-HX_basename
-\family default
- that deals with trailing slashes correctly and produces the same result
- as
-\family typewriter
-dirname
-\family default
-(3).
- It returns a pointer to a newly-allocated string that must be freed when
- done using.
-
-\family typewriter
-NULL
-\family default
- may be returned in case of an allocation error.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HX_dirname
-\family default
- Returns a pointer to a new string that contains the directory name portion
- (everything except basename).
- When done using the string, it must be freed to avoid memory leaks.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HX_strmid
-\family default
- Extract a substring of
-\family typewriter
-length
-\family default
- characters from
-\family typewriter
-s
-\family default
-, beginning at
-\family typewriter
-offset
-\family default
-.
- If
-\family typewriter
-offset
-\family default
- is negative, counting beings from the end of the string;
-\begin_inset Formula $-1$
-\end_inset
-
- is the last character (not the
-\family typewriter
-'
-\backslash
-0'
-\family default
- byte).
- If
-\family typewriter
-length
-\family default
- is negative, it will leave out that many characters off the end.
- The function returns a pointer to a new string, and the user has to free
- it.
-\end_layout
-
-\begin_layout Subsection
-In-place transformations
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-#include
-\series default
- <libHX/string.h>
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-libHX/string.h
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-char *
-\series default
-HX_chomp(
-\series bold
-char *
-\series default
-s);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\size normal
-\color none
-HX_chomp
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-size_t
-\series default
- HX_strltrim(
-\series bold
-char *
-\series default
-s);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\size normal
-\color none
-HX_strltrim
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-char *
-\series default
-HX_stpltrim(
-\series bold
-const char *
-\series default
-s);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-HX_stpltrim
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-char *
-\series default
-HX_strlower(
-\series bold
-char *
-\series default
-s);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\size normal
-\color none
-HX_strlower
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-char *
-\series default
-HX_strrev(
-\series bold
-char *
-\series default
-s);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\size normal
-\color none
-HX_strrev
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-size_t
-\series default
- HX_strrtrim(
-\series bold
-char *
-\series default
-s);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\size normal
-\color none
-HX_strrtrim
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-char *
-\series default
-HX_strupper(
-\series bold
-char *
-\series default
-s);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\size normal
-\color none
-HX_strupper
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HX_chomp
-\family default
- Removes the characters
-\family typewriter
-'
-\backslash
-r'
-\family default
- and
-\family typewriter
-'
-\backslash
-n'
-\family default
- from the right edge of the string.
- Returns the original argument.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HX_strltrim
-\family default
- Trim all whitespace (characters on which
-\family typewriter
-isspace
-\family default
-(3) return true) on the left edge of the string.
- Returns the number of characters that were stripped.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HX_stpltrim
-\family default
- Returns a pointer to the first non-whitespace character in
-\family typewriter
-s
-\family default
-.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HX_strlower
-\family default
- Transforms all characters in the string
-\family typewriter
-s
-\family default
- into lowercase using
-\family typewriter
-tolower
-\family default
-(3).
- Returns the original argument.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HX_strrev
-\family default
- Reverse the string in-place.
- Returns the original argument.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HX_strrtrim
-\family default
- Trim all whitespace on the right edge of the string.
- Returns the number of characters that were stripped.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HX_strupper
-\family default
- Transforms all characters in the string
-\family typewriter
-s
-\family default
- into uppercase using
-\family typewriter
-toupper
-\family default
-(3).
- Returns the original argument.
-\end_layout
-
-\begin_layout Subsection
-Out-of-place quoting transforms
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-#include
-\series default
- <libHX/string.h>
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-libHX/string.h
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-char *
-\series default
-HX_strquote(
-\series bold
-const char *
-\series default
-s,
-\series bold
-unsigned int
-\series default
- type,
-\series bold
-char **
-\series default
-free_me);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HX_strquote
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-
-\family typewriter
-HX_strquote
-\family default
- will escape metacharacters in a string according to
-\family typewriter
-type
-\family default
-, and returns the escaped result.
-\end_layout
-
-\begin_layout Standard
-Possible values for
-\family typewriter
-type
-\family default
-:
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXQUOTE_SQUOTE
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXQUOTE_SQUOTE
-\end_layout
-
-\end_inset
-
- Escape all single quotes and backslashes in a string with a backslash.
- (
-\begin_inset Quotes eld
-\end_inset
-
-Ol'
-\backslash
-Backslash
-\begin_inset Quotes erd
-\end_inset
-
-
-\begin_inset Formula $\rightarrow$
-\end_inset
-
-
-\begin_inset Quotes eld
-\end_inset
-
-Ol
-\backslash
-'
-\backslash
-
-\backslash
-Backslash
-\begin_inset Quotes erd
-\end_inset
-
-)
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXQUOTE_DQUOTE
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXQUOTE_DQUOTE
-\end_layout
-
-\end_inset
-
- Escape all double quotes and backslahes in a string with the backslash
- method.
- (
-\begin_inset Quotes eld
-\end_inset
-
-Ol
-\begin_inset Quotes erd
-\end_inset
-
-
-\backslash
-Backslash
-\begin_inset Quotes erd
-\end_inset
-
-
-\begin_inset Formula $\rightarrow$
-\end_inset
-
-
-\begin_inset Quotes eld
-\end_inset
-
-Ol
-\backslash
-
-\begin_inset Quotes erd
-\end_inset
-
-
-\backslash
-
-\backslash
-Backslash
-\begin_inset Quotes erd
-\end_inset
-
-)
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXQUOTE_HTML
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXQUOTE_HTML
-\end_layout
-
-\end_inset
-
- Escape '
-\family typewriter
-<
-\family default
-', '
-\family typewriter
->
-\family default
-', '
-\family typewriter
-&
-\family default
-' and '
-\family typewriter
-"
-\family default
-' by their respective HTML entities
-\family typewriter
-&lt;
-\family default
-,
-\family typewriter
-&gt;
-\family default
-,
-\family typewriter
-&amp;
-\family default
- and
-\family typewriter
-&quot;
-\family default
-.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXQUOTE_LDAPFLT
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXQUOTE_LDAPFLT
-\end_layout
-
-\end_inset
-
- Escape the string using backslash-plus-hexcode notation as described in
- RFC 4515
-\begin_inset Foot
-status open
-
-\begin_layout Plain Layout
-\begin_inset Flex URL
-status collapsed
-
-\begin_layout Plain Layout
-
-http://tools.ietf.org/html/rfc4515
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\end_inset
-
-, to make it suitable for use in an LDAP search filter.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXQUOTE_LDAPRDN
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXQUOTE_LDAPRDN
-\end_layout
-
-\end_inset
-
- Escape the string using backslash-plus-hexcode notation as described in
- RFC 4514
-\begin_inset Foot
-status open
-
-\begin_layout Plain Layout
-\begin_inset Flex URL
-status collapsed
-
-\begin_layout Plain Layout
-
-http://tools.ietf.org/html/rfc4514
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\end_inset
-
-, to make it suitable for use in an LDAP Relative Distinguished Name.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXQUOTE_BASE64
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXQUOTE_BASE64
-\end_layout
-
-\end_inset
-
- Transform the string to BASE64, as described in RFC 4648
-\begin_inset Foot
-status open
-
-\begin_layout Plain Layout
-\begin_inset Flex URL
-status collapsed
-
-\begin_layout Plain Layout
-
-http://tools.ietf.org/html/rfc4648
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\end_inset
-
-.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXQUOTE_URIENC
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXQUOTE_URIENC
-\end_layout
-
-\end_inset
-
- Escape the string so that it becomes a valid part for an URI.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXQUOTE_SQLSQUOTE
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXQUOTE_SQLSQUOTE
-\end_layout
-
-\end_inset
-
- Escape all single quotes in the string by double single-quotes, as required
- for using it in a single-quoted SQL string.
- No surrounding quotes will be generated to facilitate concatenating of
-
-\family typewriter
-HX_strquote
-\family default
- results.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXQUOTE_SQLBQUOTE
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXQUOTE_SQLBQUOTE
-\end_layout
-
-\end_inset
-
- Escape all backticks in the string by double backticks, as required for
- using it in a backtick-quoted SQL string (used for table names and columns).
- No surrounding ticks will be generated to facilitate concatenation.
-\end_layout
-
-\begin_layout Standard
-Specifying an unrecognized type will result in
-\family typewriter
-NULL
-\family default
- being returned and
-\family typewriter
-errno
-\family default
- be set to
-\family typewriter
-EINVAL
-\family default
-.
-\end_layout
-
-\begin_layout Standard
-If
-\family typewriter
-free_me
-\family default
- is
-\family typewriter
-NULL
-\family default
-, the function will always allocate memory, even if the string needs no
- quoting.
- The program then has to free the result:
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-char *
-\series default
-s = HX_strquote("<head>", HXQUOTE_HTML, NULL);
-\begin_inset Newline newline
-\end_inset
-
-printf("%s
-\backslash
-n", s);
-\begin_inset Newline newline
-\end_inset
-
-free(s);
-\end_layout
-
-\begin_layout Standard
-If
-\family typewriter
-free_me
-\family default
- is not
-\family typewriter
-NULL
-\family default
- however, the function will put the pointer to the memory area into
-\family typewriter
-*free_me
-\family default
-, if the string needed quoting.
- The program then has to free that after it is done with the quoted result:
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-char *
-\series default
-tmp = NULL;
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-char *
-\series default
-s = HX_strquote("head", HXQUOTE_HTML, &tmp);
-\begin_inset Newline newline
-\end_inset
-
-printf("%s
-\backslash
-n", s);
-\begin_inset Newline newline
-\end_inset
-
-free(tmp);
-\end_layout
-
-\begin_layout Standard
-
-\family typewriter
-tmp
-\family default
- could be
-\family typewriter
-NULL
-\family default
-, and since
-\family typewriter
-free(NULL)
-\family default
- is not an error, this is perfectly valid.
- Furthermore, if
-\family typewriter
-*free_me
-\family default
- is not
-\family typewriter
-NULL
-\family default
- by the time
-\family typewriter
-HX_strquote
-\family default
- is called, the function will free it.
- This makes it possible to call
-\family typewriter
-HX_strquote
-\family default
- in succession without
-\family typewriter
-free
-\family default
-s in between:
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-char *
-\series default
-tmp = NULL;
-\begin_inset Newline newline
-\end_inset
-
-printf("%s
-\backslash
-n", HX_strquote("<html>", HXQUOTE_HTML, &tmp));
-\begin_inset Newline newline
-\end_inset
-
-printf("%s
-\backslash
-n", HX_strquote("<head>", HXQUOTE_HTML, &tmp));
-\begin_inset Newline newline
-\end_inset
-
-free(tmp);
-\end_layout
-
-\begin_layout Subsection
-Tokenizing
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-#include
-\series default
- <libHX/string.h>
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-libHX/string.h
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-char **
-\series default
-HX_split(
-\series bold
-const char *
-\series default
-s,
-\series bold
-const char *
-\series default
-delimiters,
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-size_t *
-\series default
-fields,
-\series bold
-int
-\series default
- max);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\size normal
-\color none
-HX_split
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-char **
-\series default
-HX_split_inplace(
-\series bold
-char *
-\series default
-s,
-\series bold
-const char *
-\series default
-delimiters,
-\series bold
-int *
-\series default
-fields,
-\series bold
-int
-\series default
- max);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\size normal
-\color none
-HX_split_inplace
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-int
-\series default
- HX_split_fixed(
-\series bold
-char *
-\series default
-s,
-\series bold
-const char *
-\series default
-delimiters,
-\series bold
-int
-\series default
- max,
-\series bold
-char **
-\series default
-arr);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\size normal
-\color none
-HX_split_fixed
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-char *
-\series default
-HX_strsep(
-\series bold
-char **
-\series default
-sp,
-\series bold
-const char *
-\series default
-delimiters);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\size normal
-\color none
-HX_strsep
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-char *
-\series default
-HX_strsep2(
-\series bold
-char **
-\series default
-sp,
-\series bold
-const char *
-\series default
-dstr);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\size normal
-\color none
-HX_strsep2
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HX_split
-\family default
- Split the string
-\family typewriter
-s
-\family default
- on any characters from the
-\begin_inset Quotes eld
-\end_inset
-
-
-\family typewriter
-delimiters
-\family default
-
-\begin_inset Quotes erd
-\end_inset
-
- string.
- Both the substrings and the array holding the pointers to these substrings
- will be allocated as required; the original string is not modified.
- If
-\family typewriter
-max
-\family default
- is larger than zero, produces no more than
-\family typewriter
-max
-\family default
- fields.
- If
-\family typewriter
-fields
-\family default
- is not
-\family typewriter
-NULL
-\family default
-, the number of elements produced will be stored in
-\family typewriter
-*fields
-\family default
-.
- The result is a
-\family typewriter
-NULL
-\family default
--terminated array of
-\family typewriter
-char
-\begin_inset space ~
-\end_inset
-
-*
-\family default
-, and the user needs to free it when done with it, using
-\family typewriter
-HX_zvecfree
-\family default
- or equivalent.
- An empty string (zero-length string) for
-\family typewriter
-s
-\family default
- yields a single field.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HX_split_inplace
-\family default
- Split the string
-\family typewriter
-s
-\family default
- in-place on any characters from the
-\begin_inset Quotes eld
-\end_inset
-
-
-\family typewriter
-delimiters
-\family default
-
-\begin_inset Quotes erd
-\end_inset
-
- string.
- The array that will be holding the pointers to the substrings will be allocated
- and needs to be freed by the user, using
-\family typewriter
-free
-\family default
-(3).
- The
-\family typewriter
-fields
-\family default
- and
-\family typewriter
-max
-\family default
- arguments work as with
-\family typewriter
-HX_split
-\family default
-.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HX_split_fixed
-\family default
- Split the string
-\family typewriter
-s
-\family default
- in-place on any characters from the
-\begin_inset Quotes eld
-\end_inset
-
-
-\family typewriter
-delimiters
-\family default
-
-\begin_inset Quotes erd
-\end_inset
-
- string.
- The array for the substring pointers must be provided by the user through
- the
-\family typewriter
-arr
-\family default
- argument.
-
-\family typewriter
-max
-\family default
- must be the number of elements in the array or less.
- The array will not be
-\family typewriter
-NULL
-\family default
--terminated
-\begin_inset Foot
-status open
-
-\begin_layout Plain Layout
-An implementation may however decide to put NULL in the unassigned fields,
- but this is implementation and situation-specific.
- Do not rely on it.
-\end_layout
-
-\end_inset
-
-.
- The number of fields produced is returned.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HX_strsep
-\family default
- Extract tokens from a string.
-\begin_inset Newline newline
-\end_inset
-
-This implementation of
-\family typewriter
-strsep
-\family default
- has been added since the function is non-standard (according to the manpage,
- conforms to BSD4.4 only) and may not be available on every operating system.
-\begin_inset Newline newline
-\end_inset
-
-This function extracts tokens, separated by one of the characters in
-\family typewriter
-delimiters
-\family default
-.
- The string is modified in-place and thus must be writable.
- The delimiters in the string are then overwritten with
-\family typewriter
-'
-\backslash
-0'
-\family default
-,
-\family typewriter
-*sp
-\family default
- is advanced to the character after the delimiter, and the original pointer
- is returned.
- After the final token,
-\family typewriter
-strsep
-\family default
- will return
-\family typewriter
-NULL
-\family default
-.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HX_strsep2
-\family default
- Like
-\family typewriter
-HX_strsep
-\family default
-, but
-\family typewriter
-dstr
-\family default
- is not an array of delimiting characters, but an entire substring that
- acts as a delimiter.
-\end_layout
-
-\begin_layout Subsection
-Size-bounded string ops
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-#include
-\series default
- <libHX/string.h>
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-libHX/string.h
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-char *
-\series default
-HX_strlcat(
-\series bold
-char *
-\series default
-dest,
-\series bold
-const char *
-\series default
-src,
-\series bold
-size_t
-\series default
- length);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\size normal
-\color none
-HX_strlcat
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-char *
-\series default
-HX_strlcpy(
-\series bold
-char *
-\series default
-dest,
-\series bold
-const char *
-\series default
-src,
-\series bold
-size_t
-\series default
- length);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\size normal
-\color none
-HX_strlcpy
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-char *
-\series default
-HX_strlncat(
-\series bold
-char *
-\series default
-dest,
-\series bold
-const char *
-\series default
-src,
-\series bold
-size_t
-\series default
- dlen,
-\series bold
-size_t
-\series default
- slen);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\size normal
-\color none
-HX_strlncat
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-size_t
-\series default
- HX_strnlen(
-\series bold
-const char *
-\series default
-src,
-\series bold
-size_t
-\series default
- max);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-HX_strnlen
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-
-\family typewriter
-HX_strlcat
-\family default
- and
-\family typewriter
-HX_strlcpy
-\family default
- provide implementations of the BSD-originating
-\family typewriter
-strlcat
-\family default
-(3)
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-strlcat
-\end_layout
-
-\end_inset
-
- and
-\family typewriter
-strlcpy
-\family default
-(3)
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-strlcpy
-\end_layout
-
-\end_inset
-
-.
-
-\family typewriter
-strlcat
-\family default
- and
-\family typewriter
-strlcpy
-\family default
- are less error-prone variants for
-\family typewriter
-strncat
-\family default
- and
-\family typewriter
-strncpy
-\family default
- as they always take the length of the entire buffer specified by
-\family typewriter
-dest
-\family default
-, instead of just the length that is to be written.
- The functions guarantee that the buffer is
-\family typewriter
-'
-\backslash
-0'
-\family default
--terminated.
-\end_layout
-
-\begin_layout Standard
-
-\family typewriter
-HX_strnlen
-\family default
- will return the length of the input string or the upper bound given by
-
-\family typewriter
-max
-\family default
-, whichever is less.
- It will not attempt to access more than this many bytes in the input buffer.
-\end_layout
-
-\begin_layout Subsection
-Allocation-related
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-#include
-\series default
- <libHX/string.h>
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-libHX/string.h
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-void *
-\series default
-HX_memdup(
-\series bold
-const void *
-\series default
-ptr,
-\series bold
-size_t
-\series default
- length);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\size normal
-\color none
-HX_memdup
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-char *
-\series default
-HX_strdup(
-\series bold
-const char *
-\series default
-str);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\size normal
-\color none
-HX_strdup
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-char *
-\series default
-HX_strndup(
-\series bold
-const char *
-\series default
-str,
-\series bold
-size_t
-\series default
- max);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-HX_strndup
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-
-\begin_inset Note Greyedout
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\series bold
-char *
-\series default
-HX_strclone(
-\series bold
-char **
-\series default
-pa,
-\series bold
-const char *
-\series default
-pb);
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\size normal
-\color none
-HX_strclone
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\end_inset
-
-
-\series default
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-
-\begin_inset Newline newline
-\end_inset
-
-#ifdef
-\series default
- __cplusplus
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-template<typename type> type
-\series default
- HX_memdup(
-\series bold
-const void *
-\series default
-ptr,
-\series bold
-size_t
-\series default
- length);
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-#endif
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HX_memdup
-\family default
- Duplicates
-\family typewriter
-length
-\family default
- bytes from the memory area pointed to by
-\family typewriter
-ptr
-\family default
- and returns a pointer to the new memory block.
-
-\family typewriter
-ptr
-\family default
- may not be
-\family typewriter
-NULL
-\family default
-.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HX_strdup
-\family default
- Duplicates the string.
- The function is equivalent to
-\family typewriter
-strdup
-\family default
-, but the latter may not be available on all platforms.
-
-\family typewriter
-str
-\family default
- may be
-\family typewriter
-NULL
-\family default
-, in which case
-\family typewriter
-NULL
-\family default
- is also returned.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HX_strndup
-\family default
- Duplicates the input string, but copies at most
-\family typewriter
-max
-\family default
- characters.
- (The resulting string will be NUL-terminated of course.)
-\family typewriter
-str
-\family default
- may not be
-\family typewriter
-NULL
-\family default
-.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HX_strclone
-\family default
- Copies the string pointed to by
-\family typewriter
-pb
-\family default
- into
-\family typewriter
-*pa
-\family default
-.
- If
-\family typewriter
-*pa
-\family default
- was not
-\family typewriter
-NULL
-\family default
- by the time
-\family typewriter
-HX_strclone
-\family default
- was called, the string is freed before a new one is allocated.
- The function returns
-\family typewriter
-NULL
-\family default
- and sets
-\family typewriter
-errno
-\family default
- to
-\family typewriter
-EINVAL
-\family default
- if
-\family typewriter
-pb
-\family default
- is
-\family typewriter
-NULL
-\family default
- (this way it can be freed), or, if
-\family typewriter
-malloc
-\family default
- fails, returns
-\family typewriter
-NULL
-\family default
- and leaves
-\family typewriter
-errno
-\family default
- at what
-\family typewriter
-malloc
-\family default
- set it to.
-\begin_inset Newline newline
-\end_inset
-
-The use of this function is deprecated, albeit no replacement is proposed.
-\end_layout
-
-\begin_layout Subsection
-Examples
-\end_layout
-
-\begin_layout Subsubsection
-Using HX_split_fixed
-\begin_inset CommandInset label
-LatexCommand label
-name "subsec:string-ex-HX_split_fixed"
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-
-\family typewriter
-HX_split_fixed
-\family default
- is often used just with scoped automatic-storage variables and where the
- field count of interest is fixed, as the example for parsing
-\family typewriter
-/etc/passwd
-\family default
- shows:
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-#include
-\series default
- <stdio.h>
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-#include
-\series default
- <libHX/string.h>
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-char *
-\series default
-field[8];
-\begin_inset Newline newline
-\end_inset
-
-hxmc_t
-\series bold
-*
-\series default
-line = NULL;
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-while
-\series default
- (HX_getl(&line, fp) != NULL) {
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-if
-\series default
- (HX_split_fixed(line, ":", ARRAY_SIZE(field), field) < 7) {
-\begin_inset Newline newline
-\end_inset
-
- fprintf(stderr, "That does not look like a valid line.
-\backslash
-n");
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-continue
-\series default
-;
-\begin_inset Newline newline
-\end_inset
-
- }
-\begin_inset Newline newline
-\end_inset
-
- printf("Username: %s
-\backslash
-n", field[0]);
-\begin_inset Newline newline
-\end_inset
-
-}
-\end_layout
-
-\begin_layout Subsubsection
-Using HX_split_inplace
-\end_layout
-
-\begin_layout Standard
-Where the number of fields is not previously known and/or estimatable, but
- the string can be modified in place, one uses
-\family typewriter
-HX_split_inplace
-\family default
- as follows:
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-#include
-\series default
- <errno.h>
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-#include
-\series default
- <stdio.h>
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-#include
-\series default
- <libHX/string.h>
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-while
-\series default
- (HX_getl(&line, fp) != NULL) {
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-char **
-\series default
-field = HX_split_inplace(line, ":", NULL, 0);
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-if
-\series default
- (field == NULL) {
-\begin_inset Newline newline
-\end_inset
-
- fprintf(stderr, "Badness! %s
-\backslash
-n", strerror(errno));
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-break
-\series default
-;
-\begin_inset Newline newline
-\end_inset
-
- }
-\begin_inset Newline newline
-\end_inset
-
- printf("Username: %s
-\backslash
-n", field[0]);
-\begin_inset Newline newline
-\end_inset
-
- free(field);
-\begin_inset Newline newline
-\end_inset
-
-}
-\end_layout
-
-\begin_layout Subsubsection
-Using HX_split
-\end_layout
-
-\begin_layout Standard
-Where the string is not modifiable in-place, one has to resort to using
- the full-fledged
-\family typewriter
-HX_split
-\family default
- that allocates space for each substring.
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-#include
-\series default
- <errno.h>
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-#include
-\series default
- <stdio.h>
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-#include
-\series default
- <libHX/string.h>
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-while
-\series default
- (HX_getl(&line, fp) != NULL) {
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-char **
-\series default
-field = HX_split(line, ":", NULL, 0);
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-if
-\series default
- (field == NULL) {
-\begin_inset Newline newline
-\end_inset
-
- fprintf(stderr, "Badness.
- %s
-\backslash
-n", strerror(errno));
-\begin_inset Newline newline
-\end_inset
-
- break;
-\begin_inset Newline newline
-\end_inset
-
- }
-\begin_inset Newline newline
-\end_inset
-
- printf("Username: %s
-\backslash
-n", field[0]);
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-/*
-\family roman
-\series default
-\shape italic
-Suppose
-\begin_inset Quotes eld
-\end_inset
-
-callme
-\begin_inset Quotes erd
-\end_inset
-
- needs the original string
-\family default
-\series bold
-\shape default
- */
-\series default
-
-\begin_inset Newline newline
-\end_inset
-
- callme(line);
-\begin_inset Newline newline
-\end_inset
-
- HX_zvecfree(field);
-\begin_inset Newline newline
-\end_inset
-
-}
-\end_layout
-
-\begin_layout Subsubsection
-Using HX_strsep
-\end_layout
-
-\begin_layout Standard
-
-\family typewriter
-HX_strsep
-\family default
- provides for thread- and reentrant-safe tokenizing a string where strtok
- from the C standard would otherwise fail.
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-#include
-\series default
- <stdio.h>
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-#include
-\series default
- <libHX/string.h>
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-char
-\series default
- line
-\series bold
-[]
-\series default
- = "root:x:0:0:root:/root:/bin/bash";
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-char *
-\series default
-wp,
-\series bold
-*
-\series default
-p;
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-wp = line;
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-while
-\series default
- ((p = HX_strsep(&wp, ":")) != NULL)
-\begin_inset Newline newline
-\end_inset
-
- printf("%s
-\backslash
-n", p)
-\end_layout
-
-\begin_layout Standard
-\begin_inset Newpage clearpage
-\end_inset
-
-
-\end_layout
-
-\begin_layout Section
-Memory containers
-\begin_inset CommandInset label
-LatexCommand label
-name "sec:mc"
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-The HXmc series of functions provide scripting-like semantics for strings,
- especially automatically resizing the buffer on demand.
- They can also be used to store a binary block of data together with its
- length.
- (Hence the name: mc = memory container.)
-\end_layout
-
-\begin_layout Standard
-The benefit of using the HXmc functions is that one does not have to meticulousl
-y watch buffer and string sizes anymore.
-\end_layout
-
-\begin_layout Standard
-\begin_inset Float figure
-placement H
-wide false
-sideways false
-status open
-
-\begin_layout Paragraph
-/* Step
-\begin_inset space ~
-\end_inset
-
-1 */
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-char
-\series default
- buf
-\series bold
-[
-\family roman
-\series default
-\shape italic
-whatever was believed to be long enough
-\family default
-\series bold
-\shape default
-]
-\series default
- = "helloworld";
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-if
-\series default
- (strlen(buf) + strlen(".txt") <
-\series bold
-sizeof
-\series default
-(buf))
-\begin_inset Newline newline
-\end_inset
-
- strcat(s, ".txt");
-\end_layout
-
-\begin_layout Paragraph
-/* Step
-\begin_inset space ~
-\end_inset
-
-2 */
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-char
-\series default
- buf
-\series bold
-[
-\family roman
-\series default
-\shape italic
-long_enough
-\family default
-\series bold
-\shape default
-]
-\series default
- = "helloworld";
-\end_layout
-
-\begin_layout LyX-Code
-strlcat(s, ".txt",
-\series bold
-sizeof
-\series default
-(buf));
-\end_layout
-
-\begin_layout Paragraph
-/* Step
-\begin_inset space ~
-\end_inset
-
-3 */
-\end_layout
-
-\begin_layout LyX-Code
-hxmc_t
-\series bold
-*
-\series default
-buf = HXmc_strinit("helloworld");
-\begin_inset Newline newline
-\end_inset
-
-HXmc_strcat(&s, ".txt");
-\end_layout
-
-\begin_layout Plain Layout
-\begin_inset Caption Standard
-
-\begin_layout Plain Layout
-Improvement of string safety over time
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-This makes it quite similar to the string operations (and append seems to
- be the most commonly used one to me) supported in scripting languages that
- also do without a size argument.
- The essential part of such memory containers is that their internal (hidden)
- metadata structure contains the length of the memory block in the container.
- For binary data this may be the norm, but for C-style strings, the stored
- and auto-updated length field serves as an accelerator cache.
- For more details, see
-\family typewriter
-HXmc_length
-\family default
-.
-\end_layout
-
-\begin_layout Standard
-Of course, the automatic management of memory comes with a bit of overhead
- as the string expands beyond its preallocated region.
- Such may be mitigated by doing explicit (re)sizing.
-\end_layout
-
-\begin_layout Subsection
-Structural overview
-\end_layout
-
-\begin_layout Standard
-HXmc functions do not actually return a pointer to the memory container
- (e.
-\begin_inset space \thinspace{}
-\end_inset
-
-g.
-\begin_inset space \space{}
-\end_inset
-
-
-\family typewriter
-struct
-\family default
-) itself, but a pointer to the data block.
- Conversely, input parameters to HXmc functions will be the data block pointer.
- It is of type
-\family typewriter
-hxmc_t
-\begin_inset space ~
-\end_inset
-
-*
-\family default
-, which is typedef'ed to
-\family typewriter
-char
-\begin_inset space ~
-\end_inset
-
-*
-\family default
- and inherits all properties and privileges of
-\family typewriter
-char
-\begin_inset space ~
-\end_inset
-
-*
-\family default
-.
- Pointer arithmetic is thus supported.
- It also means you can just pass it to functions that take a
-\family typewriter
-char
-\begin_inset space ~
-\end_inset
-
-*
-\family default
- without having to do a member access like
-\family typewriter
-s.c_str
-\family default
-.
- The drawback is that many functions operating on the memory container need
- a
-\family typewriter
-hxmc_t
-\begin_inset space ~
-\end_inset
-
-**
-\family default
- (a level-two indirection), because not only does the memory block move,
- but also the memory container itself.
- This is due to the implementation of the container metadata which immediately
- and always precedes the writable memory block.
-\end_layout
-
-\begin_layout Standard
-HXmc ensures that the data block is terminated by a NUL (
-\family typewriter
-'
-\backslash
-0'
-\family default
-) byte (unless you trash it), so you do not have to, and of course, to be
- on the safe side.
- But, the automatic NUL byte is not part of the region allocated by the
- user.
- That is, when one uses the classic approach with
-\family typewriter
-malloc(4096)
-\family default
-, the user will have control of 4096 bytes and has to stuff the NUL byte
- in there somehow on his own; for strings this means the maximum string
- length is 4095.
- Requesting space for a 4096-byte sized HXmc container gives you the possibility
- to use all 4096 bytes for the string, because HXmc provides a NUL byte.
-\end_layout
-
-\begin_layout Standard
-By the way,
-\family typewriter
-hxmc_t
-\family default
- is the
-\shape italic
-only
-\shape default
- typedef in this entire library, to distinguish it from regular
-\family typewriter
-char
-\begin_inset space ~
-\end_inset
-
-*
-\family default
- that does not have a backing memory cointainer.
-\end_layout
-
-\begin_layout Subsection
-Constructors, destructors
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-#include
-\series default
- <libHX/string.h>
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-libHX/string.h
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-hxmc_t
-\series bold
-*
-\series default
-HXmc_strinit(
-\series bold
-const char *
-\series default
-s);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXmc_strinit
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-hxmc_t
-\series bold
-*
-\series default
-HXmc_meminit(
-\series bold
-const void *
-\series default
-ptr,
-\series bold
-size_t
-\series default
- size);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXmc_meminit
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXmc_strinit
-\family default
- Creates a new hxmc_t object from the supplied string and returns it.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXmc_meminit
-\family default
- Creates a new hxmc_t object from the supplied memory buffer of the given
- size and returns it.
-
-\family typewriter
-HXmc_meminit(NULL, len)
-\family default
- may be used to obtain an empty container with a preallocated region of
-
-\family typewriter
-len
-\family default
- bytes (zero is accepted for
-\family typewriter
-len
-\family default
-).
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-void
-\series default
- HXmc_free(hxmc_t
-\series bold
-*
-\series default
-s);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXmc_free
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-void
-\series default
- HXmc_zvecfree(hxmc_t
-\series bold
-**
-\series default
-s);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXmc_zvecfree
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXmc_free
-\family default
- Frees the hxmc object.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXmc_zvecfree
-\family default
- Frees all hxmc objects in the NULL-terminated array, and finally frees
- the array itself, similar to
-\family typewriter
-HX_zvecfree
-\family default
-.
-\end_layout
-
-\begin_layout Subsection
-Data manipulation
-\end_layout
-
-\begin_layout Subsubsection
-Binary-based
-\end_layout
-
-\begin_layout LyX-Code
-hxmc_t
-\series bold
-*
-\series default
-HXmc_trunc(hxmc_t
-\series bold
-**
-\series default
-mc,
-\series bold
-size_t
-\series default
- len);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\size normal
-\color none
-HXmc_trunc
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-hxmc_t
-\series bold
-*
-\series default
-HXmc_setlen(hxmc_t
-\series bold
-**
-\series default
-mc,
-\series bold
-size_t
-\series default
- len);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\size normal
-\color none
-HXmc_setlen
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-hxmc_t
-\series bold
-*
-\series default
-HXmc_memcpy(hxmc_t
-\series bold
-**
-\series default
-mc,
-\series bold
-const void *
-\series default
-ptr,
-\series bold
-size_t
-\series default
- len);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\size normal
-\color none
-HXmc_memcpy
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-hxmc_t
-\series bold
-*
-\series default
-HXmc_memcat(hxmc_t
-\series bold
-**
-\series default
-mc,
-\series bold
-const void *
-\series default
-ptr,
-\series bold
-size_t
-\series default
- len);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\size normal
-\color none
-HXmc_memcat
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-hxmc_t
-\series bold
-*
-\series default
-HXmc_mempcat(hxmc_t
-\series bold
-**
-\series default
-mc,
-\series bold
-const void *
-\series default
-ptr,
-\series bold
-size_t
-\series default
- len);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\size normal
-\color none
-HXmc_mempcat
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-hxmc_t
-\series bold
-*
-\series default
-HXmc_memins(hxmc_t
-\series bold
-**
-\series default
-mc,
-\series bold
-size_t
-\series default
- pos,
-\series bold
-const void *
-\series default
-ptr,
-\series bold
-size_t
-\series default
- len);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HX_memins
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-hxmc_t
-\series bold
-*
-\series default
-HXmc_memdel(hxmc_t
-\series bold
-**
-\series default
-mc,
-\series bold
-size_t
-\series default
- pos,
-\series bold
-size_t
-\series default
- len);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HX_memdel
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-When
-\family typewriter
-ptr
-\family default
- is
-\family typewriter
-NULL
-\family default
-, each call behaves as if
-\family typewriter
-len
-\family default
- would be zero.
- Specifically, no undefined behavior will result of the use of
-\family typewriter
-NULL
-\family default
-.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXmc_trunc
-\family default
- Truncates the container's data to
-\family typewriter
-len
-\family default
- size.
- If
-\family typewriter
-len
-\family default
- is greater than the current data size of the container, the length is in
- fact
-\shape italic
-not
-\shape default
- updated, but a reallocation may be triggered, which can be used to do explicit
- allocation.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXmc_setlen
-\family default
- Set the data length, doing a reallocation of the memory container if needed.
- The newly available bytes are uninitialized.
- Make use of this function when letting 3rd party functions write to the
- buffer, but it should not be used with
-\family typewriter
-HXmc_str*
-\family default
-(),
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXmc_memcpy
-\family default
- Truncates the container's data and copies
-\family typewriter
-len
-\family default
- bytes from the memory area pointed to by
-\family typewriter
-ptr
-\family default
- to the container.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXmc_memcat
-\family default
- Concatenates (appends)
-\family typewriter
-len
-\family default
- bytes from the memory area pointed to by
-\family typewriter
-ptr
-\family default
- to the container's data.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXmc_mempcat
-\family default
- Prepends
-\family typewriter
-len
-\family default
- bytes from the memory area pointed to by
-\family typewriter
-ptr
-\family default
- to the container's data.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXmc_memins
-\family default
- Prepends
-\family typewriter
-len
-\family default
- bytes from the memory area pointed to by
-\family typewriter
-ptr
-\family default
- to the
-\family typewriter
-pos
-\family default
-'th byte of the container's data.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXmc_memdel
-\family default
- Deletes
-\family typewriter
-len
-\family default
- bytes from the container beginning at position
-\family typewriter
-pos
-\family default
-.
-\end_layout
-
-\begin_layout Standard
-In case of a memory allocation failure, the
-\family typewriter
-HXmc_*
-\family default
- functions will return
-\family typewriter
-NULL
-\family default
-.
-\end_layout
-
-\begin_layout Subsubsection
-String-based
-\end_layout
-
-\begin_layout Standard
-The string-based functions correspond to their binary-based equivalents
- with a
-\family typewriter
-len
-\family default
- argument of
-\family typewriter
-strlen(s)
-\family default
-.
-\end_layout
-
-\begin_layout LyX-Code
-hxmc_t
-\series bold
-*
-\series default
-HXmc_strcpy(hxmc_t
-\series bold
-**
-\series default
-mc,
-\series bold
-const char *
-\series default
-s);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\size normal
-\color none
-HXmc_strcpy
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-hxmc_t
-\series bold
-*
-\series default
-HXmc_strcat(hxmc_t
-\series bold
-**
-\series default
-mc,
-\series bold
-const char *
-\series default
-s);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\size normal
-\color none
-HXmc_strcat
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-hxmc_t
-\series bold
-*
-\series default
-HXmc_strpcat(hxmc_t
-\series bold
-**
-\series default
-mc,
-\series bold
-const char *
-\series default
-s);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXmc_strpcat
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-hxmc_t
-\series bold
-*
-\series default
-HXmc_strins(hxmc_t
-\series bold
-**
-\series default
-mc,
-\series bold
-size_t
-\series default
- pos,
-\series bold
-const char *
-\series default
-s);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\size normal
-\color none
-HXmc_strins
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXmc_strcpy
-\family default
- Copies the string pointed to by
-\family typewriter
-s
-\family default
- into the memory container given by
-\family typewriter
-mc
-\family default
-.
- If
-\family typewriter
-mc
-\family default
- is
-\family typewriter
-NULL
-\family default
-, the memory container will be deallocated, that is,
-\family typewriter
-*mc
-\family default
- becomes
-\family typewriter
-NULL
-\family default
-.
-\end_layout
-
-\begin_layout Subsubsection
-From auxiliary sources
-\end_layout
-
-\begin_layout LyX-Code
-hxmc_t
-\series bold
-*
-\series default
-HX_getl(hxmc_t
-\series bold
-**
-\series default
-mc, FILE
-\series bold
-*
-\series default
-fp);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HX_getl
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HX_getl
-\family default
- Read the next line from
-\family typewriter
-fp
-\family default
- and store the result in the container.
- Returns
-\family typewriter
-NULL
-\family default
- on error, or when end of file occurs while no characters have been read.
-\end_layout
-
-\begin_layout Subsection
-Container properties
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-size_t
-\series default
- HXmc_length(
-\series bold
-const
-\series default
- hxmc_t
-\series bold
-**
-\series default
-mc);
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXmc_length
-\family default
- Returns the length of the memory container.
- This is not always equal to the actual string length.
- For example, if
-\family typewriter
-HX_chomp
-\family default
- was used on an MC-backed string,
-\family typewriter
-strlen
-\family default
- will return less than
-\family typewriter
-HXmc_length
-\family default
- if newline control characters (
-\family typewriter
-'
-\backslash
-r'
-\family default
- and
-\family typewriter
-'
-\backslash
-n'
-\family default
-) were removed.
-\end_layout
-
-\begin_layout Standard
-\begin_inset Newpage clearpage
-\end_inset
-
-
-\end_layout
-
-\begin_layout Section
-Format templates
-\begin_inset CommandInset label
-LatexCommand label
-name "sec:format"
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-HXfmt is a small template system for by-name variable expansion.
- It can be used to substitute placeholders in format strings supplied by
- the user by appropriate expanded values defined by the program.
- Such can be used to allow for flexible configuration files that define
- key-value mappings such as
-\end_layout
-
-\begin_layout LyX-Code
-detect_peer = ping6 -c1 %(ADDR)
-\begin_inset Newline newline
-\end_inset
-
-#detect_peer = nmap -sP %(ADDR) | grep -Eq "appears to be up"
-\end_layout
-
-\begin_layout Standard
-Consider for example a monitoring daemon that allows the administrator to
- specify a program of his choice with which to detect whether a peer is
- alive or not.
- The user can choose any program that is desired, but evidently needs to
- pass the address to be tested to the program.
- This is where the daemon will do a substitution of the string
-\begin_inset Quotes eld
-\end_inset
-
-
-\family typewriter
-ping -c1 %(ADDR)
-\family default
-
-\begin_inset Quotes erd
-\end_inset
-
- it read from the config file, and put the actual address in it before finally
- executing the command.
-\end_layout
-
-\begin_layout Standard
-\begin_inset Float figure
-placement H
-wide false
-sideways false
-status open
-
-\begin_layout LyX-Code
-printf("%s has %u files
-\backslash
-n", user, num);
-\begin_inset Newline newline
-\end_inset
-
-printf("%2$u files belong to %1$s
-\backslash
-n", num, user);
-\end_layout
-
-\begin_layout Plain Layout
-\begin_inset Quotes eld
-\end_inset
-
-
-\family typewriter
-%s
-\family default
-
-\begin_inset Quotes erd
-\end_inset
-
- (or
-\begin_inset Quotes eld
-\end_inset
-
-
-\family typewriter
-%1$s
-\family default
-
-\begin_inset Quotes erd
-\end_inset
-
- here) specifies how large
-\begin_inset Quotes eld
-\end_inset
-
-user
-\begin_inset Quotes erd
-\end_inset
-
- is
-\begin_inset space ~
-\end_inset
-
-—
-\family typewriter
-sizeof(const char *)
-\family default
- in this case.
- If that is missing, there is no way to know the offset of
-\begin_inset Quotes eld
-\end_inset
-
-
-\family typewriter
-num
-\family default
-
-\begin_inset Quotes erd
-\end_inset
-
- relative to
-\begin_inset Quotes eld
-\end_inset
-
-
-\family typewriter
-user
-\family default
-
-\begin_inset Quotes erd
-\end_inset
-
-, making varargs retrieval impossible.
-\end_layout
-
-\begin_layout Plain Layout
-\begin_inset Caption Standard
-
-\begin_layout Plain Layout
-
-\family typewriter
-printf
-\family default
- positional parameters
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-
-\family typewriter
-printf
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-printf
-\end_layout
-
-\end_inset
-
-, at least from GNU libc, has something vaguely similar: positional parameters
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-positional parameters
-\end_layout
-
-\end_inset
-
-.
- They have inherent drawbacks, though.
- One is of course the question of portability, but there is a bigger issue.
- All parameters must be specified, otherwise there is no way to determine
- the location of all following objects following the missing one on the
- stack in a varargs-function like
-\family typewriter
-printf
-\family default
-., which makes it unsuitable to be used with templates where omitting some
- placeholders is allowed.
-\end_layout
-
-\begin_layout Subsection
-Initialization, use and deallocation
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-#include
-\series default
- <libHX/option.h>
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-libHX/option.h
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-struct
-\series default
- HXformat_map
-\series bold
-*
-\series default
-HXformat_init(
-\series bold
-void
-\series default
-);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\size normal
-\color none
-HXformat_init
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-void
-\series default
- HXformat_free(
-\series bold
-struct
-\series default
- HXformat_map
-\series bold
-*
-\series default
-table);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\size normal
-\color none
-HXformat_free
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-int
-\series default
- HXformat_add(
-\series bold
-struct
-\series default
- HXformat_map
-\series bold
-*
-\series default
-table,
-\series bold
-const char *
-\series default
-key,
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-const void *
-\series default
-ptr,
-\series bold
-unsigned int
-\series default
- ptr_type);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\size normal
-\color none
-HXformat_add
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-
-\family typewriter
-HXformat_init
-\family default
- will allocate and set up a simple string-to-string map that is used for
- the underlying storage, and returns it.
-\end_layout
-
-\begin_layout Standard
-To release the substitution table and memory associated with it, call
-\family typewriter
-HXformat_free
-\family default
-.
-\end_layout
-
-\begin_layout Standard
-
-\family typewriter
-HXformat_add
-\family default
- is used to add substitution entries.
- One can also specify other types such as numeral types.
-
-\family typewriter
-ptr_type
-\family default
- describes the type behind
-\family typewriter
-ptr
-\family default
- and are constants from
-\family typewriter
-option.h
-\family default
- (cf.
-\begin_inset space \space{}
-\end_inset
-
-section
-\begin_inset space ~
-\end_inset
-
-
-\begin_inset CommandInset ref
-LatexCommand ref
-reference "subsec:option-types"
-
-\end_inset
-
-)
-\begin_inset space ~
-\end_inset
-
-— not all constants can be used, though, and their meaning also differs
- from what
-\family typewriter
-HX_getopt
-\family default
- or
-\family typewriter
-HX_shconfig
-\family default
- use them for
-\begin_inset space ~
-\end_inset
-
-— the two could be seen as
-\begin_inset Quotes eld
-\end_inset
-
-read
-\begin_inset Quotes erd
-\end_inset
-
- operations, while HXformat is a write operation.
-\end_layout
-
-\begin_layout Subsubsection
-Immediate types
-\end_layout
-
-\begin_layout Standard
-\begin_inset Quotes eld
-\end_inset
-
-Immediate types
-\begin_inset Quotes erd
-\end_inset
-
- are resolved when
-\family typewriter
-HXformat_add
-\family default
- is called, that is, they are copied and inserted into the tree, and are
- subsequently independent from any changes to variables in the program.
- Because the HXopt-originating type name, that is,
-\family typewriter
-HXTYPE_*
-\family default
-, is also used for deferred types, the constant
-\family typewriter
-HXFORMAT_IMMED
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXFORMAT_IMMED
-\end_layout
-
-\end_inset
-
-
-\family default
- needs to be specified on some types to denote an immediate value.
-\end_layout
-
-\begin_layout Itemize
-
-\family typewriter
-HXTYPE_STRING
-\family default
-
-\begin_inset space ~
-\end_inset
-
-—
-\family typewriter
-ptr
-\family default
- is a
-\family typewriter
-const char *
-\family default
-.
-\end_layout
-
-\begin_layout Itemize
-
-\family typewriter
-HXTYPE_
-\family default
-{
-\family typewriter
-U
-\family default
-,}{
-\family typewriter
-CHAR
-\family default
-,
-\family typewriter
-SHORT
-\family default
-,
-\family typewriter
-INT
-\family default
-,
-\family typewriter
-LONG
-\family default
-,
-\family typewriter
-LLONG
-\family default
-}
-\family typewriter
- | HXFORMAT_IMMED
-\family default
-
-\begin_inset space ~
-\end_inset
-
-— mapping to the standard types
-\end_layout
-
-\begin_layout Subsubsection
-Deferred types
-\end_layout
-
-\begin_layout Standard
-\begin_inset Quotes eld
-\end_inset
-
-Deferred types
-\begin_inset Quotes erd
-\end_inset
-
- are resolved on every invocation of a formatter function (
-\family typewriter
-HXformat_*printf
-\family default
-).
- The expansions may be changed by modifying the underlying variable pointed
- to, but the pointer must remain valid and its pointee not go out of scope.
- Figure
-\begin_inset space ~
-\end_inset
-
-
-\begin_inset CommandInset ref
-LatexCommand ref
-reference "fig:hxformat-immediate-deferred"
-
-\end_inset
-
- shows the difference in a code sample.
-\end_layout
-
-\begin_layout Itemize
-
-\family typewriter
-HXTYPE_STRP
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXTYPE_STRP
-\end_layout
-
-\end_inset
-
-
-\begin_inset space ~
-\end_inset
-
-—
-\family typewriter
-ptr
-\family default
- is a
-\family typewriter
-const char *const *
-\family default
-; the pointer resolution is deferred until the formatter is called with
- one of the
-\family typewriter
-HXformat_*printf
-\family default
- functions.
- Deferred in the sense it is always resolved anew.
-
-\end_layout
-
-\begin_layout Itemize
-
-\family typewriter
-HXTYPE_BOOL
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXTYPE_BOOL
-\end_layout
-
-\end_inset
-
-
-\begin_inset space ~
-\end_inset
-
-—
-\family typewriter
-ptr
-\family default
- is a
-\family typewriter
-const int
-\begin_inset space ~
-\end_inset
-
-*
-\family default
-.
-\end_layout
-
-\begin_layout Itemize
-
-\family typewriter
-HXTYPE_
-\family default
-{
-\family typewriter
-U
-\family default
-,}{
-\family typewriter
-CHAR
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXTYPE_CHAR
-\end_layout
-
-\end_inset
-
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXTYPE_UCHAR
-\end_layout
-
-\end_inset
-
-,
-\family typewriter
-SHORT
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXTYPE_SHORT
-\end_layout
-
-\end_inset
-
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXTYPE_USHORT
-\end_layout
-
-\end_inset
-
-,
-\family typewriter
-INT
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXTYPE_INT
-\end_layout
-
-\end_inset
-
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXTYPE_UINT
-\end_layout
-
-\end_inset
-
-,
-\family typewriter
-LONG
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXTYPE_LONG
-\end_layout
-
-\end_inset
-
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXTYPE_ULONG
-\end_layout
-
-\end_inset
-
-,
-\family typewriter
-LLONG
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXTYPE_LLONG
-\end_layout
-
-\end_inset
-
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXTYPE_ULLONG
-\end_layout
-
-\end_inset
-
-}
-\begin_inset space ~
-\end_inset
-
-— mapping to the standard types with one indirection (e.
-\begin_inset space \thinspace{}
-\end_inset
-
-g.
-\begin_inset space \space{}
-\end_inset
-
-
-\family typewriter
-int
-\begin_inset space ~
-\end_inset
-
-*
-\family default
-)
-\end_layout
-
-\begin_layout Itemize
-
-\family typewriter
-HXTYPE_
-\family default
-{
-\family typewriter
-FLOAT
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXTYPE_FLOAT
-\end_layout
-
-\end_inset
-
-,
-\family typewriter
-DOUBLE
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXTYPE_DOUBLE
-\end_layout
-
-\end_inset
-
-}
-\begin_inset space ~
-\end_inset
-
-— mapping to the two floating-point types with one indirection (e.
-\begin_inset space \thinspace{}
-\end_inset
-
-g.
-\begin_inset space \space{}
-\end_inset
-
-
-\family typewriter
-double
-\begin_inset space ~
-\end_inset
-
-*
-\family default
-)
-\end_layout
-
-\begin_layout Subsection
-Invoking the formatter
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-int
-\series default
- HXformat_aprintf(
-\series bold
-struct
-\series default
- HXformat_map
-\series bold
-*
-\series default
-table, hxmc_t
-\series bold
-**
-\series default
-dest,
-\series bold
-const char *
-\series default
-template);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXformat_aprintf
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-int
-\series default
- HXformat_sprintf(
-\series bold
-struct
-\series default
- HXformat_map
-\series bold
-*
-\series default
-table,
-\series bold
-char *
-\series default
-dest,
-\series bold
-size_t
-\series default
- size,
-\series bold
-const char *
-\series default
-template);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\size normal
-\color none
-HXformat_sprintf
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-int
-\series default
- HXformat_fprintf(
-\series bold
-struct
-\series default
- HXformat_map
-\series bold
-*
-\series default
-table, FILE
-\series bold
-*
-\series default
-filp,
-\series bold
-const char *
-\series default
-template);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\size normal
-\color none
-HXformat_fprintf
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXformat_aprintf
-\family default
- Substitute placeholders in
-\family typewriter
-template
-\family default
- using the given table.
- This will produce a string in a HX memory container (
-\family typewriter
-hxmc_t
-\family default
-), and the pointer is put into
-\family typewriter
-*dest
-\family default
-.
- The caller will be responsible for freeing it later when it is done using
- the result.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXformat_sprintf
-\family default
- Do substitution and store the expanded result in the buffer
-\family typewriter
-dest
-\family default
- which is of size
-\family typewriter
-size
-\family default
-.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXformat_fprintf
-\family default
- Do substituion and directly output the expansion to the given stdio stream.
-\end_layout
-
-\begin_layout Standard
-On success, the length of the expanded string is returned, excluding the
- trailing
-\family typewriter
-'
-\backslash
-0'
-\family default
-.
- While
-\family typewriter
-HXformat_sprintf
-\family default
- will not write more than
-\family typewriter
-size
-\family default
- bytes (including the
-\family typewriter
-'
-\backslash
-0'
-\family default
-), the length it would have taken is returned, similar to what
-\family typewriter
-sprintf
-\family default
- does.
- On error, negative errno is returned.
-\end_layout
-
-\begin_layout Standard
-The HXformat function family recognizes make-style like functions and recursive
- expansion, described below.
-\end_layout
-
-\begin_layout Subsection
-Functions
-\end_layout
-
-\begin_layout Standard
-To expand a variable, one uses a syntax like
-\begin_inset Quotes eld
-\end_inset
-
-
-\family typewriter
-%(NAME)
-\family default
-
-\begin_inset Quotes erd
-\end_inset
-
- in the format string.
- Recursive expansion like
-\begin_inset Quotes eld
-\end_inset
-
-
-\family typewriter
-%(%(USER))
-\family default
-
-\begin_inset Quotes erd
-\end_inset
-
- is supported; assuming
-\family typewriter
-%(USER)
-\family default
- would expand to
-\begin_inset Quotes eld
-\end_inset
-
-linux
-\begin_inset Quotes erd
-\end_inset
-
-, HXformat would try to resolve
-\begin_inset Quotes eld
-\end_inset
-
-
-\family typewriter
-%(linux)
-\family default
-
-\begin_inset Quotes erd
-\end_inset
-
- next.
- Besides these variable substitutions, HXformat also provides function calls
- whose syntax is
-\begin_inset Quotes eld
-\end_inset
-
-
-\family typewriter
-%(nameOfFunction parameters[...])
-\family default
-
-\begin_inset Quotes erd
-\end_inset
-
-.
- Parameters can be any text, including variables.
- Paramters are separated from another by a delimiter specific to each function.
- See this list for details:
-\end_layout
-
-\begin_layout Itemize
-
-\family typewriter
-%(env
-\family default
-
-\shape italic
-variable
-\family typewriter
-\shape default
-)
-\begin_inset Newline newline
-\end_inset
-
-
-\family default
-The
-\family typewriter
-env
-\family default
- function expands to the string that is stored in the environmental variable
- by the given name.
-\end_layout
-
-\begin_layout Itemize
-
-\family typewriter
-%(exec
-\family default
-\shape italic
-command
-\family typewriter
-\shape default
-
-\family default
-[
-\shape italic
-args
-\shape default
-...]
-\family typewriter
-)
-\family default
-
-\begin_inset Newline newline
-\end_inset
-
-The
-\family typewriter
-exec
-\family default
- function expands to the standard output of the command.
- The command is directly run without shell invocation, so no special character
- expansion (wildcards, etc.) takes place.
- stdin is set to
-\family typewriter
-/dev\SpecialChar breakableslash
-null
-\family default
-.
- The parameter delimiter is the space character.
- To be able to use this function
-\begin_inset space ~
-\end_inset
-
-— as it is relevant to security
-\begin_inset space ~
-\end_inset
-
-— the fmt table needs to have a key called
-\begin_inset Quotes eld
-\end_inset
-
-
-\family typewriter
-/libhx/exec
-\family default
-
-\begin_inset Quotes erd
-\end_inset
-
-.
- See example
-\begin_inset space ~
-\end_inset
-
-
-\begin_inset CommandInset ref
-LatexCommand ref
-reference "fig:hxformat-exec"
-
-\end_inset
-
- for details.
-\end_layout
-
-\begin_layout Itemize
-
-\family typewriter
-%(if
-\family default
-\shape italic
-condition
-\family typewriter
-\shape default
-,
-\family default
-[
-\shape italic
-then
-\shape default
-][
-\family typewriter
-,
-\family default
-[
-\shape italic
-else
-\shape default
-]]
-\family typewriter
-)
-\family default
-
-\begin_inset Newline newline
-\end_inset
-
-If the condition parameter expands to a string of non-zero length, the function
- expands to the
-\begin_inset Quotes eld
-\end_inset
-
-then
-\begin_inset Quotes erd
-\end_inset
-
- block, otherwise the
-\begin_inset Quotes eld
-\end_inset
-
-else
-\begin_inset Quotes erd
-\end_inset
-
- block.
- The delimiter used is a comma.
-\end_layout
-
-\begin_layout Itemize
-
-\family typewriter
-%(lower
-\family default
-\shape italic
-text
-\family typewriter
-\shape default
-)
-\family default
-,
-\family typewriter
-%(upper
-\family default
-\shape italic
-text
-\family typewriter
-\shape default
-)
-\family default
-
-\begin_inset Newline newline
-\end_inset
-
-Lowercases or uppercases the supplied argument.
- As these functions are meant to take only one argument, there is no delimiter
- defined that would need escaping if multiple arguments were supposed to
- be passed.
-
-\family typewriter
-%(lower a,b)
-\family default
- is equivalent to
-\family typewriter
-%(lower "a,b")
-\family default
-.
-\end_layout
-
-\begin_layout Itemize
-
-\family typewriter
-%(shell
-\family default
-\shape italic
-command
-\family typewriter
-\shape default
-
-\family default
-[
-\shape italic
-args
-\shape default
-...]
-\family typewriter
-)
-\family default
-
-\begin_inset Newline newline
-\end_inset
-
-Similar to
-\family typewriter
-%(exec)
-\family default
-, but invokes the shell inbetween (i.
-\begin_inset space \thinspace{}
-\end_inset
-
-e.
-\begin_inset space \space{}
-\end_inset
-
-`
-\family typewriter
-sh -c '
-\family default
-\shape italic
-command
-\shape default
-...
-\family typewriter
-'
-\family default
-`) such that special characters, redirection, and so on can be used.
-\end_layout
-
-\begin_layout Itemize
-
-\family typewriter
-%(substr
-\family default
-\shape italic
-text
-\family typewriter
-\shape default
-,
-\family default
-\shape italic
-offset
-\shape default
-[
-\family typewriter
-,
-\family default
-\shape italic
-length
-\shape default
-]
-\family typewriter
-)
-\family default
-
-\begin_inset Newline newline
-\end_inset
-
-Extracts a substring out of the given text, starting at
-\shape italic
-offset
-\shape default
- and running for the given length.
- If no length is given, will extract until the end of the string.
- If
-\shape italic
-offset
-\shape default
- is negative, it specifies the offset from the end of the string.
- If
-\shape italic
-length
-\shape default
- is negative, that many characters are left off the end.
-\end_layout
-
-\begin_layout Itemize
-
-\family typewriter
-%(snl
-\family default
-\shape italic
-text
-\family typewriter
-\shape default
-)
-\family default
-
-\begin_inset Newline newline
-\end_inset
-
-Strips trailing newlines from text and replaces any other newline by a space.
- What happens implicity in Makefiles'
-\family typewriter
-$(shell
-\family default
-...
-\family typewriter
-)
-\family default
- statements usually is explicitly separate in libHX.
-\end_layout
-
-\begin_layout Subsection
-Examples
-\end_layout
-
-\begin_layout Standard
-\begin_inset Float figure
-placement H
-wide false
-sideways false
-status open
-
-\begin_layout LyX-Code
-
-\series bold
-const char *
-\series default
-b = "Hello World";
-\begin_inset Newline newline
-\end_inset
-
-
-\family typewriter
-\series bold
-char
-\series default
- c
-\family default
-\series bold
-[]
-\family typewriter
-\series default
- = "Hello World";
-\family default
-
-\begin_inset Newline newline
-\end_inset
-
-
-\family typewriter
-\series bold
-struct
-\series default
- HXformat_map
-\series bold
-*
-\series default
-table = HXformat_init();
-\begin_inset Newline newline
-\end_inset
-
-HXformat_add(table, "%(GREETING1)", b, HXTYPE_STRING);
-\begin_inset Newline newline
-\end_inset
-
-HXformat_add(table, "%(GREETING2)", &c, HXTYPE_STRP);
-\begin_inset Newline newline
-\end_inset
-
-b = NULL;
-\begin_inset Newline newline
-\end_inset
-
-snprintf(c,
-\family default
-\series bold
-sizeof
-\family typewriter
-\series default
-(c), "Hello Home");
-\begin_inset Newline newline
-\end_inset
-
-HXformat_aprintf(...);
-\end_layout
-
-\begin_layout Plain Layout
-Upon calling
-\family typewriter
-HXformat_*printf
-\family default
-,
-\family typewriter
-%(GREETING1)
-\family default
- will expand to
-\begin_inset Quotes eld
-\end_inset
-
-Hello World
-\begin_inset Quotes erd
-\end_inset
-
- whereas
-\family typewriter
-%(GREETING2)
-\family default
- will expand to
-\begin_inset Quotes eld
-\end_inset
-
-Hello Home
-\begin_inset Quotes erd
-\end_inset
-
-.
-\end_layout
-
-\begin_layout Plain Layout
-\begin_inset Caption Standard
-
-\begin_layout Plain Layout
-\begin_inset CommandInset label
-LatexCommand label
-name "fig:hxformat-immediate-deferred"
-
-\end_inset
-
-Immediate and deferred resolution
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-\begin_inset Float figure
-wide false
-sideways false
-status open
-
-\begin_layout LyX-Code
-
-\series bold
-struct
-\series default
- HXformat_map
-\series bold
-*
-\series default
-table = HXformat_init();
-\begin_inset Newline newline
-\end_inset
-
-HXformat_add(table, "/libhx/exec", NULL, HXTYPE_IMMED);
-\begin_inset Newline newline
-\end_inset
-
-HXformat_aprintf(table, &result, "%(exec uname -s)");
-\end_layout
-
-\begin_layout Plain Layout
-\begin_inset Caption Standard
-
-\begin_layout Plain Layout
-\begin_inset CommandInset label
-LatexCommand label
-name "fig:hxformat-exec"
-
-\end_inset
-
-Using the
-\family typewriter
-%(exec)
-\family default
- function
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-\begin_inset Newpage clearpage
-\end_inset
-
-
-\end_layout
-
-\begin_layout Part
-Filesystem operations
-\end_layout
-
-\begin_layout Section
-Dentry operations
-\end_layout
-
-\begin_layout Subsection
-Synopsis
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-#include <libHX/io.h>
-\series default
-
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-int
-\series default
- HX_readlink(hxmc_t
-\series bold
-**
-\series default
-buf,
-\series bold
-const char *
-\series default
-path);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-HX_readlink
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-int
-\series default
- HX_realpath(hxmc_t
-\series bold
-**
-\series default
-buf,
-\series bold
-const char *
-\series default
-path,
-\series bold
-unsigned int
-\series default
- flags);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-HX_realpath
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-
-\family typewriter
-HX_readlink
-\family default
- calls through to
-\family typewriter
-readlink
-\family default
- to read the target of a symbolic link, and stores the result in the memory
- container referenced by
-\family typewriter
-*buf
-\family default
- (similar to
-\family typewriter
-HX_getl
-\family default
- semantics).
- If
-\family typewriter
-*buf
-\family default
- is
-\family typewriter
-NULL
-\family default
-, a new container will be allocated and a pointer to it stored in
-\family typewriter
-*buf
-\family default
-.
- The container's content is naturally zero-terminated automatically.
- The return value of the function will be the length of the link target,
- or negative to indicate the system error value.
-\end_layout
-
-\begin_layout Standard
-
-\family typewriter
-HX_realpath
-\family default
- will normalize the given path by transforming various path components into
- alternate descriptions.
- The
-\family typewriter
-flags
-\family default
- parameter controls its actions:
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HX_REALPATH_DEFAULT
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HX_REALPATH_DEFAULT
-\end_layout
-
-\end_inset
-
- A mnemonic for a set of standard flags:
-\family typewriter
-HX_\SpecialChar softhyphen
-REALPATH_\SpecialChar softhyphen
-SELF
-\begin_inset space ~
-\end_inset
-
-| HX_\SpecialChar softhyphen
-REALPATH_\SpecialChar softhyphen
-PARENT
-\family default
-.
- Note that
-\family typewriter
-HX_\SpecialChar softhyphen
-REALPATH_\SpecialChar softhyphen
-ABSOLUTE
-\family default
-, which would also be required to get libc's
-\family typewriter
-realpath
-\family default
-(3) behavior, is not included in the set.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HX_REALPATH_ABSOLUTE
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HX_REALPATH_ABSOLUTE
-\end_layout
-
-\end_inset
-
- Requests that the output path shall be absolute.
- In the absence of this flag, an absolute output path will only be produced
- if the input path is also absolute.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HX_REALPATH_SELF
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HX_REALPATH_SELF
-\end_layout
-
-\end_inset
-
- Request resolution of
-\begin_inset Quotes eld
-\end_inset
-
-.
-\begin_inset Quotes erd
-\end_inset
-
- path components.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HX_REALPATH_PARENT
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HX_REALPATH_PARENT
-\end_layout
-
-\end_inset
-
- Request resolution of
-\begin_inset Quotes eld
-\end_inset
-
-..
-\begin_inset Quotes erd
-\end_inset
-
- path components.
-\end_layout
-
-\begin_layout Standard
-The result is stored in a memory container whose pointer is returned through
-
-\family typewriter
-*buf
-\family default
-.
- The return value of the function will be negative to indicate a possible
- system error, or be positive non-zero for success.
-\end_layout
-
-\begin_layout Section
-Directory traversal
-\begin_inset CommandInset label
-LatexCommand label
-name "sec:dir-ops1"
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-libHX provides a minimal readdir-style wrapper for cross-platform directory
- traversal.
- This is needed because the Win32 platforms does not have readdir, and there
- is some housekeeping to do on Unixish platforms, since the
-\family typewriter
-dirent
-\family default
- structure needs allocation of a path-specific size.
-\end_layout
-
-\begin_layout Subsection
-Synopsis
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-#include
-\series default
- <libHX/io.h>
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-libHX/io.h
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-struct
-\series default
- HXdir
-\series bold
-*
-\series default
-HXdir_open(
-\series bold
-const char *
-\series default
-directory);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\size normal
-\color none
-HXdir_open
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-const char *
-\series default
-HXdir_read(
-\series bold
-struct
-\series default
- HXdir
-\series bold
-*
-\series default
-handle);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\size normal
-\color none
-HXdir_read
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-void
-\series default
- HXdir_close(
-\series bold
-struct
-\series default
- HXdir
-\series bold
-*
-\series default
-handle);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\size normal
-\color none
-HXdir_close
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-
-\family typewriter
-HXdir_open
-\family default
- returns a pointer to its private data area, or
-\family typewriter
-NULL
-\family default
- upon failure, in which case
-\family typewriter
-errno
-\family default
- is preserved from the underlying system calls.
-
-\family typewriter
-HXdir_read
-\family default
- causes the next entry from the directory to be fetched.
- The pointer returned by
-\family typewriter
-HXdir_read
-\family default
- must not be freed, and the data is overwritten in subsequent calls to the
- same handle.
- If you want to keep it around, you will have to duplicate it yourself.
-
-\family typewriter
-HXdir_close
-\family default
- will close the directory and free the private data it held.
-\end_layout
-
-\begin_layout Subsection
-Example
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-#include
-\series default
- <errno.h>
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-#include
-\series default
- <stdio.h>
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-#include
-\series default
- <libHX/io.h>
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-struct
-\series default
- HXdir
-\series bold
-*
-\series default
-dh;
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-if
-\series default
- ((dh = HXdir_open(".")) == NULL) {
-\begin_inset Newline newline
-\end_inset
-
- fprintf(stderr, "Could not open directory: %s
-\backslash
-n", strerror(errno));
-\begin_inset Newline newline
-\end_inset
-
- return;
-\begin_inset Newline newline
-\end_inset
-
-}
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-while
-\series default
- ((dentry = HXdir_read(dh)) != NULL)
-\begin_inset Newline newline
-\end_inset
-
- printf("%s
-\backslash
-n", dentry);
-\begin_inset Newline newline
-\end_inset
-
-HXdir_close(dh);
-\end_layout
-
-\begin_layout Standard
-This sample will open the current directory, and print out all entries as
- it iterates over them.
-\end_layout
-
-\begin_layout Section
-Directory operations
-\begin_inset CommandInset label
-LatexCommand label
-name "sec:dir-ops2"
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Subsection
-Synopsis
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-#include
-\series default
- <libHX/io.h>
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-libHX/io.h
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-int
-\series default
- HX_mkdir(
-\series bold
-const char *
-\series default
-path,
-\series bold
-unsigned int
-\series default
- mode);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-HX_mkdir
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-int
-\series default
- HX_rrmdir(
-\series bold
-const char *
-\series default
-path);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\size normal
-\color none
-HX_rrmdir
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-
-\family typewriter
-HX_mkdir
-\family default
- will create the directory given by
-\family typewriter
-path
-\family default
- and all its parents that do not exist yet using the given
-\family typewriter
-mode
-\family default
-.
- It is equivalent to the `
-\family typewriter
-mkdir -p
-\family default
-` shell command.
- It will return >0 for success, or
-\family typewriter
--errno
-\family default
- on error.
-\end_layout
-
-\begin_layout Standard
-
-\family typewriter
-HX_rrmdir
-\family default
- also maps to an operation commonly done on the shell, `
-\family typewriter
-rm -Rf
-\family default
-`, deleting the directory given by
-\family typewriter
-path
-\family default
-, including all files within it and its subdirectories.
- Errors during deletion are ignored, but if there was any, the errno value
- of the first one is returned negated.
-\end_layout
-
-\begin_layout Section
-File operations
-\begin_inset CommandInset label
-LatexCommand label
-name "sec:file-ops"
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Subsection
-Synopsis
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-#include
-\series default
- <libHX/io.h>
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-libHX/io.h
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-int
-\series default
- HX_copy_file(
-\series bold
-const char *
-\series default
-src,
-\series bold
-const char *
-\series default
-dest,
-\series bold
-unsigned int
-\series default
- flags, ...);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HX_copy_file
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-int
-\series default
- HX_copy_dir(
-\series bold
-const char *
-\series default
-src,
-\series bold
-const char *
-\series default
-dest,
-\series bold
-unsigned int
-\series default
- flags, ...);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HX_copy_dir
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-Possible flags that can be used with the functions:
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXF_KEEP
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXF_KEEP
-\end_layout
-
-\end_inset
-
- Do not overwrite existing files.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXF_UID
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXF_UID
-\end_layout
-
-\end_inset
-
- Change the new file's owner to the UID given in the varargs section (
-\family typewriter
-...
-\family default
-).
-
-\family typewriter
-HXF_UID
-\family default
- is processed before
-\family typewriter
-HXF_GID
-\family default
-.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXF_GID
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXF_GID
-\end_layout
-
-\end_inset
-
- Change the new file's group owner to the GID given in the varargs section.
- This is processed after
-\family typewriter
-HXF_UID
-\family default
-.
-\end_layout
-
-\begin_layout Standard
-Error checking is flakey.
-\end_layout
-
-\begin_layout Standard
-
-\family typewriter
-HX_copy_file
-\family default
- will return >0 on success, or
-\family typewriter
--errno
-\family default
- on failure.
- Errors can arise from the use of the syscalls
-\family typewriter
-open
-\family default
-,
-\family typewriter
-read
-\family default
- and
-\family typewriter
-write
-\family default
-.
- The return value of
-\family typewriter
-fchmod
-\family default
-, which is used to set the UID and GID, is actually ignored, which means
- verifying that the owner has been set cannot be detected with
-\family typewriter
-HX_copy_file
-\family default
- alone (historic negligience?).
-\end_layout
-
-\begin_layout Subsection
-Filedescriptor I/O
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-#include
-\series default
- <libHX/io.h>
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-libHX/io.h
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-ssize_t
-\series default
- HXio_fullread(
-\series bold
-int
-\series default
- fd,
-\series bold
-void *
-\series default
-buf,
-\series bold
-size_t
-\series default
- size,
-\series bold
-unsigned int
-\series default
- flags);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXio_fullread
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-ssize_t
-\series default
- HXio_fullwrite(
-\series bold
-int
-\series default
- fd,
-\series bold
-const void *
-\series default
-buf,
-\series bold
-size_t
-\series default
- size,
-\series bold
-unsigned int
-\series default
- flags);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXio_fullwrite
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-Since plain
-\family typewriter
-read
-\family default
-(2) and
-\family typewriter
-write
-\family default
-(2) may process only part of the buffer
-\begin_inset space ~
-\end_inset
-
-— even more likely so with sockets
-\begin_inset space ~
-\end_inset
-
-—, libHX provides two functions that calls these in a loop to retry said
- operations until the full amount has been processed.
- Since
-\family typewriter
-read
-\family default
- and
-\family typewriter
-write
-\family default
- can also be used with socket file descriptors, so can these.
-\end_layout
-
-\begin_layout Standard
-\begin_inset Newpage clearpage
-\end_inset
-
-
-\end_layout
-
-\begin_layout Part
-Options and Configuration Files
-\end_layout
-
-\begin_layout Section
-Option parsing
-\begin_inset CommandInset label
-LatexCommand label
-name "sec:option"
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-libHX uses a table-based approach like libpopt
-\begin_inset Foot
-status open
-
-\begin_layout Plain Layout
-The alternative would be an iterative, open-coded approach like
-\family typewriter
-getopt
-\family default
-(3) requires.
-\end_layout
-
-\end_inset
-
-.
- It provides for both long and short options and the different styles associated
- with them, such as absence or presence of an equals sign for long options
- (
-\family typewriter
---foo=bar
-\family default
- and
-\family typewriter
---foo bar
-\family default
-), bundling (writing
-\family typewriter
--abc
-\family default
- for non-argument taking options
-\family typewriter
--a -b -c
-\family default
-), squashing (writing
-\family typewriter
--fbar
-\family default
- for an argument-requiring option
-\family typewriter
--f
-\begin_inset space ~
-\end_inset
-
-bar
-\family default
-).
- The
-\begin_inset Quotes eld
-\end_inset
-
-lone dash
-\begin_inset Quotes erd
-\end_inset
-
- that is often used to indicate standard input or standard output, is correctly
- handled
-\begin_inset Foot
-status open
-
-\begin_layout Plain Layout
-popt failed to do this for a long time.
-\end_layout
-
-\end_inset
-
-, as in
-\family typewriter
--f
-\begin_inset space ~
-\end_inset
-
--
-\family default
-.
-\end_layout
-
-\begin_layout Standard
-A table-based approach allows for the parser to run as one atomic block
- of code (callbacks are, by definition,
-\begin_inset Quotes eld
-\end_inset
-
-special
-\begin_inset Quotes erd
-\end_inset
-
- exceptions), making it more opaque than an open-coded
-\family typewriter
-getopt
-\family default
-(3) loop.
- You give it your argument vector and the table, snip the finger (call the
- parser function once), and it is done.
- In getopt on the other hand, the
-\family typewriter
-getopt
-\family default
- function returns for every argument it parsed and needs to be called repeatedly.
-\end_layout
-
-\begin_layout Subsection
-Synopsis
-\begin_inset CommandInset label
-LatexCommand label
-name "subsec:option-synopsis"
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-#include
-\series default
- <libHX/option.h>
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-libHX/option.h
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-struct
-\series default
- HXoption {
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-struct HXoption
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-const char
-\series default
- *ln;
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-char
-\series default
- sh;
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-unsigned int
-\series default
- type;
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-void *
-\series default
-ptr,
-\series bold
-*
-\series default
-uptr;
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-void (*
-\series default
-cb
-\series bold
-)
-\series default
-(
-\series bold
-const struct
-\series default
- HXoptcb
-\series bold
-*
-\series default
-);
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-int
-\series default
- val;
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-const char *
-\series default
-help,
-\series bold
-*
-\series default
-htyp;
-\begin_inset Newline newline
-\end_inset
-
-};
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-int
-\series default
- HX_getopt(
-\series bold
-const struct
-\series default
- HXoption
-\series bold
-*
-\series default
-options_table,
-\series bold
-int *
-\series default
-argc,
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-const char ***
-\series default
-argv,
-\series bold
-unsigned int
-\series default
- flags);
-\end_layout
-
-\begin_layout Standard
-The various fields of
-\family typewriter
-struct HXoption
-\family default
- are:
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-ln
-\family default
- The long option name, if any.
- May be
-\family typewriter
-NULL
-\family default
- if none is to be assigned for this entry.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-sh
-\family default
- The short option name/character, if any.
- May be
-\family typewriter
-'
-\backslash
-0'
-\family default
- if none is to be assigned for this entry.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-type
-\family default
- The type of the entry, essentially denoting the type of the target variable.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-val
-\family default
- An integer value to be stored into
-\family typewriter
-*(int
-\begin_inset space ~
-\end_inset
-
-*)ptr
-\family default
- when
-\family typewriter
-HXTYPE_IVAL
-\family default
- is used.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-ptr
-\family default
- A pointer to the variable so that the option parser can store the requested
- data in it.
- The pointer may be
-\family typewriter
-NULL
-\family default
- in which case no data is stored (but
-\family typewriter
-cb
-\family default
- is still called if defined, with the data).
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-uptr
-\family default
- A user-supplied pointer.
- Its value is passed verbatim to the callback, and may be used for any purpose
- the user wishes.
- If
-\family typewriter
-type
-\family default
- is
-\family typewriter
-HXTYPE_SVAL
-\family default
-, it is the value in
-\family typewriter
-uptr
-\family default
- that will be used to populate
-\family typewriter
-*(const char
-\begin_inset space ~
-\end_inset
-
-**)ptr
-\family default
-.
- (The original
-\family typewriter
-.sval
-\family default
- field has been removed in libHX 3.12.)
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-cb
-\family default
- If not
-\family typewriter
-NULL
-\family default
-, call out to the referenced function after the option has been parsed (and
- the results possibly be stored in
-\family typewriter
-ptr
-\family default
-)
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-help
-\family default
- A help string that is shown for the option when the option table is dumped
- by request (e.
-\begin_inset space \thinspace{}
-\end_inset
-
-g.
-\begin_inset space \space{}
-\end_inset
-
-
-\family typewriter
-yourprgram --help
-\family default
-)
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-htyp
-\family default
- String containing a keyword to aid the user in understanding the available
- options during dump.
- See examples.
-\end_layout
-
-\begin_layout Standard
-Due to the amount of fields, it is advised to use C99 named initializers
- to populate a struct, as they allow to omit unspecified fields, and assume
- no specific order of the members:
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-struct
-\series default
- HXoption e = {.sh = 'f', .help = "Force"};
-\end_layout
-
-\begin_layout Standard
-It is a sad fact that C++ has not gotten around to implement these yet.
- It is advised to put the option parsing code into a separate
-\family typewriter
-.c
-\family default
- file that can then be compiled in C99 rather than C++ mode.
-\end_layout
-
-\begin_layout Subsection
-Type map
-\begin_inset CommandInset label
-LatexCommand label
-name "subsec:option-types"
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXTYPE_NONE
-\series medium
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\series medium
-HXTYPE_NONE
-\end_layout
-
-\end_inset
-
-
-\family default
-\series default
- The option does not take any argument, but the presence of the option may
- be record by setting the
-\family typewriter
-*(int
-\begin_inset space ~
-\end_inset
-
-*)ptr
-\family default
- to 1.
- Other rules apply when
-\family typewriter
-HXOPT_\SpecialChar softhyphen
-INC
-\family default
- or
-\family typewriter
-HXOPT_\SpecialChar softhyphen
-DEC
-\family default
- are specified as flags (see section
-\begin_inset space ~
-\end_inset
-
-
-\begin_inset CommandInset ref
-LatexCommand ref
-reference "subsec:option-flags"
-
-\end_inset
-
-).
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXTYPE_VAL
-\series medium
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\series medium
-HXTYPE_VAL
-\end_layout
-
-\end_inset
-
-
-\family default
-\series default
- Use the integer value specified by
-\family typewriter
-ival
-\family default
- and store it in
-\family typewriter
-*(int
-\begin_inset space ~
-\end_inset
-
-*)ptr
-\family default
-.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXTYPE_SVAL
-\series medium
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\series medium
-HXTYPE_SVAL
-\end_layout
-
-\end_inset
-
-
-\family default
-\series default
- Use the memory location specified by
-\family typewriter
-sval
-\family default
- and store it in
-\family typewriter
-*(const char
-\begin_inset space ~
-\end_inset
-
-**)ptr
-\family default
-.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXTYPE_BOOL
-\series medium
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\series medium
-HXTYPE_BOOL
-\end_layout
-
-\end_inset
-
-
-\family default
-\series default
- Interpret the supplied argument as a boolean descriptive (must be
-\begin_inset Quotes eld
-\end_inset
-
-yes
-\begin_inset Quotes erd
-\end_inset
-
-,
-\begin_inset Quotes eld
-\end_inset
-
-no
-\begin_inset Quotes erd
-\end_inset
-
-,
-\begin_inset Quotes eld
-\end_inset
-
-on
-\begin_inset Quotes erd
-\end_inset
-
-,
-\begin_inset Quotes eld
-\end_inset
-
-off
-\begin_inset Quotes erd
-\end_inset
-
-,
-\begin_inset Quotes eld
-\end_inset
-
-true
-\begin_inset Quotes erd
-\end_inset
-
-,
-\begin_inset Quotes eld
-\end_inset
-
-false
-\begin_inset Quotes erd
-\end_inset
-
-,
-\begin_inset Quotes eld
-\end_inset
-
-0
-\begin_inset Quotes erd
-\end_inset
-
- or
-\begin_inset Quotes eld
-\end_inset
-
-1
-\begin_inset Quotes erd
-\end_inset
-
-) and store the result in
-\family typewriter
-*(int
-\begin_inset space ~
-\end_inset
-
-*)ptr
-\family default
-.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXTYPE_STRING
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXTYPE_STRING
-\end_layout
-
-\end_inset
-
-
-\family default
- The argument string is duplicated to a new memory region and the resulting
- pointer stored into
-\family typewriter
-*(char
-\begin_inset space ~
-\end_inset
-
-**)ptr
-\family default
-.
- This incurs an allocation so that subsequently modifying the original argument
- string in any way will not falsely propagate.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXTYPE_STRDQ
-\series medium
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\series medium
-HXTYPE_STRDQ
-\end_layout
-
-\end_inset
-
-
-\family default
-\series default
- The argument string is duplicated to a new memory region and the resulting
- pointer is added to the given HXdeque.
- Note that you often need to use deferred initialization of the options
- table to avoid putting
-\family typewriter
-NULL
-\family default
- into the entry.
- See section
-\begin_inset space ~
-\end_inset
-
-
-\begin_inset CommandInset ref
-LatexCommand ref
-reference "subsec:option-pitfalls-static"
-
-\end_inset
-
-.
-\end_layout
-
-\begin_layout Standard
-The following table lists the types that map to the common integral and
- floating-point types.
- Signed and unsigned integeral types are processed using
-\family typewriter
-strtol
-\family default
- and
-\family typewriter
-strtoul
-\family default
-, respectively.
-
-\family typewriter
-strtol
-\family default
- and
-\family typewriter
-strtoul
-\family default
- will be called with automatic base detection.
- This usually means that a leading
-\begin_inset Quotes eld
-\end_inset
-
-0
-\begin_inset Quotes erd
-\end_inset
-
- indicates the string is given in octal (8) base, a leading
-\begin_inset Quotes eld
-\end_inset
-
-0x
-\begin_inset Quotes erd
-\end_inset
-
- indicates hexadecimal (16) base, and decimal (10) otherwise.
-
-\family typewriter
-HXTYPE_\SpecialChar softhyphen
-LLONG
-\family default
-,
-\family typewriter
- HXTYPE_\SpecialChar softhyphen
-ULLONG
-\family default
-,
-\family typewriter
- HXTYPE_\SpecialChar softhyphen
-INT64
-\family default
- and
-\family typewriter
- HXTYPE_\SpecialChar softhyphen
-UINT64
-\family default
- use
-\family typewriter
- strtoll
-\family default
- and/or
-\family typewriter
- strtoull
-\family default
-, which may not be available on all platforms.
-\begin_inset Separator latexpar
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-\align center
-\begin_inset Float table
-placement H
-wide false
-sideways false
-status open
-
-\begin_layout Plain Layout
-\align center
-\begin_inset Tabular
-<lyxtabular version="3" rows="12" columns="4">
-<features tabularvalignment="middle">
-<column alignment="center" valignment="top">
-<column alignment="center" valignment="bottom">
-<column alignment="center" valignment="top">
-<column alignment="center" valignment="top">
-<row>
-<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\family typewriter
-\series bold
-type
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\series bold
-Type of pointee
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\series bold
-type
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\series bold
-Type of pointee
-\end_layout
-
-\end_inset
-</cell>
-</row>
-<row>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXTYPE_CHAR
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXTYPE_CHAR
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\family typewriter
-char
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXTYPE_INT8
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXTYPE_INT8
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\family typewriter
-int8_t
-\end_layout
-
-\end_inset
-</cell>
-</row>
-<row>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXTYPE_UCHAR
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXTYPE_UCHAR
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\family typewriter
-unsigned char
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXTYPE_UINT8
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXTYPE_UINT8
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\family typewriter
-uint8_t
-\end_layout
-
-\end_inset
-</cell>
-</row>
-<row>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXTYPE_SHORT
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXTYPE_SHORT
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\family typewriter
-short
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXTYPE_INT16
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXTYPE_INT16
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\family typewriter
-int16_t
-\end_layout
-
-\end_inset
-</cell>
-</row>
-<row>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXTYPE_USHORT
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXTYPE_USHORT
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\family typewriter
-unsigned short
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXTYPE_UINT16
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXTYPE_UINT16
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\family typewriter
-uint16_t
-\end_layout
-
-\end_inset
-</cell>
-</row>
-<row>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXTYPE_INT
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXTYPE_INT
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\family typewriter
-int
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXTYPE_INT32
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXTYPE_INT32
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\family typewriter
-int32_t
-\end_layout
-
-\end_inset
-</cell>
-</row>
-<row>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXTYPE_UINT
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXTYPE_UINT
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\family typewriter
-unsigned int
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXTYPE_UINT32
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXTYPE_UINT32
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\family typewriter
-uint32_t
-\end_layout
-
-\end_inset
-</cell>
-</row>
-<row>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXTYPE_LONG
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXTYPE_LONG
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\family typewriter
-long
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXTYPE_INT64
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXTYPE_INT64
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\family typewriter
-int64_t
-\end_layout
-
-\end_inset
-</cell>
-</row>
-<row>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXTYPE_ULONG
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXTYPE_ULONG
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\family typewriter
-unsigned long
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXTYPE_UINT64
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXTYPE_UINT64
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\family typewriter
-uint64_t
-\end_layout
-
-\end_inset
-</cell>
-</row>
-<row>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXTYPE_LLONG
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXTYPE_LLONG
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\family typewriter
-long long
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXTYPE_FLOAT
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXTYPE_FLOAT
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\family typewriter
-float
-\end_layout
-
-\end_inset
-</cell>
-</row>
-<row>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXTYPE_ULLONG
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXTYPE_ULLONG
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\family typewriter
-unsigned long long
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXTYPE_DOUBLE
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXTYPE_DOUBLE
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\family typewriter
-double
-\end_layout
-
-\end_inset
-</cell>
-</row>
-<row>
-<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXTYPE_SIZE_T
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXTYPE_SIZE_T
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\family typewriter
-size_t
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\end_inset
-</cell>
-</row>
-</lyxtabular>
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Plain Layout
-\begin_inset Caption Standard
-
-\begin_layout Plain Layout
-Integral and floating-point types for the libHX option parser
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-
-\family typewriter
-HXTYPE_\SpecialChar softhyphen
-FLOAT
-\family default
- and
-\family typewriter
-HXTYPE_\SpecialChar softhyphen
-DOUBLE
-\family default
- make use of
-\family typewriter
-strtod
-\family default
- (
-\family typewriter
-strtof
-\family default
- is not used).
- A corresponding
-\family typewriter
-type
-\family default
- for the
-\begin_inset Quotes eld
-\end_inset
-
-long double
-\begin_inset Quotes erd
-\end_inset
-
- format is not specified, but may be implemented on behalf of the user via
- a callback (see section
-\begin_inset space ~
-\end_inset
-
-
-\begin_inset CommandInset ref
-LatexCommand ref
-reference "subsec:option-example-cb"
-
-\end_inset
-
-).
-\end_layout
-
-\begin_layout Subsection
-Flags
-\begin_inset CommandInset label
-LatexCommand label
-name "subsec:option-flags"
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-Flags can be combined into the
-\family typewriter
-type
-\family default
- parameter by OR'ing them.
- It is valid to not specify any flags at all, but most flags collide with
- one another.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXOPT_INC
-\series medium
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\series medium
-HXOPT_INC
-\end_layout
-
-\end_inset
-
-
-\family default
-\series default
- Perform an increment on the memory location specified by the
-\family typewriter
-*(int
-\begin_inset space ~
-\end_inset
-
-*)ptr
-\family default
- pointer.
- Make sure the referenced variable is initialized before!
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXOPT_DEC
-\family default
-\series medium
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXOPT_DEC
-\end_layout
-
-\end_inset
-
-
-\series default
- Perform a decrement on the pointee.
-\end_layout
-
-\begin_layout Standard
-Only one of
-\family typewriter
-HXOPT_\SpecialChar softhyphen
-INC
-\family default
- and
-\family typewriter
-HXOPT_\SpecialChar softhyphen
-DEC
-\family default
- may be specified at a time, and they require that the base type is
-\family typewriter
-HXTYPE_\SpecialChar softhyphen
-NONE
-\family default
-, or they will have no effect.
- An example may be found in section
-\begin_inset space ~
-\end_inset
-
-
-\begin_inset CommandInset ref
-LatexCommand ref
-reference "subsec:option-example-incdec"
-
-\end_inset
-
-.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXOPT_NOT
-\series medium
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\series medium
-HXOPT_NOT
-\end_layout
-
-\end_inset
-
-
-\family default
-\series default
- Binary negation of the argument directly after reading it from the command
- line into memory.
- Any of the three following operations are executed with the already-negated
- value.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXOPT_OR
-\series medium
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXOPT_OR
-\end_layout
-
-\end_inset
-
-
-\family default
-\series default
- Binary
-\begin_inset Quotes eld
-\end_inset
-
-OR
-\begin_inset Quotes erd
-\end_inset
-
-s the pointee with the specified\SpecialChar breakableslash
-transformed value.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXOPT_AND
-\series medium
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\series medium
-HXOPT_AND
-\end_layout
-
-\end_inset
-
-
-\family default
-\series default
- Binary
-\begin_inset Quotes eld
-\end_inset
-
-AND
-\begin_inset Quotes erd
-\end_inset
-
-s the pointee with the specified\SpecialChar breakableslash
-transformed value.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXOPT_XOR
-\series medium
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\series medium
-HXOPT_XOR
-\end_layout
-
-\end_inset
-
-
-\family default
-\series default
- Binary
-\begin_inset Quotes eld
-\end_inset
-
-XOR
-\begin_inset Quotes erd
-\end_inset
-
-s the pointee with the specified\SpecialChar breakableslash
-transformed value.
-\end_layout
-
-\begin_layout Standard
-Only one of (
-\family typewriter
-HXOPT_OR
-\family default
-,
-\family typewriter
-HXOPT_\SpecialChar softhyphen
-AND
-\family default
-,
-\family typewriter
-HXOPT_\SpecialChar softhyphen
-XOR
-\family default
-) may be specified at a time, but they can be used with any integral
-\family typewriter
-type
-\family default
- (
-\family typewriter
-HXTYPE_\SpecialChar softhyphen
-UINT
-\family default
-,
-\family typewriter
-HXTYPE_\SpecialChar softhyphen
-ULONG
-\family default
-, etc.).
- An example can be found in section
-\begin_inset space ~
-\end_inset
-
-
-\begin_inset CommandInset ref
-LatexCommand ref
-reference "subsec:option-example-mask"
-
-\end_inset
-
-.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXOPT_OPTIONAL
-\series medium
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\series medium
-HXOPT_OPTIONAL
-\end_layout
-
-\end_inset
-
-
-\family default
-\series default
- This flag allows for an option to take zero or one argument.
- Needless to say that this can be confusing to the user.
-
-\shape italic
-iptables
-\shape default
-'s
-\begin_inset Quotes eld
-\end_inset
-
-
-\family typewriter
--L
-\family default
-
-\begin_inset Quotes erd
-\end_inset
-
- option for example is one of this kind (though it does not use the libHX
- option parser).
- When this flag is used,
-\begin_inset Quotes eld
-\end_inset
-
-
-\family typewriter
--f -b
-\family default
-
-\begin_inset Quotes erd
-\end_inset
-
- is interpreted as
-\family typewriter
--f
-\family default
- without an argument, as is
-\begin_inset Quotes eld
-\end_inset
-
-
-\family typewriter
--f --bar
-\family default
-
-\begin_inset Quotes erd
-\end_inset
-
-
-\begin_inset space ~
-\end_inset
-
-— things that look like an option take precedence over an option with an
- optional argument.
-
-\begin_inset Quotes eld
-\end_inset
-
-
-\family typewriter
--f -
-\family default
-
-\begin_inset Quotes erd
-\end_inset
-
- of course denotes an option with an argument, as
-\begin_inset Quotes eld
-\end_inset
-
-
-\family typewriter
--
-\family default
-
-\begin_inset Quotes erd
-\end_inset
-
- is used to indicate standard input/output.
-\end_layout
-
-\begin_layout Subsection
-Special entries
-\end_layout
-
-\begin_layout Standard
-HXopt provides two special entries via macros:
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXOPT_AUTOHELP
-\series medium
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\series medium
-HXOPT_AUTOHELP
-\end_layout
-
-\end_inset
-
-
-\family default
-\series default
- Adds entries to recognize
-\begin_inset Quotes eld
-\end_inset
-
-
-\family typewriter
--?
-\family default
-
-\begin_inset Quotes erd
-\end_inset
-
- and
-\begin_inset Quotes eld
-\end_inset
-
-
-\family typewriter
---help
-\family default
-
-\begin_inset Quotes erd
-\end_inset
-
- that will display the (long-format) help screen, and
-\begin_inset Quotes eld
-\end_inset
-
-
-\family typewriter
---usage
-\family default
-
-\begin_inset Quotes erd
-\end_inset
-
- that will display the short option syntax overview.
- All three options will exit the program afterwards.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXOPT_TABLEEND
-\series medium
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\series medium
-HXOPT_TABLEEND
-\end_layout
-
-\end_inset
-
-
-\family default
-\series default
- This sentinel marks the end of the table and is required on all tables.
- (See examples for details.)
-\end_layout
-
-\begin_layout Subsection
-Invoking the parser
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-int
-\series default
- HX_getopt(
-\series bold
-const struct
-\series default
- HXoption
-\series bold
-*
-\series default
-options_table,
-\series bold
-int *
-\series default
-argc,
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-const char ***
-\series default
-argv,
-\series bold
-unsigned int
-\series default
- flags);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HX_getopt
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-
-\family typewriter
-HX_getopt
-\family default
- is the actual parsing function.
- It takes the option table, and a pointer to your
-\family typewriter
-argc
-\family default
- and
-\family typewriter
-argv
-\family default
- variables that you get from the
-\family typewriter
-main
-\family default
- function.
- The parser will, unlike GNU getopt, literally
-\begin_inset Quotes eld
-\end_inset
-
-eat
-\begin_inset Quotes erd
-\end_inset
-
- all options and their arguments, leaving only non-options in
-\family typewriter
-argv
-\family default
-, and
-\family typewriter
-argc
-\family default
- updated, when finished.
- This is similar to how Perl's
-\begin_inset Quotes eld
-\end_inset
-
-Getopt::Long
-\begin_inset Quotes erd
-\end_inset
-
- module works.
- Additional flags can control the exact behavior of
-\family typewriter
-HX_getopt
-\family default
-:
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXOPT_PTHRU
-\series medium
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\series medium
-HXOPT_PTHRU
-\end_layout
-
-\end_inset
-
-
-\family default
-\series default
-
-\begin_inset Quotes eld
-\end_inset
-
-Passthrough mode
-\begin_inset Quotes erd
-\end_inset
-
-.
- Any unknown options are not
-\begin_inset Quotes eld
-\end_inset
-
-eaten
-\begin_inset Quotes erd
-\end_inset
-
- and are instead passed back into the resulting
-\family typewriter
-argv
-\family default
- array.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXOPT_QUIET
-\series medium
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\series medium
-HXOPT_QUIET
-\end_layout
-
-\end_inset
-
-
-\family default
-\series default
- Do not print any diagnostics when encountering errors in the user's input.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXOPT_HELPONERR
-\series medium
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXOPT_HELPONERR
-\end_layout
-
-\end_inset
-
-
-\family default
-\series default
- Display the (long-format) help when an error, such as an unknown option
- or a violation of syntax, is encountered.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXOPT_USAGEONERR
-\series medium
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXOPT_USAGEONERR
-\end_layout
-
-\end_inset
-
-
-\family default
-\series default
- Display the short-format usage syntax when an error is encountered.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXOPT_RQ_ORDER
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXOPT_RQ_ORDER
-\end_layout
-
-\end_inset
-
- Specifying this option terminates option processing when the first non-option
- argument in
-\family typewriter
-argv
-\family default
- is encountered.
- This behavior is also implicit when the environment variable
-\family typewriter
-POSIXLY_CORRECT
-\family default
- is set.
-\end_layout
-
-\begin_layout Standard
-The return value can be one of the following:
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXOPT_ERR_SUCCESS
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXOPT_ERR_SUCCESS
-\end_layout
-
-\end_inset
-
- Parsing was successful.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXOPT_ERR_UNKN
-\series medium
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\series medium
-HXOPT_ERR_UNKN
-\end_layout
-
-\end_inset
-
-
-\family default
-\series default
- An unknown option was encountered.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXOPT_ERR_VOID
-\series medium
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\series medium
-HXOPT_ERR_VOID
-\end_layout
-
-\end_inset
-
-
-\family default
-\series default
- An argument was given for an option which does not allow one.
- In practice this only happens with
-\begin_inset Quotes eld
-\end_inset
-
-
-\family typewriter
---foo=bar
-\family default
-
-\begin_inset Quotes erd
-\end_inset
-
- when
-\family typewriter
---foo
-\family default
- is of type
-\family typewriter
-HXTYPE_\SpecialChar softhyphen
-NONE
-\family default
-,
-\family typewriter
-HXTYPE_\SpecialChar softhyphen
-VAL
-\family default
- or
-\family typewriter
-HXTYPE_\SpecialChar softhyphen
-SVAL
-\family default
-.
- This does not affect
-\begin_inset Quotes eld
-\end_inset
-
-
-\family typewriter
---foo bar
-\family default
-
-\begin_inset Quotes erd
-\end_inset
-
-, because this can be unambiguously interpreted as
-\begin_inset Quotes eld
-\end_inset
-
-
-\family typewriter
-bar
-\family default
-
-\begin_inset Quotes erd
-\end_inset
-
- being a remaining argument to the program.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXOPT_ERR_MIS
-\series medium
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\series medium
-HXOPT_ERR_MIS
-\end_layout
-
-\end_inset
-
-
-\family default
-\series default
- Missing argument for an option that requires one.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXOPT_ERR_AMBIG
-\series medium
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\series medium
-HXOPT_ERR_AMBIG
-\end_layout
-
-\end_inset
-
-
-\family default
-\series default
- An abbreviation of a long option was ambiguous.
-\end_layout
-
-\begin_layout Description
-negative
-\begin_inset space ~
-\end_inset
-
-non-zero Failure on behalf of lower-level calls; errno.
-\end_layout
-
-\begin_layout Subsection
-Pitfalls
-\end_layout
-
-\begin_layout Subsubsection
-Staticness of tables
-\begin_inset CommandInset label
-LatexCommand label
-name "subsec:option-pitfalls-static"
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-The following is an example of a possible pitfall regarding
-\family typewriter
-HXTYPE_\SpecialChar softhyphen
-STRDQ
-\family default
-:
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-static struct
-\series default
- HXdeque
-\series bold
-*
-\series default
-dq;
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-static bool
-\series default
- get_options(
-\series bold
-int *
-\series default
-argc,
-\series bold
-const char ***
-\series default
-argv)
-\begin_inset Newline newline
-\end_inset
-
-{
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-static const struct
-\series default
- HXoption options_table
-\series bold
-[]
-\series default
- = {
-\begin_inset Newline newline
-\end_inset
-
- {.sh = 'N', .type = HXTYPE_STRDQ, .q_strdq = dq,
-\begin_inset Newline newline
-\end_inset
-
- .help = "Add name"},
-\begin_inset Newline newline
-\end_inset
-
- HXOPT_TABLEEND,
-\begin_inset Newline newline
-\end_inset
-
- };
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-return
-\series default
- HX_getopt(options_table, argc, argv, HXOPT_USAGEONERR) ==
-\begin_inset Newline newline
-\end_inset
-
- HXOPT_ERR_SUCCESS;
-\begin_inset Newline newline
-\end_inset
-
-}
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-int
-\series default
- main(
-\series bold
-int
-\series default
- argc,
-\series bold
-const char **
-\series default
-argv)
-\begin_inset Newline newline
-\end_inset
-
-{
-\begin_inset Newline newline
-\end_inset
-
- dq = HXdeque_init();
-\begin_inset Newline newline
-\end_inset
-
- get_options(&argc, &argv);
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-return
-\series default
- 0;
-\begin_inset Newline newline
-\end_inset
-
-}
-\end_layout
-
-\begin_layout Standard
-The problem here is that
-\family typewriter
-options_\SpecialChar softhyphen
-table
-\family default
- is, due to the
-\family typewriter
-static
-\family default
- keyword, initialized at compile-time where
-\family typewriter
-dq
-\family default
- is still
-\family typewriter
-NULL
-\family default
-.
- To counter this problem and have it doing the right thing, you must remove
- the
-\family typewriter
-static
-\family default
- qualifier on the options table when used with
-\family typewriter
-HXTYPE_\SpecialChar softhyphen
-STRDQ
-\family default
-, so that it will be evaluated when it is first executed.
-\end_layout
-
-\begin_layout Standard
-It was not deemed worthwhile to have
-\family typewriter
-HXTYPE_\SpecialChar softhyphen
-STRDQ
-\family default
- take an indirect HXdeque (
-\family typewriter
-struct HXdeque
-\begin_inset space ~
-\end_inset
-
-**
-\family default
-) instead just to bypass this issue.
- (Live with it.)
-\end_layout
-
-\begin_layout Subsection
-Limitations
-\end_layout
-
-\begin_layout Standard
-The HX option parser has been influenced by both popt and Getopt::Long,
- but eventually, there are differences:
-\end_layout
-
-\begin_layout Itemize
-Long options with a single dash (
-\begin_inset Quotes eld
-\end_inset
-
-
-\family typewriter
--foo bar
-\family default
-
-\begin_inset Quotes erd
-\end_inset
-
-).
- This unsupported syntax clashes very easily with support for option bundling
- or squashing.
- In case of bundling,
-\begin_inset Quotes eld
-\end_inset
-
-
-\family typewriter
--foo
-\family default
-
-\begin_inset Quotes erd
-\end_inset
-
- might actually be
-\begin_inset Quotes eld
-\end_inset
-
-
-\family typewriter
--f -o -o
-\family default
-
-\begin_inset Quotes erd
-\end_inset
-
-, or
-\begin_inset Quotes eld
-\end_inset
-
-
-\family typewriter
--f oo
-\family default
-
-\begin_inset Quotes erd
-\end_inset
-
- in case of squashing.
- It also introduces redundant ways to specify options, which is not in the
- spirit of the author.
-\end_layout
-
-\begin_layout Itemize
-Options using a
-\begin_inset Quotes eld
-\end_inset
-
-
-\family typewriter
-+
-\family default
-
-\begin_inset Quotes erd
-\end_inset
-
- as a prefix, as in
-\begin_inset Quotes eld
-\end_inset
-
-
-\family typewriter
-+foo
-\family default
-
-\begin_inset Quotes erd
-\end_inset
-
-.
- Xterm for example uses it as a way to negate an option.
- In the author's opinion, using one character to specify options is enough
-\begin_inset space ~
-\end_inset
-
-— by GNU standards, a negator is named
-\begin_inset Quotes eld
-\end_inset
-
-
-\family typewriter
---no-foo
-\family default
-
-\begin_inset Quotes erd
-\end_inset
-
-.
- Even Microsoft stuck to a single option introducing character (that would
- be
-\begin_inset Quotes eld
-\end_inset
-
-
-\family typewriter
-/
-\family default
-
-\begin_inset Quotes erd
-\end_inset
-
-).
-\end_layout
-
-\begin_layout Itemize
-Table nesting like implemented in popt.
- HXopt has no provision for nested tables, as the need has not come up yet.
- It does however support chained processing (see section
-\begin_inset space ~
-\end_inset
-
-
-\begin_inset CommandInset ref
-LatexCommand ref
-reference "subsec:option-example-chained"
-
-\end_inset
-
-).
- You cannot do nested tables even with callbacks, as the new
-\family typewriter
-argv
-\family default
- array is only put in place shortly before
-\family typewriter
-HX_getopt
-\family default
- returns.
-\end_layout
-
-\begin_layout Subsection
-Examples
-\end_layout
-
-\begin_layout Subsubsection
-Basic example
-\end_layout
-
-\begin_layout Standard
-The following code snippet should provide an equivalent of the GNU getopt
- sample
-\begin_inset Foot
-status open
-
-\begin_layout Plain Layout
-\begin_inset Flex URL
-status open
-
-\begin_layout Plain Layout
-
-http://www.gnu.org/software/libtool/manual/libc/Example-of-Getopt.html
-\backslash
-#Example-of-Getopt
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\end_inset
-
-.
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-#include
-\series default
- <stdio.h>
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-#include
-\series default
- <stdilb.h>
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-#include
-\series default
- <libHX/option.h>
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-int
-\series default
- main(
-\series bold
-int
-\series default
- argc,
-\series bold
-const char **
-\series default
-argv)
-\begin_inset Newline newline
-\end_inset
-
-{
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-int
-\series default
- aflag = 0;
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-int
-\series default
- bflag = 0;
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-char *
-\series default
-cflag = NULL;
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-struct
-\series default
- HXoption options_table
-\series bold
-[]
-\series default
- = {
-\begin_inset Newline newline
-\end_inset
-
- {.sh = 'a', .type = HXTYPE_NONE, .ptr = &aflag},
-\begin_inset Newline newline
-\end_inset
-
- {.sh = 'b', .type = HXTYPE_NONE, .ptr = &bflag},
-\begin_inset Newline newline
-\end_inset
-
- {.sh = 'c', .type = HXTYPE_STRING, .ptr = &cflag},
-\begin_inset Newline newline
-\end_inset
-
- HXOPT_AUTOHELP,
-\end_layout
-
-\begin_layout LyX-Code
- HXOPT_TABLEEND,
-\begin_inset Newline newline
-\end_inset
-
- };
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-if
-\series default
- (HX_getopt(options_table, &argc, &argv, HXOPT_USAGEONERR) !=
-\begin_inset Newline newline
-\end_inset
-
- HXOPT_ERR_SUCCESS)
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-return
-\series default
- EXIT_FAILURE;
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
- printf("aflag = %d, bflag = %d, cvalue = %s
-\backslash
-n",
-\begin_inset Newline newline
-\end_inset
-
- aflag, bflag, cvalue);
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-while
-\series default
- (*++argv != NULL)
-\begin_inset Newline newline
-\end_inset
-
- printf("Non-option argument %s
-\backslash
-n", *argv);
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-return
-\series default
- EXIT_SUCCESS;
-\begin_inset Newline newline
-\end_inset
-
-}
-\end_layout
-
-\begin_layout Subsubsection
-Verbosity levels
-\begin_inset CommandInset label
-LatexCommand label
-name "subsec:option-example-incdec"
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-static int
-\series default
- verbosity = 1;
-\series bold
-/*
-\family roman
-\series default
-\shape italic
-somewhat silent by default
-\family default
-\series bold
-\shape default
- */
-\series default
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-static const struct
-\series default
- HXoption options_table
-\series bold
-[]
-\series default
- = {
-\begin_inset Newline newline
-\end_inset
-
- {.sh = 'q', .type = HXTYPE_NONE | HXOPT_DEC, .q_int = &verbosity,
-\begin_inset Newline newline
-\end_inset
-
- .help = "Reduce verbosity"},
-\begin_inset Newline newline
-\end_inset
-
- {.sh = 'v', .type = HXTYPE_NONE | HXOPT_INC, .q_int = &verbosity,
-\begin_inset Newline newline
-\end_inset
-
- .help = "Increase verbosity"},
-\begin_inset Newline newline
-\end_inset
-
- HXOPT_TABLEEND,
-\begin_inset Newline newline
-\end_inset
-
-};
-\end_layout
-
-\begin_layout Standard
-This sample option table makes it possible to turn the verbosity of the
- program up or down, depending on whether the user specified
-\family typewriter
--q
-\family default
- or
-\family typewriter
--v
-\family default
-.
- By passing multiple
-\family typewriter
--v
-\family default
- flags, the verbosity can be turned up even more.
- The range depends on the
-\begin_inset Quotes eld
-\end_inset
-
-
-\family typewriter
-int
-\family default
-
-\begin_inset Quotes erd
-\end_inset
-
- data type for your particular platform and compiler; if you want to have
- the verbosity capped at a specific level, you will need to use an extra
- callback:
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-static int
-\series default
- verbosity = 1;
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-static void
-\series default
- v_check(
-\series bold
-const struct
-\series default
- HXoptcb
-\series bold
-*
-\series default
-cbi)
-\begin_inset Newline newline
-\end_inset
-
-{
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-if
-\series default
- (verbosity < 0)
-\begin_inset Newline newline
-\end_inset
-
- verbosity = 0;
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-else if
-\series default
- (verbosity > 4)
-\begin_inset Newline newline
-\end_inset
-
- verbosity = 4;
-\begin_inset Newline newline
-\end_inset
-
-}
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-static const struct
-\series default
- HXoption options_table
-\series bold
-[]
-\series default
- = {
-\begin_inset Newline newline
-\end_inset
-
- {.sh = 'q', .type = HXTYPE_NONE | HXOPT_DEC, .q_int = &verbosity,
-\begin_inset Newline newline
-\end_inset
-
- .cb = v_check, .help = "Lower verbosity"},
-\begin_inset Newline newline
-\end_inset
-
- {.sh = 'v', .type = HXTYPE_NONE | HXOPT_INC, .q_int = &verbosity,
-\begin_inset Newline newline
-\end_inset
-
- .cb = v_check, .help = "Raise verbosity"},
-\begin_inset Newline newline
-\end_inset
-
- HXOPT_TABLEEND,
-\begin_inset Newline newline
-\end_inset
-
-};
-\end_layout
-
-\begin_layout Subsubsection
-Mask operations
-\begin_inset CommandInset label
-LatexCommand label
-name "subsec:option-example-mask"
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-/*
-\family roman
-\series default
-\shape italic
-run on all CPU cores by default
-\family default
-\series bold
-\shape default
- *
-\series default
-/
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-static unsigned int
-\series default
- cpu_mask = ~0U
-\series bold
-;
-\begin_inset Newline newline
-\end_inset
-
-/*
-\family roman
-\series default
-\shape italic
-use no network connections by default
-\family default
-\shape default
-
-\series bold
-*/
-\begin_inset Newline newline
-\end_inset
-
-static unsigned int
-\series default
- net_mask = 0;
-\series bold
-
-\begin_inset Newline newline
-\end_inset
-
-static struct
-\series default
- HXoption options_table
-\series bold
-[]
-\series default
- = {
-\begin_inset Newline newline
-\end_inset
-
- {.sh = 'c', .type = HXTYPE_UINT | HXOPT_NOT | HXOPT_AND,
-\begin_inset Newline newline
-\end_inset
-
- .q_uint = &cpu_mask,
-\begin_inset Newline newline
-\end_inset
-
- .help = "Mask of cores to exclude", .htyp = "cpu_mask"},
-\begin_inset Newline newline
-\end_inset
-
- {.sh = 'n', .type = HXTYPE_UINT | HXOPT_OR, .q_uint = &net_mask,
-\end_layout
-
-\begin_layout LyX-Code
- .help = "Mask of network channels to additionally use",
-\begin_inset Newline newline
-\end_inset
-
- .htyp = "channel_mask"},
-\begin_inset Newline newline
-\end_inset
-
- HXOPT_TABLEEND,
-\begin_inset Newline newline
-\end_inset
-
-};
-\end_layout
-
-\begin_layout Standard
-What this options table does is
-\family typewriter
-cpu_mask &= ~x
-\family default
- and
-\family typewriter
-net_mask |= y
-\family default
-, the classic operations of clearing and setting bits.
-\end_layout
-
-\begin_layout Subsubsection
-Support for non-standard actions
-\begin_inset CommandInset label
-LatexCommand label
-name "subsec:option-example-cb"
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-Supporting additional types or custom storage formats is easy, by simply
- using
-\family typewriter
-HXTYPE_\SpecialChar softhyphen
-STRING
-\family default
-,
-\family typewriter
-NULL
-\family default
- as the data pointer (usually by not specifying it at all), the pointer
- to your data in the user-specified pointer
-\family typewriter
-uptr
-\family default
-, and the callback function in
-\family typewriter
-cb
-\family default
-.
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-struct
-\series default
- fixed_point {
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-int
-\series default
- integral;
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-unsigned int
-\series default
- fraction;
-\begin_inset Newline newline
-\end_inset
-
-};
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-static struct
-\series default
- fixed_point number;
-\end_layout
-
-\begin_layout LyX-Code
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-static void
-\series default
- fixed_point_parse
-\series bold
-(const struct
-\series default
- HXoptcb
-\series bold
-
-\series default
-*cbi)
-\begin_inset Newline newline
-\end_inset
-
-{
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-char *
-\series default
-end;
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
- number.integral = strtol(cbi->data, &end, 0);
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-if
-\series default
- (*end == '
-\backslash
-0')
-\begin_inset Newline newline
-\end_inset
-
- number.fraction = 0;
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-else if
-\series default
- (*end == '.')
-\begin_inset Newline newline
-\end_inset
-
- number.fraction = strtoul(end + 1, NULL, 0);
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-else
-\series default
-
-\begin_inset Newline newline
-\end_inset
-
- fprintf(stderr, "Illegal input.
-\backslash
-n");
-\begin_inset Newline newline
-\end_inset
-
-}
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-
-\begin_inset Newline newline
-\end_inset
-
-static const struct
-\series default
- HXoption options_table
-\series bold
-[]
-\series default
- = {
-\begin_inset Newline newline
-\end_inset
-
- {.sh = 'n', .type = HXTYPE_STRING, .cb = fixed_point_parse,
-\begin_inset Newline newline
-\end_inset
-
- .uptr = &number, .help = "Do this or that",
-\begin_inset Newline newline
-\end_inset
-
- HXOPT_TABLEEND,
-\end_layout
-
-\begin_layout LyX-Code
-};
-\end_layout
-
-\begin_layout Subsubsection
-Chained argument processing
-\begin_inset CommandInset label
-LatexCommand label
-name "subsec:option-example-chained"
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-On the first run, only
-\family typewriter
---cake
-\family default
- and
-\family typewriter
---fruit
-\family default
- is considered, which is then used to select the next set of accepted options.
- Note that
-\family typewriter
-HXOPT_\SpecialChar softhyphen
-DESTROY_\SpecialChar softhyphen
-OLD
-\family default
- is used here, which causes the argv that is produced by the first invocation
- of
-\family typewriter
-HX_getopt
-\family default
- in the
-\family typewriter
-get_options
-\family default
- function to be freed as it gets replaced by a new argv again by
-\family typewriter
-HX_getopt
-\family default
- in
-\family typewriter
-get_cakes
-\family default
-\SpecialChar breakableslash
-
-\family typewriter
-get_fruit
-\family default
-.
-
-\family typewriter
-HXOPT_\SpecialChar softhyphen
-DESTROY_\SpecialChar softhyphen
-OLD
-\family default
- is however
-\shape italic
-not
-\shape default
- specified in the first invocation, because the initial argv resides on
- the stack and cannot be freed.
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-static bool
-\series default
- get_cakes(
-\series bold
-int *
-\series default
-argc,
-\series bold
-const char ***
-\series default
-argv)
-\begin_inset Newline newline
-\end_inset
-
-{
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-struct
-\series default
- HXoption option_table
-\series bold
-[]
-\series default
- = {
-\begin_inset Newline newline
-\end_inset
-
- ...
-\begin_inset Newline newline
-\end_inset
-
- };
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-return
-\series default
- HX_getopt(cake_table, argc, argv,
-\begin_inset Newline newline
-\end_inset
-
- HXOPT_USAGEONERR | HXOPT_DESTROY_OLD) == HXOPT_ERR_SUCCESS;
-\begin_inset Newline newline
-\end_inset
-
-}
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-static bool
-\series default
- get_fruit(
-\series bold
-int *
-\series default
-argc,
-\series bold
-const char ***
-\series default
-argv)
-\begin_inset Newline newline
-\end_inset
-
-{
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-struct
-\series default
- HXoption fruit_table
-\series bold
-[]
-\series default
- = {
-\begin_inset Newline newline
-\end_inset
-
- ...
-\begin_inset Newline newline
-\end_inset
-
- };
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-return
-\series default
- HX_getopt(fruit_table, argc, argv,
-\begin_inset Newline newline
-\end_inset
-
- HXOPT_USAGEONERR | HXOPT_DESTROY_OLD) == HXOPT_ERR_SUCCESS;
-\begin_inset Newline newline
-\end_inset
-
-}
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-static bool
-\series default
- get_options(
-\series bold
-int *
-\series default
-argc,
-\series bold
-const char ***
-\series default
-argv)
-\begin_inset Newline newline
-\end_inset
-
-{
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-int
-\series default
- cake = 0, fruit = 0;
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-struct
-\series default
- HXoption option_table
-\series bold
-[]
-\series default
- = {
-\begin_inset Newline newline
-\end_inset
-
- {.ln = "cake", .type = HXTYPE_NONE, .ptr = &cake},
-\begin_inset Newline newline
-\end_inset
-
- {.ln = "fruit", .type = HXTYPE_NONE, .ptr = &fruit},
-\begin_inset Newline newline
-\end_inset
-
- HXOPT_TABLEEND,
-\begin_inset Newline newline
-\end_inset
-
- };
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-if
-\series default
- (HX_getopt(option_table, argc, argv, HXOPT_PTHRU) !=
-\begin_inset Newline newline
-\end_inset
-
- HXOPT_ERR_SUCCESS)
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-return
-\series default
- false;
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-if
-\series default
- (cake)
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-return
-\series default
- get_cakes(argc, argv);
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-else if
-\series default
- (fruit)
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-return
-\series default
- get_fruit(argc, argv);
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-return
-\series default
- false;
-\begin_inset Newline newline
-\end_inset
-
-}
-\end_layout
-
-\begin_layout Standard
-\begin_inset Newpage clearpage
-\end_inset
-
-
-\end_layout
-
-\begin_layout Section
-Shell-style configuration file parser
-\begin_inset CommandInset label
-LatexCommand label
-name "sec:shconf"
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-libHX provides functions to read shell-style configuration files.
- Such files are common, for example, in
-\family typewriter
-/etc/sysconfig
-\family default
- on Linux systems.
- The format is pretty basic; it only knows about
-\begin_inset Quotes eld
-\end_inset
-
-
-\family typewriter
-key=value
-\family default
-
-\begin_inset Quotes erd
-\end_inset
-
- pairs and does not even have sections like INI files.
- Not relying on any features however makes them quite interchangable as
- the syntax is accepted by Unix Shells.
-\end_layout
-
-\begin_layout Standard
-Lines beginning with a hash mark (
-\family typewriter
-#
-\family default
-) are ignored, as are empty lines and unrecognized keys.
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-# Minimum / maximum values for automatic UID selection
-\series default
-
-\begin_inset Newline newline
-\end_inset
-
-UID_MIN=100
-\begin_inset Newline newline
-\end_inset
-
-UID_MAX=65000
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-# Home directory base
-\series default
-
-\begin_inset Newline newline
-\end_inset
-
-HOME="/home"
-\begin_inset Newline newline
-\end_inset
-
-#HOME="/export/home"
-\end_layout
-
-\begin_layout Standard
-Any form of variable or parameter substitution or expansion is highly implementa
-tion specific, and is not supported in libHX's reader.
- Even Shell users should not rely on it as you never know in which context
- the configuration files are evaluated.
- Still, you will have to escape specific sequences like you would need to
- in Shell.
- The use of single quotes is acceptable.
- That means:
-\end_layout
-
-\begin_layout LyX-Code
-AMOUNT="US
-\backslash
-$5"
-\begin_inset Newline newline
-\end_inset
-
-AMOUNT='US$5'
-\end_layout
-
-\begin_layout Subsection
-Synopsis
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-#include
-\series default
- <libHX/option.h>
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-libHX/option.h
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-int
-\series default
- HX_shconfig(
-\series bold
-const char *
-\series default
-file,
-\series bold
-const struct
-\series default
- HXoption
-\series bold
-*
-\series default
-table);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HX_shconfig
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-int
-\series default
- HX_shconfig_pv(
-\series bold
-const char **
-\series default
-path_vec,
-\series bold
-const char *
-\series default
-file,
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-const struct
-\series default
- HXoption
-\series bold
-*
-\series default
-table,
-\series bold
-unsigned int
-\series default
- flags);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HX_shconfig_pv
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-struct
-\series default
- HXmap
-\series bold
-*
-\series default
-HX_shconfig_map(
-\series bold
-const char *
-\series default
-file);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HX_shconfig_map
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-The shconfig parser reuses
-\family typewriter
-struct HXoption
-\family default
- that fits very well in specifying name-pointer associations.
-
-\family typewriter
-HX_shconfig
-\family default
- will read the given file using the key-to-pointer mappings from the table
- to store the variable contents.
- Of
-\family typewriter
-struct HXoption
-\family default
-, described in section
-\begin_inset space ~
-\end_inset
-
-
-\begin_inset CommandInset ref
-LatexCommand ref
-reference "subsec:option-synopsis"
-
-\end_inset
-
-, only the
-\begin_inset Quotes eld
-\end_inset
-
-
-\family typewriter
-ln
-\family default
-
-\begin_inset Quotes erd
-\end_inset
-
-,
-\begin_inset Quotes eld
-\end_inset
-
-
-\family typewriter
-type
-\family default
-
-\begin_inset Quotes erd
-\end_inset
-
- and
-\begin_inset Quotes eld
-\end_inset
-
-
-\family typewriter
-ptr
-\family default
-
-\begin_inset Quotes erd
-\end_inset
-
- fields are used.
- The list of accepted types is described in section
-\begin_inset space ~
-\end_inset
-
-
-\begin_inset CommandInset ref
-LatexCommand ref
-reference "subsec:option-types"
-
-\end_inset
-
-.
-\end_layout
-
-\begin_layout Standard
-To parse a file, call
-\family typewriter
-HX_shconfig
-\family default
- function with the corresponding parameters.
- If you want to read configuration files from different paths, i.
-\begin_inset space \thinspace{}
-\end_inset
-
-e.
-\begin_inset space \space{}
-\end_inset
-
-to build up on default values, you can use
-\family typewriter
-HX_shconfig_pv
-\family default
-
-\begin_inset Foot
-status open
-
-\begin_layout Plain Layout
-pv = path vector
-\end_layout
-
-\end_inset
-
-, which is a variant for reading a file from multiple locations.
- Its purpose is to facilitate reading system-wide settings which are then
- overriden by a file in the users home directory, for example (per-setting-overr
-ide).
- It is also possible to do per-file-override, that is, a file in the home
- directory has higher precedence than a system-wide one in such a way that
- the system-wide configuration file is not even read.
- This is accomplished by traversing the paths in the
-\begin_inset Quotes eld
-\end_inset
-
-other
-\begin_inset Quotes erd
-\end_inset
-
- direction (actually you have to turn the array around) and stopping at
- the first existing file by use of the
-\family typewriter
-SHCONF_\SpecialChar softhyphen
-ONE
-\family default
- flag.
-\end_layout
-
-\begin_layout Standard
-
-\family typewriter
-HX_shconfig_map
-\family default
- will return all entries from the file in a HXmap, usable for parsing arbitrary
- keys without having to specify any static key table.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-SHCONF_ONE
-\series medium
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\series medium
-SHCONF_ONE
-\end_layout
-
-\end_inset
-
-
-\family default
-\series default
- Parsing files will stop after one file has been successfully parsed.
- This allows for a
-\begin_inset Quotes eld
-\end_inset
-
-personal overrides system config
-\begin_inset Quotes erd
-\end_inset
-
- style.
-\end_layout
-
-\begin_layout Standard
-The call to
-\family typewriter
-HX_shconfig
-\family default
- will either return >0 for success, 0 for no success (actually, this is
- never returned) and
-\family typewriter
--errno
-\family default
- for an error.
-\end_layout
-
-\begin_layout Subsection
-Example
-\end_layout
-
-\begin_layout Subsubsection
-Per-setting-override
-\end_layout
-
-\begin_layout Standard
-This example sources key-value pairs from a configuration file in a system
- location (
-\family typewriter
-/etc
-\family default
-) first, before overriding specific keys with new values from the file in
- the home directory.
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-long
-\series default
- uid_min, uid_max;
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-char *
-\series default
-passwd_file;
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-struct
-\series default
- HXoption options_table
-\series bold
-[]
-\series default
- = {
-\begin_inset Newline newline
-\end_inset
-
- {.ln = "UID_MIN", .type = HXTYPE_LONG, .ptr = &uid_min},
-\begin_inset Newline newline
-\end_inset
-
- {.ln = "UID_MAX", .type = HXTYPE_LONG, .ptr = &uid_max},
-\begin_inset Newline newline
-\end_inset
-
- {.ln = "PWD_FILE", .type = HXTYPE_STRING, .ptr = &passwd_file},
-\begin_inset Newline newline
-\end_inset
-
- HXOPT_TABLEEND,
-\begin_inset Newline newline
-\end_inset
-
-};
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-const char *
-\series default
-home = getenv("HOME");
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-const char *
-\series default
-paths
-\series bold
-[]
-\series default
- = {"/etc", home, NULL};
-\begin_inset Newline newline
-\end_inset
-
-HX_shconfig(paths, "test.cf", options_table, 0);
-\end_layout
-
-\begin_layout Subsubsection
-Per-file-override
-\end_layout
-
-\begin_layout Standard
-This particular example reads from the file in the home directory first
- (if it exists), but stops after it has been successfull, so any subsequent
- locations listed in the
-\family typewriter
-paths
-\family default
- variable are not read.
- This has the effect that the file from the home directory has the highest
- priority too like in the previous example, but without any keys from the
- system files.
- Note the
-\family typewriter
-SHCONF_ONE
-\family default
- flag.
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-const char *
-\series default
-home = getenv("HOME");
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-const char *
-\series default
-paths
-\series bold
-[]
-\series default
- = {home, "/usr/local/etc", "/etc", NULL};
-\begin_inset Newline newline
-\end_inset
-
-HX_shconfig_pv(paths, "test.cf", options_table, SHCONF_ONE);
-\end_layout
-
-\begin_layout Standard
-\begin_inset Newpage clearpage
-\end_inset
-
-
-\end_layout
-
-\begin_layout Part
-Systems-related components
-\end_layout
-
-\begin_layout Section
-Random numbers
-\begin_inset CommandInset label
-LatexCommand label
-name "sec:random"
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Subsection
-Function overview
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-#include
-\series default
- <libHX/misc.h>
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-libHX/misc.h
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-int
-\series default
- HX_rand(
-\series bold
-void
-\series default
-);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HX_rand
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-unsigned int
-\series default
- HX_irand(
-\series bold
-unsigned int
-\series default
- min,
-\series bold
-unsigned int
-\series default
- max);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\size normal
-\color none
-HX_irand
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-double
-\series default
- HX_drand(
-\series bold
-double
-\series default
- min,
-\series bold
-double
-\series default
- max);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HX_drand
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HX_rand
-\family default
- Retrieve the next random number.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HX_irand
-\family default
- Retrieve the next random number and fold it so that
-\begin_inset Formula $\textit{min}\le n<\textit{max}$
-\end_inset
-
-, where min and max are unsigned integers.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HX_drand
-\family default
- Retrieve the next random number and fold it so that
-\begin_inset Formula $\textit{min}\le n<\textit{max}$
-\end_inset
-
-, where min and max are double-precision floating point numbers.
-\end_layout
-
-\begin_layout Subsection
-Implementation information
-\end_layout
-
-\begin_layout Standard
-On systems that provide operating system-level random number generators,
- predominantly Linux and Unix-alikes such as BSD and Solaris, these will
- be used when they are available and random numbers are requested through
-
-\family typewriter
-HX_rand
-\family default
- or
-\family typewriter
-HX_irand
-\family default
-.
-\end_layout
-
-\begin_layout Standard
-On Linux, Solaris and the BSDs, this is
-\family typewriter
-/dev/urandom
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-/dev/urandom
-\end_layout
-
-\end_inset
-
-.
-\end_layout
-
-\begin_layout Standard
-If no random number generating device is available (and libHX configured
- to use it), it will fall back to using the libc's
-\family typewriter
-rand
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-rand
-\end_layout
-
-\end_inset
-
- function.
- If libc is selected for random number generation,
-\family typewriter
-srand
-\family default
- will be called on library initialization with what is believed to be good
- defaults
-\begin_inset space ~
-\end_inset
-
-— usually this will be before a program's
-\family typewriter
-main
-\family default
- function with normal linking, but may actually happen later when used with
-
-\family typewriter
-dlopen
-\family default
-.
- The initial seed would be the current microtime when
-\family typewriter
-gettimeofday
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-gettimeofday
-\end_layout
-
-\end_inset
-
-
-\family default
- is available, or just the seconds with
-\family typewriter
-time
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-time
-\end_layout
-
-\end_inset
-
-.
- To counter the problem of different programs potentially using the same
- seed within a time window of a second due to the limited granularity of
- standard
-\family typewriter
-time
-\family default
-, the seed is augmented by process ID and parent process ID where available.
-\end_layout
-
-\begin_layout Standard
-
-\family typewriter
-/dev/random
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-/dev/random
-\end_layout
-
-\end_inset
-
-
-\family default
- is not used on Linux because it may block during read, and
-\family typewriter
-/dev/urandom
-\family default
- is just as good when there is entropy available.
- If you need definitive PRNG
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-PRNG
-\end_layout
-
-\end_inset
-
- security, perhaps use one from a crypto suite such as OpenSSL.
-\end_layout
-
-\begin_layout Standard
-\begin_inset Newpage clearpage
-\end_inset
-
-
-\end_layout
-
-\begin_layout Section
-Process management
-\begin_inset CommandInset label
-LatexCommand label
-name "sec:proc"
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-The process code is experimental at this stage (just moved from the pam_mount
- codebase).
- As it also relies on the POSIX functions
-\family typewriter
-fork
-\family default
-,
-\family typewriter
-execv
-\family default
-,
-\family typewriter
-execvp
-\family default
- and
-\family typewriter
-pipe
-\family default
-(2), so it may not be available everywhere.
- Where this is the case, the functions will return
-\family typewriter
--ENOSYS
-\family default
-.
-\end_layout
-
-\begin_layout Subsection
-Process metadata structure
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-#include
-\series default
- <libHX/proc.h>
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-libHX/proc.h
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-struct
-\series default
- HXproc {
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-const struct
-\series default
- HXproc_ops
-\series bold
-*
-\series default
-p_ops;
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-void *
-\series default
-p_data;
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-unsigned int
-\series default
- p_flags;
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-/*
-\family roman
-\series default
-\shape italic
-Following members should only be read
-\family default
-\series bold
-\shape default
- */
-\series default
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-int
-\series default
- p_stdin, p_stdout, p_stderr;
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-int
-\series default
- p_pid;
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-char
-\series default
- p_status;
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-bool
-\series default
- p_exited, p_terminated;
-\begin_inset Newline newline
-\end_inset
-
-};
-\end_layout
-
-\begin_layout Standard
-When creating a new process with the intent of running it asynchronously
- (using
-\family typewriter
-HXproc_\SpecialChar softhyphen
-run_\SpecialChar softhyphen
-async
-\family default
-), the first three fields must be filled in by the user.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-p_ops
-\family default
- A table of callbacks, generally used for setting and/or restoring signals
- before/after execution.
- This member may be
-\family typewriter
-NULL
-\family default
-.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-p_data
-\family default
- Free pointer for the user to supply.
- Will be passed to the callback functions when they are invoked.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-p_flags
-\family default
- Process creation flags, see below.
-\end_layout
-
-\begin_layout Standard
-After the subprocess has been started,
-\family typewriter
-HXproc_run_async
-\family default
- will have filled in some fields:
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-p_stdin
-\family default
- If
-\family typewriter
-HXPROC_STDIN
-\family default
- was specified in
-\family typewriter
-p_flags
-\family default
-,
-\family typewriter
-p_stdin
-\family default
- will be assigned the write side file descriptor of the subprocess's to-be
- stdin.
- The subprocess will get the read side file descriptor in this member.
- This is so that the correct fd is used in when
-\family typewriter
-p_ops->p_postfork
-\family default
- is called.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-p_stdout
-\family default
- If
-\family typewriter
-HXPROC_STDOUT
-\family default
- is specified in
-\family typewriter
-p_flags
-\family default
-,
-\family typewriter
-p_stdout
-\family default
- will be assigned the read side file descriptor of the subprocess's to-be
- stdout.
- The subprocess will get the write side file descriptor in this member.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-p_stderr
-\family default
- If
-\family typewriter
-HXPROC_STDERR
-\family default
- is specified in
-\family typewriter
-p_flags
-\family default
-,
-\family typewriter
-p_stderr
-\family default
- will be assigned the read side file descriptor of the subprocess's to-be
- stderr, and the subprocess will get the write side fd.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-p_pid
-\family default
- The process ID of the spawned process.
-\end_layout
-
-\begin_layout Standard
-Upon calling
-\family typewriter
-HXproc_wait
-\family default
-, further fields will have been filled when the function returns:
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-p_exited
-\family default
- Whether the process exited normally (cf.
-\begin_inset space \space{}
-\end_inset
-
-signalled\SpecialChar breakableslash
-terminated).
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-p_terminated
-\family default
- Whether the process was terminated (signalled).
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-p_status
-\family default
- The exit status of the process or the termination signal.
-\end_layout
-
-\begin_layout Subsubsection
-Flags
-\begin_inset CommandInset label
-LatexCommand label
-name "subsec:proc-pflags"
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-Possible values for the
-\family typewriter
-p_flags
-\family default
- member are:
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXPROC_STDIN
-\series medium
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXPROC_STDIN
-\end_layout
-
-\end_inset
-
-
-\family default
-\series default
- The subprocess's stdin file descriptor shall be connected to the master
- program, that is, not inherit the stdin of the master.
- Cannot be used for
-\family typewriter
-HXproc_\SpecialChar softhyphen
-run_\SpecialChar softhyphen
-sync
-\family default
- (because there would be no one to provide data in a sync operation).
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXPROC_STDOUT
-\series medium
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\series medium
-HXPROC_STDOUT
-\end_layout
-
-\end_inset
-
-
-\family default
-\series default
- Connect the stdout file descriptor of the subprocess with the master.
- Cannot be used for
-\family typewriter
-HXproc_run_sync
-\family default
-.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXPROC_STDERR
-\series medium
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\series medium
-HXPROC_STDERR
-\end_layout
-
-\end_inset
-
-
-\family default
-\series default
- Connect the stderr file descriptor of the subprocess with the master.
- Cannot be used for
-\family typewriter
-HXproc_run_sync
-\family default
-.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXPROC_NULL_STDIN
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXPROC_NULL_STDIN
-\end_layout
-
-\end_inset
-
- The subprocess's stdin file descriptor shall be connected to
-\family typewriter
-/dev\SpecialChar breakableslash
-null
-\family default
-.
-
-\family typewriter
-HXPROC_\SpecialChar softhyphen
-STDIN
-\family default
- and
-\family typewriter
-HXPROC_\SpecialChar softhyphen
-NULL_\SpecialChar softhyphen
-STDIN
-\family default
- are mutually exclusive.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXPROC_NULL_STDOUT
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXPROC_NULL_STDOUT
-\end_layout
-
-\end_inset
-
- Connect the stdout file descriptor of the subprocess to
-\family typewriter
-/dev\SpecialChar breakableslash
-null
-\family default
-, thereby essentially discarding its output.
-
-\family typewriter
-HXPROC_\SpecialChar softhyphen
-STDOUT
-\family default
- and
-\family typewriter
-HXPROC_\SpecialChar softhyphen
-NULL_\SpecialChar softhyphen
-STDOUT
-\family default
- are mutuall exclusive.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXPROC_NULL_STDERR
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXPROC_NULL_STDERR
-\end_layout
-
-\end_inset
-
- Connect the stderr file descriptor of the subprocess to
-\family typewriter
-/dev\SpecialChar breakableslash
-null
-\family default
-, thereby essentially discarding its output.
-
-\family typewriter
-HXPROC_\SpecialChar softhyphen
-STDERR
-\family default
- and
-\family typewriter
-HXPROC_\SpecialChar softhyphen
-NULL_\SpecialChar softhyphen
-STDERR
-\family default
- are mutually exclusive.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXPROC_VERBOSE
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXPROC_VERBOSE
-\end_layout
-
-\end_inset
-
- Have the subprocess print an error message to stderr if exec'ing returned
- an error.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXPROC_A0
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXPROC_A0
-\end_layout
-
-\end_inset
-
-
-\family typewriter
-argv[0]
-\family default
- refers to program file, while
-\family typewriter
-argv[1]
-\family default
- to the program invocation name, with
-\family typewriter
-argv[2]
-\family default
- being the arguments.
- Without this flag,
-\family typewriter
-argv[0]
-\family default
- will be both the program file and program invocation name, and arguments
- begin at
-\family typewriter
-argv[1]
-\family default
-.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXPROC_EXECV
-\family default
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HXPROC_EXECV
-\end_layout
-
-\end_inset
-
- Normally,
-\family typewriter
-execvp
-\family default
-(3)
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-execvp
-\end_layout
-
-\end_inset
-
- will be used which scans
-\family typewriter
-$PATH
-\family default
- for the program.
- Use this flag to use
-\family typewriter
-execv
-\family default
-(3)
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-execv
-\end_layout
-
-\end_inset
-
- instead, which will not do such thing.
-\end_layout
-
-\begin_layout Subsection
-Callbacks
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-#include
-\series default
- <libHX/proc.h>
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-struct
-\series default
- HXproc_ops {
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-void (*
-\series default
-p_prefork
-\series bold
-)
-\series default
-(
-\series bold
-void *
-\series default
-);
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-void (*
-\series default
-p_postfork
-\series bold
-)
-\series default
-(
-\series bold
-void *
-\series default
-);
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-void (*
-\series default
-p_complete
-\series bold
-)
-\series default
-(
-\series bold
-void *
-\series default
-);
-\begin_inset Newline newline
-\end_inset
-
-};
-\end_layout
-
-\begin_layout Standard
-
-\family typewriter
-struct HXproc_ops
-\family default
- provides a way to run user-specified functions just before the fork, after,
- and when the process has been waited for.
- They can be used to set and/or restore signals as needed, for example.
- The function pointers can be
-\family typewriter
-NULL
-\family default
-.
- The
-\family typewriter
-p_data
-\family default
- member is passed as an argument.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-p_prefork
-\family default
- Run immediately before calling
-\family typewriter
-fork
-\family default
-(2).
- This is useful, for taking any action regarding signals, like setting
-\family typewriter
-SIGCHLD
-\family default
- to
-\family typewriter
-SIG_DFL
-\family default
-, or
-\family typewriter
-SIGPIPE
-\family default
- to
-\family typewriter
-SIG_IGN
-\family default
-, for example.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-p_postfork
-\family default
- Run in the subprocess (and only there) after forking.
- Useful to do a
-\family typewriter
-setuid
-\family default
-(2) or other change in privilege level.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-p_complete
-\family default
- Run in
-\family typewriter
-HXproc_wait
-\family default
- when the process has been waited for.
- Useful to restore the signal handler(s).
-\end_layout
-
-\begin_layout Subsection
-Process control
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-#include
-\series default
- <libHX/proc.h>
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-
-\begin_inset Newline newline
-\end_inset
-
-int
-\series default
- HXproc_run_async(
-\series bold
-const char *const *
-\series default
-argv,
-\series bold
-struct
-\series default
- HXproc
-\series bold
-*
-\series default
-proc);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\size normal
-\color none
-HXproc_run_async
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-int
-\series default
- HXproc_run_sync(
-\series bold
-const char *const *
-\series default
-argv,
-\series bold
-unsigned int
-\series default
- flags);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\size normal
-\color none
-HXproc_run_sync
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-int
-\series default
- HXproc_wait(
-\series bold
-struct
-\series default
- HXproc
-\series bold
-*
-\series default
-proc);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\size normal
-\color none
-HXproc_wait
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXproc_run_async
-\family default
- Start a subprocess according to the parameters in
-\family typewriter
-proc
-\family default
-.
- Returns a negative errno code if something went wrong, or positive non-zero
- on success.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXproc_run_sync
-\family default
- Start a subprocess synchronously, similar to calling
-\family typewriter
-system
-\family default
-(3)
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-system
-\end_layout
-
-\end_inset
-
-, but with the luxury of being able to specify arguments as separate strings
- (via argv) rather than one big command line that is run through the shell.
-
-\family typewriter
-flags
-\family default
- is a value composed of the HXproc flags mentioned above in section
-\begin_inset space ~
-\end_inset
-
-
-\begin_inset CommandInset ref
-LatexCommand ref
-reference "subsec:proc-pflags"
-
-\end_inset
-
-.
-
-\family typewriter
-HXPROC_STDIN
-\family default
-,
-\family typewriter
-HXPROC_STDOUT
-\family default
- and
-\family typewriter
-HXPROC_STDERR
-\family default
- are ignored because there would be no one in a synchronous execution that
- could supply data to these file descriptors or read from them
-\begin_inset Foot
-status open
-
-\begin_layout Plain Layout
-Even for threads, please just use the async model.
-\end_layout
-
-\end_inset
-
-.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-HXproc_wait
-\family default
- Wait for a subprocess to terminate, if it has not already.
- It will also retrieve the exit status of the process and store it in the
-
-\family typewriter
-struct HXproc
-\family default
-.
-\end_layout
-
-\begin_layout Standard
-Return value will be positive non-zero on success, or negative on error.
- Underlying system function's errors are returned, plus:
-\end_layout
-
-\begin_layout Description
-
-\family sans
-EINVAL
-\family default
- Flags were not accepted.
-\end_layout
-
-\begin_layout Section
-Helper headers
-\end_layout
-
-\begin_layout Subsection
-ctype helpers
-\end_layout
-
-\begin_layout Standard
-Functions from the
-\family typewriter
-<ctype.h>
-\family default
- header, including, but not limited to,
-\family typewriter
-isalpha
-\family default
-,
-\family typewriter
-tolower
-\family default
-, and so forth, are defined to take an
-\begin_inset Quotes eld
-\end_inset
-
-
-\family typewriter
-int
-\family default
-
-\begin_inset Quotes erd
-\end_inset
-
- as first argument.
- Strings used in C programs are usually
-\begin_inset Quotes eld
-\end_inset
-
-
-\family typewriter
-char
-\begin_inset space ~
-\end_inset
-
-*
-\family default
-
-\begin_inset Quotes erd
-\end_inset
-
-, without any
-\begin_inset Quotes eld
-\end_inset
-
-
-\family typewriter
-signed
-\family default
-
-\begin_inset Quotes erd
-\end_inset
-
- or
-\begin_inset Quotes eld
-\end_inset
-
-
-\family typewriter
-unsigned
-\family default
-
-\begin_inset Quotes erd
-\end_inset
-
- qualifier.
- By a high-level view, which also matches daily common sense, characters
- (a.
-\begin_inset space \thinspace{}
-\end_inset
-
-k.
-\begin_inset space \thinspace{}
-\end_inset
-
-a.
-\begin_inset space \space{}
-\end_inset
-
-letters) have no notion of signedness
-\begin_inset space ~
-\end_inset
-
-— there is no
-\begin_inset Quotes eld
-\end_inset
-
-positive
-\begin_inset Quotes erd
-\end_inset
-
- or
-\begin_inset Quotes eld
-\end_inset
-
-negative
-\begin_inset Quotes erd
-\end_inset
-
-
-\begin_inset Quotes eld
-\end_inset
-
-A
-\begin_inset Quotes erd
-\end_inset
-
- in at least the Latin alphabet that is mapped into the ASCII set.
- In fact,
-\family typewriter
-char
-\begin_inset space ~
-\end_inset
-
-*
-\family default
- could either be
-\family typewriter
-signed char
-\begin_inset space ~
-\end_inset
-
-*
-\family default
- or
-\family typewriter
-unsigned char
-\begin_inset space ~
-\end_inset
-
-*
-\family default
-, depending on the compiler settings.
- Only when you start interpreting and using characters as a number does
- such become important.
-
-\end_layout
-
-\begin_layout Standard
-There come the problems.
- Characters are in the same class as numbers in C, that is, can be implicitly
- converted from or to a
-\begin_inset Quotes eld
-\end_inset
-
-number
-\begin_inset Quotes erd
-\end_inset
-
- (in this case, their ASCII code point) without causing a compiler warning.
- That may be practical in some cases, but is also a bit
-\begin_inset Quotes eld
-\end_inset
-
-unfortunate
-\begin_inset Quotes erd
-\end_inset
-
-.
- Characters, when interpreted as the 8-bit signed numeric quantity they
- are implicitly convertable to, run from 0 to 127 and \SpecialChar nobreakdash
-128 to \SpecialChar nobreakdash
-1.
- Since the
-\family typewriter
-isalpha
-\family default
- function and others from
-\family typewriter
-ctype.h
-\family default
- take a (signed)
-\family typewriter
-int
-\family default
- as argument means that values fed to
-\family typewriter
-isalpha
-\family default
- are sign-extended, preserving negative values.
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-/*
-\family roman
-\series default
-\shape italic
-
-\begin_inset Quotes eld
-\end_inset
-
-hyvää yötä
-\begin_inset Quotes erd
-\end_inset
-
-, UTF-8 encoded
-\family default
-\series bold
-\shape default
- */
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-const char
-\series default
-h
-\series bold
-[]
-\series default
- = {'h', 'y', 'v', 0xc3, 0xa4, 0xc3, 0xa4, ' ',
-\begin_inset Newline newline
-\end_inset
-
- 'y', 0xc3, 0xb6, 't', 0xc3, 0xa4};
-\end_layout
-
-\begin_layout Standard
-When you now pass
-\family typewriter
-h[3]
-\family default
- to
-\family typewriter
-isalpha
-\family default
- for example (regardless of whether doing so actually produces a meaningful
- result), the CPU is instructed to copy
-\begin_inset Quotes eld
-\end_inset
-
-0xc3
-\begin_inset Quotes erd
-\end_inset
-
- into a register and sign-extend it (because
-\begin_inset Quotes eld
-\end_inset
-
-char
-\begin_inset Quotes erd
-\end_inset
-
- is often
-\begin_inset Quotes eld
-\end_inset
-
-signed char
-\begin_inset Quotes erd
-\end_inset
-
-, see above), producing 0xffffffc3 (\SpecialChar nobreakdash
-61).
- But passing \SpecialChar nobreakdash
-61 is not what was intended.
-\end_layout
-
-\begin_layout Standard
-libHX's
-\family typewriter
-ctype_helper.h
-\family default
- therefore provides wrappers with a different function signature that uses
- zero extension (not sign extension) by means of using an
-\family typewriter
-unsigned
-\family default
- quantity.
- Currently this is
-\family typewriter
- unsigned char
-\family default
-, because
-\family typewriter
-isalpha
-\family default
-'s domain only goes from 0–255.
- The implication is that you cannot pass
-\family typewriter
-EOF
-\family default
- to
-\family typewriter
-HX_isalpha
-\family default
-.
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-#include
-\series default
- <libHX/ctype_helper.h>
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-libHX/ctype_helper.h
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-bool
-\series default
- HX_isalnum(
-\series bold
-unsigned char
-\series default
- c);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\size normal
-\color none
-HX_isalnum
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-bool
-\series default
- HX_isalpha(
-\series bold
-unsigned char
-\series default
- c);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\size normal
-\color none
-HX_isalpha
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-bool
-\series default
- HX_isdigit(
-\series bold
-unsigned char
-\series default
- c);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\size normal
-\color none
-HX_isdigit
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-bool
-\series default
- HX_islower(
-\series bold
-unsigned char
-\series default
- c);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\size normal
-\color none
-HX_islower
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-bool
-\series default
- HX_isprint(
-\series bold
-unsigned char
-\series default
- c);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\size normal
-\color none
-HX_isprint
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-bool
-\series default
- HX_isspace(
-\series bold
-unsigned char
-\series default
- c);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HX_isspace
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-bool
-\series default
- HX_isupper(
-\series bold
-unsigned char
-\series default
- c);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-HX_isupper
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-bool
-\series default
- HX_isxdigit(
-\series bold
-unsigned char
-\series default
- c);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\size normal
-\color none
-HX_isxdigit
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-unsigned char
-\series default
- HX_tolower(
-\series bold
-unsigned char
-\series default
- c);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\size normal
-\color none
-HX_tolower
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-unsigned char
-\series default
- HX_toupper(
-\series bold
-unsigned char
-\series default
- c);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\size normal
-\color none
-HX_toupper
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-The
-\family typewriter
-is*
-\family default
- functions also differ from ctype's in that they return
-\family typewriter
-bool
-\family default
- instead of
-\family typewriter
-int
-\family default
-.
- Not all functions from
-\family typewriter
-ctype.h
-\family default
- are present either;
-\family typewriter
-isascii
-\family default
-,
-\family typewriter
-isblank
-\family default
-,
-\family typewriter
-iscntrl
-\family default
-,
-\family typewriter
-isgraph
-\family default
-,
-\family typewriter
-ispunct
-\family default
- and
-\family typewriter
-isxdigit
-\family default
- have been omitted as the author has never needed them so far.
-\end_layout
-
-\begin_layout Subsection
-libxml2 helpers
-\end_layout
-
-\begin_layout Standard
-libxml2 uses an
-\begin_inset Quotes eld
-\end_inset
-
-
-\family typewriter
-xmlChar
-\family default
-
-\begin_inset Quotes erd
-\end_inset
-
- type as an underlying type for the strings that it reads and outputs.
-
-\family typewriter
-xmlChar
-\family default
- is typedef'ed to
-\family typewriter
-unsigned char
-\family default
- by libxml2, causing compiler warnings related to differing signedness whenever
- interacting with strings from the outside world, which are usually just
- a pointer to
-\family typewriter
-char
-\family default
-.
- Because casting would be a real chore,
-\family typewriter
-libxml_helper.h
-\family default
- will do it by providing some wrappers with better argument types.
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-#include
-\series default
- <libHX/libxml_helper.h>
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-libHX/libxml_helper.h
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-int
-\series default
- xml_strcmp(
-\series bold
-const
-\series default
- xmlChar
-\series bold
-*
-\series default
-a,
-\series bold
-const char *
-\series default
-b);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-xml_strcmp
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-int
-\series default
- xml_strcasecmp(
-\series bold
-const
-\series default
- xmlChar
-\series bold
-*
-\series default
-a,
-\series bold
-const char *
-\series default
-b);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-xml_strcasecmp
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-char *
-\series default
-xml_getprop(xmlNode
-\series bold
-*
-\series default
-node,
-\series bold
-const char *
-\series default
-attr);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-xml_getprop
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-char *xml_getnsprop(
-\series bold
-xmlNode *
-\series default
-node,
-\series bold
-const char *
-\series default
-nsprefix,
-\series bold
-const char *
-\series default
-attr);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-xml_getnsprop
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-xmlAttr
-\series bold
-*
-\series default
-xml_newprop(xmlNode
-\series bold
-*
-\series default
-node,
-\series bold
-const char *
-\series default
-attr);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-xml_newprop
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-xmlNode
-\series bold
-*
-\series default
-xml_newnode(xmlNode
-\series bold
-*
-\series default
-parent,
-\series bold
-const char *
-\series default
-name,
-\series bold
-const char *
-\series default
-value);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\size normal
-\color none
-xml_newnode
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-xmlAttr
-\series bold
-*
-\series default
-xml_setprop(xmlNode
-\series bold
-*
-\series default
-node,
-\series bold
-const char *
-\series default
-name,
-\series bold
-const char *
-\series default
-value);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-\size normal
-\color none
-xml_setprop
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-The functions map to
-\family typewriter
-strcmp
-\family default
-(3)
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-strcmp
-\end_layout
-
-\end_inset
-
-,
-\family typewriter
-strcasecmp
-\family default
-(3)
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-strcasecmp
-\end_layout
-
-\end_inset
-
-,
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-xmlGetProp
-\end_layout
-
-\end_inset
-
-
-\family typewriter
-xmlGetProp
-\family default
-,
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-xmlNewProp
-\end_layout
-
-\end_inset
-
-
-\family typewriter
-xmlNewProp
-\family default
-,
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-xmlNewTextNode
-\end_layout
-
-\end_inset
-
-
-\family typewriter
-xml\SpecialChar softhyphen
-New\SpecialChar softhyphen
-Text\SpecialChar softhyphen
-Node
-\family default
- and
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-xmlSetProp
-\end_layout
-
-\end_inset
-
-
-\family typewriter
-xml\SpecialChar softhyphen
-Set\SpecialChar softhyphen
-Prop
-\family default
-, respectively.
-\end_layout
-
-\begin_layout Standard
-
-\family typewriter
-xml_getnsprop
-\family default
- works similar to
-\family typewriter
-xmlGetNsProp
-\family default
-, but instead of taking a namespace URI, it does a lookup by namespace prefix.
- The argument order is also different compared to
-\family typewriter
-xmlGetNsProp
-\family default
-.
-\end_layout
-
-\begin_layout Subsection
-wxWidgets
-\end_layout
-
-\begin_layout LyX-Code
-
-\series bold
-#include
-\series default
- <libHX/wx_helper.hpp>
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-libHX/wx_helper.hpp
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Subsubsection
-Shortcut macros
-\end_layout
-
-\begin_layout Description
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-wxACV
-\end_layout
-
-\end_inset
-
-
-\family typewriter
-wxACV
-\family default
- Expands to
-\family typewriter
-
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-wxALIGN_CENTER_VERTICAL
-\end_layout
-
-\end_inset
-
-wxALIGN_CENTER_VERTICAL
-\end_layout
-
-\begin_layout Description
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-wxCDF
-\end_layout
-
-\end_inset
-
-
-\family typewriter
-wxCDF
-\family default
- Expands to a set of common dialog flags for
-\family typewriter
-wxDialog
-\family default
-s, which includes
-\family typewriter
-wxDEFAULT_\SpecialChar softhyphen
-FRAME_\SpecialChar softhyphen
-STYLE
-\family default
- and a flag such that the dialog does not create a new window in the task
- bar (
-\family typewriter
-wxFRAME_\SpecialChar softhyphen
-NO_\SpecialChar softhyphen
-TASKBAR
-\family default
-).
-\end_layout
-
-\begin_layout Description
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-wxDPOS
-\end_layout
-
-\end_inset
-
-
-\family typewriter
-wxDPOS
-\family default
- Expands to
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-wxDefaultPosition
-\end_layout
-
-\end_inset
-
-
-\family typewriter
-wxDefaultPosition
-\family default
-.
-\end_layout
-
-\begin_layout Description
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-wxDSIZE
-\end_layout
-
-\end_inset
-
-
-\family typewriter
-wxDSIZE
-\family default
- Expands to
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-wxDefaultSize
-\end_layout
-
-\end_inset
-
-
-\family typewriter
-wxDefaultSize
-\family default
-.
-\end_layout
-
-\begin_layout Description
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-wxDSPAN
-\end_layout
-
-\end_inset
-
-
-\family typewriter
-wxDSPAN
-\family default
- Expands to
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-wxDefaultSpan
-\end_layout
-
-\end_inset
-
-
-\family typewriter
-wxDefaultSpan
-\family default
-.
-\end_layout
-
-\begin_layout Subsubsection
-String conversion
-\end_layout
-
-\begin_layout LyX-Code
-wxString wxfu8(
-\series bold
-const char *
-\series default
-);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-wxfu8
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-wxString wxfv8(
-\series bold
-const char *
-\series default
-);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-wxfv8
-\end_layout
-
-\end_inset
-
-
-\begin_inset Newline newline
-\end_inset
-
-
-\series bold
-const char *
-\series default
-wxtu8(
-\series bold
-const
-\series default
- wxString
-\series bold
-&
-\series default
-);
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-wxtu8
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-wxfu8
-\family default
- Converts an UTF-8 string to a
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-wxString
-\end_layout
-
-\end_inset
-
-
-\family typewriter
-wxString
-\family default
- object.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-wxfv8
-\family default
- Converts an UTF-8 string to an entity usable by
-\begin_inset Index idx
-status open
-
-\begin_layout Plain Layout
-
-\family typewriter
-wxPrintf
-\end_layout
-
-\end_inset
-
-
-\family typewriter
-wxPrintf
-\family default
-.
-\end_layout
-
-\begin_layout Description
-
-\family typewriter
-wxtu8
-\family default
- Converts a wxString to a pointer to char usable by
-\family typewriter
-printf
-\family default
-.
- Note that the validity of the pointer is very limited and usually does
- not extend the statement in which it is used.
- Hence storing the pointer in a variable (
-\begin_inset Quotes eld
-\end_inset
-
-
-\family typewriter
-const char *p = wxtu8(s);
-\family default
-
-\begin_inset Quotes erd
-\end_inset
-
-) will make
-\family typewriter
-p
-\family default
- pointing to an invalid region as soon as the assignment is done.
-\end_layout
-
-\begin_layout Part
-\start_of_appendix
-Appendix
-\end_layout
-
-\begin_layout Standard
-\begin_inset CommandInset index_print
-LatexCommand printindex
-type "idx"
-name "Index"
-literal "true"
-
-\end_inset
-
-
-\end_layout
-
-\end_body
-\end_document
diff --git a/doc/libHX_Documentation.pdf b/doc/libHX_Documentation.pdf
deleted file mode 100644
index 673a851..0000000
--- a/doc/libHX_Documentation.pdf
+++ /dev/null
Binary files differ
diff --git a/doc/libHX_Documentation.rst b/doc/libHX_Documentation.rst
new file mode 100644
index 0000000..710e265
--- /dev/null
+++ b/doc/libHX_Documentation.rst
@@ -0,0 +1,142 @@
+===================
+libHX Documentation
+===================
+
+libHX collects many useful day-to-day functions, intended to reduce the amount
+of otherwise repeatedly open-coded instructions.
+
+Overview
+========
+
+* Maps (key-value pairs)
+
+ Originally created to provide a data structure like Perl's associative
+ arrays. Different map types and characteristics are available, such as
+ hash-based or the traditional rbtree.
+
+* Linked lists (Deques)
+
+ Double-ended queues, implemented as a doubly-linked list with sentinels, are
+ suitable for both providing stack and queue functionality.
+
+* Inline doubly-linked list, uncounted and counted
+
+ Light-weight linked lists as used in the Linux kernel.
+
+* Common string operations
+
+ ``basename``, ``chomp``, ``dirname``, ``getl``/``getline``, ``split``,
+ ``strlcat``/``strlcpy``, ``strlower``/``strupper``, ``str*trim``, ``strsep``,
+ etc.
+
+* Memory container, auto-sizing string operations
+
+ Scripting-like invocation for string handling — automatically doing
+ (re)allocations as needed.
+
+* String formatter (Format templates)
+
+ HXfmt is a template system for by-name variable expansion. It can be used to
+ substitute placeholders in format strings supplied by the user by appropriate
+ expanded values defined by the program.
+
+* Directory functions
+
+ Directory creation, traversal, removal, and file copying.
+
+* Option parsing
+
+ Table-/callback-based option parser that works similar to Perl's
+ Getopt::Long — no open-coding but a single “atomic” invocation.
+
+* Shell-style config parser
+
+ Configuration file reader for Shell-style “configuration” files
+ with key-value pairs, as usually foudn in ``/etc/sysconfig``.
+
+* Random number gathering
+
+ Convenient wrapper that uses kernel-provided RNG devices when
+ available.
+
+* External process invocation
+
+ Setting up pipes for the standard file descriptors for
+ sending/capturing data to/from a program.
+
+* a bit more beyond that ... Miscellaneous
+
+
+General reading
+===============
+
+* `Installation <install.rst>`_ (if you do not have a binray package from a
+ distro yet)
+* `History <history.rst>`_ remarks
+
+
+First things first
+==================
+
+Many functions are prefixed with ``HX_`` or ``HXsubsys_``, as are structures
+(sometimes without underscores, be sure to check the syntax and names), to
+avoid name clashes with possibly existing files. Functions that are not tied to
+a specific data structure such as most of the string functions use the
+subsystem-less prefix, ``HX_``. Functions from a clearly-defined subsystem,
+such as map or deque, augment the base prefix by a suffix, forming e.g.
+``HXmap_``.
+
+* `Library initialization <init.rst>`_
+
+
+Data structures
+===============
+
+* `Bitmaps <bitmaps.rst>`_
+* `Maps <maps.rst>`_
+* `Linked lists <linked_list.rst>`_
+* `Inline lists <inline_list.rst>`_
+* `Counted inline lists <inline_clist.rst>`_
+
+
+Strings and memory
+==================
+
+* `String operations <string_ops.rst>`_
+* `Memory containers <memory_container.rst>`_
+* `String formatter <string_formatter.rst>`_
+* Everything with `Files and directories <files_and_dirs.rst>`_
+
+
+Options and configuration files
+===============================
+
+* `Option parsing <option_parsing.rst>`_
+* `Shell-style config file parser <shconfig.rst>`_
+
+
+Systems-related components
+==========================
+
+* `Time functions <time_functions.rst>`_
+* `Random numbers <random_number.rst>`_
+* `Process functions <process_functions.rst>`_
+
+
+Miscellaneous
+=============
+
+* `Type-checking casts <typechecking_casts.rst>`_
+* `Helper headers <helper_headers.rst>`_ for other software
+* `Macros <macros.rst>`_
+* `Misc functions <misc_functions.rst>`_ that did not fit in any other category
+
+
+Resources
+=========
+
+As of this writing, the repository is located at
+
+* git://git.inai.de/libhx — clone URL
+
+* https://inai.de/projects/libhx/ — home page (and link to tarballs)
diff --git a/doc/linked_list.rst b/doc/linked_list.rst
new file mode 100644
index 0000000..accf7d4
--- /dev/null
+++ b/doc/linked_list.rst
@@ -0,0 +1,171 @@
+==================
+Doubly-linked list
+==================
+
+HXdeque is a data structure for a doubly-linked non-circular
+``NULL``-sentineled list. Despite being named a deque, which is short for
+double-ended queue, and which may be implemented using an array, HXdeque is in
+fact using a linked list to provide its deque functionality. Furthermore, a
+dedicated root structure and decidated node structures with indirect data
+referencing are used.
+
+
+Structural definition
+=====================
+
+.. code-block:: c
+
+ #include <libHX/deque.h>
+
+ struct HXdeque {
+ struct HXdeque_node *first, *last;
+ unsigned int items;
+ void *ptr;
+ };
+
+ struct HXdeque_node {
+ struct HXdeque_node *next, *prev;
+ struct HXdeque *parent;
+ void *ptr;
+ };
+
+The ``ptr`` member in ``struct HXdeque`` provides room for an arbitrary custom
+user-supplied pointer. items will reflect the number of elements in the list,
+and must not be modified. ``first`` and ``last`` provide entrypoints to the
+list's ends.
+
+``ptr`` within ``struct HXdeque_node`` is the pointer to the user's data. It
+may be modified and used at will by the user. See example section.
+
+
+Constructor, destructors
+========================
+
+.. code-block:: c
+
+ struct HXdeque *HXdeque_init(void);
+ void HXdeque_free(struct HXdeque *dq);
+ void HXdeque_genocide(struct HXdeque *dq);
+ void HXdeque_genocide2(struct HXdeque *dq, void (*xfree)(void *));
+ void **HXdeque_to_vec(struct HXdeque *dq, unsigned int *num);
+
+To allocate a new empty list, use ``HXdeque_init``. ``HXdeque_free`` will free
+the list (including all nodes owned by the list), but not the data pointers.
+
+``HXdeque_genocide`` is a variant that will not only destroy the list, but also
+calls a freeing function ``free``() on all stored data pointers. This puts a
+number of restrictions on the characteristics of the list: all data pointers
+must have been obtained with ``malloc``, ``calloc`` or ``realloc`` before, and
+no data pointer must exist twice in the list. The function is more efficient
+than an open-coded loop over all nodes calling ``HXdeque_del``.
+
+A generic variant is available with ``HXdeque_genocide2``, which takes a
+pointer to an appropriate freeing function. ``HXdeque_genocide`` is thus
+equivalent to ``HXdeque_genocide2(dq, free)``.
+
+To convert a linked list to a ``NULL``-terminated array, ``HXdeque_to_vec`` can
+be used. If ``num`` is not ``NULL``, the number of elements excluding the
+``NULL`` sentinel, is stored in ``*num``.
+
+
+Addition and removal
+====================
+
+.. code-block:: c
+
+ struct HXdeque_node *HXdeque_push(struct HXdeque *dq, void *ptr);
+ struct HXdeque_node *HXdeque_unshift(struct HXdeque *dq, void *ptr);
+ void *HXdeque_pop(struct HXdeque *dq);
+ void *HXdeque_shift(struct HXdeque *dq);
+ struct HXdeque *HXdeque_move(struct HXdeque_node *target, struct HXdeque_node *node);
+ void *HXdeque_del(struct HXdeque_node *node);
+
+``HXdeque_push`` and ``HXdeque_unshift`` add the data item in a new node at the
+end (“push”) or as the new first element (“unshift” as Perl calls it),
+respectively. The functions will return the new node on success, or ``NULL`` on
+failure and errno will be set. The node is owned by the list.
+
+``HXdeque_pop`` and ``HXdeque_shift`` remove the last (“pop”) or first
+(“shift”) node, respectively, and return the data pointer that was stored in
+the data.
+
+``HXdeque_move`` will unlink a node from its list, and reinsert it after the
+given target node, which may be in a different list.
+
+Deleting a node is accomplished by calling ``HXdeque_del`` on it. The data
+pointer stored in the node is not freed, but returned.
+
+
+Iteration
+=========
+
+Iterating over a HXdeque linked list is done manually and without additional
+overhead of function calls:
+
+.. code-block:: c
+
+ const struct HXdeque_node *node;
+ for (node = dq->first; node != NULL; node = node->next)
+ do_something(node->ptr);
+
+
+Searching
+=========
+
+.. code-block:: c
+
+ struct HXdeque_node *HXdeque_find(struct HXdeque *dq, const void *ptr);
+ void *HXdeque_get(struct HXdeque *dq, void *ptr);
+
+``HXdeque_find`` searches for the node which contains ``ptr``, and does so by
+beginning at the start of the list. If no node is found, ``NULL`` is returned.
+If a pointer is more than once in the list, any node may be returned.
+
+``HXdeque_get`` will further return the data pointer stored in the node —
+however, since that is just what the ptr argument is, the function practically
+only checks for existence of ``ptr`` in the list.
+
+
+Example: Using HXdeque to store and sort a list
+===============================================
+
+.. code-block:: c
+
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include <libHX/defs.h>
+ #include <libHX/deque.h>
+ #include <libHX/string.h>
+ #include <pwd.h>
+
+ int main(void)
+ {
+ struct HXdeque *dq = HXdeque_init();
+ struct passwd *pw;
+ unsigned int elem;
+ char **users;
+
+ setpwent();
+ while ((pw = getpwent()) != NULL)
+ HXdeque_push(dq, HX_strdup(pw->pw_name));
+ endpwent();
+
+ users = reinterpret_cast(char **, HXdeque_to_vec(dq, &elem));
+ HXdeque_free(dq);
+
+ qsort(users, elem, sizeof(*users), static_cast(void *, strcmp));
+ return 0;
+ }
+
+In this example, all usernames are obtained from NSS, and put into a list.
+``HX_strdup`` is used, because ``getpwent`` will overwrite the buffer it uses
+to store its results. The list is then converted to an array, and the list is
+freed (because it is not need it anymore). ``HXdeque_genocide`` must not be
+used here, because it would free all the data pointers (strings here) that were
+just inserted into the list. Finally, the list is sorted. Because ``strcmp``
+takes two ``const char *`` arguments, but qsort mandates a function taking two
+``const void *``, a cast can be used to silence the compiler. This only works
+if and when ``char *`` pointers have the same size as ``void *``, and because
+we know that the array consists of ``char *`` pointers, and not somehting else;
+therefore, ``strcmp`` will work.
diff --git a/doc/macros.rst b/doc/macros.rst
new file mode 100644
index 0000000..752f81e
--- /dev/null
+++ b/doc/macros.rst
@@ -0,0 +1,149 @@
+======
+Macros
+======
+
+All macros in this section are available through ``#include <libHX/defs.h>``.
+
+Preprocessor
+============
+
+.. code-block:: c
+
+ #define HX_STRINGIFY(s)HX_STRINGIFY
+
+Transforms the expansion of the argument ``s`` into a C string.
+
+
+Sizes
+=====
+
+.. code-block:: c
+
+ #define HXSIZEOF_Z16
+ #define HXSIZEOF_Z32
+ #define HXSIZEOF_Z64
+
+Expands to the size needed for a buffer (including ``\0``) to hold the base-10
+string representation of 16‑, 32‑ or 64‑bit integer (either signed or
+unsigned), respectively.
+
+Locators
+========
+
+.. code-block:: c
+
+ output_type *containerof(input_type *ptr, output_type, member);
+
+ size_t HXsizeof_member(struct_type, member);
+ output_type HXtypeof_member(struct_type, member);
+
+``containerof`` will return a pointer to the struct in which ``ptr`` is
+contained as the given member. (In C++, it is required that the encompassing
+``output_type`` has so-called "standard layout", but to date I have never found
+an implementation where this matters.)
+
+.. code-block:: c
+
+ struct foo {
+ int bar;
+ int baz;
+ };
+
+ static void test(int *ptr)
+ {
+ struct foo *self = containerof(baz, struct foo, baz);
+ }
+
+``HXsizeof_member`` and ``HXtypeof_member`` are shortcuts (mainly for the C
+language) to get the size or type of a named member in a given struct:
+
+.. code-block:: c
+
+ char padding[FIELD_SIZEOF(struct foo, baz)];
+
+In C++, one can simply use ``sizeof(foo::baz)`` and ``decltype(foo::baz)``.
+
+
+Array size
+==========
+
+.. code-block:: c
+
+ size_t ARRAY_SIZE(type array[]); /* implemented as a macro */
+
+Returns the number of elements in array. This only works with true arrays
+(``type[]``), and will fail to compile when passed a pointer-to-element
+(``type *``), which is often used for array access too.
+
+
+Compile-time build checks
+=========================
+
+.. code-block:: c
+
+ int BUILD_BUG_ON_EXPR(bool condition); /* implemented as a macro */
+ void BUILD_BUG_ON(bool condition); /* implemented as a macro */
+
+Causes the compiler to fail when condition evaluates to true. If not
+implemented for a compiler, it will be a no-op. ``BUILD_BUG_ON`` is meant to be
+used as a standalone statement, while ``BUILD_BUG_ON_EXPR`` is for when a check
+is to occur within an expression, that latter of which is useful for within
+macros when one cannot, or does not want to use multiple statements.
+
+.. code-block:: c
+
+ type DEMOTE_TO_PTR(type expr); /* macro */
+
+Changes the type of ``expr`` to pointer type. If ``expr`` is of array type
+class, changes it to a pointer to the first element. If ``expr`` is of function
+type class, changes it to a pointer to the function.
+
+.. code-block:: c
+
+ int main(void);
+ int (*fp)(void);
+ char a[123];
+ DEMOTE_TO_PTR(main); /* yields int (*)(void); */
+ DEMOTE_TO_PTR(fp); /* also yields int (*)(void); */
+ DEMOTE_TO_PTR(a); /* yields char * */
+
+
+UNIX file modes
+===============
+
+.. code-block:: c
+
+ #define S_IRUGO (S_IRUSR | S_IRGRP | S_IROTH)S_IRUGO
+ #define S_IWUGO (S_IWUSR | S_IWGRP | S_IWOTH)S_IWUGO
+ #define S_IXUGO (S_IXUSR | S_IXGRP | S_IXOTH)S_IXUGO
+ #define S_IRWXUGO (S_IRUGO | S_IWUGO | S_IXUGO)S_IRWXUGO
+
+The defines make it vastly easier to specify permissions for large group of
+users. For example, if one wanted to create a file with the permissions
+``rw-r--r--`` (ignoring the umask in this description), ``S_IRUSR | S_IWUSR``
+can now be used instead of the longer ``S_IRUSR | S_IWUSR | S_IRGRP |
+S_IROTH``.
+
+
+VC runtime format specifiers
+============================
+
+The Microsoft Visual C runtime (a weak libc) uses non-standard format
+specifiers for certain types. Whereas C99 specifies ``z`` for ``size_t`` and
+``ll`` for ``long long``, MSVCRT users must use ``I`` and ``I64`` (forming
+``%Id`` instead of ``%zd`` for ``ssize_t``, for example). libHX provides two
+convenience macros for this:
+
+.. code-block:: c
+
+ #define HX_SIZET_FMT "z" or "I"HX_SIZET_FMT
+ #define HX_LONGLONG_FMT "ll" or "I64"HX_LONGLONG_FMT
+
+These may be used together with ``printf`` or ``scanf``:
+
+.. code-block:: c
+
+ printf("struct timespec is of size %" HX_SIZET_FMT "u\n",
+ sizeof(struct timespec));
+
+Take note that mingw-w64's libc *does* adhere to POSIX and so, %z can be used.
diff --git a/doc/maps.rst b/doc/maps.rst
new file mode 100644
index 0000000..68eca60
--- /dev/null
+++ b/doc/maps.rst
@@ -0,0 +1,525 @@
+====
+Maps
+====
+
+A map is a collection of key-value pairs. (Some languages, such as Perl, also
+call them “associative array” or just “hash”, however, the underlying storage
+mechanism may not be an array or a hash, however.) Each key is unique and has
+an associated value. Keys can be any data desired; HXmap allows to specify your
+own key and data handling functions so they can be strings, raw pointers, or
+complex structures.
+
+To access any map-related functions, ``#include <libHX/map.h>``.
+
+
+Structural definition
+=====================
+
+The HXmap structure is a near-opaque type. Unlike the predecessor map
+implementation struct HXbtree from libHX 2.x, the 3.x API exposes much less
+fields.
+
+.. code-block:: c
+
+ struct HXmap {
+ unsigned int items, flags;
+ };
+
+``items``
+ The number of items in the tree. This field tracks the number of items
+ in the map and is used to report the number of elements to the user,
+ and is updated whenever an element is inserted or removed from the map.
+ The field must not be changed by the user.
+
+``flags``
+ The current behavior flags for the map. While implementation-private
+ bits are exposed, only ``HXMAP_NOREPLACE`` is currently allowed to be
+ (un)set by the user while a map exists.
+
+For retrieving elements from a tree, some functions work with ``struct
+HXmap_node``, which is defined as follows:
+
+.. code-block:: c
+
+ struct HXmap_node {
+ union {
+ void *key;
+ const char *const skey;
+ };
+ union {
+ void *data;
+ char *sdata;
+ };
+ };
+
+``key``
+ The so-called primary key, which uniquely identifies an element (a
+ key-value pair) in the map. The memory portions that make up the key
+ must not be modified. (If the key changes, so does its hash value
+ and/or position index, and without taking that into account, writing to
+ the key directly is going to end up with an inconsistent state. To
+ change the key, you will need to delete the element and reinsert it
+ with its new key.)
+
+``skey``
+ A convenience type field for when the map's keys are C strings. It is
+ useful for use with e.g. ``printf`` or other varargs function, which
+ would otherwise require explicit and noisy casting of the ``void *key``
+ member to ``const char *`` first.
+
+``data``
+ The data associated with the key.
+
+``sdata``
+ Convenience type field.
+
+
+Map initialization
+==================
+
+During initialization, you specify the underlying storage type by selecting a
+given constructor function. All further operations are done through the unified
+HXmap API which uses a form of virtual calls internally.
+
+Currently, there are two distinct map types in libHX. There are a handful of
+selectable symbols, though. Abstract types are:
+
+``HXMAPT_DEFAULT``
+ No further preferences or guarantees; selects any data structure that the
+ libHX maintainer deemed fast.
+
+``HXMAPT_ORDERED``
+ The map shall use a data structure that provides ordered traversal.
+
+Specific types include:
+
+``HXMAPT_HASH``
+ Hash-based map – Amortized O(1) insertion, lookup and deletion;
+ unordered.
+
+``HXMAPT_RBTREE``
+ Red-black binary tree – O(log(n)) insertion, lookup and deletion;
+ ordered.
+
+These can then be used with the initialization functions:
+
+.. code-block:: c
+
+ struct HXmap *HXmap_init(unsigned int type, unsigned int flags);
+ struct HXmap *HXmap_init5(unsigned int type, unsigned int flags, const struct HXmap_ops *ops, size_t key_size, size_t data_size);
+
+Both the *init* and *init5* variant creates a new map; the latter function
+allows to specify the operations in detail as well as key and data size, which
+may become necessary when using data sets which have their own way of being
+managed. The flags parameter can contain any of the following:
+
+``HXMAP_NONE``
+ This is just a mnemonic for the value 0, indicating no flags.
+
+``HXMAP_NOREPLACE``
+ If a key already exists and another add operation is attempted, the
+ key's associated value will be replaced by the new value. If this flag
+ is absent, ``-EEXIST`` is returned. This flag is allowed to be
+ subsequently changed by the user if so desired, using bit logic such as
+ ``map->flags &= ~HXMAP_NOREPLACE;``.
+
+``HXMAP_SKEY``
+ Notifies the constructor that keys will be C-style strings. The flag
+ presets the ``k_compare`` operation to use ``strcmp``. In the flag's
+ absence, direct value comparison will be used if the key size is
+ specified as zero (e.g. with the ``HXhashmap_init4`` function call), or
+ ``memcmp`` if the key size is non-zero.
+
+``HXMAP_CKEY``
+ Instructs the map to make copies of keys when they are added to the
+ map. This is required when the buffer holding the key changes or goes
+ out of scope. The flag presets the ``k_clone`` and ``k_free``
+ operations to ``HX_memdup`` and ``free``, and as such, the ``key_size``
+ parameter must not be zero. If however, ``HXMAP_SKEY`` is also
+ specified, ``HX_strdup`` and ``free`` will be used and ``key_size``
+ must be ``zero``.
+
+``HXMAP_SDATA``
+ Notifies the constructor that data will be C-style strings. This sets
+ up the ``d_clone`` and ``d_free`` operations.
+
+``HXMAP_CDATA``
+ Instructs the map to make copies of the data when new entries are added
+ to the map. This is required when the buffer holding the data either
+ goes out of scope, or you want to keep the original contents instead of
+ just a pointer.
+
+``HXMAP_SCKEY``
+ Mnemonic for the combination of ``HXMAP_SKEY | HXMAP_CKEY``.
+
+``HXMAP_SCDATA``
+ Mnemonic for the combination of ``HXMAP_SDATA | HXMAP_SDATA``.
+
+``HXMAP_SINGULAR``
+ Specifies that the “map” is only used as a set, i.e. it does not store
+ any values, only keys. Henceforth, the value argument to ``HXmap_add``
+ must always be ``NULL``.
+
+
+Flag combinations
+=================
+
+This subsection highlights the way ``HXMAP_SKEY`` interacts with ``HXMAP_CKEY``
+and the key size. The copy semantics are the same for ``HXMAP_SDATA`` and
+``HXMAP_CDATA``.
+
+HXMAP_SKEY unset, HXMAP_CKEY unset
+----------------------------------
+
+The ``key_size`` parameter at the time of map construction is ignored. The
+pointer value of the key parameter for the ``HXmap_add`` call is directly
+stored in the tree, and this is the key that uniquely identifies the map entry
+and which is used for comparisons. This may be used if you intend to directly
+map pointer values.
+
+.. code-block:: c
+
+ static struct something *x = ..., *y = ...;
+ HXmap_add(map, &x[0], "foo");
+ HXmap_add(map, &x[1], "bar");
+
+HXMAP_SKEY set, HXMAP_CKEY unset
+--------------------------------
+
+The ``key_size`` parameter at the time of map construction is ignored. The
+pointer value of the key parameter for the HXmap_add call is directly stored in
+the tree, but it is the C string pointed to by the key parameter that serves as
+the key.
+
+HXMAP_SKEY set, HXMAP_CKEY set
+------------------------------
+
+The ``key_size`` parameter at the time of map construction is ignored. The
+string pointed to by the key parameter will be duplicated, and the resulting
+pointer will be stored in the tree. Again, it is the pointed-to string that is
+the key.
+
+HXMAP_SKEY unset, HXMAP_CKEY set
+--------------------------------
+
+The memory block pointed to by the key parameter will be duplicated. The
+``key_size`` parameter must be non-zero for this to successfully work.
+
+With separate ops
+-----------------
+
+However, when a custom ``struct HXmap_ops`` is provided in the call to
+``HXmap_init5``, any of these semantics can be overridden. Particularly, since
+your own ops can practically ignore ``key_size``, it could be set to any value.
+
+
+Key-data operations
+===================
+
+The ``HXMAP_SKEY/CKEY/SDATA/CDATA`` flags are generally sufficient to set up
+common maps where keys and/or data are C strings or simple binary data where
+``memdup``/``memcmp`` is enough. Where the provided mechanisms are not cutting
+it, an extra ``HXmap_ops`` structure with functions specialized in handling the
+keys and/or data has to be used as an argument to the initialization function
+call.
+
+.. code-block:: c
+
+ struct HXmap_ops {
+ int (*k_compare)(const void *, const void *, size_t);
+ void *(*k_clone)(const void *, size_t);
+ void (*k_free)(void *);
+ void *(*d_clone)(const void *, size_t);
+ void (*d_free)(void *);
+ unsigned long (*k_hash)(const void *, size_t);
+ };
+
+``k_compare``
+ Function to compare two keys. The return value is the same as that of
+ ``memcmp`` or ``strcmp``: negative values indicate that the first key
+ is “less than” the second, zero indicates that both keys are equal, and
+ positive values indicate that the first key is “greater than” the
+ second. The ``size`` argument in third position is provided so that
+ ``memcmp``, which wants a size parameter, can directly be used without
+ having to write an own function. (This also means strcmp can't be
+ directly plugged in due to a function signature mismatch.)
+
+``k_clone``
+ Function that will clone (duplicate) a key. This is used for keys that
+ will be added to the tree, and potentially also for state-keeping
+ during traversal of the map. It is valid that this clone function
+ simply returns the value of the pointer it was actually passed; this is
+ used by default for maps without ``HXMAP_CKEY`` for example.
+
+``k_free``
+ Function to free a key. In most cases it defaults to ``free``(3), but
+ in case you are using complex structs, more cleanup may be needed.
+
+``d_clone``
+ Same idea as ``k_clone``, but for data.
+
+``d_free``
+ Same idea as ``k_free``, but for data.
+
+``k_hash``
+ Specifies an alternate hash function. Only to be used with hash-based
+ maps. Hashmaps default to using the DJB2 string hash function when
+ ``HXMAP_SKEY`` is given, or otherwise the Jenkins' lookup3 hash
+ function.
+
+libHX exports two hash functions that you can select for ``struct HXmap_ops``'s
+``k_hash`` if the default for a given flag combination is not to your liking.
+
+``HXhash_jlookup3``
+ Bob Jenkins's lookup3 hash.
+
+``HXhash_djb2``
+ DJB2 string hash.
+
+
+Map operations
+==============
+
+.. code-block:: c
+
+ int HXmap_add(struct HXmap *, const void *key, const void *value);
+ const struct HXmap_node *HXmap_find(const struct HXmap *, const void *key);
+ void *HXmap_get(const struct HXmap *, const void *key);
+ void *HXmap_del(struct HXmap *, const void *key);
+ void HXmap_free(struct HXmap *);
+ struct HXmap_node *HXmap_keysvalues(const struct HXmap *);
+
+``HXmap_add``
+ Adds a new node to the tree using the given key and data. When an
+ element is in the map, the key may not be modified, as doing so could
+ possibly invalidate the internal location of the element, or its
+ ordering with respect to other elements. If you need to change the key,
+ you will have to delete the element from the tree and re-insert it. On
+ error, -errno will be returned.
+
+ When ``HXMAP_SINGULAR`` is in effect, value must be ``NULL``, else
+ ``-EINVAL`` is returned.
+
+``HXmap_find``
+ Finds the node for the given key. The key can be read from the node
+ using ``node->key`` or ``node->skey`` (convenience alias for key, but
+ with a type of ``const char *``), and the data by using ``node->data``
+ or ``node->sdata``.
+
+``HXmap_get``
+ Get is a find operation directly returning ``node->data`` instead of
+ the node itself. Since ``HXmap_get`` may legitimately return ``NULL``
+ if ``NULL`` was stored in the tree as the data for a given key, only
+ ``errno`` will really tell whether the node was found or not; in the
+ latter case, ``errno`` is set to ``ENOENT``.
+
+``HXmap_del``
+ Removes an element from the map and returns the data value that was
+ associated with it. When an error occurred, or the element was not
+ found, ``NULL`` is returned. Because ``NULL`` can be a valid data
+ value, ``errno`` can be checked for non-zero. ``errno`` will be
+ ``-ENOENT`` if the element was not found, or zero when everything was
+ ok.
+
+``HXmap_free``
+ The function will delete all elements in the map and free memory it
+ holds.
+
+``HXmap_keysvalues``
+ Returns all key-value-pairs in an array of the size as many items were
+ in the map (map->items) at the time it was called. The memory must be
+ freed using ``free``(3) when it is no longer needed. The order elements
+ in the array follows the traverser notes (see below), unless otherwise
+ specified.
+
+
+Map traversal
+=============
+
+.. code-block:: c
+
+ struct HXmap_trav *HXmap_travinit(const struct HXmap *);
+ const struct HXmap_node *HXmap_traverse(struct HXmap_trav *iterator);
+ void HXmap_travfree(struct HXmap_trav *iterator);
+ void HXmap_qfe(const struct HXmap *, bool (*fn)(const struct HXmap_node *, void *arg), void *arg);
+
+``HXmap_travinit``
+ Initializes a traverser (a.k.a. iterator) for the map, and returns a
+ pointer to it. ``NULL`` will be returned in case of an error, such as
+ memory allocation failure. Traversers are returned even if the map has
+ zero elements.
+
+``HXmap_traverse``
+ Returns a pointer to a ``struct HXmap_node`` for the next element /
+ key-value pair from the map, or ``NULL`` if there are no more entries.
+
+``HXmap_travfree``
+ Releases the memory associated with a traverser.
+
+``HXmap_qfe``
+ The “quick foreach”. Iterates over all map elements in the fastest
+ possible manner, but has the restriction that no modifications to the
+ map are allowed. Furthermore, a separate function to handle each
+ visited node, is required. (Hence this is also called “closed
+ traversal”, because one cannot access the stack frame of the original
+ function which called ``HXmap_qfe``.) The user-defined function returns
+ a bool which indicates whether traversal shall continue or not.
+
+Flags for ``HXmap_travinit``:
+
+``HXMAP_NOFLAGS``
+ A mnemonic for no flags, and is defined to 0.
+
+``HXMAP_DTRAV``
+ Enable support for deletion during traversal. As it can make traversal
+ slower, it needs to be explicitly specified for cases where it is
+ needed, to not penalize cases where it is not.
+
+WARNING: Modifying the map while a traverser is active is
+implementation-specific behavior! libHX generally ensures that there will be no
+undefined behavior (e.g. crashes), but there is no guarantee that elements
+will be returned exactly once. There are fundamental cases that one should be
+aware of:
+
+* An element is inserted before where the traverser is currently positioned at.
+ The element may not be returned in subsequent calls to ``HXmap_traverse`` on
+ an already-active traverser.
+
+* Insertion or deletion may cause internal data structure to re-layout.
+
+ * Traversers of ordered data structures may choose to rebuild
+ their state.
+
+ * Traversers of unordered data structures would run risk to
+ return more than once, or not at all.
+
+Descriptions for different map types follow.
+
+:Hashmaps:
+ On ```HXmap_add`, an element may be inserted in a position that is
+ before where the traverser is currently positioned. Such elements will
+ not be returned in the remaining calls to ``HXmap_traverse``. The
+ insertion or deletion of an element may cause the internal data
+ structure to re-layout itself. When this happens, the traverser will
+ stop, so as to not return entries twice.
+
+:Binary trees:
+ Elements may be added before the traverser's position. These elements
+ will not be returned in subsequent traversion calls. If the data
+ structure changes as a result of an addition or deletion, the traverser
+ will rebuild its state and continue traversal transparently. Because
+ elements in a binary tree are ordered, that is, element positions may
+ not change with respect to another when the tree is rebalanced, there
+ is no risk of returning entries more than once. Nor will elements that
+ are sorted after the current traverser's position not be returned
+ (= they will be returned, because they cannot get reordered to before
+ the traverser like in a hash map). The HX rbtree implementation also
+ has proper handling for when the node which is currently visiting is
+ deleted.
+
+
+RB-tree Limitations
+===================
+
+The implementation has a theoretical minimum on the maximum number of nodes,
+2^{24}=16{,}777{,}216. A worst-case tree with this many elements already has a
+height of 48 (RBT_MAXDEP), which is the maximum height currently supported. The
+larger the height is that HXrbtree is supposed to handle, the more memory
+(linear increase) it needs. All functions that build or keep a path reserve
+memory for RBT_MAXDEP nodes; on x86_64, this is 9 bytes per <node, direction>
+pair, amounting to 432 bytes for path tracking alone. It may not sound like a
+lot to many, but given that kernel developers try to limit their stack usage to
+some 4096 bytes is impressive alone.
+
+
+Examples
+========
+
+Case-insensitive ordering
+-------------------------
+
+The correct way:
+
+.. code-block:: c
+
+ static int my_strcasecmp(const void *a, const void *b, size_t z) {
+ return strcasecmp(a, b);
+ }
+ static const struct HXmap_ops icase = {
+ .k_compare = my_strcasecmp,
+ };
+ HXmap_init5(HXMAPT_RBTREE, HXMAP_SKEY, &icase, 0, dsize);
+
+A hackish way (which wholly depends on the C implementation and use of extra
+safeguards is a must):
+
+.. code-block:: c
+
+ static const struct HXmap_ops icase = {
+ .k_compare = (void *)strcasecmp,
+ };
+ BUILD_BUG_ON(sizeof(DEMOTE_TO_PTR(strcasecmp)) > sizeof(void *));
+ BUILD_BUG_ON(sizeof(DEMOTE_TO_PTR(strcasecmp)) > sizeof(icase.k_compare));
+ HXmap_init5(HXMAPT_RBTREE, HXMAP_SKEY, &icase, 0, dsize);
+
+
+Reverse sorting order
+---------------------
+
+Any function that behaves like strcmp can be used. It merely has to return
+negative when ``a<b``, zero on ``a==b``, and positive non-zero when ``a>b``.
+
+.. code-block:: c
+
+ static int strcmp_rev(const void *a, const void *b, size_t z)
+ {
+ /* z is provided for cases when things are raw memory blocks. */
+ return strcmp(b, a);
+ }
+
+ static const struct HXmap_ops rev = {
+ .k_compare = strcmp_rev,
+ };
+ HXmap_init5(HXMAPT_RBTREE, HXMAP_SKEY, &rev, 0, dsize);
+
+
+Keys with non-unique data
+-------------------------
+
+Keys can actually store non-unique data, as long as this extra fields does not
+actually contribute to the logical key — the parts that do uniquely identify
+it. In the following example, the notes member may be part of struct package,
+which is the key as far as HXmap is concerned, but still, only the name and
+versions are used to identify it.
+
+.. code-block:: c
+
+ struct package {
+ char *name;
+ unsigned int major_version;
+ unsigned int minor_version;
+ char notes[64];
+ };
+
+ static int package_cmp(const void *a, const void *b)
+ {
+ const struct package *p = a, *q = b;
+ int ret;
+ ret = strcmp(p->name, q->name);
+ if (ret != 0)
+ return ret;
+ ret = p->major_version - q->major_version;
+ if (ret != 0)
+ return ret;
+ ret = p->minor_version - q->minor_version;
+ if (ret != 0)
+ return ret;
+ return 0;
+ }
+
+ static const struct HXmap_ops package_ops = {
+ .k_compare = package_cmp,
+ };
+
+ HXmap_init5(HXMAPT_RBTREE, flags, &package_ops,
+ sizeof(struct package), dsize);
diff --git a/doc/memory_container.rst b/doc/memory_container.rst
new file mode 100644
index 0000000..a1608ca
--- /dev/null
+++ b/doc/memory_container.rst
@@ -0,0 +1,197 @@
+=================
+Memory containers
+=================
+
+The HXmc series of functions provide scripting-like semantics for strings,
+especially automatically resizing the buffer on demand. They can also be used
+to store a binary block of data together with its length. (Hence the name: mc =
+memory container.)
+
+The benefit of using the HXmc functions is that one does not have to
+meticulously watch buffer and string sizes anymore.
+
+Improvement of string safety over time:
+
+.. code-block:: c
+
+ /* Step 1 */
+
+ char buf[long_enough] = "helloworld";
+ if (strlen(buf) + strlen(".txt") < sizeof(buf))
+ strcat(s, ".txt"); /* may go over end of buffer */
+
+ /* Step 2 */
+
+ char buf[long_enough] = "helloworld";
+ strlcat(s, ".txt", sizeof(buf)); /* may truncate */
+
+ /* Step 3 */
+
+ hxmc_t *buf = HXmc_strinit("helloworld");
+ HXmc_strcat(&s, ".txt");
+
+This makes it quite similar to the string operations (and append seems to be
+the most commonly used one to me) supported in scripting languages that also do
+without a size argument. The essential part of such memory containers is that
+their internal (hidden) metadata structure contains the length of the memory
+block in the container. For binary data this may be the norm, but for C-style
+strings, the stored and auto-updated length field serves as an accelerator
+cache. For more details, see ``HXmc_length``.
+
+Of course, the automatic management of memory comes with a bit of overhead as
+the string expands beyond its preallocated region. Such may be mitigated by
+doing explicit (re)sizing.
+
+
+Structural overview
+===================
+
+HXmc functions do not actually return a pointer to the memory container (e.g.
+struct) itself, but a pointer to the data block. Conversely, input parameters
+to HXmc functions will be the data block pointer. It is of type ``hxmc_t *``,
+which is typedef'ed to ``char *`` and therefore has properties of a char
+pointer. Pointer arithmetic is thus supported. It also means you can just pass
+it to functions that take a ``char *`` without having to do a member access
+like ``s.c_str()`` in C++. The drawback is that many functions operating on the
+memory container need a ``hxmc_t **`` (a level-two indirection), because not
+only does the memory block move, but also the memory container itself. This is
+due to the implementation of the container metadata which immediately and
+always precedes the writable memory block.
+
+HXmc ensures that the data block is terminated by the \0 byte (unless you trash
+it), so you do not have to, and of course, to be on the safe side. But, the
+automatic \0 byte is not part of the region allocated by the user. That is,
+when one uses the classic approach with ``malloc(4096)``, the user will have
+control of 4096 bytes and has to stuff the \0 byte in there somehow on his own;
+for strings this means the maximum string length is 4095. Requesting space for
+a 4096-byte sized HXmc container gives you the possibility to use all 4096
+bytes for the string, because HXmc provides a \0 byte.
+
+By the way, ``hxmc_t`` is the only typedef in this entire library, to
+distinguish it from regular ``char *`` that does not have a backing memory
+cointainer.
+
+Constructors, destructors
+=========================
+
+.. code-block:: c
+
+ #include <libHX/string.h>
+
+ hxmc_t *HXmc_strinit(const char *s);
+ hxmc_t *HXmc_meminit(const void *ptr, size_t size);
+ void HXmc_free(hxmc_t *s);
+ void HXmc_zvecfree(hxmc_t **s);
+
+``HXmc_strinit``
+ Creates a new ``hxmc_t`` object from the supplied string and returns
+ it.
+
+``HXmc_meminit``
+ Creates a new ``hxmc_t`` object from the supplied memory buffer of the
+ given size and returns it. ``HXmc_meminit(NULL, len)`` may be used to
+ obtain an empty container with a preallocated region of len bytes (zero
+ is accepted for ``len``).
+
+``HXmc_free``
+ Frees the hxmc object.
+
+``HXmc_zvecfree``
+ Frees all hxmc objects in the ``NULL``-terminated array, and finally
+ frees the array itself, similar to ``HX_zvecfree``.
+
+Data manipulation
+=================
+
+Binary-based
+------------
+
+.. code-block:: c
+
+ hxmc_t *HXmc_trunc(hxmc_t **mc, size_t len);HXmc_trunc
+ hxmc_t *HXmc_setlen(hxmc_t **mc, size_t len);HXmc_setlen
+ hxmc_t *HXmc_memcpy(hxmc_t **mc, const void *ptr, size_t len);
+ hxmc_t *HXmc_memcat(hxmc_t **mc, const void *ptr, size_t len);
+ hxmc_t *HXmc_mempcat(hxmc_t **mc, const void *ptr, size_t len);
+ hxmc_t *HXmc_memins(hxmc_t **mc, size_t pos, const void *ptr, size_t len);
+ hxmc_t *HXmc_memdel(hxmc_t **mc, size_t pos, size_t len);
+
+When ``ptr`` is ``NULL``, each call behaves as if ``len`` would be ``zero``.
+Specifically, no undefined behavior will result of the use of ``NULL``.
+
+``HXmc_trunc``
+ Truncates the container's data to ``len`` size. If ``len`` is greater
+ than the current data size of the container, the length is in fact not
+ updated, but a reallocation may be triggered, which can be used to do
+ explicit allocation.
+
+``HXmc_setlen``
+ Sets the data length, doing a reallocation of the memory container if
+ needed. The newly available bytes are uninitialized. Make use of this
+ function when letting 3rd party functions write to the buffer, but it
+ should not be used with ``HXmc_str*``.
+
+``HXmc_memcpy``
+ Truncates the container's data and copies ``len`` bytes from the memory
+ area pointed to by ``ptr`` to the container.
+
+``HXmc_memcat``
+ Concatenates (appends) ``len`` bytes from the memory area pointed to by
+ ``ptr`` to the container's data.
+
+``HXmc_mempcat``
+ Prepends ``len`` bytes from the memory area pointed to by ``ptr`` to
+ the container's data.
+
+``HXmc_memins``
+ Prepends ``len`` bytes from the memory area pointed to by ``ptr`` to
+ the ``pos``'th byte of the container's data.
+
+``HXmc_memdel``
+ Deletes ``len`` bytes from the container beginning at position ``pos``.
+
+In case of a memory allocation failure, the ``HXmc_*`` functions will return
+``NULL``.
+
+String-based
+------------
+
+The string-based functions correspond to their binary-based equivalents with a
+len argument of strlen(s).
+
+.. code-block:: c
+
+ hxmc_t *HXmc_strcpy(hxmc_t **mc, const char *s);
+ hxmc_t *HXmc_strcat(hxmc_t **mc, const char *s);
+ hxmc_t *HXmc_strpcat(hxmc_t **mc, const char *s);
+ hxmc_t *HXmc_strins(hxmc_t **mc, size_t pos, const char *s);
+
+``HXmc_strcpy``
+ Copies the string pointed to by ``s`` into the memory container given
+ by ``mc``. If ``mc`` is ``NULL``, the memory container will be
+ deallocated, that is, ``*mc`` becomes ``NULL``.
+
+From auxiliary sources
+----------------------
+
+.. code-block:: c
+
+ hxmc_t *HX_getl(hxmc_t **mc, FILE *fp);HX_getl
+
+``HX_getl``
+ Reads the next line from ``fp`` and store the result in the container.
+ Returns ``NULL`` on error, or when end of file occurs while no
+ characters have been read.
+
+Container properties
+--------------------
+
+.. code-block:: c
+
+ size_t HXmc_length(const hxmc_t **mc);
+
+``HXmc_length``
+ Returns the length of the memory container. This is not always equal to
+ the actual string length. For example, if ``HX_chomp`` was used on an
+ MC-backed string, ``strlen`` will return less than ``HXmc_length`` if
+ newline control characters (``\r`` and ``\n``) were removed.
diff --git a/doc/misc_functions.rst b/doc/misc_functions.rst
new file mode 100644
index 0000000..0f1bdaf
--- /dev/null
+++ b/doc/misc_functions.rst
@@ -0,0 +1,35 @@
+=======================
+Miscellaneous functions
+=======================
+
+.. code-block:: c
+
+ #include <libHX/misc.h>
+
+ int HX_ffs(unsigned long z);
+ int HX_fls(unsigned long z);
+ void HX_hexdump(FILE *fp, const void *ptr, unsigned int len);
+
+ void HX_zvecfree(char **);
+ unsigned int HX_zveclen(const char *const *);
+
+``HX_ffs``
+ Finds the first (lowest-significant) bit in a value and returns its
+ position, or ``-1`` to indicate failure.
+
+``HX_fls``
+ Finds the last (most-significant) bit in a value and returns its
+ position, or ``-1`` to indicate failure.
+
+``HX_hexdump``
+ Outputs a nice pretty-printed hex and ASCII dump to the filedescriptor
+ ``fp``. ``ptr`` is the memory area, of which ``len`` bytes will be
+ dumped.
+
+``HX_zvecfree``
+ Frees the supplied Z-vector array. (Frees all array elements from the
+ first element to (excluding) the first ``NULL`` element.)
+
+``HX_zveclen``
+ Counts the number of array elements until the first ``NULL`` array
+ element is seen, and returns this number.
diff --git a/doc/option_parsing.rst b/doc/option_parsing.rst
new file mode 100644
index 0000000..9205c2b
--- /dev/null
+++ b/doc/option_parsing.rst
@@ -0,0 +1,587 @@
+==============
+Option parsing
+==============
+
+libHX uses a table-based approach like libpopt[#f3]. It provides for both long
+and short options and the different styles associated with them, such as
+absence or presence of an equals sign for long options (``--foo=bar`` and ``--foo
+bar``), bundling (writing ``-abc`` for non-argument taking options ``-a -b -c``),
+squashing (writing ``-fbar`` for an argument-requiring option ``-f bar``). The “lone
+dash” that is often used to indicate standard input or standard output, is
+correctly handled[#f4], as in ``-f -``.
+
+.. [#f3] The alternative would be an iterative, open-coded approach like
+ ``getopt``(3) requires.
+
+.. [#f4] popt failed to do this for a long time.
+
+A table-based approach allows for the parser to run as one unit, quite unlike
+the open-coded ``getopt``(3) loop where the function returns for every argument
+it parsed and needs to be called repeatedly.
+
+
+Synopsis
+========
+
+.. code-block:: c
+
+ #include <libHX/option.h>
+
+ struct HXoption {
+ const char *ln;
+ char sh;
+ unsigned int type;
+ void *ptr, *uptr;
+ void (*cb)(const struct HXoptcb *);
+ int val;
+ const char *help, *htyp;
+ };
+
+ int HX_getopt(const struct HXoption *options_table, int *argc, const char ***argv, unsigned int flags);
+
+The various fields of ``struct HXoption`` are:
+
+``ln``
+ The long option name, if any. May be ``NULL`` if none is to be assigned
+ for this entry.
+
+``sh``
+ The short option name/character, if any. May be '``\0``' if none is to
+ be assigned for this entry.
+
+``type``
+ The type of the entry, essentially denoting the type of the target
+ variable.
+
+``val``
+ An integer value to be stored into ``*(int *)ptr`` when the option type
+ is ``HXTYPE_IVAL``.
+
+``ptr``
+ A pointer to the variable so that the option parser can store the
+ requested data in it. The pointer may be ``NULL``, in which case no
+ data is stored (but ``cb`` is still called if defined, with the data).
+
+``uptr``
+ A user-supplied pointer. Its value is passed verbatim to the callback,
+ and may be used for any purpose the user wishes. If the option type is
+ ``HXTYPE_SVAL``, it is the value in uptr that will be used to populate
+ ``*(const char **)ptr``.
+
+``cb``
+ If not ``NULL``, call out to the referenced function after the option
+ has been parsed (and the results possibly be stored in ``ptr``).
+
+``help``
+ A help string that is shown for the option when the option table is
+ dumped by request (e.g. ``yourprgram --help``).
+
+``htyp``
+ String containing a keyword to aid the user in understanding the
+ available options during dump. See examples.
+
+Due to the amount of fields, it is advised to use C99 named initializers to
+populate a struct, as they allow to omit unspecified fields, and assume no
+specific order of the members:
+
+.. code-block:: c
+
+ struct HXoption e = {.sh = 'f', .help = "Force"};
+
+It is a sad fact that C++ has not gotten around to implement named initializers
+as of C++17. It is possible to put the option parsing code into a separate C
+source file that can then be compiled in C99 rather than C++ mode.
+
+
+Type map
+========
+
+``HXTYPE_NONE``
+ The option does not take any argument, but the presence of the option
+ may be record by setting ``*(int *)ptr`` to ``1``. Other rules apply
+ when ``HXOPT_INC`` or ``HXOPT_DEC`` are specified as flags.
+
+``HXTYPE_VAL``
+ Use the integer value specified by ``ival`` and store it in
+ ``*(int *)ptr``.
+
+``HXTYPE_SVAL``
+ Use the memory location specified by ``sval`` and store it in ``*(const
+ char **)ptr``. OUTDATED.
+
+``HXTYPE_BOOL``
+ Interpret the supplied argument as a boolean descriptive (must be
+ ``yes``, ``no``, ``on``, ``off``, ``true``, ``false``, ``0`` or ``1``)
+ and store the result in ``*(int *)ptr``.
+
+``HXTYPE_STRING``
+ The argument string is duplicated to a new memory region and the
+ resulting pointer stored into ``*(char **)ptr``. This incurs an
+ allocation so that subsequently modifying the original argument string
+ in any way will not falsely propagate.
+
+``HXTYPE_STRDQ``
+ The argument string is duplicated to a new memory region and the
+ resulting pointer is added to the given HXdeque. Note that you often
+ need to use deferred initialization of the options table to avoid
+ putting ``NULL`` into the entry. See section about pitfalls.
+
+The following overview lists the types that map to the common integral and
+floating-point types. Signed and unsigned integeral types are processed using
+``strtol`` and ``strtoul``, respectively. ``strtol`` and ``strtoul`` will be
+called with automatic base detection. This usually means that a leading ``0``
+indicates the string is given in octal base, a leading ``0x`` indicates
+hexadecimal base, and decimal otherwise. ``HXTYPE_LLONG``, ``HXTYPE_ULLONG``,
+``HXTYPE_INT64`` and ``HXTYPE_UINT64`` use ``strtoll`` and/or ``strtoull``,
+which may not be available on all platforms.
+
+``HXTYPE_CHAR``
+ maps to ``char``
+
+``HXTYPE_UCHAR``
+ maps to ``unsigned char``
+
+``HXTYPE_SHORT``
+ maps to ``short``
+
+``HXTYPE_USHORT``
+ maps to ``unsigned short``
+
+``HXTYPE_INT``
+ maps to ``int``
+
+``HXTYPE_UINT``
+ maps to ``unsigned int``
+
+``HXTYPE_LONG``
+ maps to ``long``
+
+``HXTYPE_ULONG``
+ maps to ``unsigned long``
+
+``HXTYPE_LLONG``
+ maps to ``long long``
+
+``HXTYPE_ULLONG``
+ maps to ``unsigned long long``
+
+``HXTYPE_SIZE_T``
+ maps to ``size_t``
+
+``HXTYPE_FLOAT``
+ maps to ``float``
+
+``HXTYPE_DOUBLE``
+ maps to ``double``
+
+``HXTYPE_INT8``
+ maps to ``int8_t``
+
+``HXTYPE_UINT8``
+ maps to ``uint8_t``
+
+``HXTYPE_INT16``
+ maps to ``int16_t``
+
+``HXTYPE_UINT16``
+ maps to ``uint16_t``
+
+``HXTYPE_INT32``
+ maps to ``int32_t``
+
+``HXTYPE_UINT32``
+ maps to ``uint32_t``
+
+``HXTYPE_INT64``
+ maps to ``int64_t``
+
+``HXTYPE_UINT64``
+ maps to ``uint64_t``
+
+``HXTYPE_FLOAT`` and ``HXTYPE_DOUBLE`` make use of ``strtod`` (``strtof`` is
+not used). A corresponding type for the ``long double`` format is not
+specified, but may be implemented on behalf of the user via a callback.
+
+
+Flags
+=====
+
+Flags can be combined into the type parameter by OR'ing them. It is valid to
+not specify any flags at all, but most flags collide with one another.
+
+``HXOPT_INC``
+ Perform an increment on the memory location specified by the
+ ``*(int *)ptr`` pointer. Make sure the referenced variable is
+ initialized beforehand!
+
+``HXOPT_DEC``
+ Perform a decrement on the pointee. Same requirements as ``HXOPT_INC``.
+
+Only one of ``HXOPT_INC`` and ``HXOPT_DEC`` may be specified at a time,
+and they require that the base type is ``HXTYPE_NONE``, or they will
+have no effect. An example may be found below.
+
+``HXOPT_NOT``
+ Binary negation of the argument directly after reading it from the
+ command line into memory. Any of the three following operations are
+ executed with the already-negated value.
+
+``HXOPT_OR``
+ Apply bitwise OR on the pointee with the specified/transformed value.
+
+``HXOPT_AND``
+ Apply bitwise AND on the pointee with the specified/transformed value.
+
+``HXOPT_XOR``
+ Apply bitwise XOR on the pointee with the specified/transformed value.
+
+Only one of ``HXOPT_OR``, ``HXOPT_AND`` and ``HXOPT_XOR`` may be specified at
+a time, but they can be used with any integral type (``HXTYPE_UINT``,
+``HXTYPE_ULONG``, etc.). An example can be found below.
+
+``HXOPT_OPTIONAL``
+ This flag allows for an option to take zero or one argument. Needless
+ to say that this can be confusing to the user. iptables's ``-L`` option
+ for example is one of this kind (though it does not use the libHX
+ option parser). When this flag is used, ``-f -b`` is interpreted as
+ ``-f`` without an argument, as is ``-f --bar`` — things that look like
+ an option take precedence over an option with an optional argument.
+ ``-f -`` of course denotes an option with an argument, as ``-`` is
+ often used to indicate standard input/output.
+
+
+Special entries
+===============
+
+HXopt provides two special entries via macros:
+
+``HXOPT_AUTOHELP``
+ Adds entries to recognize ``-?`` and ``--help`` that will display the
+ (long-format) help screen, and ``--usage`` that will display the short
+ option syntax overview. All three options will exit the program
+ afterwards.
+
+``HXOPT_TABLEEND``
+ This sentinel marks the end of the table and is required on all tables.
+ (See examples for details.)
+
+
+Invoking the parser
+===================
+
+.. code-block:: c
+
+ int HX_getopt(const struct HXoption *options_table, int *argc, const char ***argv, unsigned int flags);HX_getopt
+
+``HX_getopt`` is the actual parsing function. It takes the option table, and a
+pointer to your argc and argv variables that you get from the main function.
+The parser will, by default, consume all options and their arguments, similar
+to Perl's ``Getopt::Long`` module. ``*argv`` is then updated to point to a new
+array of strings (to be deallocated with ``HX_zvecfree``) and ``*argc`` is
+updated accordingly. Additional flags can control the exact behavior of
+``HX_getopt``:
+
+``HXOPT_PTHRU``
+ “Passthrough mode”. Any unknown options are not “eaten” and are instead
+ passed back into the resulting argv array.
+
+``HXOPT_QUIET``
+ Do not print any diagnostics when encountering errors in the user's
+ input.
+
+``HXOPT_HELPONERR``
+ Display the (long-format) help when an error, such as an unknown option
+ or a violation of syntax, is encountered.
+
+``HXOPT_USAGEONERR``
+ Display the short-format usage syntax when an error is encountered.
+
+``HXOPT_RQ_ORDER``
+ Specifying this option terminates option processing when the first
+ non-option argument in argv is encountered. This behavior is also
+ implicit when the environment variable ``POSIXLY_CORRECT`` is set.
+
+``HXOPT_KEEP_ARGV``
+ Do not modify ``argc`` and ``argv`` at all.
+
+The return value can be one of the following:
+
+``HXOPT_ERR_SUCCESS``
+ Parsing was successful.
+
+``HXOPT_ERR_UNKN``
+ An unknown option was encountered.
+
+``HXOPT_ERR_VOID``
+ An argument was given for an option which does not allow one. In
+ practice this only happens with ``--foo=bar`` when ``--foo`` is of type
+ ``HXTYPE_NONE``, ``HXTYPE_VAL`` or ``HXTYPE_SVAL``. This does not
+ affect ``--foo bar``, because this can be unambiguously interpreted as
+ ``bar`` being a remaining argument to the program.
+
+``HXOPT_ERR_MIS``
+ Missing argument for an option that requires one.
+
+``HXOPT_ERR_AMBIG``
+ An abbreviation of a long option was ambiguous.
+
+negative non-zero
+ Failure on behalf of lower-level calls; errno.
+
+
+Pitfalls
+========
+
+Staticness of tables
+--------------------
+
+The following is an example of a possible pitfall regarding ``HXTYPE_STRDQ``:
+
+.. code-block:: c
+
+ static struct HXdeque *dq;
+
+ static bool get_options(int *argc, const char ***argv)
+ {
+ static const struct HXoption options_table[] = {
+ {.sh = 'N', .type = HXTYPE_STRDQ, .ptr = dq,
+ .help = "Add name"},
+ HXOPT_TABLEEND,
+ };
+ return HX_getopt(options_table, argc, argv, HXOPT_USAGEONERR) ==
+ HXOPT_ERR_SUCCESS;
+ }
+
+ int main(int argc, const char **argv)
+ {
+ dq = HXdeque_init();
+ get_options(&argc, &argv);
+ return 0;
+ }
+
+The problem here is that ``options_table`` is, due to the static keyword,
+initialized at compile-time when ``dq`` is still ``NULL``. To counter this
+problem and have it doing the right thing, you must remove the static qualifier
+on the options table when used with ``HXTYPE_STRDQ``, so that it will be
+evaluated when it is first executed.
+
+It was not deemed worthwhile to have ``HXTYPE_STRDQ`` take an indirect
+``HXdeque`` (``struct HXdeque **``) instead just to bypass this issue. (Live
+with it.)
+
+Limitations
+-----------
+
+The HX option parser has been influenced by both popt and Getopt::Long, but
+eventually, there are differences:
+
+* Long options with a single dash (``-foo bar``). This unsupported
+ syntax clashes easily with support for option bundling or squashing. In case
+ of bundling, ``-foo`` might actually be ``-f -o -o``, or ``-f oo`` in case of
+ squashing. It also introduces redundant ways to specify options, which is not
+ in the spirit of the author.
+
+* Options using a ``+`` as a prefix, as in ``+foo``. Xterm for
+ example uses it as a way to negate an option. In the author's opinion, using
+ one character to specify options is enough — by GNU standards, a negator is
+ named ``--no-foo``.
+
+* Table nesting like implemented in popt. HXopt has no provision for nested
+ tables, as the need has not come up yet. It does however support chained
+ processing. You cannot do nested tables even with callbacks, as the new argv
+ array is only put in place shortly before ``HX_getopt`` returns.
+
+
+Examples
+========
+
+Basic example
+-------------
+
+The following code snippet should provide an equivalent of the
+GNU getopt sample.[#f5]
+
+.. [#f5] http://www.gnu.org/software/libtool/manual/libc/Example-of-Getopt.html\#Example-of-Getopt
+
+.. code-block:: c
+
+ #include <stdio.h>
+ #include <stdilb.h>
+ #include <libHX/option.h>
+
+ int main(int argc, const char **argv)
+ {
+ int aflag = 0;
+ int bflag = 0;
+ char *cflag = NULL;
+
+ struct HXoption options_table[] = {
+ {.sh = 'a', .type = HXTYPE_NONE, .ptr = &aflag},
+ {.sh = 'b', .type = HXTYPE_NONE, .ptr = &bflag},
+ {.sh = 'c', .type = HXTYPE_STRING, .ptr = &cflag},
+ HXOPT_AUTOHELP,
+ HXOPT_TABLEEND,
+ };
+
+ if (HX_getopt(options_table, &argc, &argv, HXOPT_USAGEONERR) !=
+ HXOPT_ERR_SUCCESS)
+
+ return EXIT_FAILURE;
+
+ printf("aflag = %d, bflag = %d, cvalue = %s\n",
+ aflag, bflag, cvalue);
+
+ while (*++argv != NULL)
+ printf("Non-option argument %s\n", *argv);
+
+ return EXIT_SUCCESS;
+ }
+
+Verbosity levels
+----------------
+
+.. code-block:: c
+
+ static int verbosity = 1; /* somewhat silent by default */
+ static const struct HXoption options_table[] = {
+ {.sh = 'q', .type = HXTYPE_NONE | HXOPT_DEC, .ptr = &verbosity,
+ .help = "Reduce verbosity"},
+ {.sh = 'v', .type = HXTYPE_NONE | HXOPT_INC, .ptr = &verbosity,
+ .help = "Increase verbosity"},
+ HXOPT_TABLEEND,
+ };
+
+This sample option table makes it possible to turn the verbosity of the program
+up or down, depending on whether the user specified ``-q`` or ``-v``. By passing
+multiple ``-v`` flags, the verbosity can be turned up even more. The range depends
+on the ``int`` data type for your particular platform and compiler; if you want
+to have the verbosity capped at a specific level, you will need to use an extra
+callback:
+
+.. code-block:: c
+
+ static int verbosity = 1;
+
+ static void v_check(const struct HXoptcb *cbi)
+ {
+ if (verbosity < 0)
+ verbosity = 0;
+ else if (verbosity > 4)
+ verbosity = 4;
+ }
+
+ static const struct HXoption options_table[] = {
+ {.sh = 'q', .type = HXTYPE_NONE | HXOPT_DEC, .ptr = &verbosity,
+ .cb = v_check, .help = "Lower verbosity"},
+ {.sh = 'v', .type = HXTYPE_NONE | HXOPT_INC, .ptr = &verbosity,
+ .cb = v_check, .help = "Raise verbosity"},
+ HXOPT_TABLEEND,
+ };
+
+Mask operations
+---------------
+
+.. code-block:: c
+
+ /* run on all CPU cores by default */
+ static unsigned int cpu_mask = ~0U;
+ /* use no network connections by default */
+ static unsigned int net_mask = 0;
+ static struct HXoption options_table[] = {
+ {.sh = 'c', .type = HXTYPE_UINT | HXOPT_NOT | HXOPT_AND, .ptr = &cpu_mask,
+ .help = "Mask of cores to exclude", .htyp = "cpu_mask"},
+ {.sh = 'n', .type = HXTYPE_UINT | HXOPT_OR, .ptr = &net_mask,
+
+ .help = "Mask of network channels to additionally use",
+ .htyp = "channel_mask"},
+ HXOPT_TABLEEND,
+ };
+
+What this options table does is ``cpu_mask &= ~x`` and ``net_mask |= y``, the
+classic operations of clearing and setting bits.
+
+Support for non-standard actions
+--------------------------------
+
+Supporting additional types or custom storage formats is easy, by simply using
+``HXTYPE_STRING``, ``NULL`` as the data pointer (usually by not specifying it
+at all), the pointer to your data in the user-specified pointer ``uptr``, and
+the callback function in ``cb``.
+
+.. code-block:: c
+
+ struct fixed_point {
+ int integral;
+ unsigned int fraction;
+ };
+
+ static struct fixed_point number;
+
+ static void fixed_point_parse(const struct HXoptcb *cbi)
+ {
+ char *end;
+
+ number.integral = strtol(cbi->data, &end, 0);
+ if (*end == '\0')
+ number.fraction = 0;
+ else if (*end == '.')
+ number.fraction = strtoul(end + 1, NULL, 0);
+ else
+ fprintf(stderr, "Illegal input.\n");
+ }
+
+ static const struct HXoption options_table[] = {
+ {.sh = 'n', .type = HXTYPE_STRING, .cb = fixed_point_parse,
+ .uptr = &number, .help = "Do this or that",
+ HXOPT_TABLEEND,
+
+ };
+
+Chained argument processing
+---------------------------
+
+On the first run, only ``--cake`` and ``--fruit`` is considered, which is then
+used to select the next set of accepted options. Note that
+``HXOPT_DESTROY_OLD`` is used here, which causes the ``argv`` that is produced
+by the first invocation of ``HX_getopt`` in the ``get_options`` function to be
+freed as it gets replaced by a new argv again by ``HX_getopt`` in
+``get_cakes``/``get_fruit``. ``HXOPT_DESTROY_OLD`` is however not specified in
+the first invocation, because the initial argv resides on the stack and cannot
+be freed.
+
+.. code-block:: c
+
+ static bool get_cakes(int *argc, const char ***argv)
+ {
+ struct HXoption option_table[] = {
+ ...
+ };
+ return HX_getopt(cake_table, argc, argv,
+ HXOPT_USAGEONERR | HXOPT_DESTROY_OLD) == HXOPT_ERR_SUCCESS;
+ }
+
+ static bool get_fruit(int *argc, const char ***argv)
+ {
+ struct HXoption fruit_table[] = {
+ ...
+ };
+ return HX_getopt(fruit_table, argc, argv,
+ HXOPT_USAGEONERR | HXOPT_DESTROY_OLD) == HXOPT_ERR_SUCCESS;
+ }
+
+ static bool get_options(int *argc, const char ***argv)
+ {
+ int cake = 0, fruit = 0;
+ struct HXoption option_table[] = {
+ {.ln = "cake", .type = HXTYPE_NONE, .ptr = &cake},
+ {.ln = "fruit", .type = HXTYPE_NONE, .ptr = &fruit},
+ HXOPT_TABLEEND,
+ };
+ if (HX_getopt(option_table, argc, argv, HXOPT_PTHRU) != HXOPT_ERR_SUCCESS)
+ return false;
+ if (cake)
+ return get_cakes(argc, argv);
+ else if (fruit)
+ return get_fruit(argc, argv);
+ return false;
+ }
diff --git a/doc/process_management.rst b/doc/process_management.rst
new file mode 100644
index 0000000..8fe282b
--- /dev/null
+++ b/doc/process_management.rst
@@ -0,0 +1,233 @@
+==================
+Process management
+==================
+
+Historic note: The process code comes from a time before posix_spawn. It also
+relies on the POSIX functions ``fork``, ``execv``, ``execvp`` and ``pipe``, so
+it may not be available everywhere. Where this is the case, the functions will
+return ``-ENOSYS``.
+
+Process metadata structure
+==========================
+
+.. code-block:: c
+
+ #include <libHX/proc.h>
+
+ struct HXproc {
+ const struct HXproc_ops *p_ops;
+ void *p_data;
+ unsigned int p_flags;
+
+ /* Following members should only be read */
+ int p_stdin, p_stdout, p_stderr;
+ int p_pid;
+ char p_status;
+ bool p_exited, p_terminated;
+ };
+
+When creating a new process with the intent of running it asynchronously (using
+``HXproc_run_async``), the first three fields must be filled in by the user.
+
+``p_ops``
+ A table of callbacks, generally used for setting and/or
+ restoring signals before/after execution. This member may be
+ ``NULL``.
+
+``p_data``
+ The user may provide a pointer of his choosing. It will be
+ passed the callback functions when invoked.
+
+``p_flags``
+ Process creation flags, see below.
+
+After the subprocess has been started, ``HXproc_run_async`` will have filled in
+some fields:
+
+``p_stdin``
+ If ``HXPROC_STDIN`` was specified in ``p_flags``, ``p_stdin`` will be
+ assigned the write side file descriptor of the subprocess's to-be
+ stdin. The subprocess will get the read side file descriptor in this
+ member. This is so that the correct fd is used in when
+ ``p_ops->p_postfork`` is called.
+
+``p_stdout``
+ If ``HXPROC_STDOUT`` is specified in ``p_flags``, ``p_stdout`` will be
+ assigned the read side file descriptor of the subprocess's to-be
+ stdout. The subprocess will get the write side file descriptor value
+ from this member.
+
+``p_stderr``
+ If ``HXPROC_STDERR`` is specified in ``p_flags``, ``p_stderr`` will be
+ assigned the read side file descriptor of the subprocess's to-be stderr, and
+ the subprocess will get the write side fd.
+
+``p_pid``
+ The process ID of the spawned process.
+
+Upon calling ``HXproc_wait``, further fields will have been filled when the
+function returns:
+
+``p_exited``
+ Whether the process exited normally (cf. signalled/terminated).
+
+``p_terminated``
+ Whether the process was terminated (signalled).
+
+``p_status``
+ The exit status of the process or the termination signal.
+
+Flags
+-----
+
+Possible values for the ``p_flags`` member are:
+
+``HXPROC_STDIN``
+ The subprocess's stdin file descriptor shall be connected to the master
+ program, that is, not inherit the stdin of the master. Cannot be used
+ with ``HXproc_run_sync`` (because there would be no one to provide data
+ in a sync operation).
+
+``HXPROC_STDOUT``
+ Connect the stdout file descriptor of the subprocess with the master.
+ Cannot be used with ``HXproc_run_sync``.
+
+``HXPROC_STDERR``
+ Connect the stderr file descriptor of the subprocess with the master.
+ Cannot be used with ``HXproc_run_sync``.
+
+``HXPROC_NULL_STDIN``
+ The subprocess's stdin file descriptor shall be connected to
+ ``/dev/null``. ``HXPROC_STDIN`` and ``HXPROC_NULL_STDIN`` are mutually
+ exclusive.
+
+``HXPROC_NULL_STDOUT``
+ Connect the stdout file descriptor of the subprocess to ``/dev/null``,
+ thereby essentially discarding its output. ``HXPROC_STDOUT`` and
+ ``HXPROC_NULL_STDOUT`` are mutually exclusive.
+
+``HXPROC_NULL_STDERR``
+ Connect the stderr file descriptor of the subprocess to ``/dev/null``,
+ thereby essentially discarding its output. ``HXPROC_STDERR`` and
+ ``HXPROC_NULL_STDERR`` are mutually exclusive.
+
+``HXPROC_VERBOSE``
+ Have the subprocess print an error message to stderr if exec'ing
+ returned an error.
+
+``HXPROC_A0``
+ ``argv[0]`` refers to program file, while ``argv[1]`` to the program
+ invocation name, with ``argv[2]`` being the first argument, etc.
+ Without this flag, ``argv[0]`` will be both the program file and
+ program invocation name, and arguments begin at ``argv[1]``.
+
+``HXPROC_EXECV``
+ Normally, ``execvp`` will be used which scans ``$PATH for the program.
+ Use this flag to use ``execv`` instead, which will not do such thing.
+
+Callbacks
+=========
+
+.. code-block:: c
+
+ #include <libHX/proc.h>
+
+ struct HXproc_ops {
+ void (*p_prefork)(void *);
+ void (*p_postfork)(void *);
+ void (*p_complete)(void *);
+ };
+
+``struct HXproc_ops`` provides a way to run user-specified functions just
+before the fork, after, and when the process has been waited for. They can be
+used to set and/or restore signals as needed, for example. The function
+pointers can be ``NULL``. The ``p_data`` member is passed as an argument.
+
+``p_prefork``
+ Run immediately before calling ``fork``. This is useful for taking any
+ action regarding signals, like setting ``SIGCHLD`` to ``SIG_DFL``, or
+ ``SIGPIPE`` to ``SIG_IGN``, for example.
+
+``p_postfork``
+ Run in the subprocess (and only there) after forking. Useful
+ to do a ``setuid`` or other change in privilege level.
+
+``p_complete``
+ Run in ``HXproc_wait`` when the process has been waited for.
+ Useful to restore the signal handler(s).
+
+Process control
+===============
+
+.. code-block:: c
+
+ #include <libHX/proc.h>
+
+ int HXproc_run_async(const char *const *argv, struct HXproc *proc);
+ int HXproc_run_sync(const char *const *argv, unsigned int flags);
+ int HXproc_wait(struct HXproc *proc);
+
+``HXproc_run_async``
+ Start a subprocess according to the parameters in proc. Returns a
+ negative errno code if something went wrong, or positive non-zero on
+ success.
+
+``HXproc_run_sync``
+ Start a subprocess synchronously, similar to calling ``system``, but
+ with the luxury of being able to specify arguments as separate strings
+ (via argv) rather than one big command line that is run through the
+ shell. ``flags`` is a value composed of the HXproc flags mentioned
+ above. ``HXPROC_STDIN``, ``HXPROC_STDOUT`` and ``HXPROC_STDERR`` are ignored
+ because there would be no one in a synchronous execution that
+ could supply data to these file descriptors or read from them.[#f1]_
+
+.. [#f1] Even for threads, please just use the async model.
+
+``HXproc_wait``
+ Wait for a subprocess to terminate, if it has not already. It will also
+ retrieve the exit status of the process and store it in the ``struct
+ HXproc``.
+
+The return value will be positive non-zero on success, or negative on
+error. Underlying system function's errors are returned, plus:
+
+``EINVAL``
+ Flags were not accepted.
+
+
+User identity control
+=====================
+
+.. code-block: c
+
+ #include <libHX/proc.h>
+
+ int HXproc_switch_user(const char *user, const char *group);
+
+``HXproc_switch_user`` is a wrapper for changing process identity to an
+unprivileged user. This utilizes ``setuid``, and possibly ``setgid`` plus
+``initgroups``.
+
+``user`` can either be a username or a numeric UID in string form, the latter
+of which will be parsed with strtoul in automatic base. If ``user`` is ``NULL``
+or the empty string, no change of process user identity occurs.
+
+``group`` can likewise be a name or GID. When ``group`` is ``NULL``, the
+process group(s) will change to the the user's group(s) — both primary and
+secondary — provided a user was specified (see above). When ``gruop`` is the
+empty string, no change of process group identity occurs.
+
+
+Process information
+===================
+
+.. code-block:: c
+
+ #include <libHX/proc.h>
+
+ int HXproc_top_fd(void);
+
+``HXproc_top_fd``
+ This function gives a heuristic for the highest fd in the process.
+ The returned number may be higher than the highest live fd actually.
+ On error, negative errno is returned.
diff --git a/doc/random_numbers.rst b/doc/random_numbers.rst
new file mode 100644
index 0000000..2b87d5d
--- /dev/null
+++ b/doc/random_numbers.rst
@@ -0,0 +1,32 @@
+==============
+Random numbers
+==============
+
+Function overview
+=================
+
+.. code-block:: c
+
+ #include <libHX/misc.h>
+
+ int HX_rand(void);
+ unsigned int HX_irand(unsigned int min, unsigned int max);
+ double HX_drand(double min, double max);
+
+``HX_rand``
+ Retrieve the next random number.
+
+``HX_irand``
+ Retrieve the next random number and fold it such that *min <= n < max*.
+
+``HX_drand``
+ Retrieve the next random number and fold it such that *min <= n < max*.
+
+Implementation information
+==========================
+
+``/dev/urandom`` will be used to seed the libc-level number generator.
+
+``/dev/random`` is not used on Linux because it may block during read, and
+/dev/urandom is just as good when there is entropy available. If you need
+definitive PRNG security, perhaps use one from a crypto suite such as OpenSSL.
diff --git a/doc/shconfig.rst b/doc/shconfig.rst
new file mode 100644
index 0000000..2e30a60
--- /dev/null
+++ b/doc/shconfig.rst
@@ -0,0 +1,116 @@
+=====================================
+Shell-style configuration file parser
+=====================================
+
+libHX provides functions to read shell-style configuration files. Such files
+are common, for example, in ``/etc/sysconfig`` on Linux systems. The format is
+pretty basic; it only knows about ``key=value`` pairs and does not even have
+sections like INI files. Not relying on any features however makes them quite
+interchangable as the syntax is accepted by Unix Shells.
+
+Lines beginning with a hash mark (``#``) are ignored, as are empty lines and
+unrecognized keys.
+
+.. code-block:: sh
+
+ # Minimum / maximum values for automatic UID selection
+ UID_MIN=100
+ UID_MAX=65000
+
+ # Home directory base
+ HOME="/home"
+ #HOME="/export/home"
+
+Any form of variable or parameter substitution or expansion is highly
+implementation specific, and is not supported in libHX's reader. Even Shell
+users should not rely on it as you never know in which context the
+configuration files are evaluated. Still, you will have to escape specific
+sequences like you would need to in Shell. The use of single quotes is
+acceptable. That means::
+
+.. code-block:: sh
+
+ AMOUNT="US\$5"
+ AMOUNT='US$5'
+
+Synopsis
+========
+
+.. code-block:: c
+
+ #include <libHX/option.h>
+
+ int HX_shconfig(const char *file, const struct HXoption *table);
+ int HX_shconfig_pv(const char **path_vec, const char *file, const struct HXoption *table, unsigned int flags);
+ struct HXmap *HX_shconfig_map(const char *file);
+
+The shconfig parser reuses ``struct HXoption`` that fits very well in
+specifying name-pointer associations. ``HX_shconfig`` will read the given file
+using the key-to-pointer mappings from the table to store the variable
+contents. Of ``struct HXoption``, only the ``ln``, ``type`` and ``ptr`` fields
+are used. The list of accepted types is described in
+section [subsec:option-types].
+
+To parse a file, call ``HX_shconfig`` function with the corresponding
+parameters. If you want to read configuration files from different paths, i.e.
+to build up on default values, you can use ``HX_shconfig_pv``, which is a
+variant for reading a file from multiple locations. Its purpose is to
+facilitate reading system-wide settings which are then overriden by a file in
+the users home directory, for example (per-setting-override). It is also
+possible to do per-file-override, that is, a file in the home directory has
+higher precedence than a system-wide one in such a way that the system-wide
+configuration file is not even read. This is accomplished by traversing the
+paths in the “other” direction (actually you have to turn the array around) and
+stopping at the first existing file by use of the ``SHCONF_ONE`` flag.
+
+.. [#f2] pv = path vector
+
+``HX_shconfig_map`` will return all entries from the file in a HXmap, usable
+for parsing arbitrary keys without having to specify any static key table.
+
+``SHCONF_ONE``
+ Parsing files will stop after one file has been successfully parsed.
+ This allows for a “personal overrides system config” style.
+
+The call to ``HX_shconfig`` will either return >0 for success, 0 for no success
+(actually, this is never returned) and ``-errno`` for an error.
+
+Example
+=======
+
+Per-setting-override
+--------------------
+
+This example sources key-value pairs from a configuration file in a system
+location (``/etc``) first, before overriding specific keys with new values from the
+file in the home directory.
+
+.. code-block:: c
+
+ long uid_min, uid_max;
+ char *passwd_file;
+ struct HXoption options_table[] = {
+ {.ln = "UID_MIN", .type = HXTYPE_LONG, .ptr = &uid_min},
+ {.ln = "UID_MAX", .type = HXTYPE_LONG, .ptr = &uid_max},
+ {.ln = "PWD_FILE", .type = HXTYPE_STRING, .ptr = &passwd_file},
+ HXOPT_TABLEEND,
+ };
+ const char *home = getenv("HOME");
+ const char *paths[] = {"/etc", home, NULL};
+ HX_shconfig(paths, "test.cf", options_table, 0);
+
+Per-file-override
+-----------------
+
+This particular example reads from the file in the home directory first (if it
+exists), but stops after it has been successful, so any subsequent locations
+listed in the paths variable are not read. This has the effect that the file
+from the home directory has the highest priority too like in the previous
+example, but without any keys from the system files. Note the ``SHCONF_ONE``
+flag.
+
+.. code-block:: c
+
+ const char *home = getenv("HOME");
+ const char *paths[] = {home, "/usr/local/etc", "/etc", NULL};
+ HX_shconfig_pv(paths, "test.cf", options_table, SHCONF_ONE);
diff --git a/doc/slurp.c b/doc/slurp.c
deleted file mode 100644
index f0b047d..0000000
--- a/doc/slurp.c
+++ /dev/null
@@ -1,38 +0,0 @@
-static void *p_slurp(const char *file, size_t *outsize)
-{
- struct stat sb;
- int ret = 0, fd = open(file, O_RDONLY | O_BINARY);
- void *buf = NULL;
- ssize_t rdret;
-
- if (fd < 0) {
- fprintf(stderr, "ERROR: Slurping %s failed: %s\n",
- file, strerror(errno));
- return NULL;
- }
- if (fstat(fd, &buf) < 0) {
- ret = errno;
- perror("fstat");
- goto out;
- }
- *outsize = sb.st_size; /* truncate if need be */
- buf = malloc(*outsize);
- if (buf == NULL) {
- ret = errno;
- perror("malloc");
- goto out;
- }
- rdret = read(fd, buf, *outsize);
- if (rdret < 0) {
- ret = errno;
- perror("read");
- free(buf);
- } else {
- *outsize = rdret;
- }
- out:
- close(fd);
- errno = ret;
- return buf;
-}
-
diff --git a/doc/socket_functions.rst b/doc/socket_functions.rst
new file mode 100644
index 0000000..fe2b69d
--- /dev/null
+++ b/doc/socket_functions.rst
@@ -0,0 +1,16 @@
+================
+Socket functions
+================
+
+.. code-block:: c
+
+ #include <libHX/socket.h>
+
+ int HX_socket_from_env(const struct addrinfo *ai, const char *intf);
+
+``HX_socket_from_env``
+ The function looks up the current process's file descriptors for a
+ socket that is listening and which matches the given addrinfo and
+ (optionally) intf if the latter is not NULL``. Upon success, the fd
+ number is returned, or -1 if no file descriptor matched. No errors are
+ signalled.
diff --git a/doc/string_formatter.rst b/doc/string_formatter.rst
new file mode 100644
index 0000000..fdb9c19
--- /dev/null
+++ b/doc/string_formatter.rst
@@ -0,0 +1,210 @@
+=======================
+String format templates
+=======================
+
+HXfmt is a template system for by-name variable expansion. It can be used to
+substitute placeholders in format strings supplied by the user by appropriate
+expanded values defined by the program. Such can be used to allow for flexible
+configuration files that define key-value mappings such as
+
+::
+
+ detect_peer = ping6 -c1 %(ADDR)
+ #detect_peer = nmap -sP %(ADDR) | grep -Eq "appears to be up"
+
+Consider, for example, a monitoring daemon that allows the administrator to
+specify a program of his choice with which to detect whether a peer is alive or
+not. The user can choose any program that is desired, but evidently needs to
+pass the address to be tested to the program. This is where the daemon will do
+a substitution of the string ``ping -c1 %(ADDR)`` it read from the config file,
+and put the actual address in it before finally executing the command.
+
+.. code-block:: c
+
+ printf("%s has %u files\n", user, num);
+ printf("%2$u files belong to %1$s\n", num, user);
+
+``%s`` (or ``%1$s`` here) specifies how large ``user`` is — ``sizeof(const char
+*)`` in this case. If that is missing, there is no way to know the offset of
+``num`` relative to ``user``, making varargs retrieval impossible.
+
+``printf``, at least from GNU libc, has something vaguely similar: positional
+parameters. They have inherent drawbacks, though. One is of course the question
+of portability, but there is a bigger issue. All parameters must be specified,
+otherwise there is no way to determine the location of all following objects
+following the missing one on the stack in a varargs-function like printf, which
+makes it unsuitable to be used with templates where omitting some placeholders
+is allowed.
+
+Initialization, use and deallocation
+====================================
+
+.. code-block:: c
+
+ #include <libHX/option.h>
+
+ struct HXformat_map *HXformat_init(void);
+ void HXformat_free(struct HXformat_map *table);
+ int HXformat_add(struct HXformat_map *table, const char *key, const void *ptr, unsigned int ptr_type);
+
+``HXformat_init`` will allocate and set up a string-to-string map that is used
+for the underlying storage, and returns it.
+
+To release the substitution table and memory associated with it, call
+``HXformat_free``.
+
+``HXformat_add`` is used to add substitution entries. One can also specify
+other types such as numeric types. ``ptr_type`` describes the type behind
+``ptr`` and the constants are the same from ``option.h`` (cf. section on
+optionp arsing) — not all constants can be used, though, and their meaning also
+differs from what ``HX_getopt`` or ``HX_shconfig`` use them for — the two could
+be seen as “read” operations, while ``HXformat`` is a write operation.
+
+Immediate types
+===============
+
+“Immediate types” are resolved when ``HXformat_add`` is called, that is, they
+are copied and inserted into the tree, and are subsequently independent from
+any changes to variables in the program. Because the HXopt-originating type
+name, i.e. ``HXTYPE_*``, is also used for deferred types, the constant
+``HXFORMAT_IMMED`` needs to be specified on some types to denote an immediate
+value.
+
+* ``HXTYPE_STRING`` — ptr is a ``const char *``.
+
+* ``HXTYPE_{U,}{CHAR,SHORT,INT,LONG,LLONG} | HXFORMAT_IMMED`` —
+ mapping to the standard typesk
+
+Deferred types
+==============
+
+“Deferred types” are resolved on every invocation of a formatter function
+(``HXformat_*printf``). The expansions may be changed by modifying the
+underlying variable pointed to, but the pointer must remain valid and its
+pointee not go out of scope. Code samples are provided below.
+
+* ``HXTYPE_STRP`` — ptr is a ``const char *const *``; the
+ pointer resolution is deferred until the formatter is called with one of the
+ ``HXformat_*printf`` functions. Deferred in the sense it is always resolved
+ anew.
+
+* ``HXTYPE_BOOL`` — ptr is a ``const int *``.
+
+* ``HXTYPE_{U,}..``, ``HXTYPE_FLOAT``, ``HXTYPE_DOUBLE`` — mapping to the
+ standard types with one indirection (e.g. ``int *``).
+
+Invoking the formatter
+======================
+
+.. code-block:: c
+
+ int HXformat_aprintf(struct HXformat_map *table, hxmc_t **dest, const char *template);
+ int HXformat_sprintf(struct HXformat_map *table, char *dest, size_t size, const char *template);
+ int HXformat_fprintf(struct HXformat_map *table, FILE *filp, const char *template);
+
+``HXformat_aprintf``
+ Substitutes placeholders in template using the given table. This will
+ produce a string in a HX memory container (``hxmc_t``), and the pointer
+ is placed into ``*dest``. The caller will be responsible for freeing it
+ later when it is done using the result.
+
+``HXformat_sprintf``
+ Does substitution and stores the expanded result in the buffer ``dest``
+ which is of size ``size``.
+
+``HXformat_fprintf``
+ Does substituion and directly outputs the expansion to the given stdio
+ stream.
+
+On success, the length of the expanded string is returned, excluding the
+trailing ``\0``. While ``HXformat_sprintf`` will not write more than ``size``
+bytes (including the ``\0``), the length it would have taken is returned,
+similar to what sprintf does. On error, ``-errno`` is returned.
+
+The HXformat function family recognizes make-style like functions and recursive
+expansion, described below.
+
+Functions
+=========
+
+To expand a variable, one uses a syntax like ``%(NAME)`` in the format string.
+Recursive expansion like ``%(%(USER))`` is supported; assuming ``%(USER)``
+would expand to ``linux``, HXformat would try to resolve ``%(linux)`` next.
+Besides these variable substitutions, HXformat also provides function calls
+whose syntax isx ``%(nameOfFunction parameters[...])``. Parameters can be any
+text, including variables. Paramters are separated from another by a delimiter
+specific to each function. See this list for details:
+
+* ``%(env variable)``
+
+ The ``env`` function expands to the string that is stored in the
+ environmental variable by the given name.
+
+* ``%(exec command [args...])``
+
+ The ``exec`` function expands to the standard output of the command. The
+ command is directly run without shell invocation, so no special character
+ expansion (wildcards, etc.) takes place. stdin is set to ``/dev/null``. The
+ parameter delimiter is the space character. To be able to use this function —
+ as it is relevant to security — the fmt table needs to have a key
+ with the magic value ``/libhx/exec``.
+
+* ``%(if condition,[then][,[else]])``
+
+ If the condition parameter expands to a string of non-zero length, the
+ function expands to the ``then`` block, otherwise the ``else`` block. The
+ delimiter used is a comma.
+
+* ``%(lower text)``, ``%(upper text)``
+
+ Lowercases or uppercases the supplied argument. As these functions are meant
+ to take only one argument, there is no delimiter defined that would need
+ escaping if multiple arguments were supposed to be passed. ``%(lower a,b)``
+ is equivalent to ``%(lower "a,b")``.
+
+* ``%(shell command [args...])``
+
+ Similar to ``%(exec)``, but invokes the shell inbetween (i.e. ``sh -c
+ 'command...'``) such that special characters, redirection, and so on can be
+ used.
+
+* ``%(substr text,offset[,length])``
+
+ Extracts a substring out of the given text, starting at offset and running
+ for the given length. If no length is given, will extract until the end of
+ the string. If ``offset`` is negative, it specifies the offset from the end
+ of the string. If ``length`` is negative, that many characters are left off
+ the end.
+
+* ``%(snl text)``
+
+ Strips trailing newlines from text and replaces any other newline by a space.
+ What happens implicity in Makefiles' ``$(shell ...)`` statements usually is
+ explicitly separate in libHX.
+
+Example: Immediate and deferred resolution
+==========================================
+
+.. code-block:: c
+
+ const char *b = "Hello World";
+ char c[] = "Hello World";
+ struct HXformat_map *table = HXformat_init();
+ HXformat_add(table, "%(GREETING1)", b, HXTYPE_STRING);
+ HXformat_add(table, "%(GREETING2)", &c, HXTYPE_STRP);
+ b = NULL;
+ snprintf(c, sizeof(c), "Hello Home");
+ HXformat_aprintf(...);
+
+Upon calling ``HXformat_*printf``, ``%(GREETING1)`` will expand to ``Hello
+World`` whereas ``%(GREETING2)`` will expand to ``Hello Home``.
+
+
+Example: Using the %(exec) function
+===================================
+
+.. code-block:: c
+
+ struct HXformat_map *table = HXformat_init();
+ HXformat_add(table, "/libhx/exec", NULL, HXTYPE_IMMED);
+ HXformat_aprintf(table, &result, "%(exec uname -s)");
diff --git a/doc/string_ops.rst b/doc/string_ops.rst
new file mode 100644
index 0000000..9bb711f
--- /dev/null
+++ b/doc/string_ops.rst
@@ -0,0 +1,569 @@
+=================
+String operations
+=================
+
+Some string functions are merely present in libHX because they are otherwise
+unportable; some are only in the C libraries of the BSDs, some only in GNU
+libc.
+
+
+Locating chars
+==============
+
+.. code-block:: c
+
+ #include <libHX/string.h>
+
+ void *HX_memmem(const void *haystack, size_t hsize, const void *needle, size_t nsize);
+ char *HX_strbchr(const char *start, const char *now, char delimiter);
+ char *HX_strchr2(const char *s, const char *accept);
+ size_t HX_strrcspn(const char *s, const char *reject);
+
+``HX_memmem``
+ Analogous to ``strstr``(3), ``memmem`` tries to locate the memory block
+ pointed to by ``needle`` (which is of length ``nsize``) in the block
+ pointed to by ``haystack`` (which is of size ``hsize``). It returns a
+ pointer to the first occurrence in ``haystack``, or ``NULL`` when it
+ was not found.
+
+``HX_strbchr``
+ Searches the character specified by delimiter in the range from ``now``
+ to ``start``. It works like ``strrchr``(3), but begins at ``now``
+ rather than the ``end`` of the string.
+
+``HX_strchr2``
+ This function searches the string ``s`` for any set of bytes that are
+ not specified in the second argument, ``n``. In this regard, the
+ function is the opposite to ``strpbrk``(3).
+
+``HX_strrcspn``
+ Works like ``strcspn``(3), but processes the string from ``end`` to
+ ``start``.
+
+
+Extraction
+==========
+
+.. code-block:: c
+
+ #include <libHX/string.h>
+
+ char *HX_basename(const char *s);
+ char *HX_basename_exact(const char *s);
+ char *HX_dirname(const char *s);
+ char *HX_strmid(const char *s, long offset, long length);
+
+``HX_basename``
+ Returns a pointer to the basename portion of the supplied path ``s``.
+ The result of this function is never ``NULL``, and must never be freed
+ either. Trailing slashes are not stripped, to avoid having to do an
+ allocation. In other words, ``HX_basename("/mnt/")`` will return
+ ``mnt/``. If you need to have the slashes stripped, use
+ ``HX_basename_exact``. A possible use for this function is, for
+ example, to derive a logging prefix from ``argv[0]``.
+
+.. code-block:: c
+
+ int main(int argc, const char **argv)
+ {
+ if (foo())
+ fprintf(stderr, "%s: Special condition occurred.\n",
+ HX_basename(argv[0]));
+ return 0;
+ }
+
+``HX_basename_exact``
+ The accurate and safe version of ``HX_basename`` that deals with
+ trailing slashes correctly and produces the same result as
+ ``dirname``(3). It returns a pointer to a newly-allocated string that
+ must be freed when done using. ``NULL`` may be returned in case of an
+ allocation error.
+
+``HX_dirname``
+ Returns a pointer to a new string that contains the directory name
+ portion (everything except basename). When done using the string, it
+ must be freed to avoid memory leaks.
+
+``HX_strmid``
+ Extract a substring of length characters from ``s``, beginning at
+ ``offset``. If ``offset`` is negative, counting beings from the end of
+ the string; -1 is the last character (not the ``'\0'`` byte). If
+ ``length`` is negative, it will leave out that many characters off the
+ end. The function returns a pointer to a new string, and the user has
+ to free it.
+
+
+In-place transformations
+========================
+
+.. code-block:: c
+
+ #include <libHX/string.h>
+
+ char *HX_chomp(char *s);
+ size_t HX_strltrim(char *s);
+ char *HX_stpltrim(const char *s);
+ char *HX_strlower(char *s);
+ char *HX_strrev(char *s);
+ size_t HX_strrtrim(char *s);
+ char *HX_strupper(char *s);
+
+``HX_chomp``
+ Removes the characters ``'\r'`` and ``'\n'`` from the right edge of the
+ string. Returns the original argument.
+
+``HX_strltrim``
+ Trims all whitespace (characters on which ``isspace``(3) returns true)
+ on the left edge of the string. Returns the number of characters that
+ were stripped.
+
+``HX_stpltrim``
+ Returns a pointer to the first non-whitespace character in ``s``.
+
+``HX_strlower``
+ Transforms all characters in the string ``s`` into lowercase using
+ ``tolower``(3). Returns the original argument.
+
+``HX_strrev``
+ Reverse the string in-place. Returns the original argument.
+
+``HX_strrtrim``
+ Trim all whitespace on the right edge of the string. Returns the number
+ of characters that were stripped.
+
+``HX_strupper``
+ Transforms all characters in the string ``s`` into uppercase using
+ ``toupper``(3). Returns the original argument.
+
+
+Out-of-place quoting transforms
+===============================
+
+.. code-block:: c
+
+ #include <libHX/string.h>
+
+ char *HX_strquote(const char *s, unsigned int type, char **free_me);
+
+``HX_strquote`` will escape metacharacters in a string according to type, and
+returns the escaped result.
+
+Possible values for type:
+
+``HXQUOTE_SQUOTE``
+ Escapes all single quotes and backslashes in a string with a backslash.
+ (``Ol' \Backslash`` becomes ``Ol\' \\Backslash``.)
+
+``HXQUOTE_DQUOTE``
+ Escapes all double quotes and backslahes in a string with the backslash
+ method. (``Ol” \Backslash`` becomes ``Ol\” \\Backslash``.)
+
+``HXQUOTE_HTML``
+ Escapes ``'<'``, ``'>'``, ``'&'`` and ``'"'`` by their respective HTML
+ entities, ``&lt;``, ``&gt;``, ``&amp;`` and ``&quot;``.
+
+``HXQUOTE_LDAPFLT``
+ Escapes the string using backslash-plus-hexcode notation as described
+ in `RFC 4515`_, to make it suitable for use in an LDAP search
+ filter.
+
+``HXQUOTE_LDAPRDN``
+ Escapes the string using backslash-plus-hexcode notation as described
+ in `RFC 4514`_, to make it suitable for use in an LDAP Relative
+ Distinguished Name.
+
+``HXQUOTE_BASE64``
+ Transforms the string to BASE64, as described in `RFC 4648`_.
+
+``HXQUOTE_BASE64URL``
+ Transforms the string to base64url, as described in `RFC 4648`_.
+
+``HXQUOTE_BASE64IMAP``
+ Transforms the string to base64 for IMAP, as described in `RFC 3501`_.
+
+``HXQUOTE_URIENC``
+ Escapes the string so that it becomes a valid part for an URI.
+
+``HXQUOTE_SQLSQUOTE``
+ Escapes all single quotes in the string by double single-quotes, as
+ required for using it in a single-quoted SQL string. No surrounding
+ quotes will be generated to facilitate concatenating of HX_strquote
+ results.
+
+``HXQUOTE_SQLBQUOTE``
+ Escape all backticks in the string by double backticks, as required for
+ using it in a backtick-quoted SQL string (used for table names and
+ columns). No surrounding ticks will be generated to facilitate
+ concatenation.
+
+.. _RFC 4514: http://tools.ietf.org/html/rfc4514
+.. _RFC 4515: http://tools.ietf.org/html/rfc4515
+.. _RFC 4648: http://tools.ietf.org/html/rfc4648
+
+Specifying an unrecognized type will result in ``NULL`` being returned and
+``errno`` be set to ``EINVAL``.
+
+If ``free_me`` is ``NULL``, the function will always allocate memory, even if
+the string needs no quoting. The program then has to free the result:
+
+.. code-block:: c
+
+ char *s = HX_strquote("<head>", HXQUOTE_HTML, NULL);
+ printf("%s\n", s);
+ free(s);
+
+If ``free_me`` is not ``NULL`` however, the function will put the pointer to
+the memory area into ``*free_me``, if the string needed quoting. The program
+then has to free that after it is done with the quoted result:
+
+.. code-block:: c
+
+ char *tmp = NULL;
+ char *s = HX_strquote("head", HXQUOTE_HTML, &tmp);
+ printf("%s\n", s);
+ free(tmp);
+
+``tmp`` could be ``NULL``, and since ``free(NULL)`` is not an error, this is
+perfectly valid. Furthermore, if ``*free_me`` is not ``NULL`` by the time
+``HX_strquote`` is called, the function will free it. This makes it possible to
+call ``HX_strquote`` in succession without explicit free calls in between:
+
+.. code-block:: c
+
+ char *tmp = NULL;
+ printf("%s\n", HX_strquote("<html>", HXQUOTE_HTML, &tmp));
+ printf("%s\n", HX_strquote("<head>", HXQUOTE_HTML, &tmp));
+ free(tmp);
+
+
+Tokenizing
+==========
+
+.. code-block:: c
+
+ #include <libHX/string.h>libHX/string.h
+
+ char **HX_split(const char *s, const char *delimiters, size_t *fields, int max);
+ char **HX_split_inplace(char *s, const char *delimiters, int *fields, int max);
+ int HX_split_fixed(char *s, const char *delimiters, int max, char **arr);
+ char *HX_strsep(char **sp, const char *delimiters);
+ char *HX_strsep2(char **sp, const char *dstr);
+
+``HX_split``
+ Splits the string ``s`` on any characters from the ``delimiters``
+ string. Both the substrings and the array holding the pointers to these
+ substrings will be allocated as required; the original string is not
+ modified. If ``max`` is larger than zero, produces no more than ``max``
+ fields. If ``fields`` is not ``NULL``, the number of elements produced
+ will be stored in ``*fields``. The result is a NULL-terminated array of
+ ``char *``s, and the user needs to free it when done with it, using
+ ``HX_zvecfree`` or equivalent. An empty string (zero-length string) for
+ ``s`` yields a single field.
+
+``HX_split_inplace``
+ Splits the string ``s`` in-place on any characters from the
+ ``delimiters`` string. The resulting array will hold pointers to parts
+ of the original string. The array itself needs to be freed by the user,
+ using ``free``(3), the individual elements must not be freed. The
+ ``fields`` and ``max`` arguments work as with ``HX_split``.
+
+``HX_split_fixed``
+ Splits the string ``s`` in-place on any characters from the
+ ``delimiters`` string. The array for the substring pointers must be
+ provided by the user through the ``arr`` argument. ``max`` must be the
+ number of elements in the array, or less. The array will *not* be
+ NULL-terminated[#fixfoot]. The number of fields produced is returned.
+
+.. [#fixfoot] An implementation may however decide to put ``NULL`` in the
+ unassigned fields, but this is implementation-dependent.
+
+``HX_strsep``
+ Extract tokens from a string. This implementation of strsep has been
+ added since the function is non-standard (according to the manpage,
+ conforms to BSD4.4 only) and may not be available on every operating
+ system. This function extracts tokens, separated by one of the
+ characters in ``delimiters``. The string is modified in-place and thus
+ must be mutable. The delimiters in the string are then overwritten with
+ ``'\0'``, ``*sp`` is advanced to the character after the delimiter, and
+ the original pointer is returned. After the final token, ``HX_strsep``
+ will return ``NULL``.
+
+``HX_strsep2``
+ Like ``HX_strsep``, but ``dstr`` is not an array of delimiting
+ characters, but an entire substring that acts as one delimiter.
+
+
+Size-bounded string operations
+==============================
+
+.. code-block:: c
+
+ #include <libHX/string.h>
+
+ char *HX_strlcat(char *dest, const char *src, size_t length);
+ char *HX_strlcpy(char *dest, const char *src, size_t length);
+ char *HX_strlncat(char *dest, const char *src, size_t dlen, size_t slen);
+ size_t HX_strnlen(const char *src, size_t max);
+
+``HX_strlcat`` and ``HX_strlcpy`` provide implementations of the
+BSD-originating ``strlcat``(3) and ``strlcpy``(3) functions. ``strlcat`` and
+``strlcpy`` are less error-prone variants for ``strncat`` and ``strncpy`` as
+they always take the length of the entire buffer specified by ``dest``, instead
+of just the length that is to be written. The functions guarantee that the
+buffer is ``'\0'``-terminated.
+
+``HX_strnlen`` will return the length of the input string or the upper bound
+given by ``max``, whichever is less. It will not attempt to access more than
+this many bytes in the input buffer.
+
+
+Allocation-related
+==================
+
+.. code-block:: c
+
+ #include <libHX/string.h>
+
+ void *HX_memdup(const void *ptr, size_t length);
+ char *HX_strdup(const char *str);
+ char *HX_strndup(const char *str, size_t max);
+ char *HX_strclone(char **pa, const char *pb);
+
+ #ifdef __cplusplus
+ template<typename type> type HX_memdup(const void *ptr, size_t length);
+ #endif
+
+``HX_memdup``
+ Duplicates `length` bytes from the memory area pointed to by ``ptr``
+ and returns a pointer to the new memory block. ``ptr`` may not be
+ ``NULL``.
+
+``HX_strdup``
+ Duplicates the string. The function is equivalent to ``strdup``, but
+ the latter may not be available on all platforms. ``str`` may be
+ ``NULL``, in which case ``NULL`` is also returned.
+
+``HX_strndup``
+ Duplicates the input string, but copies at most ``max`` characters.
+ (The resulting string will be ``NUL``-terminated of course.) ``str``
+ may not be ``NULL``.
+
+``HX_strclone``
+ Copies the string pointed to by ``pb`` into ``*pa``. If ``*pa`` was not
+ ``NULL`` by the time ``HX_strclone`` was called, the string is freed
+ before a new one is allocated. The function returns ``NULL`` and sets
+ ``errno`` to ``EINVAL`` if ``pb`` is ``NULL`` (this way it can be
+ freed), or, if ``malloc`` fails, returns ``NULL`` and leaves ``errno``
+ at what ``malloc`` had set it to. The use of this function is
+ deprecated, albeit no replacement is proposed.
+
+
+Numbers to human-readable sizes with units
+==========================================
+
+.. code-block:: c
+
+ #include <libHX/string.h>
+
+ char *HX_unit_size(char *out, size_t outsize, unsigned long long number,
+ unsigned int divisor, unsigned int cutoff);
+ char *HX_unit_size_cu(char *out, size_t outsize,
+ unsigned long long number, unsigned int divisor);
+
+``HX_unit_size`` takes an arbitrary number and and produces a more
+readily-readable shortened (string) representation with a unit suffix. It does
+this by dividing ``number`` by ``pow(divisor, i)`` for some integer _i_ such
+that the resulting (integer) quotient is the highest possible value _v_ that is
+less than ``cutoff``. This value _v_ is then emitted into ``out`` together with
+the corresponding SI prefix.
+
+In other words, ``cutoff`` is the value when it attempts to do another
+iteration of the division. For example, if the cutoff is set at 8192,
+then 8191 will stay as-is, but 8192 is reduced to "8K". The popular
+``wget`` utility implements a cutoff of 1024.
+
+Note that the SI prefix for one iteration (i==1), i.e. kilo, is a lower-case
+``'k'``. If you need consistent upper-case output in your program, (i.e. K/M/G
+instead of k/M/G), use a subsequent call to ``HX_strupper``.
+
+When ``divisor`` is 0, it defaults to 1000. When ``cutoff`` is 0, an
+implementation-defined cutoff point is used. When ``cutoff`` is less than
+``divisor``, the result is implementation-defined.
+
+The output number of ``HX_unit_size`` is always integer; no fractions are
+emitted. This is rooted in the following idea:
+
+* An output like ``1G`` is quite broad and some precision would be nice. The
+ author has historically preferred 3 digits instead of just 2, thanks to wget
+ and rsync.
+
+* ``1.34G`` has the same string length as ``1340M``, i.e. both occupy the same
+ visual space in console outputs, but the latter has another digit of
+ precision.
+
+* By ditching fractions this way, ``HX_unit_size`` also sidesteps the issue of
+ excess digits being emitted (usually up to 5) from the trivial use (by
+ wget/rsync) of ``printf("%.2f", v)``.
+
+(With regard to the 1.34G-vs-1340M argument, do note that, to actually receive
+"``1340M``" as output, you need to set a conveniently high cutoff value such
+as 10000. Otherwise, you might get "``1G``".)
+
+The ``HX_unit_size_cu`` function will instead mimic the behavior of coreutils
+(/usr/bin/df, /usr/bin/ls). That is, it divides ``number`` by ``pow(divisor,
+i)`` for some integer _i_ such that the resulting (real) quotient is
+less-than-or-equal ``divisor-1``. It rounds the value up to the next integer if
+the fractional part is >90%, and if the quotient is greater-or-equal 10, the
+fractional part is stripped and not emitted to ``out``.
+
+In practice, the rounding up of ``HX_unit_size_cu`` lends itself to display
+occupying sizes, whereas the implicit rounding down (of integer divisions)
+in ``HX_unit_size`` lend itself to sizes in progress meters.
+
+
+Unit-suffixed numbers to full numbers
+=====================================
+
+.. code-block:: c
+
+ #include <libHX/string.h>
+
+ double HX_strtod_unit(const char *s, char **end,
+ unsigned int exponent);
+ unsigned long long HX_strtoull_unit(const char *s, char **end,
+ unsigned int exponent);
+
+The ``HX_strtod_unit`` and ``HX_strtoull_unit`` functions behave similar to
+``strtod`` and ``strtoul``, respectively, in that they convert the initial part
+of the string in ``s`` to a ``double`` and ``unsigned long long``,
+respectively, and apply the selected multiplication factor from ``exponent`` in
+resolving an optional unit suffix.
+
+Upon overflow, ``errno`` is set to ``ERANGE`` just like the stdlib functions.
+Unlike some implementations of ``strtoul``, negative numbers are outright
+rejected.
+
+.. code-block:: c
+
+ unsigned long long bytes = HX_strtoull_unit("1.5G", NULL, 1024);
+
+
+Conversion from/to human-readable durations with units
+======================================================
+
+.. code-block:: c
+
+ #include <libHX/string.h>
+
+ unsigned long long HX_strtoull_sec(const char *s, char **end);
+ char *HX_unit_seconds(char *out, size_t outsize,
+ unsigned long long seconds,
+ unsigned int flags);
+
+``HX_strtoull_sec`` converts a time duration with units, such as ``"15min30s"``
+into an all-seconds value. The recognized unit strings are: ``years``,
+``year``, ``y``, ``months``, ``month``, ``days``, ``day``, ``d``, ``hours``,
+``hour``, ``h``, ``minutes``, ``minute``, ``min``, ``seconds``, ``second``,
+``s`` and the empty string (for seconds). When parsing stops at any point,
+``*end`` is set to the location, similar to how the ``strtoull`` C function
+would.
+
+One year is defined to be 365.25 days of 86400 seconds; one month is defined to
+be 1/12 such a year. This is consistent with the units employed by systemd.
+
+``HX_unit_seconds`` is the reverse and transforms the duration given by
+``seconds`` into a string representation broken into days, hours, minutes, and
+remaining seconds as appropriate. By default, only the d/h/min/s units are
+emitted. The ``flags`` argument specifies if any other units should be emitted;
+``HXUNIT_YEARS``, ``HXUNIT_MONTHS`` and ``HXUNIT_WEEKS`` are available.
+
+
+Examples
+========
+
+Using HX_split_fixed
+--------------------
+
+``HX_split_fixed`` is often used just with scoped automatic-storage variables
+and where the field count of interest is fixed, as the example for parsing
+``/etc/passwd`` shows:
+
+.. code-block:: c
+
+ #include <stdio.h>
+ #include <libHX/string.h>
+
+ char *field[8];
+ hxmc_t *line = NULL;
+
+ while (HX_getl(&line, fp) != NULL) {
+ if (HX_split_fixed(line, ":", ARRAY_SIZE(field), field) < 7) {
+ fprintf(stderr, "That does not look like a valid line.\n");
+ continue;
+ }
+ printf("Username: %s\n", field[0]);
+ }
+
+Using HX_split_inplace
+----------------------
+
+Where the number of fields is not previously known and/or estimatable, but the
+string can be modified in place, one uses ``HX_split_inplace`` as follows:
+
+.. code-block:: c
+
+ #include <errno.h>
+ #include <stdio.h>
+ #include <libHX/string.h>
+
+ while (HX_getl(&line, fp) != NULL) {
+ char **field = HX_split_inplace(line, ":", NULL, 0);
+ if (field == NULL) {
+ fprintf(stderr, "Badness! %s\n", strerror(errno));
+ break;
+ }
+ printf("Username: %s\n", field[0]);
+ free(field);
+ }
+
+Using HX_split
+--------------
+
+Where the string is not modifiable in-place, one has to resort to using the
+full-fledged ``HX_split`` that allocates space for each substring.
+
+.. code-block:: c
+
+ #include <errno.h>
+ #include <stdio.h>
+ #include <libHX/string.h>
+
+ while (HX_getl(&line, fp) != NULL) {
+ char **field = HX_split(line, ":", NULL, 0);
+ if (field == NULL) {
+ fprintf(stderr, "Badness. %s\n", strerror(errno));
+ break;
+ }
+ printf("Username: %s\n", field[0]);
+ /* Suppose “callme” needs the original string */
+ callme(line);
+ HX_zvecfree(field);
+ }
+
+Using HX_strsep
+---------------
+
+``HX_strsep`` provides for thread- and reentrant-safe tokenizing a string where
+strtok from the C standard would otherwise fail.
+
+.. code-block:: c
+
+ #include <stdio.h>
+ #include <libHX/string.h>
+
+ char line[] = "root:x:0:0:root:/root:/bin/bash";
+ char *wp, *p;
+
+ wp = line;
+ while ((p = HX_strsep(&wp, ":")) != NULL)
+ printf("%s\n", p)
diff --git a/doc/strlcpy-timing.rst b/doc/strlcpy-timing.rst
new file mode 100644
index 0000000..17c7892
--- /dev/null
+++ b/doc/strlcpy-timing.rst
@@ -0,0 +1,111 @@
+strncpy fills the buffer with \0s if there is room left, which can build up
+runtime if the buffer is much larger than the string to be copied. The turning
+point on i7-4600U is about when the buffer is 3 times larger or more than the
+string. Copying a M-char string into a buffer of size N with different
+strategies turned out as follows, not favorably for switching to memcpy
+approach:
+
+M->N: [str minus mem] (str=walltime, mem=walltime)
+
+::
+
+ 3-> 4: 0.-18010833 (str=0.053766602 mem=0.071777435)
+ 3-> 8: 0.-02276861 (str=0.069214041 mem=0.071490902)
+ 3-> 16: 0.-02594396 (str=0.069160485 mem=0.071754881)
+ 3-> 32: 0.-06119749 (str=0.064986286 mem=0.071106035)
+ 3-> 64: 0.-10011776 (str=0.062121350 mem=0.072133126)
+ 3-> 80: 0.000049152 (str=0.071466420 mem=0.071417268)
+ 3-> 128: 0.-10057727 (str=0.062143411 mem=0.072201138)
+ 3-> 256: 0.006148232 (str=0.077881866 mem=0.071733634)
+ 3->1024: 0.133625167 (str=0.206994485 mem=0.073369318)
+ 3->2048: 0.335047756 (str=0.405503204 mem=0.070455448)
+ 7-> 4: 0.-28288138 (str=0.046614065 mem=0.074902203)
+ 7-> 8: 0.-20974635 (str=0.052778755 mem=0.073753390)
+ 7-> 16: 0.-06903916 (str=0.068165128 mem=0.075069044)
+ 7-> 32: 0.-11161234 (str=0.064787697 mem=0.075948931)
+ 7-> 64: 0.-12026108 (str=0.061544945 mem=0.073571053)
+ 7-> 80: 0.-01877441 (str=0.072047713 mem=0.073925154)
+ 7-> 128: 0.-11343544 (str=0.062557326 mem=0.073900870)
+ 7-> 256: 0.005472409 (str=0.079922333 mem=0.074449924)
+ 7->1024: 0.133164952 (str=0.206290338 mem=0.073125386)
+ 7->2048: 0.329050142 (str=0.403909643 mem=0.074859501)
+ 15-> 4: 0.-28134891 (str=0.046436269 mem=0.074571160)
+ 15-> 8: 0.-26808385 (str=0.047722251 mem=0.074530636)
+ 15-> 16: 0.-21857806 (str=0.052866161 mem=0.074723967)
+ 15-> 32: 0.-15183331 (str=0.058903617 mem=0.074086948)
+ 15-> 64: 0.-06020317 (str=0.068661890 mem=0.074682207)
+ 15-> 80: 0.-13077126 (str=0.061986539 mem=0.075063665)
+ 15-> 128: 0.-05110583 (str=0.069024087 mem=0.074134670)
+ 15-> 256: 0.010346893 (str=0.085920728 mem=0.075573835)
+ 15->1024: 0.130128294 (str=0.203516720 mem=0.073388426)
+ 15->2048: 0.384323201 (str=0.459435357 mem=0.075112156)
+ 31-> 4: 0.-40592735 (str=0.043398064 mem=0.083990799)
+ 31-> 8: 0.-40405756 (str=0.043312982 mem=0.083718738)
+ 31-> 16: 0.-42308714 (str=0.044729400 mem=0.087038114)
+ 31-> 32: 0.-14127856 (str=0.056652936 mem=0.070780792)
+ 31-> 64: 0.-01889875 (str=0.069010683 mem=0.070900558)
+ 31-> 80: 0.001793133 (str=0.072637736 mem=0.070844603)
+ 31-> 128: 0.-02607933 (str=0.068334098 mem=0.070942031)
+ 31-> 256: 0.018139903 (str=0.088753971 mem=0.070614068)
+ 31->1024: 0.133949645 (str=0.204402776 mem=0.070453131)
+ 31->2048: 0.398049056 (str=0.468551187 mem=0.070502131)
+ 63-> 4: 0.-40166921 (str=0.043758420 mem=0.083925341)
+ 63-> 8: 0.-40966732 (str=0.043495110 mem=0.084461842)
+ 63-> 16: 0.-43784039 (str=0.043770941 mem=0.087554980)
+ 63-> 32: 0.-31256988 (str=0.046623389 mem=0.077880377)
+ 63-> 64: 0.-13997348 (str=0.068499638 mem=0.082496986)
+ 63-> 80: 0.-13916305 (str=0.068620538 mem=0.082536843)
+ 63-> 128: 0.-08328403 (str=0.074551339 mem=0.082879742)
+ 63-> 256: 0.004095734 (str=0.087035878 mem=0.082940144)
+ 63->1024: 0.151451020 (str=0.233770899 mem=0.082319879)
+ 63->2048: 0.355839456 (str=0.438594030 mem=0.082754574)
+ 79-> 4: 0.-53092708 (str=0.045118918 mem=0.098211626)
+ 79-> 8: 0.-54340043 (str=0.043908506 mem=0.098248549)
+ 79-> 16: 0.-57213292 (str=0.043950458 mem=0.101163750)
+ 79-> 32: 0.-44929075 (str=0.047104201 mem=0.092033276)
+ 79-> 64: 0.-40841792 (str=0.060369798 mem=0.101211590)
+ 79-> 80: 0.-34512567 (str=0.072643063 mem=0.107155630)
+ 79-> 128: 0.-26004050 (str=0.081177431 mem=0.107181481)
+ 79-> 256: 0.-14164733 (str=0.093010965 mem=0.107175698)
+ 79->1024: 0.131262747 (str=0.238379553 mem=0.107116806)
+ 79->2048: 0.337908136 (str=0.444999897 mem=0.107091761)
+ 127-> 4: 0.-53463038 (str=0.044954314 mem=0.098417352)
+ 127-> 8: 0.-54030635 (str=0.044154075 mem=0.098184710)
+ 127-> 16: 0.-56778235 (str=0.044743552 mem=0.101521787)
+ 127-> 32: 0.-44858267 (str=0.047231395 mem=0.092089662)
+ 127-> 64: 0.-42149730 (str=0.059234517 mem=0.101384247)
+ 127-> 80: 0.-45513663 (str=0.062055806 mem=0.107569469)
+ 127-> 128: 0.-23468852 (str=0.083671245 mem=0.107140097)
+ 127-> 256: 0.-04999520 (str=0.102026030 mem=0.107025550)
+ 127->1024: 0.139261976 (str=0.246475516 mem=0.107213540)
+ 127->2048: 0.345950301 (str=0.453134545 mem=0.107184244)
+ 255-> 4: 0.-70209659 (str=0.044940128 mem=0.115149787)
+ 255-> 8: 0.-71166235 (str=0.044243636 mem=0.115409871)
+ 255-> 16: 0.-73994321 (str=0.044365563 mem=0.118359884)
+ 255-> 32: 0.-61137064 (str=0.047746212 mem=0.108883276)
+ 255-> 64: 0.-58453794 (str=0.059850772 mem=0.118304566)
+ 255-> 80: 0.-61859639 (str=0.062199397 mem=0.124059036)
+ 255-> 128: 0.-42561423 (str=0.081341036 mem=0.123902459)
+ 255-> 256: 0.-35252238 (str=0.127124980 mem=0.162377218)
+ 255->1024: 0.097331464 (str=0.259751271 mem=0.162419807)
+ 255->2048: 0.305789595 (str=0.468141377 mem=0.162351782)
+ 1023-> 4: 0.-161452842 (str=0.043764021 mem=0.205216863)
+ 1023-> 8: 0.-155095262 (str=0.043698735 mem=0.198793997)
+ 1023-> 16: 0.-153207918 (str=0.043675714 mem=0.196883632)
+ 1023-> 32: 0.-152565254 (str=0.047438108 mem=0.200003362)
+ 1023-> 64: 0.-144192775 (str=0.058773300 mem=0.202966075)
+ 1023-> 80: 0.-149929950 (str=0.062432021 mem=0.212361971)
+ 1023-> 128: 0.-132285886 (str=0.080313089 mem=0.212598975)
+ 1023-> 256: 0.-133526587 (str=0.108033655 mem=0.241560242)
+ 1023->1024: 0.-90772704 (str=0.311350193 mem=0.402122897)
+ 1023->2048: 0.088417585 (str=0.490594175 mem=0.402176590)
+ 1368-> 4: 0.-211901350 (str=0.044167308 mem=0.256068658)
+ 1368-> 8: 0.-203185010 (str=0.044571028 mem=0.247756038)
+ 1368-> 16: 0.-200207782 (str=0.044133973 mem=0.244341755)
+ 1368-> 32: 0.-202440240 (str=0.047977200 mem=0.250417440)
+ 1368-> 64: 0.-193238434 (str=0.058934429 mem=0.252172863)
+ 1368-> 80: 0.-200936170 (str=0.062169785 mem=0.263105955)
+ 1368-> 128: 0.-181397289 (str=0.081740755 mem=0.263138044)
+ 1368-> 256: 0.-183151788 (str=0.107983466 mem=0.291135254)
+ 1368->1024: 0.-142070533 (str=0.292431947 mem=0.434502480)
+ 1368->2048: 0.-16089517 (str=0.508519291 mem=0.524608808)
diff --git a/doc/strlcpy-timing.txt b/doc/strlcpy-timing.txt
deleted file mode 100644
index 56ed40c..0000000
--- a/doc/strlcpy-timing.txt
+++ /dev/null
@@ -1,109 +0,0 @@
-strncpy fills the buffer with \0s if there is room left, which can build up
-runtime if the buffer is much larger than the string to be copied. The turning
-point on i7-4600U is about when the buffer is 3 times larger or more than the
-string. Copying a M-char string into a buffer of size N with different
-strategies turned out as follows, not favorably for switching to memcpy
-approach:
-
-M->N: [str minus mem] (str=walltime, mem=walltime)
-
- 3-> 4: 0.-18010833 (str=0.053766602 mem=0.071777435)
- 3-> 8: 0.-02276861 (str=0.069214041 mem=0.071490902)
- 3-> 16: 0.-02594396 (str=0.069160485 mem=0.071754881)
- 3-> 32: 0.-06119749 (str=0.064986286 mem=0.071106035)
- 3-> 64: 0.-10011776 (str=0.062121350 mem=0.072133126)
- 3-> 80: 0.000049152 (str=0.071466420 mem=0.071417268)
- 3-> 128: 0.-10057727 (str=0.062143411 mem=0.072201138)
- 3-> 256: 0.006148232 (str=0.077881866 mem=0.071733634)
- 3->1024: 0.133625167 (str=0.206994485 mem=0.073369318)
- 3->2048: 0.335047756 (str=0.405503204 mem=0.070455448)
- 7-> 4: 0.-28288138 (str=0.046614065 mem=0.074902203)
- 7-> 8: 0.-20974635 (str=0.052778755 mem=0.073753390)
- 7-> 16: 0.-06903916 (str=0.068165128 mem=0.075069044)
- 7-> 32: 0.-11161234 (str=0.064787697 mem=0.075948931)
- 7-> 64: 0.-12026108 (str=0.061544945 mem=0.073571053)
- 7-> 80: 0.-01877441 (str=0.072047713 mem=0.073925154)
- 7-> 128: 0.-11343544 (str=0.062557326 mem=0.073900870)
- 7-> 256: 0.005472409 (str=0.079922333 mem=0.074449924)
- 7->1024: 0.133164952 (str=0.206290338 mem=0.073125386)
- 7->2048: 0.329050142 (str=0.403909643 mem=0.074859501)
- 15-> 4: 0.-28134891 (str=0.046436269 mem=0.074571160)
- 15-> 8: 0.-26808385 (str=0.047722251 mem=0.074530636)
- 15-> 16: 0.-21857806 (str=0.052866161 mem=0.074723967)
- 15-> 32: 0.-15183331 (str=0.058903617 mem=0.074086948)
- 15-> 64: 0.-06020317 (str=0.068661890 mem=0.074682207)
- 15-> 80: 0.-13077126 (str=0.061986539 mem=0.075063665)
- 15-> 128: 0.-05110583 (str=0.069024087 mem=0.074134670)
- 15-> 256: 0.010346893 (str=0.085920728 mem=0.075573835)
- 15->1024: 0.130128294 (str=0.203516720 mem=0.073388426)
- 15->2048: 0.384323201 (str=0.459435357 mem=0.075112156)
- 31-> 4: 0.-40592735 (str=0.043398064 mem=0.083990799)
- 31-> 8: 0.-40405756 (str=0.043312982 mem=0.083718738)
- 31-> 16: 0.-42308714 (str=0.044729400 mem=0.087038114)
- 31-> 32: 0.-14127856 (str=0.056652936 mem=0.070780792)
- 31-> 64: 0.-01889875 (str=0.069010683 mem=0.070900558)
- 31-> 80: 0.001793133 (str=0.072637736 mem=0.070844603)
- 31-> 128: 0.-02607933 (str=0.068334098 mem=0.070942031)
- 31-> 256: 0.018139903 (str=0.088753971 mem=0.070614068)
- 31->1024: 0.133949645 (str=0.204402776 mem=0.070453131)
- 31->2048: 0.398049056 (str=0.468551187 mem=0.070502131)
- 63-> 4: 0.-40166921 (str=0.043758420 mem=0.083925341)
- 63-> 8: 0.-40966732 (str=0.043495110 mem=0.084461842)
- 63-> 16: 0.-43784039 (str=0.043770941 mem=0.087554980)
- 63-> 32: 0.-31256988 (str=0.046623389 mem=0.077880377)
- 63-> 64: 0.-13997348 (str=0.068499638 mem=0.082496986)
- 63-> 80: 0.-13916305 (str=0.068620538 mem=0.082536843)
- 63-> 128: 0.-08328403 (str=0.074551339 mem=0.082879742)
- 63-> 256: 0.004095734 (str=0.087035878 mem=0.082940144)
- 63->1024: 0.151451020 (str=0.233770899 mem=0.082319879)
- 63->2048: 0.355839456 (str=0.438594030 mem=0.082754574)
- 79-> 4: 0.-53092708 (str=0.045118918 mem=0.098211626)
- 79-> 8: 0.-54340043 (str=0.043908506 mem=0.098248549)
- 79-> 16: 0.-57213292 (str=0.043950458 mem=0.101163750)
- 79-> 32: 0.-44929075 (str=0.047104201 mem=0.092033276)
- 79-> 64: 0.-40841792 (str=0.060369798 mem=0.101211590)
- 79-> 80: 0.-34512567 (str=0.072643063 mem=0.107155630)
- 79-> 128: 0.-26004050 (str=0.081177431 mem=0.107181481)
- 79-> 256: 0.-14164733 (str=0.093010965 mem=0.107175698)
- 79->1024: 0.131262747 (str=0.238379553 mem=0.107116806)
- 79->2048: 0.337908136 (str=0.444999897 mem=0.107091761)
- 127-> 4: 0.-53463038 (str=0.044954314 mem=0.098417352)
- 127-> 8: 0.-54030635 (str=0.044154075 mem=0.098184710)
- 127-> 16: 0.-56778235 (str=0.044743552 mem=0.101521787)
- 127-> 32: 0.-44858267 (str=0.047231395 mem=0.092089662)
- 127-> 64: 0.-42149730 (str=0.059234517 mem=0.101384247)
- 127-> 80: 0.-45513663 (str=0.062055806 mem=0.107569469)
- 127-> 128: 0.-23468852 (str=0.083671245 mem=0.107140097)
- 127-> 256: 0.-04999520 (str=0.102026030 mem=0.107025550)
- 127->1024: 0.139261976 (str=0.246475516 mem=0.107213540)
- 127->2048: 0.345950301 (str=0.453134545 mem=0.107184244)
- 255-> 4: 0.-70209659 (str=0.044940128 mem=0.115149787)
- 255-> 8: 0.-71166235 (str=0.044243636 mem=0.115409871)
- 255-> 16: 0.-73994321 (str=0.044365563 mem=0.118359884)
- 255-> 32: 0.-61137064 (str=0.047746212 mem=0.108883276)
- 255-> 64: 0.-58453794 (str=0.059850772 mem=0.118304566)
- 255-> 80: 0.-61859639 (str=0.062199397 mem=0.124059036)
- 255-> 128: 0.-42561423 (str=0.081341036 mem=0.123902459)
- 255-> 256: 0.-35252238 (str=0.127124980 mem=0.162377218)
- 255->1024: 0.097331464 (str=0.259751271 mem=0.162419807)
- 255->2048: 0.305789595 (str=0.468141377 mem=0.162351782)
-1023-> 4: 0.-161452842 (str=0.043764021 mem=0.205216863)
-1023-> 8: 0.-155095262 (str=0.043698735 mem=0.198793997)
-1023-> 16: 0.-153207918 (str=0.043675714 mem=0.196883632)
-1023-> 32: 0.-152565254 (str=0.047438108 mem=0.200003362)
-1023-> 64: 0.-144192775 (str=0.058773300 mem=0.202966075)
-1023-> 80: 0.-149929950 (str=0.062432021 mem=0.212361971)
-1023-> 128: 0.-132285886 (str=0.080313089 mem=0.212598975)
-1023-> 256: 0.-133526587 (str=0.108033655 mem=0.241560242)
-1023->1024: 0.-90772704 (str=0.311350193 mem=0.402122897)
-1023->2048: 0.088417585 (str=0.490594175 mem=0.402176590)
-1368-> 4: 0.-211901350 (str=0.044167308 mem=0.256068658)
-1368-> 8: 0.-203185010 (str=0.044571028 mem=0.247756038)
-1368-> 16: 0.-200207782 (str=0.044133973 mem=0.244341755)
-1368-> 32: 0.-202440240 (str=0.047977200 mem=0.250417440)
-1368-> 64: 0.-193238434 (str=0.058934429 mem=0.252172863)
-1368-> 80: 0.-200936170 (str=0.062169785 mem=0.263105955)
-1368-> 128: 0.-181397289 (str=0.081740755 mem=0.263138044)
-1368-> 256: 0.-183151788 (str=0.107983466 mem=0.291135254)
-1368->1024: 0.-142070533 (str=0.292431947 mem=0.434502480)
-1368->2048: 0.-16089517 (str=0.508519291 mem=0.524608808)
diff --git a/doc/time_functions.rst b/doc/time_functions.rst
new file mode 100644
index 0000000..d9a57a1
--- /dev/null
+++ b/doc/time_functions.rst
@@ -0,0 +1,125 @@
+==============
+Time functions
+==============
+
+Time in POSIX systems is represented in ``struct timespec``. This structure is
+composed of two members: one integer for the number of full seconds in the time
+value, and one integer for the number of nanoseconds that remain when
+subtracting the full seconds from the time value. POSIX leaves it unspecified
+how negative time is to be represented with this structure, so I have devised
+an algebra for use with the same struct that gives negative time support.
+
+Since integers often cannot store negative zero (due to e.g. use of 2s
+complements in the language implementation), we will store the minus sign in
+the nanosecond member if the integral second part is zero. This gives us the
+property that we can test for negative time by looking for whether at least one
+member of the structure is negative. Also, we want to avoid storing the minus
+in both members to somewhat aid the pretty-printing construct often seen,
+
+.. code-block:: c
+
+ printf("%ld.%09ld\n", (long)ts.tv_sec, ts.tv_nsec);
+
+The number of combinations of a (non-zero) negative number, zero and a
+(non-zero) positive number is small, so we can actually just exhaustively list
+them all.
+
++----------------+------------+
+| Representation | Time value |
++================+============+
+| {-1, -1} | illegal |
++----------------+------------+
+| {-1, 0} | -1.0 s |
++----------------+------------+
+| {-1, 1} | -1.1 s |
++----------------+------------+
+| { 0, -1} | -0.1 s |
++----------------+------------+
+| { 0, 0} | 0.0 s |
++----------------+------------+
+| { 0, 1} | 0.1 s |
++----------------+------------+
+| { 1, -1} | illegal |
++----------------+------------+
+| { 1, 0} | 1.0 s |
++----------------+------------+
+| { 1, 1} | 1.1 s |
++----------------+------------+
+
+Function list
+=============
+
+.. code-block:: c
+
+ #include <libHX/misc.h>
+
+ bool HX_timespec_isneg(const struct timespec *p);
+
+ struct timespec *HX_timespec_neg(struct timespec *result,
+ const struct timespec *p);
+
+ struct timespec *HX_timespec_add(struct timespec *result,
+ const struct timespec *p, const struct timespec *q);
+
+ struct timespec *HX_timespec_sub(struct timespec *delta,
+ const struct timespec *p, const struct timespec *q);
+
+ struct timespec *HX_timespec_mul(struct timespec *delta,
+ const struct timespec *p, int f);
+
+ struct timespec *HX_timespec_mulf(struct timespec *delta,
+ const struct timespec *p, double f);
+
+ struct timeval *HX_timeval_sub(struct timeval *delta,
+ const struct timeval *p, const struct timeval *q);
+
+ int HX_time_compare(const struct stat *a, const struct stat *b,
+ int mode);
+
+``HX_timespec_isneg``
+ Determines whether a timespec structure represents (non-zero) negative
+ time.
+
+``HX_timespec_neg``
+ Computes the negation of the time specified by ``p``. ``result`` and
+ ``p`` may point to the same structure.
+
+``HX_timespec_add``
+ Calculates the sum of the two times specified by ``p`` and ``q``, which
+ are of type ``struct timespec``. Any and all of ``result``, ``p`` and
+ ``q`` may point to the same structure.
+
+``HX_timespec_sub``
+ Calculates the difference between the two timepoints ``p`` and ``q``,
+ which are of type ``struct timespec`` (nanosecond granularity).
+
+``HX_timespec_mul``
+ Multiplies the time quantum in ``p`` by ``f``.
+
+``HX_timespec_mulf``
+ Multiplies the time quantum in ``p`` by ``f``.
+
+``HX_timeval_sub``
+ Calculates the difference between the two timepoints ``p`` and ``q``,
+ which are of type ``struct timeval`` (microsecnod granularity).
+
+``HX_time_compare``
+ Compares the timestamps from two struct stats. ``mode`` indicates which
+ field is compared, which can either be ``'a'`` for the access time,
+ ``'c'`` for the inode change time, ``'m'`` for the modification time,
+ or ``'o'`` for the creation time (where available). Returns a negative
+ number if the time in ``a`` is less than ``b``, zero when they are
+ equal, or a positive number greater than zero if ``a`` is greater than
+ ``b``.
+
+The macros ``HX_TIMESPEC_FMT`` and ``HX_TIMESPEC_EXP`` can be used for passing
+and printing a ``struct timespec`` using the ``*printf`` function family:
+
+.. code-block:: c
+
+ struct timespec p;
+ clock_gettime(CLOCK_MONOTONIC, &p);
+ printf("Now: " HX_TIMESPEC_FMT, HX_TIMESPEC_EXP(&p));
+
+Similarly, ``HX_TIMEVAL_FMT`` and ``HX_TIMEVAL_EXP`` exist for the older
+``struct timeval``.
diff --git a/doc/typecheck_casts.rst b/doc/typecheck_casts.rst
new file mode 100644
index 0000000..b7f882e
--- /dev/null
+++ b/doc/typecheck_casts.rst
@@ -0,0 +1,178 @@
+===================
+Type-checking casts
+===================
+
+The C++ language provides “new-style casts”, referring to the four
+template-looking invocations ``static_cast<>``, ``const_cast<>``,
+``reinterpret_cast<>`` and ``dynamic_cast<>``. No such blessing was given to
+the C language, but still, even using macros that expand to the olde cast make
+it much easier to find casts in source code and annotate why something was
+casted, which is already an improvement. — Actually, it is possible to do a
+some type checking, using some GCC extensions, which augments these macros from
+their documentary nature to an actual safety measure.
+
+
+``reinterpret_cast``
+====================
+
+``reinterpret_cast()`` maps directly to the old-style typecast,
+``(type)(expr)``, and causes the bit pattern for the ``expr`` rvalue to be
+“reinterpreted” as a new type. You will notice that “reinterpret” is the
+longest of all the ``*_cast`` names, and can easily cause lines to grow beyond
+80 columns (the good maximum in many style guides). As a side effect, it is a
+good indicator that something potentially dangerous might be going on, for
+example converting intergers from/to pointer.
+
+.. code-block:: c
+
+ #include <libHX/defs.h>
+
+ int i;
+ /* Tree with numeric keys */
+ tree = HXhashmap_init(0);
+ for (i = 0; i < 6; ++i)
+ HXmap_add(tree, reinterpret_cast(void *,
+ static_cast(long, i)), my_data);
+
+
+``signed_cast``
+===============
+
+This tag is for annotating that the cast was solely done to change the
+signedness of pointers to char — and only those. No integers etc. The intention
+is to facilitate working with libraries that use ``unsigned char *`` pointers,
+such as libcrypto and libssl (from the OpenSSL project) or libxml2, for
+example. See table [tab:defs-signed_cast] for the allowed conversions. C++ does
+not actually have a ``signed_cast<>``, and one would have to use
+``reinterpret_cast<>`` to do the conversion, because ``static_cast<>`` does not
+allow conversion from ``const char *`` to ``const unsigned char *``, for
+example. (libHX's ``static_cast()`` would also throw at least a compiler
+warning about the different signedness.) This is where signed_cast comes in.
+(libHX provides a ``signed_cast<>`` for C++ though.)
+
+.. table :: Accepted conversions for ``signed_cast()``
+
++-----------------------+----+-----+-----+-----+------+------+
+| From \ To | c* | sc* | uc* | Cc* | Csc* | Cuc* |
++=======================+====+=====+=====+=====+======+======+
+| char * | ok | ok | ok | ok | ok | ok |
++-----------------------+----+-----+-----+-----+------+------+
+| signed char * | ok | ok | ok | ok | ok | ok |
++-----------------------+----+-----+-----+-----+------+------+
+| unsigned char * | ok | ok | ok | ok | ok | ok |
++-----------------------+----+-----+-----+-----+------+------+
+| const char * | – | – | - | ok | ok | ok |
++-----------------------+----+-----+-----+-----+------+------+
+| const signed char * | – | – | – | ok | ok | ok |
++-----------------------+----+-----+-----+-----+------+------+
+| const unsigned char * | – | – | – | ok | ok | ok |
++-----------------------+----+-----+-----+-----+------+------+
+
+
+``static_cast``
+===============
+
+Just like C++'s ``static_cast<>``, libHX's ``static_cast()`` verifies that
+``expr`` can be implicitly converted to the new type (by a simple ``b = a``).
+Such is mainly useful for forcing a specific type, as is needed in varargs
+functions such as ``printf``, and where the conversion actually incurs other
+side effects, such as truncation or promotion:
+
+.. code-block:: c
+
+ /* Convert to a type printf knows about */
+ uint64_t x = something;
+ printf("%llu\n", static_cast(unsigned long long, x));
+
+Because there is no format specifier for ``uint64_t`` for ``printf`` (well yes,
+there is ``PRIu64``), a conversion to an accepted type is necessary to not
+cause undefined behavior. Code that does, for example, ``printf("%u")`` on a
+``long`` only happens to work on architectures where ``sizeof(unsigned int) ==
+sizeof(unsigned long)``, such as i386. On x86_64, an ``unsigned long`` is
+usually twice as big as an ``unsigned int``, so that 8 bytes are pushed onto
+the stack, but printf only unshifts 4 bytes because the developer indicated
+``%u``, leading to misreading the next variable on the stack.
+
+.. code-block:: c
+
+ /* Force promotion */
+ double a_quarter = static_cast(double, 1) / 4;
+
+Were ``1`` not promoted to double, the result in ``q`` would be zero because
+``1/4`` is just an integer division, yielding zero. By making one of the
+operands a floating-point quantity, the compiler will instruct the FPU to
+compute the result. Of course, one could have also written ``1.0`` instead of
+``static_cast(double, 1)``, but this is left for the programmer to decide which
+style s/he prefers.
+
+.. code-block:: c
+
+ /* Force truncation before invoking second sqrt */
+ double f = sqrt(static_cast(int, 10 * sqrt(3.0 / 4)));
+
+And here, the conversion from ``double`` to ``int`` incurs a (wanted)
+truncation of the decimal fraction, that is, rounding down for positive
+numbers, and rounding up for negative numbers.
+
+Allowed conversions
+-------------------
+
+* Numbers
+
+ Conversion between numeric types, such as ``char``, ``short``, ``int``,
+ ``long``, ``long long``, ``intN_t``, both their signed and unsigned variants,
+ ``float`` and ``double``.
+
+* Generic Pointer
+
+ Conversion from ``type *`` to and from ``void *``. (Where type may very
+ well be a type with further indirection.)
+
+* Generic Pointer (const)
+
+ Conversion from ``const type *`` to and from ``const void *``.
+
+Limitations
+-----------
+
+Because the implementation of our ``static_cast`` involves a C99 compound
+literals and those are not constant expressions, ``static_cast`` cannot be used
+in such contexts. (Cf. `GCC issue 105510
+<https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105510#c3>`_).
+
+.. code-block:: c
+
+ static const int a = static_cast(int, 1U);
+
+Furthermore, because an implicit assignment is used in the implementation, it
+can trigger `-Wsign-conversion` warnings.
+
+
+``const_cast``
+==============
+
+const_cast allows to add or remove “const” qualifiers from the
+type a pointer is pointing to. Due to technical limitations, it
+could not be implemented to support arbitrary indirection.
+Instead, const_cast comes in three variants, to be used for
+indirection levels of 1 to 3:
+
+* ``const_cast1(type *, expr)`` with ``typeof(expr) = type *``.
+ (Similarly for any combinations of const.)
+
+* ``const_cast2(type **, expr)`` with ``typeof(expr) = type **`` (and all
+ combinations of const in all possible locations).
+
+* ``const_cast3(type ***, expr)`` with ``typeof(expr) = type ***`` (and all
+ combinations...).
+
+As indirection levels above 3 are really unlikely[#f3], having only these three
+type-checking cast macros was deemed sufficient. The only place where libHX
+even uses a level‑3 indirection is in the option parser.
+
+.. [#t3] See “Three Star Programmer”
+
+Conversion is permitted when expression and target type are from the table.
+
+It is currently not possible to use const_cast1/2/3 on pointers to structures
+whose member structure is unknown.
diff --git a/doc/ux-file.rst b/doc/ux-file.rst
new file mode 100644
index 0000000..ae21c56
--- /dev/null
+++ b/doc/ux-file.rst
@@ -0,0 +1,31 @@
+======================================
+ux-file - Unix compatibility functions
+======================================
+
+Date authored: 2006-02-25
+
+Description
+===========
+
+libHX provides some dummy Unix functions for platforms where they are not
+available. They mostly return `-ENOSYS`.
+
+Synopsis
+========
+
+.. code-block:: c
+
+ #include <libHX.h>
+
+ int chown(const char *PATH, long UID, long GID);
+ int fchmod(int FD, long PERM);
+ int fchown(int FD, long UID, long GID);
+ int lchown(const char *PATH, long UID, long GID);
+ int lstat(const char *PATH, struct stat *SB);
+ int mkfifo(const char *PATH, long MODE);
+ int mknod(const char *PATH, long MODE, long DEV);
+ int readlink(const char *PATH, char *DEST, size_t LEN);
+ int symlink(const char *SRC, const char *DEST);
+
+``lstat()``
+ Maps to ``stat()`` under Win32.
diff --git a/doc/ux-file.txt b/doc/ux-file.txt
deleted file mode 100644
index 2f32247..0000000
--- a/doc/ux-file.txt
+++ /dev/null
@@ -1,30 +0,0 @@
-===============================================================================
-ux-file - Unix compatibility functions 2006-02-25
-
-
-DESCRIPTION
-
- libHX provides some dummy Unix functions for platforms where they are not
- available. They mostly return -ENOSYS.
-
-
-SYNOPSIS
-
- #include <libHX.h>
-
- int chown(const char *PATH, long UID, long GID);
- int fchmod(int FD, long PERM);
- int fchown(int FD, long UID, long GID);
- int lchown(const char *PATH, long UID, long GID);
- int lstat(const char *PATH, struct stat *SB);
- int mkfifo(const char *PATH, long MODE);
- int mknod(const char *PATH, long MODE, long DEV);
- int readlink(const char *PATH, char *DEST, size_t LEN);
- int symlink(const char *SRC, const char *DEST);
-
-
-lstat()
-
- Maps to stat() under Win32.
-
-===============================================================================
diff --git a/doc/ux-mmap.rst b/doc/ux-mmap.rst
new file mode 100644
index 0000000..c59421c
--- /dev/null
+++ b/doc/ux-mmap.rst
@@ -0,0 +1,27 @@
+======================================
+ux-mmap - Unix compatibility functions
+======================================
+
+Date authored: 2006-02-25
+
+Description
+===========
+
+libHX provides a Linux-style ``mmap()`` function for Win32.
+
+Synopsis
+========
+
+.. code-block:: c
+
+ #include <libHX.h>
+
+ void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);
+
+``mmap()``
+
+ See the Linux manual page ``mmap``(2) for details. Many flags described
+ in ``mmap``(2) do not work. What does work: ``PROT_NONE``,
+ ``PROT_READ``, ``PROT_WRITE``, ``PROT_EXEC`` (only WinXP SP2 or
+ WinServer2003 SP1 or up), ``MAP_SHARED`` and ``MAP_PRIVATE``.
+ ``MAP_SHARED`` is the default if no ``MAP_PRIVATE`` is given.
diff --git a/doc/ux-mmap.txt b/doc/ux-mmap.txt
deleted file mode 100644
index 43f5ac9..0000000
--- a/doc/ux-mmap.txt
+++ /dev/null
@@ -1,26 +0,0 @@
-===============================================================================
-ux-mmap - Unix compatibility functions 2006-02-25
-
-
-DESCRIPTION
-
- libHX provides a Linux-style mmap() function for Win32.
-
-
-SYNOPSIS
-
- #include <libHX.h>
-
- void *mmap(void *START, size_t LENGTH, int PROT, int FLAGS, int FD,
- off_t OFFSET);
-
-
-mmap()
-
- See the Linux manual page mmap(2) for details. Many flags described in
- mmap(2) do not work. What does work: PROT_NONE, PROT_READ, PROT_WRITE,
- PROT_EXEC (only WinPX SP2 or WinServer2003 SP1 or up), MAP_SHARED and
- MAP_PRIVATE. MAP_SHARED is the default if no MAP_PRIVATE is given.
-
-
-===============================================================================