summaryrefslogtreecommitdiff
path: root/util
diff options
context:
space:
mode:
Diffstat (limited to 'util')
-rw-r--r--util/Makefile.am152
-rw-r--r--util/Makefile.in839
-rw-r--r--util/rarian-example.c122
-rw-r--r--util/rarian-sk-config.in78
-rw-r--r--util/rarian-sk-extract.in31
-rw-r--r--util/rarian-sk-gen-uuid.c70
-rw-r--r--util/rarian-sk-get-cl.cpp236
-rw-r--r--util/rarian-sk-get-content-list.in23
-rw-r--r--util/rarian-sk-get-extended-content-list.in23
-rw-r--r--util/rarian-sk-get-scripts.in13
-rw-r--r--util/rarian-sk-install.in30
-rw-r--r--util/rarian-sk-migrate.cpp313
-rw-r--r--util/rarian-sk-preinstall.cpp141
-rw-r--r--util/rarian-sk-rebuild.in38
-rwxr-xr-xutil/rarian-sk-update.in425
-rw-r--r--util/tinystr.cpp115
-rw-r--r--util/tinystr.h319
-rw-r--r--util/tinyxml.cpp1799
-rw-r--r--util/tinyxml.h1520
-rw-r--r--util/tinyxmlerror.cpp52
-rw-r--r--util/tinyxmlparser.cpp1580
21 files changed, 7919 insertions, 0 deletions
diff --git a/util/Makefile.am b/util/Makefile.am
new file mode 100644
index 0000000..9967a65
--- /dev/null
+++ b/util/Makefile.am
@@ -0,0 +1,152 @@
+INCLUDES = \
+ -I$(srcdir)/../librarian
+LDADD = \
+ ../librarian/librarian.la
+
+if ENABLE_SK_COMPAT
+bin_SCRIPTS = \
+ rarian-sk-update \
+ rarian-sk-install \
+ rarian-sk-rebuild \
+ rarian-sk-config \
+ rarian-sk-get-scripts \
+ rarian-sk-get-content-list \
+ rarian-sk-get-extended-content-list
+endif
+
+DISTCLEANFILES= rarian-sk-update \
+ rarian-sk-install \
+ rarian-sk-rebuild \
+ rarian-sk-config \
+ rarian-sk-get-scripts \
+ rarian-sk-get-content-list \
+ rarian-sk-get-extended-content-list
+
+bin_PROGRAMS = \
+ rarian-example
+
+if ENABLE_SK_COMPAT
+bin_PROGRAMS += rarian-sk-migrate \
+ rarian-sk-preinstall \
+ rarian-sk-gen-uuid \
+ rarian-sk-get-cl
+
+if ENABLE_EXTRACT
+bin_SCRIPTS += rarian-sk-extract
+endif
+endif
+
+if ENABLE_SK_COMPAT
+rarian_sk_migrate_SOURCES = \
+ rarian-sk-migrate.cpp \
+ tinystr.cpp \
+ tinyxml.cpp \
+ tinyxmlerror.cpp \
+ tinyxmlparser.cpp \
+ tinystr.h \
+ tinyxml.h \
+ ../librarian/rarian-reg-full.h \
+ ../librarian/rarian-reg-full.c
+
+rarian_sk_preinstall_SOURCES = \
+ rarian-sk-preinstall.cpp \
+ tinystr.cpp \
+ tinyxml.cpp \
+ tinyxmlerror.cpp \
+ tinyxmlparser.cpp \
+ tinystr.h \
+ tinyxml.h
+
+rarian_sk_get_cl_SOURCES = \
+ rarian-sk-get-cl.cpp \
+ tinystr.cpp \
+ tinyxml.cpp \
+ tinyxmlerror.cpp \
+ tinyxmlparser.cpp \
+ tinystr.h \
+ tinyxml.h
+
+rarian_sk_get_cl_CXXFLAGS = -DDATADIR=\""$(datadir)"\" -DLOCALSTATEDIR=\""$(localstatedir)"\"
+
+rarian_sk_gen_uuid_SOURCES = \
+ rarian-sk-gen-uuid.c
+endif
+
+rarian_example_SOURCES = \
+ rarian-example.c
+
+if ENABLE_INSTALL
+install-exec-hook:
+if ENABLE_SK_COMPAT
+ @echo Moving Files if needed
+ @if [ -h $(DESTDIR)$(bindir)/scrollkeeper-config ]; then rm $(DESTDIR)$(bindir)/scrollkeeper-config; \
+ elif [ -e $(DESTDIR)$(bindir)/scrollkeeper-config ]; then \
+ mv $(DESTDIR)$(bindir)/scrollkeeper-config $(DESTDIR)$(bindir)/scrollkeeper-config.real; fi
+if ENABLE_EXTRACT
+ @if [ -h $(DESTDIR)$(bindir)/scrollkeeper-extract ]; then rm $(DESTDIR)$(bindir)/scrollkeeper-extract; \
+ elif [ -e $(DESTDIR)$(bindir)/scrollkeeper-extract ]; then \
+ mv $(DESTDIR)$(bindir)/scrollkeeper-extract $(DESTDIR)$(bindir)/scrollkeeper-extract.real; fi
+endif
+ @if [ -h $(DESTDIR)$(bindir)/scrollkeeper-gen-seriesid ]; then rm $(DESTDIR)$(bindir)/scrollkeeper-gen-seriesid; \
+ elif [ -e $(DESTDIR)$(bindir)/scrollkeeper-gen-seriesid ]; then \
+ mv $(DESTDIR)$(bindir)/scrollkeeper-gen-seriesid $(DESTDIR)$(bindir)/scrollkeeper-gen-seriesid.real; fi
+ @if [ -h $(DESTDIR)$(bindir)/scrollkeeper-get-cl ]; then rm $(DESTDIR)$(bindir)/scrollkeeper-get-cl; \
+ elif [ -e $(DESTDIR)$(bindir)/scrollkeeper-get-cl ]; then \
+ mv $(DESTDIR)$(bindir)/scrollkeeper-get-cl $(DESTDIR)$(bindir)/scrollkeeper-get-cl.real; fi
+ @if [ -h $(DESTDIR)$(bindir)/scrollkeeper-get-content-list ]; then rm $(DESTDIR)$(bindir)/scrollkeeper-get-content-list; \
+ elif [ -e $(DESTDIR)$(bindir)/scrollkeeper-get-content-list ]; then \
+ mv $(DESTDIR)$(bindir)/scrollkeeper-get-content-list $(DESTDIR)$(bindir)/scrollkeeper-get-content-list.real; fi
+ @if [ -h $(DESTDIR)$(bindir)/scrollkeeper-get-extended-content-list ]; then rm $(DESTDIR)$(bindir)/scrollkeeper-get-extended-content-list; \
+ elif [ -e $(DESTDIR)$(bindir)/scrollkeeper-get-extended-content-list ]; then \
+ mv $(DESTDIR)$(bindir)/scrollkeeper-get-extended-content-list $(DESTDIR)$(bindir)/scrollkeeper-get-extended-content-list.real; fi
+ @if [ -h $(DESTDIR)$(bindir)/scrollkeeper-get-index-from-docpath ]; then rm $(DESTDIR)$(bindir)/scrollkeeper-get-index-from-docpath; \
+ elif [ -e $(DESTDIR)$(bindir)/scrollkeeper-get-index-from-docpath ]; then \
+ mv $(DESTDIR)$(bindir)/scrollkeeper-get-index-from-docpath $(DESTDIR)$(bindir)/scrollkeeper-get-index-from-docpath.real; fi
+ @if [ -h $(DESTDIR)$(bindir)/scrollkeeper-get-toc-from-docpath ]; then rm $(DESTDIR)$(bindir)/scrollkeeper-get-toc-from-docpath; \
+ elif [ -e $(DESTDIR)$(bindir)/scrollkeeper-get-toc-from-docpath ]; then \
+ mv $(DESTDIR)$(bindir)/scrollkeeper-get-toc-from-docpath $(DESTDIR)$(bindir)/scrollkeeper-get-toc-from-docpath.real; fi
+ @if [ -h $(DESTDIR)$(bindir)/scrollkeeper-get-toc-from-id ]; then rm $(DESTDIR)$(bindir)/scrollkeeper-get-toc-from-id; \
+ elif [ -e $(DESTDIR)$(bindir)/scrollkeeper-get-toc-from-id ]; then \
+ mv $(DESTDIR)$(bindir)/scrollkeeper-get-toc-from-id $(DESTDIR)$(bindir)/scrollkeeper-get-toc-from-id.real; fi
+ @if [ -h $(DESTDIR)$(bindir)/scrollkeeper-install ]; then rm $(DESTDIR)$(bindir)/scrollkeeper-install; \
+ elif [ -e $(DESTDIR)$(bindir)/scrollkeeper-install ]; then \
+ mv $(DESTDIR)$(bindir)/scrollkeeper-install $(DESTDIR)$(bindir)/scrollkeeper-install.real; fi
+ @if [ -h $(DESTDIR)$(bindir)/scrollkeeper-preinstall ]; then rm $(DESTDIR)$(bindir)/scrollkeeper-preinstall; \
+ elif [ -e $(DESTDIR)$(bindir)/scrollkeeper-preinstall ]; then \
+ mv $(DESTDIR)$(bindir)/scrollkeeper-preinstall $(DESTDIR)$(bindir)/scrollkeeper-preinstall.real; fi
+ @if [ -h $(DESTDIR)$(bindir)/scrollkeeper-rebuilddb ]; then rm $(DESTDIR)$(bindir)/scrollkeeper-rebuilddb; \
+ elif [ -e $(DESTDIR)$(bindir)/scrollkeeper-rebuilddb ]; then \
+ mv $(DESTDIR)$(bindir)/scrollkeeper-rebuilddb $(DESTDIR)$(bindir)/scrollkeeper-rebuilddb.real; fi
+ @if [ -h $(DESTDIR)$(bindir)/scrollkeeper-uninstall ]; then rm $(DESTDIR)$(bindir)/scrollkeeper-uninstall; \
+ elif [ -e $(DESTDIR)$(bindir)/scrollkeeper-uninstall ]; then \
+ mv $(DESTDIR)$(bindir)/scrollkeeper-uninstall $(DESTDIR)$(bindir)/scrollkeeper-uninstall.real; fi
+ @if [ -h $(DESTDIR)$(bindir)/scrollkeeper-update ]; then rm $(DESTDIR)$(bindir)/scrollkeeper-update; \
+ elif [ -e $(DESTDIR)$(bindir)/scrollkeeper-update ]; then \
+ mv $(DESTDIR)$(bindir)/scrollkeeper-update $(DESTDIR)$(bindir)/scrollkeeper-update.real; fi
+ @cd $(DESTDIR)$(bindir); ln -s rarian-sk-config scrollkeeper-config
+if ENABLE_EXTRACT
+ @cd $(DESTDIR)$(bindir); ln -s rarian-sk-extract scrollkeeper-extract
+endif
+ @cd $(DESTDIR)$(bindir); ln -s rarian-sk-gen-uuid scrollkeeper-gen-seriesid
+ @cd $(DESTDIR)$(bindir); ln -s rarian-sk-get-cl scrollkeeper-get-cl
+ @cd $(DESTDIR)$(bindir); ln -s rarian-sk-get-content-list scrollkeeper-get-content-list
+ @cd $(DESTDIR)$(bindir); ln -s rarian-sk-get-extended-content-list scrollkeeper-get-extended-content-list
+ @cd $(DESTDIR)$(bindir); ln -s rarian-sk-get-scripts scrollkeeper-get-index-from-docpath
+ @cd $(DESTDIR)$(bindir); ln -s rarian-sk-get-scripts scrollkeeper-get-toc-from-docpath
+ @cd $(DESTDIR)$(bindir); ln -s rarian-sk-get-scripts scrollkeeper-get-toc-from-id
+ @cd $(DESTDIR)$(bindir); ln -s rarian-sk-install scrollkeeper-install
+ @cd $(DESTDIR)$(bindir); ln -s rarian-sk-preinstall scrollkeeper-preinstall
+ @cd $(DESTDIR)$(bindir); ln -s rarian-sk-rebuild scrollkeeper-rebuilddb
+ @cd $(DESTDIR)$(bindir); ln -s rarian-sk-install scrollkeeper-uninstall
+ @cd $(DESTDIR)$(bindir); ln -s rarian-sk-update scrollkeeper-update
+ @mkdir -p $(DESTDIR)/$(localstatedir)/lib/rarian
+if ENABLE_SKDB_UPDATE
+ @echo "Translating current database"
+ @$(DESTDIR)$(bindir)/rarian-sk-update
+endif
+endif
+
+else
+install-exec-hook:
+ @echo WARNING: Installed in UNINSTALLED mode. Prepare for things to be broken!!!!!
+endif
diff --git a/util/Makefile.in b/util/Makefile.in
new file mode 100644
index 0000000..fff6158
--- /dev/null
+++ b/util/Makefile.in
@@ -0,0 +1,839 @@
+# Makefile.in generated by automake 1.10.1 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@
+bin_PROGRAMS = rarian-example$(EXEEXT) $(am__EXEEXT_1)
+@ENABLE_SK_COMPAT_TRUE@am__append_1 = rarian-sk-migrate \
+@ENABLE_SK_COMPAT_TRUE@ rarian-sk-preinstall \
+@ENABLE_SK_COMPAT_TRUE@ rarian-sk-gen-uuid \
+@ENABLE_SK_COMPAT_TRUE@ rarian-sk-get-cl
+
+@ENABLE_EXTRACT_TRUE@@ENABLE_SK_COMPAT_TRUE@am__append_2 = rarian-sk-extract
+subdir = util
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
+ $(srcdir)/rarian-sk-config.in $(srcdir)/rarian-sk-extract.in \
+ $(srcdir)/rarian-sk-get-content-list.in \
+ $(srcdir)/rarian-sk-get-extended-content-list.in \
+ $(srcdir)/rarian-sk-get-scripts.in \
+ $(srcdir)/rarian-sk-install.in $(srcdir)/rarian-sk-rebuild.in \
+ $(srcdir)/rarian-sk-update.in
+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)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES = rarian-sk-update rarian-sk-install \
+ rarian-sk-rebuild rarian-sk-config rarian-sk-get-scripts \
+ rarian-sk-extract rarian-sk-get-content-list \
+ rarian-sk-get-extended-content-list
+@ENABLE_SK_COMPAT_TRUE@am__EXEEXT_1 = rarian-sk-migrate$(EXEEXT) \
+@ENABLE_SK_COMPAT_TRUE@ rarian-sk-preinstall$(EXEEXT) \
+@ENABLE_SK_COMPAT_TRUE@ rarian-sk-gen-uuid$(EXEEXT) \
+@ENABLE_SK_COMPAT_TRUE@ rarian-sk-get-cl$(EXEEXT)
+am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(bindir)"
+binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
+PROGRAMS = $(bin_PROGRAMS)
+am_rarian_example_OBJECTS = rarian-example.$(OBJEXT)
+rarian_example_OBJECTS = $(am_rarian_example_OBJECTS)
+rarian_example_LDADD = $(LDADD)
+rarian_example_DEPENDENCIES = ../librarian/librarian.la
+am__rarian_sk_gen_uuid_SOURCES_DIST = rarian-sk-gen-uuid.c
+@ENABLE_SK_COMPAT_TRUE@am_rarian_sk_gen_uuid_OBJECTS = \
+@ENABLE_SK_COMPAT_TRUE@ rarian-sk-gen-uuid.$(OBJEXT)
+rarian_sk_gen_uuid_OBJECTS = $(am_rarian_sk_gen_uuid_OBJECTS)
+rarian_sk_gen_uuid_LDADD = $(LDADD)
+rarian_sk_gen_uuid_DEPENDENCIES = ../librarian/librarian.la
+am__rarian_sk_get_cl_SOURCES_DIST = rarian-sk-get-cl.cpp tinystr.cpp \
+ tinyxml.cpp tinyxmlerror.cpp tinyxmlparser.cpp tinystr.h \
+ tinyxml.h
+@ENABLE_SK_COMPAT_TRUE@am_rarian_sk_get_cl_OBJECTS = rarian_sk_get_cl-rarian-sk-get-cl.$(OBJEXT) \
+@ENABLE_SK_COMPAT_TRUE@ rarian_sk_get_cl-tinystr.$(OBJEXT) \
+@ENABLE_SK_COMPAT_TRUE@ rarian_sk_get_cl-tinyxml.$(OBJEXT) \
+@ENABLE_SK_COMPAT_TRUE@ rarian_sk_get_cl-tinyxmlerror.$(OBJEXT) \
+@ENABLE_SK_COMPAT_TRUE@ rarian_sk_get_cl-tinyxmlparser.$(OBJEXT)
+rarian_sk_get_cl_OBJECTS = $(am_rarian_sk_get_cl_OBJECTS)
+rarian_sk_get_cl_LDADD = $(LDADD)
+rarian_sk_get_cl_DEPENDENCIES = ../librarian/librarian.la
+rarian_sk_get_cl_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
+ $(rarian_sk_get_cl_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+am__rarian_sk_migrate_SOURCES_DIST = rarian-sk-migrate.cpp tinystr.cpp \
+ tinyxml.cpp tinyxmlerror.cpp tinyxmlparser.cpp tinystr.h \
+ tinyxml.h ../librarian/rarian-reg-full.h \
+ ../librarian/rarian-reg-full.c
+@ENABLE_SK_COMPAT_TRUE@am_rarian_sk_migrate_OBJECTS = \
+@ENABLE_SK_COMPAT_TRUE@ rarian-sk-migrate.$(OBJEXT) \
+@ENABLE_SK_COMPAT_TRUE@ tinystr.$(OBJEXT) tinyxml.$(OBJEXT) \
+@ENABLE_SK_COMPAT_TRUE@ tinyxmlerror.$(OBJEXT) \
+@ENABLE_SK_COMPAT_TRUE@ tinyxmlparser.$(OBJEXT) \
+@ENABLE_SK_COMPAT_TRUE@ rarian-reg-full.$(OBJEXT)
+rarian_sk_migrate_OBJECTS = $(am_rarian_sk_migrate_OBJECTS)
+rarian_sk_migrate_LDADD = $(LDADD)
+rarian_sk_migrate_DEPENDENCIES = ../librarian/librarian.la
+am__rarian_sk_preinstall_SOURCES_DIST = rarian-sk-preinstall.cpp \
+ tinystr.cpp tinyxml.cpp tinyxmlerror.cpp tinyxmlparser.cpp \
+ tinystr.h tinyxml.h
+@ENABLE_SK_COMPAT_TRUE@am_rarian_sk_preinstall_OBJECTS = \
+@ENABLE_SK_COMPAT_TRUE@ rarian-sk-preinstall.$(OBJEXT) \
+@ENABLE_SK_COMPAT_TRUE@ tinystr.$(OBJEXT) tinyxml.$(OBJEXT) \
+@ENABLE_SK_COMPAT_TRUE@ tinyxmlerror.$(OBJEXT) \
+@ENABLE_SK_COMPAT_TRUE@ tinyxmlparser.$(OBJEXT)
+rarian_sk_preinstall_OBJECTS = $(am_rarian_sk_preinstall_OBJECTS)
+rarian_sk_preinstall_LDADD = $(LDADD)
+rarian_sk_preinstall_DEPENDENCIES = ../librarian/librarian.la
+binSCRIPT_INSTALL = $(INSTALL_SCRIPT)
+SCRIPTS = $(bin_SCRIPTS)
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(rarian_example_SOURCES) $(rarian_sk_gen_uuid_SOURCES) \
+ $(rarian_sk_get_cl_SOURCES) $(rarian_sk_migrate_SOURCES) \
+ $(rarian_sk_preinstall_SOURCES)
+DIST_SOURCES = $(rarian_example_SOURCES) \
+ $(am__rarian_sk_gen_uuid_SOURCES_DIST) \
+ $(am__rarian_sk_get_cl_SOURCES_DIST) \
+ $(am__rarian_sk_migrate_SOURCES_DIST) \
+ $(am__rarian_sk_preinstall_SOURCES_DIST)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BASH = @BASH@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CONVERT_DIR = @CONVERT_DIR@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@
+DSYMUTIL = @DSYMUTIL@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ENABLE_INSTALL = @ENABLE_INSTALL@
+ENABLE_OMF_READ = @ENABLE_OMF_READ@
+ENABLE_SKDB_UPDATE = @ENABLE_SKDB_UPDATE@
+ENABLE_SK_COMPAT = @ENABLE_SK_COMPAT@
+EXEEXT = @EXEEXT@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+NMEDIT = @NMEDIT@
+OBJEXT = @OBJEXT@
+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_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+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@
+have_bash = @have_bash@
+have_xslt = @have_xslt@
+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@
+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_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+INCLUDES = \
+ -I$(srcdir)/../librarian
+
+LDADD = \
+ ../librarian/librarian.la
+
+@ENABLE_SK_COMPAT_TRUE@bin_SCRIPTS = rarian-sk-update \
+@ENABLE_SK_COMPAT_TRUE@ rarian-sk-install rarian-sk-rebuild \
+@ENABLE_SK_COMPAT_TRUE@ rarian-sk-config rarian-sk-get-scripts \
+@ENABLE_SK_COMPAT_TRUE@ rarian-sk-get-content-list \
+@ENABLE_SK_COMPAT_TRUE@ rarian-sk-get-extended-content-list \
+@ENABLE_SK_COMPAT_TRUE@ $(am__append_2)
+DISTCLEANFILES = rarian-sk-update \
+ rarian-sk-install \
+ rarian-sk-rebuild \
+ rarian-sk-config \
+ rarian-sk-get-scripts \
+ rarian-sk-get-content-list \
+ rarian-sk-get-extended-content-list
+
+@ENABLE_SK_COMPAT_TRUE@rarian_sk_migrate_SOURCES = \
+@ENABLE_SK_COMPAT_TRUE@ rarian-sk-migrate.cpp \
+@ENABLE_SK_COMPAT_TRUE@ tinystr.cpp \
+@ENABLE_SK_COMPAT_TRUE@ tinyxml.cpp \
+@ENABLE_SK_COMPAT_TRUE@ tinyxmlerror.cpp \
+@ENABLE_SK_COMPAT_TRUE@ tinyxmlparser.cpp \
+@ENABLE_SK_COMPAT_TRUE@ tinystr.h \
+@ENABLE_SK_COMPAT_TRUE@ tinyxml.h \
+@ENABLE_SK_COMPAT_TRUE@ ../librarian/rarian-reg-full.h \
+@ENABLE_SK_COMPAT_TRUE@ ../librarian/rarian-reg-full.c
+
+@ENABLE_SK_COMPAT_TRUE@rarian_sk_preinstall_SOURCES = \
+@ENABLE_SK_COMPAT_TRUE@ rarian-sk-preinstall.cpp \
+@ENABLE_SK_COMPAT_TRUE@ tinystr.cpp \
+@ENABLE_SK_COMPAT_TRUE@ tinyxml.cpp \
+@ENABLE_SK_COMPAT_TRUE@ tinyxmlerror.cpp \
+@ENABLE_SK_COMPAT_TRUE@ tinyxmlparser.cpp \
+@ENABLE_SK_COMPAT_TRUE@ tinystr.h \
+@ENABLE_SK_COMPAT_TRUE@ tinyxml.h
+
+@ENABLE_SK_COMPAT_TRUE@rarian_sk_get_cl_SOURCES = \
+@ENABLE_SK_COMPAT_TRUE@ rarian-sk-get-cl.cpp \
+@ENABLE_SK_COMPAT_TRUE@ tinystr.cpp \
+@ENABLE_SK_COMPAT_TRUE@ tinyxml.cpp \
+@ENABLE_SK_COMPAT_TRUE@ tinyxmlerror.cpp \
+@ENABLE_SK_COMPAT_TRUE@ tinyxmlparser.cpp \
+@ENABLE_SK_COMPAT_TRUE@ tinystr.h \
+@ENABLE_SK_COMPAT_TRUE@ tinyxml.h
+
+@ENABLE_SK_COMPAT_TRUE@rarian_sk_get_cl_CXXFLAGS = -DDATADIR=\""$(datadir)"\" -DLOCALSTATEDIR=\""$(localstatedir)"\"
+@ENABLE_SK_COMPAT_TRUE@rarian_sk_gen_uuid_SOURCES = \
+@ENABLE_SK_COMPAT_TRUE@ rarian-sk-gen-uuid.c
+
+rarian_example_SOURCES = \
+ rarian-example.c
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .cpp .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu util/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu util/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+rarian-sk-update: $(top_builddir)/config.status $(srcdir)/rarian-sk-update.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+rarian-sk-install: $(top_builddir)/config.status $(srcdir)/rarian-sk-install.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+rarian-sk-rebuild: $(top_builddir)/config.status $(srcdir)/rarian-sk-rebuild.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+rarian-sk-config: $(top_builddir)/config.status $(srcdir)/rarian-sk-config.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+rarian-sk-get-scripts: $(top_builddir)/config.status $(srcdir)/rarian-sk-get-scripts.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+rarian-sk-extract: $(top_builddir)/config.status $(srcdir)/rarian-sk-extract.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+rarian-sk-get-content-list: $(top_builddir)/config.status $(srcdir)/rarian-sk-get-content-list.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+rarian-sk-get-extended-content-list: $(top_builddir)/config.status $(srcdir)/rarian-sk-get-extended-content-list.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+install-binPROGRAMS: $(bin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
+ @list='$(bin_PROGRAMS)'; for p in $$list; do \
+ p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+ if test -f $$p \
+ || test -f $$p1 \
+ ; then \
+ f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
+ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \
+ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \
+ else :; fi; \
+ done
+
+uninstall-binPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(bin_PROGRAMS)'; for p in $$list; do \
+ f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
+ echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \
+ rm -f "$(DESTDIR)$(bindir)/$$f"; \
+ done
+
+clean-binPROGRAMS:
+ @list='$(bin_PROGRAMS)'; for p in $$list; do \
+ f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f $$p $$f"; \
+ rm -f $$p $$f ; \
+ done
+rarian-example$(EXEEXT): $(rarian_example_OBJECTS) $(rarian_example_DEPENDENCIES)
+ @rm -f rarian-example$(EXEEXT)
+ $(LINK) $(rarian_example_OBJECTS) $(rarian_example_LDADD) $(LIBS)
+rarian-sk-gen-uuid$(EXEEXT): $(rarian_sk_gen_uuid_OBJECTS) $(rarian_sk_gen_uuid_DEPENDENCIES)
+ @rm -f rarian-sk-gen-uuid$(EXEEXT)
+ $(LINK) $(rarian_sk_gen_uuid_OBJECTS) $(rarian_sk_gen_uuid_LDADD) $(LIBS)
+rarian-sk-get-cl$(EXEEXT): $(rarian_sk_get_cl_OBJECTS) $(rarian_sk_get_cl_DEPENDENCIES)
+ @rm -f rarian-sk-get-cl$(EXEEXT)
+ $(rarian_sk_get_cl_LINK) $(rarian_sk_get_cl_OBJECTS) $(rarian_sk_get_cl_LDADD) $(LIBS)
+rarian-sk-migrate$(EXEEXT): $(rarian_sk_migrate_OBJECTS) $(rarian_sk_migrate_DEPENDENCIES)
+ @rm -f rarian-sk-migrate$(EXEEXT)
+ $(CXXLINK) $(rarian_sk_migrate_OBJECTS) $(rarian_sk_migrate_LDADD) $(LIBS)
+rarian-sk-preinstall$(EXEEXT): $(rarian_sk_preinstall_OBJECTS) $(rarian_sk_preinstall_DEPENDENCIES)
+ @rm -f rarian-sk-preinstall$(EXEEXT)
+ $(CXXLINK) $(rarian_sk_preinstall_OBJECTS) $(rarian_sk_preinstall_LDADD) $(LIBS)
+install-binSCRIPTS: $(bin_SCRIPTS)
+ @$(NORMAL_INSTALL)
+ test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
+ @list='$(bin_SCRIPTS)'; for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ if test -f $$d$$p; then \
+ f=`echo "$$p" | sed 's|^.*/||;$(transform)'`; \
+ echo " $(binSCRIPT_INSTALL) '$$d$$p' '$(DESTDIR)$(bindir)/$$f'"; \
+ $(binSCRIPT_INSTALL) "$$d$$p" "$(DESTDIR)$(bindir)/$$f"; \
+ else :; fi; \
+ done
+
+uninstall-binSCRIPTS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(bin_SCRIPTS)'; for p in $$list; do \
+ f=`echo "$$p" | sed 's|^.*/||;$(transform)'`; \
+ echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \
+ rm -f "$(DESTDIR)$(bindir)/$$f"; \
+ done
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rarian-example.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rarian-reg-full.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rarian-sk-gen-uuid.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rarian-sk-migrate.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rarian-sk-preinstall.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rarian_sk_get_cl-rarian-sk-get-cl.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rarian_sk_get_cl-tinystr.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rarian_sk_get_cl-tinyxml.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rarian_sk_get_cl-tinyxmlerror.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rarian_sk_get_cl-tinyxmlparser.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tinystr.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tinyxml.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tinyxmlerror.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tinyxmlparser.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+rarian-reg-full.o: ../librarian/rarian-reg-full.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rarian-reg-full.o -MD -MP -MF $(DEPDIR)/rarian-reg-full.Tpo -c -o rarian-reg-full.o `test -f '../librarian/rarian-reg-full.c' || echo '$(srcdir)/'`../librarian/rarian-reg-full.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/rarian-reg-full.Tpo $(DEPDIR)/rarian-reg-full.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../librarian/rarian-reg-full.c' object='rarian-reg-full.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rarian-reg-full.o `test -f '../librarian/rarian-reg-full.c' || echo '$(srcdir)/'`../librarian/rarian-reg-full.c
+
+rarian-reg-full.obj: ../librarian/rarian-reg-full.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rarian-reg-full.obj -MD -MP -MF $(DEPDIR)/rarian-reg-full.Tpo -c -o rarian-reg-full.obj `if test -f '../librarian/rarian-reg-full.c'; then $(CYGPATH_W) '../librarian/rarian-reg-full.c'; else $(CYGPATH_W) '$(srcdir)/../librarian/rarian-reg-full.c'; fi`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/rarian-reg-full.Tpo $(DEPDIR)/rarian-reg-full.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../librarian/rarian-reg-full.c' object='rarian-reg-full.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rarian-reg-full.obj `if test -f '../librarian/rarian-reg-full.c'; then $(CYGPATH_W) '../librarian/rarian-reg-full.c'; else $(CYGPATH_W) '$(srcdir)/../librarian/rarian-reg-full.c'; fi`
+
+.cpp.o:
+@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $<
+
+.cpp.obj:
+@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.cpp.lo:
+@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $<
+
+rarian_sk_get_cl-rarian-sk-get-cl.o: rarian-sk-get-cl.cpp
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rarian_sk_get_cl_CXXFLAGS) $(CXXFLAGS) -MT rarian_sk_get_cl-rarian-sk-get-cl.o -MD -MP -MF $(DEPDIR)/rarian_sk_get_cl-rarian-sk-get-cl.Tpo -c -o rarian_sk_get_cl-rarian-sk-get-cl.o `test -f 'rarian-sk-get-cl.cpp' || echo '$(srcdir)/'`rarian-sk-get-cl.cpp
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/rarian_sk_get_cl-rarian-sk-get-cl.Tpo $(DEPDIR)/rarian_sk_get_cl-rarian-sk-get-cl.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='rarian-sk-get-cl.cpp' object='rarian_sk_get_cl-rarian-sk-get-cl.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rarian_sk_get_cl_CXXFLAGS) $(CXXFLAGS) -c -o rarian_sk_get_cl-rarian-sk-get-cl.o `test -f 'rarian-sk-get-cl.cpp' || echo '$(srcdir)/'`rarian-sk-get-cl.cpp
+
+rarian_sk_get_cl-rarian-sk-get-cl.obj: rarian-sk-get-cl.cpp
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rarian_sk_get_cl_CXXFLAGS) $(CXXFLAGS) -MT rarian_sk_get_cl-rarian-sk-get-cl.obj -MD -MP -MF $(DEPDIR)/rarian_sk_get_cl-rarian-sk-get-cl.Tpo -c -o rarian_sk_get_cl-rarian-sk-get-cl.obj `if test -f 'rarian-sk-get-cl.cpp'; then $(CYGPATH_W) 'rarian-sk-get-cl.cpp'; else $(CYGPATH_W) '$(srcdir)/rarian-sk-get-cl.cpp'; fi`
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/rarian_sk_get_cl-rarian-sk-get-cl.Tpo $(DEPDIR)/rarian_sk_get_cl-rarian-sk-get-cl.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='rarian-sk-get-cl.cpp' object='rarian_sk_get_cl-rarian-sk-get-cl.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rarian_sk_get_cl_CXXFLAGS) $(CXXFLAGS) -c -o rarian_sk_get_cl-rarian-sk-get-cl.obj `if test -f 'rarian-sk-get-cl.cpp'; then $(CYGPATH_W) 'rarian-sk-get-cl.cpp'; else $(CYGPATH_W) '$(srcdir)/rarian-sk-get-cl.cpp'; fi`
+
+rarian_sk_get_cl-tinystr.o: tinystr.cpp
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rarian_sk_get_cl_CXXFLAGS) $(CXXFLAGS) -MT rarian_sk_get_cl-tinystr.o -MD -MP -MF $(DEPDIR)/rarian_sk_get_cl-tinystr.Tpo -c -o rarian_sk_get_cl-tinystr.o `test -f 'tinystr.cpp' || echo '$(srcdir)/'`tinystr.cpp
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/rarian_sk_get_cl-tinystr.Tpo $(DEPDIR)/rarian_sk_get_cl-tinystr.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='tinystr.cpp' object='rarian_sk_get_cl-tinystr.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rarian_sk_get_cl_CXXFLAGS) $(CXXFLAGS) -c -o rarian_sk_get_cl-tinystr.o `test -f 'tinystr.cpp' || echo '$(srcdir)/'`tinystr.cpp
+
+rarian_sk_get_cl-tinystr.obj: tinystr.cpp
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rarian_sk_get_cl_CXXFLAGS) $(CXXFLAGS) -MT rarian_sk_get_cl-tinystr.obj -MD -MP -MF $(DEPDIR)/rarian_sk_get_cl-tinystr.Tpo -c -o rarian_sk_get_cl-tinystr.obj `if test -f 'tinystr.cpp'; then $(CYGPATH_W) 'tinystr.cpp'; else $(CYGPATH_W) '$(srcdir)/tinystr.cpp'; fi`
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/rarian_sk_get_cl-tinystr.Tpo $(DEPDIR)/rarian_sk_get_cl-tinystr.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='tinystr.cpp' object='rarian_sk_get_cl-tinystr.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rarian_sk_get_cl_CXXFLAGS) $(CXXFLAGS) -c -o rarian_sk_get_cl-tinystr.obj `if test -f 'tinystr.cpp'; then $(CYGPATH_W) 'tinystr.cpp'; else $(CYGPATH_W) '$(srcdir)/tinystr.cpp'; fi`
+
+rarian_sk_get_cl-tinyxml.o: tinyxml.cpp
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rarian_sk_get_cl_CXXFLAGS) $(CXXFLAGS) -MT rarian_sk_get_cl-tinyxml.o -MD -MP -MF $(DEPDIR)/rarian_sk_get_cl-tinyxml.Tpo -c -o rarian_sk_get_cl-tinyxml.o `test -f 'tinyxml.cpp' || echo '$(srcdir)/'`tinyxml.cpp
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/rarian_sk_get_cl-tinyxml.Tpo $(DEPDIR)/rarian_sk_get_cl-tinyxml.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='tinyxml.cpp' object='rarian_sk_get_cl-tinyxml.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rarian_sk_get_cl_CXXFLAGS) $(CXXFLAGS) -c -o rarian_sk_get_cl-tinyxml.o `test -f 'tinyxml.cpp' || echo '$(srcdir)/'`tinyxml.cpp
+
+rarian_sk_get_cl-tinyxml.obj: tinyxml.cpp
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rarian_sk_get_cl_CXXFLAGS) $(CXXFLAGS) -MT rarian_sk_get_cl-tinyxml.obj -MD -MP -MF $(DEPDIR)/rarian_sk_get_cl-tinyxml.Tpo -c -o rarian_sk_get_cl-tinyxml.obj `if test -f 'tinyxml.cpp'; then $(CYGPATH_W) 'tinyxml.cpp'; else $(CYGPATH_W) '$(srcdir)/tinyxml.cpp'; fi`
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/rarian_sk_get_cl-tinyxml.Tpo $(DEPDIR)/rarian_sk_get_cl-tinyxml.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='tinyxml.cpp' object='rarian_sk_get_cl-tinyxml.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rarian_sk_get_cl_CXXFLAGS) $(CXXFLAGS) -c -o rarian_sk_get_cl-tinyxml.obj `if test -f 'tinyxml.cpp'; then $(CYGPATH_W) 'tinyxml.cpp'; else $(CYGPATH_W) '$(srcdir)/tinyxml.cpp'; fi`
+
+rarian_sk_get_cl-tinyxmlerror.o: tinyxmlerror.cpp
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rarian_sk_get_cl_CXXFLAGS) $(CXXFLAGS) -MT rarian_sk_get_cl-tinyxmlerror.o -MD -MP -MF $(DEPDIR)/rarian_sk_get_cl-tinyxmlerror.Tpo -c -o rarian_sk_get_cl-tinyxmlerror.o `test -f 'tinyxmlerror.cpp' || echo '$(srcdir)/'`tinyxmlerror.cpp
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/rarian_sk_get_cl-tinyxmlerror.Tpo $(DEPDIR)/rarian_sk_get_cl-tinyxmlerror.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='tinyxmlerror.cpp' object='rarian_sk_get_cl-tinyxmlerror.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rarian_sk_get_cl_CXXFLAGS) $(CXXFLAGS) -c -o rarian_sk_get_cl-tinyxmlerror.o `test -f 'tinyxmlerror.cpp' || echo '$(srcdir)/'`tinyxmlerror.cpp
+
+rarian_sk_get_cl-tinyxmlerror.obj: tinyxmlerror.cpp
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rarian_sk_get_cl_CXXFLAGS) $(CXXFLAGS) -MT rarian_sk_get_cl-tinyxmlerror.obj -MD -MP -MF $(DEPDIR)/rarian_sk_get_cl-tinyxmlerror.Tpo -c -o rarian_sk_get_cl-tinyxmlerror.obj `if test -f 'tinyxmlerror.cpp'; then $(CYGPATH_W) 'tinyxmlerror.cpp'; else $(CYGPATH_W) '$(srcdir)/tinyxmlerror.cpp'; fi`
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/rarian_sk_get_cl-tinyxmlerror.Tpo $(DEPDIR)/rarian_sk_get_cl-tinyxmlerror.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='tinyxmlerror.cpp' object='rarian_sk_get_cl-tinyxmlerror.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rarian_sk_get_cl_CXXFLAGS) $(CXXFLAGS) -c -o rarian_sk_get_cl-tinyxmlerror.obj `if test -f 'tinyxmlerror.cpp'; then $(CYGPATH_W) 'tinyxmlerror.cpp'; else $(CYGPATH_W) '$(srcdir)/tinyxmlerror.cpp'; fi`
+
+rarian_sk_get_cl-tinyxmlparser.o: tinyxmlparser.cpp
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rarian_sk_get_cl_CXXFLAGS) $(CXXFLAGS) -MT rarian_sk_get_cl-tinyxmlparser.o -MD -MP -MF $(DEPDIR)/rarian_sk_get_cl-tinyxmlparser.Tpo -c -o rarian_sk_get_cl-tinyxmlparser.o `test -f 'tinyxmlparser.cpp' || echo '$(srcdir)/'`tinyxmlparser.cpp
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/rarian_sk_get_cl-tinyxmlparser.Tpo $(DEPDIR)/rarian_sk_get_cl-tinyxmlparser.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='tinyxmlparser.cpp' object='rarian_sk_get_cl-tinyxmlparser.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rarian_sk_get_cl_CXXFLAGS) $(CXXFLAGS) -c -o rarian_sk_get_cl-tinyxmlparser.o `test -f 'tinyxmlparser.cpp' || echo '$(srcdir)/'`tinyxmlparser.cpp
+
+rarian_sk_get_cl-tinyxmlparser.obj: tinyxmlparser.cpp
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rarian_sk_get_cl_CXXFLAGS) $(CXXFLAGS) -MT rarian_sk_get_cl-tinyxmlparser.obj -MD -MP -MF $(DEPDIR)/rarian_sk_get_cl-tinyxmlparser.Tpo -c -o rarian_sk_get_cl-tinyxmlparser.obj `if test -f 'tinyxmlparser.cpp'; then $(CYGPATH_W) 'tinyxmlparser.cpp'; else $(CYGPATH_W) '$(srcdir)/tinyxmlparser.cpp'; fi`
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/rarian_sk_get_cl-tinyxmlparser.Tpo $(DEPDIR)/rarian_sk_get_cl-tinyxmlparser.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='tinyxmlparser.cpp' object='rarian_sk_get_cl-tinyxmlparser.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rarian_sk_get_cl_CXXFLAGS) $(CXXFLAGS) -c -o rarian_sk_get_cl-tinyxmlparser.obj `if test -f 'tinyxmlparser.cpp'; then $(CYGPATH_W) 'tinyxmlparser.cpp'; else $(CYGPATH_W) '$(srcdir)/tinyxmlparser.cpp'; fi`
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+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; nonemtpy = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ 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: $(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)
+ @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
+check-am: all-am
+check: check-am
+all-am: Makefile $(PROGRAMS) $(SCRIPTS)
+installdirs:
+ for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(bindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(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)
+ -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-exec-am: install-binPROGRAMS install-binSCRIPTS
+ @$(NORMAL_INSTALL)
+ $(MAKE) $(AM_MAKEFLAGS) install-exec-hook
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-ps: install-ps-am
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-binPROGRAMS uninstall-binSCRIPTS
+
+.MAKE: install-am install-exec-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \
+ clean-generic clean-libtool ctags distclean distclean-compile \
+ distclean-generic distclean-libtool distclean-tags distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-binPROGRAMS install-binSCRIPTS install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-exec-hook install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags uninstall uninstall-am uninstall-binPROGRAMS \
+ uninstall-binSCRIPTS
+
+
+@ENABLE_INSTALL_TRUE@install-exec-hook:
+@ENABLE_INSTALL_TRUE@@ENABLE_SK_COMPAT_TRUE@ @echo Moving Files if needed
+@ENABLE_INSTALL_TRUE@@ENABLE_SK_COMPAT_TRUE@ @if [ -h $(DESTDIR)$(bindir)/scrollkeeper-config ]; then rm $(DESTDIR)$(bindir)/scrollkeeper-config; \
+@ENABLE_INSTALL_TRUE@@ENABLE_SK_COMPAT_TRUE@ elif [ -e $(DESTDIR)$(bindir)/scrollkeeper-config ]; then \
+@ENABLE_INSTALL_TRUE@@ENABLE_SK_COMPAT_TRUE@ mv $(DESTDIR)$(bindir)/scrollkeeper-config $(DESTDIR)$(bindir)/scrollkeeper-config.real; fi
+@ENABLE_EXTRACT_TRUE@@ENABLE_INSTALL_TRUE@@ENABLE_SK_COMPAT_TRUE@ @if [ -h $(DESTDIR)$(bindir)/scrollkeeper-extract ]; then rm $(DESTDIR)$(bindir)/scrollkeeper-extract; \
+@ENABLE_EXTRACT_TRUE@@ENABLE_INSTALL_TRUE@@ENABLE_SK_COMPAT_TRUE@ elif [ -e $(DESTDIR)$(bindir)/scrollkeeper-extract ]; then \
+@ENABLE_EXTRACT_TRUE@@ENABLE_INSTALL_TRUE@@ENABLE_SK_COMPAT_TRUE@ mv $(DESTDIR)$(bindir)/scrollkeeper-extract $(DESTDIR)$(bindir)/scrollkeeper-extract.real; fi
+@ENABLE_INSTALL_TRUE@@ENABLE_SK_COMPAT_TRUE@ @if [ -h $(DESTDIR)$(bindir)/scrollkeeper-gen-seriesid ]; then rm $(DESTDIR)$(bindir)/scrollkeeper-gen-seriesid; \
+@ENABLE_INSTALL_TRUE@@ENABLE_SK_COMPAT_TRUE@ elif [ -e $(DESTDIR)$(bindir)/scrollkeeper-gen-seriesid ]; then \
+@ENABLE_INSTALL_TRUE@@ENABLE_SK_COMPAT_TRUE@ mv $(DESTDIR)$(bindir)/scrollkeeper-gen-seriesid $(DESTDIR)$(bindir)/scrollkeeper-gen-seriesid.real; fi
+@ENABLE_INSTALL_TRUE@@ENABLE_SK_COMPAT_TRUE@ @if [ -h $(DESTDIR)$(bindir)/scrollkeeper-get-cl ]; then rm $(DESTDIR)$(bindir)/scrollkeeper-get-cl; \
+@ENABLE_INSTALL_TRUE@@ENABLE_SK_COMPAT_TRUE@ elif [ -e $(DESTDIR)$(bindir)/scrollkeeper-get-cl ]; then \
+@ENABLE_INSTALL_TRUE@@ENABLE_SK_COMPAT_TRUE@ mv $(DESTDIR)$(bindir)/scrollkeeper-get-cl $(DESTDIR)$(bindir)/scrollkeeper-get-cl.real; fi
+@ENABLE_INSTALL_TRUE@@ENABLE_SK_COMPAT_TRUE@ @if [ -h $(DESTDIR)$(bindir)/scrollkeeper-get-content-list ]; then rm $(DESTDIR)$(bindir)/scrollkeeper-get-content-list; \
+@ENABLE_INSTALL_TRUE@@ENABLE_SK_COMPAT_TRUE@ elif [ -e $(DESTDIR)$(bindir)/scrollkeeper-get-content-list ]; then \
+@ENABLE_INSTALL_TRUE@@ENABLE_SK_COMPAT_TRUE@ mv $(DESTDIR)$(bindir)/scrollkeeper-get-content-list $(DESTDIR)$(bindir)/scrollkeeper-get-content-list.real; fi
+@ENABLE_INSTALL_TRUE@@ENABLE_SK_COMPAT_TRUE@ @if [ -h $(DESTDIR)$(bindir)/scrollkeeper-get-extended-content-list ]; then rm $(DESTDIR)$(bindir)/scrollkeeper-get-extended-content-list; \
+@ENABLE_INSTALL_TRUE@@ENABLE_SK_COMPAT_TRUE@ elif [ -e $(DESTDIR)$(bindir)/scrollkeeper-get-extended-content-list ]; then \
+@ENABLE_INSTALL_TRUE@@ENABLE_SK_COMPAT_TRUE@ mv $(DESTDIR)$(bindir)/scrollkeeper-get-extended-content-list $(DESTDIR)$(bindir)/scrollkeeper-get-extended-content-list.real; fi
+@ENABLE_INSTALL_TRUE@@ENABLE_SK_COMPAT_TRUE@ @if [ -h $(DESTDIR)$(bindir)/scrollkeeper-get-index-from-docpath ]; then rm $(DESTDIR)$(bindir)/scrollkeeper-get-index-from-docpath; \
+@ENABLE_INSTALL_TRUE@@ENABLE_SK_COMPAT_TRUE@ elif [ -e $(DESTDIR)$(bindir)/scrollkeeper-get-index-from-docpath ]; then \
+@ENABLE_INSTALL_TRUE@@ENABLE_SK_COMPAT_TRUE@ mv $(DESTDIR)$(bindir)/scrollkeeper-get-index-from-docpath $(DESTDIR)$(bindir)/scrollkeeper-get-index-from-docpath.real; fi
+@ENABLE_INSTALL_TRUE@@ENABLE_SK_COMPAT_TRUE@ @if [ -h $(DESTDIR)$(bindir)/scrollkeeper-get-toc-from-docpath ]; then rm $(DESTDIR)$(bindir)/scrollkeeper-get-toc-from-docpath; \
+@ENABLE_INSTALL_TRUE@@ENABLE_SK_COMPAT_TRUE@ elif [ -e $(DESTDIR)$(bindir)/scrollkeeper-get-toc-from-docpath ]; then \
+@ENABLE_INSTALL_TRUE@@ENABLE_SK_COMPAT_TRUE@ mv $(DESTDIR)$(bindir)/scrollkeeper-get-toc-from-docpath $(DESTDIR)$(bindir)/scrollkeeper-get-toc-from-docpath.real; fi
+@ENABLE_INSTALL_TRUE@@ENABLE_SK_COMPAT_TRUE@ @if [ -h $(DESTDIR)$(bindir)/scrollkeeper-get-toc-from-id ]; then rm $(DESTDIR)$(bindir)/scrollkeeper-get-toc-from-id; \
+@ENABLE_INSTALL_TRUE@@ENABLE_SK_COMPAT_TRUE@ elif [ -e $(DESTDIR)$(bindir)/scrollkeeper-get-toc-from-id ]; then \
+@ENABLE_INSTALL_TRUE@@ENABLE_SK_COMPAT_TRUE@ mv $(DESTDIR)$(bindir)/scrollkeeper-get-toc-from-id $(DESTDIR)$(bindir)/scrollkeeper-get-toc-from-id.real; fi
+@ENABLE_INSTALL_TRUE@@ENABLE_SK_COMPAT_TRUE@ @if [ -h $(DESTDIR)$(bindir)/scrollkeeper-install ]; then rm $(DESTDIR)$(bindir)/scrollkeeper-install; \
+@ENABLE_INSTALL_TRUE@@ENABLE_SK_COMPAT_TRUE@ elif [ -e $(DESTDIR)$(bindir)/scrollkeeper-install ]; then \
+@ENABLE_INSTALL_TRUE@@ENABLE_SK_COMPAT_TRUE@ mv $(DESTDIR)$(bindir)/scrollkeeper-install $(DESTDIR)$(bindir)/scrollkeeper-install.real; fi
+@ENABLE_INSTALL_TRUE@@ENABLE_SK_COMPAT_TRUE@ @if [ -h $(DESTDIR)$(bindir)/scrollkeeper-preinstall ]; then rm $(DESTDIR)$(bindir)/scrollkeeper-preinstall; \
+@ENABLE_INSTALL_TRUE@@ENABLE_SK_COMPAT_TRUE@ elif [ -e $(DESTDIR)$(bindir)/scrollkeeper-preinstall ]; then \
+@ENABLE_INSTALL_TRUE@@ENABLE_SK_COMPAT_TRUE@ mv $(DESTDIR)$(bindir)/scrollkeeper-preinstall $(DESTDIR)$(bindir)/scrollkeeper-preinstall.real; fi
+@ENABLE_INSTALL_TRUE@@ENABLE_SK_COMPAT_TRUE@ @if [ -h $(DESTDIR)$(bindir)/scrollkeeper-rebuilddb ]; then rm $(DESTDIR)$(bindir)/scrollkeeper-rebuilddb; \
+@ENABLE_INSTALL_TRUE@@ENABLE_SK_COMPAT_TRUE@ elif [ -e $(DESTDIR)$(bindir)/scrollkeeper-rebuilddb ]; then \
+@ENABLE_INSTALL_TRUE@@ENABLE_SK_COMPAT_TRUE@ mv $(DESTDIR)$(bindir)/scrollkeeper-rebuilddb $(DESTDIR)$(bindir)/scrollkeeper-rebuilddb.real; fi
+@ENABLE_INSTALL_TRUE@@ENABLE_SK_COMPAT_TRUE@ @if [ -h $(DESTDIR)$(bindir)/scrollkeeper-uninstall ]; then rm $(DESTDIR)$(bindir)/scrollkeeper-uninstall; \
+@ENABLE_INSTALL_TRUE@@ENABLE_SK_COMPAT_TRUE@ elif [ -e $(DESTDIR)$(bindir)/scrollkeeper-uninstall ]; then \
+@ENABLE_INSTALL_TRUE@@ENABLE_SK_COMPAT_TRUE@ mv $(DESTDIR)$(bindir)/scrollkeeper-uninstall $(DESTDIR)$(bindir)/scrollkeeper-uninstall.real; fi
+@ENABLE_INSTALL_TRUE@@ENABLE_SK_COMPAT_TRUE@ @if [ -h $(DESTDIR)$(bindir)/scrollkeeper-update ]; then rm $(DESTDIR)$(bindir)/scrollkeeper-update; \
+@ENABLE_INSTALL_TRUE@@ENABLE_SK_COMPAT_TRUE@ elif [ -e $(DESTDIR)$(bindir)/scrollkeeper-update ]; then \
+@ENABLE_INSTALL_TRUE@@ENABLE_SK_COMPAT_TRUE@ mv $(DESTDIR)$(bindir)/scrollkeeper-update $(DESTDIR)$(bindir)/scrollkeeper-update.real; fi
+@ENABLE_INSTALL_TRUE@@ENABLE_SK_COMPAT_TRUE@ @cd $(DESTDIR)$(bindir); ln -s rarian-sk-config scrollkeeper-config
+@ENABLE_EXTRACT_TRUE@@ENABLE_INSTALL_TRUE@@ENABLE_SK_COMPAT_TRUE@ @cd $(DESTDIR)$(bindir); ln -s rarian-sk-extract scrollkeeper-extract
+@ENABLE_INSTALL_TRUE@@ENABLE_SK_COMPAT_TRUE@ @cd $(DESTDIR)$(bindir); ln -s rarian-sk-gen-uuid scrollkeeper-gen-seriesid
+@ENABLE_INSTALL_TRUE@@ENABLE_SK_COMPAT_TRUE@ @cd $(DESTDIR)$(bindir); ln -s rarian-sk-get-cl scrollkeeper-get-cl
+@ENABLE_INSTALL_TRUE@@ENABLE_SK_COMPAT_TRUE@ @cd $(DESTDIR)$(bindir); ln -s rarian-sk-get-content-list scrollkeeper-get-content-list
+@ENABLE_INSTALL_TRUE@@ENABLE_SK_COMPAT_TRUE@ @cd $(DESTDIR)$(bindir); ln -s rarian-sk-get-extended-content-list scrollkeeper-get-extended-content-list
+@ENABLE_INSTALL_TRUE@@ENABLE_SK_COMPAT_TRUE@ @cd $(DESTDIR)$(bindir); ln -s rarian-sk-get-scripts scrollkeeper-get-index-from-docpath
+@ENABLE_INSTALL_TRUE@@ENABLE_SK_COMPAT_TRUE@ @cd $(DESTDIR)$(bindir); ln -s rarian-sk-get-scripts scrollkeeper-get-toc-from-docpath
+@ENABLE_INSTALL_TRUE@@ENABLE_SK_COMPAT_TRUE@ @cd $(DESTDIR)$(bindir); ln -s rarian-sk-get-scripts scrollkeeper-get-toc-from-id
+@ENABLE_INSTALL_TRUE@@ENABLE_SK_COMPAT_TRUE@ @cd $(DESTDIR)$(bindir); ln -s rarian-sk-install scrollkeeper-install
+@ENABLE_INSTALL_TRUE@@ENABLE_SK_COMPAT_TRUE@ @cd $(DESTDIR)$(bindir); ln -s rarian-sk-preinstall scrollkeeper-preinstall
+@ENABLE_INSTALL_TRUE@@ENABLE_SK_COMPAT_TRUE@ @cd $(DESTDIR)$(bindir); ln -s rarian-sk-rebuild scrollkeeper-rebuilddb
+@ENABLE_INSTALL_TRUE@@ENABLE_SK_COMPAT_TRUE@ @cd $(DESTDIR)$(bindir); ln -s rarian-sk-install scrollkeeper-uninstall
+@ENABLE_INSTALL_TRUE@@ENABLE_SK_COMPAT_TRUE@ @cd $(DESTDIR)$(bindir); ln -s rarian-sk-update scrollkeeper-update
+@ENABLE_INSTALL_TRUE@@ENABLE_SK_COMPAT_TRUE@ @mkdir -p $(DESTDIR)/$(localstatedir)/lib/rarian
+@ENABLE_INSTALL_TRUE@@ENABLE_SKDB_UPDATE_TRUE@@ENABLE_SK_COMPAT_TRUE@ @echo "Translating current database"
+@ENABLE_INSTALL_TRUE@@ENABLE_SKDB_UPDATE_TRUE@@ENABLE_SK_COMPAT_TRUE@ @$(DESTDIR)$(bindir)/rarian-sk-update
+
+@ENABLE_INSTALL_FALSE@install-exec-hook:
+@ENABLE_INSTALL_FALSE@ @echo WARNING: Installed in UNINSTALLED mode. Prepare for things to be broken!!!!!
+# 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/util/rarian-example.c b/util/rarian-example.c
new file mode 100644
index 0000000..d203a19
--- /dev/null
+++ b/util/rarian-example.c
@@ -0,0 +1,122 @@
+/*
+ * rarian-example.c
+ * This file is part of Rarian
+ *
+ * Copyright (C) 2006 - Don Scorgie
+ *
+ * Rarian is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Rarian is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Rarian; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#define I_KNOW_RARIAN_0_8_IS_UNSTABLE
+#include <rarian.h>
+
+void
+print_section (RrnSect *sect, int depth)
+{
+ int i=0;
+ RrnSect *child;
+ for (i=0; i < depth; i++) {
+ printf (" ");
+ }
+ printf ("Child: %s\n", sect->name);
+ for (i=0; i < depth; i++) {
+ printf (" ");
+ }
+ printf ("-> %s\n\n", sect->uri);
+ child = sect->children;
+
+ while (child) {
+ print_section (child, depth+1);
+ child = child->next;
+ }
+
+}
+
+int
+for_each_cb (RrnReg *reg, void * user_data)
+{
+ RrnSect *sect;
+ char **cats;
+ if (!reg) {
+ printf ("Error: No reg passed in!\n");
+ exit (6);
+ }
+ printf ("Document: %s\n", reg->name);
+ printf ("-> %s\n", reg->uri);
+ printf ("-> ghelp:%s\n", reg->ghelp_name);
+ cats = reg->categories;
+ if (cats && *cats)
+ printf ("Categories:\n");
+ while (cats && *cats) {
+ printf ("-> %s\n", *cats);
+ cats++;
+ }
+ printf ("\n");
+
+ sect = reg->children;
+ while (sect) {
+ print_section (sect, 1);
+ sect = sect->next;
+ }
+
+ return TRUE;
+}
+
+info_for_each (RrnInfoEntry *entry, void *data)
+{
+ if (entry->section)
+ printf ("Info page: %s\n\tPath: %s#%s\n\tComment: %s\n",
+ entry->doc_name, entry->base_filename,
+ entry->section, entry->comment);
+ else
+ printf ("Info page: %s\n\tPath: %s\n\tComment: %s\n",
+ entry->doc_name, entry->base_filename,
+ entry->comment);
+ return TRUE;
+}
+
+man_for_each (RrnManEntry *entry, void *data)
+{
+ printf ("Man page %s\n", entry->name);
+ printf ("\tPath: %s\n", entry->path);
+ return TRUE;
+}
+
+int
+main(int argc, char *argv[])
+{
+ char **cats = rrn_info_get_categories ();
+ char **iter = cats;
+
+ rrn_man_for_each ((RrnManForeachFunc) man_for_each, NULL);
+
+ while (iter && *iter) {
+ printf ("Info category: %s\n", *iter);
+ iter++;
+ }
+
+ rrn_info_for_each ((RrnInfoForeachFunc) info_for_each, NULL);
+
+ rrn_for_each((RrnForeachFunc) for_each_cb, NULL);
+
+ rrn_shutdown ();
+ rrn_info_shutdown ();
+ rrn_man_shutdown ();
+
+ return 0;
+}
diff --git a/util/rarian-sk-config.in b/util/rarian-sk-config.in
new file mode 100644
index 0000000..c0ffbf0
--- /dev/null
+++ b/util/rarian-sk-config.in
@@ -0,0 +1,78 @@
+#!@BASH@
+
+# Yet another simple wrapper for scrollkeeper wierdness
+# This one emulates scrollkeeper-config,
+# bugs and all.
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+bindir=@bindir@
+convert_dir=@CONVERT_DIR@
+statedir=@localstatedir@/lib/rarian
+datarootdir=@datarootdir@
+datadir=@datadir@
+output_dir=${datadir}/help
+package_version=@PACKAGE_VERSION@
+omf_read_enabled=@ENABLE_OMF_READ@
+
+
+print_help()
+{
+ echo "Usage: `basename $0` [OPTION]"
+ echo "(Rarian replacement for scrollkeeper-config)"
+ echo ""
+ echo "OPTION is one of:"
+ echo ""
+ echo -e " --help\t\tDisplay this message and exit"
+ echo -e " --version\t\tDisplay version for this package"
+ echo -e " --prefix\t\tPrint install directory"
+ echo -e " --localstatedir\t\tprint localstatedir used at package build time"
+ echo -e " --pkglocalstatedir\t\tprintscrollkeeper data directory"
+ echo -e " --pkgdatadir\t\tprint scrollkeeper home directory"
+ echo -e " --omfdir\t\t print OMF files directories (one per line)"
+
+
+
+
+}
+
+if [[ $# != 1 ]]
+then
+ print_help
+ exit
+fi
+
+case "$1" in
+ --help )
+ print_help
+ ;;
+ --version )
+ echo $package_version \(Rarian replacement for scrollkeeper-config\)
+ ;;
+ --prefix )
+ echo $prefix
+ ;;
+ --localstatedir )
+ echo $statedir
+ ;;
+ --pkglocalstatedir )
+ echo $statedir
+ ;;
+ --pkgdatadir )
+ echo $datadir/librarian
+ ;;
+ --omfdir )
+ if [ $omf_read_enabled = 0 ]
+ then
+ for x in $(grep -e '^0:@:' $statedir/rarian-update-mtimes > /dev/null 2>&1)
+ do
+ echo ${x##0:@:}
+ done
+ else
+ echo $datadir/omf
+ fi
+ ;;
+ * )
+ print_help
+ ;;
+ esac
diff --git a/util/rarian-sk-extract.in b/util/rarian-sk-extract.in
new file mode 100644
index 0000000..c7adaef
--- /dev/null
+++ b/util/rarian-sk-extract.in
@@ -0,0 +1,31 @@
+#!@BASH@
+
+# Wrapper around xsltproc to mimic scrollkeeper-extract.
+#
+# Note that scrollkeeper internally uses libxslt for
+# this, so this method is cheaper and achieves the same result
+
+print_usage()
+{
+ echo -e "Usage: "
+ echo -e "`basename $0` <xml file> <stylesheet 1> <output file 1> <stylesheet 2> <output file 2> ..."
+}
+
+if [[ $# < 2 ]]
+then
+ print_usage
+ exit 0
+fi
+
+infile=$1
+shift 1
+
+while true; do
+ xsltproc --xinclude --xincludestyle $1 $infile > $2
+ #echo "xml: $infile style: $1 out: $2"
+ shift 2
+ if [[ $# < 2 ]];
+ then
+ break
+ fi
+done \ No newline at end of file
diff --git a/util/rarian-sk-gen-uuid.c b/util/rarian-sk-gen-uuid.c
new file mode 100644
index 0000000..2fa0a31
--- /dev/null
+++ b/util/rarian-sk-gen-uuid.c
@@ -0,0 +1,70 @@
+/*
+ * rarian-sk-gen-uuid.c
+ * This file is part of Rarian
+ *
+ * Copyright (C) 2006 - Don scorgie
+ *
+ * Rarian is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Rarian is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Rarian; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+#include <time.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+int main (int argc, char *argv[])
+{
+ int i;
+ char *rand_string;//[38];
+ char *tmp;
+ unsigned int r;
+
+ r = time(NULL);
+
+ tmp = malloc (sizeof(char) *2);
+ rand_string = malloc (sizeof(char) * 39);
+ *rand_string = '0';
+
+ srand (r);
+ for (i=0; i<8; i++) {
+ sprintf(tmp, "%x", (int) (((rand()*1.0) / (RAND_MAX*1.0)) * 16));
+ strcat (rand_string, tmp);
+ }
+ rand_string[i] = '-';
+ for (i=9; i < 13; i++) {
+ sprintf(tmp, "%x", (int) (((rand()*1.0) / (RAND_MAX*1.0)) * 16));
+ strcat (rand_string, tmp);
+ }
+ rand_string[i] = '-';
+ for (i=14; i < 18; i++) {
+ sprintf(tmp, "%x", (int) (((rand()*1.0) / (RAND_MAX*1.0)) * 16));
+ strcat (rand_string, tmp);
+ }
+ rand_string[i] = '-';
+ for (i=19; i < 23; i++) {
+ sprintf(tmp, "%x", (int) (((rand()*1.0) / (RAND_MAX*1.0)) * 16));
+ strcat (rand_string, tmp);
+ }
+ rand_string[i] = '-';
+ for (i=24; i < 37; i++) {
+ sprintf(tmp, "%x", (int) (((rand()*1.0) / (RAND_MAX*1.0)) * 16));
+ strcat (rand_string, tmp);
+ }
+
+ rand_string[i] = '0';
+ printf ("%s\n", rand_string);
+ return 0;
+}
diff --git a/util/rarian-sk-get-cl.cpp b/util/rarian-sk-get-cl.cpp
new file mode 100644
index 0000000..776b64c
--- /dev/null
+++ b/util/rarian-sk-get-cl.cpp
@@ -0,0 +1,236 @@
+/*
+ * rarian-sk-get-cl.cpp
+ * This file is part of Rarian
+ *
+ * Copyright (C) 2006 - Don scorgie
+ *
+ * Rarian is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Rarian is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Rarian; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+#define I_KNOW_RARIAN_0_8_IS_UNSTABLE
+#include <rarian.h>
+#include <rarian-utils.h>
+#include <tinyxml.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+static char *cat = NULL;
+static TiXmlElement *docs = NULL;
+static int id = 0;
+
+void
+print_usage (char *proc_name)
+{
+ printf ("Usage: %s <LOCALE> <CAT TREE NAME>\n", proc_name);
+ exit (0);
+}
+
+void
+get_attribute (TiXmlElement *elem)
+{
+ TiXmlAttribute* pAttrib=elem->FirstAttribute();
+ if (strcmp (pAttrib->Value(), "")) {
+ char *new_cat = NULL;
+ char *iter = NULL;
+ char *st_iter = NULL;
+ char *tmp = NULL;
+
+ cat = strdup (pAttrib->Value());
+ /* Fix category to mimic scrollkeeper */
+ new_cat = (char *) calloc (sizeof(char), strlen (cat));
+
+ st_iter = cat;
+ iter = cat;
+ while (iter && *iter) {
+ while (iter && *iter && *iter != '|') {
+ iter++;
+ }
+ tmp = rrn_strndup (st_iter, (iter-st_iter));
+ if (*new_cat) {
+ strcat (new_cat, tmp);
+ } else {
+ strcpy (new_cat, tmp);
+ }
+ free (tmp);
+ if (*iter == '|')
+ iter++;
+ else
+ break;
+ st_iter = iter;
+ }
+ elem->SetAttribute("categorycode", new_cat);
+
+ }
+}
+
+int
+get_docs (RrnReg *reg, TiXmlNode *pParent)
+{
+ if (reg->omf_location) {
+ TiXmlElement * doc = new TiXmlElement ("doc");
+ TiXmlElement * entry;
+ TiXmlElement * text;
+ char *tmp;
+
+ doc->SetAttribute ("id", id);
+ id++;
+
+ /* doctitle */
+ entry = new TiXmlElement ("doctitle");
+ entry->LinkEndChild (new TiXmlText (reg->name));
+ doc->LinkEndChild (entry);
+
+ /* docomf */
+ entry = new TiXmlElement ("docomf");
+ entry->LinkEndChild (new TiXmlText (reg->omf_location));
+ doc->LinkEndChild (entry);
+
+ /* docsource */
+ tmp = reg->uri + 7;// Remove file://
+ entry = new TiXmlElement ("docsource");
+ entry->LinkEndChild (new TiXmlText (tmp));
+ doc->LinkEndChild (entry);
+
+ /* docformat */
+ entry = new TiXmlElement ("docformat");
+ entry->LinkEndChild (new TiXmlText (reg->type));
+ doc->LinkEndChild (entry);
+
+ /* docseriesid */
+ tmp = reg->identifier + 17;// remove org.scrollkeeper.
+ entry = new TiXmlElement ("docseriesid");
+ entry->LinkEndChild (new TiXmlText (tmp));
+ doc->LinkEndChild (entry);
+ pParent->LinkEndChild (doc);
+
+ }
+
+ return 0;
+}
+
+void
+process_node (TiXmlNode *pParent)
+{
+ TiXmlNode* pChild;
+ TiXmlText* pText;
+ int t = pParent->Type();
+ int num;
+
+ switch ( t )
+ {
+ case TiXmlNode::DOCUMENT:
+ break;
+
+ case TiXmlNode::ELEMENT:
+ if (!strcmp (pParent->Value(), "sect")) {
+ get_attribute (pParent->ToElement());
+ rrn_for_each_in_category ((RrnForeachFunc) get_docs, cat, pParent);
+ free (cat);
+
+ }
+ default:
+ break;
+ }
+
+ for ( pChild = pParent->FirstChild(); pChild != 0; pChild = pChild->NextSibling())
+ {
+ process_node ( pChild);
+ }
+}
+
+
+/* Find a suitable file to dump out output to.
+ * for now, we're always going to the same file
+ */
+char *
+find_dump_name ()
+{
+ char *filename = NULL;
+ char *user = getenv ("USERNAME");
+ char *basepath = NULL;
+ int i=0;
+ int last = 0;
+ unsigned int lasttime = 0;
+ int init = 1;
+
+ if (!user) {
+ /* if USERNAME isn't set, we use the "default" username: UNKNOWN */
+ user = strdup ("UNKNOWN");
+ }
+
+ basepath = (char *) malloc (sizeof(char) * (strlen(user) + 18 /*/tmp/scrollkeeper.*/ + 1));
+ sprintf (basepath, "/tmp/scrollkeeper-%s", user);
+ mkdir(basepath, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
+
+
+ filename = (char *) malloc (sizeof(char) * (strlen(user) + 18 /*/tmp/scrollkeeper.*/ + 10 /*contents.0*/) + 1);
+
+ for (i=0 ;i<5; i++) {
+ struct stat sbuf;
+ sprintf (filename, "/tmp/scrollkeeper-%s/contents.%d", user, i);
+ if (stat(filename,&sbuf) == -1) {
+ last = i;
+ break;
+ }
+ if (sbuf.st_mtime < lasttime || init) {
+ init = 0;
+ last = i;
+ lasttime = sbuf.st_mtime;
+ }
+ }
+ sprintf (filename, "/tmp/scrollkeeper-%s/contents.%d", user, last);
+
+ return filename;
+}
+
+int main (int argc, char * argv[])
+{
+ int skip = 0;
+
+ if (argc < 3 || argc > 4) {
+ print_usage (argv[0]);
+ }
+ if (!strcmp(argv[1], "-v")) {
+ skip = 1;
+ }
+
+ if (strcmp (argv[2+skip], "scrollkeeper_extended_cl.xml") &&
+ strcmp (argv[2+skip], "scrollkeeper_cl.xml")) {
+ print_usage (argv[0]);
+ }
+ bool loadok;
+
+ rrn_set_language (argv[1+skip]);
+
+ TiXmlDocument doc (DATADIR"/librarian/rarian-sk-cl.xml");
+ loadok = doc.LoadFile(TIXML_ENCODING_UTF8);
+
+ if (!loadok) {
+ fprintf (stderr, "ERROR: Cannot parse template file. Aborting.\n");
+ exit (2);
+ }
+
+ TiXmlNode *pParent = doc.FirstChildElement();
+
+ process_node (pParent);
+
+ char *filename = find_dump_name ();
+ doc.SaveFile(filename);
+ printf ("%s\n", filename);
+
+ exit (0);
+
+}
diff --git a/util/rarian-sk-get-content-list.in b/util/rarian-sk-get-content-list.in
new file mode 100644
index 0000000..b123774
--- /dev/null
+++ b/util/rarian-sk-get-content-list.in
@@ -0,0 +1,23 @@
+#! /bin/sh
+
+# Simple wrapper to make calling scrollkeeper-get-cl easier
+# Copied and edited from scrollkeeper source tree
+
+usage()
+{
+ cat <<EOF
+Usage: `basename $0` <LOCALE>
+EOF
+
+ exit $1
+}
+
+if test $# -ne 1; then
+ usage 1
+fi
+
+# Assume we're installed in the same place as get-cl
+# If it ain't in the normal path, this is needed
+`dirname $0`/rarian-sk-get-cl $1 scrollkeeper_cl.xml
+
+exit $? \ No newline at end of file
diff --git a/util/rarian-sk-get-extended-content-list.in b/util/rarian-sk-get-extended-content-list.in
new file mode 100644
index 0000000..a20444a
--- /dev/null
+++ b/util/rarian-sk-get-extended-content-list.in
@@ -0,0 +1,23 @@
+#! /bin/sh
+
+# Simple wrapper to make calling scrollkeeper-get-cl (extended) easier
+# Copied and edited from scrollkeeper source tree
+
+usage()
+{
+ cat <<EOF
+Usage: `basename $0` <LOCALE>
+EOF
+
+ exit $1
+}
+
+if test $# -ne 1; then
+ usage 1
+fi
+
+# Assume we're installed in the same place as get-cl
+# If it ain't in the normal path, this is needed
+`dirname $0`/rarian-sk-get-cl $1 scrollkeeper_extended_cl.xml
+
+exit $? \ No newline at end of file
diff --git a/util/rarian-sk-get-scripts.in b/util/rarian-sk-get-scripts.in
new file mode 100644
index 0000000..eec1980
--- /dev/null
+++ b/util/rarian-sk-get-scripts.in
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+# More zero-effect scripts. The scripts these replace seem to
+# not do anything on my machine (any files they try and access
+# don't exist). Therefore, they get ignored for now, since
+# I've never even seen them used. Ever. Sigh.
+
+# replaces:
+# scrollkeeper-get-index-from-index-from-docpath
+# scrollkeeper-get-toc-from-docpath
+# scrollkeeper-get-toc-from-id
+
+exit \ No newline at end of file
diff --git a/util/rarian-sk-install.in b/util/rarian-sk-install.in
new file mode 100644
index 0000000..ba514d0
--- /dev/null
+++ b/util/rarian-sk-install.in
@@ -0,0 +1,30 @@
+#!/bin/sh
+
+# A simple replacement for scrollkeeper-install / scrollkeeper-uninstall
+# scrollkeeper-preinstall
+# The real program install program is called from scrollkeeper-update
+# The real uninstall program isn't used. Ever.
+# scrollkeeper-preinstall is another random program. I've read the
+# source and still can't figure out exactly what it does. It seems
+# to do some stuff that should be really done by configure scripts
+# (replacing the docpath with another)
+
+# In the New World Order, these are unneccessary, so we just ignore
+# them and exit happily.
+
+# However, since these are installed and available for use, we
+# have to "emulate" them by (basically) returning true.
+# Don't ever ask me why scrollkeeper works the way it does. I'll
+# bore you to tears.
+
+# Anyway, if you've read this far, the license for this file is simple:
+# Use it however you want. Seriously, if you want to give me credit
+# for an empty file, go ahead. Use it any way you want. I offer
+# no guarentees about functioning correctly, however since the script
+# is simpler than "Hello World", I don't think it'll go wrong.
+
+# We ignore all user input and return
+# Update.
+
+
+exit 0 \ No newline at end of file
diff --git a/util/rarian-sk-migrate.cpp b/util/rarian-sk-migrate.cpp
new file mode 100644
index 0000000..4294eb3
--- /dev/null
+++ b/util/rarian-sk-migrate.cpp
@@ -0,0 +1,313 @@
+/*
+ * rarian-sk-migrate.cpp
+ * This file is part of Rarian
+ *
+ * Copyright (C) 2006 - Don scorgie
+ *
+ * Rarian is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Rarian is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Rarian; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dirent.h>
+#include <unistd.h>
+
+#include <tinyxml.h>
+#define I_KNOW_RARIAN_0_8_IS_UNSTABLE
+#include <rarian.h>
+#include <rarian-reg-full.h>
+
+#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <time.h>
+
+static RrnRegFull *reg = NULL;
+static RrnReg *tmp_reg = NULL;
+static char *lang;
+static char *sk_series;
+static char *new_series;
+static char *type;
+static char *categories;
+
+static bool am_parsing = false;
+
+enum ElemType {
+ REG_NAME,
+ REG_URI,
+ REG_DESC,
+ REG_LANG,
+ REG_SERIES,
+ REG_TYPE,
+ REG_CATEGORIES
+};
+
+void
+dump_extended_keyfile (char *path, char *base)
+{
+ RrnListEntry *iter;
+
+ printf ("# File generated from scrollkeeper files %s/%s-*.omf\n", path, base);
+ printf ("# This should be replaced by the new keyfile at some point");
+
+ printf ("\n[Document]\n\n");
+
+ iter = reg->name;
+ while (iter) {
+ if (!iter->lang || !strcmp (iter->lang, "C")) {
+ printf ("Name=%s\n", iter->text);
+ } else {
+ printf ("Name[%s]=%s\n", iter->lang, iter->text);
+ }
+ iter = iter->next;
+ }
+ iter = reg->comment;
+ while (iter) {
+ if (!iter->lang || !strcmp (iter->lang, "C")) {
+ printf ("Comment=%s\n", iter->text);
+ } else {
+ printf ("Comment[%s]=%s\n", iter->lang, iter->text);
+ }
+ iter = iter->next;
+ }
+ iter = reg->uri;
+ while (iter) {
+ if (!iter->lang || !strcmp (iter->lang, "C")) {
+ printf ("DocPath=%s\n", iter->text);
+ } else {
+ printf ("DocPath[%s]=%s\n", iter->lang, iter->text);
+ }
+ iter = iter->next;
+ }
+ if (type) {
+ printf ("DocType=%s\n", type);
+ } else {
+ printf ("DocType=\n");
+ }
+ if (new_series) {
+ printf ("DocIdentifier=%s\n", new_series);
+ } else {
+ fprintf (stderr, "ERROR: new series is undefined!\n");
+ }
+ if (categories) {
+ printf ("Categories=%s\n", categories);
+ }
+ if (new_series) {
+ printf ("x-DocHeritage=%s\n", new_series);
+ }
+ printf ("x-Scrollkeeper-omf-loc=%s/%s-*.omf\n", path, base);
+
+}
+
+
+void
+add_info ()
+{
+ if (!lang) {
+ lang = strdup ("C");
+ }
+ reg->uri = rrn_full_add_field (reg->uri, tmp_reg->uri, lang);
+ reg->comment = rrn_full_add_field (reg->comment, tmp_reg->comment, lang);
+ reg->name = rrn_full_add_field (reg->name, tmp_reg->name, lang);
+
+}
+
+void
+get_attribute (TiXmlElement *elem, ElemType e)
+{
+ TiXmlAttribute* pAttrib=elem->FirstAttribute();
+ if (e == REG_URI && strcmp (pAttrib->Value(), "")) {
+ tmp_reg->uri = strdup (pAttrib->Value());
+ } else if (e == REG_URI && !strcmp(pAttrib->Value(), "")){
+ tmp_reg->uri = strdup ("");
+ } else if (e == REG_LANG) {
+ if (strcmp (pAttrib->Value(), "")) {
+ lang = strdup (pAttrib->Value());
+ }
+ } else if (e == REG_SERIES) {
+ if (strcmp (pAttrib->Value(), "")) {
+ if (!sk_series) {
+ sk_series = strdup (pAttrib->Value());
+ }
+ }
+ } else if (e == REG_TYPE && strcmp (pAttrib->Value(), "")) {
+ if (!type) {
+ type = strdup (pAttrib->Value());
+ }
+ } else if (e == REG_TYPE && !strcmp (pAttrib->Value(), "")) {
+ /* Do nothing */
+ } else if (e == REG_CATEGORIES && strcmp (pAttrib->Value(), "")) {
+ if (!categories) {
+ categories = strdup (pAttrib->Value());
+ }
+ } else if (e == REG_CATEGORIES && !strcmp (pAttrib->Value(), "")) {
+ /* Do Nothing */
+ } else {
+ printf ("ERROR: Trying to get attribute from unknown entry type. Exiting\n");
+ exit (7);
+ }
+}
+
+void
+get_text (TiXmlNode* pElement, ElemType e)
+{
+
+ if (!pElement) {
+ if (e == REG_NAME) {
+ tmp_reg->name = strdup (" ");
+ } else {
+ tmp_reg->comment = strdup (" ");
+ }
+ return;
+ }
+ if (e == REG_NAME) {
+ tmp_reg->name = strdup (pElement->Value());
+ } else if (e == REG_DESC ) {
+ tmp_reg->comment = strdup (pElement->Value());
+ }
+
+}
+
+void
+process_node (TiXmlNode *pParent)
+{
+ TiXmlNode* pChild;
+ TiXmlText* pText;
+ int t = pParent->Type();
+ int num;
+ ElemType e;
+
+
+ switch ( t )
+ {
+ case TiXmlNode::DOCUMENT:
+ break;
+
+ case TiXmlNode::ELEMENT:
+ if (!strcmp (pParent->Value(), "omf")) {
+ am_parsing = true;
+ } else if (!am_parsing) {
+ printf ("ERROR: Does not appear to be a valid OMF file. Aborting\n");
+ exit (6);
+ }
+ if (!strcmp (pParent->Value(), "title")) {
+ e = REG_NAME;
+ get_text (pParent->FirstChild(), e);
+ } else if (!strcmp (pParent->Value(), "description")) {
+ e = REG_DESC;
+ get_text (pParent->FirstChild(), e);
+ } else if (!strcmp (pParent->Value(), "identifier")) {
+ e = REG_URI;
+ get_attribute (pParent->ToElement(), e);
+ } else if (!strcmp (pParent->Value(), "language")) {
+ e = REG_LANG;
+ get_attribute (pParent->ToElement(), e);
+ } else if (!strcmp (pParent->Value(), "relation")) {
+ e = REG_SERIES;
+ get_attribute (pParent->ToElement(), e);
+ } else if (!strcmp (pParent->Value(), "format")) {
+ e = REG_TYPE;
+ get_attribute (pParent->ToElement(), e);
+ } else if (!strcmp (pParent->Value(), "subject")) {
+ e = REG_CATEGORIES;
+ get_attribute (pParent->ToElement(), e);
+ }
+ break;
+ default:
+ break;
+ }
+
+ for ( pChild = pParent->FirstChild(); pChild != 0; pChild = pChild->NextSibling())
+ {
+ process_node ( pChild);
+ }
+}
+
+void
+process_file (char *path, char *fname)
+{
+ char *name = NULL;
+ int size = 0;
+ bool loadok;
+
+ size += strlen (path);
+ size += strlen (fname);
+ size += 2;
+
+ tmp_reg = rrn_reg_new ();
+
+ name = (char *) malloc (sizeof (char) * size);
+ sprintf (name, "%s/%s", path, fname);
+
+ TiXmlDocument doc (name);
+ loadok = doc.LoadFile(TIXML_ENCODING_UTF8);
+
+ if (!loadok) {
+ fprintf (stderr, "ERROR: Cannot parse %s. Is it valid?\n", name);
+ exit (2);
+ }
+
+ TiXmlNode *pParent = doc.FirstChildElement();
+
+ process_node (pParent);
+
+ add_info ();
+
+ rrn_reg_free (tmp_reg);
+ free (name);
+}
+
+int main (int argc, char * argv[])
+{
+ DIR * dirp = NULL;
+ struct dirent * dp = NULL;
+ struct stat buf;
+ char *path = NULL;
+
+ if (argc != 3 || access (argv[1], R_OK)) {
+ fprintf (stderr, "ERROR: Cannot access directory %s\n", argv[1]);
+ }
+ reg = rrn_reg_new_full ();
+
+ dirp = opendir (argv[1]);
+ while (1) {
+ if ((dp = readdir(dirp)) != NULL) {
+ stat(dp->d_name,&buf);
+ if (buf.st_mode == S_IFREG && !strncmp (dp->d_name, argv[2], strlen (argv[2]))) {
+ process_file (argv[1], dp->d_name);
+ }
+ } else {
+ break;
+ }
+ }
+
+ if (sk_series) {
+ new_series = (char *) malloc (sizeof (char) * 255);
+ sprintf (new_series, "org.scrollkeeper.%s", sk_series);
+ } else {
+ time_t t1;
+
+ time(&t1);
+
+ new_series = (char *) malloc (sizeof (char) * 255);
+ sprintf (new_series, "org.scrollkeeper.undefined.%d", (long) t1);
+ }
+ dump_extended_keyfile (argv[1], argv[2]);
+
+ exit (0);
+}
diff --git a/util/rarian-sk-preinstall.cpp b/util/rarian-sk-preinstall.cpp
new file mode 100644
index 0000000..0bbff67
--- /dev/null
+++ b/util/rarian-sk-preinstall.cpp
@@ -0,0 +1,141 @@
+/*
+ * rarian-sk-preinstall.cpp
+ * This file is part of Rarian
+ *
+ * Copyright (C) 2006 - Don scorgie
+ *
+ * Rarian is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Rarian is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Rarian; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+
+#include <tinyxml.h>
+
+#include <stdio.h>
+
+static char *new_url = NULL;
+
+static bool am_parsing = false;
+
+void
+print_usage (char *proc_name)
+{
+ printf ("Usage: %s [-n] <INSTALLED_DOC_NAME> <OLD OMF FILE> <NEW OMF FILENAME>\n", proc_name);
+ printf ("\nExample: %s /usr/share/help/beanstalk.xml beanstalk.omf new-beanstalk.omf\n", proc_name);
+ printf ("The -n flag is now ignored (it is no longer needed).\n");
+ exit (0);
+}
+
+void
+get_attribute (TiXmlElement *elem)
+{
+ TiXmlAttribute* pAttrib=elem->FirstAttribute();
+ if (strcmp (pAttrib->Value(), "")) {
+
+ elem->SetAttribute("url", new_url);
+ }
+}
+
+void
+process_node (TiXmlNode *pParent)
+{
+ TiXmlNode* pChild;
+ TiXmlText* pText;
+ int t = pParent->Type();
+ int num;
+
+ switch ( t )
+ {
+ case TiXmlNode::DOCUMENT:
+ break;
+
+ case TiXmlNode::ELEMENT:
+ if (!strcmp (pParent->Value(), "omf")) {
+ am_parsing = true;
+ } else if (!am_parsing) {
+ printf ("ERROR: Does not appear to be a valid OMF file. Aborting\n");
+ exit (6);
+ }
+ if (!strcmp (pParent->Value(), "identifier")) {
+ get_attribute (pParent->ToElement());
+ }
+ default:
+ break;
+ }
+
+ for ( pChild = pParent->FirstChild(); pChild != 0; pChild = pChild->NextSibling())
+ {
+ process_node ( pChild);
+ }
+}
+
+void
+process_new_url (char *input)
+{
+ if (!strncmp (input, "file:", 5)) {
+ new_url = strdup (input);
+ } else {
+ int i = 0;
+ char *t = input;
+
+ while (*t == '/') {
+ i++;
+ t++;
+ }
+ if (i == 1) {
+ /* Normal path. Add file:/ to the start */
+ new_url = (char *) malloc (sizeof(char) * (strlen (input) + 7));
+ sprintf (new_url, "file:/%s", input);
+ } else {
+ /* Don't know what to do. Just copy and append file: to it */
+ new_url = (char *) malloc (sizeof(char) * (strlen(input) + 6));
+ sprintf (new_url, "file:%s", input);
+ }
+ }
+}
+
+int main (int argc, char * argv[])
+{
+ int skip = 0;
+ if (argc < 3 || argc > 4) {
+ print_usage (argv[0]);
+ }
+
+ if (!strcmp(argv[1], "-n"))
+ skip = 1;
+
+ process_new_url (argv[1+skip]);
+
+
+ bool loadok;
+
+ TiXmlDocument doc (argv[2+skip]);
+ loadok = doc.LoadFile(TIXML_ENCODING_UTF8);
+
+ if (!loadok) {
+ fprintf (stderr, "ERROR: Cannot parse %s. Is it valid?\n", argv[2+skip]);
+ exit (2);
+ }
+
+ TiXmlNode *pParent = doc.FirstChildElement();
+
+ process_node (pParent);
+
+ doc.SaveFile(argv[3+skip]);
+
+ free (new_url);
+
+ exit (0);
+}
diff --git a/util/rarian-sk-rebuild.in b/util/rarian-sk-rebuild.in
new file mode 100644
index 0000000..f79e9b0
--- /dev/null
+++ b/util/rarian-sk-rebuild.in
@@ -0,0 +1,38 @@
+#!@BASH@
+
+# Another simple wrapper script. This time for scrollkeeper-rebuilddb
+# This one is slightly more complex in that we have to run a command!
+# We also need to pull out the paths from the relevant place first.
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+bindir=@bindir@
+convert_dir=@CONVERT_DIR@
+datarootdir=@datarootdir@
+statedir=@localstatedir@/lib/rarian
+datadir=@datadir@
+output_dir=${datadir}/help
+package_version=@PACKAGE_VERSION@
+convert_string="REPLACEME"
+
+if [ ! @ENABLE_OMF_READ@ ]
+then
+
+if [ -e $statedir/rarian-update-mtimes ]
+then
+ for x in $(grep -e '^0:@:' $statedir/rarian-update-mtimes)
+ do
+ if [[ $convert_string != "REPLACEME" ]]
+ then
+ convert_string=$convert_string:${x##0:@:}
+ else
+ convert_string=${x##0:@:}
+ fi
+ done
+else
+ convert_string=$convert_dir
+fi
+
+$bindir/rarian-sk-update -v --clean-index -o $convert_string
+
+fi \ No newline at end of file
diff --git a/util/rarian-sk-update.in b/util/rarian-sk-update.in
new file mode 100755
index 0000000..8a26a9a
--- /dev/null
+++ b/util/rarian-sk-update.in
@@ -0,0 +1,425 @@
+#!@BASH@
+
+# This script is designed to replace scrollkeeper-update
+# It iterates through all the directories specified using -o <dir_list>
+# If these aren't specified, the default convert_dir is used
+# (typically /usr/share/omf) and checks whether the last-modified time for
+# the directory has changed from the previous run.
+# The previous timings are stored in output_dir/.rarian-update-mtimes
+# in the file format:
+# <mtime>:@:<dir_name>:@:<converted filenames>
+# For top-level directories, the mtime is '0'
+# When multiple scrolls are generated from a single omf subdir,
+# the scroll names are seperated by a semi-colon.
+
+# I'll annotate the rest of the scirpt
+# If you want more info, please ping me and I'll try and help.
+
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+bindir=@bindir@
+statedir=@localstatedir@/lib/rarian
+convert_dir=@CONVERT_DIR@
+datarootdir=@datarootdir@
+datadir=@datadir@
+output_dir=${datadir}/help
+package_version=@PACKAGE_VERSION@
+real_convert[0]=$convert_dir
+skip_omf_translate=@ENABLE_OMF_READ@
+
+# Print the version info for this file
+print_version()
+{
+ echo "`basename $0` version 0.9"
+ echo "This script is distributed as part of Rarian v$package_version"
+ echo "Use '`basename $0` --help' for options and instructions for running"
+ echo ""
+ echo "Have a nice day!"
+
+ exit 0
+}
+
+# Standard help message
+print_usage()
+{
+ echo "Usage: `basename $0` [OPTIONS]"
+ echo "Update Rarian scrolls archive from scrollkeeper omf files."
+ echo "Note: This script is a replacement for scrollkeeper-update, but"
+ echo "does not update the scrollkeeper internal database."
+ echo ""
+ echo "Options:"
+ echo -e "-o DIR\t\t\t\tUse the specified omf directories for"
+ echo -e "\t\t\t\tconversion. Multiple directories can be "
+ echo -e "\t\t\t\tspecified using colon (:) separator."
+ echo -e "-r DIR\t\t\t\tUse the specified directory for the"\
+ "resulting"
+ echo -e "\t\t\t\tscrolls. If the directory doesn't exist, it"
+ echo -e "\t\t\t\twill be created at run time."
+ echo -e "\t\t\t\t Note: Multiple output paths are not supported"
+ echo -e "--c\t\t\t\tRebuild the index entirely. This will rebuild"
+ echo -e "\t\t\t\tall scroll files and may take a long time."
+ echo -e "-v\t\t\t\tTurn Verbosity on."
+ echo -e "-p\t\t\t\tSpecify a different place to store the mtimes file."
+ echo -e "-q\t\t\t\tRun silently (default)."
+ echo -e "-h, -?\t\t\t\tPrint this help message and exit."
+ echo ""
+ echo "Using this script without option will use the default omf directory"
+ echo "'$convert_dir' and the default output directory '$output_dir'"
+
+ echo ""
+ if [ $skip_omf_translate != 0 ]
+ then
+ echo "NOTE (2): This script doesn't do anything and is "
+ echo "only provided for scrollkeeper compatibility"
+ fi
+ exit 0
+}
+
+# Nice print function to call when we're in verbose mode.
+# In normal mode, it's a no-op.
+print_verbose()
+{
+ if [ $verbose ]
+ then
+ echo "$1"
+ fi
+}
+
+
+# Process_dir handles the calling of the migration program
+# It calls the program with the correct parameters
+# and moves the results to the correct place.
+process_dir()
+{
+ fname_list=""
+ old_basename=""
+ for f in $1/*.omf; do
+ bname=$(basename $f)
+ bname=${bname%-*.omf}
+ if [[ $bname != $old_basename ]]
+ then
+ old_basename=$bname
+ filename=$bname.document
+ fname_list=$fname_list$filename";"
+ if $bindir/rarian-sk-migrate $(dirname $f) ${bname%-*.omf} > $tmpdir/tmp.rarian
+ then
+ cp $tmpdir/tmp.rarian $output_dir/$filename
+ rm $tmpdir/tmp.rarian
+ else
+ echo "Error: Cannot process file "$f". See "$tmpdir"/tmp.rarian for the reason."
+ exit 5
+ fi
+ fi
+ done
+ echo -e `stat -c %Y $1`':@:'$1':@:'$fname_list >> $tmpdir/rarian-updates
+}
+
+# Split up the omf dirs specified on the command line
+# I've never seen this used in practice, but
+# better safe than sorry
+split_omf_dirs ()
+{
+ let counter=0
+ while [ $convert_dir ]
+ do
+ entry=`echo $convert_dir | cut -d ':' -f 1`
+ convert_dir=${convert_dir#$entry}
+ convert_dir=${convert_dir#:}
+ real_convert[$counter]=$entry
+ let counter+=1
+ done
+
+}
+
+# Determine whether the directory defined within the index file
+# was specified in the convert_dirs
+am_adding_dir ()
+{
+ let counter=0
+ am_processing="0"
+ for i in ${real_convert[@]}
+ do
+ if [[ $fname == $i ]]
+ then
+ real_convert[$counter]="0"
+ am_processing="1"
+ return
+ fi
+ let counter+=1
+ done
+}
+
+# The directory wasn't specified. This does nothing except cat the
+# relevant lines from the old file to the new one
+skip_directory ()
+{
+ read line
+ time=`echo $line | awk -F ":@:" '{print $1}'`
+ while [[ $time -ne 0 ]]
+ do
+ echo $line
+ echo $line >> $tmpdir/rarian-updates
+ read line
+ time=`echo $line | awk -F ":@:" '{print $1}'`
+ done
+}
+
+# Go through the given directory and add all subdirs (containing omfs)
+# to the index file (and convert the omf's to scrolls)
+add_all_files ()
+{
+ for i in $(ls $fname);
+ do
+ if [ -d $fname/$i ]
+ then
+ print_verbose "$fname/$i is new and will be added"
+ process_dir $fname/$i
+ fi
+ done
+ read line
+}
+
+# If the given directory actually exists within the omf dir
+dirs_contains ()
+{
+ let counter=0
+ am_processing="0"
+ for i in ${entries[@]}
+ do
+ if [[ $1 == $i ]]
+ then
+ entries[$counter]="0"
+ am_processing="1"
+ return
+ fi
+ let counter+=1
+ done
+}
+
+# The meat. Goes through and checks each directory mtime against the
+# cached version. If they're different, regenerate the scroll.
+# If the dir has been removed, delete.
+process_directory ()
+{
+ let counter=0
+ for i in $(ls $fname)
+ do
+ entries[$counter]="$fname/$i"
+ let counter+=1
+ done
+
+ read line
+
+ old_time=`echo $line | awk -F ":@:" '{print $1}'`
+
+ while [[ $old_time && $old_time != "0" ]]
+ do
+ name=`echo $line | awk -F ":@:" '{print $2}'`
+
+ dirs_contains $name
+
+ if [[ $am_processing != "0" ]]
+ then
+ new_time=`stat -c %Y $name`
+ if [[ $new_time -ne $old_time ]]
+ then
+ print_verbose "Directory $name has changed. Updating."
+ process_dir $name
+ else
+ echo $line >> $tmpdir/rarian-updates
+ fi
+ else
+ filenames=`echo $line | awk -F ":@:" '{print $3}'`
+ while [[ $filenames ]]
+ do
+ entry=`echo $filenames | cut -d ';' -f 1`
+ print_verbose "Directory resonsible for $entry has been removed. Deleting"
+ filenames=${filenames#$entry}
+ filenames=${filenames#;}
+ mv $entry $tmpdir
+ done
+
+ fi
+
+ read line
+ old_time=`echo $line | awk -F ":@:" '{print $1}'`
+ done
+
+ for i in ${entries[@]}
+ do
+ if [[ $i != "0" ]]
+ then
+ print_verbose "Directory $i is new and will be added."
+ process_dir $i
+ fi
+ done
+}
+
+
+
+# Beginning of the main chunk of the script
+
+# Sorry for the stupid naming of options.
+# They are inherited from scrollkeeper :(
+
+# We use TEMP as set -- seems to nuke the return value of getopt
+TEMP=`getopt -u -n$(basename $0) -o "o:r:p:vqnhV" \
+ -- "$@"` \
+ || print_usage
+
+if [ $? != 0 ] ; then
+ print_usage
+ exit 0
+fi
+
+eval set -- "$TEMP"
+
+while true; do
+ case "$1" in
+ -o )
+ convert_dir=$2
+ update_output_dir=1
+ shift 2
+ ;;
+ -r )
+ output_dir=$2
+ overload_update=1
+ shift 2
+ ;;
+ -v )
+ verbose=1
+ shift
+ ;;
+ -q )
+ shift
+ ;;
+ -c )
+ clean_index=1
+ shift
+ ;;
+ -h | -\? )
+ print_usage
+ ;;
+ -n )
+ # Scrollkeeper compat. Actually do nothing
+ shift
+ ;;
+ -p )
+ statedir=$2
+ shift 2
+ ;;
+ -V | --version )
+ print_version
+ ;;
+ * )
+ break
+ ;;
+ esac
+done
+
+if [ $verbose ]
+then
+ echo "Verbosity turned on"
+fi
+
+if [ $skip_omf_translate = 0 ]
+then
+
+split_omf_dirs
+
+if [ $update_output_dir ] && [ ! $overload_update ]
+then
+ # We assume here that people are sensible and put the
+ # omf files in <prefix>/share/omf
+ # Also assumes only a single omf path
+ print_verbose "Using non-installed location"
+ output_dir=`dirname $real_convert[0]`/help
+fi
+
+print_verbose "Outputting to $output_dir"
+
+if [ $clean_index ]
+then
+ print_verbose "Removing index file $statedir/rarian-update-mtimes"
+ rm $statedir/rarian-update-mtimes > /dev/null 2>&1
+fi
+
+
+tmpdir=/tmp/rarian-$RANDOM
+mkdir $tmpdir
+
+if [ ! -d $output_dir ]
+then
+ mkdir -p $output_dir
+fi
+
+if [ ! -d $statedir ]
+then
+ mkdir -p $statedir
+fi
+
+
+res=$(touch $statedir/rarian-update-mtimes > /dev/null 2>&1)
+
+if [ $? -ne 0 ]
+then
+ echo "Error: Unable to write to the output directory $output_dir."
+ echo "write permission is needed in order to run"
+ echo "this script. If you don't have it, things"
+ echo "break. Please run this script with the correct"
+ echo "permissions (normally root). Exiting."
+ exit 3
+fi
+
+exec < $statedir/rarian-update-mtimes
+
+read line
+fname=`echo $line | awk -F ":@:" '{print $2}'`
+
+
+while [[ $fname != "" ]]
+do
+ print_verbose "Processing directory $fname"
+ echo "0:@:$fname" >> $tmpdir/rarian-updates
+ am_adding_dir $fname
+ if [[ ! $(ls $fname 2>&1) ]]
+ then
+ print_verbose "Previous directory $fname no longer exists"
+ else
+ if [[ $am_processing != "0" ]]
+ then
+ process_directory
+ else
+ skip_directory
+ fi
+ fname=`echo $line | awk -F ":@:" '{print $2}'`
+ fi
+done
+
+for i in ${real_convert[@]}
+do
+ if [[ $i != "0" ]]
+ then
+ res=$(ls $i 2>/dev/null)
+ if [[ ! $res ]]
+ then
+ print_verbose "Path $i does not exist. Ignoring"
+ else
+
+ print_verbose "Adding contents of directory $i"
+ fname=$i
+ echo "0:@:$fname" >> $tmpdir/rarian-updates
+ add_all_files
+ fi
+ fi
+done
+
+rm -f $statedir/rarian-update-mtimes
+if [ -e $tmpdir/rarian-updates ]
+then
+ mv $tmpdir/rarian-updates $statedir/rarian-update-mtimes
+fi
+rm -rf $tmpdir
+
+fi # ENABLE_OMF_READ \ No newline at end of file
diff --git a/util/tinystr.cpp b/util/tinystr.cpp
new file mode 100644
index 0000000..4125242
--- /dev/null
+++ b/util/tinystr.cpp
@@ -0,0 +1,115 @@
+/*
+www.sourceforge.net/projects/tinyxml
+Original file by Yves Berquin.
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any
+damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any
+purpose, including commercial applications, and to alter it and
+redistribute it freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must
+not claim that you wrote the original software. If you use this
+software in a product, an acknowledgment in the product documentation
+would be appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and
+must not be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source
+distribution.
+*/
+
+/*
+ * THIS FILE WAS ALTERED BY Tyge Løvset, 7. April 2005.
+ */
+
+
+#ifndef TIXML_USE_STL
+
+#include "tinystr.h"
+
+// Error value for find primitive
+const TiXmlString::size_type TiXmlString::npos = static_cast< size_type >(-1);
+
+// Null rep.
+TiXmlString::Rep TiXmlString::nullrep_ = { 0, 0, '\0' };
+
+
+void TiXmlString::reserve (size_type cap)
+{
+ if (cap > capacity())
+ {
+ TiXmlString tmp;
+ tmp.init(length(), cap);
+ memcpy(tmp.start(), data(), length());
+ swap(tmp);
+ }
+}
+
+
+TiXmlString& TiXmlString::assign(const char* str, size_type len)
+{
+ size_type cap = capacity();
+ if (len > cap || cap > 3*(len + 8))
+ {
+ TiXmlString tmp;
+ tmp.init(len);
+ memcpy(tmp.start(), str, len);
+ swap(tmp);
+ }
+ else
+ {
+ memmove(start(), str, len);
+ set_size(len);
+ }
+ return *this;
+}
+
+
+TiXmlString& TiXmlString::append(const char* str, size_type len)
+{
+ size_type newsize = length() + len;
+ if (newsize > capacity())
+ {
+ reserve (newsize + capacity());
+ }
+ memmove(finish(), str, len);
+ set_size(newsize);
+ return *this;
+}
+
+
+TiXmlString operator + (const TiXmlString & a, const TiXmlString & b)
+{
+ TiXmlString tmp;
+ tmp.reserve(a.length() + b.length());
+ tmp += a;
+ tmp += b;
+ return tmp;
+}
+
+TiXmlString operator + (const TiXmlString & a, const char* b)
+{
+ TiXmlString tmp;
+ TiXmlString::size_type b_len = static_cast<TiXmlString::size_type>( strlen(b) );
+ tmp.reserve(a.length() + b_len);
+ tmp += a;
+ tmp.append(b, b_len);
+ return tmp;
+}
+
+TiXmlString operator + (const char* a, const TiXmlString & b)
+{
+ TiXmlString tmp;
+ TiXmlString::size_type a_len = static_cast<TiXmlString::size_type>( strlen(a) );
+ tmp.reserve(a_len + b.length());
+ tmp.append(a, a_len);
+ tmp += b;
+ return tmp;
+}
+
+
+#endif // TIXML_USE_STL
diff --git a/util/tinystr.h b/util/tinystr.h
new file mode 100644
index 0000000..6e3b999
--- /dev/null
+++ b/util/tinystr.h
@@ -0,0 +1,319 @@
+/*
+www.sourceforge.net/projects/tinyxml
+Original file by Yves Berquin.
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any
+damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any
+purpose, including commercial applications, and to alter it and
+redistribute it freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must
+not claim that you wrote the original software. If you use this
+software in a product, an acknowledgment in the product documentation
+would be appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and
+must not be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source
+distribution.
+*/
+
+/*
+ * THIS FILE WAS ALTERED BY Tyge Lovset, 7. April 2005.
+ *
+ * - completely rewritten. compact, clean, and fast implementation.
+ * - sizeof(TiXmlString) = pointer size (4 bytes on 32-bit systems)
+ * - fixed reserve() to work as per specification.
+ * - fixed buggy compares operator==(), operator<(), and operator>()
+ * - fixed operator+=() to take a const ref argument, following spec.
+ * - added "copy" constructor with length, and most compare operators.
+ * - added swap(), clear(), size(), capacity(), operator+().
+ */
+
+#ifndef TIXML_USE_STL
+
+#ifndef TIXML_STRING_INCLUDED
+#define TIXML_STRING_INCLUDED
+
+#include <assert.h>
+#include <string.h>
+
+/* The support for explicit isn't that universal, and it isn't really
+ required - it is used to check that the TiXmlString class isn't incorrectly
+ used. Be nice to old compilers and macro it here:
+*/
+#if defined(_MSC_VER) && (_MSC_VER >= 1200 )
+ // Microsoft visual studio, version 6 and higher.
+ #define TIXML_EXPLICIT explicit
+#elif defined(__GNUC__) && (__GNUC__ >= 3 )
+ // GCC version 3 and higher.s
+ #define TIXML_EXPLICIT explicit
+#else
+ #define TIXML_EXPLICIT
+#endif
+
+
+/*
+ TiXmlString is an emulation of a subset of the std::string template.
+ Its purpose is to allow compiling TinyXML on compilers with no or poor STL support.
+ Only the member functions relevant to the TinyXML project have been implemented.
+ The buffer allocation is made by a simplistic power of 2 like mechanism : if we increase
+ a string and there's no more room, we allocate a buffer twice as big as we need.
+*/
+class TiXmlString
+{
+ public :
+ // The size type used
+ typedef size_t size_type;
+
+ // Error value for find primitive
+ static const size_type npos; // = -1;
+
+
+ // TiXmlString empty constructor
+ TiXmlString () : rep_(&nullrep_)
+ {
+ }
+
+ // TiXmlString copy constructor
+ TiXmlString ( const TiXmlString & copy)
+ {
+ init(copy.length());
+ memcpy(start(), copy.data(), length());
+ }
+
+ // TiXmlString constructor, based on a string
+ TIXML_EXPLICIT TiXmlString ( const char * copy)
+ {
+ init( static_cast<size_type>( strlen(copy) ));
+ memcpy(start(), copy, length());
+ }
+
+ // TiXmlString constructor, based on a string
+ TIXML_EXPLICIT TiXmlString ( const char * str, size_type len)
+ {
+ init(len);
+ memcpy(start(), str, len);
+ }
+
+ // TiXmlString destructor
+ ~TiXmlString ()
+ {
+ quit();
+ }
+
+ // = operator
+ TiXmlString& operator = (const char * copy)
+ {
+ return assign( copy, (size_type)strlen(copy));
+ }
+
+ // = operator
+ TiXmlString& operator = (const TiXmlString & copy)
+ {
+ return assign(copy.start(), copy.length());
+ }
+
+
+ // += operator. Maps to append
+ TiXmlString& operator += (const char * suffix)
+ {
+ return append(suffix, static_cast<size_type>( strlen(suffix) ));
+ }
+
+ // += operator. Maps to append
+ TiXmlString& operator += (char single)
+ {
+ return append(&single, 1);
+ }
+
+ // += operator. Maps to append
+ TiXmlString& operator += (const TiXmlString & suffix)
+ {
+ return append(suffix.data(), suffix.length());
+ }
+
+
+ // Convert a TiXmlString into a null-terminated char *
+ const char * c_str () const { return rep_->str; }
+
+ // Convert a TiXmlString into a char * (need not be null terminated).
+ const char * data () const { return rep_->str; }
+
+ // Return the length of a TiXmlString
+ size_type length () const { return rep_->size; }
+
+ // Alias for length()
+ size_type size () const { return rep_->size; }
+
+ // Checks if a TiXmlString is empty
+ bool empty () const { return rep_->size == 0; }
+
+ // Return capacity of string
+ size_type capacity () const { return rep_->capacity; }
+
+
+ // single char extraction
+ const char& at (size_type index) const
+ {
+ assert( index < length() );
+ return rep_->str[ index ];
+ }
+
+ // [] operator
+ char& operator [] (size_type index) const
+ {
+ assert( index < length() );
+ return rep_->str[ index ];
+ }
+
+ // find a char in a string. Return TiXmlString::npos if not found
+ size_type find (char lookup) const
+ {
+ return find(lookup, 0);
+ }
+
+ // find a char in a string from an offset. Return TiXmlString::npos if not found
+ size_type find (char tofind, size_type offset) const
+ {
+ if (offset >= length()) return npos;
+
+ for (const char* p = c_str() + offset; *p != '\0'; ++p)
+ {
+ if (*p == tofind) return static_cast< size_type >( p - c_str() );
+ }
+ return npos;
+ }
+
+ void clear ()
+ {
+ //Lee:
+ //The original was just too strange, though correct:
+ // TiXmlString().swap(*this);
+ //Instead use the quit & re-init:
+ quit();
+ init(0,0);
+ }
+
+ /* Function to reserve a big amount of data when we know we'll need it. Be aware that this
+ function DOES NOT clear the content of the TiXmlString if any exists.
+ */
+ void reserve (size_type cap);
+
+ TiXmlString& assign (const char* str, size_type len);
+
+ TiXmlString& append (const char* str, size_type len);
+
+ void swap (TiXmlString& other)
+ {
+ Rep* r = rep_;
+ rep_ = other.rep_;
+ other.rep_ = r;
+ }
+
+ private:
+
+ void init(size_type sz) { init(sz, sz); }
+ void set_size(size_type sz) { rep_->str[ rep_->size = sz ] = '\0'; }
+ char* start() const { return rep_->str; }
+ char* finish() const { return rep_->str + rep_->size; }
+
+ struct Rep
+ {
+ size_type size, capacity;
+ char str[1];
+ };
+
+ void init(size_type sz, size_type cap)
+ {
+ if (cap)
+ {
+ // Lee: the original form:
+ // rep_ = static_cast<Rep*>(operator new(sizeof(Rep) + cap));
+ // doesn't work in some cases of new being overloaded. Switching
+ // to the normal allocation, although use an 'int' for systems
+ // that are overly picky about structure alignment.
+ const size_type bytesNeeded = sizeof(Rep) + cap;
+ const size_type intsNeeded = ( bytesNeeded + sizeof(int) - 1 ) / sizeof( int );
+ rep_ = reinterpret_cast<Rep*>( new int[ intsNeeded ] );
+
+ rep_->str[ rep_->size = sz ] = '\0';
+ rep_->capacity = cap;
+ }
+ else
+ {
+ rep_ = &nullrep_;
+ }
+ }
+
+ void quit()
+ {
+ if (rep_ != &nullrep_)
+ {
+ // The rep_ is really an array of ints. (see the allocator, above).
+ // Cast it back before delete, so the compiler won't incorrectly call destructors.
+ delete [] ( reinterpret_cast<int*>( rep_ ) );
+ }
+ }
+
+ Rep * rep_;
+ static Rep nullrep_;
+
+} ;
+
+
+inline bool operator == (const TiXmlString & a, const TiXmlString & b)
+{
+ return ( a.length() == b.length() ) // optimization on some platforms
+ && ( strcmp(a.c_str(), b.c_str()) == 0 ); // actual compare
+}
+inline bool operator < (const TiXmlString & a, const TiXmlString & b)
+{
+ return strcmp(a.c_str(), b.c_str()) < 0;
+}
+
+inline bool operator != (const TiXmlString & a, const TiXmlString & b) { return !(a == b); }
+inline bool operator > (const TiXmlString & a, const TiXmlString & b) { return b < a; }
+inline bool operator <= (const TiXmlString & a, const TiXmlString & b) { return !(b < a); }
+inline bool operator >= (const TiXmlString & a, const TiXmlString & b) { return !(a < b); }
+
+inline bool operator == (const TiXmlString & a, const char* b) { return strcmp(a.c_str(), b) == 0; }
+inline bool operator == (const char* a, const TiXmlString & b) { return b == a; }
+inline bool operator != (const TiXmlString & a, const char* b) { return !(a == b); }
+inline bool operator != (const char* a, const TiXmlString & b) { return !(b == a); }
+
+TiXmlString operator + (const TiXmlString & a, const TiXmlString & b);
+TiXmlString operator + (const TiXmlString & a, const char* b);
+TiXmlString operator + (const char* a, const TiXmlString & b);
+
+
+/*
+ TiXmlOutStream is an emulation of std::ostream. It is based on TiXmlString.
+ Only the operators that we need for TinyXML have been developped.
+*/
+class TiXmlOutStream : public TiXmlString
+{
+public :
+
+ // TiXmlOutStream << operator.
+ TiXmlOutStream & operator << (const TiXmlString & in)
+ {
+ *this += in;
+ return *this;
+ }
+
+ // TiXmlOutStream << operator.
+ TiXmlOutStream & operator << (const char * in)
+ {
+ *this += in;
+ return *this;
+ }
+
+} ;
+
+#endif // TIXML_STRING_INCLUDED
+#endif // TIXML_USE_STL
diff --git a/util/tinyxml.cpp b/util/tinyxml.cpp
new file mode 100644
index 0000000..6a83291
--- /dev/null
+++ b/util/tinyxml.cpp
@@ -0,0 +1,1799 @@
+/*
+www.sourceforge.net/projects/tinyxml
+Original code (2.0 and earlier )copyright (c) 2000-2002 Lee Thomason (www.grinninglizard.com)
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any
+damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any
+purpose, including commercial applications, and to alter it and
+redistribute it freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must
+not claim that you wrote the original software. If you use this
+software in a product, an acknowledgment in the product documentation
+would be appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and
+must not be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source
+distribution.
+*/
+
+#include <ctype.h>
+#include "tinyxml.h"
+
+#ifdef TIXML_USE_STL
+#include <sstream>
+#include <iostream>
+#endif
+
+
+bool TiXmlBase::condenseWhiteSpace = true;
+
+void TiXmlBase::PutString( const TIXML_STRING& str, TIXML_OSTREAM* stream )
+{
+ TIXML_STRING buffer;
+ PutString( str, &buffer );
+ (*stream) << buffer;
+}
+
+void TiXmlBase::PutString( const TIXML_STRING& str, TIXML_STRING* outString )
+{
+ int i=0;
+
+ while( i<(int)str.length() )
+ {
+ unsigned char c = (unsigned char) str[i];
+
+ if ( c == '&'
+ && i < ( (int)str.length() - 2 )
+ && str[i+1] == '#'
+ && str[i+2] == 'x' )
+ {
+ // Hexadecimal character reference.
+ // Pass through unchanged.
+ // &#xA9; -- copyright symbol, for example.
+ //
+ // The -1 is a bug fix from Rob Laveaux. It keeps
+ // an overflow from happening if there is no ';'.
+ // There are actually 2 ways to exit this loop -
+ // while fails (error case) and break (semicolon found).
+ // However, there is no mechanism (currently) for
+ // this function to return an error.
+ while ( i<(int)str.length()-1 )
+ {
+ outString->append( str.c_str() + i, 1 );
+ ++i;
+ if ( str[i] == ';' )
+ break;
+ }
+ }
+ else if ( c == '&' )
+ {
+ outString->append( entity[0].str, entity[0].strLength );
+ ++i;
+ }
+ else if ( c == '<' )
+ {
+ outString->append( entity[1].str, entity[1].strLength );
+ ++i;
+ }
+ else if ( c == '>' )
+ {
+ outString->append( entity[2].str, entity[2].strLength );
+ ++i;
+ }
+ else if ( c == '\"' )
+ {
+ outString->append( entity[3].str, entity[3].strLength );
+ ++i;
+ }
+ else if ( c == '\'' )
+ {
+ outString->append( entity[4].str, entity[4].strLength );
+ ++i;
+ }
+ else if ( c < 32 )
+ {
+ // Easy pass at non-alpha/numeric/symbol
+ // Below 32 is symbolic.
+ char buf[ 32 ];
+
+ #if defined(TIXML_SNPRINTF)
+ TIXML_SNPRINTF( buf, sizeof(buf), "&#x%02X;", (unsigned) ( c & 0xff ) );
+ #else
+ sprintf( buf, "&#x%02X;", (unsigned) ( c & 0xff ) );
+ #endif
+
+ //*ME: warning C4267: convert 'size_t' to 'int'
+ //*ME: Int-Cast to make compiler happy ...
+ outString->append( buf, (int)strlen( buf ) );
+ ++i;
+ }
+ else
+ {
+ //char realc = (char) c;
+ //outString->append( &realc, 1 );
+ *outString += (char) c; // somewhat more efficient function call.
+ ++i;
+ }
+ }
+}
+
+
+// <-- Strange class for a bug fix. Search for STL_STRING_BUG
+TiXmlBase::StringToBuffer::StringToBuffer( const TIXML_STRING& str )
+{
+ buffer = new char[ str.length()+1 ];
+ if ( buffer )
+ {
+ strcpy( buffer, str.c_str() );
+ }
+}
+
+
+TiXmlBase::StringToBuffer::~StringToBuffer()
+{
+ delete [] buffer;
+}
+// End strange bug fix. -->
+
+
+TiXmlNode::TiXmlNode( NodeType _type ) : TiXmlBase()
+{
+ parent = 0;
+ type = _type;
+ firstChild = 0;
+ lastChild = 0;
+ prev = 0;
+ next = 0;
+}
+
+
+TiXmlNode::~TiXmlNode()
+{
+ TiXmlNode* node = firstChild;
+ TiXmlNode* temp = 0;
+
+ while ( node )
+ {
+ temp = node;
+ node = node->next;
+ delete temp;
+ }
+}
+
+
+void TiXmlNode::CopyTo( TiXmlNode* target ) const
+{
+ target->SetValue (value.c_str() );
+ target->userData = userData;
+}
+
+
+void TiXmlNode::Clear()
+{
+ TiXmlNode* node = firstChild;
+ TiXmlNode* temp = 0;
+
+ while ( node )
+ {
+ temp = node;
+ node = node->next;
+ delete temp;
+ }
+
+ firstChild = 0;
+ lastChild = 0;
+}
+
+
+TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node )
+{
+ assert( node->parent == 0 || node->parent == this );
+ assert( node->GetDocument() == 0 || node->GetDocument() == this->GetDocument() );
+
+ node->parent = this;
+
+ node->prev = lastChild;
+ node->next = 0;
+
+ if ( lastChild )
+ lastChild->next = node;
+ else
+ firstChild = node; // it was an empty list.
+
+ lastChild = node;
+ return node;
+}
+
+
+TiXmlNode* TiXmlNode::InsertEndChild( const TiXmlNode& addThis )
+{
+ TiXmlNode* node = addThis.Clone();
+ if ( !node )
+ return 0;
+
+ return LinkEndChild( node );
+}
+
+
+TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis )
+{
+ if ( !beforeThis || beforeThis->parent != this )
+ return 0;
+
+ TiXmlNode* node = addThis.Clone();
+ if ( !node )
+ return 0;
+ node->parent = this;
+
+ node->next = beforeThis;
+ node->prev = beforeThis->prev;
+ if ( beforeThis->prev )
+ {
+ beforeThis->prev->next = node;
+ }
+ else
+ {
+ assert( firstChild == beforeThis );
+ firstChild = node;
+ }
+ beforeThis->prev = node;
+ return node;
+}
+
+
+TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis )
+{
+ if ( !afterThis || afterThis->parent != this )
+ return 0;
+
+ TiXmlNode* node = addThis.Clone();
+ if ( !node )
+ return 0;
+ node->parent = this;
+
+ node->prev = afterThis;
+ node->next = afterThis->next;
+ if ( afterThis->next )
+ {
+ afterThis->next->prev = node;
+ }
+ else
+ {
+ assert( lastChild == afterThis );
+ lastChild = node;
+ }
+ afterThis->next = node;
+ return node;
+}
+
+
+TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis )
+{
+ if ( replaceThis->parent != this )
+ return 0;
+
+ TiXmlNode* node = withThis.Clone();
+ if ( !node )
+ return 0;
+
+ node->next = replaceThis->next;
+ node->prev = replaceThis->prev;
+
+ if ( replaceThis->next )
+ replaceThis->next->prev = node;
+ else
+ lastChild = node;
+
+ if ( replaceThis->prev )
+ replaceThis->prev->next = node;
+ else
+ firstChild = node;
+
+ delete replaceThis;
+ node->parent = this;
+ return node;
+}
+
+
+bool TiXmlNode::RemoveChild( TiXmlNode* removeThis )
+{
+ if ( removeThis->parent != this )
+ {
+ assert( 0 );
+ return false;
+ }
+
+ if ( removeThis->next )
+ removeThis->next->prev = removeThis->prev;
+ else
+ lastChild = removeThis->prev;
+
+ if ( removeThis->prev )
+ removeThis->prev->next = removeThis->next;
+ else
+ firstChild = removeThis->next;
+
+ delete removeThis;
+ return true;
+}
+
+const TiXmlNode* TiXmlNode::FirstChild( const char * _value ) const
+{
+ const TiXmlNode* node;
+ for ( node = firstChild; node; node = node->next )
+ {
+ if ( strcmp( node->Value(), _value ) == 0 )
+ return node;
+ }
+ return 0;
+}
+
+
+TiXmlNode* TiXmlNode::FirstChild( const char * _value )
+{
+ TiXmlNode* node;
+ for ( node = firstChild; node; node = node->next )
+ {
+ if ( strcmp( node->Value(), _value ) == 0 )
+ return node;
+ }
+ return 0;
+}
+
+
+const TiXmlNode* TiXmlNode::LastChild( const char * _value ) const
+{
+ const TiXmlNode* node;
+ for ( node = lastChild; node; node = node->prev )
+ {
+ if ( strcmp( node->Value(), _value ) == 0 )
+ return node;
+ }
+ return 0;
+}
+
+TiXmlNode* TiXmlNode::LastChild( const char * _value )
+{
+ TiXmlNode* node;
+ for ( node = lastChild; node; node = node->prev )
+ {
+ if ( strcmp( node->Value(), _value ) == 0 )
+ return node;
+ }
+ return 0;
+}
+
+const TiXmlNode* TiXmlNode::IterateChildren( const TiXmlNode* previous ) const
+{
+ if ( !previous )
+ {
+ return FirstChild();
+ }
+ else
+ {
+ assert( previous->parent == this );
+ return previous->NextSibling();
+ }
+}
+
+TiXmlNode* TiXmlNode::IterateChildren( TiXmlNode* previous )
+{
+ if ( !previous )
+ {
+ return FirstChild();
+ }
+ else
+ {
+ assert( previous->parent == this );
+ return previous->NextSibling();
+ }
+}
+
+const TiXmlNode* TiXmlNode::IterateChildren( const char * val, const TiXmlNode* previous ) const
+{
+ if ( !previous )
+ {
+ return FirstChild( val );
+ }
+ else
+ {
+ assert( previous->parent == this );
+ return previous->NextSibling( val );
+ }
+}
+
+TiXmlNode* TiXmlNode::IterateChildren( const char * val, TiXmlNode* previous )
+{
+ if ( !previous )
+ {
+ return FirstChild( val );
+ }
+ else
+ {
+ assert( previous->parent == this );
+ return previous->NextSibling( val );
+ }
+}
+
+const TiXmlNode* TiXmlNode::NextSibling( const char * _value ) const
+{
+ const TiXmlNode* node;
+ for ( node = next; node; node = node->next )
+ {
+ if ( strcmp( node->Value(), _value ) == 0 )
+ return node;
+ }
+ return 0;
+}
+
+TiXmlNode* TiXmlNode::NextSibling( const char * _value )
+{
+ TiXmlNode* node;
+ for ( node = next; node; node = node->next )
+ {
+ if ( strcmp( node->Value(), _value ) == 0 )
+ return node;
+ }
+ return 0;
+}
+
+const TiXmlNode* TiXmlNode::PreviousSibling( const char * _value ) const
+{
+ const TiXmlNode* node;
+ for ( node = prev; node; node = node->prev )
+ {
+ if ( strcmp( node->Value(), _value ) == 0 )
+ return node;
+ }
+ return 0;
+}
+
+TiXmlNode* TiXmlNode::PreviousSibling( const char * _value )
+{
+ TiXmlNode* node;
+ for ( node = prev; node; node = node->prev )
+ {
+ if ( strcmp( node->Value(), _value ) == 0 )
+ return node;
+ }
+ return 0;
+}
+
+void TiXmlElement::RemoveAttribute( const char * name )
+{
+ TIXML_STRING str( name );
+ TiXmlAttribute* node = attributeSet.Find( str );
+ if ( node )
+ {
+ attributeSet.Remove( node );
+ delete node;
+ }
+}
+
+const TiXmlElement* TiXmlNode::FirstChildElement() const
+{
+ const TiXmlNode* node;
+
+ for ( node = FirstChild();
+ node;
+ node = node->NextSibling() )
+ {
+ if ( node->ToElement() )
+ return node->ToElement();
+ }
+ return 0;
+}
+
+TiXmlElement* TiXmlNode::FirstChildElement()
+{
+ TiXmlNode* node;
+
+ for ( node = FirstChild();
+ node;
+ node = node->NextSibling() )
+ {
+ if ( node->ToElement() )
+ return node->ToElement();
+ }
+ return 0;
+}
+
+const TiXmlElement* TiXmlNode::FirstChildElement( const char * _value ) const
+{
+ const TiXmlNode* node;
+
+ for ( node = FirstChild( _value );
+ node;
+ node = node->NextSibling( _value ) )
+ {
+ if ( node->ToElement() )
+ return node->ToElement();
+ }
+ return 0;
+}
+
+TiXmlElement* TiXmlNode::FirstChildElement( const char * _value )
+{
+ TiXmlNode* node;
+
+ for ( node = FirstChild( _value );
+ node;
+ node = node->NextSibling( _value ) )
+ {
+ if ( node->ToElement() )
+ return node->ToElement();
+ }
+ return 0;
+}
+
+const TiXmlElement* TiXmlNode::NextSiblingElement() const
+{
+ const TiXmlNode* node;
+
+ for ( node = NextSibling();
+ node;
+ node = node->NextSibling() )
+ {
+ if ( node->ToElement() )
+ return node->ToElement();
+ }
+ return 0;
+}
+
+TiXmlElement* TiXmlNode::NextSiblingElement()
+{
+ TiXmlNode* node;
+
+ for ( node = NextSibling();
+ node;
+ node = node->NextSibling() )
+ {
+ if ( node->ToElement() )
+ return node->ToElement();
+ }
+ return 0;
+}
+
+const TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value ) const
+{
+ const TiXmlNode* node;
+
+ for ( node = NextSibling( _value );
+ node;
+ node = node->NextSibling( _value ) )
+ {
+ if ( node->ToElement() )
+ return node->ToElement();
+ }
+ return 0;
+}
+
+TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value )
+{
+ TiXmlNode* node;
+
+ for ( node = NextSibling( _value );
+ node;
+ node = node->NextSibling( _value ) )
+ {
+ if ( node->ToElement() )
+ return node->ToElement();
+ }
+ return 0;
+}
+
+
+const TiXmlDocument* TiXmlNode::GetDocument() const
+{
+ const TiXmlNode* node;
+
+ for( node = this; node; node = node->parent )
+ {
+ if ( node->ToDocument() )
+ return node->ToDocument();
+ }
+ return 0;
+}
+
+TiXmlDocument* TiXmlNode::GetDocument()
+{
+ TiXmlNode* node;
+
+ for( node = this; node; node = node->parent )
+ {
+ if ( node->ToDocument() )
+ return node->ToDocument();
+ }
+ return 0;
+}
+
+TiXmlElement::TiXmlElement (const char * _value)
+ : TiXmlNode( TiXmlNode::ELEMENT )
+{
+ firstChild = lastChild = 0;
+ value = _value;
+}
+
+
+#ifdef TIXML_USE_STL
+TiXmlElement::TiXmlElement( const std::string& _value )
+ : TiXmlNode( TiXmlNode::ELEMENT )
+{
+ firstChild = lastChild = 0;
+ value = _value;
+}
+#endif
+
+
+TiXmlElement::TiXmlElement( const TiXmlElement& copy)
+ : TiXmlNode( TiXmlNode::ELEMENT )
+{
+ firstChild = lastChild = 0;
+ copy.CopyTo( this );
+}
+
+
+void TiXmlElement::operator=( const TiXmlElement& base )
+{
+ ClearThis();
+ base.CopyTo( this );
+}
+
+
+TiXmlElement::~TiXmlElement()
+{
+ ClearThis();
+}
+
+
+void TiXmlElement::ClearThis()
+{
+ Clear();
+ while( attributeSet.First() )
+ {
+ TiXmlAttribute* node = attributeSet.First();
+ attributeSet.Remove( node );
+ delete node;
+ }
+}
+
+
+const char * TiXmlElement::Attribute( const char * name ) const
+{
+ TIXML_STRING str( name );
+ const TiXmlAttribute* node = attributeSet.Find( str );
+
+ if ( node )
+ return node->Value();
+
+ return 0;
+}
+
+
+const char * TiXmlElement::Attribute( const char * name, int* i ) const
+{
+ const char * s = Attribute( name );
+ if ( i )
+ {
+ if ( s )
+ *i = atoi( s );
+ else
+ *i = 0;
+ }
+ return s;
+}
+
+
+const char * TiXmlElement::Attribute( const char * name, double* d ) const
+{
+ const char * s = Attribute( name );
+ if ( d )
+ {
+ if ( s )
+ *d = atof( s );
+ else
+ *d = 0;
+ }
+ return s;
+}
+
+
+int TiXmlElement::QueryIntAttribute( const char* name, int* ival ) const
+{
+ TIXML_STRING str( name );
+ const TiXmlAttribute* node = attributeSet.Find( str );
+ if ( !node )
+ return TIXML_NO_ATTRIBUTE;
+
+ return node->QueryIntValue( ival );
+}
+
+
+int TiXmlElement::QueryDoubleAttribute( const char* name, double* dval ) const
+{
+ TIXML_STRING str( name );
+ const TiXmlAttribute* node = attributeSet.Find( str );
+ if ( !node )
+ return TIXML_NO_ATTRIBUTE;
+
+ return node->QueryDoubleValue( dval );
+}
+
+
+void TiXmlElement::SetAttribute( const char * name, int val )
+{
+ char buf[64];
+ #if defined(TIXML_SNPRINTF)
+ TIXML_SNPRINTF( buf, sizeof(buf), "%d", val );
+ #else
+ sprintf( buf, "%d", val );
+ #endif
+ SetAttribute( name, buf );
+}
+
+
+#ifdef TIXML_USE_STL
+void TiXmlElement::SetAttribute( const std::string& name, int val )
+{
+ std::ostringstream oss;
+ oss << val;
+ SetAttribute( name, oss.str() );
+}
+#endif
+
+
+void TiXmlElement::SetDoubleAttribute( const char * name, double val )
+{
+ char buf[256];
+ #if defined(TIXML_SNPRINTF)
+ TIXML_SNPRINTF( buf, sizeof(buf), "%f", val );
+ #else
+ sprintf( buf, "%f", val );
+ #endif
+ SetAttribute( name, buf );
+}
+
+
+void TiXmlElement::SetAttribute( const char * cname, const char * cvalue )
+{
+ TIXML_STRING _name( cname );
+ TIXML_STRING _value( cvalue );
+
+ TiXmlAttribute* node = attributeSet.Find( _name );
+ if ( node )
+ {
+ node->SetValue( cvalue );
+ return;
+ }
+
+ TiXmlAttribute* attrib = new TiXmlAttribute( cname, cvalue );
+ if ( attrib )
+ {
+ attributeSet.Add( attrib );
+ }
+ else
+ {
+ TiXmlDocument* document = GetDocument();
+ if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN );
+ }
+}
+
+
+#ifdef TIXML_USE_STL
+void TiXmlElement::SetAttribute( const std::string& name, const std::string& _value )
+{
+ TiXmlAttribute* node = attributeSet.Find( name );
+ if ( node )
+ {
+ node->SetValue( _value );
+ return;
+ }
+
+ TiXmlAttribute* attrib = new TiXmlAttribute( name, _value );
+ if ( attrib )
+ {
+ attributeSet.Add( attrib );
+ }
+ else
+ {
+ TiXmlDocument* document = GetDocument();
+ if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN );
+ }
+}
+#endif
+
+
+void TiXmlElement::Print( FILE* cfile, int depth ) const
+{
+ int i;
+ for ( i=0; i<depth; i++ )
+ {
+ fprintf( cfile, " " );
+ }
+
+ fprintf( cfile, "<%s", value.c_str() );
+
+ const TiXmlAttribute* attrib;
+ for ( attrib = attributeSet.First(); attrib; attrib = attrib->Next() )
+ {
+ fprintf( cfile, " " );
+ attrib->Print( cfile, depth );
+ }
+
+ // There are 3 different formatting approaches:
+ // 1) An element without children is printed as a <foo /> node
+ // 2) An element with only a text child is printed as <foo> text </foo>
+ // 3) An element with children is printed on multiple lines.
+ TiXmlNode* node;
+ if ( !firstChild )
+ {
+ fprintf( cfile, " />" );
+ }
+ else if ( firstChild == lastChild && firstChild->ToText() )
+ {
+ fprintf( cfile, ">" );
+ firstChild->Print( cfile, depth + 1 );
+ fprintf( cfile, "</%s>", value.c_str() );
+ }
+ else
+ {
+ fprintf( cfile, ">" );
+
+ for ( node = firstChild; node; node=node->NextSibling() )
+ {
+ if ( !node->ToText() )
+ {
+ fprintf( cfile, "\n" );
+ }
+ node->Print( cfile, depth+1 );
+ }
+ fprintf( cfile, "\n" );
+ for( i=0; i<depth; ++i )
+ fprintf( cfile, " " );
+ fprintf( cfile, "</%s>", value.c_str() );
+ }
+}
+
+void TiXmlElement::StreamOut( TIXML_OSTREAM * stream ) const
+{
+ (*stream) << "<" << value;
+
+ const TiXmlAttribute* attrib;
+ for ( attrib = attributeSet.First(); attrib; attrib = attrib->Next() )
+ {
+ (*stream) << " ";
+ attrib->StreamOut( stream );
+ }
+
+ // If this node has children, give it a closing tag. Else
+ // make it an empty tag.
+ TiXmlNode* node;
+ if ( firstChild )
+ {
+ (*stream) << ">";
+
+ for ( node = firstChild; node; node=node->NextSibling() )
+ {
+ node->StreamOut( stream );
+ }
+ (*stream) << "</" << value << ">";
+ }
+ else
+ {
+ (*stream) << " />";
+ }
+}
+
+
+void TiXmlElement::CopyTo( TiXmlElement* target ) const
+{
+ // superclass:
+ TiXmlNode::CopyTo( target );
+
+ // Element class:
+ // Clone the attributes, then clone the children.
+ const TiXmlAttribute* attribute = 0;
+ for( attribute = attributeSet.First();
+ attribute;
+ attribute = attribute->Next() )
+ {
+ target->SetAttribute( attribute->Name(), attribute->Value() );
+ }
+
+ TiXmlNode* node = 0;
+ for ( node = firstChild; node; node = node->NextSibling() )
+ {
+ target->LinkEndChild( node->Clone() );
+ }
+}
+
+
+TiXmlNode* TiXmlElement::Clone() const
+{
+ TiXmlElement* clone = new TiXmlElement( Value() );
+ if ( !clone )
+ return 0;
+
+ CopyTo( clone );
+ return clone;
+}
+
+
+const char* TiXmlElement::GetText() const
+{
+ const TiXmlNode* child = this->FirstChild();
+ if ( child ) {
+ const TiXmlText* childText = child->ToText();
+ if ( childText ) {
+ return childText->Value();
+ }
+ }
+ return 0;
+}
+
+
+TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::DOCUMENT )
+{
+ tabsize = 4;
+ useMicrosoftBOM = false;
+ ClearError();
+}
+
+TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::DOCUMENT )
+{
+ tabsize = 4;
+ useMicrosoftBOM = false;
+ value = documentName;
+ ClearError();
+}
+
+
+#ifdef TIXML_USE_STL
+TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::DOCUMENT )
+{
+ tabsize = 4;
+ useMicrosoftBOM = false;
+ value = documentName;
+ ClearError();
+}
+#endif
+
+
+TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::DOCUMENT )
+{
+ copy.CopyTo( this );
+}
+
+
+void TiXmlDocument::operator=( const TiXmlDocument& copy )
+{
+ Clear();
+ copy.CopyTo( this );
+}
+
+
+bool TiXmlDocument::LoadFile( TiXmlEncoding encoding )
+{
+ // See STL_STRING_BUG below.
+ StringToBuffer buf( value );
+
+ if ( buf.buffer && LoadFile( buf.buffer, encoding ) )
+ return true;
+
+ return false;
+}
+
+
+bool TiXmlDocument::SaveFile() const
+{
+ // See STL_STRING_BUG below.
+ StringToBuffer buf( value );
+
+ if ( buf.buffer && SaveFile( buf.buffer ) )
+ return true;
+
+ return false;
+}
+
+bool TiXmlDocument::LoadFile( const char* filename, TiXmlEncoding encoding )
+{
+ // There was a really terrifying little bug here. The code:
+ // value = filename
+ // in the STL case, cause the assignment method of the std::string to
+ // be called. What is strange, is that the std::string had the same
+ // address as it's c_str() method, and so bad things happen. Looks
+ // like a bug in the Microsoft STL implementation.
+ // See STL_STRING_BUG above.
+ // Fixed with the StringToBuffer class.
+ value = filename;
+
+ // reading in binary mode so that tinyxml can normalize the EOL
+ FILE* file = fopen( value.c_str (), "rb" );
+
+ if ( file )
+ {
+ bool result = LoadFile( file, encoding );
+ fclose( file );
+ return result;
+ }
+ else
+ {
+ SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return false;
+ }
+}
+
+bool TiXmlDocument::LoadFile( FILE* file, TiXmlEncoding encoding )
+{
+ if ( !file )
+ {
+ SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return false;
+ }
+
+ // Delete the existing data:
+ Clear();
+ location.Clear();
+
+ // Get the file size, so we can pre-allocate the string. HUGE speed impact.
+ long length = 0;
+ fseek( file, 0, SEEK_END );
+ length = ftell( file );
+ fseek( file, 0, SEEK_SET );
+
+ // Strange case, but good to handle up front.
+ if ( length == 0 )
+ {
+ SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return false;
+ }
+
+ // If we have a file, assume it is all one big XML file, and read it in.
+ // The document parser may decide the document ends sooner than the entire file, however.
+ TIXML_STRING data;
+ data.reserve( length );
+
+ // Subtle bug here. TinyXml did use fgets. But from the XML spec:
+ // 2.11 End-of-Line Handling
+ // <snip>
+ // <quote>
+ // ...the XML processor MUST behave as if it normalized all line breaks in external
+ // parsed entities (including the document entity) on input, before parsing, by translating
+ // both the two-character sequence #xD #xA and any #xD that is not followed by #xA to
+ // a single #xA character.
+ // </quote>
+ //
+ // It is not clear fgets does that, and certainly isn't clear it works cross platform.
+ // Generally, you expect fgets to translate from the convention of the OS to the c/unix
+ // convention, and not work generally.
+
+ /*
+ while( fgets( buf, sizeof(buf), file ) )
+ {
+ data += buf;
+ }
+ */
+
+ char* buf = new char[ length+1 ];
+ buf[0] = 0;
+
+ if ( fread( buf, length, 1, file ) != 1 ) {
+ SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return false;
+ }
+
+ const char* lastPos = buf;
+ const char* p = buf;
+
+ buf[length] = 0;
+ while( *p ) {
+ assert( p < (buf+length) );
+ if ( *p == 0xa ) {
+ // Newline character. No special rules for this. Append all the characters
+ // since the last string, and include the newline.
+ data.append( lastPos, (p-lastPos+1) ); // append, include the newline
+ ++p; // move past the newline
+ lastPos = p; // and point to the new buffer (may be 0)
+ assert( p <= (buf+length) );
+ }
+ else if ( *p == 0xd ) {
+ // Carriage return. Append what we have so far, then
+ // handle moving forward in the buffer.
+ if ( (p-lastPos) > 0 ) {
+ data.append( lastPos, p-lastPos ); // do not add the CR
+ }
+ data += (char)0xa; // a proper newline
+
+ if ( *(p+1) == 0xa ) {
+ // Carriage return - new line sequence
+ p += 2;
+ lastPos = p;
+ assert( p <= (buf+length) );
+ }
+ else {
+ // it was followed by something else...that is presumably characters again.
+ ++p;
+ lastPos = p;
+ assert( p <= (buf+length) );
+ }
+ }
+ else {
+ ++p;
+ }
+ }
+ // Handle any left over characters.
+ if ( p-lastPos ) {
+ data.append( lastPos, p-lastPos );
+ }
+ delete [] buf;
+ buf = 0;
+
+ Parse( data.c_str(), 0, encoding );
+
+ if ( Error() )
+ return false;
+ else
+ return true;
+}
+
+
+bool TiXmlDocument::SaveFile( const char * filename ) const
+{
+ // The old c stuff lives on...
+ FILE* fp = fopen( filename, "w" );
+ if ( fp )
+ {
+ bool result = SaveFile( fp );
+ fclose( fp );
+ return result;
+ }
+ return false;
+}
+
+
+bool TiXmlDocument::SaveFile( FILE* fp ) const
+{
+ if ( useMicrosoftBOM )
+ {
+ const unsigned char TIXML_UTF_LEAD_0 = 0xefU;
+ const unsigned char TIXML_UTF_LEAD_1 = 0xbbU;
+ const unsigned char TIXML_UTF_LEAD_2 = 0xbfU;
+
+ fputc( TIXML_UTF_LEAD_0, fp );
+ fputc( TIXML_UTF_LEAD_1, fp );
+ fputc( TIXML_UTF_LEAD_2, fp );
+ }
+ Print( fp, 0 );
+ return true;
+}
+
+
+void TiXmlDocument::CopyTo( TiXmlDocument* target ) const
+{
+ TiXmlNode::CopyTo( target );
+
+ target->error = error;
+ target->errorDesc = errorDesc.c_str ();
+
+ TiXmlNode* node = 0;
+ for ( node = firstChild; node; node = node->NextSibling() )
+ {
+ target->LinkEndChild( node->Clone() );
+ }
+}
+
+
+TiXmlNode* TiXmlDocument::Clone() const
+{
+ TiXmlDocument* clone = new TiXmlDocument();
+ if ( !clone )
+ return 0;
+
+ CopyTo( clone );
+ return clone;
+}
+
+
+void TiXmlDocument::Print( FILE* cfile, int depth ) const
+{
+ const TiXmlNode* node;
+ for ( node=FirstChild(); node; node=node->NextSibling() )
+ {
+ node->Print( cfile, depth );
+ fprintf( cfile, "\n" );
+ }
+}
+
+void TiXmlDocument::StreamOut( TIXML_OSTREAM * out ) const
+{
+ const TiXmlNode* node;
+ for ( node=FirstChild(); node; node=node->NextSibling() )
+ {
+ node->StreamOut( out );
+
+ // Special rule for streams: stop after the root element.
+ // The stream in code will only read one element, so don't
+ // write more than one.
+ if ( node->ToElement() )
+ break;
+ }
+}
+
+
+const TiXmlAttribute* TiXmlAttribute::Next() const
+{
+ // We are using knowledge of the sentinel. The sentinel
+ // have a value or name.
+ if ( next->value.empty() && next->name.empty() )
+ return 0;
+ return next;
+}
+
+TiXmlAttribute* TiXmlAttribute::Next()
+{
+ // We are using knowledge of the sentinel. The sentinel
+ // have a value or name.
+ if ( next->value.empty() && next->name.empty() )
+ return 0;
+ return next;
+}
+
+const TiXmlAttribute* TiXmlAttribute::Previous() const
+{
+ // We are using knowledge of the sentinel. The sentinel
+ // have a value or name.
+ if ( prev->value.empty() && prev->name.empty() )
+ return 0;
+ return prev;
+}
+
+TiXmlAttribute* TiXmlAttribute::Previous()
+{
+ // We are using knowledge of the sentinel. The sentinel
+ // have a value or name.
+ if ( prev->value.empty() && prev->name.empty() )
+ return 0;
+ return prev;
+}
+
+void TiXmlAttribute::Print( FILE* cfile, int /*depth*/ ) const
+{
+ TIXML_STRING n, v;
+
+ PutString( name, &n );
+ PutString( value, &v );
+
+ if (value.find ('\"') == TIXML_STRING::npos)
+ fprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str() );
+ else
+ fprintf (cfile, "%s='%s'", n.c_str(), v.c_str() );
+}
+
+
+void TiXmlAttribute::StreamOut( TIXML_OSTREAM * stream ) const
+{
+ if (value.find( '\"' ) != TIXML_STRING::npos)
+ {
+ PutString( name, stream );
+ (*stream) << "=" << "'";
+ PutString( value, stream );
+ (*stream) << "'";
+ }
+ else
+ {
+ PutString( name, stream );
+ (*stream) << "=" << "\"";
+ PutString( value, stream );
+ (*stream) << "\"";
+ }
+}
+
+int TiXmlAttribute::QueryIntValue( int* ival ) const
+{
+ if ( sscanf( value.c_str(), "%d", ival ) == 1 )
+ return TIXML_SUCCESS;
+ return TIXML_WRONG_TYPE;
+}
+
+int TiXmlAttribute::QueryDoubleValue( double* dval ) const
+{
+ if ( sscanf( value.c_str(), "%lf", dval ) == 1 )
+ return TIXML_SUCCESS;
+ return TIXML_WRONG_TYPE;
+}
+
+void TiXmlAttribute::SetIntValue( int _value )
+{
+ char buf [64];
+ #if defined(TIXML_SNPRINTF)
+ TIXML_SNPRINTF(buf, sizeof(buf), "%d", _value);
+ #else
+ sprintf (buf, "%d", _value);
+ #endif
+ SetValue (buf);
+}
+
+void TiXmlAttribute::SetDoubleValue( double _value )
+{
+ char buf [256];
+ #if defined(TIXML_SNPRINTF)
+ TIXML_SNPRINTF( buf, sizeof(buf), "%lf", _value);
+ #else
+ sprintf (buf, "%lf", _value);
+ #endif
+ SetValue (buf);
+}
+
+int TiXmlAttribute::IntValue() const
+{
+ return atoi (value.c_str ());
+}
+
+double TiXmlAttribute::DoubleValue() const
+{
+ return atof (value.c_str ());
+}
+
+
+TiXmlComment::TiXmlComment( const TiXmlComment& copy ) : TiXmlNode( TiXmlNode::COMMENT )
+{
+ copy.CopyTo( this );
+}
+
+
+void TiXmlComment::operator=( const TiXmlComment& base )
+{
+ Clear();
+ base.CopyTo( this );
+}
+
+
+void TiXmlComment::Print( FILE* cfile, int depth ) const
+{
+ for ( int i=0; i<depth; i++ )
+ {
+ fputs( " ", cfile );
+ }
+ fprintf( cfile, "<!--%s-->", value.c_str() );
+}
+
+void TiXmlComment::StreamOut( TIXML_OSTREAM * stream ) const
+{
+ (*stream) << "<!--";
+ //PutString( value, stream );
+ (*stream) << value;
+ (*stream) << "-->";
+}
+
+
+void TiXmlComment::CopyTo( TiXmlComment* target ) const
+{
+ TiXmlNode::CopyTo( target );
+}
+
+
+TiXmlNode* TiXmlComment::Clone() const
+{
+ TiXmlComment* clone = new TiXmlComment();
+
+ if ( !clone )
+ return 0;
+
+ CopyTo( clone );
+ return clone;
+}
+
+
+void TiXmlText::Print( FILE* cfile, int depth ) const
+{
+ if ( cdata )
+ {
+ int i;
+ fprintf( cfile, "\n" );
+ for ( i=0; i<depth; i++ ) {
+ fprintf( cfile, " " );
+ }
+ fprintf( cfile, "<![CDATA[" );
+ fprintf( cfile, "%s", value.c_str() ); // unformatted output
+ fprintf( cfile, "]]>\n" );
+ }
+ else
+ {
+ TIXML_STRING buffer;
+ PutString( value, &buffer );
+ fprintf( cfile, "%s", buffer.c_str() );
+ }
+}
+
+
+void TiXmlText::StreamOut( TIXML_OSTREAM * stream ) const
+{
+ if ( cdata )
+ {
+ (*stream) << "<![CDATA[" << value << "]]>";
+ }
+ else
+ {
+ PutString( value, stream );
+ }
+}
+
+
+void TiXmlText::CopyTo( TiXmlText* target ) const
+{
+ TiXmlNode::CopyTo( target );
+ target->cdata = cdata;
+}
+
+
+TiXmlNode* TiXmlText::Clone() const
+{
+ TiXmlText* clone = 0;
+ clone = new TiXmlText( "" );
+
+ if ( !clone )
+ return 0;
+
+ CopyTo( clone );
+ return clone;
+}
+
+
+TiXmlDeclaration::TiXmlDeclaration( const char * _version,
+ const char * _encoding,
+ const char * _standalone )
+ : TiXmlNode( TiXmlNode::DECLARATION )
+{
+ version = _version;
+ encoding = _encoding;
+ standalone = _standalone;
+}
+
+
+#ifdef TIXML_USE_STL
+TiXmlDeclaration::TiXmlDeclaration( const std::string& _version,
+ const std::string& _encoding,
+ const std::string& _standalone )
+ : TiXmlNode( TiXmlNode::DECLARATION )
+{
+ version = _version;
+ encoding = _encoding;
+ standalone = _standalone;
+}
+#endif
+
+
+TiXmlDeclaration::TiXmlDeclaration( const TiXmlDeclaration& copy )
+ : TiXmlNode( TiXmlNode::DECLARATION )
+{
+ copy.CopyTo( this );
+}
+
+
+void TiXmlDeclaration::operator=( const TiXmlDeclaration& copy )
+{
+ Clear();
+ copy.CopyTo( this );
+}
+
+
+void TiXmlDeclaration::Print( FILE* cfile, int /*depth*/ ) const
+{
+ fprintf (cfile, "<?xml ");
+
+ if ( !version.empty() )
+ fprintf (cfile, "version=\"%s\" ", version.c_str ());
+ if ( !encoding.empty() )
+ fprintf (cfile, "encoding=\"%s\" ", encoding.c_str ());
+ if ( !standalone.empty() )
+ fprintf (cfile, "standalone=\"%s\" ", standalone.c_str ());
+ fprintf (cfile, "?>");
+}
+
+void TiXmlDeclaration::StreamOut( TIXML_OSTREAM * stream ) const
+{
+ (*stream) << "<?xml ";
+
+ if ( !version.empty() )
+ {
+ (*stream) << "version=\"";
+ PutString( version, stream );
+ (*stream) << "\" ";
+ }
+ if ( !encoding.empty() )
+ {
+ (*stream) << "encoding=\"";
+ PutString( encoding, stream );
+ (*stream ) << "\" ";
+ }
+ if ( !standalone.empty() )
+ {
+ (*stream) << "standalone=\"";
+ PutString( standalone, stream );
+ (*stream) << "\" ";
+ }
+ (*stream) << "?>";
+}
+
+
+void TiXmlDeclaration::CopyTo( TiXmlDeclaration* target ) const
+{
+ TiXmlNode::CopyTo( target );
+
+ target->version = version;
+ target->encoding = encoding;
+ target->standalone = standalone;
+}
+
+
+TiXmlNode* TiXmlDeclaration::Clone() const
+{
+ TiXmlDeclaration* clone = new TiXmlDeclaration();
+
+ if ( !clone )
+ return 0;
+
+ CopyTo( clone );
+ return clone;
+}
+
+
+void TiXmlUnknown::Print( FILE* cfile, int depth ) const
+{
+ for ( int i=0; i<depth; i++ )
+ fprintf( cfile, " " );
+ fprintf( cfile, "<%s>", value.c_str() );
+}
+
+
+void TiXmlUnknown::StreamOut( TIXML_OSTREAM * stream ) const
+{
+ (*stream) << "<" << value << ">"; // Don't use entities here! It is unknown.
+}
+
+
+void TiXmlUnknown::CopyTo( TiXmlUnknown* target ) const
+{
+ TiXmlNode::CopyTo( target );
+}
+
+
+TiXmlNode* TiXmlUnknown::Clone() const
+{
+ TiXmlUnknown* clone = new TiXmlUnknown();
+
+ if ( !clone )
+ return 0;
+
+ CopyTo( clone );
+ return clone;
+}
+
+
+TiXmlAttributeSet::TiXmlAttributeSet()
+{
+ sentinel.next = &sentinel;
+ sentinel.prev = &sentinel;
+}
+
+
+TiXmlAttributeSet::~TiXmlAttributeSet()
+{
+ assert( sentinel.next == &sentinel );
+ assert( sentinel.prev == &sentinel );
+}
+
+
+void TiXmlAttributeSet::Add( TiXmlAttribute* addMe )
+{
+ assert( !Find( TIXML_STRING( addMe->Name() ) ) ); // Shouldn't be multiply adding to the set.
+
+ addMe->next = &sentinel;
+ addMe->prev = sentinel.prev;
+
+ sentinel.prev->next = addMe;
+ sentinel.prev = addMe;
+}
+
+void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe )
+{
+ TiXmlAttribute* node;
+
+ for( node = sentinel.next; node != &sentinel; node = node->next )
+ {
+ if ( node == removeMe )
+ {
+ node->prev->next = node->next;
+ node->next->prev = node->prev;
+ node->next = 0;
+ node->prev = 0;
+ return;
+ }
+ }
+ assert( 0 ); // we tried to remove a non-linked attribute.
+}
+
+const TiXmlAttribute* TiXmlAttributeSet::Find( const TIXML_STRING& name ) const
+{
+ const TiXmlAttribute* node;
+
+ for( node = sentinel.next; node != &sentinel; node = node->next )
+ {
+ if ( node->name == name )
+ return node;
+ }
+ return 0;
+}
+
+TiXmlAttribute* TiXmlAttributeSet::Find( const TIXML_STRING& name )
+{
+ TiXmlAttribute* node;
+
+ for( node = sentinel.next; node != &sentinel; node = node->next )
+ {
+ if ( node->name == name )
+ return node;
+ }
+ return 0;
+}
+
+#ifdef TIXML_USE_STL
+TIXML_ISTREAM & operator >> (TIXML_ISTREAM & in, TiXmlNode & base)
+{
+ TIXML_STRING tag;
+ tag.reserve( 8 * 1000 );
+ base.StreamIn( &in, &tag );
+
+ base.Parse( tag.c_str(), 0, TIXML_DEFAULT_ENCODING );
+ return in;
+}
+#endif
+
+
+TIXML_OSTREAM & operator<< (TIXML_OSTREAM & out, const TiXmlNode & base)
+{
+ base.StreamOut (& out);
+ return out;
+}
+
+
+#ifdef TIXML_USE_STL
+std::string & operator<< (std::string& out, const TiXmlNode& base )
+{
+ std::ostringstream os_stream( std::ostringstream::out );
+ base.StreamOut( &os_stream );
+
+ out.append( os_stream.str() );
+ return out;
+}
+#endif
+
+
+TiXmlHandle TiXmlHandle::FirstChild() const
+{
+ if ( node )
+ {
+ TiXmlNode* child = node->FirstChild();
+ if ( child )
+ return TiXmlHandle( child );
+ }
+ return TiXmlHandle( 0 );
+}
+
+
+TiXmlHandle TiXmlHandle::FirstChild( const char * value ) const
+{
+ if ( node )
+ {
+ TiXmlNode* child = node->FirstChild( value );
+ if ( child )
+ return TiXmlHandle( child );
+ }
+ return TiXmlHandle( 0 );
+}
+
+
+TiXmlHandle TiXmlHandle::FirstChildElement() const
+{
+ if ( node )
+ {
+ TiXmlElement* child = node->FirstChildElement();
+ if ( child )
+ return TiXmlHandle( child );
+ }
+ return TiXmlHandle( 0 );
+}
+
+
+TiXmlHandle TiXmlHandle::FirstChildElement( const char * value ) const
+{
+ if ( node )
+ {
+ TiXmlElement* child = node->FirstChildElement( value );
+ if ( child )
+ return TiXmlHandle( child );
+ }
+ return TiXmlHandle( 0 );
+}
+
+
+TiXmlHandle TiXmlHandle::Child( int count ) const
+{
+ if ( node )
+ {
+ int i;
+ TiXmlNode* child = node->FirstChild();
+ for ( i=0;
+ child && i<count;
+ child = child->NextSibling(), ++i )
+ {
+ // nothing
+ }
+ if ( child )
+ return TiXmlHandle( child );
+ }
+ return TiXmlHandle( 0 );
+}
+
+
+TiXmlHandle TiXmlHandle::Child( const char* value, int count ) const
+{
+ if ( node )
+ {
+ int i;
+ TiXmlNode* child = node->FirstChild( value );
+ for ( i=0;
+ child && i<count;
+ child = child->NextSibling( value ), ++i )
+ {
+ // nothing
+ }
+ if ( child )
+ return TiXmlHandle( child );
+ }
+ return TiXmlHandle( 0 );
+}
+
+
+TiXmlHandle TiXmlHandle::ChildElement( int count ) const
+{
+ if ( node )
+ {
+ int i;
+ TiXmlElement* child = node->FirstChildElement();
+ for ( i=0;
+ child && i<count;
+ child = child->NextSiblingElement(), ++i )
+ {
+ // nothing
+ }
+ if ( child )
+ return TiXmlHandle( child );
+ }
+ return TiXmlHandle( 0 );
+}
+
+
+TiXmlHandle TiXmlHandle::ChildElement( const char* value, int count ) const
+{
+ if ( node )
+ {
+ int i;
+ TiXmlElement* child = node->FirstChildElement( value );
+ for ( i=0;
+ child && i<count;
+ child = child->NextSiblingElement( value ), ++i )
+ {
+ // nothing
+ }
+ if ( child )
+ return TiXmlHandle( child );
+ }
+ return TiXmlHandle( 0 );
+}
diff --git a/util/tinyxml.h b/util/tinyxml.h
new file mode 100644
index 0000000..091575a
--- /dev/null
+++ b/util/tinyxml.h
@@ -0,0 +1,1520 @@
+/*
+www.sourceforge.net/projects/tinyxml
+Original code (2.0 and earlier )copyright (c) 2000-2002 Lee Thomason (www.grinninglizard.com)
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any
+damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any
+purpose, including commercial applications, and to alter it and
+redistribute it freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must
+not claim that you wrote the original software. If you use this
+software in a product, an acknowledgment in the product documentation
+would be appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and
+must not be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source
+distribution.
+*/
+
+
+#ifndef TINYXML_INCLUDED
+#define TINYXML_INCLUDED
+
+#ifdef _MSC_VER
+#pragma warning( push )
+#pragma warning( disable : 4530 )
+#pragma warning( disable : 4786 )
+#endif
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+// Help out windows:
+#if defined( _DEBUG ) && !defined( DEBUG )
+#define DEBUG
+#endif
+
+#ifdef TIXML_USE_STL
+ #include <string>
+ #include <iostream>
+ #define TIXML_STRING std::string
+ #define TIXML_ISTREAM std::istream
+ #define TIXML_OSTREAM std::ostream
+#else
+ #include "tinystr.h"
+ #define TIXML_STRING TiXmlString
+ #define TIXML_OSTREAM TiXmlOutStream
+#endif
+
+// Deprecated library function hell. Compilers want to use the
+// new safe versions. This probably doesn't fully address the problem,
+// but it gets closer. There are too many compilers for me to fully
+// test. If you get compilation troubles, undefine TIXML_SAFE
+
+#define TIXML_SAFE // TinyXml isn't fully buffer overrun protected, safe code. This is work in progress.
+#ifdef TIXML_SAFE
+ #if defined(_MSC_VER) && (_MSC_VER >= 1400 )
+ // Microsoft visual studio, version 2005 and higher.
+ #define TIXML_SNPRINTF _snprintf_s
+ #define TIXML_SNSCANF _snscanf_s
+ #elif defined(_MSC_VER) && (_MSC_VER >= 1200 )
+ // Microsoft visual studio, version 6 and higher.
+ //#pragma message( "Using _sn* functions." )
+ #define TIXML_SNPRINTF _snprintf
+ #define TIXML_SNSCANF _snscanf
+ #elif defined(__GNUC__) && (__GNUC__ >= 3 )
+ // GCC version 3 and higher.s
+ //#warning( "Using sn* functions." )
+ #define TIXML_SNPRINTF snprintf
+ #define TIXML_SNSCANF snscanf
+ #endif
+#endif
+
+class TiXmlDocument;
+class TiXmlElement;
+class TiXmlComment;
+class TiXmlUnknown;
+class TiXmlAttribute;
+class TiXmlText;
+class TiXmlDeclaration;
+class TiXmlParsingData;
+
+const int TIXML_MAJOR_VERSION = 2;
+const int TIXML_MINOR_VERSION = 4;
+const int TIXML_PATCH_VERSION = 3;
+
+/* Internal structure for tracking location of items
+ in the XML file.
+*/
+struct TiXmlCursor
+{
+ TiXmlCursor() { Clear(); }
+ void Clear() { row = col = -1; }
+
+ int row; // 0 based.
+ int col; // 0 based.
+};
+
+
+// Only used by Attribute::Query functions
+enum
+{
+ TIXML_SUCCESS,
+ TIXML_NO_ATTRIBUTE,
+ TIXML_WRONG_TYPE
+};
+
+
+// Used by the parsing routines.
+enum TiXmlEncoding
+{
+ TIXML_ENCODING_UNKNOWN,
+ TIXML_ENCODING_UTF8,
+ TIXML_ENCODING_LEGACY
+};
+
+const TiXmlEncoding TIXML_DEFAULT_ENCODING = TIXML_ENCODING_UNKNOWN;
+
+/** TiXmlBase is a base class for every class in TinyXml.
+ It does little except to establish that TinyXml classes
+ can be printed and provide some utility functions.
+
+ In XML, the document and elements can contain
+ other elements and other types of nodes.
+
+ @verbatim
+ A Document can contain: Element (container or leaf)
+ Comment (leaf)
+ Unknown (leaf)
+ Declaration( leaf )
+
+ An Element can contain: Element (container or leaf)
+ Text (leaf)
+ Attributes (not on tree)
+ Comment (leaf)
+ Unknown (leaf)
+
+ A Decleration contains: Attributes (not on tree)
+ @endverbatim
+*/
+class TiXmlBase
+{
+ friend class TiXmlNode;
+ friend class TiXmlElement;
+ friend class TiXmlDocument;
+
+public:
+ TiXmlBase() : userData(0) {}
+ virtual ~TiXmlBase() {}
+
+ /** All TinyXml classes can print themselves to a filestream.
+ This is a formatted print, and will insert tabs and newlines.
+
+ (For an unformatted stream, use the << operator.)
+ */
+ virtual void Print( FILE* cfile, int depth ) const = 0;
+
+ /** The world does not agree on whether white space should be kept or
+ not. In order to make everyone happy, these global, static functions
+ are provided to set whether or not TinyXml will condense all white space
+ into a single space or not. The default is to condense. Note changing this
+ values is not thread safe.
+ */
+ static void SetCondenseWhiteSpace( bool condense ) { condenseWhiteSpace = condense; }
+
+ /// Return the current white space setting.
+ static bool IsWhiteSpaceCondensed() { return condenseWhiteSpace; }
+
+ /** Return the position, in the original source file, of this node or attribute.
+ The row and column are 1-based. (That is the first row and first column is
+ 1,1). If the returns values are 0 or less, then the parser does not have
+ a row and column value.
+
+ Generally, the row and column value will be set when the TiXmlDocument::Load(),
+ TiXmlDocument::LoadFile(), or any TiXmlNode::Parse() is called. It will NOT be set
+ when the DOM was created from operator>>.
+
+ The values reflect the initial load. Once the DOM is modified programmatically
+ (by adding or changing nodes and attributes) the new values will NOT update to
+ reflect changes in the document.
+
+ There is a minor performance cost to computing the row and column. Computation
+ can be disabled if TiXmlDocument::SetTabSize() is called with 0 as the value.
+
+ @sa TiXmlDocument::SetTabSize()
+ */
+ int Row() const { return location.row + 1; }
+ int Column() const { return location.col + 1; } ///< See Row()
+
+ void SetUserData( void* user ) { userData = user; }
+ void* GetUserData() { return userData; }
+
+ // Table that returs, for a given lead byte, the total number of bytes
+ // in the UTF-8 sequence.
+ static const int utf8ByteTable[256];
+
+ virtual const char* Parse( const char* p,
+ TiXmlParsingData* data,
+ TiXmlEncoding encoding /*= TIXML_ENCODING_UNKNOWN */ ) = 0;
+
+ enum
+ {
+ TIXML_NO_ERROR = 0,
+ TIXML_ERROR,
+ TIXML_ERROR_OPENING_FILE,
+ TIXML_ERROR_OUT_OF_MEMORY,
+ TIXML_ERROR_PARSING_ELEMENT,
+ TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME,
+ TIXML_ERROR_READING_ELEMENT_VALUE,
+ TIXML_ERROR_READING_ATTRIBUTES,
+ TIXML_ERROR_PARSING_EMPTY,
+ TIXML_ERROR_READING_END_TAG,
+ TIXML_ERROR_PARSING_UNKNOWN,
+ TIXML_ERROR_PARSING_COMMENT,
+ TIXML_ERROR_PARSING_DECLARATION,
+ TIXML_ERROR_DOCUMENT_EMPTY,
+ TIXML_ERROR_EMBEDDED_NULL,
+ TIXML_ERROR_PARSING_CDATA,
+
+ TIXML_ERROR_STRING_COUNT
+ };
+
+protected:
+
+ // See STL_STRING_BUG
+ // Utility class to overcome a bug.
+ class StringToBuffer
+ {
+ public:
+ StringToBuffer( const TIXML_STRING& str );
+ ~StringToBuffer();
+ char* buffer;
+ };
+
+ static const char* SkipWhiteSpace( const char*, TiXmlEncoding encoding );
+ inline static bool IsWhiteSpace( char c )
+ {
+ return ( isspace( (unsigned char) c ) || c == '\n' || c == '\r' );
+ }
+ inline static bool IsWhiteSpace( int c )
+ {
+ if ( c < 256 )
+ return IsWhiteSpace( (char) c );
+ return false; // Again, only truly correct for English/Latin...but usually works.
+ }
+
+ virtual void StreamOut (TIXML_OSTREAM *) const = 0;
+
+ #ifdef TIXML_USE_STL
+ static bool StreamWhiteSpace( TIXML_ISTREAM * in, TIXML_STRING * tag );
+ static bool StreamTo( TIXML_ISTREAM * in, int character, TIXML_STRING * tag );
+ #endif
+
+ /* Reads an XML name into the string provided. Returns
+ a pointer just past the last character of the name,
+ or 0 if the function has an error.
+ */
+ static const char* ReadName( const char* p, TIXML_STRING* name, TiXmlEncoding encoding );
+
+ /* Reads text. Returns a pointer past the given end tag.
+ Wickedly complex options, but it keeps the (sensitive) code in one place.
+ */
+ static const char* ReadText( const char* in, // where to start
+ TIXML_STRING* text, // the string read
+ bool ignoreWhiteSpace, // whether to keep the white space
+ const char* endTag, // what ends this text
+ bool ignoreCase, // whether to ignore case in the end tag
+ TiXmlEncoding encoding ); // the current encoding
+
+ // If an entity has been found, transform it into a character.
+ static const char* GetEntity( const char* in, char* value, int* length, TiXmlEncoding encoding );
+
+ // Get a character, while interpreting entities.
+ // The length can be from 0 to 4 bytes.
+ inline static const char* GetChar( const char* p, char* _value, int* length, TiXmlEncoding encoding )
+ {
+ assert( p );
+ if ( encoding == TIXML_ENCODING_UTF8 )
+ {
+ *length = utf8ByteTable[ *((unsigned char*)p) ];
+ assert( *length >= 0 && *length < 5 );
+ }
+ else
+ {
+ *length = 1;
+ }
+
+ if ( *length == 1 )
+ {
+ if ( *p == '&' )
+ return GetEntity( p, _value, length, encoding );
+ *_value = *p;
+ return p+1;
+ }
+ else if ( *length )
+ {
+ //strncpy( _value, p, *length ); // lots of compilers don't like this function (unsafe),
+ // and the null terminator isn't needed
+ for( int i=0; p[i] && i<*length; ++i ) {
+ _value[i] = p[i];
+ }
+ return p + (*length);
+ }
+ else
+ {
+ // Not valid text.
+ return 0;
+ }
+ }
+
+ // Puts a string to a stream, expanding entities as it goes.
+ // Note this should not contian the '<', '>', etc, or they will be transformed into entities!
+ static void PutString( const TIXML_STRING& str, TIXML_OSTREAM* out );
+
+ static void PutString( const TIXML_STRING& str, TIXML_STRING* out );
+
+ // Return true if the next characters in the stream are any of the endTag sequences.
+ // Ignore case only works for english, and should only be relied on when comparing
+ // to English words: StringEqual( p, "version", true ) is fine.
+ static bool StringEqual( const char* p,
+ const char* endTag,
+ bool ignoreCase,
+ TiXmlEncoding encoding );
+
+ static const char* errorString[ TIXML_ERROR_STRING_COUNT ];
+
+ TiXmlCursor location;
+
+ /// Field containing a generic user pointer
+ void* userData;
+
+ // None of these methods are reliable for any language except English.
+ // Good for approximation, not great for accuracy.
+ static int IsAlpha( unsigned char anyByte, TiXmlEncoding encoding );
+ static int IsAlphaNum( unsigned char anyByte, TiXmlEncoding encoding );
+ inline static int ToLower( int v, TiXmlEncoding encoding )
+ {
+ if ( encoding == TIXML_ENCODING_UTF8 )
+ {
+ if ( v < 128 ) return tolower( v );
+ return v;
+ }
+ else
+ {
+ return tolower( v );
+ }
+ }
+ static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );
+
+private:
+ TiXmlBase( const TiXmlBase& ); // not implemented.
+ void operator=( const TiXmlBase& base ); // not allowed.
+
+ struct Entity
+ {
+ const char* str;
+ unsigned int strLength;
+ char chr;
+ };
+ enum
+ {
+ NUM_ENTITY = 5,
+ MAX_ENTITY_LENGTH = 6
+
+ };
+ static Entity entity[ NUM_ENTITY ];
+ static bool condenseWhiteSpace;
+};
+
+
+/** The parent class for everything in the Document Object Model.
+ (Except for attributes).
+ Nodes have siblings, a parent, and children. A node can be
+ in a document, or stand on its own. The type of a TiXmlNode
+ can be queried, and it can be cast to its more defined type.
+*/
+class TiXmlNode : public TiXmlBase
+{
+ friend class TiXmlDocument;
+ friend class TiXmlElement;
+
+public:
+ #ifdef TIXML_USE_STL
+
+ /** An input stream operator, for every class. Tolerant of newlines and
+ formatting, but doesn't expect them.
+ */
+ friend std::istream& operator >> (std::istream& in, TiXmlNode& base);
+
+ /** An output stream operator, for every class. Note that this outputs
+ without any newlines or formatting, as opposed to Print(), which
+ includes tabs and new lines.
+
+ The operator<< and operator>> are not completely symmetric. Writing
+ a node to a stream is very well defined. You'll get a nice stream
+ of output, without any extra whitespace or newlines.
+
+ But reading is not as well defined. (As it always is.) If you create
+ a TiXmlElement (for example) and read that from an input stream,
+ the text needs to define an element or junk will result. This is
+ true of all input streams, but it's worth keeping in mind.
+
+ A TiXmlDocument will read nodes until it reads a root element, and
+ all the children of that root element.
+ */
+ friend std::ostream& operator<< (std::ostream& out, const TiXmlNode& base);
+
+ /// Appends the XML node or attribute to a std::string.
+ friend std::string& operator<< (std::string& out, const TiXmlNode& base );
+
+ #else
+ // Used internally, not part of the public API.
+ friend TIXML_OSTREAM& operator<< (TIXML_OSTREAM& out, const TiXmlNode& base);
+ #endif
+
+ /** The types of XML nodes supported by TinyXml. (All the
+ unsupported types are picked up by UNKNOWN.)
+ */
+ enum NodeType
+ {
+ DOCUMENT,
+ ELEMENT,
+ COMMENT,
+ UNKNOWN,
+ TEXT,
+ DECLARATION,
+ TYPECOUNT
+ };
+
+ virtual ~TiXmlNode();
+
+ /** The meaning of 'value' changes for the specific type of
+ TiXmlNode.
+ @verbatim
+ Document: filename of the xml file
+ Element: name of the element
+ Comment: the comment text
+ Unknown: the tag contents
+ Text: the text string
+ @endverbatim
+
+ The subclasses will wrap this function.
+ */
+ const char *Value() const { return value.c_str (); }
+
+ #ifdef TIXML_USE_STL
+ /** Return Value() as a std::string. If you only use STL,
+ this is more efficient than calling Value().
+ Only available in STL mode.
+ */
+ const std::string& ValueStr() const { return value; }
+ #endif
+
+ /** Changes the value of the node. Defined as:
+ @verbatim
+ Document: filename of the xml file
+ Element: name of the element
+ Comment: the comment text
+ Unknown: the tag contents
+ Text: the text string
+ @endverbatim
+ */
+ void SetValue(const char * _value) { value = _value;}
+
+ #ifdef TIXML_USE_STL
+ /// STL std::string form.
+ void SetValue( const std::string& _value ) { value = _value; }
+ #endif
+
+ /// Delete all the children of this node. Does not affect 'this'.
+ void Clear();
+
+ /// One step up the DOM.
+ TiXmlNode* Parent() { return parent; }
+ const TiXmlNode* Parent() const { return parent; }
+
+ const TiXmlNode* FirstChild() const { return firstChild; } ///< The first child of this node. Will be null if there are no children.
+ TiXmlNode* FirstChild() { return firstChild; }
+ const TiXmlNode* FirstChild( const char * value ) const; ///< The first child of this node with the matching 'value'. Will be null if none found.
+ TiXmlNode* FirstChild( const char * value ); ///< The first child of this node with the matching 'value'. Will be null if none found.
+
+ const TiXmlNode* LastChild() const { return lastChild; } /// The last child of this node. Will be null if there are no children.
+ TiXmlNode* LastChild() { return lastChild; }
+ const TiXmlNode* LastChild( const char * value ) const; /// The last child of this node matching 'value'. Will be null if there are no children.
+ TiXmlNode* LastChild( const char * value );
+
+ #ifdef TIXML_USE_STL
+ const TiXmlNode* FirstChild( const std::string& _value ) const { return FirstChild (_value.c_str ()); } ///< STL std::string form.
+ TiXmlNode* FirstChild( const std::string& _value ) { return FirstChild (_value.c_str ()); } ///< STL std::string form.
+ const TiXmlNode* LastChild( const std::string& _value ) const { return LastChild (_value.c_str ()); } ///< STL std::string form.
+ TiXmlNode* LastChild( const std::string& _value ) { return LastChild (_value.c_str ()); } ///< STL std::string form.
+ #endif
+
+ /** An alternate way to walk the children of a node.
+ One way to iterate over nodes is:
+ @verbatim
+ for( child = parent->FirstChild(); child; child = child->NextSibling() )
+ @endverbatim
+
+ IterateChildren does the same thing with the syntax:
+ @verbatim
+ child = 0;
+ while( child = parent->IterateChildren( child ) )
+ @endverbatim
+
+ IterateChildren takes the previous child as input and finds
+ the next one. If the previous child is null, it returns the
+ first. IterateChildren will return null when done.
+ */
+ const TiXmlNode* IterateChildren( const TiXmlNode* previous ) const;
+ TiXmlNode* IterateChildren( TiXmlNode* previous );
+
+ /// This flavor of IterateChildren searches for children with a particular 'value'
+ const TiXmlNode* IterateChildren( const char * value, const TiXmlNode* previous ) const;
+ TiXmlNode* IterateChildren( const char * value, TiXmlNode* previous );
+
+ #ifdef TIXML_USE_STL
+ const TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) const { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form.
+ TiXmlNode* IterateChildren( const std::string& _value, TiXmlNode* previous ) { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form.
+ #endif
+
+ /** Add a new node related to this. Adds a child past the LastChild.
+ Returns a pointer to the new object or NULL if an error occured.
+ */
+ TiXmlNode* InsertEndChild( const TiXmlNode& addThis );
+
+
+ /** Add a new node related to this. Adds a child past the LastChild.
+
+ NOTE: the node to be added is passed by pointer, and will be
+ henceforth owned (and deleted) by tinyXml. This method is efficient
+ and avoids an extra copy, but should be used with care as it
+ uses a different memory model than the other insert functions.
+
+ @sa InsertEndChild
+ */
+ TiXmlNode* LinkEndChild( TiXmlNode* addThis );
+
+ /** Add a new node related to this. Adds a child before the specified child.
+ Returns a pointer to the new object or NULL if an error occured.
+ */
+ TiXmlNode* InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis );
+
+ /** Add a new node related to this. Adds a child after the specified child.
+ Returns a pointer to the new object or NULL if an error occured.
+ */
+ TiXmlNode* InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis );
+
+ /** Replace a child of this node.
+ Returns a pointer to the new object or NULL if an error occured.
+ */
+ TiXmlNode* ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis );
+
+ /// Delete a child of this node.
+ bool RemoveChild( TiXmlNode* removeThis );
+
+ /// Navigate to a sibling node.
+ const TiXmlNode* PreviousSibling() const { return prev; }
+ TiXmlNode* PreviousSibling() { return prev; }
+
+ /// Navigate to a sibling node.
+ const TiXmlNode* PreviousSibling( const char * ) const;
+ TiXmlNode* PreviousSibling( const char * );
+
+ #ifdef TIXML_USE_STL
+ const TiXmlNode* PreviousSibling( const std::string& _value ) const { return PreviousSibling (_value.c_str ()); } ///< STL std::string form.
+ TiXmlNode* PreviousSibling( const std::string& _value ) { return PreviousSibling (_value.c_str ()); } ///< STL std::string form.
+ const TiXmlNode* NextSibling( const std::string& _value) const { return NextSibling (_value.c_str ()); } ///< STL std::string form.
+ TiXmlNode* NextSibling( const std::string& _value) { return NextSibling (_value.c_str ()); } ///< STL std::string form.
+ #endif
+
+ /// Navigate to a sibling node.
+ const TiXmlNode* NextSibling() const { return next; }
+ TiXmlNode* NextSibling() { return next; }
+
+ /// Navigate to a sibling node with the given 'value'.
+ const TiXmlNode* NextSibling( const char * ) const;
+ TiXmlNode* NextSibling( const char * );
+
+ /** Convenience function to get through elements.
+ Calls NextSibling and ToElement. Will skip all non-Element
+ nodes. Returns 0 if there is not another element.
+ */
+ const TiXmlElement* NextSiblingElement() const;
+ TiXmlElement* NextSiblingElement();
+
+ /** Convenience function to get through elements.
+ Calls NextSibling and ToElement. Will skip all non-Element
+ nodes. Returns 0 if there is not another element.
+ */
+ const TiXmlElement* NextSiblingElement( const char * ) const;
+ TiXmlElement* NextSiblingElement( const char * );
+
+ #ifdef TIXML_USE_STL
+ const TiXmlElement* NextSiblingElement( const std::string& _value) const { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form.
+ TiXmlElement* NextSiblingElement( const std::string& _value) { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form.
+ #endif
+
+ /// Convenience function to get through elements.
+ const TiXmlElement* FirstChildElement() const;
+ TiXmlElement* FirstChildElement();
+
+ /// Convenience function to get through elements.
+ const TiXmlElement* FirstChildElement( const char * value ) const;
+ TiXmlElement* FirstChildElement( const char * value );
+
+ #ifdef TIXML_USE_STL
+ const TiXmlElement* FirstChildElement( const std::string& _value ) const { return FirstChildElement (_value.c_str ()); } ///< STL std::string form.
+ TiXmlElement* FirstChildElement( const std::string& _value ) { return FirstChildElement (_value.c_str ()); } ///< STL std::string form.
+ #endif
+
+ /** Query the type (as an enumerated value, above) of this node.
+ The possible types are: DOCUMENT, ELEMENT, COMMENT,
+ UNKNOWN, TEXT, and DECLARATION.
+ */
+ int Type() const { return type; }
+
+ /** Return a pointer to the Document this node lives in.
+ Returns null if not in a document.
+ */
+ const TiXmlDocument* GetDocument() const;
+ TiXmlDocument* GetDocument();
+
+ /// Returns true if this node has no children.
+ bool NoChildren() const { return !firstChild; }
+
+ virtual const TiXmlDocument* ToDocument() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+ virtual const TiXmlElement* ToElement() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+ virtual const TiXmlComment* ToComment() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+ virtual const TiXmlUnknown* ToUnknown() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+ virtual const TiXmlText* ToText() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+ virtual const TiXmlDeclaration* ToDeclaration() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+
+ virtual TiXmlDocument* ToDocument() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+ virtual TiXmlElement* ToElement() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+ virtual TiXmlComment* ToComment() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+ virtual TiXmlUnknown* ToUnknown() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+ virtual TiXmlText* ToText() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+ virtual TiXmlDeclaration* ToDeclaration() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+
+ /** Create an exact duplicate of this node and return it. The memory must be deleted
+ by the caller.
+ */
+ virtual TiXmlNode* Clone() const = 0;
+
+protected:
+ TiXmlNode( NodeType _type );
+
+ // Copy to the allocated object. Shared functionality between Clone, Copy constructor,
+ // and the assignment operator.
+ void CopyTo( TiXmlNode* target ) const;
+
+ #ifdef TIXML_USE_STL
+ // The real work of the input operator.
+ virtual void StreamIn( TIXML_ISTREAM* in, TIXML_STRING* tag ) = 0;
+ #endif
+
+ // Figure out what is at *p, and parse it. Returns null if it is not an xml node.
+ TiXmlNode* Identify( const char* start, TiXmlEncoding encoding );
+
+ TiXmlNode* parent;
+ NodeType type;
+
+ TiXmlNode* firstChild;
+ TiXmlNode* lastChild;
+
+ TIXML_STRING value;
+
+ TiXmlNode* prev;
+ TiXmlNode* next;
+
+private:
+ TiXmlNode( const TiXmlNode& ); // not implemented.
+ void operator=( const TiXmlNode& base ); // not allowed.
+};
+
+
+/** An attribute is a name-value pair. Elements have an arbitrary
+ number of attributes, each with a unique name.
+
+ @note The attributes are not TiXmlNodes, since they are not
+ part of the tinyXML document object model. There are other
+ suggested ways to look at this problem.
+*/
+class TiXmlAttribute : public TiXmlBase
+{
+ friend class TiXmlAttributeSet;
+
+public:
+ /// Construct an empty attribute.
+ TiXmlAttribute() : TiXmlBase()
+ {
+ document = 0;
+ prev = next = 0;
+ }
+
+ #ifdef TIXML_USE_STL
+ /// std::string constructor.
+ TiXmlAttribute( const std::string& _name, const std::string& _value )
+ {
+ name = _name;
+ value = _value;
+ document = 0;
+ prev = next = 0;
+ }
+ #endif
+
+ /// Construct an attribute with a name and value.
+ TiXmlAttribute( const char * _name, const char * _value )
+ {
+ name = _name;
+ value = _value;
+ document = 0;
+ prev = next = 0;
+ }
+
+ const char* Name() const { return name.c_str (); } ///< Return the name of this attribute.
+ const char* Value() const { return value.c_str (); } ///< Return the value of this attribute.
+ int IntValue() const; ///< Return the value of this attribute, converted to an integer.
+ double DoubleValue() const; ///< Return the value of this attribute, converted to a double.
+
+ // Get the tinyxml string representation
+ const TIXML_STRING& NameTStr() const { return name; }
+
+ /** QueryIntValue examines the value string. It is an alternative to the
+ IntValue() method with richer error checking.
+ If the value is an integer, it is stored in 'value' and
+ the call returns TIXML_SUCCESS. If it is not
+ an integer, it returns TIXML_WRONG_TYPE.
+
+ A specialized but useful call. Note that for success it returns 0,
+ which is the opposite of almost all other TinyXml calls.
+ */
+ int QueryIntValue( int* _value ) const;
+ /// QueryDoubleValue examines the value string. See QueryIntValue().
+ int QueryDoubleValue( double* _value ) const;
+
+ void SetName( const char* _name ) { name = _name; } ///< Set the name of this attribute.
+ void SetValue( const char* _value ) { value = _value; } ///< Set the value.
+
+ void SetIntValue( int _value ); ///< Set the value from an integer.
+ void SetDoubleValue( double _value ); ///< Set the value from a double.
+
+ #ifdef TIXML_USE_STL
+ /// STL std::string form.
+ void SetName( const std::string& _name ) { name = _name; }
+ /// STL std::string form.
+ void SetValue( const std::string& _value ) { value = _value; }
+ #endif
+
+ /// Get the next sibling attribute in the DOM. Returns null at end.
+ const TiXmlAttribute* Next() const;
+ TiXmlAttribute* Next();
+ /// Get the previous sibling attribute in the DOM. Returns null at beginning.
+ const TiXmlAttribute* Previous() const;
+ TiXmlAttribute* Previous();
+
+ bool operator==( const TiXmlAttribute& rhs ) const { return rhs.name == name; }
+ bool operator<( const TiXmlAttribute& rhs ) const { return name < rhs.name; }
+ bool operator>( const TiXmlAttribute& rhs ) const { return name > rhs.name; }
+
+ /* Attribute parsing starts: first letter of the name
+ returns: the next char after the value end quote
+ */
+ virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
+
+ // Prints this Attribute to a FILE stream.
+ virtual void Print( FILE* cfile, int depth ) const;
+
+ virtual void StreamOut( TIXML_OSTREAM * out ) const;
+ // [internal use]
+ // Set the document pointer so the attribute can report errors.
+ void SetDocument( TiXmlDocument* doc ) { document = doc; }
+
+private:
+ TiXmlAttribute( const TiXmlAttribute& ); // not implemented.
+ void operator=( const TiXmlAttribute& base ); // not allowed.
+
+ TiXmlDocument* document; // A pointer back to a document, for error reporting.
+ TIXML_STRING name;
+ TIXML_STRING value;
+ TiXmlAttribute* prev;
+ TiXmlAttribute* next;
+};
+
+
+/* A class used to manage a group of attributes.
+ It is only used internally, both by the ELEMENT and the DECLARATION.
+
+ The set can be changed transparent to the Element and Declaration
+ classes that use it, but NOT transparent to the Attribute
+ which has to implement a next() and previous() method. Which makes
+ it a bit problematic and prevents the use of STL.
+
+ This version is implemented with circular lists because:
+ - I like circular lists
+ - it demonstrates some independence from the (typical) doubly linked list.
+*/
+class TiXmlAttributeSet
+{
+public:
+ TiXmlAttributeSet();
+ ~TiXmlAttributeSet();
+
+ void Add( TiXmlAttribute* attribute );
+ void Remove( TiXmlAttribute* attribute );
+
+ const TiXmlAttribute* First() const { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; }
+ TiXmlAttribute* First() { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; }
+ const TiXmlAttribute* Last() const { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; }
+ TiXmlAttribute* Last() { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; }
+
+ const TiXmlAttribute* Find( const TIXML_STRING& name ) const;
+ TiXmlAttribute* Find( const TIXML_STRING& name );
+
+private:
+ //*ME: Because of hidden/disabled copy-construktor in TiXmlAttribute (sentinel-element),
+ //*ME: this class must be also use a hidden/disabled copy-constructor !!!
+ TiXmlAttributeSet( const TiXmlAttributeSet& ); // not allowed
+ void operator=( const TiXmlAttributeSet& ); // not allowed (as TiXmlAttribute)
+
+ TiXmlAttribute sentinel;
+};
+
+
+/** The element is a container class. It has a value, the element name,
+ and can contain other elements, text, comments, and unknowns.
+ Elements also contain an arbitrary number of attributes.
+*/
+class TiXmlElement : public TiXmlNode
+{
+public:
+ /// Construct an element.
+ TiXmlElement (const char * in_value);
+
+ #ifdef TIXML_USE_STL
+ /// std::string constructor.
+ TiXmlElement( const std::string& _value );
+ #endif
+
+ TiXmlElement( const TiXmlElement& );
+
+ void operator=( const TiXmlElement& base );
+
+ virtual ~TiXmlElement();
+
+ /** Given an attribute name, Attribute() returns the value
+ for the attribute of that name, or null if none exists.
+ */
+ const char* Attribute( const char* name ) const;
+
+ /** Given an attribute name, Attribute() returns the value
+ for the attribute of that name, or null if none exists.
+ If the attribute exists and can be converted to an integer,
+ the integer value will be put in the return 'i', if 'i'
+ is non-null.
+ */
+ const char* Attribute( const char* name, int* i ) const;
+
+ /** Given an attribute name, Attribute() returns the value
+ for the attribute of that name, or null if none exists.
+ If the attribute exists and can be converted to an double,
+ the double value will be put in the return 'd', if 'd'
+ is non-null.
+ */
+ const char* Attribute( const char* name, double* d ) const;
+
+ /** QueryIntAttribute examines the attribute - it is an alternative to the
+ Attribute() method with richer error checking.
+ If the attribute is an integer, it is stored in 'value' and
+ the call returns TIXML_SUCCESS. If it is not
+ an integer, it returns TIXML_WRONG_TYPE. If the attribute
+ does not exist, then TIXML_NO_ATTRIBUTE is returned.
+ */
+ int QueryIntAttribute( const char* name, int* _value ) const;
+ /// QueryDoubleAttribute examines the attribute - see QueryIntAttribute().
+ int QueryDoubleAttribute( const char* name, double* _value ) const;
+ /// QueryFloatAttribute examines the attribute - see QueryIntAttribute().
+ int QueryFloatAttribute( const char* name, float* _value ) const {
+ double d;
+ int result = QueryDoubleAttribute( name, &d );
+ if ( result == TIXML_SUCCESS ) {
+ *_value = (float)d;
+ }
+ return result;
+ }
+
+ /** Sets an attribute of name to a given value. The attribute
+ will be created if it does not exist, or changed if it does.
+ */
+ void SetAttribute( const char* name, const char * _value );
+
+ #ifdef TIXML_USE_STL
+ const char* Attribute( const std::string& name ) const { return Attribute( name.c_str() ); }
+ const char* Attribute( const std::string& name, int* i ) const { return Attribute( name.c_str(), i ); }
+ const char* Attribute( const std::string& name, double* d ) const { return Attribute( name.c_str(), d ); }
+ int QueryIntAttribute( const std::string& name, int* _value ) const { return QueryIntAttribute( name.c_str(), _value ); }
+ int QueryDoubleAttribute( const std::string& name, double* _value ) const { return QueryDoubleAttribute( name.c_str(), _value ); }
+
+ /// STL std::string form.
+ void SetAttribute( const std::string& name, const std::string& _value );
+ ///< STL std::string form.
+ void SetAttribute( const std::string& name, int _value );
+ #endif
+
+ /** Sets an attribute of name to a given value. The attribute
+ will be created if it does not exist, or changed if it does.
+ */
+ void SetAttribute( const char * name, int value );
+
+ /** Sets an attribute of name to a given value. The attribute
+ will be created if it does not exist, or changed if it does.
+ */
+ void SetDoubleAttribute( const char * name, double value );
+
+ /** Deletes an attribute with the given name.
+ */
+ void RemoveAttribute( const char * name );
+ #ifdef TIXML_USE_STL
+ void RemoveAttribute( const std::string& name ) { RemoveAttribute (name.c_str ()); } ///< STL std::string form.
+ #endif
+
+ const TiXmlAttribute* FirstAttribute() const { return attributeSet.First(); } ///< Access the first attribute in this element.
+ TiXmlAttribute* FirstAttribute() { return attributeSet.First(); }
+ const TiXmlAttribute* LastAttribute() const { return attributeSet.Last(); } ///< Access the last attribute in this element.
+ TiXmlAttribute* LastAttribute() { return attributeSet.Last(); }
+
+ /** Convenience function for easy access to the text inside an element. Although easy
+ and concise, GetText() is limited compared to getting the TiXmlText child
+ and accessing it directly.
+
+ If the first child of 'this' is a TiXmlText, the GetText()
+ returns the character string of the Text node, else null is returned.
+
+ This is a convenient method for getting the text of simple contained text:
+ @verbatim
+ <foo>This is text</foo>
+ const char* str = fooElement->GetText();
+ @endverbatim
+
+ 'str' will be a pointer to "This is text".
+
+ Note that this function can be misleading. If the element foo was created from
+ this XML:
+ @verbatim
+ <foo><b>This is text</b></foo>
+ @endverbatim
+
+ then the value of str would be null. The first child node isn't a text node, it is
+ another element. From this XML:
+ @verbatim
+ <foo>This is <b>text</b></foo>
+ @endverbatim
+ GetText() will return "This is ".
+
+ WARNING: GetText() accesses a child node - don't become confused with the
+ similarly named TiXmlHandle::Text() and TiXmlNode::ToText() which are
+ safe type casts on the referenced node.
+ */
+ const char* GetText() const;
+
+ /// Creates a new Element and returns it - the returned element is a copy.
+ virtual TiXmlNode* Clone() const;
+ // Print the Element to a FILE stream.
+ virtual void Print( FILE* cfile, int depth ) const;
+
+ /* Attribtue parsing starts: next char past '<'
+ returns: next char past '>'
+ */
+ virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
+
+ virtual const TiXmlElement* ToElement() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+ virtual TiXmlElement* ToElement() { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+
+protected:
+
+ void CopyTo( TiXmlElement* target ) const;
+ void ClearThis(); // like clear, but initializes 'this' object as well
+
+ // Used to be public [internal use]
+ #ifdef TIXML_USE_STL
+ virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag );
+ #endif
+ virtual void StreamOut( TIXML_OSTREAM * out ) const;
+
+ /* [internal use]
+ Reads the "value" of the element -- another element, or text.
+ This should terminate with the current end tag.
+ */
+ const char* ReadValue( const char* in, TiXmlParsingData* prevData, TiXmlEncoding encoding );
+
+private:
+
+ TiXmlAttributeSet attributeSet;
+};
+
+
+/** An XML comment.
+*/
+class TiXmlComment : public TiXmlNode
+{
+public:
+ /// Constructs an empty comment.
+ TiXmlComment() : TiXmlNode( TiXmlNode::COMMENT ) {}
+ TiXmlComment( const TiXmlComment& );
+ void operator=( const TiXmlComment& base );
+
+ virtual ~TiXmlComment() {}
+
+ /// Returns a copy of this Comment.
+ virtual TiXmlNode* Clone() const;
+ /// Write this Comment to a FILE stream.
+ virtual void Print( FILE* cfile, int depth ) const;
+
+ /* Attribtue parsing starts: at the ! of the !--
+ returns: next char past '>'
+ */
+ virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
+
+ virtual const TiXmlComment* ToComment() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+ virtual TiXmlComment* ToComment() { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+
+protected:
+ void CopyTo( TiXmlComment* target ) const;
+
+ // used to be public
+ #ifdef TIXML_USE_STL
+ virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag );
+ #endif
+ virtual void StreamOut( TIXML_OSTREAM * out ) const;
+
+private:
+
+};
+
+
+/** XML text. A text node can have 2 ways to output the next. "normal" output
+ and CDATA. It will default to the mode it was parsed from the XML file and
+ you generally want to leave it alone, but you can change the output mode with
+ SetCDATA() and query it with CDATA().
+*/
+class TiXmlText : public TiXmlNode
+{
+ friend class TiXmlElement;
+public:
+ /** Constructor for text element. By default, it is treated as
+ normal, encoded text. If you want it be output as a CDATA text
+ element, set the parameter _cdata to 'true'
+ */
+ TiXmlText (const char * initValue ) : TiXmlNode (TiXmlNode::TEXT)
+ {
+ SetValue( initValue );
+ cdata = false;
+ }
+ virtual ~TiXmlText() {}
+
+ #ifdef TIXML_USE_STL
+ /// Constructor.
+ TiXmlText( const std::string& initValue ) : TiXmlNode (TiXmlNode::TEXT)
+ {
+ SetValue( initValue );
+ cdata = false;
+ }
+ #endif
+
+ TiXmlText( const TiXmlText& copy ) : TiXmlNode( TiXmlNode::TEXT ) { copy.CopyTo( this ); }
+ void operator=( const TiXmlText& base ) { base.CopyTo( this ); }
+
+ /// Write this text object to a FILE stream.
+ virtual void Print( FILE* cfile, int depth ) const;
+
+ /// Queries whether this represents text using a CDATA section.
+ bool CDATA() { return cdata; }
+ /// Turns on or off a CDATA representation of text.
+ void SetCDATA( bool _cdata ) { cdata = _cdata; }
+
+ virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
+
+ virtual const TiXmlText* ToText() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+ virtual TiXmlText* ToText() { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+
+protected :
+ /// [internal use] Creates a new Element and returns it.
+ virtual TiXmlNode* Clone() const;
+ void CopyTo( TiXmlText* target ) const;
+
+ virtual void StreamOut ( TIXML_OSTREAM * out ) const;
+ bool Blank() const; // returns true if all white space and new lines
+ // [internal use]
+ #ifdef TIXML_USE_STL
+ virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag );
+ #endif
+
+private:
+ bool cdata; // true if this should be input and output as a CDATA style text element
+};
+
+
+/** In correct XML the declaration is the first entry in the file.
+ @verbatim
+ <?xml version="1.0" standalone="yes"?>
+ @endverbatim
+
+ TinyXml will happily read or write files without a declaration,
+ however. There are 3 possible attributes to the declaration:
+ version, encoding, and standalone.
+
+ Note: In this version of the code, the attributes are
+ handled as special cases, not generic attributes, simply
+ because there can only be at most 3 and they are always the same.
+*/
+class TiXmlDeclaration : public TiXmlNode
+{
+public:
+ /// Construct an empty declaration.
+ TiXmlDeclaration() : TiXmlNode( TiXmlNode::DECLARATION ) {}
+
+#ifdef TIXML_USE_STL
+ /// Constructor.
+ TiXmlDeclaration( const std::string& _version,
+ const std::string& _encoding,
+ const std::string& _standalone );
+#endif
+
+ /// Construct.
+ TiXmlDeclaration( const char* _version,
+ const char* _encoding,
+ const char* _standalone );
+
+ TiXmlDeclaration( const TiXmlDeclaration& copy );
+ void operator=( const TiXmlDeclaration& copy );
+
+ virtual ~TiXmlDeclaration() {}
+
+ /// Version. Will return an empty string if none was found.
+ const char *Version() const { return version.c_str (); }
+ /// Encoding. Will return an empty string if none was found.
+ const char *Encoding() const { return encoding.c_str (); }
+ /// Is this a standalone document?
+ const char *Standalone() const { return standalone.c_str (); }
+
+ /// Creates a copy of this Declaration and returns it.
+ virtual TiXmlNode* Clone() const;
+ /// Print this declaration to a FILE stream.
+ virtual void Print( FILE* cfile, int depth ) const;
+
+ virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
+
+ virtual const TiXmlDeclaration* ToDeclaration() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+ virtual TiXmlDeclaration* ToDeclaration() { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+
+protected:
+ void CopyTo( TiXmlDeclaration* target ) const;
+ // used to be public
+ #ifdef TIXML_USE_STL
+ virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag );
+ #endif
+ virtual void StreamOut ( TIXML_OSTREAM * out) const;
+
+private:
+
+ TIXML_STRING version;
+ TIXML_STRING encoding;
+ TIXML_STRING standalone;
+};
+
+
+/** Any tag that tinyXml doesn't recognize is saved as an
+ unknown. It is a tag of text, but should not be modified.
+ It will be written back to the XML, unchanged, when the file
+ is saved.
+
+ DTD tags get thrown into TiXmlUnknowns.
+*/
+class TiXmlUnknown : public TiXmlNode
+{
+public:
+ TiXmlUnknown() : TiXmlNode( TiXmlNode::UNKNOWN ) {}
+ virtual ~TiXmlUnknown() {}
+
+ TiXmlUnknown( const TiXmlUnknown& copy ) : TiXmlNode( TiXmlNode::UNKNOWN ) { copy.CopyTo( this ); }
+ void operator=( const TiXmlUnknown& copy ) { copy.CopyTo( this ); }
+
+ /// Creates a copy of this Unknown and returns it.
+ virtual TiXmlNode* Clone() const;
+ /// Print this Unknown to a FILE stream.
+ virtual void Print( FILE* cfile, int depth ) const;
+
+ virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
+
+ virtual const TiXmlUnknown* ToUnknown() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+ virtual TiXmlUnknown* ToUnknown() { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+
+protected:
+ void CopyTo( TiXmlUnknown* target ) const;
+
+ #ifdef TIXML_USE_STL
+ virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag );
+ #endif
+ virtual void StreamOut ( TIXML_OSTREAM * out ) const;
+
+private:
+
+};
+
+
+/** Always the top level node. A document binds together all the
+ XML pieces. It can be saved, loaded, and printed to the screen.
+ The 'value' of a document node is the xml file name.
+*/
+class TiXmlDocument : public TiXmlNode
+{
+public:
+ /// Create an empty document, that has no name.
+ TiXmlDocument();
+ /// Create a document with a name. The name of the document is also the filename of the xml.
+ TiXmlDocument( const char * documentName );
+
+ #ifdef TIXML_USE_STL
+ /// Constructor.
+ TiXmlDocument( const std::string& documentName );
+ #endif
+
+ TiXmlDocument( const TiXmlDocument& copy );
+ void operator=( const TiXmlDocument& copy );
+
+ virtual ~TiXmlDocument() {}
+
+ /** Load a file using the current document value.
+ Returns true if successful. Will delete any existing
+ document data before loading.
+ */
+ bool LoadFile( TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING );
+ /// Save a file using the current document value. Returns true if successful.
+ bool SaveFile() const;
+ /// Load a file using the given filename. Returns true if successful.
+ bool LoadFile( const char * filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING );
+ /// Save a file using the given filename. Returns true if successful.
+ bool SaveFile( const char * filename ) const;
+ /** Load a file using the given FILE*. Returns true if successful. Note that this method
+ doesn't stream - the entire object pointed at by the FILE*
+ will be interpreted as an XML file. TinyXML doesn't stream in XML from the current
+ file location. Streaming may be added in the future.
+ */
+ bool LoadFile( FILE*, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING );
+ /// Save a file using the given FILE*. Returns true if successful.
+ bool SaveFile( FILE* ) const;
+
+ #ifdef TIXML_USE_STL
+ bool LoadFile( const std::string& filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ) ///< STL std::string version.
+ {
+ StringToBuffer f( filename );
+ return ( f.buffer && LoadFile( f.buffer, encoding ));
+ }
+ bool SaveFile( const std::string& filename ) const ///< STL std::string version.
+ {
+ StringToBuffer f( filename );
+ return ( f.buffer && SaveFile( f.buffer ));
+ }
+ #endif
+
+ /** Parse the given null terminated block of xml data. Passing in an encoding to this
+ method (either TIXML_ENCODING_LEGACY or TIXML_ENCODING_UTF8 will force TinyXml
+ to use that encoding, regardless of what TinyXml might otherwise try to detect.
+ */
+ virtual const char* Parse( const char* p, TiXmlParsingData* data = 0, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING );
+
+ /** Get the root element -- the only top level element -- of the document.
+ In well formed XML, there should only be one. TinyXml is tolerant of
+ multiple elements at the document level.
+ */
+ const TiXmlElement* RootElement() const { return FirstChildElement(); }
+ TiXmlElement* RootElement() { return FirstChildElement(); }
+
+ /** If an error occurs, Error will be set to true. Also,
+ - The ErrorId() will contain the integer identifier of the error (not generally useful)
+ - The ErrorDesc() method will return the name of the error. (very useful)
+ - The ErrorRow() and ErrorCol() will return the location of the error (if known)
+ */
+ bool Error() const { return error; }
+
+ /// Contains a textual (english) description of the error if one occurs.
+ const char * ErrorDesc() const { return errorDesc.c_str (); }
+
+ /** Generally, you probably want the error string ( ErrorDesc() ). But if you
+ prefer the ErrorId, this function will fetch it.
+ */
+ int ErrorId() const { return errorId; }
+
+ /** Returns the location (if known) of the error. The first column is column 1,
+ and the first row is row 1. A value of 0 means the row and column wasn't applicable
+ (memory errors, for example, have no row/column) or the parser lost the error. (An
+ error in the error reporting, in that case.)
+
+ @sa SetTabSize, Row, Column
+ */
+ int ErrorRow() { return errorLocation.row+1; }
+ int ErrorCol() { return errorLocation.col+1; } ///< The column where the error occured. See ErrorRow()
+
+ /** SetTabSize() allows the error reporting functions (ErrorRow() and ErrorCol())
+ to report the correct values for row and column. It does not change the output
+ or input in any way.
+
+ By calling this method, with a tab size
+ greater than 0, the row and column of each node and attribute is stored
+ when the file is loaded. Very useful for tracking the DOM back in to
+ the source file.
+
+ The tab size is required for calculating the location of nodes. If not
+ set, the default of 4 is used. The tabsize is set per document. Setting
+ the tabsize to 0 disables row/column tracking.
+
+ Note that row and column tracking is not supported when using operator>>.
+
+ The tab size needs to be enabled before the parse or load. Correct usage:
+ @verbatim
+ TiXmlDocument doc;
+ doc.SetTabSize( 8 );
+ doc.Load( "myfile.xml" );
+ @endverbatim
+
+ @sa Row, Column
+ */
+ void SetTabSize( int _tabsize ) { tabsize = _tabsize; }
+
+ int TabSize() const { return tabsize; }
+
+ /** If you have handled the error, it can be reset with this call. The error
+ state is automatically cleared if you Parse a new XML block.
+ */
+ void ClearError() { error = false;
+ errorId = 0;
+ errorDesc = "";
+ errorLocation.row = errorLocation.col = 0;
+ //errorLocation.last = 0;
+ }
+
+ /** Dump the document to standard out. */
+ void Print() const { Print( stdout, 0 ); }
+
+ /// Print this Document to a FILE stream.
+ virtual void Print( FILE* cfile, int depth = 0 ) const;
+ // [internal use]
+ void SetError( int err, const char* errorLocation, TiXmlParsingData* prevData, TiXmlEncoding encoding );
+
+ virtual const TiXmlDocument* ToDocument() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+ virtual TiXmlDocument* ToDocument() { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+
+protected :
+ virtual void StreamOut ( TIXML_OSTREAM * out) const;
+ // [internal use]
+ virtual TiXmlNode* Clone() const;
+ #ifdef TIXML_USE_STL
+ virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag );
+ #endif
+
+private:
+ void CopyTo( TiXmlDocument* target ) const;
+
+ bool error;
+ int errorId;
+ TIXML_STRING errorDesc;
+ int tabsize;
+ TiXmlCursor errorLocation;
+ bool useMicrosoftBOM; // the UTF-8 BOM were found when read. Note this, and try to write.
+};
+
+
+/**
+ A TiXmlHandle is a class that wraps a node pointer with null checks; this is
+ an incredibly useful thing. Note that TiXmlHandle is not part of the TinyXml
+ DOM structure. It is a separate utility class.
+
+ Take an example:
+ @verbatim
+ <Document>
+ <Element attributeA = "valueA">
+ <Child attributeB = "value1" />
+ <Child attributeB = "value2" />
+ </Element>
+ <Document>
+ @endverbatim
+
+ Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very
+ easy to write a *lot* of code that looks like:
+
+ @verbatim
+ TiXmlElement* root = document.FirstChildElement( "Document" );
+ if ( root )
+ {
+ TiXmlElement* element = root->FirstChildElement( "Element" );
+ if ( element )
+ {
+ TiXmlElement* child = element->FirstChildElement( "Child" );
+ if ( child )
+ {
+ TiXmlElement* child2 = child->NextSiblingElement( "Child" );
+ if ( child2 )
+ {
+ // Finally do something useful.
+ @endverbatim
+
+ And that doesn't even cover "else" cases. TiXmlHandle addresses the verbosity
+ of such code. A TiXmlHandle checks for null pointers so it is perfectly safe
+ and correct to use:
+
+ @verbatim
+ TiXmlHandle docHandle( &document );
+ TiXmlElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", 1 ).Element();
+ if ( child2 )
+ {
+ // do something useful
+ @endverbatim
+
+ Which is MUCH more concise and useful.
+
+ It is also safe to copy handles - internally they are nothing more than node pointers.
+ @verbatim
+ TiXmlHandle handleCopy = handle;
+ @endverbatim
+
+ What they should not be used for is iteration:
+
+ @verbatim
+ int i=0;
+ while ( true )
+ {
+ TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", i ).Element();
+ if ( !child )
+ break;
+ // do something
+ ++i;
+ }
+ @endverbatim
+
+ It seems reasonable, but it is in fact two embedded while loops. The Child method is
+ a linear walk to find the element, so this code would iterate much more than it needs
+ to. Instead, prefer:
+
+ @verbatim
+ TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild( "Child" ).Element();
+
+ for( child; child; child=child->NextSiblingElement() )
+ {
+ // do something
+ }
+ @endverbatim
+*/
+class TiXmlHandle
+{
+public:
+ /// Create a handle from any node (at any depth of the tree.) This can be a null pointer.
+ TiXmlHandle( TiXmlNode* _node ) { this->node = _node; }
+ /// Copy constructor
+ TiXmlHandle( const TiXmlHandle& ref ) { this->node = ref.node; }
+ TiXmlHandle operator=( const TiXmlHandle& ref ) { this->node = ref.node; return *this; }
+
+ /// Return a handle to the first child node.
+ TiXmlHandle FirstChild() const;
+ /// Return a handle to the first child node with the given name.
+ TiXmlHandle FirstChild( const char * value ) const;
+ /// Return a handle to the first child element.
+ TiXmlHandle FirstChildElement() const;
+ /// Return a handle to the first child element with the given name.
+ TiXmlHandle FirstChildElement( const char * value ) const;
+
+ /** Return a handle to the "index" child with the given name.
+ The first child is 0, the second 1, etc.
+ */
+ TiXmlHandle Child( const char* value, int index ) const;
+ /** Return a handle to the "index" child.
+ The first child is 0, the second 1, etc.
+ */
+ TiXmlHandle Child( int index ) const;
+ /** Return a handle to the "index" child element with the given name.
+ The first child element is 0, the second 1, etc. Note that only TiXmlElements
+ are indexed: other types are not counted.
+ */
+ TiXmlHandle ChildElement( const char* value, int index ) const;
+ /** Return a handle to the "index" child element.
+ The first child element is 0, the second 1, etc. Note that only TiXmlElements
+ are indexed: other types are not counted.
+ */
+ TiXmlHandle ChildElement( int index ) const;
+
+ #ifdef TIXML_USE_STL
+ TiXmlHandle FirstChild( const std::string& _value ) const { return FirstChild( _value.c_str() ); }
+ TiXmlHandle FirstChildElement( const std::string& _value ) const { return FirstChildElement( _value.c_str() ); }
+
+ TiXmlHandle Child( const std::string& _value, int index ) const { return Child( _value.c_str(), index ); }
+ TiXmlHandle ChildElement( const std::string& _value, int index ) const { return ChildElement( _value.c_str(), index ); }
+ #endif
+
+ /// Return the handle as a TiXmlNode. This may return null.
+ TiXmlNode* Node() const { return node; }
+ /// Return the handle as a TiXmlElement. This may return null.
+ TiXmlElement* Element() const { return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); }
+ /// Return the handle as a TiXmlText. This may return null.
+ TiXmlText* Text() const { return ( ( node && node->ToText() ) ? node->ToText() : 0 ); }
+ /// Return the handle as a TiXmlUnknown. This may return null;
+ TiXmlUnknown* Unknown() const { return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); }
+
+private:
+ TiXmlNode* node;
+};
+
+#ifdef _MSC_VER
+#pragma warning( pop )
+#endif
+
+#endif
+
diff --git a/util/tinyxmlerror.cpp b/util/tinyxmlerror.cpp
new file mode 100644
index 0000000..5788438
--- /dev/null
+++ b/util/tinyxmlerror.cpp
@@ -0,0 +1,52 @@
+/*
+www.sourceforge.net/projects/tinyxml
+Original code (2.0 and earlier )copyright (c) 2000-2002 Lee Thomason (www.grinninglizard.com)
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any
+damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any
+purpose, including commercial applications, and to alter it and
+redistribute it freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must
+not claim that you wrote the original software. If you use this
+software in a product, an acknowledgment in the product documentation
+would be appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and
+must not be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source
+distribution.
+*/
+
+#include "tinyxml.h"
+
+// The goal of the seperate error file is to make the first
+// step towards localization. tinyxml (currently) only supports
+// english error messages, but the could now be translated.
+//
+// It also cleans up the code a bit.
+//
+
+const char* TiXmlBase::errorString[ TIXML_ERROR_STRING_COUNT ] =
+{
+ "No error",
+ "Error",
+ "Failed to open file",
+ "Memory allocation failed.",
+ "Error parsing Element.",
+ "Failed to read Element name",
+ "Error reading Element value.",
+ "Error reading Attributes.",
+ "Error: empty tag.",
+ "Error reading end tag.",
+ "Error parsing Unknown.",
+ "Error parsing Comment.",
+ "Error parsing Declaration.",
+ "Error document empty.",
+ "Error null (0) or unexpected EOF found in input stream.",
+ "Error parsing CDATA.",
+};
diff --git a/util/tinyxmlparser.cpp b/util/tinyxmlparser.cpp
new file mode 100644
index 0000000..9a77ebc
--- /dev/null
+++ b/util/tinyxmlparser.cpp
@@ -0,0 +1,1580 @@
+/*
+www.sourceforge.net/projects/tinyxml
+Original code (2.0 and earlier )copyright (c) 2000-2002 Lee Thomason (www.grinninglizard.com)
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any
+damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any
+purpose, including commercial applications, and to alter it and
+redistribute it freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must
+not claim that you wrote the original software. If you use this
+software in a product, an acknowledgment in the product documentation
+would be appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and
+must not be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source
+distribution.
+*/
+
+#include "tinyxml.h"
+#include <ctype.h>
+#include <stddef.h>
+
+//#define DEBUG_PARSER
+#if defined( DEBUG_PARSER )
+# if defined( DEBUG ) && defined( _MSC_VER )
+# include <windows.h>
+# define TIXML_LOG OutputDebugString
+# else
+# define TIXML_LOG printf
+# endif
+#endif
+
+// Note tha "PutString" hardcodes the same list. This
+// is less flexible than it appears. Changing the entries
+// or order will break putstring.
+TiXmlBase::Entity TiXmlBase::entity[ NUM_ENTITY ] =
+{
+ { "&amp;", 5, '&' },
+ { "&lt;", 4, '<' },
+ { "&gt;", 4, '>' },
+ { "&quot;", 6, '\"' },
+ { "&apos;", 6, '\'' }
+};
+
+// Bunch of unicode info at:
+// http://www.unicode.org/faq/utf_bom.html
+// Including the basic of this table, which determines the #bytes in the
+// sequence from the lead byte. 1 placed for invalid sequences --
+// although the result will be junk, pass it through as much as possible.
+// Beware of the non-characters in UTF-8:
+// ef bb bf (Microsoft "lead bytes")
+// ef bf be
+// ef bf bf
+
+const unsigned char TIXML_UTF_LEAD_0 = 0xefU;
+const unsigned char TIXML_UTF_LEAD_1 = 0xbbU;
+const unsigned char TIXML_UTF_LEAD_2 = 0xbfU;
+
+const int TiXmlBase::utf8ByteTable[256] =
+{
+ // 0 1 2 3 4 5 6 7 8 9 a b c d e f
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x00
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x10
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x20
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x30
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x40
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x50
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x60
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x70 End of ASCII range
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x80 0x80 to 0xc1 invalid
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x90
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xa0
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xb0
+ 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xc0 0xc2 to 0xdf 2 byte
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xd0
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 0xe0 0xe0 to 0xef 3 byte
+ 4, 4, 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // 0xf0 0xf0 to 0xf4 4 byte, 0xf5 and higher invalid
+};
+
+
+void TiXmlBase::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length )
+{
+ const unsigned long BYTE_MASK = 0xBF;
+ const unsigned long BYTE_MARK = 0x80;
+ const unsigned long FIRST_BYTE_MARK[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
+
+ if (input < 0x80)
+ *length = 1;
+ else if ( input < 0x800 )
+ *length = 2;
+ else if ( input < 0x10000 )
+ *length = 3;
+ else if ( input < 0x200000 )
+ *length = 4;
+ else
+ { *length = 0; return; } // This code won't covert this correctly anyway.
+
+ output += *length;
+
+ // Scary scary fall throughs.
+ switch (*length)
+ {
+ case 4:
+ --output;
+ *output = (char)((input | BYTE_MARK) & BYTE_MASK);
+ input >>= 6;
+ case 3:
+ --output;
+ *output = (char)((input | BYTE_MARK) & BYTE_MASK);
+ input >>= 6;
+ case 2:
+ --output;
+ *output = (char)((input | BYTE_MARK) & BYTE_MASK);
+ input >>= 6;
+ case 1:
+ --output;
+ *output = (char)(input | FIRST_BYTE_MARK[*length]);
+ }
+}
+
+
+/*static*/ int TiXmlBase::IsAlpha( unsigned char anyByte, TiXmlEncoding /*encoding*/ )
+{
+ // This will only work for low-ascii, everything else is assumed to be a valid
+ // letter. I'm not sure this is the best approach, but it is quite tricky trying
+ // to figure out alhabetical vs. not across encoding. So take a very
+ // conservative approach.
+
+// if ( encoding == TIXML_ENCODING_UTF8 )
+// {
+ if ( anyByte < 127 )
+ return isalpha( anyByte );
+ else
+ return 1; // What else to do? The unicode set is huge...get the english ones right.
+// }
+// else
+// {
+// return isalpha( anyByte );
+// }
+}
+
+
+/*static*/ int TiXmlBase::IsAlphaNum( unsigned char anyByte, TiXmlEncoding /*encoding*/ )
+{
+ // This will only work for low-ascii, everything else is assumed to be a valid
+ // letter. I'm not sure this is the best approach, but it is quite tricky trying
+ // to figure out alhabetical vs. not across encoding. So take a very
+ // conservative approach.
+
+// if ( encoding == TIXML_ENCODING_UTF8 )
+// {
+ if ( anyByte < 127 )
+ return isalnum( anyByte );
+ else
+ return 1; // What else to do? The unicode set is huge...get the english ones right.
+// }
+// else
+// {
+// return isalnum( anyByte );
+// }
+}
+
+
+class TiXmlParsingData
+{
+ friend class TiXmlDocument;
+ public:
+ void Stamp( const char* now, TiXmlEncoding encoding );
+
+ const TiXmlCursor& Cursor() { return cursor; }
+
+ private:
+ // Only used by the document!
+ TiXmlParsingData( const char* start, int _tabsize, int row, int col )
+ {
+ assert( start );
+ stamp = start;
+ tabsize = _tabsize;
+ cursor.row = row;
+ cursor.col = col;
+ }
+
+ TiXmlCursor cursor;
+ const char* stamp;
+ int tabsize;
+};
+
+
+void TiXmlParsingData::Stamp( const char* now, TiXmlEncoding encoding )
+{
+ assert( now );
+
+ // Do nothing if the tabsize is 0.
+ if ( tabsize < 1 )
+ {
+ return;
+ }
+
+ // Get the current row, column.
+ int row = cursor.row;
+ int col = cursor.col;
+ const char* p = stamp;
+ assert( p );
+
+ while ( p < now )
+ {
+ // Treat p as unsigned, so we have a happy compiler.
+ const unsigned char* pU = (const unsigned char*)p;
+
+ // Code contributed by Fletcher Dunn: (modified by lee)
+ switch (*pU) {
+ case 0:
+ // We *should* never get here, but in case we do, don't
+ // advance past the terminating null character, ever
+ return;
+
+ case '\r':
+ // bump down to the next line
+ ++row;
+ col = 0;
+ // Eat the character
+ ++p;
+
+ // Check for \r\n sequence, and treat this as a single character
+ if (*p == '\n') {
+ ++p;
+ }
+ break;
+
+ case '\n':
+ // bump down to the next line
+ ++row;
+ col = 0;
+
+ // Eat the character
+ ++p;
+
+ // Check for \n\r sequence, and treat this as a single
+ // character. (Yes, this bizarre thing does occur still
+ // on some arcane platforms...)
+ if (*p == '\r') {
+ ++p;
+ }
+ break;
+
+ case '\t':
+ // Eat the character
+ ++p;
+
+ // Skip to next tab stop
+ col = (col / tabsize + 1) * tabsize;
+ break;
+
+ case TIXML_UTF_LEAD_0:
+ if ( encoding == TIXML_ENCODING_UTF8 )
+ {
+ if ( *(p+1) && *(p+2) )
+ {
+ // In these cases, don't advance the column. These are
+ // 0-width spaces.
+ if ( *(pU+1)==TIXML_UTF_LEAD_1 && *(pU+2)==TIXML_UTF_LEAD_2 )
+ p += 3;
+ else if ( *(pU+1)==0xbfU && *(pU+2)==0xbeU )
+ p += 3;
+ else if ( *(pU+1)==0xbfU && *(pU+2)==0xbfU )
+ p += 3;
+ else
+ { p +=3; ++col; } // A normal character.
+ }
+ }
+ else
+ {
+ ++p;
+ ++col;
+ }
+ break;
+
+ default:
+ if ( encoding == TIXML_ENCODING_UTF8 )
+ {
+ // Eat the 1 to 4 byte utf8 character.
+ int step = TiXmlBase::utf8ByteTable[*((unsigned char*)p)];
+ if ( step == 0 )
+ step = 1; // Error case from bad encoding, but handle gracefully.
+ p += step;
+
+ // Just advance one column, of course.
+ ++col;
+ }
+ else
+ {
+ ++p;
+ ++col;
+ }
+ break;
+ }
+ }
+ cursor.row = row;
+ cursor.col = col;
+ assert( cursor.row >= -1 );
+ assert( cursor.col >= -1 );
+ stamp = p;
+ assert( stamp );
+}
+
+
+const char* TiXmlBase::SkipWhiteSpace( const char* p, TiXmlEncoding encoding )
+{
+ if ( !p || !*p )
+ {
+ return 0;
+ }
+ if ( encoding == TIXML_ENCODING_UTF8 )
+ {
+ while ( *p )
+ {
+ const unsigned char* pU = (const unsigned char*)p;
+
+ // Skip the stupid Microsoft UTF-8 Byte order marks
+ if ( *(pU+0)==TIXML_UTF_LEAD_0
+ && *(pU+1)==TIXML_UTF_LEAD_1
+ && *(pU+2)==TIXML_UTF_LEAD_2 )
+ {
+ p += 3;
+ continue;
+ }
+ else if(*(pU+0)==TIXML_UTF_LEAD_0
+ && *(pU+1)==0xbfU
+ && *(pU+2)==0xbeU )
+ {
+ p += 3;
+ continue;
+ }
+ else if(*(pU+0)==TIXML_UTF_LEAD_0
+ && *(pU+1)==0xbfU
+ && *(pU+2)==0xbfU )
+ {
+ p += 3;
+ continue;
+ }
+
+ if ( IsWhiteSpace( *p ) || *p == '\n' || *p =='\r' ) // Still using old rules for white space.
+ ++p;
+ else
+ break;
+ }
+ }
+ else
+ {
+ while ( *p && IsWhiteSpace( *p ) || *p == '\n' || *p =='\r' )
+ ++p;
+ }
+
+ return p;
+}
+
+#ifdef TIXML_USE_STL
+/*static*/ bool TiXmlBase::StreamWhiteSpace( TIXML_ISTREAM * in, TIXML_STRING * tag )
+{
+ for( ;; )
+ {
+ if ( !in->good() ) return false;
+
+ int c = in->peek();
+ // At this scope, we can't get to a document. So fail silently.
+ if ( !IsWhiteSpace( c ) || c <= 0 )
+ return true;
+
+ *tag += (char) in->get();
+ }
+}
+
+/*static*/ bool TiXmlBase::StreamTo( TIXML_ISTREAM * in, int character, TIXML_STRING * tag )
+{
+ //assert( character > 0 && character < 128 ); // else it won't work in utf-8
+ while ( in->good() )
+ {
+ int c = in->peek();
+ if ( c == character )
+ return true;
+ if ( c <= 0 ) // Silent failure: can't get document at this scope
+ return false;
+
+ in->get();
+ *tag += (char) c;
+ }
+ return false;
+}
+#endif
+
+const char* TiXmlBase::ReadName( const char* p, TIXML_STRING * name, TiXmlEncoding encoding )
+{
+ *name = "";
+ assert( p );
+
+ // Names start with letters or underscores.
+ // Of course, in unicode, tinyxml has no idea what a letter *is*. The
+ // algorithm is generous.
+ //
+ // After that, they can be letters, underscores, numbers,
+ // hyphens, or colons. (Colons are valid ony for namespaces,
+ // but tinyxml can't tell namespaces from names.)
+ if ( p && *p
+ && ( IsAlpha( (unsigned char) *p, encoding ) || *p == '_' ) )
+ {
+ while( p && *p
+ && ( IsAlphaNum( (unsigned char ) *p, encoding )
+ || *p == '_'
+ || *p == '-'
+ || *p == '.'
+ || *p == ':' ) )
+ {
+ (*name) += *p;
+ ++p;
+ }
+ return p;
+ }
+ return 0;
+}
+
+const char* TiXmlBase::GetEntity( const char* p, char* value, int* length, TiXmlEncoding encoding )
+{
+ // Presume an entity, and pull it out.
+ TIXML_STRING ent;
+ int i;
+ *length = 0;
+
+ if ( *(p+1) && *(p+1) == '#' && *(p+2) )
+ {
+ unsigned long ucs = 0;
+ ptrdiff_t delta = 0;
+ unsigned mult = 1;
+
+ if ( *(p+2) == 'x' )
+ {
+ // Hexadecimal.
+ if ( !*(p+3) ) return 0;
+
+ const char* q = p+3;
+ q = strchr( q, ';' );
+
+ if ( !q || !*q ) return 0;
+
+ delta = q-p;
+ --q;
+
+ while ( *q != 'x' )
+ {
+ if ( *q >= '0' && *q <= '9' )
+ ucs += mult * (*q - '0');
+ else if ( *q >= 'a' && *q <= 'f' )
+ ucs += mult * (*q - 'a' + 10);
+ else if ( *q >= 'A' && *q <= 'F' )
+ ucs += mult * (*q - 'A' + 10 );
+ else
+ return 0;
+ mult *= 16;
+ --q;
+ }
+ }
+ else
+ {
+ // Decimal.
+ if ( !*(p+2) ) return 0;
+
+ const char* q = p+2;
+ q = strchr( q, ';' );
+
+ if ( !q || !*q ) return 0;
+
+ delta = q-p;
+ --q;
+
+ while ( *q != '#' )
+ {
+ if ( *q >= '0' && *q <= '9' )
+ ucs += mult * (*q - '0');
+ else
+ return 0;
+ mult *= 10;
+ --q;
+ }
+ }
+ if ( encoding == TIXML_ENCODING_UTF8 )
+ {
+ // convert the UCS to UTF-8
+ ConvertUTF32ToUTF8( ucs, value, length );
+ }
+ else
+ {
+ *value = (char)ucs;
+ *length = 1;
+ }
+ return p + delta + 1;
+ }
+
+ // Now try to match it.
+ for( i=0; i<NUM_ENTITY; ++i )
+ {
+ if ( strncmp( entity[i].str, p, entity[i].strLength ) == 0 )
+ {
+ assert( strlen( entity[i].str ) == entity[i].strLength );
+ *value = entity[i].chr;
+ *length = 1;
+ return ( p + entity[i].strLength );
+ }
+ }
+
+ // So it wasn't an entity, its unrecognized, or something like that.
+ *value = *p; // Don't put back the last one, since we return it!
+ return p+1;
+}
+
+
+bool TiXmlBase::StringEqual( const char* p,
+ const char* tag,
+ bool ignoreCase,
+ TiXmlEncoding encoding )
+{
+ assert( p );
+ assert( tag );
+ if ( !p || !*p )
+ {
+ assert( 0 );
+ return false;
+ }
+
+ const char* q = p;
+
+ if ( ignoreCase )
+ {
+ while ( *q && *tag && ToLower( *q, encoding ) == ToLower( *tag, encoding ) )
+ {
+ ++q;
+ ++tag;
+ }
+
+ if ( *tag == 0 )
+ return true;
+ }
+ else
+ {
+ while ( *q && *tag && *q == *tag )
+ {
+ ++q;
+ ++tag;
+ }
+
+ if ( *tag == 0 ) // Have we found the end of the tag, and everything equal?
+ return true;
+ }
+ return false;
+}
+
+const char* TiXmlBase::ReadText( const char* p,
+ TIXML_STRING * text,
+ bool trimWhiteSpace,
+ const char* endTag,
+ bool caseInsensitive,
+ TiXmlEncoding encoding )
+{
+ *text = "";
+ if ( !trimWhiteSpace // certain tags always keep whitespace
+ || !condenseWhiteSpace ) // if true, whitespace is always kept
+ {
+ // Keep all the white space.
+ while ( p && *p
+ && !StringEqual( p, endTag, caseInsensitive, encoding )
+ )
+ {
+ int len;
+ char cArr[4] = { 0, 0, 0, 0 };
+ p = GetChar( p, cArr, &len, encoding );
+ text->append( cArr, len );
+ }
+ }
+ else
+ {
+ bool whitespace = false;
+
+ // Remove leading white space:
+ p = SkipWhiteSpace( p, encoding );
+ while ( p && *p
+ && !StringEqual( p, endTag, caseInsensitive, encoding ) )
+ {
+ if ( *p == '\r' || *p == '\n' )
+ {
+ whitespace = true;
+ ++p;
+ }
+ else if ( IsWhiteSpace( *p ) )
+ {
+ whitespace = true;
+ ++p;
+ }
+ else
+ {
+ // If we've found whitespace, add it before the
+ // new character. Any whitespace just becomes a space.
+ if ( whitespace )
+ {
+ (*text) += ' ';
+ whitespace = false;
+ }
+ int len;
+ char cArr[4] = { 0, 0, 0, 0 };
+ p = GetChar( p, cArr, &len, encoding );
+ if ( len == 1 )
+ (*text) += cArr[0]; // more efficient
+ else
+ text->append( cArr, len );
+ }
+ }
+ }
+ return p + strlen( endTag );
+}
+
+#ifdef TIXML_USE_STL
+
+void TiXmlDocument::StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag )
+{
+ // The basic issue with a document is that we don't know what we're
+ // streaming. Read something presumed to be a tag (and hope), then
+ // identify it, and call the appropriate stream method on the tag.
+ //
+ // This "pre-streaming" will never read the closing ">" so the
+ // sub-tag can orient itself.
+
+ if ( !StreamTo( in, '<', tag ) )
+ {
+ SetError( TIXML_ERROR_PARSING_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return;
+ }
+
+ while ( in->good() )
+ {
+ int tagIndex = (int) tag->length();
+ while ( in->good() && in->peek() != '>' )
+ {
+ int c = in->get();
+ if ( c <= 0 )
+ {
+ SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
+ break;
+ }
+ (*tag) += (char) c;
+ }
+
+ if ( in->good() )
+ {
+ // We now have something we presume to be a node of
+ // some sort. Identify it, and call the node to
+ // continue streaming.
+ TiXmlNode* node = Identify( tag->c_str() + tagIndex, TIXML_DEFAULT_ENCODING );
+
+ if ( node )
+ {
+ node->StreamIn( in, tag );
+ bool isElement = node->ToElement() != 0;
+ delete node;
+ node = 0;
+
+ // If this is the root element, we're done. Parsing will be
+ // done by the >> operator.
+ if ( isElement )
+ {
+ return;
+ }
+ }
+ else
+ {
+ SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return;
+ }
+ }
+ }
+ // We should have returned sooner.
+ SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN );
+}
+
+#endif
+
+const char* TiXmlDocument::Parse( const char* p, TiXmlParsingData* prevData, TiXmlEncoding encoding )
+{
+ ClearError();
+
+ // Parse away, at the document level. Since a document
+ // contains nothing but other tags, most of what happens
+ // here is skipping white space.
+ if ( !p || !*p )
+ {
+ SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return 0;
+ }
+
+ // Note that, for a document, this needs to come
+ // before the while space skip, so that parsing
+ // starts from the pointer we are given.
+ location.Clear();
+ if ( prevData )
+ {
+ location.row = prevData->cursor.row;
+ location.col = prevData->cursor.col;
+ }
+ else
+ {
+ location.row = 0;
+ location.col = 0;
+ }
+ TiXmlParsingData data( p, TabSize(), location.row, location.col );
+ location = data.Cursor();
+
+ if ( encoding == TIXML_ENCODING_UNKNOWN )
+ {
+ // Check for the Microsoft UTF-8 lead bytes.
+ const unsigned char* pU = (const unsigned char*)p;
+ if ( *(pU+0) && *(pU+0) == TIXML_UTF_LEAD_0
+ && *(pU+1) && *(pU+1) == TIXML_UTF_LEAD_1
+ && *(pU+2) && *(pU+2) == TIXML_UTF_LEAD_2 )
+ {
+ encoding = TIXML_ENCODING_UTF8;
+ useMicrosoftBOM = true;
+ }
+ }
+
+ p = SkipWhiteSpace( p, encoding );
+ if ( !p )
+ {
+ SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return 0;
+ }
+
+ while ( p && *p )
+ {
+ TiXmlNode* node = Identify( p, encoding );
+ if ( node )
+ {
+ p = node->Parse( p, &data, encoding );
+ LinkEndChild( node );
+ }
+ else
+ {
+ break;
+ }
+
+ // Did we get encoding info?
+ if ( encoding == TIXML_ENCODING_UNKNOWN
+ && node->ToDeclaration() )
+ {
+ TiXmlDeclaration* dec = node->ToDeclaration();
+ const char* enc = dec->Encoding();
+ assert( enc );
+
+ if ( *enc == 0 )
+ encoding = TIXML_ENCODING_UTF8;
+ else if ( StringEqual( enc, "UTF-8", true, TIXML_ENCODING_UNKNOWN ) )
+ encoding = TIXML_ENCODING_UTF8;
+ else if ( StringEqual( enc, "UTF8", true, TIXML_ENCODING_UNKNOWN ) )
+ encoding = TIXML_ENCODING_UTF8; // incorrect, but be nice
+ else
+ encoding = TIXML_ENCODING_LEGACY;
+ }
+
+ p = SkipWhiteSpace( p, encoding );
+ }
+
+ // Was this empty?
+ if ( !firstChild ) {
+ SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, encoding );
+ return 0;
+ }
+
+ // All is well.
+ return p;
+}
+
+void TiXmlDocument::SetError( int err, const char* pError, TiXmlParsingData* data, TiXmlEncoding encoding )
+{
+ // The first error in a chain is more accurate - don't set again!
+ if ( error )
+ return;
+
+ assert( err > 0 && err < TIXML_ERROR_STRING_COUNT );
+ error = true;
+ errorId = err;
+ errorDesc = errorString[ errorId ];
+
+ errorLocation.Clear();
+ if ( pError && data )
+ {
+ data->Stamp( pError, encoding );
+ errorLocation = data->Cursor();
+ }
+}
+
+
+TiXmlNode* TiXmlNode::Identify( const char* p, TiXmlEncoding encoding )
+{
+ TiXmlNode* returnNode = 0;
+
+ p = SkipWhiteSpace( p, encoding );
+ if( !p || !*p || *p != '<' )
+ {
+ return 0;
+ }
+
+ TiXmlDocument* doc = GetDocument();
+ p = SkipWhiteSpace( p, encoding );
+
+ if ( !p || !*p )
+ {
+ return 0;
+ }
+
+ // What is this thing?
+ // - Elements start with a letter or underscore, but xml is reserved.
+ // - Comments: <!--
+ // - Decleration: <?xml
+ // - Everthing else is unknown to tinyxml.
+ //
+
+ const char* xmlHeader = { "<?xml" };
+ const char* commentHeader = { "<!--" };
+ const char* dtdHeader = { "<!" };
+ const char* cdataHeader = { "<![CDATA[" };
+
+ if ( StringEqual( p, xmlHeader, true, encoding ) )
+ {
+ #ifdef DEBUG_PARSER
+ TIXML_LOG( "XML parsing Declaration\n" );
+ #endif
+ returnNode = new TiXmlDeclaration();
+ }
+ else if ( StringEqual( p, commentHeader, false, encoding ) )
+ {
+ #ifdef DEBUG_PARSER
+ TIXML_LOG( "XML parsing Comment\n" );
+ #endif
+ returnNode = new TiXmlComment();
+ }
+ else if ( StringEqual( p, cdataHeader, false, encoding ) )
+ {
+ #ifdef DEBUG_PARSER
+ TIXML_LOG( "XML parsing CDATA\n" );
+ #endif
+ TiXmlText* text = new TiXmlText( "" );
+ text->SetCDATA( true );
+ returnNode = text;
+ }
+ else if ( StringEqual( p, dtdHeader, false, encoding ) )
+ {
+ #ifdef DEBUG_PARSER
+ TIXML_LOG( "XML parsing Unknown(1)\n" );
+ #endif
+ returnNode = new TiXmlUnknown();
+ }
+ else if ( IsAlpha( *(p+1), encoding )
+ || *(p+1) == '_' )
+ {
+ #ifdef DEBUG_PARSER
+ TIXML_LOG( "XML parsing Element\n" );
+ #endif
+ returnNode = new TiXmlElement( "" );
+ }
+ else
+ {
+ #ifdef DEBUG_PARSER
+ TIXML_LOG( "XML parsing Unknown(2)\n" );
+ #endif
+ returnNode = new TiXmlUnknown();
+ }
+
+ if ( returnNode )
+ {
+ // Set the parent, so it can report errors
+ returnNode->parent = this;
+ }
+ else
+ {
+ if ( doc )
+ doc->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN );
+ }
+ return returnNode;
+}
+
+#ifdef TIXML_USE_STL
+
+void TiXmlElement::StreamIn (TIXML_ISTREAM * in, TIXML_STRING * tag)
+{
+ // We're called with some amount of pre-parsing. That is, some of "this"
+ // element is in "tag". Go ahead and stream to the closing ">"
+ while( in->good() )
+ {
+ int c = in->get();
+ if ( c <= 0 )
+ {
+ TiXmlDocument* document = GetDocument();
+ if ( document )
+ document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return;
+ }
+ (*tag) += (char) c ;
+
+ if ( c == '>' )
+ break;
+ }
+
+ if ( tag->length() < 3 ) return;
+
+ // Okay...if we are a "/>" tag, then we're done. We've read a complete tag.
+ // If not, identify and stream.
+
+ if ( tag->at( tag->length() - 1 ) == '>'
+ && tag->at( tag->length() - 2 ) == '/' )
+ {
+ // All good!
+ return;
+ }
+ else if ( tag->at( tag->length() - 1 ) == '>' )
+ {
+ // There is more. Could be:
+ // text
+ // closing tag
+ // another node.
+ for ( ;; )
+ {
+ StreamWhiteSpace( in, tag );
+
+ // Do we have text?
+ if ( in->good() && in->peek() != '<' )
+ {
+ // Yep, text.
+ TiXmlText text( "" );
+ text.StreamIn( in, tag );
+
+ // What follows text is a closing tag or another node.
+ // Go around again and figure it out.
+ continue;
+ }
+
+ // We now have either a closing tag...or another node.
+ // We should be at a "<", regardless.
+ if ( !in->good() ) return;
+ assert( in->peek() == '<' );
+ int tagIndex = (int) tag->length();
+
+ bool closingTag = false;
+ bool firstCharFound = false;
+
+ for( ;; )
+ {
+ if ( !in->good() )
+ return;
+
+ int c = in->peek();
+ if ( c <= 0 )
+ {
+ TiXmlDocument* document = GetDocument();
+ if ( document )
+ document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return;
+ }
+
+ if ( c == '>' )
+ break;
+
+ *tag += (char) c;
+ in->get();
+
+ if ( !firstCharFound && c != '<' && !IsWhiteSpace( c ) )
+ {
+ firstCharFound = true;
+ if ( c == '/' )
+ closingTag = true;
+ }
+ }
+ // If it was a closing tag, then read in the closing '>' to clean up the input stream.
+ // If it was not, the streaming will be done by the tag.
+ if ( closingTag )
+ {
+ if ( !in->good() )
+ return;
+
+ int c = in->get();
+ if ( c <= 0 )
+ {
+ TiXmlDocument* document = GetDocument();
+ if ( document )
+ document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return;
+ }
+ assert( c == '>' );
+ *tag += (char) c;
+
+ // We are done, once we've found our closing tag.
+ return;
+ }
+ else
+ {
+ // If not a closing tag, id it, and stream.
+ const char* tagloc = tag->c_str() + tagIndex;
+ TiXmlNode* node = Identify( tagloc, TIXML_DEFAULT_ENCODING );
+ if ( !node )
+ return;
+ node->StreamIn( in, tag );
+ delete node;
+ node = 0;
+
+ // No return: go around from the beginning: text, closing tag, or node.
+ }
+ }
+ }
+}
+#endif
+
+const char* TiXmlElement::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
+{
+ p = SkipWhiteSpace( p, encoding );
+ TiXmlDocument* document = GetDocument();
+
+ if ( !p || !*p )
+ {
+ if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, 0, 0, encoding );
+ return 0;
+ }
+
+ if ( data )
+ {
+ data->Stamp( p, encoding );
+ location = data->Cursor();
+ }
+
+ if ( *p != '<' )
+ {
+ if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, p, data, encoding );
+ return 0;
+ }
+
+ p = SkipWhiteSpace( p+1, encoding );
+
+ // Read the name.
+ const char* pErr = p;
+
+ p = ReadName( p, &value, encoding );
+ if ( !p || !*p )
+ {
+ if ( document ) document->SetError( TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME, pErr, data, encoding );
+ return 0;
+ }
+
+ TIXML_STRING endTag ("</");
+ endTag += value;
+ endTag += ">";
+
+ // Check for and read attributes. Also look for an empty
+ // tag or an end tag.
+ while ( p && *p )
+ {
+ pErr = p;
+ p = SkipWhiteSpace( p, encoding );
+ if ( !p || !*p )
+ {
+ if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, pErr, data, encoding );
+ return 0;
+ }
+ if ( *p == '/' )
+ {
+ ++p;
+ // Empty tag.
+ if ( *p != '>' )
+ {
+ if ( document ) document->SetError( TIXML_ERROR_PARSING_EMPTY, p, data, encoding );
+ return 0;
+ }
+ return (p+1);
+ }
+ else if ( *p == '>' )
+ {
+ // Done with attributes (if there were any.)
+ // Read the value -- which can include other
+ // elements -- read the end tag, and return.
+ ++p;
+ p = ReadValue( p, data, encoding ); // Note this is an Element method, and will set the error if one happens.
+ if ( !p || !*p )
+ return 0;
+
+ // We should find the end tag now
+ if ( StringEqual( p, endTag.c_str(), false, encoding ) )
+ {
+ p += endTag.length();
+ return p;
+ }
+ else
+ {
+ if ( document ) document->SetError( TIXML_ERROR_READING_END_TAG, p, data, encoding );
+ return 0;
+ }
+ }
+ else
+ {
+ // Try to read an attribute:
+ TiXmlAttribute* attrib = new TiXmlAttribute();
+ if ( !attrib )
+ {
+ if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, pErr, data, encoding );
+ return 0;
+ }
+
+ attrib->SetDocument( document );
+ const char* pErr = p;
+ p = attrib->Parse( p, data, encoding );
+
+ if ( !p || !*p )
+ {
+ if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, pErr, data, encoding );
+ delete attrib;
+ return 0;
+ }
+
+ // Handle the strange case of double attributes:
+ TiXmlAttribute* node = attributeSet.Find( attrib->NameTStr() );
+ if ( node )
+ {
+ node->SetValue( attrib->Value() );
+ delete attrib;
+ return 0;
+ }
+
+ attributeSet.Add( attrib );
+ }
+ }
+ return p;
+}
+
+
+const char* TiXmlElement::ReadValue( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
+{
+ TiXmlDocument* document = GetDocument();
+
+ // Read in text and elements in any order.
+ const char* pWithWhiteSpace = p;
+ p = SkipWhiteSpace( p, encoding );
+
+ while ( p && *p )
+ {
+ if ( *p != '<' )
+ {
+ // Take what we have, make a text element.
+ TiXmlText* textNode = new TiXmlText( "" );
+
+ if ( !textNode )
+ {
+ if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, encoding );
+ return 0;
+ }
+
+ if ( TiXmlBase::IsWhiteSpaceCondensed() )
+ {
+ p = textNode->Parse( p, data, encoding );
+ }
+ else
+ {
+ // Special case: we want to keep the white space
+ // so that leading spaces aren't removed.
+ p = textNode->Parse( pWithWhiteSpace, data, encoding );
+ }
+
+ if ( !textNode->Blank() )
+ LinkEndChild( textNode );
+ else
+ delete textNode;
+ }
+ else
+ {
+ // We hit a '<'
+ // Have we hit a new element or an end tag? This could also be
+ // a TiXmlText in the "CDATA" style.
+ if ( StringEqual( p, "</", false, encoding ) )
+ {
+ return p;
+ }
+ else
+ {
+ TiXmlNode* node = Identify( p, encoding );
+ if ( node )
+ {
+ p = node->Parse( p, data, encoding );
+ LinkEndChild( node );
+ }
+ else
+ {
+ return 0;
+ }
+ }
+ }
+ pWithWhiteSpace = p;
+ p = SkipWhiteSpace( p, encoding );
+ }
+
+ if ( !p )
+ {
+ if ( document ) document->SetError( TIXML_ERROR_READING_ELEMENT_VALUE, 0, 0, encoding );
+ }
+ return p;
+}
+
+
+#ifdef TIXML_USE_STL
+void TiXmlUnknown::StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag )
+{
+ while ( in->good() )
+ {
+ int c = in->get();
+ if ( c <= 0 )
+ {
+ TiXmlDocument* document = GetDocument();
+ if ( document )
+ document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return;
+ }
+ (*tag) += (char) c;
+
+ if ( c == '>' )
+ {
+ // All is well.
+ return;
+ }
+ }
+}
+#endif
+
+
+const char* TiXmlUnknown::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
+{
+ TiXmlDocument* document = GetDocument();
+ p = SkipWhiteSpace( p, encoding );
+
+ if ( data )
+ {
+ data->Stamp( p, encoding );
+ location = data->Cursor();
+ }
+ if ( !p || !*p || *p != '<' )
+ {
+ if ( document ) document->SetError( TIXML_ERROR_PARSING_UNKNOWN, p, data, encoding );
+ return 0;
+ }
+ ++p;
+ value = "";
+
+ while ( p && *p && *p != '>' )
+ {
+ value += *p;
+ ++p;
+ }
+
+ if ( !p )
+ {
+ if ( document ) document->SetError( TIXML_ERROR_PARSING_UNKNOWN, 0, 0, encoding );
+ }
+ if ( *p == '>' )
+ return p+1;
+ return p;
+}
+
+#ifdef TIXML_USE_STL
+void TiXmlComment::StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag )
+{
+ while ( in->good() )
+ {
+ int c = in->get();
+ if ( c <= 0 )
+ {
+ TiXmlDocument* document = GetDocument();
+ if ( document )
+ document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return;
+ }
+
+ (*tag) += (char) c;
+
+ if ( c == '>'
+ && tag->at( tag->length() - 2 ) == '-'
+ && tag->at( tag->length() - 3 ) == '-' )
+ {
+ // All is well.
+ return;
+ }
+ }
+}
+#endif
+
+
+const char* TiXmlComment::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
+{
+ TiXmlDocument* document = GetDocument();
+ value = "";
+
+ p = SkipWhiteSpace( p, encoding );
+
+ if ( data )
+ {
+ data->Stamp( p, encoding );
+ location = data->Cursor();
+ }
+ const char* startTag = "<!--";
+ const char* endTag = "-->";
+
+ if ( !StringEqual( p, startTag, false, encoding ) )
+ {
+ document->SetError( TIXML_ERROR_PARSING_COMMENT, p, data, encoding );
+ return 0;
+ }
+ p += strlen( startTag );
+ p = ReadText( p, &value, false, endTag, false, encoding );
+ return p;
+}
+
+
+const char* TiXmlAttribute::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
+{
+ p = SkipWhiteSpace( p, encoding );
+ if ( !p || !*p ) return 0;
+
+ int tabsize = 4;
+ if ( document )
+ tabsize = document->TabSize();
+
+ if ( data )
+ {
+ data->Stamp( p, encoding );
+ location = data->Cursor();
+ }
+ // Read the name, the '=' and the value.
+ const char* pErr = p;
+ p = ReadName( p, &name, encoding );
+ if ( !p || !*p )
+ {
+ if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, pErr, data, encoding );
+ return 0;
+ }
+ p = SkipWhiteSpace( p, encoding );
+ if ( !p || !*p || *p != '=' )
+ {
+ if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding );
+ return 0;
+ }
+
+ ++p; // skip '='
+ p = SkipWhiteSpace( p, encoding );
+ if ( !p || !*p )
+ {
+ if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding );
+ return 0;
+ }
+
+ const char* end;
+
+ if ( *p == '\'' )
+ {
+ ++p;
+ end = "\'";
+ p = ReadText( p, &value, false, end, false, encoding );
+ }
+ else if ( *p == '"' )
+ {
+ ++p;
+ end = "\"";
+ p = ReadText( p, &value, false, end, false, encoding );
+ }
+ else
+ {
+ // All attribute values should be in single or double quotes.
+ // But this is such a common error that the parser will try
+ // its best, even without them.
+ value = "";
+ while ( p && *p // existence
+ && !IsWhiteSpace( *p ) && *p != '\n' && *p != '\r' // whitespace
+ && *p != '/' && *p != '>' ) // tag end
+ {
+ value += *p;
+ ++p;
+ }
+ }
+ return p;
+}
+
+#ifdef TIXML_USE_STL
+void TiXmlText::StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag )
+{
+ if ( cdata )
+ {
+ int c = in->get();
+ if ( c <= 0 )
+ {
+ TiXmlDocument* document = GetDocument();
+ if ( document )
+ document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return;
+ }
+
+ (*tag) += (char) c;
+
+ if ( c == '>'
+ && tag->at( tag->length() - 2 ) == ']'
+ && tag->at( tag->length() - 3 ) == ']' )
+ {
+ // All is well.
+ return;
+ }
+ }
+ else
+ {
+ while ( in->good() )
+ {
+ int c = in->peek();
+ if ( c == '<' )
+ return;
+ if ( c <= 0 )
+ {
+ TiXmlDocument* document = GetDocument();
+ if ( document )
+ document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return;
+ }
+
+ (*tag) += (char) c;
+ in->get();
+ }
+ }
+}
+#endif
+
+const char* TiXmlText::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
+{
+ value = "";
+ TiXmlDocument* document = GetDocument();
+
+ if ( data )
+ {
+ data->Stamp( p, encoding );
+ location = data->Cursor();
+ }
+
+ const char* const startTag = "<![CDATA[";
+ const char* const endTag = "]]>";
+
+ if ( cdata || StringEqual( p, startTag, false, encoding ) )
+ {
+ cdata = true;
+
+ if ( !StringEqual( p, startTag, false, encoding ) )
+ {
+ document->SetError( TIXML_ERROR_PARSING_CDATA, p, data, encoding );
+ return 0;
+ }
+ p += strlen( startTag );
+
+ // Keep all the white space, ignore the encoding, etc.
+ while ( p && *p
+ && !StringEqual( p, endTag, false, encoding )
+ )
+ {
+ value += *p;
+ ++p;
+ }
+
+ TIXML_STRING dummy;
+ p = ReadText( p, &dummy, false, endTag, false, encoding );
+ return p;
+ }
+ else
+ {
+ bool ignoreWhite = true;
+
+ const char* end = "<";
+ p = ReadText( p, &value, ignoreWhite, end, false, encoding );
+ if ( p )
+ return p-1; // don't truncate the '<'
+ return 0;
+ }
+}
+
+#ifdef TIXML_USE_STL
+void TiXmlDeclaration::StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag )
+{
+ while ( in->good() )
+ {
+ int c = in->get();
+ if ( c <= 0 )
+ {
+ TiXmlDocument* document = GetDocument();
+ if ( document )
+ document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return;
+ }
+ (*tag) += (char) c;
+
+ if ( c == '>' )
+ {
+ // All is well.
+ return;
+ }
+ }
+}
+#endif
+
+const char* TiXmlDeclaration::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding _encoding )
+{
+ p = SkipWhiteSpace( p, _encoding );
+ // Find the beginning, find the end, and look for
+ // the stuff in-between.
+ TiXmlDocument* document = GetDocument();
+ if ( !p || !*p || !StringEqual( p, "<?xml", true, _encoding ) )
+ {
+ if ( document ) document->SetError( TIXML_ERROR_PARSING_DECLARATION, 0, 0, _encoding );
+ return 0;
+ }
+ if ( data )
+ {
+ data->Stamp( p, _encoding );
+ location = data->Cursor();
+ }
+ p += 5;
+
+ version = "";
+ encoding = "";
+ standalone = "";
+
+ while ( p && *p )
+ {
+ if ( *p == '>' )
+ {
+ ++p;
+ return p;
+ }
+
+ p = SkipWhiteSpace( p, _encoding );
+ if ( StringEqual( p, "version", true, _encoding ) )
+ {
+ TiXmlAttribute attrib;
+ p = attrib.Parse( p, data, _encoding );
+ version = attrib.Value();
+ }
+ else if ( StringEqual( p, "encoding", true, _encoding ) )
+ {
+ TiXmlAttribute attrib;
+ p = attrib.Parse( p, data, _encoding );
+ encoding = attrib.Value();
+ }
+ else if ( StringEqual( p, "standalone", true, _encoding ) )
+ {
+ TiXmlAttribute attrib;
+ p = attrib.Parse( p, data, _encoding );
+ standalone = attrib.Value();
+ }
+ else
+ {
+ // Read over whatever it is.
+ while( p && *p && *p != '>' && !IsWhiteSpace( *p ) )
+ ++p;
+ }
+ }
+ return 0;
+}
+
+bool TiXmlText::Blank() const
+{
+ for ( unsigned i=0; i<value.length(); i++ )
+ if ( !IsWhiteSpace( value[i] ) )
+ return false;
+ return true;
+}
+