From 532d4a24e2013262dfa41fd85c06a9715c99abf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Frings-F=C3=BCrst?= Date: Mon, 24 Oct 2022 21:03:42 +0200 Subject: New upstream version 4.7 --- doc/.gitignore | 2 - doc/Makefile.am | 16 - doc/Makefile.in | 518 - doc/api.rst | 374 + doc/api.txt | 353 - doc/bitmaps.rst | 49 + doc/changelog.rst | 140 + doc/changelog.txt | 556 - doc/dirstamp.rst | 7 + doc/dirstamp.txt | 4 - doc/files_and_dirs.rst | 190 + doc/generate | 19 - doc/helper_headers.rst | 128 + doc/history.rst | 22 + doc/init.rst | 17 + doc/inline_clist.rst | 59 + doc/inline_list.rst | 253 + doc/install.rst | 50 + doc/libHX_Documentation.lyx | 24663 ------------------------------------------ doc/libHX_Documentation.pdf | Bin 522656 -> 0 bytes doc/libHX_Documentation.rst | 142 + doc/linked_list.rst | 171 + doc/macros.rst | 149 + doc/maps.rst | 525 + doc/memory_container.rst | 197 + doc/misc_functions.rst | 35 + doc/option_parsing.rst | 587 + doc/process_management.rst | 233 + doc/random_numbers.rst | 32 + doc/shconfig.rst | 116 + doc/slurp.c | 38 - doc/socket_functions.rst | 16 + doc/string_formatter.rst | 210 + doc/string_ops.rst | 569 + doc/strlcpy-timing.rst | 111 + doc/strlcpy-timing.txt | 109 - doc/time_functions.rst | 125 + doc/typecheck_casts.rst | 178 + doc/ux-file.rst | 31 + doc/ux-file.txt | 30 - doc/ux-mmap.rst | 27 + doc/ux-mmap.txt | 26 - 42 files changed, 4743 insertions(+), 26334 deletions(-) delete mode 100644 doc/.gitignore delete mode 100644 doc/Makefile.am delete mode 100644 doc/Makefile.in create mode 100644 doc/api.rst delete mode 100644 doc/api.txt create mode 100644 doc/bitmaps.rst create mode 100644 doc/changelog.rst delete mode 100644 doc/changelog.txt create mode 100644 doc/dirstamp.rst delete mode 100644 doc/dirstamp.txt create mode 100644 doc/files_and_dirs.rst delete mode 100755 doc/generate create mode 100644 doc/helper_headers.rst create mode 100644 doc/history.rst create mode 100644 doc/init.rst create mode 100644 doc/inline_clist.rst create mode 100644 doc/inline_list.rst create mode 100644 doc/install.rst delete mode 100644 doc/libHX_Documentation.lyx delete mode 100644 doc/libHX_Documentation.pdf create mode 100644 doc/libHX_Documentation.rst create mode 100644 doc/linked_list.rst create mode 100644 doc/macros.rst create mode 100644 doc/maps.rst create mode 100644 doc/memory_container.rst create mode 100644 doc/misc_functions.rst create mode 100644 doc/option_parsing.rst create mode 100644 doc/process_management.rst create mode 100644 doc/random_numbers.rst create mode 100644 doc/shconfig.rst delete mode 100644 doc/slurp.c create mode 100644 doc/socket_functions.rst create mode 100644 doc/string_formatter.rst create mode 100644 doc/string_ops.rst create mode 100644 doc/strlcpy-timing.rst delete mode 100644 doc/strlcpy-timing.txt create mode 100644 doc/time_functions.rst create mode 100644 doc/typecheck_casts.rst create mode 100644 doc/ux-file.rst delete mode 100644 doc/ux-file.txt create mode 100644 doc/ux-mmap.rst delete mode 100644 doc/ux-mmap.txt (limited to 'doc') 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 + + 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 + #include + #include + + 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 + ```` or ```` 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 - or 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 + + 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 + #include + #include + + 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 + + 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 + + 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 + + #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 + + 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 ```` 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 + + 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 + + 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 + +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 + + 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 + + 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 + + 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 - -\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 - -\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 - - - - - - - - - - - -\begin_inset Text - -\begin_layout Plain Layout - -\series bold -From -\backslash - To -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout - -\series bold -c* -\series default -section -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout - -\series bold -sc* -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout - -\series bold -uc* -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout - -\series bold -Cc* -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout - -\series bold -Csc* -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout - -\series bold -Cuc* -\end_layout - -\end_inset - - - - -\begin_inset Text - -\begin_layout Plain Layout - -\family typewriter -\series bold -char * -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -\begin_inset Formula $\checkmark$ -\end_inset - - -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -\begin_inset Formula $\checkmark$ -\end_inset - - -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -\begin_inset Formula $\checkmark$ -\end_inset - - -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -\begin_inset Formula $\checkmark$ -\end_inset - - -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -\begin_inset Formula $\checkmark$ -\end_inset - - -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -\begin_inset Formula $\checkmark$ -\end_inset - - -\end_layout - -\end_inset - - - - -\begin_inset Text - -\begin_layout Plain Layout - -\family typewriter -\series bold -signed char * -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -\begin_inset Formula $\checkmark$ -\end_inset - - -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -\begin_inset Formula $\checkmark$ -\end_inset - - -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -\begin_inset Formula $\checkmark$ -\end_inset - - -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -\begin_inset Formula $\checkmark$ -\end_inset - - -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -\begin_inset Formula $\checkmark$ -\end_inset - - -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -\begin_inset Formula $\checkmark$ -\end_inset - - -\end_layout - -\end_inset - - - - -\begin_inset Text - -\begin_layout Plain Layout - -\family typewriter -\series bold -unsigned char * -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -\begin_inset Formula $\checkmark$ -\end_inset - - -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -\begin_inset Formula $\checkmark$ -\end_inset - - -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -\begin_inset Formula $\checkmark$ -\end_inset - - -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -\begin_inset Formula $\checkmark$ -\end_inset - - -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -\begin_inset Formula $\checkmark$ -\end_inset - - -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -\begin_inset Formula $\checkmark$ -\end_inset - - -\end_layout - -\end_inset - - - - -\begin_inset Text - -\begin_layout Plain Layout - -\family typewriter -\series bold -const char * -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -– -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -– -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -– -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -\begin_inset Formula $\checkmark$ -\end_inset - - -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -\begin_inset Formula $\checkmark$ -\end_inset - - -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -\begin_inset Formula $\checkmark$ -\end_inset - - -\end_layout - -\end_inset - - - - -\begin_inset Text - -\begin_layout Plain Layout - -\family typewriter -\series bold -const signed char * -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -– -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -– -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -– -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -\begin_inset Formula $\checkmark$ -\end_inset - - -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -\begin_inset Formula $\checkmark$ -\end_inset - - -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -\begin_inset Formula $\checkmark$ -\end_inset - - -\end_layout - -\end_inset - - - - -\begin_inset Text - -\begin_layout Plain Layout - -\family typewriter -\series bold -const unsigned char * -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -– -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -– -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -– -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -\begin_inset Formula $\checkmark$ -\end_inset - - -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -\begin_inset Formula $\checkmark$ -\end_inset - - -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -\begin_inset Formula $\checkmark$ -\end_inset - - -\end_layout - -\end_inset - - - - -\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 - - - - - - -\begin_inset Text - -\begin_layout Plain Layout - -\family typewriter -int ** -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout - -\family typewriter -int *const * -\end_layout - -\end_inset - - - - -\begin_inset Text - -\begin_layout Plain Layout - -\family typewriter -const int ** -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout - -\family typewriter -const int *const * -\end_layout - -\end_inset - - - - -\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 -\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 - -\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 - - - - - - - - - - -\begin_inset Text - -\begin_layout Plain Layout -Representation -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -Time value -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -R -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -T -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -R -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -T -\end_layout - -\end_inset - - - - -\begin_inset Text - -\begin_layout Plain Layout -\begin_inset Formula $\left\{ -1,-1\right\} $ -\end_inset - - -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -illegal -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -\begin_inset Formula $\left\{ 0,-1\right\} $ -\end_inset - - -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout --0.1 -\begin_inset space \thinspace{} -\end_inset - -s -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -\begin_inset Formula $\left\{ 1,-1\right\} $ -\end_inset - - -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -illegal -\end_layout - -\end_inset - - - - -\begin_inset Text - -\begin_layout Plain Layout -\begin_inset Formula $\left\{ -1,0\right\} $ -\end_inset - - -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout --1.0 -\begin_inset space \thinspace{} -\end_inset - -s -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -\begin_inset Formula $\left\{ 0,0\right\} $ -\end_inset - - -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -0.0 -\begin_inset space \thinspace{} -\end_inset - -s -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -\begin_inset Formula $\left\{ 1,0\right\} $ -\end_inset - - -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -1.0 -\begin_inset space \thinspace{} -\end_inset - -s -\end_layout - -\end_inset - - - - -\begin_inset Text - -\begin_layout Plain Layout -\begin_inset Formula $\left\{ -1,1\right\} $ -\end_inset - - -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout --1.1 -\begin_inset space \thinspace{} -\end_inset - -s -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -\begin_inset Formula $\left\{ 0,1\right\} $ -\end_inset - - -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -0.1 -\begin_inset space \thinspace{} -\end_inset - -s -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -\begin_inset Formula $\left\{ 1,1\right\} $ -\end_inset - - -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -1.1 -\begin_inset space \thinspace{} -\end_inset - -s -\end_layout - -\end_inset - - - - -\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} -\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 - -\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 - -\begin_inset Newline newline -\end_inset - - -\series bold -#include -\series default - -\begin_inset Newline newline -\end_inset - - -\series bold -#include -\series default - -\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 -\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 $ab$ -\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 - -\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 - -\begin_inset Newline newline -\end_inset - - -\series bold -#include -\series default - -\begin_inset Newline newline -\end_inset - - -\series bold -#include -\series default - -\begin_inset Newline newline -\end_inset - - -\series bold -#include -\series default - -\begin_inset Newline newline -\end_inset - - -\series bold -#include -\series default - -\begin_inset Newline newline -\end_inset - - -\series bold -#include -\series default - -\begin_inset Newline newline -\end_inset - - -\series bold -#include -\series default - -\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 - -\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 - -\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 - -\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 - -\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 - -\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 - -\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 -< -\family default -, -\family typewriter -> -\family default -, -\family typewriter -& -\family default - and -\family typewriter -" -\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("", 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("", HXQUOTE_HTML, &tmp)); -\begin_inset Newline newline -\end_inset - -printf("%s -\backslash -n", HX_strquote("", 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 - -\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 - -\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 - -\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 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 - -\begin_inset Newline newline -\end_inset - - -\series bold -#include -\series default - -\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 - -\begin_inset Newline newline -\end_inset - - -\series bold -#include -\series default - -\begin_inset Newline newline -\end_inset - - -\series bold -#include -\series default - -\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 - -\begin_inset Newline newline -\end_inset - - -\series bold -#include -\series default - -\begin_inset Newline newline -\end_inset - - -\series bold -#include -\series default - -\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 - -\begin_inset Newline newline -\end_inset - - -\series bold -#include -\series default - -\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 - -\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 - -\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 -\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 - -\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 - -\begin_inset Newline newline -\end_inset - - -\series bold -#include -\series default - -\begin_inset Newline newline -\end_inset - - -\series bold -#include -\series default - -\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 - -\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 - -\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 - -\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 - -\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 - - - - - - - - -\begin_inset Text - -\begin_layout Plain Layout - -\family typewriter -\series bold -type -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout - -\series bold -Type of pointee -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout - -\series bold -type -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout - -\series bold -Type of pointee -\end_layout - -\end_inset - - - - -\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 - - -\begin_inset Text - -\begin_layout Plain Layout - -\family typewriter -char -\end_layout - -\end_inset - - -\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 - - -\begin_inset Text - -\begin_layout Plain Layout - -\family typewriter -int8_t -\end_layout - -\end_inset - - - - -\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 - - -\begin_inset Text - -\begin_layout Plain Layout - -\family typewriter -unsigned char -\end_layout - -\end_inset - - -\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 - - -\begin_inset Text - -\begin_layout Plain Layout - -\family typewriter -uint8_t -\end_layout - -\end_inset - - - - -\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 - - -\begin_inset Text - -\begin_layout Plain Layout - -\family typewriter -short -\end_layout - -\end_inset - - -\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 - - -\begin_inset Text - -\begin_layout Plain Layout - -\family typewriter -int16_t -\end_layout - -\end_inset - - - - -\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 - - -\begin_inset Text - -\begin_layout Plain Layout - -\family typewriter -unsigned short -\end_layout - -\end_inset - - -\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 - - -\begin_inset Text - -\begin_layout Plain Layout - -\family typewriter -uint16_t -\end_layout - -\end_inset - - - - -\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 - - -\begin_inset Text - -\begin_layout Plain Layout - -\family typewriter -int -\end_layout - -\end_inset - - -\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 - - -\begin_inset Text - -\begin_layout Plain Layout - -\family typewriter -int32_t -\end_layout - -\end_inset - - - - -\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 - - -\begin_inset Text - -\begin_layout Plain Layout - -\family typewriter -unsigned int -\end_layout - -\end_inset - - -\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 - - -\begin_inset Text - -\begin_layout Plain Layout - -\family typewriter -uint32_t -\end_layout - -\end_inset - - - - -\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 - - -\begin_inset Text - -\begin_layout Plain Layout - -\family typewriter -long -\end_layout - -\end_inset - - -\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 - - -\begin_inset Text - -\begin_layout Plain Layout - -\family typewriter -int64_t -\end_layout - -\end_inset - - - - -\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 - - -\begin_inset Text - -\begin_layout Plain Layout - -\family typewriter -unsigned long -\end_layout - -\end_inset - - -\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 - - -\begin_inset Text - -\begin_layout Plain Layout - -\family typewriter -uint64_t -\end_layout - -\end_inset - - - - -\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 - - -\begin_inset Text - -\begin_layout Plain Layout - -\family typewriter -long long -\end_layout - -\end_inset - - -\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 - - -\begin_inset Text - -\begin_layout Plain Layout - -\family typewriter -float -\end_layout - -\end_inset - - - - -\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 - - -\begin_inset Text - -\begin_layout Plain Layout - -\family typewriter -unsigned long long -\end_layout - -\end_inset - - -\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 - - -\begin_inset Text - -\begin_layout Plain Layout - -\family typewriter -double -\end_layout - -\end_inset - - - - -\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 - - -\begin_inset Text - -\begin_layout Plain Layout - -\family typewriter -size_t -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout - -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout - -\end_layout - -\end_inset - - - - -\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 - -\begin_inset Newline newline -\end_inset - - -\series bold -#include -\series default - -\begin_inset Newline newline -\end_inset - - -\series bold -#include -\series default - -\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 - -\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 - -\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 - -\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 - -\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 - -\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 - -\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 - -\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 - -\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 - -\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 Binary files a/doc/libHX_Documentation.pdf and /dev/null 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 `_ (if you do not have a binray package from a + distro yet) +* `History `_ 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 `_ + + +Data structures +=============== + +* `Bitmaps `_ +* `Maps `_ +* `Linked lists `_ +* `Inline lists `_ +* `Counted inline lists `_ + + +Strings and memory +================== + +* `String operations `_ +* `Memory containers `_ +* `String formatter `_ +* Everything with `Files and directories `_ + + +Options and configuration files +=============================== + +* `Option parsing `_ +* `Shell-style config file parser `_ + + +Systems-related components +========================== + +* `Time functions `_ +* `Random numbers `_ +* `Process functions `_ + + +Miscellaneous +============= + +* `Type-checking casts `_ +* `Helper headers `_ for other software +* `Macros `_ +* `Misc functions `_ 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 + + 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 + #include + #include + #include + #include + #include + #include + + 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 ``. + +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 ``. + + +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 +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 ``ab``. + +.. 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 + + 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 + + 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 + + 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 + #include + #include + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + 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, ``<``, ``>``, ``&`` and ``"``. + +``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("", 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("", HXQUOTE_HTML, &tmp)); + printf("%s\n", HX_strquote("", HXQUOTE_HTML, &tmp)); + free(tmp); + + +Tokenizing +========== + +.. code-block:: c + + #include 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 + + 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 + + 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 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 + + 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 + + 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 + + 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 + #include + + 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 + #include + #include + + 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 + #include + #include + + 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 + #include + + 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 + + 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 + + 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 +`_). + +.. 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 + + 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 - - 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 + + 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 - - 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. - - -=============================================================================== -- cgit v1.2.3