diff options
Diffstat (limited to 'doc/libHX_Documentation.lyx')
-rw-r--r-- | doc/libHX_Documentation.lyx | 24728 |
1 files changed, 24728 insertions, 0 deletions
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 + <libHX/init.h> +\begin_inset Newline newline +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +int +\series default + HX_init( +\series bold +void +\series default +); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +libHX_init +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +void +\series default + HX_exit( +\series bold +void +\series default +); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +libHX_exit +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +Before using the library's functions, +\family typewriter +HX_init +\family default + must be called. + This function will initialize any needed state libHX needs for itself, + if any. + It is designed to be invoked multiple times, such as for example, from + different libraries linking to libHX itself, and will refcount. + On success, >0 is returned. + If there was an error, it will return a negative error code or zero. + +\family typewriter +HX_exit +\family default + is the logical counterpart of notifying that the library is no longer used. +\end_layout + +\begin_layout Section +Type-checking casts +\end_layout + +\begin_layout Standard +The C++ language provides so-called +\begin_inset Quotes eld +\end_inset + +new-style casts +\begin_inset Quotes erd +\end_inset + +, referring to the four template-looking invocations +\family typewriter +static_cast<> +\family default +, +\family typewriter +const_cast<> +\family default +, +\family typewriter +reinterpret_cast<> +\family default + and +\family typewriter +dynamic_cast<> +\family default +. + No such blessing was given to the C language, but still, even using macros + that expand to the olde cast make it much easier to find casts in source + code and annotate why something was casted, which is already an improvement. +\begin_inset space ~ +\end_inset + +--- Actually, it +\shape italic +is +\shape default + possible to do a some type checking, using some GCC extensions, which augments + these macros from their documentary nature to an actual safety measure. +\end_layout + +\begin_layout Subsection + +\family typewriter +reinterpret_cast +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +reinterpret_cast +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard + +\family typewriter +reinterpret_cast() +\family default + maps directly to the old-style typecast, +\family typewriter +(type)(expr) +\family default +, and causes the bit pattern for the expr rvalue to be +\begin_inset Quotes eld +\end_inset + +reinterpreted +\begin_inset Quotes erd +\end_inset + + as a new type. + You will notice that +\begin_inset Quotes eld +\end_inset + +reinterpret +\begin_inset Quotes erd +\end_inset + + is the longest of all the +\family typewriter +*_cast +\family default + names, and can easily cause your line to grow to 80 columns (the good maximum + in many style guides). + As a side effect, it is a good indicator that something potentially dangerous + might be going on, for example converting intergers from/to pointer. +\end_layout + +\begin_layout LyX-Code + +\series bold +#include +\series default + <libHX/defs.h> +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +libHX/defs.h +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold + +\begin_inset Newline newline +\end_inset + +int +\series default + i; +\begin_inset Newline newline +\end_inset + + +\series bold +/* +\family roman +\series default +\shape italic +Tree with numeric keys +\family default +\series bold +\shape default + */ +\series default + +\begin_inset Newline newline +\end_inset + +tree = HXhashmap_init(0); +\begin_inset Newline newline +\end_inset + + +\series bold +for +\series default + (i = 0; i < 6; ++i) +\begin_inset Newline newline +\end_inset + + HXmap_add(tree, +\series bold +reinterpret_cast +\series default +( +\series bold +void * +\series default +, +\begin_inset Newline newline +\end_inset + + +\series bold +static_cast +\series default +( +\series bold +long +\series default +, i)), my_data); +\end_layout + +\begin_layout Subsection + +\family typewriter +signed_cast +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +signed_cast +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +This tag is for annotating that the cast was solely done to change the signednes +s of pointers to char +\begin_inset space ~ +\end_inset + +--- and only those. + No integers etc. + The intention is to facilitate working with libraries that use +\family typewriter +unsigned char +\begin_inset space ~ +\end_inset + +* +\family default + pointers, such as libcrypto and libssl (from the OpenSSL project) or libxml2, + for example. + See table +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "tab:defs-signed_cast" + +\end_inset + + for the allowed conversions. + C++ does +\shape italic +not +\shape default + actually have a +\family typewriter +signed_cast<> +\family default +, and one would have to use +\family typewriter +reinterpret_cast<> +\family default + to do the conversion, because +\family typewriter +static_cast<> +\family default + does not allow conversion from +\family typewriter +const char +\begin_inset space ~ +\end_inset + +* +\family default + to +\family typewriter +const unsigned char +\begin_inset space ~ +\end_inset + +* +\family default +, for example. + (libHX's +\family typewriter +static_cast() +\family default + would also throw at least a compiler warning about the different signedness.) + libHX does provide a +\family typewriter +signed_cast<> +\family default + for C++ though. + This is where +\family typewriter +signed_cast +\family default + comes in. +\end_layout + +\begin_layout Standard +\begin_inset Float table +wide false +sideways false +status open + +\begin_layout Plain Layout +\align center +\begin_inset Tabular +<lyxtabular version="3" rows="7" columns="7"> +<features tabularvalignment="middle"> +<column alignment="center" valignment="top" width="0"> +<column alignment="center" valignment="top" width="0"> +<column alignment="center" valignment="top" width="0"> +<column alignment="center" valignment="top" width="0"> +<column alignment="center" valignment="top" width="0"> +<column alignment="center" valignment="top" width="0"> +<column alignment="center" valignment="top" width="0"> +<row> +<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\series bold +From +\backslash + To +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\series bold +c* +\series default +section +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\series bold +sc* +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\series bold +uc* +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\series bold +Cc* +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\series bold +Csc* +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\series bold +Cuc* +\end_layout + +\end_inset +</cell> +</row> +<row> +<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\family typewriter +\series bold +char * +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout +\begin_inset Formula $\checkmark$ +\end_inset + + +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout +\begin_inset Formula $\checkmark$ +\end_inset + + +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout +\begin_inset Formula $\checkmark$ +\end_inset + + +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout +\begin_inset Formula $\checkmark$ +\end_inset + + +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout +\begin_inset Formula $\checkmark$ +\end_inset + + +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout +\begin_inset Formula $\checkmark$ +\end_inset + + +\end_layout + +\end_inset +</cell> +</row> +<row> +<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\family typewriter +\series bold +signed char * +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout +\begin_inset Formula $\checkmark$ +\end_inset + + +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout +\begin_inset Formula $\checkmark$ +\end_inset + + +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout +\begin_inset Formula $\checkmark$ +\end_inset + + +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout +\begin_inset Formula $\checkmark$ +\end_inset + + +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout +\begin_inset Formula $\checkmark$ +\end_inset + + +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout +\begin_inset Formula $\checkmark$ +\end_inset + + +\end_layout + +\end_inset +</cell> +</row> +<row> +<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\family typewriter +\series bold +unsigned char * +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout +\begin_inset Formula $\checkmark$ +\end_inset + + +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout +\begin_inset Formula $\checkmark$ +\end_inset + + +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout +\begin_inset Formula $\checkmark$ +\end_inset + + +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout +\begin_inset Formula $\checkmark$ +\end_inset + + +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout +\begin_inset Formula $\checkmark$ +\end_inset + + +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout +\begin_inset Formula $\checkmark$ +\end_inset + + +\end_layout + +\end_inset +</cell> +</row> +<row> +<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\family typewriter +\series bold +const char * +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout +-- +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout +-- +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout +-- +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout +\begin_inset Formula $\checkmark$ +\end_inset + + +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout +\begin_inset Formula $\checkmark$ +\end_inset + + +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout +\begin_inset Formula $\checkmark$ +\end_inset + + +\end_layout + +\end_inset +</cell> +</row> +<row> +<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\family typewriter +\series bold +const signed char * +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout +-- +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout +-- +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout +-- +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout +\begin_inset Formula $\checkmark$ +\end_inset + + +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout +\begin_inset Formula $\checkmark$ +\end_inset + + +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout +\begin_inset Formula $\checkmark$ +\end_inset + + +\end_layout + +\end_inset +</cell> +</row> +<row> +<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\family typewriter +\series bold +const unsigned char * +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout +-- +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout +-- +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout +-- +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout +\begin_inset Formula $\checkmark$ +\end_inset + + +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout +\begin_inset Formula $\checkmark$ +\end_inset + + +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout +\begin_inset Formula $\checkmark$ +\end_inset + + +\end_layout + +\end_inset +</cell> +</row> +</lyxtabular> + +\end_inset + + +\end_layout + +\begin_layout Plain Layout +\begin_inset Caption + +\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 +<lyxtabular version="3" rows="2" columns="2"> +<features tabularvalignment="middle"> +<column alignment="center" valignment="top" width="0"> +<column alignment="center" valignment="top" width="0"> +<row> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\family typewriter +int ** +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\family typewriter +int *const * +\end_layout + +\end_inset +</cell> +</row> +<row> +<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\family typewriter +const int ** +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\family typewriter +const int *const * +\end_layout + +\end_inset +</cell> +</row> +</lyxtabular> + +\end_inset + + +\end_layout + +\begin_layout Plain Layout +\begin_inset Caption + +\begin_layout Plain Layout +Accepted expr/target types for +\family typewriter +const_cast2 +\family default +; example for the +\begin_inset Quotes eld +\end_inset + +int +\begin_inset Quotes erd +\end_inset + + type +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Plain Layout +\align center +Conversion is permitted when expression and target type are from the table. +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +It is currently not possible to use +\family typewriter +const_cast +\family default +1/2/3 on pointers to structures whose member structure is unknown. +\end_layout + +\begin_layout Standard +\begin_inset Newpage clearpage +\end_inset + + +\end_layout + +\begin_layout Section +Macros +\end_layout + +\begin_layout Standard +All macros in this section are available through +\family typewriter +#include <libHX/defs.h> +\family default + +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +libHX/defs.h +\end_layout + +\end_inset + +. +\end_layout + +\begin_layout Subsection +Preprocessor +\end_layout + +\begin_layout LyX-Code + +\series bold +#define +\series default + HX_STRINGIFY(s) +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HX_STRINGIFY +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +Transforms the expansion of the argument +\family typewriter +s +\family default + into a C string. +\end_layout + +\begin_layout Subsection +Sizes +\end_layout + +\begin_layout LyX-Code + +\series bold +#define +\series default + HXSIZEOF_Z16 +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXSIZEOF_Z16 +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +#define +\series default + HXSIZEOF_Z32 +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXSIZEOF_Z32 +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +#define +\series default + HXSIZEOF_Z64 +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXSIZEOF_Z64 +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +Expands to the size needed for a buffer (including ' +\family typewriter + +\backslash +0 +\family default +') to hold the base-10 string representation of a 16\SpecialChar \nobreakdash- +, 32\SpecialChar \nobreakdash- + or 64\SpecialChar \nobreakdash- +bit integer. +\end_layout + +\begin_layout Subsection +Locators +\end_layout + +\begin_layout LyX-Code + +\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 + <libHX/misc.h> +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +libHX/misc.h +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +int +\series default + HX_ffs( +\series bold +unsigned long +\series default + z); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HX_ffs +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +int +\series default + HX_fls( +\series bold +unsigned long +\series default + z); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HX_fls +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +void +\series default + HX_hexdump( +\series bold +FILE * +\series default +fp, +\series bold +const void * +\series default +ptr, +\series bold +unsigned int +\series default + len); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HX_hexdump +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +void +\series default + HX_zvecfree( +\series bold +char ** +\series default +); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HX_zvecfree +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +unsigned int +\series default + HX_zveclen( +\series bold +const char *const * +\series default +); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HX_zveclen +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Description + +\family typewriter +HX_ffs +\family default + Finds the first (lowest-significant) bit in a value and returns its position, + or -1 to indicate failure. +\end_layout + +\begin_layout Description + +\family typewriter +HX_fls +\family default + Finds the last (most-significant) bit in a value and returns its position, + or -1 to indicate failure. +\end_layout + +\begin_layout Description + +\family typewriter +HX_hexdump +\family default + Outputs a nice pretty-printed hex and ASCII dump to the filedescriptor + +\family typewriter +fp +\family default +. + +\family typewriter +ptr +\family default + is the memory area, of which +\family typewriter +len +\family default + bytes will be dumped. +\end_layout + +\begin_layout Description + +\family typewriter +HX_zvecfree +\family default + Frees the supplied Z-vector array. + (Frees all array elements from the first element to (excluding) the first + +\family typewriter +NULL +\family default + element.) +\end_layout + +\begin_layout Description + +\family typewriter +HX_zveclen +\family default + Counts the number of array elements until the first +\family typewriter +NULL +\family default + array element is seen, and returns this number. +\end_layout + +\begin_layout Section +Time functions +\end_layout + +\begin_layout Standard +Time in POSIX systems is represented in +\family typewriter +struct timespec +\family default +. + This structure is composed of two members: one integer for the number of + full seconds in the time value, and one integer for the number of nanoseconds + that remain when subtracting the full seconds from the time value. + POSIX leaves it unspecified how negative time is to be represented with + this structure, so I have devised an algebra for use with the same struct + that gives negative time support. +\end_layout + +\begin_layout Standard +Since integers often cannot store negative zero (due to e. +\begin_inset space \thinspace{} +\end_inset + +g. +\begin_inset space \space{} +\end_inset + +use of 2s complements in the language implementation), we will store the + minus sign in the nanosecond member if the integral second part is zero. + This gives us the property that we can test for negative time by looking + for whether at least one member of the structure is negative. + Also, we want to avoid storing the minus in both members to somewhat aid + the pretty-printing construct often seen, +\end_layout + +\begin_layout LyX-Code +printf("%ld.%09ld +\backslash +n", (long)ts.tv_sec, ts.tv_nsec); +\end_layout + +\begin_layout Standard +The number of combinations of a (non-zero) negative number, zero and a (non-zero +) positive number is small, so we can actually just exhaustively list them + all. +\end_layout + +\begin_layout Standard +\noindent +\align center +\begin_inset Tabular +<lyxtabular version="3" rows="4" columns="6"> +<features tabularvalignment="middle"> +<column alignment="center" valignment="top" width="0"> +<column alignment="center" valignment="top" width="0"> +<column alignment="center" valignment="top" width="0"> +<column alignment="center" valignment="top" width="0"> +<column alignment="center" valignment="top" width="0"> +<column alignment="center" valignment="top" width="0"> +<row> +<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout +Representation +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout +Time value +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout +R +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout +T +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout +R +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout +T +\end_layout + +\end_inset +</cell> +</row> +<row> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout +\begin_inset Formula $\left\{ -1,-1\right\} $ +\end_inset + + +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout +illegal +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout +\begin_inset Formula $\left\{ 0,-1\right\} $ +\end_inset + + +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout +-0.1 +\begin_inset space \thinspace{} +\end_inset + +s +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout +\begin_inset Formula $\left\{ 1,-1\right\} $ +\end_inset + + +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout +illegal +\end_layout + +\end_inset +</cell> +</row> +<row> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout +\begin_inset Formula $\left\{ -1,0\right\} $ +\end_inset + + +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout +-1.0 +\begin_inset space \thinspace{} +\end_inset + +s +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout +\begin_inset Formula $\left\{ 0,0\right\} $ +\end_inset + + +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout +0.0 +\begin_inset space \thinspace{} +\end_inset + +s +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout +\begin_inset Formula $\left\{ 1,0\right\} $ +\end_inset + + +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout +1.0 +\begin_inset space \thinspace{} +\end_inset + +s +\end_layout + +\end_inset +</cell> +</row> +<row> +<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout +\begin_inset Formula $\left\{ -1,1\right\} $ +\end_inset + + +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout +-1.1 +\begin_inset space \thinspace{} +\end_inset + +s +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout +\begin_inset Formula $\left\{ 0,1\right\} $ +\end_inset + + +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout +0.1 +\begin_inset space \thinspace{} +\end_inset + +s +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout +\begin_inset Formula $\left\{ 1,1\right\} $ +\end_inset + + +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout +1.1 +\begin_inset space \thinspace{} +\end_inset + +s +\end_layout + +\end_inset +</cell> +</row> +</lyxtabular> + +\end_inset + + +\end_layout + +\begin_layout Standard +The set of so-extended valid timespecs is therefore: +\end_layout + +\begin_layout Standard +\begin_inset Formula +\[ +K=\left\{ \left(i,f\right):i,f\in\mathbb{Z}\wedge i\neq0\wedge0\leq f<10^{9}\right\} \cup\left\{ \left(i,f\right):i=0\wedge f\in\mathbb{Z}\wedge-10^{9}<f<10^{9}\right\} +\] + +\end_inset + + +\end_layout + +\begin_layout Subsection +Function list +\end_layout + +\begin_layout LyX-Code + +\series bold +#include +\series default + <libHX/misc.h> +\begin_inset Newline newline +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +bool +\series default + HX_timespec_isneg( +\series bold +const struct +\series default + timespec +\series bold +* +\series default +p); +\begin_inset Index idx +status open + +\begin_layout Plain Layout +HX_timespec_isneg +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +struct +\series default + timespec +\series bold +* +\series default +HX_timespec_neg( +\series bold +struct +\series default + timespec +\series bold +* +\series default +result, +\begin_inset Newline newline +\end_inset + + +\series bold +const struct +\series default + timespec +\series bold +* +\series default +p); +\begin_inset Index idx +status open + +\begin_layout Plain Layout +HX_timespec_neg +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +struct +\series default + timespec +\series bold +* +\series default +HX_timespec_add( +\series bold +struct +\series default + timespec +\series bold +* +\series default +result, +\begin_inset Newline newline +\end_inset + + +\series bold +const struct +\series default + timespec +\series bold +* +\series default +p, +\series bold +const struct +\series default + timespec +\series bold +* +\series default +q); +\begin_inset Index idx +status open + +\begin_layout Plain Layout +HX_timespec_add +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +struct +\series default + timespec +\series bold +* +\series default +HX_timespec_sub( +\series bold +struct +\series default + timespec +\series bold +* +\series default +delta, +\begin_inset Newline newline +\end_inset + + +\series bold +const struct +\series default + timespec +\series bold +* +\series default +p, +\series bold +const struct +\series default + timespec +\series bold +* +\series default +q); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HX_timespec_sub +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +struct +\series default + timespec +\series bold +* +\series default +HX_timespec_mul( +\series bold +struct +\series default + timespec +\series bold +* +\series default +delta, +\begin_inset Newline newline +\end_inset + + +\series bold +const struct +\series default + timespec +\series bold +* +\series default +p, +\series bold +int +\series default + f); +\begin_inset Index idx +status open + +\begin_layout Plain Layout +HX_timespec_mul +\end_layout + +\end_inset + + +\end_layout + +\begin_layout LyX-Code + +\series bold +struct +\series default + timespec +\series bold +* +\series default +HX_timespec_mulf( +\series bold +struct +\series default + timespec +\series bold +* +\series default +delta, +\begin_inset Newline newline +\end_inset + + +\series bold +const struct +\series default + timespec +\series bold +* +\series default +p, +\series bold +double +\series default + f); +\begin_inset Index idx +status open + +\begin_layout Plain Layout +HX_timespec_mulf +\end_layout + +\end_inset + + +\end_layout + +\begin_layout LyX-Code + +\series bold +struct +\series default + timeval +\series bold +* +\series default +HX_timeval_sub( +\series bold +struct +\series default + timeval +\series bold +* +\series default +delta, +\begin_inset Newline newline +\end_inset + + +\series bold +const struct +\series default + timeval +\series bold +* +\series default +p, +\series bold +const struct +\series default + timeval +\series bold +* +\series default +q); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HX_timeval_sub +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +int +\series default + HX_time_compare( +\series bold +const struct +\series default + stat +\series bold +* +\series default +a, +\series bold +const struct +\series default + stat +\series bold +* +\series default +b, +\series bold +int +\series default + mode); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HX_time_compare +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Description + +\family typewriter +HX_timespec_isneg +\family default + Determines whether a timespec structure represents (non-zero) negative + time. +\end_layout + +\begin_layout Description + +\family typewriter +HX_timespec_neg +\family default + Computes the negation of the time specified by +\family typewriter +p +\family default +. + +\family typewriter +result +\family default + and +\family typewriter +p +\family default + may point to the same structure. +\end_layout + +\begin_layout Description + +\family typewriter +HX_timespec_add +\family default + Calculates the sum of the two times specified by +\family typewriter +p +\family default + and +\family typewriter +q +\family default +, which are of type +\family typewriter +struct timespec +\family default +. + Any of +\family typewriter +result +\family default +, +\family typewriter +p +\family default + and +\family typewriter +q +\family default + may point to the same structure. +\end_layout + +\begin_layout Description + +\family typewriter +HX_timespec_sub +\family default + Calculates the difference between the two timepoints p and q, which are + of type +\family typewriter +struct timespec +\family default + (nanosecond granularity). +\end_layout + +\begin_layout Description + +\family typewriter +HX_timespec_mul +\family default + Multiplies the time quantum in +\family typewriter +p +\family default + by +\family typewriter +f +\family default +. +\end_layout + +\begin_layout Description + +\family typewriter +HX_timespec_mulf +\family default + Multiplies the time quantum in +\family typewriter +p +\family default + by +\family typewriter +f +\family default +. +\end_layout + +\begin_layout Description + +\family typewriter +HX_timeval_sub +\family default + Calculates the difference between the two timepoints p and q, which are + of type +\family typewriter +struct timeval +\family default + (microsecnod granularity). +\end_layout + +\begin_layout Description + +\family typewriter +HX_time_compare +\family default + Compares the timestamps from two +\family typewriter +struct stat +\family default +s. + +\family typewriter +mode +\family default + indicates which field is compared, which can either be +\family typewriter +'a' +\family default + for the access time, +\family typewriter +'c' +\family default + for the inode change time, +\family typewriter +'m' +\family default + for the modification time, or +\family typewriter +'o' +\family default + for the creation time (where available). + Returns a negative number if the time in +\family typewriter +a +\family default + is less than +\family typewriter +b +\family default +, zero when they are equal, or a positive number greater than zero if +\family typewriter +a +\family default + is greater than +\family typewriter +b +\family default +. +\end_layout + +\begin_layout Standard +The macros +\family typewriter +HX_TIMESPEC_FMT +\family default + +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HX_TIMESPEC_FMT +\end_layout + +\end_inset + + and +\family typewriter +HX_TIMESPEC_EXP +\family default + +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HX_TIMESPEC_EXP +\end_layout + +\end_inset + + can be used for passing and printing a +\family typewriter +struct timespec +\family default + using the * +\family typewriter +printf +\family default + function family: +\end_layout + +\begin_layout LyX-Code + +\series bold +struct +\series default + timespec p; +\begin_inset Newline newline +\end_inset + +clock_gettime(CLOCK_MONOTONIC, &p); +\begin_inset Newline newline +\end_inset + +printf("Now: " HX_TIMESPEC_FMT, HX_TIMESPEC_EXP(&p)); +\end_layout + +\begin_layout Standard +Similarly, +\family typewriter +HX_TIMEVAL_FMT +\family default + +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HX_TIMEVAL_FMT +\end_layout + +\end_inset + + and +\family typewriter +HX_TIMEVAL_EXP +\family default + +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HX_TIMEVAL_EXP +\end_layout + +\end_inset + + exist for the older +\family typewriter +struct timeval +\family default +. +\end_layout + +\begin_layout Standard +\begin_inset Newpage clearpage +\end_inset + + +\end_layout + +\begin_layout Section +Bitmaps +\end_layout + +\begin_layout LyX-Code + +\series bold +#include +\series default + <libHX/misc.h> +\begin_inset Newline newline +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +size_t +\series default + HXbitmap_size( +\series bold +type +\series default + array, +\series bold +unsigned int +\series default + bits); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXbitmap_size +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +void +\series default + HXbitmap_set( +\series bold +type * +\series default +bmap, +\series bold +unsigned int +\series default + bit); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXbitmap_set +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +void +\series default + HXbitmap_clear( +\series bold +type * +\series default +bmap, +\series bold +unsigned int +\series default + bit); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXbitmap_clear +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +bool +\series default + HXbitmap_test( +\series bold +type * +\series default +bmap, +\series bold +unsigned int +\series default + bit); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXbitmap_test +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +All of these four are implemented as macros, so they can be used with any + integer type that is desired to be used. +\end_layout + +\begin_layout Description + +\family typewriter +HXbitmap_size +\family default + Returns the amount of +\begin_inset Quotes eld +\end_inset + +type +\begin_inset Quotes erd +\end_inset + +-based integers that would be needed to hold an array of the requested amount + of bits. +\end_layout + +\begin_layout Description + +\family typewriter +HXbitmap_set +\family default + Set the specific bit in the bitmap. +\end_layout + +\begin_layout Description + +\family typewriter +HXbitmap_clear +\family default + Clear the specific bit in this bitmap. +\end_layout + +\begin_layout Description + +\family typewriter +HXbitmap_test +\family default + Test for the specific bit and returns +\family typewriter +true +\family default + if it is set, otherwise +\family typewriter +false +\family default +. +\end_layout + +\begin_layout Subsubsection +Example +\end_layout + +\begin_layout LyX-Code + +\series bold +#include +\series default + <stdlib.h> +\begin_inset Newline newline +\end_inset + + +\series bold +#include +\series default + <string.h> +\begin_inset Newline newline +\end_inset + + +\series bold +#include +\series default + <libHX/misc.h> +\begin_inset Newline newline +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +int +\series default + main( +\series bold +void +\series default +) +\begin_inset Newline newline +\end_inset + +{ +\begin_inset Newline newline +\end_inset + + +\series bold +unsigned long +\series default + bitmap +\series bold +[ +\series default +HXbitmap_size( +\series bold +unsigned long +\series default +, 128) +\series bold +] +\series default +; +\begin_inset Newline newline +\end_inset + + +\begin_inset Newline newline +\end_inset + + memset(bitmap, 0, sizeof(bitmap)); +\begin_inset Newline newline +\end_inset + + HXbitmap_set(bitmap, 49); +\begin_inset Newline newline +\end_inset + + +\series bold +return +\series default + HXbitmap_get(bitmap, HX_irand(0, 128)) ? +\begin_inset Newline newline +\end_inset + + EXIT_SUCCESS : EXIT_FAILURE; +\begin_inset Newline newline +\end_inset + +} +\end_layout + +\begin_layout Standard +\begin_inset Newpage clearpage +\end_inset + + +\end_layout + +\begin_layout Part +Data structures +\end_layout + +\begin_layout Section +Maps +\begin_inset CommandInset label +LatexCommand label +name "sec:maps" + +\end_inset + + +\end_layout + +\begin_layout Standard +A map is a collection of key-value pairs. + (Some languages, such as Perl, also call them +\begin_inset Quotes eld +\end_inset + +associative array +\begin_inset Quotes erd +\end_inset + + or just +\begin_inset Quotes eld +\end_inset + +hash +\begin_inset Quotes erd +\end_inset + +, however, the underlying storage mechanism may not be an array or a hash, + however.) Each key is unique and has an associated value. + Keys can be any data desired; HXmap allows to specify your own key and + data handling functions so they can be strings, raw pointers, or complex + structures. +\end_layout + +\begin_layout Standard +To access any map-related functions, +\family typewriter +#include <libHX\SpecialChar \slash{} +map.h> +\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 $a<b$ +\end_inset + +, zero on +\begin_inset Formula $a=b$ +\end_inset + +, and positive non-zero when +\begin_inset Formula $a>b$ +\end_inset + +. +\end_layout + +\begin_layout LyX-Code + +\series bold +static int +\series default + strcmp_rev( +\series bold +const void * +\series default +a, +\series bold +const void * +\series default +b, +\series bold +size_t +\series default + z) +\begin_inset Newline newline +\end_inset + +{ +\begin_inset Newline newline +\end_inset + + +\series bold +/* +\family roman +\series default +\shape italic +z is provided for cases when things are raw memory blocks. + +\family default +\series bold +\shape default + */ +\series default + +\begin_inset Newline newline +\end_inset + + +\series bold +return +\series default + strcmp(b, a); +\begin_inset Newline newline +\end_inset + +} +\begin_inset Newline newline +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +static const struct +\series default + HXmap_ops rev = { +\begin_inset Newline newline +\end_inset + + .k_compare = strcmp_rev, +\begin_inset Newline newline +\end_inset + +}; +\begin_inset Newline newline +\end_inset + +HXmap_init5(HXMAPT_RBTREE, HXMAP_SKEY, &rev, 0, +\shape italic +dsize +\shape default +); +\end_layout + +\begin_layout Subsubsection +Keys with non-unique data +\begin_inset CommandInset label +LatexCommand label +name "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 + <libHX/deque.h> +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +libHX/deque.h +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +struct +\series default + HXdeque { +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +struct HXdeque +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +struct +\series default + HXdeque_node +\series bold +* +\series default +first, +\series bold +* +\series default +last; +\begin_inset Newline newline +\end_inset + + +\series bold +unsigned int +\series default + items; +\begin_inset Newline newline +\end_inset + + +\series bold +void * +\series default +ptr; +\begin_inset Newline newline +\end_inset + +}; +\begin_inset Newline newline +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +struct +\series default + HXdeque_node { +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +struct HXdeque_node +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +struct +\series default + HXdeque_node +\series bold +* +\series default +next, +\series bold +* +\series default +prev; +\begin_inset Newline newline +\end_inset + + +\series bold +struct +\series default + HXdeque +\series bold +* +\series default +parent; +\begin_inset Newline newline +\end_inset + + +\series bold +void * +\series default +ptr; +\begin_inset Newline newline +\end_inset + +}; +\end_layout + +\begin_layout Standard +The +\family typewriter +ptr +\family default + member in +\family typewriter +struct HXdeque +\family default + provides room for an arbitrary custom user-supplied pointer. + +\family typewriter +items +\family default + will reflect the number of elements in the list, and must not be modified. + +\family typewriter +first +\family default + and +\family typewriter +last +\family default + provide entrypoints to the list's ends. +\end_layout + +\begin_layout Standard + +\family typewriter +ptr +\family default + within +\family typewriter +struct HXdeque_node +\family default + is the pointer to the user's data. + It may be modified and used at will by the user. + See example section +\begin_inset space ~ +\end_inset + +. +\end_layout + +\begin_layout Subsection +Constructor, destructors +\end_layout + +\begin_layout LyX-Code + +\series bold +struct +\series default + HXdeque +\series bold +* +\series default +HXdeque_init( +\series bold +void +\series default +); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXdeque_init +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +void +\series default + HXdeque_free( +\series bold +struct +\series default + HXdeque +\series bold +* +\series default +dq); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXdeque_free +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +void +\series default + HXdeque_genocide( +\series bold +struct +\series default + HXdeque +\series bold +* +\series default +dq); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXdeque_genocide +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +void +\series default + HXdeque_genocide2( +\series bold +struct +\series default + HXdeque +\series bold +* +\series default +dq, +\series bold +void (* +\series default +xfree +\series bold +) +\series default +( +\series bold +void * +\series default +)); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXdeque_genocide2 +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +void ** +\series default +HXdeque_to_vec( +\series bold +struct +\series default + HXdeque +\series bold +* +\series default +dq, +\series bold +unsigned int * +\series default +num); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXdeque_to_vec +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +To allocate a new empty list, use +\family typewriter +HXdeque_init +\family default +. + +\family typewriter +HXdeque_free +\family default + will free the list (including all nodes owned by the list), but not the + data pointers. +\end_layout + +\begin_layout Standard + +\family typewriter +HXdeque_genocide +\family default + is a variant that will not only destroy the list, but also calls a freeing + function +\family typewriter +free() +\family default + on all stored data pointers. + This puts a number of restrictions on the characteristics of the list: + all data pointers must have been obtained with +\family typewriter +malloc +\family default +, +\family typewriter +calloc +\family default + or +\family typewriter +realloc +\family default + before, and no data pointer must exist twice in the list. + The function is more efficient than an open-coded loop over all nodes calling + +\family typewriter +HXdeque_del +\family default +. +\end_layout + +\begin_layout Standard +A generic variant is available with +\family typewriter +HXdeque_genocide2 +\family default +, which takes a pointer to an appropriate freeing function. + +\family typewriter +HXdeque_genocide +\family default + is thus equivalent to +\family typewriter +HXdeque_genocide2(dq, free) +\family default +. +\end_layout + +\begin_layout Standard +To convert a linked list to a +\family typewriter +NULL +\family default +-terminated array, +\family typewriter +HXdeque_to_vec +\family default + can be used. + If +\family typewriter +num +\family default + is not +\family typewriter +NULL +\family default +, the number of elements excluding the +\family typewriter +NULL +\family default + sentinel, is stored in +\family typewriter +*num +\family default +. +\end_layout + +\begin_layout Subsection +Addition and removal +\end_layout + +\begin_layout LyX-Code + +\series bold +struct +\series default + HXdeque_node +\series bold +* +\series default +HXdeque_push( +\series bold +struct +\series default + HXdeque +\series bold +* +\series default +dq, +\series bold +void * +\series default +ptr); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXdeque_push +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +struct +\series default + HXdeque_node +\series bold +* +\series default +HXdeque_unshift( +\series bold +struct +\series default + HXdeque +\series bold +* +\series default +dq, +\series bold +void * +\series default +ptr); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXdeque_unshift +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +void * +\series default +HXdeque_pop( +\series bold +struct +\series default + HXdeque +\series bold +* +\series default +dq); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXdeque_pop +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +void * +\series default +HXdeque_shift( +\series bold +struct +\series default + HXdeque +\series bold +* +\series default +dq); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXdeque_shift +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +struct +\series default + HXdeque +\series bold +* +\series default +HXdeque_move( +\series bold +struct +\series default + HXdeque_node +\series bold +* +\series default +target, +\begin_inset Newline newline +\end_inset + + +\series bold +struct +\series default + HXdeque_node +\series bold +* +\series default +node); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXdeque_move +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +void * +\series default +HXdeque_del( +\series bold +struct +\series default + HXdeque_node +\series bold +* +\series default +node); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXdeque_del +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard + +\family typewriter +HXdeque_\SpecialChar \- +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 + <stdio.h> +\begin_inset Newline newline +\end_inset + + +\series bold +#include +\series default + <stdlib.h> +\begin_inset Newline newline +\end_inset + + +\series bold +#include +\series default + <string.h> +\begin_inset Newline newline +\end_inset + + +\series bold +#include +\series default + <libHX/defs.h> +\begin_inset Newline newline +\end_inset + + +\series bold +#include +\series default + <libHX/deque.h> +\begin_inset Newline newline +\end_inset + + +\series bold +#include +\series default + <libHX/string.h> +\begin_inset Newline newline +\end_inset + + +\series bold +#include +\series default + <pwd.h> +\begin_inset Newline newline +\end_inset + + +\series bold + +\begin_inset Newline newline +\end_inset + +int +\series default + main( +\series bold +void +\series default +) +\begin_inset Newline newline +\end_inset + +{ +\series bold + +\begin_inset Newline newline +\end_inset + + +\series default + +\series bold +struct +\series default + HXdeque +\series bold +* +\series default +dq = HXdeque_init(); +\begin_inset Newline newline +\end_inset + + +\series bold +struct +\series default + passwd *pw; +\begin_inset Newline newline +\end_inset + + +\family typewriter +\series bold +unsigned int +\series default + elem; +\begin_inset Newline newline +\end_inset + + +\series bold +char ** +\series default +users; +\family default + +\begin_inset Newline newline +\end_inset + + +\begin_inset Newline newline +\end_inset + + setpwent(); +\begin_inset Newline newline +\end_inset + + +\series bold +while +\series default + ((pw = getpwent()) != NULL) +\begin_inset Newline newline +\end_inset + + HXdeque_push(dq, HX_strdup(pw->pw_name)); +\begin_inset Newline newline +\end_inset + + endpwent(); +\begin_inset Newline newline +\end_inset + + +\begin_inset Newline newline +\end_inset + + users = +\series bold +reinterpret_cast +\series default +( +\series bold +char ** +\series default +, HXdeque_to_vec(dq, &elem)); +\begin_inset Newline newline +\end_inset + + HXdeque_free(dq); +\begin_inset Newline newline +\end_inset + + +\begin_inset Newline newline +\end_inset + + qsort(users, elem, +\series bold +sizeof +\series default +(*users), +\series bold +static_cast +\series default +( +\series bold +void * +\series default +, strcmp)); +\begin_inset Newline newline +\end_inset + + return 0; +\begin_inset Newline newline +\end_inset + +} +\end_layout + +\begin_layout Plain Layout +\begin_inset Caption + +\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 + <libHX/list.h> +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +libHX/list.h +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +struct +\series default + HXlist_head { +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +struct HXlist_head +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +/* +\family roman +\series default +\shape italic +All fields considered private +\family default +\series bold +\shape default + */ +\series default + +\begin_inset Newline newline +\end_inset + +}; +\begin_inset Newline newline +\end_inset + + +\begin_inset Newline newline +\end_inset + +HXLIST_HEAD_INIT(name); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXLIST_HEAD_INIT +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + +HXLIST_HEAD(name); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXLIST_HEAD +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +void +\series default + HXlist_init( +\series bold +struct +\series default + HXlist_head +\series bold +* +\series default +list); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXlist_init +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +void +\series default + HXlist_add( +\series bold +struct +\series default + HXlist_head +\series bold +* +\series default +list, +\series bold +struct +\series default + HXlist_head +\series bold +* +\series default +elem); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXlist_add +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +void +\series default + HXlist_add_tail( +\series bold +struct +\series default + HXlist_head +\series bold +* +\series default +list, +\series bold +struct +\series default + HXlist_head +\series bold +* +\series default +elem); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXlist_add_tail +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +void +\series default + HXlist_del( +\series bold +struct +\series default + HXlist_head +\series bold +* +\series default +element); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXlist_del +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +bool +\series default + HXlist_empty( +\series bold +const struct +\series default + HXlist_head +\series bold +* +\series default +list); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXlist_empty +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Description + +\family typewriter +HXLIST_HEAD_INIT +\family default + This macro expands to the static initializer for a list head. +\end_layout + +\begin_layout Description + +\family typewriter +HXLIST_HEAD +\family default + This macro expands to the definition of a list head (i. +\begin_inset space \thinspace{} +\end_inset + +e. +\begin_inset space \space{} +\end_inset + + +\family typewriter +struct HXlist_head name = HXLIST_HEAD_INIT; +\family default +) +\end_layout + +\begin_layout Description + +\family typewriter +HXlist_init +\family default + Initializes the list head. + This function is generally used when the list head is on the heap where + the static initializer cannot be used. +\end_layout + +\begin_layout Description + +\family typewriter +HXlist_add +\family default + Adds +\family typewriter +elem +\family default + to the front of the list. +\end_layout + +\begin_layout Description + +\family typewriter +HXlist_add_tail +\family default + Adds +\family typewriter +elem +\family default + to the end of the list. +\end_layout + +\begin_layout Description + +\family typewriter +HXlist_del +\family default + Deletes the given element from the list. +\end_layout + +\begin_layout Description + +\family typewriter +HXlist_empty +\family default + Tests whether the list is empty. + Note: For clists, you could also use +\family typewriter +clist->items == 0 +\family default +. +\end_layout + +\begin_layout Subsection +Traversal +\end_layout + +\begin_layout Standard +Traversal is implemented using macros that expand to for() statements which + can syntactically be used like them, i. +\begin_inset space \thinspace{} +\end_inset + +e. +\begin_inset space \space{} +\end_inset + +curly braces may be omitted if only a single statement is in the body of + the loop. +\end_layout + +\begin_layout Standard +The +\family typewriter +head +\family default + parameter specifies the list head ( +\family typewriter +struct HXlist_head +\family default +), +\family typewriter +pos +\family default + specifies an iterator, also of type +\family typewriter +struct HXlist_head +\family default +. + Lists can either be traversed in forward direction, or, using the +\family typewriter +_rev +\family default + variants, in reverse direction. + The +\family typewriter +_safe +\family default + variants use a temporary +\family typewriter +n +\family default + to hold the next object in the list, which is needed when pos itself is + going to be inaccessible at the end of the block, through, for example, + freeing its encompassing object. +\end_layout + +\begin_layout LyX-Code +HXlist_for_each(pos, head) +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXlist_for_each +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + +HXlist_for_each_rev(pos, head) +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXlist_for_each_rev +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + +HXlist_for_each_safe(pos, n, head) +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXlist_for_each_safe +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + +HXlist_for_each_rev_safe(pos, n, head) +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXlist_for_each_rev_safe +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Description + +\family typewriter +HXlist_for_each +\family default + Forward iteration over the list heads. +\end_layout + +\begin_layout Description + +\family typewriter +HXlist_for_each_rev +\family default + Reverse iteration over the list heads. +\end_layout + +\begin_layout Description + +\family typewriter +HXlist_for_each_safe +\family default + Forward iteration over the list heads that is safe against freeing +\family typewriter +pos +\family default +. +\end_layout + +\begin_layout Description + +\family typewriter +HXlist_for_each_rev_safe +\family default + Reverse iteration over the list heads that is safe against freeing +\family typewriter +pos +\family default +. +\end_layout + +\begin_layout Standard +The +\family typewriter +_entry +\family default + variants use an iterator +\family typewriter +pos +\family default + of the type of the encompassing object (e. +\begin_inset space \thinspace{} +\end_inset + +g. +\begin_inset space \space{} +\end_inset + + +\family typewriter +struct item +\family default + in below's example), so that the manual +\family typewriter +HXlist_entry +\family default + invocation is not needed. + +\family typewriter +member +\family default + is the name of the list structure embedded into the item. +\end_layout + +\begin_layout LyX-Code +HXlist_for_each_entry(pos, head, member) +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXlist_for_each_entry +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + +HXlist_for_each_entry_rev(pos, head, member) +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXlist_for_each_entry_rev +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + +HXlist_for_each_entry_safe(pos, n, head, member) +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXlist_for_each_entry_safe +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Description + +\family typewriter +HXlist_for_each_entry +\family default + Forward iteration over the list elements. +\end_layout + +\begin_layout Description + +\family typewriter +HXlist_for_each_entry_rev +\family default + Reverse iteration over the list elements. +\end_layout + +\begin_layout Description + +\family typewriter +HXlist_for_each_entry_safe +\family default + Forward iteration over the list elements that is safe against freeing +\family typewriter +pos +\family default +. +\end_layout + +\begin_layout Subsection +Examples +\end_layout + +\begin_layout LyX-Code + +\series bold +struct +\series default + item { +\begin_inset Newline newline +\end_inset + + +\series bold +struct +\series default + HXlist_head anchor; +\begin_inset Newline newline +\end_inset + + +\series bold +char +\series default + name +\series bold +[ +\series default +32 +\series bold +] +\series default +; +\begin_inset Newline newline +\end_inset + +}; +\begin_inset Newline newline +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +struct +\series default + HXlist_head +\series bold +* +\series default +e; +\begin_inset Newline newline +\end_inset + + +\series bold +struct +\series default + item +\series bold +* +\series default +i, +\series bold +* +\series default +j; +\begin_inset Newline newline +\end_inset + +HXLIST_HEAD(list); +\begin_inset Newline newline +\end_inset + + +\begin_inset Newline newline +\end_inset + +i = malloc( +\series bold +sizeof +\series default +( +\series bold +* +\series default +i)); +\begin_inset Newline newline +\end_inset + +HXlist_init(&e->anchor); +\begin_inset Newline newline +\end_inset + +strcpy(i->name, "foo"); +\begin_inset Newline newline +\end_inset + +HXlist_add_tail(&list, &i->anchor); +\begin_inset Newline newline +\end_inset + + +\begin_inset Newline newline +\end_inset + +i = malloc( +\series bold +sizeof +\series default +( +\series bold +* +\series default +i)); +\begin_inset Newline newline +\end_inset + +HXlist_init(&e->anchor); +\begin_inset Newline newline +\end_inset + +strcpy(i->name, "bar"); +\begin_inset Newline newline +\end_inset + +HXlist_add_tail(&list, &i->anchor); +\begin_inset Newline newline +\end_inset + + +\begin_inset Newline newline +\end_inset + +HXlist_for_each(e, &list) { +\begin_inset Newline newline +\end_inset + + i = HXlist_entry(e, +\series bold +typeof +\series default +( +\series bold +* +\series default +i), anchor); +\begin_inset Newline newline +\end_inset + + printf("e=%p i=%p name=%s +\backslash +n", e, i, i->name); +\begin_inset Newline newline +\end_inset + +} +\begin_inset Newline newline +\end_inset + + +\begin_inset Newline newline +\end_inset + +HXlist_for_each_entry(i, &list, anchor) +\begin_inset Newline newline +\end_inset + + printf("i=%p name=%s +\backslash +n", i, i->name); +\begin_inset Newline newline +\end_inset + + +\begin_inset Newline newline +\end_inset + +HXlist_for_each_entry_rev(i, &list, anchor) +\begin_inset Newline newline +\end_inset + + printf("i=%p name=%s +\backslash +n", i, i->name); +\begin_inset Newline newline +\end_inset + + +\begin_inset Newline newline +\end_inset + +HXlist_for_each_entry_safe(i, j, &list, anchor) { +\begin_inset Newline newline +\end_inset + + printf("i=%p name=%s +\backslash +n", i, i->name); +\begin_inset Newline newline +\end_inset + + free(i); +\begin_inset Newline newline +\end_inset + +} +\end_layout + +\begin_layout Subsection +When to use HXdeque/HXlist +\end_layout + +\begin_layout Standard +The choice whether to use HXdeque or HXlist/HXclist depends on whether one + wants the list head handling on the developer or on the library. + Especially for +\begin_inset Quotes eld +\end_inset + +atomic +\begin_inset Quotes erd +\end_inset + + and +\begin_inset Quotes eld +\end_inset + +small +\begin_inset Quotes erd +\end_inset + + data, it might be easier to just let HXdeque do the management. + Compare the following two code examples to store strings: +\end_layout + +\begin_layout Standard +\begin_inset Float figure +placement H +wide false +sideways false +status open + +\begin_layout LyX-Code + +\series bold +int +\series default + main( +\family typewriter +\series bold +int +\series default + argc, +\series bold +const char ** +\series default +argv) +\begin_inset Newline newline +\end_inset + +{ +\begin_inset Newline newline +\end_inset + + +\series bold +struct +\series default + HXdeque +\series bold +* +\series default +dq = HXdeque_init(); +\begin_inset Newline newline +\end_inset + + +\series bold +while +\series default + (--argc) +\begin_inset Newline newline +\end_inset + + HXdeque_push(dq, ++argv); +\begin_inset Newline newline +\end_inset + + +\family default +\series bold +return +\family typewriter +\series default + 0; +\begin_inset Newline newline +\end_inset + +} +\end_layout + +\begin_layout Plain Layout +\begin_inset Caption + +\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 + <libHX/list.h> +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +libHX/list.h +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +struct +\series default + HXclist_head { +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +struct HXclist_head +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +/* +\family roman +\series default +\shape italic +public readonly: +\family default +\series bold +\shape default + */ +\series default + +\begin_inset Newline newline +\end_inset + + +\series bold +unsigned int +\series default + items; +\begin_inset Newline newline +\end_inset + + +\series bold +/* +\family roman +\series default +\shape italic +Undocumented fields are considered +\begin_inset Quotes eld +\end_inset + +private +\begin_inset Quotes erd +\end_inset + + +\family default +\series bold +\shape default + */ +\series default + +\begin_inset Newline newline +\end_inset + +}; +\begin_inset Newline newline +\end_inset + + +\begin_inset Newline newline +\end_inset + +HXCLIST_HEAD_INIT(name); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXCLIST_HEAD_INIT +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + +HXCLIST_HEAD(name); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXCLIST_HEAD +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +void +\series default + HXclist_init( +\series bold +struct +\series default + HXclist_head +\series bold +* +\series default +head); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXclist_init +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +void +\series default + HXclist_unshift( +\series bold +struct +\series default + HXclist_head +\series bold +* +\series default +head, +\series bold +struct +\series default + HXlist_head +\series bold +* +\series default +new_node); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXclist_unshift +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +void +\series default + HXclist_push( +\series bold +struct +\series default + HXclist_head +\series bold +* +\series default +head, +\series bold +struct +\series default + HXlist_head +\series bold +* +\series default +new_node); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXclist_push +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +type +\series default + HXclist_pop( +\series bold +struct +\series default + HXclist_head +\series bold +* +\series default +head, +\series bold +type +\series default +, member); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXclist_pop +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +type +\series default + HXclist_shift( +\series bold +struct +\series default + HXclist_head +\series bold +* +\series default +head, +\series bold +type +\series default +, member); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXclist_shift +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +void +\series default + HXclist_del( +\series bold +struct +\series default + HXclist_head +\series bold +* +\series default +head, +\series bold +struct +\series default +HXlist_chead +\series bold +* +\series default +node); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXclist_del +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Description + +\family typewriter +HXCLIST_HEAD_INIT +\family default + Macro that expands to the static initializer for a clist. +\end_layout + +\begin_layout Description + +\family typewriter +HXCLIST_HEAD +\family default + Macro that expands to the definition of a clist head, with initialization. +\end_layout + +\begin_layout Description + +\family typewriter +HXclist_init +\family default + Initializes a clist. + This function is generally used when the head has been allocated from the + heap. +\end_layout + +\begin_layout Description + +\family typewriter +HXclist_unshift +\family default + Adds the node to the front of the list. +\end_layout + +\begin_layout Description + +\family typewriter +HXclist_push +\family default + Adds the node to the end of the list. +\end_layout + +\begin_layout Description + +\family typewriter +HXclist_pop +\family default + Removes the last node in the list and returns it. +\end_layout + +\begin_layout Description + +\family typewriter +HXclist_shift +\family default + Removes the first node in the list and returns it. +\end_layout + +\begin_layout Description + +\family typewriter +HXclist_del +\family default + Deletes the node from the list. +\end_layout + +\begin_layout Standard +The list count in the clist head is updated whenever a modification is done + on the clist through these functions. +\end_layout + +\begin_layout Standard +\begin_inset Newpage clearpage +\end_inset + + +\end_layout + +\begin_layout Part +Strings and memory +\end_layout + +\begin_layout Section +String operations +\begin_inset CommandInset label +LatexCommand label +name "sec:strings" + +\end_inset + + +\end_layout + +\begin_layout Standard +Some string functions are merely present in libHX because they are otherwise + unportable; some are only in the C libraries of the BSDs, some only in + GNU libc. +\end_layout + +\begin_layout Subsection +Locating chars +\end_layout + +\begin_layout LyX-Code + +\series bold +#include +\series default + <libHX/string.h> +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +libHX/string.h +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +void * +\series default +HX_memmem( +\series bold +const void * +\series default +haystack, +\series bold +size_t +\series default + hsize, +\begin_inset Newline newline +\end_inset + + +\series bold +const void * +\series default +needle, +\series bold +size_t +\series default + nsize); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HX_memmem +\end_layout + +\end_inset + + +\series bold + +\begin_inset Newline newline +\end_inset + +char * +\series default +HX_strbchr( +\series bold +const char * +\series default +start, +\series bold +const char * +\series default +now, +\series bold +char +\series default + delimiter); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HX_strbchr +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +char * +\series default +HX_strchr2( +\series bold +const char * +\series default +s, +\series bold +const char * +\series default +accept); +\begin_inset Index idx +status open + +\begin_layout Plain Layout +HX_strchr2 +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +size_t +\series default + HX_strrcspn( +\series bold +const char * +\series default +s, +\series bold +const char * +\series default +reject); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HX_strccspn +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Description + +\family typewriter +HX_memmem +\family default + Analogous to +\family typewriter +strstr +\family default +(3), +\family typewriter +memmem +\family default + tries to locate the memory block pointed to by +\family typewriter +needle +\family default + (which is of length +\family typewriter +nsize +\family default +) in the block pointed to by +\family typewriter +haystack +\family default + (which is of size +\family typewriter +hsize +\family default +). + It returns a pointer to the first occurrence in +\family typewriter +haystack +\family default +, or +\family typewriter +NULL +\family default + when it was not found. +\end_layout + +\begin_layout Description + +\family typewriter +HX_strbchr +\family default + Searches the character specified by +\family typewriter +delimiter +\family default + in the range from +\family typewriter +now +\family default + to +\family typewriter +start +\family default +. + It works like +\family typewriter +strrchr +\family default +(3) +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +strrchr +\end_layout + +\end_inset + +, but begins at +\family typewriter +now +\family default + rather than the end of the string. +\end_layout + +\begin_layout Description + +\family typewriter +HX_strchr2 +\family default + This function searches the string +\family typewriter +s +\family default + for any set of bytes that are not specified in the second argument, +\family typewriter +n +\family default +. + In this regard, the function is the opposite to +\family typewriter +strpbrk +\family default +(3) +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +strpbrk +\end_layout + +\end_inset + +. +\end_layout + +\begin_layout Description + +\family typewriter +HX_strrcspn +\family default + Works like +\family typewriter +strcspn +\family default +(3) +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +\size normal +\color none +strcspn +\end_layout + +\end_inset + +, but processes the string from end to start. +\end_layout + +\begin_layout Subsection +Extraction +\end_layout + +\begin_layout LyX-Code + +\series bold +#include +\series default + <libHX/string.h> +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +libHX/string.h +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +char * +\series default +HX_basename( +\series bold +const char * +\series default +s); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HX_basename +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +char * +\series default +HX_basename_exact( +\series bold +const char * +\series default +s); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HX_basename_exact +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +char * +\series default +HX_dirname( +\series bold +const char * +\series default +s); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +\size normal +\color none +HX_dirname +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +char * +\series default +HX_strmid( +\series bold +const char * +\series default +s, +\series bold +long +\series default + offset, +\series bold +long +\series default + length); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +\size normal +\color none +HX_strmid +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Description + +\family typewriter +HX_basename +\family default + Returns a pointer to the basename portion of the supplied path +\family typewriter +s +\family default +. + The result of this function is never +\family typewriter +NULL +\family default +, and must never be freed either. + Trailing slashes are not stripped, to avoid having to do an allocation. + In other words, +\family typewriter +basename("/mnt/") +\family default + will return +\begin_inset Quotes eld +\end_inset + + +\family typewriter +mnt/ +\family default + +\begin_inset Quotes erd +\end_inset + +. + If you need to have the slashes stripped, use +\family typewriter +HX_basename_exact +\family default +. + A possible use for this function is, for example, to derive a logging prefix + from +\family typewriter +argv[0] +\family default +. +\end_layout + +\begin_layout LyX-Code + +\series bold +int +\series default + main( +\series bold +int +\series default + argc, +\series bold +const char ** +\series default +argv) +\begin_inset Newline newline +\end_inset + +{ +\begin_inset Newline newline +\end_inset + + +\series bold +if +\series default + (foo()) +\end_layout + +\begin_layout LyX-Code + fprintf(stderr, "%s: Special condition occurred. +\backslash +n", +\begin_inset Newline newline +\end_inset + + HX_basename(argv[0])); +\begin_inset Newline newline +\end_inset + + +\series bold +return +\series default + 0; +\begin_inset Newline newline +\end_inset + +} +\end_layout + +\begin_layout Description + +\family typewriter +HX_basename_exact +\family default + The accurate and safe version of +\family typewriter +HX_basename +\family default + that deals with trailing slashes correctly and produces the same result + as +\family typewriter +dirname +\family default +(3). + It returns a pointer to a newly-allocated string that must be freed when + done using. + +\family typewriter +NULL +\family default + may be returned in case of an allocation error. +\end_layout + +\begin_layout Description + +\family typewriter +HX_dirname +\family default + Returns a pointer to a new string that contains the directory name portion + (everything except basename). + When done using the string, it must be freed to avoid memory leaks. +\end_layout + +\begin_layout Description + +\family typewriter +HX_strmid +\family default + Extract a substring of +\family typewriter +length +\family default + characters from +\family typewriter +s +\family default +, beginning at +\family typewriter +offset +\family default +. + If +\family typewriter +offset +\family default + is negative, counting beings from the end of the string; +\begin_inset Formula $-1$ +\end_inset + + is the last character (not the +\family typewriter +' +\backslash +0' +\family default + byte). + If +\family typewriter +length +\family default + is negative, it will leave out that many characters off the end. + The function returns a pointer to a new string, and the user has to free + it. +\end_layout + +\begin_layout Subsection +In-place transformations +\end_layout + +\begin_layout LyX-Code + +\series bold +#include +\series default + <libHX/string.h> +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +libHX/string.h +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +char * +\series default +HX_chomp( +\series bold +char * +\series default +s); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +\size normal +\color none +HX_chomp +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +size_t +\series default + HX_strltrim( +\series bold +char * +\series default +s); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +\size normal +\color none +HX_strltrim +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +char * +\series default +HX_stpltrim( +\series bold +const char * +\series default +s); +\begin_inset Index idx +status open + +\begin_layout Plain Layout +HX_stpltrim +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +char * +\series default +HX_strlower( +\series bold +char * +\series default +s); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +\size normal +\color none +HX_strlower +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +char * +\series default +HX_strrev( +\series bold +char * +\series default +s); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +\size normal +\color none +HX_strrev +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +size_t +\series default + HX_strrtrim( +\series bold +char * +\series default +s); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +\size normal +\color none +HX_strrtrim +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +char * +\series default +HX_strupper( +\series bold +char * +\series default +s); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +\size normal +\color none +HX_strupper +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Description + +\family typewriter +HX_chomp +\family default + Removes the characters +\family typewriter +' +\backslash +r' +\family default + and +\family typewriter +' +\backslash +n' +\family default + from the right edge of the string. + Returns the original argument. +\end_layout + +\begin_layout Description + +\family typewriter +HX_strltrim +\family default + Trim all whitespace (characters on which +\family typewriter +isspace +\family default +(3) return true) on the left edge of the string. + Returns the number of characters that were stripped. +\end_layout + +\begin_layout Description + +\family typewriter +HX_stpltrim +\family default + Returns a pointer to the first non-whitespace character in +\family typewriter +s +\family default +. +\end_layout + +\begin_layout Description + +\family typewriter +HX_strlower +\family default + Transforms all characters in the string +\family typewriter +s +\family default + into lowercase using +\family typewriter +tolower +\family default +(3). + Returns the original argument. +\end_layout + +\begin_layout Description + +\family typewriter +HX_strrev +\family default + Reverse the string in-place. + Returns the original argument. +\end_layout + +\begin_layout Description + +\family typewriter +HX_strrtrim +\family default + Trim all whitespace on the right edge of the string. + Returns the number of characters that were stripped. +\end_layout + +\begin_layout Description + +\family typewriter +HX_strupper +\family default + Transforms all characters in the string +\family typewriter +s +\family default + into uppercase using +\family typewriter +toupper +\family default +(3). + Returns the original argument. +\end_layout + +\begin_layout Subsection +Out-of-place quoting transforms +\end_layout + +\begin_layout LyX-Code + +\series bold +#include +\series default + <libHX/string.h> +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +libHX/string.h +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +char * +\series default +HX_strquote( +\series bold +const char * +\series default +s, +\series bold +unsigned int +\series default + type, +\series bold +char ** +\series default +free_me); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HX_strquote +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard + +\family typewriter +HX_strquote +\family default + will escape metacharacters in a string according to +\family typewriter +type +\family default +, and returns the escaped result. +\end_layout + +\begin_layout Standard +Possible values for +\family typewriter +type +\family default +: +\end_layout + +\begin_layout Description + +\family typewriter +HXQUOTE_SQUOTE +\family default + +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXQUOTE_SQUOTE +\end_layout + +\end_inset + + Escape all single quotes and backslashes in a string with a backslash. + ( +\begin_inset Quotes eld +\end_inset + +Ol' +\backslash +Backslash +\begin_inset Quotes erd +\end_inset + + +\begin_inset Formula $\rightarrow$ +\end_inset + + +\begin_inset Quotes eld +\end_inset + +Ol +\backslash +' +\backslash + +\backslash +Backslash +\begin_inset Quotes erd +\end_inset + +) +\end_layout + +\begin_layout Description + +\family typewriter +HXQUOTE_DQUOTE +\family default + +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXQUOTE_DQUOTE +\end_layout + +\end_inset + + Escape all double quotes and backslahes in a string with the backslash + method. + ( +\begin_inset Quotes eld +\end_inset + +Ol +\begin_inset Quotes erd +\end_inset + + +\backslash +Backslash +\begin_inset Quotes erd +\end_inset + + +\begin_inset Formula $\rightarrow$ +\end_inset + + +\begin_inset Quotes eld +\end_inset + +Ol +\backslash + +\begin_inset Quotes erd +\end_inset + + +\backslash + +\backslash +Backslash +\begin_inset Quotes erd +\end_inset + +) +\end_layout + +\begin_layout Description + +\family typewriter +HXQUOTE_HTML +\family default + +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXQUOTE_HTML +\end_layout + +\end_inset + + Escape ' +\family typewriter +< +\family default +', ' +\family typewriter +> +\family default +', ' +\family typewriter +& +\family default +' and ' +\family typewriter +" +\family default +' by their respective HTML entities +\family typewriter +< +\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("<head>", HXQUOTE_HTML, NULL); +\begin_inset Newline newline +\end_inset + +printf("%s +\backslash +n", s); +\begin_inset Newline newline +\end_inset + +free(s); +\end_layout + +\begin_layout Standard +If +\family typewriter +free_me +\family default + is not +\family typewriter +NULL +\family default + however, the function will put the pointer to the memory area into +\family typewriter +*free_me +\family default +, if the string needed quoting. + The program then has to free that after it is done with the quoted result: +\end_layout + +\begin_layout LyX-Code + +\series bold +char * +\series default +tmp = NULL; +\begin_inset Newline newline +\end_inset + + +\series bold +char * +\series default +s = HX_strquote("head", HXQUOTE_HTML, &tmp); +\begin_inset Newline newline +\end_inset + +printf("%s +\backslash +n", s); +\begin_inset Newline newline +\end_inset + +free(tmp); +\end_layout + +\begin_layout Standard + +\family typewriter +tmp +\family default + could be +\family typewriter +NULL +\family default +, and since +\family typewriter +free(NULL) +\family default + is not an error, this is perfectly valid. + Furthermore, if +\family typewriter +*free_me +\family default + is not +\family typewriter +NULL +\family default + by the time +\family typewriter +HX_strquote +\family default + is called, the function will free it. + This makes it possible to call +\family typewriter +HX_strquote +\family default + in succession without +\family typewriter +free +\family default +s in between: +\end_layout + +\begin_layout LyX-Code + +\series bold +char * +\series default +tmp = NULL; +\begin_inset Newline newline +\end_inset + +printf("%s +\backslash +n", HX_strquote("<html>", HXQUOTE_HTML, &tmp)); +\begin_inset Newline newline +\end_inset + +printf("%s +\backslash +n", HX_strquote("<head>", HXQUOTE_HTML, &tmp)); +\begin_inset Newline newline +\end_inset + +free(tmp); +\end_layout + +\begin_layout Subsection +Tokenizing +\end_layout + +\begin_layout LyX-Code + +\series bold +#include +\series default + <libHX/string.h> +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +libHX/string.h +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +char ** +\series default +HX_split( +\series bold +const char * +\series default +s, +\series bold +const char * +\series default +delimiters, +\begin_inset Newline newline +\end_inset + + +\series bold +size_t * +\series default +fields, +\series bold +int +\series default + max); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +\size normal +\color none +HX_split +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +char ** +\series default +HX_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 + <libHX/string.h> +\begin_inset Index idx +status open + +\begin_layout Plain Layout +libHX/string.h +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +char * +\series default +HX_strlcat( +\series bold +char * +\series default +dest, +\series bold +const char * +\series default +src, +\series bold +size_t +\series default + length); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +\size normal +\color none +HX_strlcat +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +char * +\series default +HX_strlcpy( +\series bold +char * +\series default +dest, +\series bold +const char * +\series default +src, +\series bold +size_t +\series default + length); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +\size normal +\color none +HX_strlcpy +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +char * +\series default +HX_strlncat( +\series bold +char * +\series default +dest, +\series bold +const char * +\series default +src, +\series bold +size_t +\series default + dlen, +\series bold +size_t +\series default + slen); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +\size normal +\color none +HX_strlncat +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +size_t +\series default + HX_strnlen( +\series bold +const char * +\series default +src, +\series bold +size_t +\series default + max); +\begin_inset Index idx +status open + +\begin_layout Plain Layout +HX_strnlen +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard + +\family typewriter +HX_strlcat +\family default + and +\family typewriter +HX_strlcpy +\family default + provide implementations of the BSD-originating +\family typewriter +strlcat +\family default +(3) +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +strlcat +\end_layout + +\end_inset + + and +\family typewriter +strlcpy +\family default +(3) +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +strlcpy +\end_layout + +\end_inset + +. + +\family typewriter +strlcat +\family default + and +\family typewriter +strlcpy +\family default + are less error-prone variants for +\family typewriter +strncat +\family default + and +\family typewriter +strncpy +\family default + as they always take the length of the entire buffer specified by +\family typewriter +dest +\family default +, instead of just the length that is to be written. + The functions guarantee that the buffer is +\family typewriter +' +\backslash +0' +\family default +-terminated. +\end_layout + +\begin_layout Standard + +\family typewriter +HX_strnlen +\family default + will return the length of the input string or the upper bound given by + +\family typewriter +max +\family default +, whichever is less. + It will not attempt to access more than this many bytes in the input buffer. +\end_layout + +\begin_layout Subsection +Allocation-related +\end_layout + +\begin_layout LyX-Code + +\series bold +#include +\series default + <libHX/string.h> +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +libHX/string.h +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +void * +\series default +HX_memdup( +\series bold +const void * +\series default +ptr, +\series bold +size_t +\series default + length); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +\size normal +\color none +HX_memdup +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +char * +\series default +HX_strdup( +\series bold +const char * +\series default +str); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +\size normal +\color none +HX_strdup +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +char * +\series default +HX_strndup( +\series bold +const char * +\series default +str, +\series bold +size_t +\series default + max); +\begin_inset Index idx +status open + +\begin_layout Plain Layout +HX_strndup +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold + +\begin_inset Note Greyedout +status open + +\begin_layout Plain Layout + +\family typewriter +\series bold +char * +\series default +HX_strclone( +\series bold +char ** +\series default +pa, +\series bold +const char * +\series default +pb); +\family default + +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +\size normal +\color none +HX_strclone +\end_layout + +\end_inset + + +\end_layout + +\end_inset + + +\series default + +\begin_inset Newline newline +\end_inset + + +\series bold + +\begin_inset Newline newline +\end_inset + +#ifdef +\series default + __cplusplus +\begin_inset Newline newline +\end_inset + + +\series bold +template<typename type> type +\series default + HX_memdup( +\series bold +const void * +\series default +ptr, +\series bold +size_t +\series default + length); +\begin_inset Newline newline +\end_inset + + +\series bold +#endif +\end_layout + +\begin_layout Description + +\family typewriter +HX_memdup +\family default + Duplicates +\family typewriter +length +\family default + bytes from the memory area pointed to by +\family typewriter +ptr +\family default + and returns a pointer to the new memory block. + +\family typewriter +ptr +\family default + may not be +\family typewriter +NULL +\family default +. +\end_layout + +\begin_layout Description + +\family typewriter +HX_strdup +\family default + Duplicates the string. + The function is equivalent to +\family typewriter +strdup +\family default +, but the latter may not be available on all platforms. + +\family typewriter +str +\family default + may be +\family typewriter +NULL +\family default +, in which case +\family typewriter +NULL +\family default + is also returned. +\end_layout + +\begin_layout Description + +\family typewriter +HX_strndup +\family default + Duplicates the input string, but copies at most +\family typewriter +max +\family default + characters. + (The resulting string will be NUL-terminated of course.) +\family typewriter +str +\family default + may not be +\family typewriter +NULL +\family default +. +\end_layout + +\begin_layout Description + +\family typewriter +HX_strclone +\family default + Copies the string pointed to by +\family typewriter +pb +\family default + into +\family typewriter +*pa +\family default +. + If +\family typewriter +*pa +\family default + was not +\family typewriter +NULL +\family default + by the time +\family typewriter +HX_strclone +\family default + was called, the string is freed before a new one is allocated. + The function returns +\family typewriter +NULL +\family default + and sets +\family typewriter +errno +\family default + to +\family typewriter +EINVAL +\family default + if +\family typewriter +pb +\family default + is +\family typewriter +NULL +\family default + (this way it can be freed), or, if +\family typewriter +malloc +\family default + fails, returns +\family typewriter +NULL +\family default + and leaves +\family typewriter +errno +\family default + at what +\family typewriter +malloc +\family default + set it to. +\begin_inset Newline newline +\end_inset + +The use of this function is deprecated, albeit no replacement is proposed. +\end_layout + +\begin_layout Subsection +Examples +\end_layout + +\begin_layout Subsubsection +Using HX_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 + <stdio.h> +\begin_inset Newline newline +\end_inset + + +\series bold +#include +\series default + <libHX/string.h> +\begin_inset Newline newline +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +char * +\series default +field[8]; +\begin_inset Newline newline +\end_inset + +hxmc_t +\series bold +* +\series default +line = NULL; +\begin_inset Newline newline +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +while +\series default + (HX_getl(&line, fp) != NULL) { +\begin_inset Newline newline +\end_inset + + +\series bold +if +\series default + (HX_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 + <errno.h> +\begin_inset Newline newline +\end_inset + + +\series bold +#include +\series default + <stdio.h> +\begin_inset Newline newline +\end_inset + + +\series bold +#include +\series default + <libHX/string.h> +\begin_inset Newline newline +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +while +\series default + (HX_getl(&line, fp) != NULL) { +\begin_inset Newline newline +\end_inset + + +\series bold +char ** +\series default +field = HX_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 + <errno.h> +\begin_inset Newline newline +\end_inset + + +\series bold +#include +\series default + <stdio.h> +\begin_inset Newline newline +\end_inset + + +\series bold +#include +\series default + <libHX/string.h> +\begin_inset Newline newline +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +while +\series default + (HX_getl(&line, fp) != NULL) { +\begin_inset Newline newline +\end_inset + + +\series bold +char ** +\series default +field = HX_split(line, ":", NULL, 0); +\begin_inset Newline newline +\end_inset + + +\series bold +if +\series default + (field == NULL) { +\begin_inset Newline newline +\end_inset + + fprintf(stderr, "Badness. + %s +\backslash +n", strerror(errno)); +\begin_inset Newline newline +\end_inset + + break; +\begin_inset Newline newline +\end_inset + + } +\begin_inset Newline newline +\end_inset + + printf("Username: %s +\backslash +n", field[0]); +\begin_inset Newline newline +\end_inset + + +\series bold +/* +\family roman +\series default +\shape italic +Suppose +\begin_inset Quotes eld +\end_inset + +callme +\begin_inset Quotes erd +\end_inset + + needs the original string +\family default +\series bold +\shape default + */ +\series default + +\begin_inset Newline newline +\end_inset + + callme(line); +\begin_inset Newline newline +\end_inset + + HX_zvecfree(field); +\begin_inset Newline newline +\end_inset + +} +\end_layout + +\begin_layout Subsubsection +Using HX_strsep +\end_layout + +\begin_layout Standard + +\family typewriter +HX_strsep +\family default + provides for thread- and reentrant-safe tokenizing a string where strtok + from the C standard would otherwise fail. +\end_layout + +\begin_layout LyX-Code + +\series bold +#include +\series default + <stdio.h> +\begin_inset Newline newline +\end_inset + + +\series bold +#include +\series default + <libHX/string.h> +\begin_inset Newline newline +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +char +\series default + line +\series bold +[] +\series default + = "root:x:0:0:root:/root:/bin/bash"; +\begin_inset Newline newline +\end_inset + + +\series bold +char * +\series default +wp, +\series bold +* +\series default +p; +\begin_inset Newline newline +\end_inset + + +\begin_inset Newline newline +\end_inset + +wp = line; +\begin_inset Newline newline +\end_inset + + +\series bold +while +\series default + ((p = HX_strsep(&wp, ":")) != NULL) +\begin_inset Newline newline +\end_inset + + printf("%s +\backslash +n", p) +\end_layout + +\begin_layout Standard +\begin_inset Newpage clearpage +\end_inset + + +\end_layout + +\begin_layout Section +Memory containers +\begin_inset CommandInset label +LatexCommand label +name "sec:mc" + +\end_inset + + +\end_layout + +\begin_layout Standard +The HXmc series of functions provide scripting-like semantics for strings, + especially automatically resizing the buffer on demand. + They can also be used to store a binary block of data together with its + length. + (Hence the name: mc = memory container.) +\end_layout + +\begin_layout Standard +The benefit of using the HXmc functions is that one does not have to meticulousl +y watch buffer and string sizes anymore. +\end_layout + +\begin_layout Standard +\begin_inset Float figure +placement H +wide false +sideways false +status open + +\begin_layout Paragraph +/* Step +\begin_inset space ~ +\end_inset + +1 */ +\end_layout + +\begin_layout LyX-Code + +\series bold +char +\series default + buf +\series bold +[ +\family roman +\series default +\shape italic +whatever was believed to be long enough +\family default +\series bold +\shape default +] +\series default + = "helloworld"; +\end_layout + +\begin_layout LyX-Code + +\series bold +if +\series default + (strlen(buf) + strlen(".txt") < +\series bold +sizeof +\series default +(buf)) +\begin_inset Newline newline +\end_inset + + strcat(s, ".txt"); +\end_layout + +\begin_layout Paragraph +/* Step +\begin_inset space ~ +\end_inset + +2 */ +\end_layout + +\begin_layout LyX-Code + +\series bold +char +\series default + buf +\series bold +[ +\family roman +\series default +\shape italic +long_enough +\family default +\series bold +\shape default +] +\series default + = "helloworld"; +\end_layout + +\begin_layout LyX-Code +strlcat(s, ".txt", +\series bold +sizeof +\series default +(buf)); +\end_layout + +\begin_layout Paragraph +/* Step +\begin_inset space ~ +\end_inset + +3 */ +\end_layout + +\begin_layout LyX-Code +hxmc_t +\series bold +* +\series default +buf = HXmc_strinit("helloworld"); +\begin_inset Newline newline +\end_inset + +HXmc_strcat(&s, ".txt"); +\end_layout + +\begin_layout Plain Layout +\begin_inset Caption + +\begin_layout Plain Layout +Improvement of string safety over time +\end_layout + +\end_inset + + +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +This makes it quite similar to the string operations (and append seems to + be the most commonly used one to me) supported in scripting languages that + also do without a size argument. + The essential part of such memory containers is that their internal (hidden) + metadata structure contains the length of the memory block in the container. + For binary data this may be the norm, but for C-style strings, the stored + and auto-updated length field serves as an accelerator cache. + For more details, see +\family typewriter +HXmc_length +\family default +. +\end_layout + +\begin_layout Standard +Of course, the automatic management of memory comes with a bit of overhead + as the string expands beyond its preallocated region. + Such may be mitigated by doing explicit (re)sizing. +\end_layout + +\begin_layout Subsection +Structural overview +\end_layout + +\begin_layout Standard +HXmc functions do not actually return a pointer to the memory container + (e. +\begin_inset space \thinspace{} +\end_inset + +g. +\begin_inset space \space{} +\end_inset + + +\family typewriter +struct +\family default +) itself, but a pointer to the data block. + Conversely, input parameters to HXmc functions will be the data block pointer. + It is of type +\family typewriter +hxmc_t +\begin_inset space ~ +\end_inset + +* +\family default +, which is typedef'ed to +\family typewriter +char +\begin_inset space ~ +\end_inset + +* +\family default + and inherits all properties and privileges of +\family typewriter +char +\begin_inset space ~ +\end_inset + +* +\family default +. + Pointer arithmetic is thus supported. + It also means you can just pass it to functions that take a +\family typewriter +char +\begin_inset space ~ +\end_inset + +* +\family default + without having to do a member access like +\family typewriter +s.c_str +\family default +. + The drawback is that many functions operating on the memory container need + a +\family typewriter +hxmc_t +\begin_inset space ~ +\end_inset + +** +\family default + (a level-two indirection), because not only does the memory block move, + but also the memory container itself. + This is due to the implementation of the container metadata which immediately + and always precedes the writable memory block. +\end_layout + +\begin_layout Standard +HXmc ensures that the data block is terminated by a NUL ( +\family typewriter +' +\backslash +0' +\family default +) byte (unless you trash it), so you do not have to, and of course, to be + on the safe side. + But, the automatic NUL byte is not part of the region allocated by the + user. + That is, when one uses the classic approach with +\family typewriter +malloc(4096) +\family default +, the user will have control of 4096 bytes and has to stuff the NUL byte + in there somehow on his own; for strings this means the maximum string + length is 4095. + Requesting space for a 4096-byte sized HXmc container gives you the possibility + to use all 4096 bytes for the string, because HXmc provides a NUL byte. +\end_layout + +\begin_layout Standard +By the way, +\family typewriter +hxmc_t +\family default + is the +\shape italic +only +\shape default + typedef in this entire library, to distinguish it from regular +\family typewriter +char +\begin_inset space ~ +\end_inset + +* +\family default + that does not have a backing memory cointainer. +\end_layout + +\begin_layout Subsection +Constructors, destructors +\end_layout + +\begin_layout LyX-Code + +\series bold +#include +\series default + <libHX/string.h> +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +libHX/string.h +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\begin_inset Newline newline +\end_inset + +hxmc_t +\series bold +* +\series default +HXmc_strinit( +\series bold +const char * +\series default +s); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXmc_strinit +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + +hxmc_t +\series bold +* +\series default +HXmc_meminit( +\series bold +const void * +\series default +ptr, +\series bold +size_t +\series default + size); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXmc_meminit +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Description + +\family typewriter +HXmc_strinit +\family default + Creates a new hxmc_t object from the supplied string and returns it. +\end_layout + +\begin_layout Description + +\family typewriter +HXmc_meminit +\family default + Creates a new hxmc_t object from the supplied memory buffer of the given + size and returns it. + +\family typewriter +HXmc_meminit(NULL, len) +\family default + may be used to obtain an empty container with a preallocated region of + +\family typewriter +len +\family default + bytes (zero is accepted for +\family typewriter +len +\family default +). +\end_layout + +\begin_layout LyX-Code + +\series bold +void +\series default + HXmc_free(hxmc_t +\series bold +* +\series default +s); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXmc_free +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +void +\series default + HXmc_zvecfree(hxmc_t +\series bold +** +\series default +s); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXmc_zvecfree +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Description + +\family typewriter +HXmc_free +\family default + Frees the hxmc object. +\end_layout + +\begin_layout Description + +\family typewriter +HXmc_zvecfree +\family default + Frees all hxmc objects in the NULL-terminated array, and finally frees + the array itself, similar to +\family typewriter +HX_zvecfree +\family default +. +\end_layout + +\begin_layout Subsection +Data manipulation +\end_layout + +\begin_layout Subsubsection +Binary-based +\end_layout + +\begin_layout LyX-Code +hxmc_t +\series bold +* +\series default +HXmc_trunc(hxmc_t +\series bold +** +\series default +mc, +\series bold +size_t +\series default + len); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +\size normal +\color none +HXmc_trunc +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + +hxmc_t +\series bold +* +\series default +HXmc_setlen(hxmc_t +\series bold +** +\series default +mc, +\series bold +size_t +\series default + len); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +\size normal +\color none +HXmc_setlen +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + +hxmc_t +\series bold +* +\series default +HXmc_memcpy(hxmc_t +\series bold +** +\series default +mc, +\series bold +const void * +\series default +ptr, +\series bold +size_t +\series default + len); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +\size normal +\color none +HXmc_memcpy +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + +hxmc_t +\series bold +* +\series default +HXmc_memcat(hxmc_t +\series bold +** +\series default +mc, +\series bold +const void * +\series default +ptr, +\series bold +size_t +\series default + len); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +\size normal +\color none +HXmc_memcat +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + +hxmc_t +\series bold +* +\series default +HXmc_mempcat(hxmc_t +\series bold +** +\series default +mc, +\series bold +const void * +\series default +ptr, +\series bold +size_t +\series default + len); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +\size normal +\color none +HXmc_mempcat +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + +hxmc_t +\series bold +* +\series default +HXmc_memins(hxmc_t +\series bold +** +\series default +mc, +\series bold +size_t +\series default + pos, +\series bold +const void * +\series default +ptr, +\series bold +size_t +\series default + len); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HX_memins +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + +hxmc_t +\series bold +* +\series default +HXmc_memdel(hxmc_t +\series bold +** +\series default +mc, +\series bold +size_t +\series default + pos, +\series bold +size_t +\series default + len); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HX_memdel +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +When +\family typewriter +ptr +\family default + is +\family typewriter +NULL +\family default +, each call behaves as if +\family typewriter +len +\family default + would be zero. + Specifically, no undefined behavior will result of the use of +\family typewriter +NULL +\family default +. +\end_layout + +\begin_layout Description + +\family typewriter +HXmc_trunc +\family default + Truncates the container's data to +\family typewriter +len +\family default + size. + If +\family typewriter +len +\family default + is greater than the current data size of the container, the length is in + fact +\shape italic +not +\shape default + updated, but a reallocation may be triggered, which can be used to do explicit + allocation. +\end_layout + +\begin_layout Description + +\family typewriter +HXmc_setlen +\family default + Set the data length, doing a reallocation of the memory container if needed. + The newly available bytes are uninitialized. + Make use of this function when letting 3rd party functions write to the + buffer, but it should not be used with +\family typewriter +HXmc_str* +\family default +(), +\end_layout + +\begin_layout Description + +\family typewriter +HXmc_memcpy +\family default + Truncates the container's data and copies +\family typewriter +len +\family default + bytes from the memory area pointed to by +\family typewriter +ptr +\family default + to the container. +\end_layout + +\begin_layout Description + +\family typewriter +HXmc_memcat +\family default + Concatenates (appends) +\family typewriter +len +\family default + bytes from the memory area pointed to by +\family typewriter +ptr +\family default + to the container's data. +\end_layout + +\begin_layout Description + +\family typewriter +HXmc_mempcat +\family default + Prepends +\family typewriter +len +\family default + bytes from the memory area pointed to by +\family typewriter +ptr +\family default + to the container's data. +\end_layout + +\begin_layout Description + +\family typewriter +HXmc_memins +\family default + Prepends +\family typewriter +len +\family default + bytes from the memory area pointed to by +\family typewriter +ptr +\family default + to the +\family typewriter +pos +\family default +'th byte of the container's data. +\end_layout + +\begin_layout Description + +\family typewriter +HXmc_memdel +\family default + Deletes +\family typewriter +len +\family default + bytes from the container beginning at position +\family typewriter +pos +\family default +. +\end_layout + +\begin_layout Standard +In case of a memory allocation failure, the +\family typewriter +HXmc_* +\family default + functions will return +\family typewriter +NULL +\family default +. +\end_layout + +\begin_layout Subsubsection +String-based +\end_layout + +\begin_layout Standard +The string-based functions correspond to their binary-based equivalents + with a +\family typewriter +len +\family default + argument of +\family typewriter +strlen(s) +\family default +. +\end_layout + +\begin_layout LyX-Code +hxmc_t +\series bold +* +\series default +HXmc_strcpy(hxmc_t +\series bold +** +\series default +mc, +\series bold +const char * +\series default +s); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +\size normal +\color none +HXmc_strcpy +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + +hxmc_t +\series bold +* +\series default +HXmc_strcat(hxmc_t +\series bold +** +\series default +mc, +\series bold +const char * +\series default +s); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +\size normal +\color none +HXmc_strcat +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + +hxmc_t +\series bold +* +\series default +HXmc_strpcat(hxmc_t +\series bold +** +\series default +mc, +\series bold +const char * +\series default +s); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXmc_strpcat +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + +hxmc_t +\series bold +* +\series default +HXmc_strins(hxmc_t +\series bold +** +\series default +mc, +\series bold +size_t +\series default + pos, +\series bold +const char * +\series default +s); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +\size normal +\color none +HXmc_strins +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Description + +\family typewriter +HXmc_strcpy +\family default + Copies the string pointed to by +\family typewriter +s +\family default + into the memory container given by +\family typewriter +mc +\family default +. + If +\family typewriter +mc +\family default + is +\family typewriter +NULL +\family default +, the memory container will be deallocated, that is, +\family typewriter +*mc +\family default + becomes +\family typewriter +NULL +\family default +. +\end_layout + +\begin_layout Subsubsection +From auxiliary sources +\end_layout + +\begin_layout LyX-Code +hxmc_t +\series bold +* +\series default +HX_getl(hxmc_t +\series bold +** +\series default +mc, FILE +\series bold +* +\series default +fp); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HX_getl +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Description + +\family typewriter +HX_getl +\family default + Read the next line from +\family typewriter +fp +\family default + and store the result in the container. + Returns +\family typewriter +NULL +\family default + on error, or when end of file occurs while no characters have been read. +\end_layout + +\begin_layout Subsection +Container properties +\end_layout + +\begin_layout LyX-Code + +\series bold +size_t +\series default + HXmc_length( +\series bold +const +\series default + hxmc_t +\series bold +** +\series default +mc); +\end_layout + +\begin_layout Description + +\family typewriter +HXmc_length +\family default + Returns the length of the memory container. + This is not always equal to the actual string length. + For example, if +\family typewriter +HX_chomp +\family default + was used on an MC-backed string, +\family typewriter +strlen +\family default + will return less than +\family typewriter +HXmc_length +\family default + if newline control characters ( +\family typewriter +' +\backslash +r' +\family default + and +\family typewriter +' +\backslash +n' +\family default +) were removed. +\end_layout + +\begin_layout Standard +\begin_inset Newpage clearpage +\end_inset + + +\end_layout + +\begin_layout Section +Format templates +\begin_inset CommandInset label +LatexCommand label +name "sec:format" + +\end_inset + + +\end_layout + +\begin_layout Standard +HXfmt is a small template system for by-name variable expansion. + It can be used to substitute placeholders in format strings supplied by + the user by appropriate expanded values defined by the program. + Such can be used to allow for flexible configuration files that define + key-value mappings such as +\end_layout + +\begin_layout LyX-Code +detect_peer = ping6 -c1 %(ADDR) +\begin_inset Newline newline +\end_inset + +#detect_peer = nmap -sP %(ADDR) | grep -Eq "appears to be up" +\end_layout + +\begin_layout Standard +Consider for example a monitoring daemon that allows the administrator to + specify a program of his choice with which to detect whether a peer is + alive or not. + The user can choose any program that is desired, but evidently needs to + pass the address to be tested to the program. + This is where the daemon will do a substitution of the string +\begin_inset Quotes eld +\end_inset + + +\family typewriter +ping -c1 %(ADDR) +\family default + +\begin_inset Quotes erd +\end_inset + + it read from the config file, and put the actual address in it before finally + executing the command. +\end_layout + +\begin_layout Standard +\begin_inset Float figure +placement H +wide false +sideways false +status open + +\begin_layout LyX-Code +printf("%s has %u files +\backslash +n", user, num); +\begin_inset Newline newline +\end_inset + +printf("%2$u files belong to %1$s +\backslash +n", num, user); +\end_layout + +\begin_layout Plain Layout +\begin_inset Quotes eld +\end_inset + + +\family typewriter +%s +\family default + +\begin_inset Quotes erd +\end_inset + + (or +\begin_inset Quotes eld +\end_inset + + +\family typewriter +%1$s +\family default + +\begin_inset Quotes erd +\end_inset + + here) specifies how large +\begin_inset Quotes eld +\end_inset + +user +\begin_inset Quotes erd +\end_inset + + is +\begin_inset space ~ +\end_inset + +--- +\family typewriter +sizeof(const char *) +\family default + in this case. + If that is missing, there is no way to know the offset of +\begin_inset Quotes eld +\end_inset + + +\family typewriter +num +\family default + +\begin_inset Quotes erd +\end_inset + + relative to +\begin_inset Quotes eld +\end_inset + + +\family typewriter +user +\family default + +\begin_inset Quotes erd +\end_inset + +, making varargs retrieval impossible. +\end_layout + +\begin_layout Plain Layout +\begin_inset Caption + +\begin_layout Plain Layout + +\family typewriter +printf +\family default + positional parameters +\end_layout + +\end_inset + + +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard + +\family typewriter +printf +\family default + +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +printf +\end_layout + +\end_inset + +, at least from GNU libc, has something vaguely similar: positional parameters +\begin_inset Index idx +status open + +\begin_layout Plain Layout +positional parameters +\end_layout + +\end_inset + +. + They have inherent drawbacks, though. + One is of course the question of portability, but there is a bigger issue. + All parameters must be specified, otherwise there is no way to determine + the location of all following objects following the missing one on the + stack in a varargs-function like +\family typewriter +printf +\family default +., which makes it unsuitable to be used with templates where omitting some + placeholders is allowed. +\end_layout + +\begin_layout Subsection +Initialization, use and deallocation +\end_layout + +\begin_layout LyX-Code + +\series bold +#include +\series default + <libHX/option.h> +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +libHX/option.h +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +struct +\series default + HXformat_map +\series bold +* +\series default +HXformat_init( +\series bold +void +\series default +); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +\size normal +\color none +HXformat_init +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +void +\series default + HXformat_free( +\series bold +struct +\series default + HXformat_map +\series bold +* +\series default +table); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +\size normal +\color none +HXformat_free +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +int +\series default + HXformat_add( +\series bold +struct +\series default + HXformat_map +\series bold +* +\series default +table, +\series bold +const char * +\series default +key, +\begin_inset Newline newline +\end_inset + + +\series bold +const void * +\series default +ptr, +\series bold +unsigned int +\series default + ptr_type); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +\size normal +\color none +HXformat_add +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard + +\family typewriter +HXformat_init +\family default + will allocate and set up a simple string-to-string map that is used for + the underlying storage, and returns it. +\end_layout + +\begin_layout Standard +To release the substitution table and memory associated with it, call +\family typewriter +HXformat_free +\family default +. +\end_layout + +\begin_layout Standard + +\family typewriter +HXformat_add +\family default + is used to add substitution entries. + One can also specify other types such as numeral types. + +\family typewriter +ptr_type +\family default + describes the type behind +\family typewriter +ptr +\family default + and are constants from +\family typewriter +option.h +\family default + (cf. +\begin_inset space \space{} +\end_inset + +section +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "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 <libHX/io.h> +\series default + +\begin_inset Newline newline +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +int +\series default + HX_readlink(hxmc_t +\series bold +** +\series default +buf, +\series bold +const char * +\series default +path); +\begin_inset Index idx +status open + +\begin_layout Plain Layout +HX_readlink +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +int +\series default + HX_realpath(hxmc_t +\series bold +** +\series default +buf, +\series bold +const char * +\series default +path, +\series bold +unsigned int +\series default + flags); +\begin_inset Index idx +status open + +\begin_layout Plain Layout +HX_realpath +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard + +\family typewriter +HX_readlink +\family default + calls through to +\family typewriter +readlink +\family default + to read the target of a symbolic link, and stores the result in the memory + container referenced by +\family typewriter +*buf +\family default + (similar to +\family typewriter +HX_getl +\family default + semantics). + If +\family typewriter +*buf +\family default + is +\family typewriter +NULL +\family default +, a new container will be allocated and a pointer to it stored in +\family typewriter +*buf +\family default +. + The container's content is naturally zero-terminated automatically. + The return value of the function will be the length of the link target, + or negative to indicate the system error value. +\end_layout + +\begin_layout Standard + +\family typewriter +HX_realpath +\family default + will normalize the given path by transforming various path components into + alternate descriptions. + The +\family typewriter +flags +\family default + parameter controls its actions: +\end_layout + +\begin_layout Description + +\family typewriter +HX_REALPATH_DEFAULT +\family default + +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HX_REALPATH_DEFAULT +\end_layout + +\end_inset + + A mnemonic for a set of standard flags: +\family typewriter +HX_\SpecialChar \- +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 + <libHX/io.h> +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +libHX/io.h +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +struct +\series default + HXdir +\series bold +* +\series default +HXdir_open( +\series bold +const char * +\series default +directory); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +\size normal +\color none +HXdir_open +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +const char * +\series default +HXdir_read( +\series bold +struct +\series default + HXdir +\series bold +* +\series default +handle); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +\size normal +\color none +HXdir_read +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +void +\series default + HXdir_close( +\series bold +struct +\series default + HXdir +\series bold +* +\series default +handle); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +\size normal +\color none +HXdir_close +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard + +\family typewriter +HXdir_open +\family default + returns a pointer to its private data area, or +\family typewriter +NULL +\family default + upon failure, in which case +\family typewriter +errno +\family default + is preserved from the underlying system calls. + +\family typewriter +HXdir_read +\family default + causes the next entry from the directory to be fetched. + The pointer returned by +\family typewriter +HXdir_read +\family default + must not be freed, and the data is overwritten in subsequent calls to the + same handle. + If you want to keep it around, you will have to duplicate it yourself. + +\family typewriter +HXdir_close +\family default + will close the directory and free the private data it held. +\end_layout + +\begin_layout Subsection +Example +\end_layout + +\begin_layout LyX-Code + +\series bold +#include +\series default + <errno.h> +\begin_inset Newline newline +\end_inset + + +\series bold +#include +\series default + <stdio.h> +\begin_inset Newline newline +\end_inset + + +\series bold +#include +\series default + <libHX/io.h> +\begin_inset Newline newline +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +struct +\series default + HXdir +\series bold +* +\series default +dh; +\begin_inset Newline newline +\end_inset + + +\series bold +if +\series default + ((dh = HXdir_open(".")) == NULL) { +\begin_inset Newline newline +\end_inset + + fprintf(stderr, "Could not open directory: %s +\backslash +n", strerror(errno)); +\begin_inset Newline newline +\end_inset + + return; +\begin_inset Newline newline +\end_inset + +} +\begin_inset Newline newline +\end_inset + + +\series bold +while +\series default + ((dentry = HXdir_read(dh)) != NULL) +\begin_inset Newline newline +\end_inset + + printf("%s +\backslash +n", dentry); +\begin_inset Newline newline +\end_inset + +HXdir_close(dh); +\end_layout + +\begin_layout Standard +This sample will open the current directory, and print out all entries as + it iterates over them. +\end_layout + +\begin_layout Section +Directory operations +\begin_inset CommandInset label +LatexCommand label +name "sec:dir-ops2" + +\end_inset + + +\end_layout + +\begin_layout Subsection +Synopsis +\end_layout + +\begin_layout LyX-Code + +\series bold +#include +\series default + <libHX/io.h> +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +libHX/io.h +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +int +\series default + HX_mkdir( +\series bold +const char * +\series default +path, +\series bold +unsigned int +\series default + mode); +\begin_inset Index idx +status open + +\begin_layout Plain Layout +HX_mkdir +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +int +\series default + HX_rrmdir( +\series bold +const char * +\series default +path); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +\size normal +\color none +HX_rrmdir +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard + +\family typewriter +HX_mkdir +\family default + will create the directory given by +\family typewriter +path +\family default + and all its parents that do not exist yet using the given +\family typewriter +mode +\family default +. + It is equivalent to the ` +\family typewriter +mkdir -p +\family default +` shell command. + It will return >0 for success, or +\family typewriter +-errno +\family default + on error. +\end_layout + +\begin_layout Standard + +\family typewriter +HX_rrmdir +\family default + also maps to an operation commonly done on the shell, ` +\family typewriter +rm -Rf +\family default +`, deleting the directory given by +\family typewriter +path +\family default +, including all files within it and its subdirectories. + Errors during deletion are ignored, but if there was any, the errno value + of the first one is returned negated. +\end_layout + +\begin_layout Section +File operations +\begin_inset CommandInset label +LatexCommand label +name "sec:file-ops" + +\end_inset + + +\end_layout + +\begin_layout Subsection +Synopsis +\end_layout + +\begin_layout LyX-Code + +\series bold +#include +\series default + <libHX/io.h> +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +libHX/io.h +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +int +\series default + HX_copy_file( +\series bold +const char * +\series default +src, +\series bold +const char * +\series default +dest, +\series bold +unsigned int +\series default + flags, ...); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HX_copy_file +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +int +\series default + HX_copy_dir( +\series bold +const char * +\series default +src, +\series bold +const char * +\series default +dest, +\series bold +unsigned int +\series default + flags, ...); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HX_copy_dir +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +Possible flags that can be used with the functions: +\end_layout + +\begin_layout Description + +\family typewriter +HXF_KEEP +\family default + +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXF_KEEP +\end_layout + +\end_inset + + Do not overwrite existing files. +\end_layout + +\begin_layout Description + +\family typewriter +HXF_UID +\family default + +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXF_UID +\end_layout + +\end_inset + + Change the new file's owner to the UID given in the varargs section ( +\family typewriter +... +\family default +). + +\family typewriter +HXF_UID +\family default + is processed before +\family typewriter +HXF_GID +\family default +. +\end_layout + +\begin_layout Description + +\family typewriter +HXF_GID +\family default + +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXF_GID +\end_layout + +\end_inset + + Change the new file's group owner to the GID given in the varargs section. + This is processed after +\family typewriter +HXF_UID +\family default +. +\end_layout + +\begin_layout Standard +Error checking is flakey. +\end_layout + +\begin_layout Standard + +\family typewriter +HX_copy_file +\family default + will return >0 on success, or +\family typewriter +-errno +\family default + on failure. + Errors can arise from the use of the syscalls +\family typewriter +open +\family default +, +\family typewriter +read +\family default + and +\family typewriter +write +\family default +. + The return value of +\family typewriter +fchmod +\family default +, which is used to set the UID and GID, is actually ignored, which means + verifying that the owner has been set cannot be detected with +\family typewriter +HX_copy_file +\family default + alone (historic negligience?). +\end_layout + +\begin_layout Subsection +Filedescriptor I/O +\end_layout + +\begin_layout LyX-Code + +\series bold +#include +\series default + <libHX/io.h> +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +libHX/io.h +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +ssize_t +\series default + HXio_fullread( +\series bold +int +\series default + fd, +\series bold +void * +\series default +buf, +\series bold +size_t +\series default + size, +\series bold +unsigned int +\series default + flags); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXio_fullread +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +ssize_t +\series default + HXio_fullwrite( +\series bold +int +\series default + fd, +\series bold +const void * +\series default +buf, +\series bold +size_t +\series default + size, +\series bold +unsigned int +\series default + flags); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXio_fullwrite +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +Since plain +\family typewriter +read +\family default +(2) and +\family typewriter +write +\family default +(2) may process only part of the buffer +\begin_inset space ~ +\end_inset + +--- even more likely so with sockets +\begin_inset space ~ +\end_inset + +---, libHX provides two functions that calls these in a loop to retry said + operations until the full amount has been processed. + Since +\family typewriter +read +\family default + and +\family typewriter +write +\family default + can also be used with socket file descriptors, so can these. +\end_layout + +\begin_layout Standard +\begin_inset Newpage clearpage +\end_inset + + +\end_layout + +\begin_layout Part +Options and Configuration Files +\end_layout + +\begin_layout Section +Option parsing +\begin_inset CommandInset label +LatexCommand label +name "sec:option" + +\end_inset + + +\end_layout + +\begin_layout Standard +libHX uses a table-based approach like libpopt +\begin_inset Foot +status open + +\begin_layout Plain Layout +The alternative would be an iterative, open-coded approach like +\family typewriter +getopt +\family default +(3) requires. +\end_layout + +\end_inset + +. + It provides for both long and short options and the different styles associated + with them, such as absence or presence of an equals sign for long options + ( +\family typewriter +--foo=bar +\family default + and +\family typewriter +--foo bar +\family default +), bundling (writing +\family typewriter +-abc +\family default + for non-argument taking options +\family typewriter +-a -b -c +\family default +), squashing (writing +\family typewriter +-fbar +\family default + for an argument-requiring option +\family typewriter +-f +\begin_inset space ~ +\end_inset + +bar +\family default +). + The +\begin_inset Quotes eld +\end_inset + +lone dash +\begin_inset Quotes erd +\end_inset + + that is often used to indicate standard input or standard output, is correctly + handled +\begin_inset Foot +status open + +\begin_layout Plain Layout +popt failed to do this for a long time. +\end_layout + +\end_inset + +, as in +\family typewriter +-f +\begin_inset space ~ +\end_inset + +- +\family default +. +\end_layout + +\begin_layout Standard +A table-based approach allows for the parser to run as one atomic block + of code (callbacks are, by definition, +\begin_inset Quotes eld +\end_inset + +special +\begin_inset Quotes erd +\end_inset + + exceptions), making it more opaque than an open-coded +\family typewriter +getopt +\family default +(3) loop. + You give it your argument vector and the table, snip the finger (call the + parser function once), and it is done. + In getopt on the other hand, the +\family typewriter +getopt +\family default + function returns for every argument it parsed and needs to be called repeatedly. +\end_layout + +\begin_layout Subsection +Synopsis +\begin_inset CommandInset label +LatexCommand label +name "sub:option-synopsis" + +\end_inset + + +\end_layout + +\begin_layout LyX-Code + +\series bold +#include +\series default + <libHX/option.h> +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +libHX/option.h +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +struct +\series default + HXoption { +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +struct HXoption +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +const char +\series default + *ln; +\begin_inset Newline newline +\end_inset + + +\series bold +char +\series default + sh; +\begin_inset Newline newline +\end_inset + + +\series bold +unsigned int +\series default + type; +\begin_inset Newline newline +\end_inset + + +\series bold +void * +\series default +ptr, +\series bold +* +\series default +uptr; +\begin_inset Newline newline +\end_inset + + +\series bold +void (* +\series default +cb +\series bold +) +\series default +( +\series bold +const struct +\series default + HXoptcb +\series bold +* +\series default +); +\begin_inset Newline newline +\end_inset + + +\series bold +int +\series default + val; +\begin_inset Newline newline +\end_inset + + +\series bold +const char * +\series default +help, +\series bold +* +\series default +htyp; +\begin_inset Newline newline +\end_inset + +}; +\begin_inset Newline newline +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +int +\series default + HX_getopt( +\series bold +const struct +\series default + HXoption +\series bold +* +\series default +options_table, +\series bold +int * +\series default +argc, +\begin_inset Newline newline +\end_inset + + +\series bold +const char *** +\series default +argv, +\series bold +unsigned int +\series default + flags); +\end_layout + +\begin_layout Standard +The various fields of +\family typewriter +struct HXoption +\family default + are: +\end_layout + +\begin_layout Description + +\family typewriter +ln +\family default + The long option name, if any. + May be +\family typewriter +NULL +\family default + if none is to be assigned for this entry. +\end_layout + +\begin_layout Description + +\family typewriter +sh +\family default + The short option name/character, if any. + May be +\family typewriter +' +\backslash +0' +\family default + if none is to be assigned for this entry. +\end_layout + +\begin_layout Description + +\family typewriter +type +\family default + The type of the entry, essentially denoting the type of the target variable. +\end_layout + +\begin_layout Description + +\family typewriter +val +\family default + An integer value to be stored into +\family typewriter +*(int +\begin_inset space ~ +\end_inset + +*)ptr +\family default + when +\family typewriter +HXTYPE_IVAL +\family default + is used. +\end_layout + +\begin_layout Description + +\family typewriter +ptr +\family default + A pointer to the variable so that the option parser can store the requested + data in it. + The pointer may be +\family typewriter +NULL +\family default + in which case no data is stored (but +\family typewriter +cb +\family default + is still called if defined, with the data). +\end_layout + +\begin_layout Description + +\family typewriter +uptr +\family default + A user-supplied pointer. + Its value is passed verbatim to the callback, and may be used for any purpose + the user wishes. + If +\family typewriter +type +\family default + is +\family typewriter +HXTYPE_SVAL +\family default +, it is the value in +\family typewriter +uptr +\family default + that will be used to populate +\family typewriter +*(const char +\begin_inset space ~ +\end_inset + +**)ptr +\family default +. + (The original +\family typewriter +.sval +\family default + field has been removed in libHX 3.12.) +\end_layout + +\begin_layout Description + +\family typewriter +cb +\family default + If not +\family typewriter +NULL +\family default +, call out to the referenced function after the option has been parsed (and + the results possibly be stored in +\family typewriter +ptr +\family default +) +\end_layout + +\begin_layout Description + +\family typewriter +help +\family default + A help string that is shown for the option when the option table is dumped + by request (e. +\begin_inset space \thinspace{} +\end_inset + +g. +\begin_inset space \space{} +\end_inset + + +\family typewriter +yourprgram --help +\family default +) +\end_layout + +\begin_layout Description + +\family typewriter +htyp +\family default + String containing a keyword to aid the user in understanding the available + options during dump. + See examples. +\end_layout + +\begin_layout Standard +Due to the amount of fields, it is advised to use C99 named initializers + to populate a struct, as they allow to omit unspecified fields, and assume + no specific order of the members: +\end_layout + +\begin_layout LyX-Code + +\series bold +struct +\series default + HXoption e = {.sh = 'f', .help = "Force"}; +\end_layout + +\begin_layout Standard +It is a sad fact that C++ has not gotten around to implement these yet. + It is advised to put the option parsing code into a separate +\family typewriter +.c +\family default + file that can then be compiled in C99 rather than C++ mode. +\end_layout + +\begin_layout Subsection +Type map +\begin_inset CommandInset label +LatexCommand label +name "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 +<lyxtabular version="3" rows="12" columns="4"> +<features tabularvalignment="middle"> +<column alignment="center" valignment="top" width="0"> +<column alignment="center" valignment="bottom" width="0"> +<column alignment="center" valignment="top" width="0"> +<column alignment="center" valignment="top" width="0"> +<row> +<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\family typewriter +\series bold +type +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\series bold +Type of pointee +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\series bold +type +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\series bold +Type of pointee +\end_layout + +\end_inset +</cell> +</row> +<row> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\family typewriter +HXTYPE_CHAR +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXTYPE_CHAR +\end_layout + +\end_inset + + +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\family typewriter +char +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\family typewriter +HXTYPE_INT8 +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXTYPE_INT8 +\end_layout + +\end_inset + + +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\family typewriter +int8_t +\end_layout + +\end_inset +</cell> +</row> +<row> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\family typewriter +HXTYPE_UCHAR +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXTYPE_UCHAR +\end_layout + +\end_inset + + +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\family typewriter +unsigned char +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\family typewriter +HXTYPE_UINT8 +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXTYPE_UINT8 +\end_layout + +\end_inset + + +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\family typewriter +uint8_t +\end_layout + +\end_inset +</cell> +</row> +<row> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\family typewriter +HXTYPE_SHORT +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXTYPE_SHORT +\end_layout + +\end_inset + + +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\family typewriter +short +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\family typewriter +HXTYPE_INT16 +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXTYPE_INT16 +\end_layout + +\end_inset + + +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\family typewriter +int16_t +\end_layout + +\end_inset +</cell> +</row> +<row> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\family typewriter +HXTYPE_USHORT +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXTYPE_USHORT +\end_layout + +\end_inset + + +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\family typewriter +unsigned short +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\family typewriter +HXTYPE_UINT16 +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXTYPE_UINT16 +\end_layout + +\end_inset + + +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\family typewriter +uint16_t +\end_layout + +\end_inset +</cell> +</row> +<row> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\family typewriter +HXTYPE_INT +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXTYPE_INT +\end_layout + +\end_inset + + +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\family typewriter +int +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\family typewriter +HXTYPE_INT32 +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXTYPE_INT32 +\end_layout + +\end_inset + + +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\family typewriter +int32_t +\end_layout + +\end_inset +</cell> +</row> +<row> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\family typewriter +HXTYPE_UINT +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXTYPE_UINT +\end_layout + +\end_inset + + +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\family typewriter +unsigned int +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\family typewriter +HXTYPE_UINT32 +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXTYPE_UINT32 +\end_layout + +\end_inset + + +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\family typewriter +uint32_t +\end_layout + +\end_inset +</cell> +</row> +<row> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\family typewriter +HXTYPE_LONG +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXTYPE_LONG +\end_layout + +\end_inset + + +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\family typewriter +long +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\family typewriter +HXTYPE_INT64 +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXTYPE_INT64 +\end_layout + +\end_inset + + +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\family typewriter +int64_t +\end_layout + +\end_inset +</cell> +</row> +<row> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\family typewriter +HXTYPE_ULONG +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXTYPE_ULONG +\end_layout + +\end_inset + + +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\family typewriter +unsigned long +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\family typewriter +HXTYPE_UINT64 +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXTYPE_UINT64 +\end_layout + +\end_inset + + +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\family typewriter +uint64_t +\end_layout + +\end_inset +</cell> +</row> +<row> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\family typewriter +HXTYPE_LLONG +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXTYPE_LLONG +\end_layout + +\end_inset + + +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\family typewriter +long long +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\family typewriter +HXTYPE_FLOAT +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXTYPE_FLOAT +\end_layout + +\end_inset + + +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\family typewriter +float +\end_layout + +\end_inset +</cell> +</row> +<row> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\family typewriter +HXTYPE_ULLONG +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXTYPE_ULLONG +\end_layout + +\end_inset + + +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\family typewriter +unsigned long long +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\family typewriter +HXTYPE_DOUBLE +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXTYPE_DOUBLE +\end_layout + +\end_inset + + +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\family typewriter +double +\end_layout + +\end_inset +</cell> +</row> +<row> +<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\family typewriter +HXTYPE_SIZE_T +\family default + +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HXTYPE_SIZE_T +\end_layout + +\end_inset + + +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\family typewriter +size_t +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none"> +\begin_inset Text + +\begin_layout Plain Layout + +\end_layout + +\end_inset +</cell> +</row> +</lyxtabular> + +\end_inset + + +\end_layout + +\begin_layout Plain Layout +\begin_inset Caption + +\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 + <stdio.h> +\begin_inset Newline newline +\end_inset + + +\series bold +#include +\series default + <stdilb.h> +\begin_inset Newline newline +\end_inset + + +\series bold +#include +\series default + <libHX/option.h> +\begin_inset Newline newline +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +int +\series default + main( +\series bold +int +\series default + argc, +\series bold +const char ** +\series default +argv) +\begin_inset Newline newline +\end_inset + +{ +\begin_inset Newline newline +\end_inset + + +\series bold +int +\series default + aflag = 0; +\begin_inset Newline newline +\end_inset + + +\series bold +int +\series default + bflag = 0; +\begin_inset Newline newline +\end_inset + + +\series bold +char * +\series default +cflag = NULL; +\begin_inset Newline newline +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +struct +\series default + HXoption options_table +\series bold +[] +\series default + = { +\begin_inset Newline newline +\end_inset + + {.sh = 'a', .type = HXTYPE_NONE, .ptr = &aflag}, +\begin_inset Newline newline +\end_inset + + {.sh = 'b', .type = HXTYPE_NONE, .ptr = &bflag}, +\begin_inset Newline newline +\end_inset + + {.sh = 'c', .type = HXTYPE_STRING, .ptr = &cflag}, +\begin_inset Newline newline +\end_inset + + HXOPT_AUTOHELP, +\end_layout + +\begin_layout LyX-Code + HXOPT_TABLEEND, +\begin_inset Newline newline +\end_inset + + }; +\begin_inset Newline newline +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +if +\series default + (HX_getopt(options_table, &argc, &argv, HXOPT_USAGEONERR) != +\begin_inset Newline newline +\end_inset + + HXOPT_ERR_SUCCESS) +\end_layout + +\begin_layout LyX-Code + +\series bold +return +\series default + EXIT_FAILURE; +\begin_inset Newline newline +\end_inset + + +\begin_inset Newline newline +\end_inset + + printf("aflag = %d, bflag = %d, cvalue = %s +\backslash +n", +\begin_inset Newline newline +\end_inset + + aflag, bflag, cvalue); +\begin_inset Newline newline +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +while +\series default + (*++argv != NULL) +\begin_inset Newline newline +\end_inset + + printf("Non-option argument %s +\backslash +n", *argv); +\begin_inset Newline newline +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +return +\series default + EXIT_SUCCESS; +\begin_inset Newline newline +\end_inset + +} +\end_layout + +\begin_layout Subsubsection +Verbosity levels +\begin_inset CommandInset label +LatexCommand label +name "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 + <libHX/option.h> +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +libHX/option.h +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +int +\series default + HX_shconfig( +\series bold +const char * +\series default +file, +\series bold +const struct +\series default + HXoption +\series bold +* +\series default +table); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HX_shconfig +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +int +\series default + HX_shconfig_pv( +\series bold +const char ** +\series default +path_vec, +\series bold +const char * +\series default +file, +\begin_inset Newline newline +\end_inset + + +\series bold +const struct +\series default + HXoption +\series bold +* +\series default +table, +\series bold +unsigned int +\series default + flags); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HX_shconfig_pv +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +struct +\series default + HXmap +\series bold +* +\series default +HX_shconfig_map( +\series bold +const char * +\series default +file); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HX_shconfig_map +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +The shconfig parser reuses +\family typewriter +struct HXoption +\family default + that fits very well in specifying name-pointer associations. + +\family typewriter +HX_shconfig +\family default + will read the given file using the key-to-pointer mappings from the table + to store the variable contents. + Of +\family typewriter +struct HXoption +\family default +, described in section +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "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 + <libHX/misc.h> +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +libHX/misc.h +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +int +\series default + HX_rand( +\series bold +void +\series default +); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HX_rand +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +unsigned int +\series default + HX_irand( +\series bold +unsigned int +\series default + min, +\series bold +unsigned int +\series default + max); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +\size normal +\color none +HX_irand +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +double +\series default + HX_drand( +\series bold +double +\series default + min, +\series bold +double +\series default + max); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HX_drand +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Description + +\family typewriter +HX_rand +\family default + Retrieve the next random number. +\end_layout + +\begin_layout Description + +\family typewriter +HX_irand +\family default + Retrieve the next random number and fold it so that +\begin_inset Formula $\textit{min}\le n<\textit{max}$ +\end_inset + +, where min and max are unsigned integers. +\end_layout + +\begin_layout Description + +\family typewriter +HX_drand +\family default + Retrieve the next random number and fold it so that +\begin_inset Formula $\textit{min}\le n<\textit{max}$ +\end_inset + +, where min and max are double-precision floating point numbers. +\end_layout + +\begin_layout Subsection +Implementation information +\end_layout + +\begin_layout Standard +On systems that provide operating system-level random number generators, + predominantly Linux and Unix-alikes such as BSD and Solaris, these will + be used when they are available and random numbers are requested through + +\family typewriter +HX_rand +\family default + or +\family typewriter +HX_irand +\family default +. +\end_layout + +\begin_layout Standard +On Linux, Solaris and the BSDs, this is +\family typewriter +/dev/urandom +\family default + +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +/dev/urandom +\end_layout + +\end_inset + +. +\end_layout + +\begin_layout Standard +If no random number generating device is available (and libHX configured + to use it), it will fall back to using the libc's +\family typewriter +rand +\family default + +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +rand +\end_layout + +\end_inset + + function. + If libc is selected for random number generation, +\family typewriter +srand +\family default + will be called on library initialization with what is believed to be good + defaults +\begin_inset space ~ +\end_inset + +--- usually this will be before a program's +\family typewriter +main +\family default + function with normal linking, but may actually happen later when used with + +\family typewriter +dlopen +\family default +. + The initial seed would be the current microtime when +\family typewriter +gettimeofday +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +gettimeofday +\end_layout + +\end_inset + + +\family default + is available, or just the seconds with +\family typewriter +time +\family default + +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +time +\end_layout + +\end_inset + +. + To counter the problem of different programs potentially using the same + seed within a time window of a second due to the limited granularity of + standard +\family typewriter +time +\family default +, the seed is augmented by process ID and parent process ID where available. +\end_layout + +\begin_layout Standard + +\family typewriter +/dev/random +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +/dev/random +\end_layout + +\end_inset + + +\family default + is not used on Linux because it may block during read, and +\family typewriter +/dev/urandom +\family default + is just as good when there is entropy available. + If you need definitive PRNG +\begin_inset Index idx +status open + +\begin_layout Plain Layout +PRNG +\end_layout + +\end_inset + + security, perhaps use one from a crypto suite such as OpenSSL. +\end_layout + +\begin_layout Standard +\begin_inset Newpage clearpage +\end_inset + + +\end_layout + +\begin_layout Section +Process management +\begin_inset CommandInset label +LatexCommand label +name "sec:proc" + +\end_inset + + +\end_layout + +\begin_layout Standard +The process code is experimental at this stage (just moved from the pam_mount + codebase). + As it also relies on the POSIX functions +\family typewriter +fork +\family default +, +\family typewriter +execv +\family default +, +\family typewriter +execvp +\family default + and +\family typewriter +pipe +\family default +(2), so it may not be available everywhere. + Where this is the case, the functions will return +\family typewriter +-ENOSYS +\family default +. +\end_layout + +\begin_layout Subsection +Process metadata structure +\end_layout + +\begin_layout LyX-Code + +\series bold +#include +\series default + <libHX/proc.h> +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +libHX/proc.h +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +struct +\series default + HXproc { +\begin_inset Newline newline +\end_inset + + +\series bold +const struct +\series default + HXproc_ops +\series bold +* +\series default +p_ops; +\begin_inset Newline newline +\end_inset + + +\series bold +void * +\series default +p_data; +\begin_inset Newline newline +\end_inset + + +\series bold +unsigned int +\series default + p_flags; +\begin_inset Newline newline +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +/* +\family roman +\series default +\shape italic +Following members should only be read +\family default +\series bold +\shape default + */ +\series default + +\begin_inset Newline newline +\end_inset + + +\series bold +int +\series default + p_stdin, p_stdout, p_stderr; +\begin_inset Newline newline +\end_inset + + +\series bold +int +\series default + p_pid; +\begin_inset Newline newline +\end_inset + + +\series bold +char +\series default + p_status; +\begin_inset Newline newline +\end_inset + + +\series bold +bool +\series default + p_exited, p_terminated; +\begin_inset Newline newline +\end_inset + +}; +\end_layout + +\begin_layout Standard +When creating a new process with the intent of running it asynchronously + (using +\family typewriter +HXproc_\SpecialChar \- +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 + <libHX/proc.h> +\begin_inset Newline newline +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +struct +\series default + HXproc_ops { +\begin_inset Newline newline +\end_inset + + +\series bold +void (* +\series default +p_prefork +\series bold +) +\series default +( +\series bold +void * +\series default +); +\begin_inset Newline newline +\end_inset + + +\series bold +void (* +\series default +p_postfork +\series bold +) +\series default +( +\series bold +void * +\series default +); +\begin_inset Newline newline +\end_inset + + +\series bold +void (* +\series default +p_complete +\series bold +) +\series default +( +\series bold +void * +\series default +); +\begin_inset Newline newline +\end_inset + +}; +\end_layout + +\begin_layout Standard + +\family typewriter +struct HXproc_ops +\family default + provides a way to run user-specified functions just before the fork, after, + and when the process has been waited for. + They can be used to set and/or restore signals as needed, for example. + The function pointers can be +\family typewriter +NULL +\family default +. + The +\family typewriter +p_data +\family default + member is passed as an argument. +\end_layout + +\begin_layout Description + +\family typewriter +p_prefork +\family default + Run immediately before calling +\family typewriter +fork +\family default +(2). + This is useful, for taking any action regarding signals, like setting +\family typewriter +SIGCHLD +\family default + to +\family typewriter +SIG_DFL +\family default +, or +\family typewriter +SIGPIPE +\family default + to +\family typewriter +SIG_IGN +\family default +, for example. +\end_layout + +\begin_layout Description + +\family typewriter +p_postfork +\family default + Run in the subprocess (and only there) after forking. + Useful to do a +\family typewriter +setuid +\family default +(2) or other change in privilege level. +\end_layout + +\begin_layout Description + +\family typewriter +p_complete +\family default + Run in +\family typewriter +HXproc_wait +\family default + when the process has been waited for. + Useful to restore the signal handler(s). +\end_layout + +\begin_layout Subsection +Process control +\end_layout + +\begin_layout LyX-Code + +\series bold +#include +\series default + <libHX/proc.h> +\begin_inset Newline newline +\end_inset + + +\series bold + +\begin_inset Newline newline +\end_inset + +int +\series default + HXproc_run_async( +\series bold +const char *const * +\series default +argv, +\series bold +struct +\series default + HXproc +\series bold +* +\series default +proc); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +\size normal +\color none +HXproc_run_async +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +int +\series default + HXproc_run_sync( +\series bold +const char *const * +\series default +argv, +\series bold +unsigned int +\series default + flags); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +\size normal +\color none +HXproc_run_sync +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +int +\series default + HXproc_wait( +\series bold +struct +\series default + HXproc +\series bold +* +\series default +proc); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +\size normal +\color none +HXproc_wait +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Description + +\family typewriter +HXproc_run_async +\family default + Start a subprocess according to the parameters in +\family typewriter +proc +\family default +. + Returns a negative errno code if something went wrong, or positive non-zero + on success. +\end_layout + +\begin_layout Description + +\family typewriter +HXproc_run_sync +\family default + Start a subprocess synchronously, similar to calling +\family typewriter +system +\family default +(3) +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +system +\end_layout + +\end_inset + +, but with the luxury of being able to specify arguments as separate strings + (via argv) rather than one big command line that is run through the shell. + +\family typewriter +flags +\family default + is a value composed of the HXproc flags mentioned above in section +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "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 +<ctype.h> +\family default + header, including, but not limited to, +\family typewriter +isalpha +\family default +, +\family typewriter +tolower +\family default +, and so forth, are defined to take an +\begin_inset Quotes eld +\end_inset + + +\family typewriter +int +\family default + +\begin_inset Quotes erd +\end_inset + + as first argument. + Strings used in C programs are usually +\begin_inset Quotes eld +\end_inset + + +\family typewriter +char +\begin_inset space ~ +\end_inset + +* +\family default + +\begin_inset Quotes erd +\end_inset + +, without any +\begin_inset Quotes eld +\end_inset + + +\family typewriter +signed +\family default + +\begin_inset Quotes erd +\end_inset + + or +\begin_inset Quotes eld +\end_inset + + +\family typewriter +unsigned +\family default + +\begin_inset Quotes erd +\end_inset + + qualifier. + By a high-level view, which also matches daily common sense, characters + (a. +\begin_inset space \thinspace{} +\end_inset + +k. +\begin_inset space \thinspace{} +\end_inset + +a. +\begin_inset space \space{} +\end_inset + +letters) have no notion of signedness +\begin_inset space ~ +\end_inset + +--- there is no +\begin_inset Quotes eld +\end_inset + +positive +\begin_inset Quotes erd +\end_inset + + or +\begin_inset Quotes eld +\end_inset + +negative +\begin_inset Quotes erd +\end_inset + + +\begin_inset Quotes eld +\end_inset + +A +\begin_inset Quotes erd +\end_inset + + in at least the Latin alphabet that is mapped into the ASCII set. + In fact, +\family typewriter +char +\begin_inset space ~ +\end_inset + +* +\family default + could either be +\family typewriter +signed char +\begin_inset space ~ +\end_inset + +* +\family default + or +\family typewriter +unsigned char +\begin_inset space ~ +\end_inset + +* +\family default +, depending on the compiler settings. + Only when you start interpreting and using characters as a number does + such become important. + +\end_layout + +\begin_layout Standard +There come the problems. + Characters are in the same class as numbers in C, that is, can be implicitly + converted from or to a +\begin_inset Quotes eld +\end_inset + +number +\begin_inset Quotes erd +\end_inset + + (in this case, their ASCII code point) without causing a compiler warning. + That may be practical in some cases, but is also a bit +\begin_inset Quotes eld +\end_inset + +unfortunate +\begin_inset Quotes erd +\end_inset + +. + Characters, when interpreted as the 8-bit signed numeric quantity they + are implicitly convertable to, run from 0 to 127 and \SpecialChar \nobreakdash- +128 to \SpecialChar \nobreakdash- +1. + Since the +\family typewriter +isalpha +\family default + function and others from +\family typewriter +ctype.h +\family default + take a (signed) +\family typewriter +int +\family default + as argument means that values fed to +\family typewriter +isalpha +\family default + are sign-extended, preserving negative values. +\end_layout + +\begin_layout LyX-Code + +\series bold +/* +\family roman +\series default +\shape italic + +\begin_inset Quotes eld +\end_inset + +hyvää yötä +\begin_inset Quotes erd +\end_inset + +, UTF-8 encoded +\family default +\series bold +\shape default + */ +\end_layout + +\begin_layout LyX-Code + +\series bold +const char +\series default +h +\series bold +[] +\series default + = {'h', 'y', 'v', 0xc3, 0xa4, 0xc3, 0xa4, ' ', +\begin_inset Newline newline +\end_inset + + 'y', 0xc3, 0xb6, 't', 0xc3, 0xa4}; +\end_layout + +\begin_layout Standard +When you now pass +\family typewriter +h[3] +\family default + to +\family typewriter +isalpha +\family default + for example (regardless of whether doing so actually produces a meaningful + result), the CPU is instructed to copy +\begin_inset Quotes eld +\end_inset + +0xc3 +\begin_inset Quotes erd +\end_inset + + into a register and sign-extend it (because +\begin_inset Quotes eld +\end_inset + +char +\begin_inset Quotes erd +\end_inset + + is often +\begin_inset Quotes eld +\end_inset + +signed char +\begin_inset Quotes erd +\end_inset + +, see above), producing 0xffffffc3 (\SpecialChar \nobreakdash- +61). + But passing \SpecialChar \nobreakdash- +61 is not what was intended. +\end_layout + +\begin_layout Standard +libHX's +\family typewriter +ctype_helper.h +\family default + therefore provides wrappers with a different function signature that uses + zero extension (not sign extension) by means of using an +\family typewriter +unsigned +\family default + quantity. + Currently this is +\family typewriter + unsigned char +\family default +, because +\family typewriter +isalpha +\family default +'s domain only goes from 0--255. + The implication is that you cannot pass +\family typewriter +EOF +\family default + to +\family typewriter +HX_isalpha +\family default +. +\end_layout + +\begin_layout LyX-Code + +\series bold +#include +\series default + <libHX/ctype_helper.h> +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +libHX/ctype_helper.h +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +bool +\series default + HX_isalnum( +\series bold +unsigned char +\series default + c); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +\size normal +\color none +HX_isalnum +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +bool +\series default + HX_isalpha( +\series bold +unsigned char +\series default + c); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +\size normal +\color none +HX_isalpha +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +bool +\series default + HX_isdigit( +\series bold +unsigned char +\series default + c); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +\size normal +\color none +HX_isdigit +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +bool +\series default + HX_islower( +\series bold +unsigned char +\series default + c); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +\size normal +\color none +HX_islower +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +bool +\series default + HX_isprint( +\series bold +unsigned char +\series default + c); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +\size normal +\color none +HX_isprint +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +bool +\series default + HX_isspace( +\series bold +unsigned char +\series default + c); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HX_isspace +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +bool +\series default + HX_isupper( +\series bold +unsigned char +\series default + c); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +HX_isupper +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +bool +\series default + HX_isxdigit( +\series bold +unsigned char +\series default + c); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +\size normal +\color none +HX_isxdigit +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +unsigned char +\series default + HX_tolower( +\series bold +unsigned char +\series default + c); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +\size normal +\color none +HX_tolower +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +unsigned char +\series default + HX_toupper( +\series bold +unsigned char +\series default + c); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +\size normal +\color none +HX_toupper +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +The +\family typewriter +is* +\family default + functions also differ from ctype's in that they return +\family typewriter +bool +\family default + instead of +\family typewriter +int +\family default +. + Not all functions from +\family typewriter +ctype.h +\family default + are present either; +\family typewriter +isascii +\family default +, +\family typewriter +isblank +\family default +, +\family typewriter +iscntrl +\family default +, +\family typewriter +isgraph +\family default +, +\family typewriter +ispunct +\family default + and +\family typewriter +isxdigit +\family default + have been omitted as the author has never needed them so far. +\end_layout + +\begin_layout Subsection +libxml2 helpers +\end_layout + +\begin_layout Standard +libxml2 uses an +\begin_inset Quotes eld +\end_inset + + +\family typewriter +xmlChar +\family default + +\begin_inset Quotes erd +\end_inset + + type as an underlying type for the strings that it reads and outputs. + +\family typewriter +xmlChar +\family default + is typedef'ed to +\family typewriter +unsigned char +\family default + by libxml2, causing compiler warnings related to differing signedness whenever + interacting with strings from the outside world, which are usually just + a pointer to +\family typewriter +char +\family default +. + Because casting would be a real chore, +\family typewriter +libxml_helper.h +\family default + will do it by providing some wrappers with better argument types. +\end_layout + +\begin_layout LyX-Code + +\series bold +#include +\series default + <libHX/libxml_helper.h> +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +libHX/libxml_helper.h +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +int +\series default + xml_strcmp( +\series bold +const +\series default + xmlChar +\series bold +* +\series default +a, +\series bold +const char * +\series default +b); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +xml_strcmp +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +int +\series default + xml_strcasecmp( +\series bold +const +\series default + xmlChar +\series bold +* +\series default +a, +\series bold +const char * +\series default +b); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +xml_strcasecmp +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\series bold +char * +\series default +xml_getprop(xmlNode +\series bold +* +\series default +node, +\series bold +const char * +\series default +attr); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +xml_getprop +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + +char *xml_getnsprop( +\series bold +xmlNode * +\series default +node, +\series bold +const char * +\series default +nsprefix, +\series bold +const char * +\series default +attr); +\begin_inset Index idx +status open + +\begin_layout Plain Layout +xml_getnsprop +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + +xmlAttr +\series bold +* +\series default +xml_newprop(xmlNode +\series bold +* +\series default +node, +\series bold +const char * +\series default +attr); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +xml_newprop +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + +xmlNode +\series bold +* +\series default +xml_newnode(xmlNode +\series bold +* +\series default +parent, +\series bold +const char * +\series default +name, +\series bold +const char * +\series default +value); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +\size normal +\color none +xml_newnode +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + +xmlAttr +\series bold +* +\series default +xml_setprop(xmlNode +\series bold +* +\series default +node, +\series bold +const char * +\series default +name, +\series bold +const char * +\series default +value); +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +\size normal +\color none +xml_setprop +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +The functions map to +\family typewriter +strcmp +\family default +(3) +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +strcmp +\end_layout + +\end_inset + +, +\family typewriter +strcasecmp +\family default +(3) +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +strcasecmp +\end_layout + +\end_inset + +, +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +xmlGetProp +\end_layout + +\end_inset + + +\family typewriter +xmlGetProp +\family default +, +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +xmlNewProp +\end_layout + +\end_inset + + +\family typewriter +xmlNewProp +\family default +, +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +xmlNewTextNode +\end_layout + +\end_inset + + +\family typewriter +xml\SpecialChar \- +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 + <libHX/wx_helper.hpp> +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +libHX/wx_helper.hpp +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Subsubsection +Shortcut macros +\end_layout + +\begin_layout Description +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +wxACV +\end_layout + +\end_inset + + +\family typewriter +wxACV +\family default + Expands to +\family typewriter + +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +wxALIGN_CENTER_VERTICAL +\end_layout + +\end_inset + +wxALIGN_CENTER_VERTICAL +\end_layout + +\begin_layout Description +\begin_inset Index idx +status open + +\begin_layout Plain Layout + +\family typewriter +wxCDF +\end_layout + +\end_inset + + +\family typewriter +wxCDF +\family default + Expands to a set of common dialog flags for +\family typewriter +wxDialog +\family default +s, which includes +\family typewriter +wxDEFAULT_\SpecialChar \- +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 |