diff --git a/Makefile.am b/Makefile.am
index 8c61da454a..e7f1f799a5 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -103,6 +103,7 @@ $(RECURSIVE_TARGETS): freeswitch
CORE_CFLAGS = `$(switch_builddir)/libs/apr/apr-1-config --cflags --cppflags --includes`
CORE_CFLAGS += `$(switch_builddir)/libs/apr-util/apu-1-config --includes`
+CORE_CFLAGS += -I$(switch_srcdir)/libs/libtpl-1.5/src
CORE_CFLAGS += -I$(switch_srcdir)/libs/stfu
CORE_CFLAGS += -I$(switch_builddir)/libs/sqlite
CORE_CFLAGS += -I$(switch_srcdir)/libs/pcre
@@ -204,6 +205,7 @@ library_include_HEADERS = \
libs/libteletone/src/libteletone_detect.h \
libs/libteletone/src/libteletone_generate.h \
libs/libteletone/src/libteletone.h \
+ libs/libtpl-1.5/src/tpl.h \
src/include/switch_limit.h \
src/include/switch_odbc.h
@@ -266,6 +268,7 @@ libfreeswitch_la_SOURCES = \
src/switch_profile.c \
src/switch_json.c \
src/switch_curl.c \
+ libs/libtpl-1.5/src/tpl.c \
libs/stfu/stfu.c \
libs/libteletone/src/libteletone_detect.c \
libs/libteletone/src/libteletone_generate.c \
diff --git a/libs/libtpl-1.5/LICENSE b/libs/libtpl-1.5/LICENSE
new file mode 100755
index 0000000000..7d020b96eb
--- /dev/null
+++ b/libs/libtpl-1.5/LICENSE
@@ -0,0 +1,21 @@
+Copyright (c) 2005-2010, Troy Hanson http://tpl.sourceforge.net
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/libs/libtpl-1.5/Makefile.am b/libs/libtpl-1.5/Makefile.am
new file mode 100755
index 0000000000..780f7ff8e9
--- /dev/null
+++ b/libs/libtpl-1.5/Makefile.am
@@ -0,0 +1,2 @@
+SUBDIRS = src
+EXTRA_DIST = LICENSE tests lang doc
diff --git a/libs/libtpl-1.5/Makefile.in b/libs/libtpl-1.5/Makefile.in
new file mode 100644
index 0000000000..89ed294b0b
--- /dev/null
+++ b/libs/libtpl-1.5/Makefile.in
@@ -0,0 +1,635 @@
+# Makefile.in generated by automake 1.10.2 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = .
+DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in $(top_srcdir)/config/config.h.in \
+ $(top_srcdir)/configure config/config.guess config/config.sub \
+ config/depcomp config/install-sh config/ltmain.sh \
+ config/missing
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
+ configure.lineno config.status.lineno
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config/config.h
+CONFIG_CLEAN_FILES =
+SOURCES =
+DIST_SOURCES =
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+ html-recursive info-recursive install-data-recursive \
+ install-dvi-recursive install-exec-recursive \
+ install-html-recursive install-info-recursive \
+ install-pdf-recursive install-ps-recursive install-recursive \
+ installcheck-recursive installdirs-recursive pdf-recursive \
+ ps-recursive uninstall-recursive
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
+ distclean-recursive maintainer-clean-recursive
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = $(SUBDIRS)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+distdir = $(PACKAGE)-$(VERSION)
+top_distdir = $(distdir)
+am__remove_distdir = \
+ { test ! -d $(distdir) \
+ || { find $(distdir) -type d ! -perm -200 -exec chmod u+w {} ';' \
+ && rm -fr $(distdir); }; }
+DIST_ARCHIVES = $(distdir).tar.gz
+GZIP_ENV = --best
+distuninstallcheck_listfiles = find . -type f -print
+distcleancheck_listfiles = find . -type f -print
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+SUBDIRS = src
+EXTRA_DIST = LICENSE tests lang doc
+all: all-recursive
+
+.SUFFIXES:
+am--refresh:
+ @:
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ echo ' cd $(srcdir) && $(AUTOMAKE) --foreign '; \
+ cd $(srcdir) && $(AUTOMAKE) --foreign \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --foreign Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ echo ' $(SHELL) ./config.status'; \
+ $(SHELL) ./config.status;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ $(SHELL) ./config.status --recheck
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(srcdir) && $(AUTOCONF)
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
+
+config/config.h: config/stamp-h1
+ @if test ! -f $@; then \
+ rm -f config/stamp-h1; \
+ $(MAKE) $(AM_MAKEFLAGS) config/stamp-h1; \
+ else :; fi
+
+config/stamp-h1: $(top_srcdir)/config/config.h.in $(top_builddir)/config.status
+ @rm -f config/stamp-h1
+ cd $(top_builddir) && $(SHELL) ./config.status config/config.h
+$(top_srcdir)/config/config.h.in: $(am__configure_deps)
+ cd $(top_srcdir) && $(AUTOHEADER)
+ rm -f config/stamp-h1
+ touch $@
+
+distclean-hdr:
+ -rm -f config/config.h config/stamp-h1
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+distclean-libtool:
+ -rm -f libtool config.lt
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+# (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+ @failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+$(RECURSIVE_CLEAN_TARGETS):
+ @failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ rev=''; for subdir in $$list; do \
+ if test "$$subdir" = "."; then :; else \
+ rev="$$subdir $$rev"; \
+ fi; \
+ done; \
+ rev="$$rev ."; \
+ target=`echo $@ | sed s/-recursive//`; \
+ for subdir in $$rev; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done && test -z "$$fail"
+tags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+ done
+ctags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ $(am__remove_distdir)
+ test -d $(distdir) || mkdir $(distdir)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+ list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test -d "$(distdir)/$$subdir" \
+ || $(MKDIR_P) "$(distdir)/$$subdir" \
+ || exit 1; \
+ distdir=`$(am__cd) $(distdir) && pwd`; \
+ top_distdir=`$(am__cd) $(top_distdir) && pwd`; \
+ (cd $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$top_distdir" \
+ distdir="$$distdir/$$subdir" \
+ am__remove_distdir=: \
+ am__skip_length_check=: \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
+ -find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \
+ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
+ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \
+ ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
+ || chmod -R a+r $(distdir)
+dist-gzip: distdir
+ tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+ $(am__remove_distdir)
+
+dist-bzip2: distdir
+ tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2
+ $(am__remove_distdir)
+
+dist-lzma: distdir
+ tardir=$(distdir) && $(am__tar) | lzma -9 -c >$(distdir).tar.lzma
+ $(am__remove_distdir)
+
+dist-tarZ: distdir
+ tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
+ $(am__remove_distdir)
+
+dist-shar: distdir
+ shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
+ $(am__remove_distdir)
+
+dist-zip: distdir
+ -rm -f $(distdir).zip
+ zip -rq $(distdir).zip $(distdir)
+ $(am__remove_distdir)
+
+dist dist-all: distdir
+ tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+ $(am__remove_distdir)
+
+# This target untars the dist file and tries a VPATH configuration. Then
+# it guarantees that the distribution is self-contained by making another
+# tarfile.
+distcheck: dist
+ case '$(DIST_ARCHIVES)' in \
+ *.tar.gz*) \
+ GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(am__untar) ;;\
+ *.tar.bz2*) \
+ bunzip2 -c $(distdir).tar.bz2 | $(am__untar) ;;\
+ *.tar.lzma*) \
+ unlzma -c $(distdir).tar.lzma | $(am__untar) ;;\
+ *.tar.Z*) \
+ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
+ *.shar.gz*) \
+ GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\
+ *.zip*) \
+ unzip $(distdir).zip ;;\
+ esac
+ chmod -R a-w $(distdir); chmod a+w $(distdir)
+ mkdir $(distdir)/_build
+ mkdir $(distdir)/_inst
+ chmod a-w $(distdir)
+ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
+ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
+ && cd $(distdir)/_build \
+ && ../configure --srcdir=.. --prefix="$$dc_install_base" \
+ $(DISTCHECK_CONFIGURE_FLAGS) \
+ && $(MAKE) $(AM_MAKEFLAGS) \
+ && $(MAKE) $(AM_MAKEFLAGS) dvi \
+ && $(MAKE) $(AM_MAKEFLAGS) check \
+ && $(MAKE) $(AM_MAKEFLAGS) install \
+ && $(MAKE) $(AM_MAKEFLAGS) installcheck \
+ && $(MAKE) $(AM_MAKEFLAGS) uninstall \
+ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \
+ distuninstallcheck \
+ && chmod -R a-w "$$dc_install_base" \
+ && ({ \
+ (cd ../.. && umask 077 && mkdir "$$dc_destdir") \
+ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \
+ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \
+ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \
+ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \
+ } || { rm -rf "$$dc_destdir"; exit 1; }) \
+ && rm -rf "$$dc_destdir" \
+ && $(MAKE) $(AM_MAKEFLAGS) dist \
+ && rm -rf $(DIST_ARCHIVES) \
+ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck
+ $(am__remove_distdir)
+ @(echo "$(distdir) archives ready for distribution: "; \
+ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
+ sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x'
+distuninstallcheck:
+ @cd $(distuninstallcheck_dir) \
+ && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \
+ || { echo "ERROR: files left after uninstall:" ; \
+ if test -n "$(DESTDIR)"; then \
+ echo " (check DESTDIR support)"; \
+ fi ; \
+ $(distuninstallcheck_listfiles) ; \
+ exit 1; } >&2
+distcleancheck: distclean
+ @if test '$(srcdir)' = . ; then \
+ echo "ERROR: distcleancheck can only run from a VPATH build" ; \
+ exit 1 ; \
+ fi
+ @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
+ || { echo "ERROR: files left in build directory after distclean:" ; \
+ $(distcleancheck_listfiles) ; \
+ exit 1; } >&2
+check-am: all-am
+check: check-recursive
+all-am: Makefile
+installdirs: installdirs-recursive
+installdirs-am:
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-recursive
+ -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-hdr \
+ distclean-libtool distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-recursive
+
+install-exec-am:
+
+install-html: install-html-recursive
+
+install-info: install-info-recursive
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-ps: install-ps-recursive
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+ -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+ -rm -rf $(top_srcdir)/autom4te.cache
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) install-am \
+ install-strip
+
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+ all all-am am--refresh check check-am clean clean-generic \
+ clean-libtool ctags ctags-recursive dist dist-all dist-bzip2 \
+ dist-gzip dist-lzma dist-shar dist-tarZ dist-zip distcheck \
+ distclean distclean-generic distclean-hdr distclean-libtool \
+ distclean-tags distcleancheck distdir distuninstallcheck dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs installdirs-am \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags tags-recursive uninstall uninstall-am
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/libs/libtpl-1.5/README b/libs/libtpl-1.5/README
new file mode 100755
index 0000000000..aefeea2ed4
--- /dev/null
+++ b/libs/libtpl-1.5/README
@@ -0,0 +1,56 @@
+tpl: fast, easy serialization in C
+==============================================================================
+
+Documentation for tpl is available in the doc/ directory or at:
+
+ http://tpl.sourceforge.net
+
+You can build tpl as a library, like so:
+
+ ./configure
+ make
+ make install
+
+This installs libtpl.so and libtpl.a into a standard system library directory.
+You can customize the install directory using configure's "--prefix" option:
+
+ ./configure --prefix=/some/directory
+
+For other options accepted by configure, run "./configure --help".
+
+NON-LIBRARY OPTION
+------------------
+Alternatively, if you don't want to muck around with libraries, you can simply
+copy these two files into your own C project and build them with your program:
+
+ src/tpl.h
+ src/tpl.c
+
+WINDOWS
+-------
+You can build tpl as a DLL under Visual Studio 2008. Or you can use MinGW or
+Cygwin.
+
+SELF-TEST SUITE
+---------------
+The automated self-test can be run by doing:
+
+ cd tests
+ make
+
+LICENSE
+-------
+The BSD license applies to this software. The text is in the LICENSE file.
+
+CREDITS
+-------
+Many people have contributed to tpl, both bits of code and ideas. Rather than
+listing them all here, at risk of omitting anyone- I just wish to say thank
+you. Some particular features are noted with contributors' names in the
+ChangeLog.
+
+Feel free to send me questions, comments or bug reports.
+
+Troy D. Hanson, February 5, 2010
+thanson@users.sourceforge.net
+
diff --git a/libs/libtpl-1.5/bootstrap b/libs/libtpl-1.5/bootstrap
new file mode 100755
index 0000000000..d717c2b87a
--- /dev/null
+++ b/libs/libtpl-1.5/bootstrap
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+# THIS SCRIPT IS FOR PROJECT MAINTAINER ONLY
+# It is executed only to generate "configure"
+
+set -x
+aclocal -I config
+autoheader
+libtoolize --copy --force
+automake --foreign --add-missing --copy
+autoconf
diff --git a/libs/libtpl-1.5/configure.ac b/libs/libtpl-1.5/configure.ac
new file mode 100755
index 0000000000..3d2fe0e7b6
--- /dev/null
+++ b/libs/libtpl-1.5/configure.ac
@@ -0,0 +1,28 @@
+AC_PREREQ(2.59)
+
+AC_INIT([libtpl], [1.4], [thanson@users.sourceforge.net])
+AC_CONFIG_SRCDIR(src/tpl.c)
+AC_CONFIG_AUX_DIR(config)
+AC_CONFIG_HEADERS(config/config.h)
+AM_INIT_AUTOMAKE
+AC_PROG_CC
+dnl next 4 lines are a hack to avoid libtool's
+dnl needless checks for C++ and Fortran compilers
+m4_undefine([AC_PROG_CXX])
+m4_defun([AC_PROG_CXX],[])
+m4_undefine([AC_PROG_F77])
+m4_defun([AC_PROG_F77],[])
+AC_PROG_LIBTOOL
+
+dnl detect Cygwin or MinGW and use mmap family replacements
+AC_CONFIG_LIBOBJ_DIR(src/win)
+case $host in
+ *-*-mingw32* | *-*-cygwin* | *-*-windows*)
+ AC_LIBOBJ(mmap)
+ AC_MSG_NOTICE([using custom mmap for Cygwin/MinGW])
+ ;;
+esac
+
+AC_CONFIG_FILES(src/win/Makefile src/Makefile Makefile)
+AC_OUTPUT
+
diff --git a/libs/libtpl-1.5/doc/Makefile b/libs/libtpl-1.5/doc/Makefile
new file mode 100755
index 0000000000..eaa3d499c9
--- /dev/null
+++ b/libs/libtpl-1.5/doc/Makefile
@@ -0,0 +1,26 @@
+all: css userguide pdf changelog perl
+
+userguide: txt/userguide.txt
+ asciidoc --unsafe --out-file=html/userguide.html -a linkcss=1 -a theme=tdh txt/userguide.txt
+
+changelog: txt/ChangeLog.txt
+ asciidoc --out-file=html/ChangeLog.html txt/ChangeLog.txt
+
+.PHONY: pdf
+
+pdf: txt/userguide.txt
+ a2x -f pdf $<
+ mv txt/userguide.pdf pdf/
+ cd html && ln -sf ../pdf/userguide.pdf userguide.pdf
+ rm txt/userguide.xml
+
+perl: txt/perl.txt
+ asciidoc --unsafe --out-file=html/perl.html -a linkcss=1 -a theme=tdh txt/perl.txt
+
+css: html/toc.css
+ cat /etc/asciidoc/stylesheets/xhtml11.css html/toc.css > html/tdh.css
+ cp /etc/asciidoc/stylesheets/xhtml11-quirks.css html/tdh-quirks.css
+
+docbook: txt/userguide.txt
+ asciidoc -b docbook --out-file=/tmp/userguide.xml txt/userguide.txt
+ xmlto -o html html-nochunks /tmp/userguide.xml
diff --git a/libs/libtpl-1.5/doc/NOTES b/libs/libtpl-1.5/doc/NOTES
new file mode 100755
index 0000000000..9133089b74
--- /dev/null
+++ b/libs/libtpl-1.5/doc/NOTES
@@ -0,0 +1,11 @@
+# maintainer notes
+
+# IE6 png gamma bug:
+# PNG images in IE6 display with wrong background colors,
+# solution: save PNG in Gimp *Without save gamma checked*
+
+#update sourceforge web site:
+#cd html
+#scp *.{html,css} thanson@shell.sourceforge.net:/home/groups/t/tp/tpl/htdocs
+#cd img
+#scp *.png *.jpg thanson@shell.sourceforge.net:/home/groups/t/tp/tpl/htdocs/img
diff --git a/libs/libtpl-1.5/doc/html/ChangeLog.html b/libs/libtpl-1.5/doc/html/ChangeLog.html
new file mode 100755
index 0000000000..a051e60c0d
--- /dev/null
+++ b/libs/libtpl-1.5/doc/html/ChangeLog.html
@@ -0,0 +1,602 @@
+
+
+
+
+
+
+
The Perl API for reading and writing tpl is nearly identical to the C API. This
+document will briefly explain the Perl API and provide examples. The chief
+motivation for having a Perl API is to communicate with C programs that use tpl.
+
+
+
+ Tip
+ |
+
+ Start with the C API This document assumes familiarity with the C API. The concepts of using tpl
+are not explained here. For an introduction to tpl and its C API, see the
+User Guide. |
+
+
+
Tpl.pm
+
The Tpl.pm file (in the lang/perl) directory contains the Perl module. You
+can copy it to another directory if you wish. Your Perl program may need to
+include a use lib statement to find the module.
+
+
+
#!/usr/bin/perl
+use lib "/some/directory";
+use Tpl;
+
+
tpl_map
+
This function resembles the C version, except that it’s invoked via the Tpl
+module, and it takes references to Perl variables after the format string.
+
+
+
my $i;
+my $tpl = Tpl->tpl_map("A(i)",\$i);
+
+
The return value is a tpl object; all other API calls are object methods.
+Incidentally, there is no tpl_free() method corresponding to the C API.
+
Fixed-length arrays
+
Format strings such as i# denote a fixed-length array. In the Perl API,
+fixed-length arrays require two arguments: a list reference, and the fixed
+length. For example:
+
+
+
my @x;
+my $tpl = Tpl->tpl_map("i#", \@x, 10);
+
+
When fixed-length arrays are packed or unpacked, the specified number of
+elements will be copied from (or placed into) the designated list.
+
Structures
+
Format strings containing S(…) are handled in the Perl API as if only the
+interior, parenthesized part was present. (It does not work like the C API). So
+simply ignore the S(…) and consider only its interior format characters when
+constructing the argument list:
+
+
+
my ($str, $int);
+my $tpl = Tpl->tpl_map("S(si)", \$str, \$int);
+
+
It really only makes sense to use S(…) in a format string in the Perl API if
+you are communicating with a C program that uses structures.
+
tpl_pack
+
This is nearly identical to the C version. The only argument is the index
+number to pack.
+
+
tpl_dump
+
This method is a little different than the C version. Given no arguments, it
+returns the tpl image; given one argument it writes a file with that name.
+
+
+
$tpl->tpl_dump("demo.tpl"); # writes demo.tpl
+
+
+
+
+
my $img = $tpl->tpl_dump();
+
+
The tpl image is a binary buffer. You can do whatever you want with it, such as
+write it to a socket or pipe (probably to C program listening on the other end),
+or save it somewhere and later re-load it using tpl_load().
+
tpl_load
+
This method loads a tpl image from a file or from a Perl variable. It takes
+one argument. If it’s not a reference, it’s assumed to be a filename to load.
+
+
+
$tpl->tpl_load("demo.tpl");
+
+
Otherwise, if the argument is a Perl reference, it’s construed as a variable
+containing the tpl image:
+
+
+
$tpl->tpl_load(\$img);
+
+
The method will die if the image is invalid or the file doesn’t exist. You
+can wrap it with eval to catch such errors:
+
+
+
eval { $tpl->tpl_load(\$img); };
+print "failed to load\n" if $@;
+
+
tpl_unpack
+
This is nearly identical to the C version. The only argument is the index
+number to unpack.
+
+
+
+
Integer array
+
+
Packing A(i) to file
+
+
#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Tpl;
+
+my $i;
+my $tpl = Tpl->tpl_map("A(i)",\$i);
+for($i=0; $i<10; $i++) {
+ $tpl->tpl_pack(1);
+}
+$tpl->tpl_dump("demo.tpl");
+
+
+
Unpacking A(i) from file
+
+
#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Tpl;
+
+my $j;
+my $tpl2 = Tpl->tpl_map("A(i)",\$j);
+$tpl2->tpl_load("demo.tpl");
+while($tpl2->tpl_unpack(1) > 0) {
+ print "$j\n";
+}
+
+
Message-passing
+
While the bulk of this example is socket handling, it demonstrates how you can
+use tpl as a message-passing format. In the real-world, you might have a C
+server and a Perl client, for example. In this example, we’ll code both a client
+and a server in Perl.
+
+
Server
+
The server waits for a connection from a client. When it gets one, it accepts
+the connection and immediately forks a child process to handle it. Then it goes
+back to waiting for another new connection.
+
The server child process handles the client by loading and unpacking the tpl
+image sent by the client (containing an array of integers). It calculates their
+sum and constructs a new tpl image containing the sum, which it sends back to
+the client.
+
+
Server
+
+
#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use IO::Socket::INET;
+use Tpl;
+
+$SIG{CHLD} = "IGNORE"; # don't create zombies
+
+our $port = 2000;
+
+sub handle_client {
+ my $client = shift;
+
+ undef $/;
+ my $request = <$client>; # get request (slurp)
+
+ # read input array, and calculate total
+ my ($i,$total);
+ my $tpl = Tpl->tpl_map("A(i)", \$i);
+ eval { $tpl->tpl_load(\$request); };
+ die "received invalid tpl" if $@;
+ $total += $i while $tpl->tpl_unpack(1) > 0;
+
+ # formulate response and send
+ my $tpl2 = Tpl->tpl_map("i", \$total);
+ $tpl2->tpl_pack(0);
+ my $response = $tpl2->tpl_dump();
+ print $client $response;
+ close $client;
+}
+
+my $server = IO::Socket::INET->new(LocalPort => $port,
+ Type => SOCK_STREAM,
+ Reuse => 1,
+ Listen => 10 )
+ or die "Can't listen on port $port: $!\n";
+
+while (1) {
+ my $client = $server->accept();
+ next unless $client;
+ # new connection
+ my $pid = fork;
+ die "can't fork: $!\n" unless defined $pid;
+ if ($pid > 0) {
+ # parent
+ close $client;
+ } elsif ($pid == 0) {
+ # child
+ handle_client($client);
+ exit(0);
+ }
+}
+close ($server);
+
+
Client
+
The client is a simpler program. It constructs the tpl image containing the
+integer array (taken from its command-line arguments), connects to the server
+and sends the tpl image to it, and then awaits the response tpl. The response
+containing the sum is loaded, unpacked and printed.
+
+
Client
+
+
#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use IO::Socket::INET;
+use Tpl;
+
+our $port = 2000;
+
+# construct tpl
+my $i;
+my $tpl = Tpl->tpl_map("A(i)",\$i);
+$tpl->tpl_pack(1) while ($i=shift @ARGV);
+my $request = $tpl->tpl_dump();
+
+# send to server, get response
+my $socket = IO::Socket::INET->new("localhost:$port") or die "can't connect";
+print $socket $request;
+shutdown($socket,1); # done writing (half-close)
+undef $/;
+my $response = <$socket>; # get reply (slurp)
+
+# decode response (or print error)
+my $total;
+my $tpl2 = Tpl->tpl_map("i", \$total);
+eval { $tpl2->tpl_load(\$response); };
+die "invalid response\n" if $@;
+$tpl2->tpl_unpack(0);
+print "total is $total\n";
+
+
Running thise example
+
If the client and server programs are in client.pl and server.pl, then
+you can run the example by starting the server in one window:
+
+
Then run the client in another window. E.g.,
+
+
The client runs and then exits, printing:
+
+
You can re-run the client with different arguments. When done, type Ctrl-C in
+the server window to terminate it.
+
+
+
+
diff --git a/libs/libtpl-1.5/doc/html/styles.css b/libs/libtpl-1.5/doc/html/styles.css
new file mode 100755
index 0000000000..c23156eee9
--- /dev/null
+++ b/libs/libtpl-1.5/doc/html/styles.css
@@ -0,0 +1,160 @@
+#banner {
+ /* font-size: x-large; */
+ /* background: #ff00ff; */
+ /* height: 100px; */
+}
+
+#topnav {
+ /* background-image: url(img/grad_topnav.png); */
+ /* background-repeat: repeat-y; */
+ /* background-color: #af00af; */
+ /* height: 25px; */
+ margin: 10px 0px 10px 20px;
+ padding: 3px;
+ font-size: 9pt;
+ font-family: sans-serif;
+ /* border-style: solid; */
+ /* border-width: 1px; */
+}
+
+
+#topnav {font-weight: bold}
+#topnav a {font-weight: normal}
+
+h1,p { margin: 0; } /* non-0 margin on firefox */
+
+#mid {
+ background-image: url(img/grad_azure.png);
+ background-repeat: repeat-y;
+ /* background-color: #ffddaa; */
+ padding-top: 20px;
+ margin-bottom: 10px;
+}
+
+#mid img {
+ padding-left: 10px;
+ vertical-align: middle;
+}
+
+a img {
+ border: 0
+}
+
+#nav {
+ background-color: #fff8f1;
+ margin-left: 10px;
+ margin-top: 20px;
+ float: left;
+ padding: 10px;
+ border-style: solid;
+ border-width: 2px;
+ font-family: sans-serif;
+}
+
+
+#nav h2 {
+ font-weight: bold;
+ font-size: 10pt;
+}
+
+#nav h3 {
+ /* font-weight: bold; */
+ padding-left: 5px;
+ /* font-style: oblique; */
+ font-family: sans-serif;
+ font-size: 7pt;
+}
+
+#nav div {
+ font-size: 9pt;
+ padding-left: 15px;
+}
+
+#main {
+ background: #ffffff;
+ margin-top: 20px;
+ margin-left: 170px;
+ padding-left: 20px;
+ height: 100%;
+ /* font-family: sans-serif; */
+}
+
+#main h1 {
+ font-family: sans-serif;
+}
+
+
+.listing {
+ margin: 20px;
+ font-family: sans-serif;
+ font-weight: bold;
+}
+
+.code {
+ padding: 10px;
+ background: #f3f3f3;
+ font-size: 8pt;
+ font-weight: normal;
+ width: 80%;
+ border-style: solid;
+ border-width: 1px;
+}
+
+.code pre {
+ padding-left: 20px;
+ padding-right: 80px;
+}
+
+#formatstrings {
+ margin: 20px;
+}
+
+#footer {
+ /* background: #00ffff; */
+ margin-top: 5px;
+ font-size: small;
+ font-family: sans-serif;
+}
+
+em {
+ font-weight: bold;
+}
+
+hr {
+ height: 0.04em;
+ background: black;
+ margin: 0 10% 0 0;
+}
+
+#footer img {
+ margin-right: 5px;
+ float: right;
+}
+
+.lead {
+ font-family: sans-serif;
+ font-size: larger;
+ font-weight: bold;
+ /* font-style: oblique; */
+ margin: 30px 30px 30px 0px;
+ color: #1122dd;
+}
+
+ol {
+ font-family: monospace;
+ background: #dddddd;
+ padding-top: 10px;
+ padding-bottom: 10px;
+ width: 80%;
+ border-width: 1px;
+ border-style: solid;
+ /* font-size: smaller; */
+}
+
+#main #portrait {
+ float: right;
+ font-size: smaller;
+ font-family: sans-serif;
+ text-align: center;
+ margin: 10px;
+}
diff --git a/libs/libtpl-1.5/doc/html/tdh-quirks.css b/libs/libtpl-1.5/doc/html/tdh-quirks.css
new file mode 100755
index 0000000000..7478972ce1
--- /dev/null
+++ b/libs/libtpl-1.5/doc/html/tdh-quirks.css
@@ -0,0 +1,31 @@
+/* Workarounds for IE6's broken and incomplete CSS2. */
+
+div.sidebar-content {
+ background: #ffffee;
+ border: 1px solid silver;
+ padding: 0.5em;
+}
+div.sidebar-title, div.image-title {
+ font-family: sans-serif;
+ font-weight: bold;
+ margin-top: 0.0em;
+ margin-bottom: 0.5em;
+}
+
+div.listingblock div.content {
+ border: 1px solid silver;
+ background: #f4f4f4;
+ padding: 0.5em;
+}
+
+div.quoteblock-content {
+ padding-left: 2.0em;
+}
+
+div.exampleblock-content {
+ border-left: 2px solid silver;
+ padding-left: 0.5em;
+}
+
+/* IE6 sets dynamically generated links as visited. */
+div#toc a:visited { color: blue; }
diff --git a/libs/libtpl-1.5/doc/html/tdh.css b/libs/libtpl-1.5/doc/html/tdh.css
new file mode 100755
index 0000000000..b9679f31ff
--- /dev/null
+++ b/libs/libtpl-1.5/doc/html/tdh.css
@@ -0,0 +1,301 @@
+/* Debug borders */
+p, li, dt, dd, div, pre, h1, h2, h3, h4, h5, h6 {
+/*
+ border: 1px solid red;
+*/
+}
+
+body {
+ margin: 1em 5% 1em 5%;
+}
+
+a {
+ color: blue;
+ text-decoration: underline;
+}
+a:visited {
+ color: fuchsia;
+}
+
+em {
+ font-style: italic;
+}
+
+strong {
+ font-weight: bold;
+}
+
+tt {
+ color: navy;
+}
+
+h1, h2, h3, h4, h5, h6 {
+ color: #527bbd;
+ font-family: sans-serif;
+ margin-top: 1.2em;
+ margin-bottom: 0.5em;
+ line-height: 1.3;
+}
+
+h1, h2, h3 {
+ border-bottom: 2px solid silver;
+}
+h2 {
+ padding-top: 0.5em;
+}
+h3 {
+ float: left;
+}
+h3 + * {
+ clear: left;
+}
+
+div.sectionbody {
+ font-family: serif;
+ margin-left: 0;
+}
+
+hr {
+ border: 1px solid silver;
+}
+
+p {
+ margin-top: 0.5em;
+ margin-bottom: 0.5em;
+}
+
+pre {
+ padding: 0;
+ margin: 0;
+}
+
+span#author {
+ color: #527bbd;
+ font-family: sans-serif;
+ font-weight: bold;
+ font-size: 1.1em;
+}
+span#email {
+}
+span#revision {
+ font-family: sans-serif;
+}
+
+div#footer {
+ font-family: sans-serif;
+ font-size: small;
+ border-top: 2px solid silver;
+ padding-top: 0.5em;
+ margin-top: 4.0em;
+}
+div#footer-text {
+ float: left;
+ padding-bottom: 0.5em;
+}
+div#footer-badges {
+ float: right;
+ padding-bottom: 0.5em;
+}
+
+div#preamble,
+div.tableblock, div.imageblock, div.exampleblock, div.verseblock,
+div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,
+div.admonitionblock {
+ margin-right: 10%;
+ margin-top: 1.5em;
+ margin-bottom: 1.5em;
+}
+div.admonitionblock {
+ margin-top: 2.5em;
+ margin-bottom: 2.5em;
+}
+
+div.content { /* Block element content. */
+ padding: 0;
+}
+
+/* Block element titles. */
+div.title, caption.title {
+ font-family: sans-serif;
+ font-weight: bold;
+ text-align: left;
+ margin-top: 1.0em;
+ margin-bottom: 0.5em;
+}
+div.title + * {
+ margin-top: 0;
+}
+
+td div.title:first-child {
+ margin-top: 0.0em;
+}
+div.content div.title:first-child {
+ margin-top: 0.0em;
+}
+div.content + div.title {
+ margin-top: 0.0em;
+}
+
+div.sidebarblock > div.content {
+ background: #ffffee;
+ border: 1px solid silver;
+ padding: 0.5em;
+}
+
+div.listingblock {
+ margin-right: 0%;
+}
+div.listingblock > div.content {
+ border: 1px solid silver;
+ background: #f4f4f4;
+ padding: 0.5em;
+}
+
+div.quoteblock > div.content {
+ padding-left: 2.0em;
+}
+
+div.attribution {
+ text-align: right;
+}
+div.verseblock + div.attribution {
+ text-align: left;
+}
+
+div.admonitionblock .icon {
+ vertical-align: top;
+ font-size: 1.1em;
+ font-weight: bold;
+ text-decoration: underline;
+ color: #527bbd;
+ padding-right: 0.5em;
+}
+div.admonitionblock td.content {
+ padding-left: 0.5em;
+ border-left: 2px solid silver;
+}
+
+div.exampleblock > div.content {
+ border-left: 2px solid silver;
+ padding: 0.5em;
+}
+
+div.verseblock div.content {
+ white-space: pre;
+}
+
+div.imageblock div.content { padding-left: 0; }
+div.imageblock img { border: 1px solid silver; }
+span.image img { border-style: none; }
+
+dl {
+ margin-top: 0.8em;
+ margin-bottom: 0.8em;
+}
+dt {
+ margin-top: 0.5em;
+ margin-bottom: 0;
+ font-style: italic;
+}
+dd > *:first-child {
+ margin-top: 0;
+}
+
+ul, ol {
+ list-style-position: outside;
+}
+div.olist2 ol {
+ list-style-type: lower-alpha;
+}
+
+div.tableblock > table {
+ border: 3px solid #527bbd;
+}
+thead {
+ font-family: sans-serif;
+ font-weight: bold;
+}
+tfoot {
+ font-weight: bold;
+}
+
+div.hlist {
+ margin-top: 0.8em;
+ margin-bottom: 0.8em;
+}
+div.hlist td {
+ padding-bottom: 5px;
+}
+td.hlist1 {
+ vertical-align: top;
+ font-style: italic;
+ padding-right: 0.8em;
+}
+td.hlist2 {
+ vertical-align: top;
+}
+
+@media print {
+ div#footer-badges { display: none; }
+}
+
+div#toctitle {
+ color: #527bbd;
+ font-family: sans-serif;
+ font-size: 1.1em;
+ font-weight: bold;
+ margin-top: 1.0em;
+ margin-bottom: 0.1em;
+}
+
+div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 {
+ margin-top: 0;
+ margin-bottom: 0;
+}
+div.toclevel2 {
+ margin-left: 2em;
+ font-size: 0.9em;
+}
+div.toclevel3 {
+ margin-left: 4em;
+ font-size: 0.9em;
+}
+div.toclevel4 {
+ margin-left: 6em;
+ font-size: 0.9em;
+}
+#toc {
+ float: right;
+ font-family: sans-serif;
+ border: 1px solid #000;
+ margin: 0px 0px 20px 20px;
+ padding: 0px;
+ background: #f0f0f0;
+ font-size: 80%;
+}
+
+#toc #hdr {
+ color:#ffffff;
+ background:#98b1c4;
+ text-align:center;
+ margin-bottom:5px;
+}
+
+a img {
+ border: 0
+}
+
+#toc a:visited, #toc a:link { color:#000; text-decoration: none }
+#toc a:hover { color:#00f; text-decoration: underline; }
+
+#toc .level2 { margin-left: 1em; margin-top: 2px; margin-bottom: 2px; text-decoration: underline; }
+#toc .level3 { margin-left: 2em; font-size: 0.8em }
+
+.toplink {
+ float: right;
+ font-size: 50%;
+ cursor: pointer;
+}
+
+#topnav {font-weight: bold}
+#topnav a {font-weight: normal}
diff --git a/libs/libtpl-1.5/doc/html/toc.css b/libs/libtpl-1.5/doc/html/toc.css
new file mode 100755
index 0000000000..ae3363ee51
--- /dev/null
+++ b/libs/libtpl-1.5/doc/html/toc.css
@@ -0,0 +1,35 @@
+#toc {
+ float: right;
+ font-family: sans-serif;
+ border: 1px solid #000;
+ margin: 0px 0px 20px 20px;
+ padding: 0px;
+ background: #f0f0f0;
+ font-size: 80%;
+}
+
+#toc #hdr {
+ color:#ffffff;
+ background:#98b1c4;
+ text-align:center;
+ margin-bottom:5px;
+}
+
+a img {
+ border: 0
+}
+
+#toc a:visited, #toc a:link { color:#000; text-decoration: none }
+#toc a:hover { color:#00f; text-decoration: underline; }
+
+#toc .level2 { margin-left: 1em; margin-top: 2px; margin-bottom: 2px; text-decoration: underline; }
+#toc .level3 { margin-left: 2em; font-size: 0.8em }
+
+.toplink {
+ float: right;
+ font-size: 50%;
+ cursor: pointer;
+}
+
+#topnav {font-weight: bold}
+#topnav a {font-weight: normal}
diff --git a/libs/libtpl-1.5/doc/html/userguide.html b/libs/libtpl-1.5/doc/html/userguide.html
new file mode 100755
index 0000000000..368a605f20
--- /dev/null
+++ b/libs/libtpl-1.5/doc/html/userguide.html
@@ -0,0 +1,1539 @@
+
+
+
+
+
+
+
Serialization in C
+
Tpl is a library for serializing C data. The data is stored in its natural
+binary form. The API is small and tries to stay "out of the way".
+Tpl can serialize many C data types, including structures.
+
Uses for tpl
+
Tpl makes a convenient file format. For example, suppose a program needs to
+store a list of user names and ids. This can be expressed using the format
+string A(si). If the program needs two such lists (say, one for regular
+users and one for administrators) this could be expressed as A(si)A(si). It
+is easy to read and write this kind of structured data using tpl.
+
Tpl can also be used as an IPC message format. It handles byte order issues
+and deframing individual messages off of a stream automatically.
+
Expressing type
+
The "data type" of a tpl is explicitly stated as a format string. There is
+never any ambiguity about the type of data stored in a tpl. Some examples:
+
+-
+
+A(is) is a variable-length array of integer-string pairs
+
+
+-
+
+A(is)A(is) are two such arrays, completely independent of one another
+
+
+-
+
+S(ci) is a structure containing a char and integer
+
+
+-
+
+S(ci)# is a fixed-length array of the latter structure
+
+
+-
+
+A(A(i)) is a nested array, that is, an array of integer arrays
+
+
+
+
The tpl image
+
A tpl image is the serialized form of a tpl, stored in a memory buffer or file,
+or written to a file descriptor.
+
What’s in a tpl image?
+
There is no need to understand the internal structure of the tpl image. But for the
+curious, the image is a strictly defined binary buffer having two sections,
+a header and the data. The header encodes the length of the image, its
+format string, endian order and other flags. The data section contains the
+packed data.
+
No framing needed
+
A property of the tpl image is that consecutive images can be written to a stream
+without requiring any delimiter between them. The reader making use of
+tpl_gather (or tpl_load in TPL_FD mode) will obtain exactly one tpl image at
+a time. Therefore tpl images can be used as an IPC message format without any
+higher-level framing protocol.
+
Data portability
+
A tpl image generated on one kind of CPU will generally be portable to other
+CPU types when tpl is used properly. This may be a surprise considering that
+tpl is a binary format. But tpl has been carefully designed to make this work.
+Each format character has an associated explicitly-sized type. For
+integer and floating point types, whose "endian" or byte-order convention varies
+from one CPU to another, tpl automatically and transparently corrects the
+endian order (if needed) during the unpacking process. Floating point numbers
+present their own special difficulties. No guarantees
+are made with regard to floating point portability. That said, because many
+modern CPU’s use IEEE 754 floating point representation, data is likely to be
+portable among them.
+
XML and Perl
+
Note: The tplxml utility and the Perl module are currently unsupported in tpl 1.5.
+
XML
+
While a tpl image is a binary entity, you can view any tpl image in XML format
+using the included tplxml utility, located in the lang/perl directory.
+
+
+
tplxml file.tpl > file.xml
+tplxml file.xml > file.tpl
+
+
The utility is bidirectional, as shown. The file extension is not important;
+tplxml inspects its input to see if it’s tpl or XML. You can also pipe data
+into it instead of giving it a filename. The tplxml utility is slow. Its
+purpose is two-fold: debugging (manual inspection of the data in a tpl), and
+interoperability with XML-based programs. The resulting XML is often ten times
+the size of the original binary tpl image.
+
Perl
+
There is a Perl module in lang/perl/Tpl.pm. The Perl API
+is convenient for writing Perl scripts that interoperate with C programs, and
+need to pass structured data back and forth. It is written in pure Perl.
+
+
The tpl software was developed for POSIX systems and has been tested on 32- and 64-bit
+platforms including:
+
+
BSD licensed
+
+
Download
+
Please follow the link to download on the
+tpl website.
+
Getting help
+
+
Resources
+
+
+
+
Tpl has no dependencies on libraries other than the system C library. You
+can simply copy the tpl source into your project, so you have no dependencies.
+Alternatively, you can build tpl as a library and link it to your program.
+
As source
+
The simplest way to use tpl is to copy the source files tpl.h and tpl.c
+(from the src/ directory) right into your project, and build them with the
+rest of your source files. No special compiler flags are required.
+
As a library
+
Alternatively, to build tpl as a library, from the top-level directory, run:
+
+
+
./configure
+make
+make install
+
+
This installs a static library libtpl.a and a shared library (e.g.,
+libtpl.so), if your system supports them, in standard places. The installation
+directory can be customized using ./configure --prefix=/some/directory. Run
+configure --help for further options.
+
Test suite
+
You can compile and run the built-in test suite by running:
+
+
On Windows
+
DLL
+
On the tpl home page, a Visual Studio 2008 solution package is available for
+download. This zip file contains pre-built 32- and 64-bit versions of tpl as a
+DLL. If you like, you can build the DLL yourself using VS2008 or VS2010 (the
+free Express Edition is sufficient) by opening the solution file and choosing
+Build Solution.
+
Non-DLL usage
+
Alternatively, tpl can be used directly (instead of as a DLL) by compiling
+the tpl sources right into your program. To do this, add tpl.c, tpl.h,
+win/mman.h and win/mmap.c to your program’s source and header files and
+add the preprocessor definition TPL_NOLIB.
+
MinGW/Cygwin
+
Prior to tpl release 1.5, using tpl on Windows required building it with MinGW
+or Cygwin. This is no longer necessary. If you want to build it that way anyway,
+use the non-Windows (i.e. tar.bz2) tpl download and follow the "configure; make;
+make install" approach.
+
+
+
To use tpl, you need to know the order in which to call the API functions, and
+the background concepts of format string, arrays and index numbers.
+
Order of functions
+
Creating a tpl is always the first step, and freeing it is the last step. In
+between, you either pack and dump the tpl (if you’re serializing data) or you
+load a tpl image and unpack it (if you’re deserializing data).
+
+
+Order of usage
+
+
+
+
+
+Step |
+ If you’re serializing… |
+ If you’re deserializing… |
+
+
+
+
+1. |
+tpl_map() |
+tpl_map() |
+
+
+2. |
+tpl_pack() |
+tpl_load() |
+
+
+3. |
+tpl_dump() |
+tpl_unpack() |
+
+
+4. |
+tpl_free() |
+tpl_free() |
+
+
+
+
+
+
When a tpl is created using tpl_map(), its data type is expressed as a format
+string. Each character in the format string has an associated argument of a
+specific type. For example, this is how a format string and its arguments are
+passed in to tpl_map:
+
+
+
tpl_node *tn;
+char c;
+int i[10];
+tn = tpl_map("ci#", &c, i, 10); /* ci# is our format string */
+
+
+
+Supported format characters
+
+
+
+
+
+Type |
+ Description |
+ Required argument type |
+
+
+
+
+j |
+16-bit signed int |
+int16_t* or equivalent |
+
+
+v |
+16-bit unsigned int |
+uint16_t* or equivalent |
+
+
+i |
+32-bit signed int |
+int32_t* or equivalent |
+
+
+u |
+32-bit unsigned int |
+uint32_t* or equivalent |
+
+
+I |
+64-bit signed int |
+int64_t* or equivalent |
+
+
+U |
+64-bit unsigned int |
+uint64_t* or equivalent |
+
+
+c |
+character (byte) |
+char* |
+
+
+s |
+string |
+char** |
+
+
+f |
+64-bit double precision float |
+double* (varies by platform) |
+
+
+# |
+array length; modifies preceding iujvIUcsf or S(…) |
+int |
+
+
+B |
+binary buffer (arbitrary-length) |
+tpl_bin* |
+
+
+S |
+structure (…) |
+struct * |
+
+
+$ |
+nested structure (…) |
+none |
+
+
+A |
+array (…) |
+none |
+
+
+
+
+
Explicit sizes
+
The sizes of data types such as long and double vary by platform. This must
+be kept in mind because most tpl format characters require a pointer argument to
+a specific-sized type, listed above. You can use explicit-sized types such as
+int32_t (defined in inttypes.h) in your program if you find this helpful.
+
The trouble with double
+
Unfortunately there are no standard explicit-sized floating-point types-- no
+float64_t, for example. If you plan to serialize double on your platform
+using tpl’s f format character, first be sure that your double is 64 bits.
+Second, if you plan to deserialize it on a different kind of CPU, be sure that
+both CPU’s use the same floating-point representation such as IEEE 754.
+
Arrays
+
Arrays come in two kinds: fixed-length and variable-length arrays.
+Intuitively, they can be thought of like conventional C arrays and linked lists.
+In general, use fixed-length arrays if possible, and variable-length arrays
+if necessary. The variable-length arrays support more complex data types, and
+give or receive the elements to your program one by one.
+
Fixed-length vs. Variable-length arrays
+
+-
+Notation
+
+-
+
+ Fixed-length arrays are denoted like i# (a simple type followed by one or
+ more # signs), but variable-length arrays are denoted like A(i).
+
+
+-
+Element handling
+
+-
+
+ All the elements of a fixed-length array are packed or unpacked at once. But
+ the elements of a variable-length array are packed or unpacked one by one.
+
+
+-
+Array length
+
+-
+
+ The number of elements in a fixed-length array is specified before use--
+ before any data is packed. But variable-length arrays do not have a fixed
+ element count. They can have any number of elements packed into them. When
+ unpacking a variable-length array, they are unpacked one by one until they
+ are exhausted.
+
+
+-
+Element types
+
+-
+
+ Elements of fixed-length arrays can be the integer, byte, double, string
+ types or structures. (This excludes format characters BA). Fixed-length
+ arrays can also be multi-dimensional like i##. Variable-length arrays can
+ have simple or complex elements-- for example, an array of ints A(i), an
+ array of int/double pairs A(if), or even nested arrays like A(A(if)).
+
+
+
+
Before explaining all the concepts, it’s illustrative to see how both kinds of
+arrays are used. Let’s pack the integers 0 through 9 both ways.
+
+
Packing 0-9 as a fixed-length array
+
+
#include "tpl.h"
+int main() {
+ tpl_node *tn;
+ int x[] = {0,1,2,3,4,5,6,7,8,9};
+
+ tn = tpl_map("i#", x, 10);
+ tpl_pack(tn,0); /* pack all 10 elements at once */
+ tpl_dump(tn, TPL_FILE, "/tmp/fixed.tpl");
+ tpl_free(tn);
+}
+
+
Note that the length of the fixed-length array (10) was passed as an argument to
+tpl_map(). The corresponding unpacking example is listed
+further below. Now let’s see how we would pack 0-9 as a variable-length array:
+
+
Packing 0-9 as a variable-length array
+
+
#include "tpl.h"
+int main() {
+ tpl_node *tn;
+ int x;
+
+ tn = tpl_map("A(i)", &x);
+ for(x = 0; x < 10; x++) tpl_pack(tn,1); /* pack one element at a time */
+ tpl_dump(tn, TPL_FILE, "/tmp/variable.tpl");
+ tpl_free(tn);
+}
+
+
Notice how we called tpl_pack in a loop, once for each element 0-9. Again,
+there is a corresponding unpacking example shown later in the
+guide. You might also notice that this time, we passed 1 as the final argument
+to tpl_pack. This is an index number designating which variable-length array
+we’re packing. In this case, there is only one.
+
Index numbers
+
Index numbers identify a particular variable-length array in the format string.
+Each A(…) in a format string has its own index number. The index numbers
+are assigned left-to-right starting from 1. Examples:
+
+
+
A(i) /* index number 1 */
+A(i)A(i) /* index numbers 1 and 2 */
+A(A(i)) /* index numbers 1 and 2 (order is independent of nesting) */
+
+
Special index number 0
+
The special index number 0 designates all the format characters that are not
+inside an A(…). Examples of what index 0 does (and does not) designate:
+
+
+
S(ius) /* index 0 designates the whole thing */
+iA(c)u /* index 0 designates the i and the u */
+c#A(i)S(ci) /* index 0 designates the c# and the S(ci) */
+
+
An index number is passed to tpl_pack and tpl_unpack to specify which
+variable-length array (or non-array, in the case of index number 0) to act upon.
+
Integers
+
The array examples above demonstrated how integers could be
+packed. We’ll show some further examples here of unpacking integers and dealing
+with multi-dimensional arrays. The same program could be used to demonstrate
+working with byte, 16-bit shorts, 32-bit or 64-bit signed and unsigned integers
+with only a change to the data type and the format character.
+
+
Unpacking 0-9 from a fixed-length array
+
+
#include "tpl.h"
+int main() {
+ tpl_node *tn;
+ int x[10];
+
+ tn = tpl_map("i#", x, 10);
+ tpl_load(tn, TPL_FILE, "/tmp/fixed.tpl");
+ tpl_unpack(tn,0); /* unpack all 10 elements at once */
+ tpl_free(tn);
+ /* now do something with x[0]...x[9].. (not shown */
+}
+
+
For completeness, let’s also see how to unpack a variable-length integer array.
+
+
Unpacking 0-9 from a variable-length array
+
+
#include "tpl.h"
+int main() {
+ tpl_node *tn;
+ int x;
+
+ tn = tpl_map("A(i)", &x);
+ tpl_load(tn, TPL_FILE, "/tmp/variable.tpl");
+ while (tpl_unpack(tn,1) > 0) printf("%d\n",x); /* unpack one by one */
+ tpl_free(tn);
+}
+
+
Multi-dimensional arrays
+
A multi-dimensional matrix of integers can be packed and unpacked the same way
+as any fixed-length array.
+
+
+
int xy[XDIM][YDIM];
+...
+tn = tpl_map("i##", xy, XDIM, YDIM);
+tpl_pack(tn, 0);
+
+
This single call to tpl_pack packs the entire matrix.
+
Strings
+
Tpl can serialize C strings. A different format is used for char* vs. char[ ]
+as described below. Let’s look at char* first:
+
+
Packing a string
+
+
#include "tpl.h"
+
+ int main() {
+ tpl_node *tn;
+ char *s = "hello, world!";
+ tn = tpl_map("s", &s);
+ tpl_pack(tn,0); /* copies "hello, world!" into the tpl */
+ tpl_dump(tn,TPL_FILE,"string.tpl");
+ tpl_free(tn);
+ }
+
+
The char* must point to a null-terminated string or be a NULL pointer.
+
When deserializing (unpacking) a C string, space for it will be allocated
+automatically, but you are responsible for freeing it (unless it is NULL):
+
+
Unpacking a string
+
+
#include "tpl.h"
+
+ int main() {
+ tpl_node *tn;
+ char *s;
+ tn = tpl_map("s", &s);
+ tpl_load(tn,TPL_FILE,"string.tpl");
+ tpl_unpack(tn,0); /* allocates space, points s to "hello, world!" */
+ printf("unpacked %s\n", s);
+ free(s); /* our responsibility to free s */
+ tpl_free(tn);
+ }
+
+
char* vs char[ ]
+
The s format character is only for use with char* types. In the example
+above, s is a char*. If it had been a char s[14], we would use the format
+characters c# to pack or unpack it, as a fixed-length character array. (This
+unpacks the characters "in-place", instead of into a dynamically allocated
+buffer). Also, a fixed-length buffer described by c# need not be
+null-terminated.
+
Arrays of strings
+
You can use fixed- or variable-length arrays of strings in tpl. An example of
+packing a fixed-length two-dimensional array of strings is shown here.
+
+
+
char *labels[2][3] = { {"one", "two", "three"},
+ {"eins", "zwei", "drei" } };
+tpl_node *tn;
+tn = tpl_map("s##", labels, 2, 3);
+tpl_pack(tn,0);
+tpl_dump(tn,TPL_FILE,filename);
+tpl_free(tn);
+
+
Later, when unpacking these strings, the programmer must remember to free them
+one by one, after they are no longer needed.
+
+
+
char *olabels[2][3];
+int i,j;
+
+
+
+
tn = tpl_map("s##", olabels, 2, 3);
+tpl_load(tn,TPL_FILE,filename);
+tpl_unpack(tn,0);
+tpl_free(tn);
+
+
+
+
for(i=0;i<2;i++) {
+ for(j=0;j<3;j++) {
+ printf("%s\n", olabels[i][j]);
+ free(olabels[i][j]);
+ }
+}
+
+
Binary buffers
+
Packing an arbitrary-length binary buffer (tpl format character B) makes use
+of the tpl_bin structure. You must declare this structure and populate it
+with the address and length of the binary buffer to be packed.
+
+
Packing a binary buffer
+
+
#include "tpl.h"
+ #include <sys/time.h>
+
+ int main() {
+ tpl_node *tn;
+ tpl_bin tb;
+
+ /* we'll use a timeval as our guinea pig */
+ struct timeval tv;
+ gettimeofday(&tv,NULL);
+
+ tn = tpl_map( "B", &tb );
+ tb.sz = sizeof(struct timeval); /* size of buffer to pack */
+ tb.addr = &tv; /* address of buffer to pack */
+ tpl_pack( tn, 0 );
+ tpl_dump(tn, TPL_FILE, "bin.tpl");
+ tpl_free(tn);
+ }
+
+
When you unpack a binary buffer, tpl will automatically allocate it, and will
+populate your tpl_bin structure with its address and length. You are
+responsible for eventually freeing the buffer.
+
+
Unpacking a binary buffer
+
+
#include "tpl.h"
+
+ int main() {
+ tpl_node *tn;
+ tpl_bin tb;
+
+ tn = tpl_map( "B", &tb );
+ tpl_load( tn, TPL_FILE, "bin.tpl" );
+ tpl_unpack( tn, 0 );
+ tpl_free(tn);
+
+ printf("binary buffer of length %d at address %p\n", tb.sz, tb.addr);
+ free(tb.addr); /* our responsibility to free it */
+ }
+
+
Structures
+
You can use tpl to pack and unpack structures, and arrays of structures.
+
+
+
struct ci {
+ char c;
+ int i;
+};
+struct ci s = {'a', 1};
+
+
+
+
tn = tpl_map("S(ci)", &s); /* pass structure address */
+tpl_pack(tn, 0);
+tpl_dump(tn, TPL_FILE, "struct.tpl");
+tpl_free(tn);
+
+
As shown, omit the individual arguments for the format characters inside the
+parenthesis. The exception is for fixed-length arrays; when S(…) contains a
+# character, its length argument is required: tpl_map("S(f#i)", &s, 10);
+
When using the S(…) format, the only characters allowed inside the
+parentheses are iujvcsfIU#$().
+
Structure arrays
+
Arrays of structures are the same as simple arrays. Fixed- or variable- length
+arrays are supported.
+
+
+
struct ci sa[100], one;
+
+
+
+
tn = tpl_map("S(ci)#", sa, 100); /* fixed-length array of 100 structures */
+tn = tpl_map("A(S(ci))", &one); /* variable-length array (one at a time)*/
+
+
The differences between fixed- and variable-length arrays are explained in the
+Arrays section.
+
Nested structures
+
When dealing with nested structures, the outermost structure uses the S format
+character, and the inner nested structures use the $ format. Only the
+outermost structure’s address is given to tpl_map.
+
+
+
struct inner_t {
+ char a;
+}
+
+
+
+
struct outer_t {
+ char b;
+ struct inner_t i;
+}
+
+
+
+
tpl_node *tn;
+struct outer_t outer = {'b', {'a'}};
+
+
+
+
tn = tpl_map("S(c$(c))", &outer);
+
+
Structures can nest to any level. Currently tpl does not support fixed-length
+array suffixes on inner structures. However the outermost structure can have a
+length suffix even if it contains some nested structures.
+
Linked lists
+
While tpl has no specific data type for a linked list, the technique for
+packing them is illustrated here. First describe your list element as a
+format string and then surround it with A(…) to describe it as
+variable-length array. Then, using a temporary variable, iterate over each
+list element, copying it to the temporary variable and packing it.
+
+
+
struct element {
+ char c;
+ int i;
+ struct element *next;
+}
+
+
+
+
struct element *list, *i, tmp;
+tpl_node *tn;
+
+
+
+
/* add some elements to list.. (not shown)*/
+
+
+
+
tn = tpl_map("A(ci)", &tmp);
+for(i = list; i != NULL; i=i->next) {
+ tmp = *i;
+ tpl_pack(tn, 1);
+}
+tpl_dump(tn,TPL_FILE,"list.tpl");
+tpl_free(tn);
+
+
Unpacking is similar. The for loop is just replaced with:
+
+
+
while( tpl_unpack(tn,1) > 0) {
+ struct element *newelt = malloc(sizeof(struct element));
+ *newelt = tmp;
+ add_to_list(list, newelt);
+}
+
+
As you can see, tpl does not reinstate the whole list at once-- just one
+element at a time. You need to link the elements manually. A future release of
+tpl may support pointer swizzling to make this easier.
+
+
+
tpl_map
+
The only way to create a tpl is to call tpl_map(). The first argument is the
+format string. This is followed by a list of arguments as required by
+the particular characters in the format string. E.g,
+
+
+
tpl_node *tn;
+int i;
+tn = tpl_map( "A(i)", &i );
+
+
The function creates a mapping between the items in the format string and the C
+program variables whose addresses are given. Later, the C variables will be read
+or written as the tpl is packed or unpacked.
+
This function returns a tpl_node* on success, or NULL on failure.
+
tpl_pack
+
The function tpl_pack() packs data into a tpl. The arguments to
+tpl_pack() are a tpl_node* and an index number.
+
+
+
tn = tpl_map("A(i)A(c)", &i, &c);
+for(i=0; i<10; i++) tpl_pack(tn, 1); /* pack 0-9 into index 1 */
+for(c='a; c<='z'; c++) tpl_pack(tn, 2); /* pack a-z into index 2 */
+
+
+
Index number 0
+
It is necessary to pack index number 0 only if the format string contains
+characters that are not inside an A(…), such as the i in the format string
+iA(c).
+
Variable-length arrays
+
Adding elements to an array
+
To add elements to a variable-length array, call tpl_pack() repeatedly. Each
+call adds another element to the array.
+
Zero-length arrays are ok
+
It’s perfectly acceptable to pack nothing into a variable-length array,
+resulting in a zero-length array.
+
Packing nested arrays
+
In a format string containing a nested, variable-length array, such as
+A(A(s)), the inner, child array should be packed prior to the parent array.
+
When you pack a parent array, a "snapshot" of the current child array is placed
+into the parent’s new element. Packing a parent array also empties the child
+array. This way, you can pack new data into the child, then pack the parent
+again. This creates distinct parent elements which each contain distinct child
+arrays.
+
+
+
+ Tip
+ |
+When dealing with nested arrays like A(A(i)), pack them from the "inside
+out" (child first), but unpack them from the "outside in" (parent first). |
+
+
+
The example below creates a tpl having the format string A(A(c)).
+
+
Packing nested arrays
+
+
#include "tpl.h"
+
+int main() {
+ char c;
+ tpl_node *tn;
+
+ tn = tpl_map("A(A(c))", &c);
+
+ for(c='a'; c<'c'; c++) tpl_pack(tn,2); /* pack child (twice) */
+ tpl_pack(tn, 1); /* pack parent */
+
+ for(c='1'; c<'4'; c++) tpl_pack(tn,2); /* pack child (three times) */
+ tpl_pack(tn, 1); /* pack parent */
+
+ tpl_dump(tn, TPL_FILE, "test40.tpl");
+ tpl_free(tn);
+}
+
+
This creates a nested array in which the parent has two elements: the first
+element is the two-element nested array a, b; and the second element is
+the three-element nested array 1, 2, 3.
+The nested unpacking example shows how this tpl is unpacked.
+
tpl_dump
+
After packing a tpl, tpl_dump() is used to write the tpl image to a file,
+memory buffer or file descriptor. The corresponding modes are shown below. A
+final mode is for querying the output size without actually performing the dump.
+
+
+
+
+
+
+Write to… |
+Usage |
+
+
+
+
+file |
+tpl_dump(tn, TPL_FILE, "file.tpl" ); |
+
+
+file descriptor |
+tpl_dump(tn, TPL_FD, 2); |
+
+
+memory |
+tpl_dump(tn, TPL_MEM, &addr, &len ); |
+
+
+caller’s memory |
+tpl_dump(tn, TPL_MEM|TPL_PREALLOCD, buf, sizeof(buf)); |
+
+
+just get size |
+tpl_dump(tn, TPL_GETSIZE, &sz); |
+
+
+
+
+
The first argument is the tpl_node* and the second is one of these constants:
+
+-
+TPL_FILE
+
+-
+
+ Writes the tpl to a file whose name is given in the following argument.
+ The file is created with permissions 664 (rw-rw-r--) unless further
+ restricted by the process umask.
+
+
+-
+TPL_FD
+
+-
+
+ Writes the tpl to the file descriptor given in the following argument.
+ The descriptor can be either blocking or non-blocking, but will busy-loop
+ if non-blocking and the contents cannot be written immediately.
+
+
+-
+TPL_MEM
+
+-
+
+ Writes the tpl to a memory buffer. The following two arguments must be a
+ void** and a size_t*. The function will allocate a buffer and store
+ its address and length into these locations. The caller is responsible to
+ free() the buffer when done using it.
+
+
+-
+TPL_MEM|TPL_PREALLOCD
+
+-
+
+ Writes the tpl to a memory buffer that the caller has already allocated or
+ declared. The following two arguments must be a void* and a size_t
+ specifying the buffer address and size respectively. (If the buffer is of
+ insufficient size to receive the tpl dump, the function will return -1).
+ This mode can be useful in conjunction with tpl_load in TPL_EXCESS_OK
+ mode, as shown here.
+
+
+-
+TPL_GETSIZE
+
+-
+
+ This special mode does not actually dump the tpl. Instead it places the size
+ that the dump would require into the uint32_t pointed to by the
+ following argument.
+
+
+
+
The return value is 0 on success, or -1 on error.
+
The tpl_dump() function does not free the tpl. Use tpl_free() to release
+the tpl’s resources when done.
+
+
+
+ Tip
+ |
+
+ Back-to-back tpl images require no delimiter If you want to store a series of tpl images, or transmit sequential tpl images
+over a socket (perhaps as messages to another program), you can simply dump them
+sequentially without needing to add any delimiter for the individual tpl images.
+Tpl images are internally delimited, so tpl_load will read just one at a time
+even if multiple images are contiguous. |
+
+
+
tpl_load
+
This API function reads a previously-dumped tpl image from a file, memory
+buffer or file descriptor, and prepares it for subsequent unpacking. The format
+string specified in the preceding call to tpl_map() will be cross-checked
+for equality with the format string stored in the tpl image.
+
+
+
tn = tpl_map( "A(i)", &i );
+tpl_load( tn, TPL_FILE, "demo.tpl" );
+
+
The first argument to tpl_load() is the tpl_node*. The second argument is
+one of the constants:
+
+-
+TPL_FILE
+
+-
+
+ Loads the tpl from the file named in the following argument. It is also
+ possible to bitwise-OR this flag with TPL_EXCESS_OK as explained below.
+
+
+-
+TPL_MEM
+
+-
+
+ Loads the tpl from a memory buffer. The following two arguments must be a
+ void* and a size_t, specifying the buffer address and size,
+ respectively. The caller must not free the memory buffer until after
+ freeing the tpl with tpl_free(). (If the caller wishes to hand over
+ responsibility for freeing the memory buffer, so that it’s automatically
+ freed along with the tpl when tpl_free() is called, the constant
+ TPL_UFREE may be bitwise-OR’d with TPL_MEM to achieve this).
+ Furthermore, TPL_MEM may be bitwise-OR’d with TPL_EXCESS_OK, explained
+ below.
+
+
+-
+TPL_FD
+
+-
+
+ Loads the tpl from the file descriptor given in the following argument.
+ The descriptor is read until one complete tpl image is loaded; no bytes
+ past the end of the tpl image will be read. The descriptor can be either
+ blocking or non-blocking, but will busy-loop if non-blocking and the
+ contents cannot be read immediately.
+
+
+
+
During loading, the tpl image will be extensively checked for internal validity.
+
This function returns 0 on success or -1 on error.
+
TPL_EXCESS_OK
+
When reading a tpl image from a file or memory (but not from a file descriptor)
+the size of the file or memory buffer must exactly equal that of the tpl image
+stored therein. In other words, no excess trailing data beyond the tpl image is
+permitted. The bit flag TPL_EXCESS_OK can be OR’d with TPL_MEM or TPL_FILE
+to relax this requirement.
+
A situation where this flag can be useful is in conjunction with tpl_dump in
+the TPL_MEM|TPL_PREALLOCD mode. In this example, the program does not concern
+itself with the actual tpl size as long as LEN is sufficiently large.
+
+
+
char buf[LEN]; /* will store and read tpl images here */
+...
+tpl_dump(tn, TPL_MEM|TPL_PREALLOCD, buf, LEN);
+...
+tpl_load(tn, TPL_MEM|TPL_EXCESS_OK, buf, LEN);
+
+
tpl_unpack
+
The tpl_unpack() function unpacks data from the tpl. When data is unpacked,
+it is copied to the C program variables originally specified in tpl_map().
+The first argument to tpl_unpack is the tpl_node* for the tpl and the
+second argument is an index number.
+
+
+
tn = tpl_map( "A(i)A(c)", &i, &c );
+tpl_load( tn, TPL_FILE, "nested.tpl" );
+while (tpl_unpack( tn, 1) > 0) printf("i is %d\n", i); /* unpack index 1 */
+while (tpl_unpack( tn, 2) > 0) printf("c is %c\n", c); /* unpack index 2 */
+
+
Index number 0
+
It is necessary to unpack index number 0 only if the format string contains
+characters that are not inside an A(…), such as the i in the format string
+iA(c).
+
Variable-length arrays
+
Unpacking elements from an array
+
For variable-length arrays, each call to tpl_unpack() unpacks another element.
+The return value can be used to tell when you’re done: if it’s positive, an
+element was unpacked; if it’s 0, nothing was unpacked because there are no more
+elements. A negative retun value indicates an error (e.g. invalid index number).
+In this document, we usually unpack variable-length arrays using a while loop:
+
+
+
while( tpl_unpack( tn, 1 ) > 0 ) {
+ /* got another element */
+}
+
+
Array length
+
When unpacking a variable-length array, it may be convenient to know ahead of
+time how many elements will need to be unpacked. You can use tpl_Alen() to
+get this number.
+
Unpacking nested arrays
+
In a format string containing a nested variable-length array such as A(A(s)),
+unpack the outer, parent array before unpacking the child array.
+
When you unpack a parent array, it prepares the child array for unpacking.
+After unpacking the elements of the child array, the program can repeat the
+process by unpacking another parent element, then the child elements, and so on.
+The example below unpacks a tpl having the format string A(A(c)).
+
+
Unpacking nested arrays
+
+
#include "tpl.h"
+#include <stdio.h>
+
+int main() {
+ char c;
+ tpl_node *tn;
+
+ tn = tpl_map("A(A(c))", &c);
+
+ tpl_load(tn, TPL_FILE, "test40.tpl");
+ while (tpl_unpack(tn,1) > 0) {
+ while (tpl_unpack(tn,2) > 0) printf("%c ",c);
+ printf("\n");
+ }
+ tpl_free(tn);
+}
+
+
+
+
tpl_free
+
The final step for any tpl is to release it using tpl_free(). Its only
+argument is the the tpl_node* to free.
+
+
This function does not return a value (it is void).
+
tpl_Alen
+
This function takes a tpl_node* and an index number and returns an int
+specifying the number of elements in the variable-length array.
+
+
+
num_elements = tpl_Alen(tn, index);
+
+
This is mainly useful for programs that unpack data and need to know ahead of
+time the number of elements that will need to be unpacked. (It returns the
+current number of elements; it will decrease as elements are unpacked).
+
tpl_peek
+
This function peeks into a file or a memory buffer containing a tpl image and
+and returns a copy of its format string. It can also peek at the lengths of
+any fixed-length arrays in the format string, or it can also peek into the data
+stored in the tpl.
+
+
The format string can be obtained
+like this:
+
+
+
fmt = tpl_peek(TPL_FILE, "file.tpl");
+fmt = tpl_peek(TPL_MEM, addr, sz);
+
+
On success, a copy of the format string is returned. The caller must eventually
+free it. On error, such as a non-existent file, or an invalid tpl image, it
+returns NULL.
+
Array length peek
+
The lengths of all fixed-length arrays in the format string can be queried using
+the TPL_FXLENS mode. It provides the number of such fixed-length arrays and
+their lengths. If the former is non-zero, the caller must free the latter array
+when finished. The format string itself must also be freed.
+
+
+
uint32_t num_fxlens, *fxlens, j;
+fmt = tpl_peek(TPL_FILE|TPL_FXLENS, filename, &num_fxlens, &fxlens);
+if (fmt) {
+ printf("format %s, num_fxlens %u\n", fmt, num_fxlens);
+ for(j=0; j<num_fxlens; j++) printf("fxlens[%u] %u\n", j, fxlens[j]);
+ if (num_fxlens > 0) free(fxlens);
+ free(fmt);
+}
+
+
The TPL_FXLENS mode is mutually exclusive with TPL_DATAPEEK.
+
Data peek
+
To peek into the data, additional arguments are used. This is a quick
+alternative to mapping, loading and unpacking the tpl, but peeking is limited
+to the data in index 0. In other words, no peeking into A(…) types.
+Suppose the tpl image in file.tpl has the format string siA(i). Then the
+index 0 format characters are si. This is how to peek at their content:
+
+
+
char *s;
+int i;
+fmt = tpl_peek(TPL_FILE | TPL_DATAPEEK, "file.tpl", "si", &s, &i);
+
+
Now s, i, and fmt have been populated with data. The caller must
+eventually free fmt and s because they are allocated strings.
+Of course, it works with TPL_MEM as well as TPL_FILE. Notice that
+TPL_DATAPEEK was OR’d with the mode. You can also specify any leading
+portion of the index 0 format if you don’t want to peek at the whole thing:
+
+
+
fmt = tpl_peek(TPL_FILE | TPL_DATAPEEK, "file.tpl", "s", &s);
+
+
The TPL_DATAPEEK mode is mutually exclusive with TPL_FXLENS.
+
Structure peek
+
Lastly you can peek into S(…) structures in index 0, but omit the
+surrounding S(…) in the format, and specify an argument to receive
+each structure member individually. You can specify any leading portion
+of the structure format. For example if struct.tpl has the format string
+S(si), you can peek at its data in these ways:
+
+
+
fmt = tpl_peek(TPL_FILE | TPL_DATAPEEK, "struct.tpl", "s", &s);
+fmt = tpl_peek(TPL_FILE | TPL_DATAPEEK, "struct.tpl", "si", &s, &i);
+
+
tpl_jot
+
This is a quick shortcut for generating a tpl. It can be used instead of the
+usual "map, pack, dump, and free" lifecycle. With tpl_jot all those steps are
+handled for you. It only works for simple formats-- namely, those without
+A(…) in their format string. Here is how it is used:
+
+
+
char *hello = "hello", *world = "world";
+tpl_jot( TPL_FILE, "file.tpl", "ss", &hello, &world);
+
+
It supports the three standard modes, TPL_FILE, TPL_FD and TPL_MEM.
+It returns -1 on failure (such as a bad format string or error writing the
+file) or 0 on success.
+
tpl_hook
+
Most users will just leave these hooks at their default values. You can change
+these hook values if you want to modify tpl’s internal memory management and
+error reporting behavior.
+
A global structure called tpl_hook encapsulates the hooks. A program can
+reconfigure any hook by specifying an alternative function whose prototype
+matches the default. For example:
+
+
+
#include "tpl.h"
+extern tpl_hook_t tpl_hook;
+
+
+
+
int main() {
+ tpl_hook.oops = printf;
+ ...
+}
+
+
+
+Configurable hooks
+
+
+
+
+
+Hook |
+Description |
+ Default |
+
+
+
+
+tpl_hook.oops |
+log error messages |
+tpl_oops |
+
+
+tpl_hook.malloc |
+allocate memory |
+malloc |
+
+
+tpl_hook.realloc |
+reallocate memory |
+realloc |
+
+
+tpl_hook.free |
+free memory |
+free |
+
+
+tpl_hook.fatal |
+log fatal message and exit |
+tpl_fatal |
+
+
+tpl_hook.gather_max |
+tpl_gather max image size |
+0 (unlimited) |
+
+
+
+
+
The oops hook
+
The oops has the same prototype as printf. The built-in default oops
+handling function writes the error message to stderr.
+
The fatal hook
+
The fatal hook is invoked when a tpl function cannot continue because of an out-
+of-memory condition or some other usage violation or inconsistency. It has this
+prototype:
+
+
+
void fatal_fcn(char *fmt, ...);
+
+
The fatal hook must not return. It must either exit, or if the program needs
+to handle the failure and keep executing, setjmp and longjmp can be used.
+The default behavior is to exit(-1).
+
+
Using longjmp in a fatal error handler
+
+
#include <setjmp.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include "tpl.h"
+
+jmp_buf env;
+extern tpl_hook_t tpl_hook;
+
+void catch_fatal(char *fmt, ...) {
+ va_list ap;
+
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ longjmp(env,-1); /* return to setjmp point */
+}
+
+int main() {
+ int err;
+ tpl_node *tn;
+ tpl_hook.fatal = catch_fatal; /* install fatal handler */
+
+ err = setjmp(env); /* on error, control will return here */
+ if (err) {
+ printf("caught error!\n");
+ return -1;
+ }
+
+ tn = tpl_map("@"); /* generate a fatal error */
+ printf("program ending, without error\n");
+ return 0;
+}
+
+
This example is included in tests/test123.c. When run, this program prints:
+
+
+
unsupported option @
+failed to parse @
+caught error!
+
+
tpl_gather
+
+
The prototype for this function is:
+
+
+
int tpl_gather( int mode, ...);
+
+
The mode argument is one of three constants listed below, which must be
+followed by the mode-specific required arguments:
+
+
+
TPL_GATHER_BLOCKING, int fd, void **img, size_t *sz
+TPL_GATHER_NONBLOCKING, int fd, tpl_gather_t **gs, tpl_gather_cb *cb, void *data
+TPL_GATHER_MEM, void *addr, size_t sz, tpl_gather_t **gs, tpl_gather_cb *cb, void *data
+
+
+
+
+ Note
+ |
+
+ tpl_hook.gather_max All modes honor tpl_hook.gather_max, specifying the maximum byte size for a
+tpl image to be gathered (the default is unlimited, signified by 0). If a source
+attempts to send a tpl image larger than this maximum, whatever partial image
+has been read will be discarded, and no further reading will take place; in this
+case tpl_gather will return a negative (error) value to inform the caller that
+it should stop gathering from this source, and close the originating file
+descriptor if there is one. (The whole idea is to prevent untrusted sources from
+sending extremely large tpl images which would consume too much memory.) |
+
+
+
TPL_GATHER_BLOCKING
+
In this mode, tpl_gather blocks while reading file descriptor fd until one
+complete tpl image is read. No bytes past the end of the tpl image will be read.
+The address of the buffer containing the image is returned in img and its size
+is placed in sz. The caller is responsible for eventually freeing the buffer.
+The function returns 1 on success, 0 on end-of-file, or a negative number on
+error.
+
TPL_GATHER_NONBLOCKING
+
This mode is for non-blocking, event-driven programs that implement their
+own file descriptor readability testing using select() or the like. In this
+mode, tpl images are gathered in chunks as data becomes readable. Whenever a
+full tpl image has been gathered, it invokes a caller-specified callback to do
+something with the image. The arguments are the file descriptor fd which the
+caller has determined to be readable and which must be in non-blocking mode, a
+pointer to a file-descriptor-specific handle which the caller has declared
+(explained below); a callback to invoke when a tpl image has been read; and an
+opaque pointer that will passed to the callback.
+
For each file descriptor on which tpl_gather will be used, the caller must
+declare a tpl_gather_t* and initialize it to NULL. Thereafter it will be
+used internally by tpl_gather whenever data is readable on the descriptor.
+
The callback will only be invoked whenever tpl_gather() has accumulated one
+complete tpl image. It must have this prototype:
+
+
+
int (tpl_gather_cb)(void *img, size_t sz, void *data);
+
+
The callback can do anything with the tpl image but it must not free it. It can
+be copied if it needs to survive past the callback’s return. The callback should
+return 0 under normal circumstances, or a negative number to abort; that is,
+returning a negative number causes tpl_gather itself to discard any remaining
+full or partial tpl images that have been read, and to return a negative number
+(-4 in particular) to signal its caller to close the file descriptor.
+
The return value of tpl_gather() is negative if an error occured or 0 if a
+normal EOF was encountered-- both cases require that the caller close the file
+descriptor (and stop monitoring it for readability, obviously). If the return
+value is positive, the function succeeded in gathering whatever data was
+currently readable, which may have been a partial tpl image, or one or more
+complete images.
+
Typical Usage
+
The program will have established a file descriptor in non-blocking mode and
+be monitoring it for readability, using select(). Whenever it’s readable, the
+program calls tpl_gather(). In skeletal terms:
+
+
+
tpl_gather_t *gt=NULL;
+int rc;
+
+
+
+
void fd_is_readable(int fd) {
+ rc = tpl_gather( TPL_GATHER_NONBLOCKING, fd, >, callback, NULL );
+ if (rc <= 0) {
+ close(fd); /* got eof or fatal */
+ stop_watching_fd(fd);
+ }
+}
+
+
+
+
int callback( void *img, size_t sz, void *data ) {
+ printf("got a tpl image\n"); /* do something with img. do not free it. */
+ return 0; /* normal (no error) */
+}
+
+
TPL_GATHER_MEM
+
This mode is identical to TPL_GATHER_NONBLOCKING except that it gathers from a
+memory buffer instead of from a file descriptor. In other words, if some other
+layer of code-- say, a decryption function (that is decrypting fixed-size
+blocks) produces tpl fragments one-by-one, this mode can be used to reconstitute
+the tpl images and invoke the callback for each one. Its parameters are the same
+as for the TPL_GATHER_NONBLOCKING mode except that instead of a file
+descriptor, it takes a buffer address and size. The return values are also the
+same as for TPL_GATHER_NONBLOCKING noting of course there is no file
+descriptor to close on a non-positive return value.
+
+
+
+
diff --git a/libs/libtpl-1.5/doc/pdf/userguide.pdf b/libs/libtpl-1.5/doc/pdf/userguide.pdf
new file mode 100755
index 0000000000..b870fdcb9b
Binary files /dev/null and b/libs/libtpl-1.5/doc/pdf/userguide.pdf differ
diff --git a/libs/libtpl-1.5/doc/txt/ChangeLog.txt b/libs/libtpl-1.5/doc/txt/ChangeLog.txt
new file mode 100755
index 0000000000..b55964db16
--- /dev/null
+++ b/libs/libtpl-1.5/doc/txt/ChangeLog.txt
@@ -0,0 +1,59 @@
+tpl ChangeLog
+=============
+
+Version 1.5 (2010-02-05)
+--------------------------
+* tpl now builds as a DLL under Microsoft Visual Studio! (thanks, degski and Zhang Yafei!)
+* there are now two download options: the http://downloads.sourceforge.net/tpl/libtpl-1.5.tar.bz2[tarball] and the Visual Studio http://downloads.sourceforge.net/tpl/tpl-1.5-vs2008.zip[solution]
+* a crash in `tpl_free` on certain format strings has been fixed (thanks, Eric Rose!)
+* fixed a bug in `tpl_dump` on 64-bit, big-endian platforms
+* changed some pointer casts from `long` to `uintptr_t` since 64-bit Windows has 32-bit longs
+* tpl has been downloaded 4,195 times.
+
+
+Version 1.4 (2009-04-21)
+--------------------------
+* fixed-length arrays can now be multi-dimensional like `i##`
+* fixed-length string arrays like `s#` are now supported
+* nested structures can now be expressed, using the dollar symbol, e.g. `S(ci$(cc))`
+* `tpl_dump` can use a caller-allocated output buffer (`TPL_MEM|TPL_PREALLOCD`)
+* `tpl_load` can tolerate excess space in input buffer (`TPL_MEM|TPL_EXCESS_OK`)
+* implement `TPL_FXLENS` flag for `tpl_peek` to get lengths of fixed-length arrays
+* implement `TPL_GETSIZE` flag for `tpl_dump` to get dump size without dumping
+* fix success return code from `tpl_dump(TPL_FD,...)` (thanks, Max Lapan!)
+* deprecated the wildcard unpacking `S(*)` feature
+
+Version 1.3 (2009-02-10)
+--------------------------
+* added `TPL_DATAPEEK` mode for `tpl_peek`
+* added support for `NULL` strings
+* added support for 16-bit integer types (`j`,`v`)
+* added `tpl_jot`
+* added support for fixed-length arrays of structures `S(...)#`
+* added support for pre-C99 compilers (thanks, Wei Wei!)
+* improved structure alignment calculation (thanks, Wu Yongwei!)
+* added RPM spec file (thanks, Alessandro Ren!)
+* compiles cleanly with `-Wall` and `-pedantic` and with `-O3`
+* made link:license.html[BSD license] terms even more permissive
+* test suite: exit with status zero when all tests pass
+* added PDF user guide
+* added http://troydhanson.wordpress.com/feed/[update news] image:img/rss.png[(RSS)]
+* added http://apps.sourceforge.net/mediawiki/tpl/[tpl wiki]
+
+Version 1.2 (2007-04-27)
+--------------------------
+* Perl API and XML converter support 64-bit types
+
+Version 1.1 (2007-04-25)
+--------------------------
+* support for serializing C structures
+* support for serializing fixed-length arrays
+* MinGW support (thanks, Horea Haitonic!)
+* revised User Guide
+
+Version 1.0 (2006-09-28)
+--------------------------
+* Initial version
+
+// vim: set tw=80 wm=2 nowrap syntax=asciidoc:
+
diff --git a/libs/libtpl-1.5/doc/txt/compiling.txt b/libs/libtpl-1.5/doc/txt/compiling.txt
new file mode 100755
index 0000000000..abb73ecf17
--- /dev/null
+++ b/libs/libtpl-1.5/doc/txt/compiling.txt
@@ -0,0 +1,38 @@
+Compiling libtpl.a and libtpl.so
+--------------------------------
+
+********************************************************************************
+Normally in the top-level directory you simply run:
+
+ ./configure
+ make
+ make install
+
+The rest of the document is not needed if you use this method.
+********************************************************************************
+
+
+Manual compilation of static and shared library on a GNU Linux system:
+----------------------------------------------------------------------
+
+First cd into the "src" directory.
+
+Static library
+~~~~~~~~~~~~~~
+You can build the static library `libtpl.a` using these commands:
+
+ cc -c tpl.c
+ ar rc libtpl.a tpl.o
+ ranlib libtpl.a
+
+Dynamic library
+~~~~~~~~~~~~~~
+You can build the dynamic library `libtpl.so` using these commands:
+
+ cc -fpic -c tpl.c
+ cc -shared -o libtpl.so tpl.o
+
+Keep in mind that you need to set the `LD_LIBRARY_PATH` environment variable
+to include the directory where `libtpl.so` is installed in order for your
+program to run. Alternatively you can put `libtpl.so` in a standard place like
+`/usr/lib` and regenerate `ld.so.cache` using `ldconfig`.
diff --git a/libs/libtpl-1.5/doc/txt/examples.txt b/libs/libtpl-1.5/doc/txt/examples.txt
new file mode 100755
index 0000000000..9faca3fd69
--- /dev/null
+++ b/libs/libtpl-1.5/doc/txt/examples.txt
@@ -0,0 +1,297 @@
+tpl examples
+============
+Troy D. Hanson