From bd82d030011cd8b9655e5ded6b6df9343b42a6bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Frings-F=C3=BCrst?= Date: Wed, 4 Feb 2015 14:09:54 +0100 Subject: Imported Upstream version 3.22 --- doc/.gitignore | 2 + doc/Makefile.am | 16 + doc/Makefile.in | 505 + doc/api.txt | 355 + doc/assorted.txt | 68 + doc/changelog.txt | 535 + doc/const_cast.c | 12 + doc/dirstamp.txt | 4 + doc/generate | 6 + doc/generator.cpp | 43 + doc/libHX_Documentation.lyx | 24728 ++++++++++++++++++++++++++++++++++++++++++ doc/libHX_Documentation.pdf | Bin 0 -> 523100 bytes doc/slurp.c | 38 + doc/ux-file.txt | 30 + doc/ux-mmap.txt | 26 + 15 files changed, 26368 insertions(+) create mode 100644 doc/.gitignore create mode 100644 doc/Makefile.am create mode 100644 doc/Makefile.in create mode 100644 doc/api.txt create mode 100644 doc/assorted.txt create mode 100644 doc/changelog.txt create mode 100644 doc/const_cast.c create mode 100644 doc/dirstamp.txt create mode 100755 doc/generate create mode 100644 doc/generator.cpp create mode 100644 doc/libHX_Documentation.lyx create mode 100644 doc/libHX_Documentation.pdf create mode 100644 doc/slurp.c create mode 100644 doc/ux-file.txt create mode 100644 doc/ux-mmap.txt (limited to 'doc') diff --git a/doc/.gitignore b/doc/.gitignore new file mode 100644 index 0000000..2789f42 --- /dev/null +++ b/doc/.gitignore @@ -0,0 +1,2 @@ +*.lyx~ +*.pdf diff --git a/doc/Makefile.am b/doc/Makefile.am new file mode 100644 index 0000000..14eba9f --- /dev/null +++ b/doc/Makefile.am @@ -0,0 +1,16 @@ +# -*- 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 new file mode 100644 index 0000000..50f826f --- /dev/null +++ b/doc/Makefile.in @@ -0,0 +1,505 @@ +# Makefile.in generated by automake 1.13.4 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2013 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 = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +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 +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(am__dist_doc_DATA_DIST) +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) +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) +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@ +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 +.PRECIOUS: 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 + + +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.txt b/doc/api.txt new file mode 100644 index 0000000..eb3b06b --- /dev/null +++ b/doc/api.txt @@ -0,0 +1,355 @@ + +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.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 FIELD_SIZEOF +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 HX_diff_timespec +3.0 3.0 3.0 HX_diff_timeval +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 2.0 2.0 offsetof +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/assorted.txt b/doc/assorted.txt new file mode 100644 index 0000000..b2739e1 --- /dev/null +++ b/doc/assorted.txt @@ -0,0 +1,68 @@ +=============================================================================== +assorted - Assorted functions 2006-02-25 + + +DESCRIPTION + + Some functions have been taken out of libHX because they are largely unused + in code I write. Since there are currently not too many users of libHX that + seem to need these functions, they currently remain out. + + +SYNOPSIS + + size_t HX_pack(char *fmt, size_t len, ...); + int HX_tofrac(size_t *num, size_t *denom, double arg); + + +HX_pack() + + Mimics perl's pack function. FMT can contain: + + A Pascal-style string: a uint8_t length specifier and a string + with up to 255 chars + a (same) + C encode as uint8_t + c encode as int8_t + H encode as uint16_t + h encode as int16_t + L encode as uint32_t + l encode as int32_t + S Like A, but with a uint16_t length specifier and a string + with up to 64K chars + s (same) + V fixed-size string; first argument is string, second is length + + Example: + + HX_pack(dest, sizeof(dest), "LLSV", 1337, 2006, "64k test string", + "fixed test", 5); + + will produce this byte sequence on x86: + + 39 05 00 00 1337 + D6 07 00 00 2006 + 0E 00 15 + 36 34 6B 20 74 65 "64k test string" (length=15) + 73 74 20 73 74 72 + 69 6E 67 + 66 69 78 65 64 "fixed" + + +HX_tofrac() + + Calculates a readable fraction (i.e. 1/3) from arg and puts the + *numerator into num, the denominator into *denom. Since the fraction + is found out by an iterative loop, you can specify the minimum value + of the denominator in *num and the maximum value of the denominator + into *denom before calling the function. + + If a suitable fraction has been found (within the range of the + minimum / maximum denominator, *num and *denom will be overwritten + with the results and 1 is returned; 0 for no success. + + You need to re-put your min/max denom values into *num and *denom + then. + + + diff --git a/doc/changelog.txt b/doc/changelog.txt new file mode 100644 index 0000000..2b68284 --- /dev/null +++ b/doc/changelog.txt @@ -0,0 +1,535 @@ + + +HEAD +==== + + +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/const_cast.c b/doc/const_cast.c new file mode 100644 index 0000000..0a7c070 --- /dev/null +++ b/doc/const_cast.c @@ -0,0 +1,12 @@ +/* + Fails to compile with gcc-4.7, 4.8 with the error message + "const_cast.c:5:13: error: dereferencing pointer to incomplete type". + But __typeof__(*f) is just a fancy way of writing "struct undisclosed" + and should be permitted. (Request for enhancement) +*/ +struct undisclosed; +int main(void) { + const struct undisclosed *f = 0; + __typeof__(*f) *g = 0; + return 0; +} diff --git a/doc/dirstamp.txt b/doc/dirstamp.txt new file mode 100644 index 0000000..92c1696 --- /dev/null +++ b/doc/dirstamp.txt @@ -0,0 +1,4 @@ +Improved dirstamp: + +dirstamp.lst: + [ ! -e $@ -o -n "$(find dir/ -newer $@ -print -quit)" ] && touch $@ || :; diff --git a/doc/generate b/doc/generate new file mode 100755 index 0000000..ed3b8aa --- /dev/null +++ b/doc/generate @@ -0,0 +1,6 @@ +#!/bin/sh -ex + +if [ -z "$srcdir" ]; then + srcdir="."; +fi; +exec lyx -e pdf2 "$srcdir/libHX_Documentation.lyx"; diff --git a/doc/generator.cpp b/doc/generator.cpp new file mode 100644 index 0000000..6c64f80 --- /dev/null +++ b/doc/generator.cpp @@ -0,0 +1,43 @@ +/* + * sample. + * + * Something more or less like Python generators. + */ +#include +#include +template class fi /* filler_iterator */ { + private: + base &parent; + public: + fi(base &p) : parent(p) {}; + bool operator!=(const fi &) { return parent.has_more(); }; + const fi &operator++(void) { return *this; }; + int operator*(void) { return parent.yield(); }; +}; + +class rdgen { + private: + unsigned int remaining; + + public: + rdgen(unsigned int x) { + remaining = x; + }; + bool has_more(void) { + return remaining > 0; + }; + int yield(void) { + --remaining; + return rand(); + }; + + fi begin(void) { return fi(*this); }; + fi end(void) { return fi(*this); }; +}; + +int main(int argc, const char **argv) +{ + for (auto x : rdgen(argc)) + printf("%d\n", x); + return 0; +} diff --git a/doc/libHX_Documentation.lyx b/doc/libHX_Documentation.lyx new file mode 100644 index 0000000..69ad84c --- /dev/null +++ b/doc/libHX_Documentation.lyx @@ -0,0 +1,24728 @@ +#LyX 2.0 created this file. For more info see http://www.lyx.org/ +\lyxformat 413 +\begin_document +\begin_header +\textclass article +\use_default_options true +\maintain_unincluded_children false +\language english +\language_package default +\inputencoding utf8 +\fontencoding global +\font_roman lmodern +\font_sans lmss +\font_typewriter lmtt +\font_default_family default +\use_non_tex_fonts false +\font_sc false +\font_osf false +\font_sf_scale 100 +\font_tt_scale 100 + +\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_amsmath 1 +\use_esint 1 +\use_mhchem 1 +\use_mathdots 1 +\cite_engine natbib_numerical +\use_bibtopic false +\use_indices false +\paperorientation portrait +\suppress_date false +\use_refstyle 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 +\quotes_language english +\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.22 +\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 \slash{} +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 \- +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 + +\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 "sub: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 + +\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 + +\series bold +long +\series default + offsetof(type, member); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +offsetof +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + +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 + FIELD_SIZEOF(struct_type, member); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +FIELD_SIZEOF +\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 +In case +\family typewriter +offsetof +\family default + and +\family typewriter +containerof +\family default + have not already defined by inclusion of another header file, libHX's defs.h + will define these accessors. + +\family typewriter +offsetof +\family default + is defined in +\family typewriter +stddef.h +\family default + (for C) or +\family typewriter +cstddef +\family default + (C++), but inclusion of these is not necessary if you have included +\family typewriter +defs.h +\family default +. + +\family typewriter +defs.h +\family default + will use GCC's +\family typewriter +__builtin_\SpecialChar \- +offsetof +\family default + if available, which does some extra sanity checks in C++ mode. +\end_layout + +\begin_layout Standard + +\family typewriter +offsetof +\family default + calculates the offset of the specified member in the type, which needs + to be a struct or union. +\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 +FIELD_SIZEOF +\family default + (formerly +\family typewriter +HXsizeof_member +\family default + +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXsizeof_member +\end_layout + +\end_inset + +) and +\family typewriter +HXtypeof_member +\family default + are convenient shortcuts 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 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 \- +BUG_\SpecialChar \- +ON_\SpecialChar \- +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. +\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 "sub: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 \- +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 \- +SKEY +\family default + OR'ed with +\family typewriter +HXMAP_\SpecialChar \- +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 \- +SDATA +\family default + OR'ed with +\family typewriter +HXMAP_\SpecialChar \- +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 \slash{} + +\family typewriter +CKEY +\family default +\SpecialChar \slash{} + +\family typewriter +SDATA +\family default +\SpecialChar \slash{} + +\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 "sub: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 \slash{} + 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. +\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 "sub: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 \- +push +\family default + and +\family typewriter +HXdeque_\SpecialChar \- +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 \- +pop +\family default + and +\family typewriter +HXdeque_\SpecialChar \- +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 \- +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 + +\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 + +\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 + +\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 \- +direct_\SpecialChar \- +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 + +\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 + +\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 + +\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_split4( +\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_split4 +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +int +\series default + HX_split5( +\series bold +char * +\series default +s, +\series bold +const char * +\series default +delimiters, +\series bold +int +\series default + max, +\series bold +char ** +\series default +stack); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +\size normal +\color none +HX_split5 +\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_split4 +\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_split5 +\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 +stack +\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_split5 +\begin_inset CommandInset label +LatexCommand label +name "sub:string-ex-HX_split5" + +\end_inset + + +\end_layout + +\begin_layout Standard + +\family typewriter +HX_split5 +\family default +, where the +\begin_inset Quotes eld +\end_inset + +5 +\begin_inset Quotes erd +\end_inset + + should be interpreted (with a bit of imagination and the knowledge of leetspeak +) as an +\begin_inset Quotes eld +\end_inset + +S +\begin_inset Quotes erd +\end_inset + + for stack, as +\family typewriter +HX_split5 +\family default + is often used only with on-stack 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_split5(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_split4 +\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_split4 +\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_split4(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 + +\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 + +\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 "sub: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 \slash{} +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 + +\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 + +\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 \- +REALPATH_\SpecialChar \- +SELF +\begin_inset space ~ +\end_inset + +| HX_\SpecialChar \- +REALPATH_\SpecialChar \- +PARENT +\family default +. + Note that +\family typewriter +HX_\SpecialChar \- +REALPATH_\SpecialChar \- +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 platforms such as do not have readdir (e. +\begin_inset space \thinspace{} +\end_inset + +g. +\begin_inset space \space{} +\end_inset + +Win32), or to work around peculiarities in the lower implementation. + Solaris's +\family typewriter +struct dirent +\family default + for example is +\begin_inset Quotes eld +\end_inset + +too small +\begin_inset Quotes erd +\end_inset + +, that is, +\family typewriter +readdir +\family default + will cause a buffer overrun when Linux code is directly ported to it without + anticipating for this scenario. + libHX's +\family typewriter +io.c +\family default + mitigates this. +\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 "sub: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 "sub: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 \- +INC +\family default + or +\family typewriter +HXOPT_\SpecialChar \- +DEC +\family default + are specified as flags (see section +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "sub: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 "sub: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 \- +LLONG +\family default +, +\family typewriter + HXTYPE_\SpecialChar \- +ULLONG +\family default +, +\family typewriter + HXTYPE_\SpecialChar \- +INT64 +\family default + and +\family typewriter + HXTYPE_\SpecialChar \- +UINT64 +\family default + use +\family typewriter + strtoll +\family default + and/or +\family typewriter + strtoull +\family default +, which may not be available on all platforms. +\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 + +\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 \- +FLOAT +\family default + and +\family typewriter +HXTYPE_\SpecialChar \- +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 "sub:option-example-cb" + +\end_inset + +). +\end_layout + +\begin_layout Subsection +Flags +\begin_inset CommandInset label +LatexCommand label +name "sub: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 \- +INC +\family default + and +\family typewriter +HXOPT_\SpecialChar \- +DEC +\family default + may be specified at a time, and they require that the base type is +\family typewriter +HXTYPE_\SpecialChar \- +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 "sub: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 \slash{} +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 \slash{} +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 \slash{} +transformed value. +\end_layout + +\begin_layout Standard +Only one of ( +\family typewriter +HXOPT_OR +\family default +, +\family typewriter +HXOPT_\SpecialChar \- +AND +\family default +, +\family typewriter +HXOPT_\SpecialChar \- +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 \- +UINT +\family default +, +\family typewriter +HXTYPE_\SpecialChar \- +ULONG +\family default +, etc.). + An example can be found in section +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "sub: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 \- +NONE +\family default +, +\family typewriter +HXTYPE_\SpecialChar \- +VAL +\family default + or +\family typewriter +HXTYPE_\SpecialChar \- +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 +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 "sub:option-pitfalls-static" + +\end_inset + + +\end_layout + +\begin_layout Standard +The following is an example of a trap regarding +\family typewriter +HXTYPE_\SpecialChar \- +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 \- +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 \- +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 \- +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 "sub: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 "sub: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 "sub: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 "sub: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 \- +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 "sub: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 \- +DESTROY_\SpecialChar \- +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 \slash{} + +\family typewriter +get_fruit +\family default +. + +\family typewriter +HXOPT_\SpecialChar \- +DESTROY_\SpecialChar \- +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 "sub: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 "sub: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 \- +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 \- +run_\SpecialChar \- +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 \slash{} +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 "sub: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 \- +run_\SpecialChar \- +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 \slash{} +null +\family default +. + +\family typewriter +HXPROC_\SpecialChar \- +STDIN +\family default + and +\family typewriter +HXPROC_\SpecialChar \- +NULL_\SpecialChar \- +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 \slash{} +null +\family default +, thereby essentially discarding its output. + +\family typewriter +HXPROC_\SpecialChar \- +STDOUT +\family default + and +\family typewriter +HXPROC_\SpecialChar \- +NULL_\SpecialChar \- +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 \slash{} +null +\family default +, thereby essentially discarding its output. + +\family typewriter +HXPROC_\SpecialChar \- +STDERR +\family default + and +\family typewriter +HXPROC_\SpecialChar \- +NULL_\SpecialChar \- +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 "sub: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 \- +New\SpecialChar \- +Text\SpecialChar \- +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 \- +Set\SpecialChar \- +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 \- +FRAME_\SpecialChar \- +STYLE +\family default + and a flag such that the dialog does not create a new window in the task + bar ( +\family typewriter +wxFRAME_\SpecialChar \- +NO_\SpecialChar \- +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" + +\end_inset + + +\end_layout + +\end_body +\end_document diff --git a/doc/libHX_Documentation.pdf b/doc/libHX_Documentation.pdf new file mode 100644 index 0000000..0a1f6fb Binary files /dev/null and b/doc/libHX_Documentation.pdf differ diff --git a/doc/slurp.c b/doc/slurp.c new file mode 100644 index 0000000..f0b047d --- /dev/null +++ b/doc/slurp.c @@ -0,0 +1,38 @@ +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/ux-file.txt b/doc/ux-file.txt new file mode 100644 index 0000000..2f32247 --- /dev/null +++ b/doc/ux-file.txt @@ -0,0 +1,30 @@ +=============================================================================== +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.txt b/doc/ux-mmap.txt new file mode 100644 index 0000000..43f5ac9 --- /dev/null +++ b/doc/ux-mmap.txt @@ -0,0 +1,26 @@ +=============================================================================== +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