diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 05:48:59 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 05:48:59 +0000 |
commit | c484829272cd13a738e35412498e12f2c9a194ac (patch) | |
tree | a1f5ec09629ee895bd3963fa8820b45f2f4c574b /src/parser | |
parent | Initial commit. (diff) | |
download | liborcus-upstream.tar.xz liborcus-upstream.zip |
Adding upstream version 0.19.2.upstream/0.19.2upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/parser')
50 files changed, 12906 insertions, 0 deletions
diff --git a/src/parser/Makefile.am b/src/parser/Makefile.am new file mode 100644 index 0000000..c5c534c --- /dev/null +++ b/src/parser/Makefile.am @@ -0,0 +1,338 @@ + +AM_CPPFLAGS = \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/src/include \ + -DSRCDIR=\""$(top_srcdir)"\" \ + $(BOOST_CPPFLAGS) \ + -D__ORCUS_PSR_BUILDING_DLL + +if HAVE_FILESYSTEM +AM_CPPFLAGS += "-DHAVE_FILESYSTEM=1" +endif + +if HAVE_EXPERIMENTAL_FILESYSTEM +AM_CPPFLAGS += "-DHAVE_EXPERIMENTAL_FILESYSTEM=1" +endif + +lib_LTLIBRARIES = liborcus-parser-@ORCUS_API_VERSION@.la +liborcus_parser_@ORCUS_API_VERSION@_la_SOURCES = \ + win_stdint.h \ + base64.cpp \ + cell_buffer.cpp \ + css_parser_base.cpp \ + css_types.cpp \ + csv_parser_base.cpp \ + exception.cpp \ + json_global.cpp \ + json_parser_base.cpp \ + json_parser_thread.cpp \ + parser_base.cpp \ + parser_global.cpp \ + sax_parser_base.cpp \ + sax_token_parser.cpp \ + sax_token_parser_thread.cpp \ + stream.cpp \ + string_pool.cpp \ + tokens.cpp \ + types.cpp \ + utf8.hpp \ + utf8.cpp \ + xml_namespace.cpp \ + xml_writer.cpp \ + yaml_parser_base.cpp \ + zip_archive.cpp \ + zip_archive_stream.cpp + + +liborcus_parser_@ORCUS_API_VERSION@_la_LDFLAGS = \ + -no-undefined \ + $(BOOST_SYSTEM_LDFLAGS) + +liborcus_parser_@ORCUS_API_VERSION@_la_LIBADD = \ + $(BOOST_SYSTEM_LIBS) \ + $(ZLIB_LIBS) + +if !HAVE_FILESYSTEM +if HAVE_EXPERIMENTAL_FILESYSTEM +liborcus_parser_@ORCUS_API_VERSION@_la_LDFLAGS += -lstdc++fs +else +liborcus_parser_@ORCUS_API_VERSION@_la_LDFLAGS += $(BOOST_FILESYSTEM_LDFLAGS) +liborcus_parser_@ORCUS_API_VERSION@_la_LIBADD += $(BOOST_FILESYSTEM_LIBS) +endif +endif + +EXTRA_PROGRAMS = \ + css-parser-test \ + csv-parser-test \ + json-parser-test \ + parser-global-test \ + parser-test-base \ + parser-test-base64 \ + parser-test-json-validation \ + parser-test-numeric \ + parser-test-stream \ + parser-test-string-pool \ + parser-test-threaded-json-parser \ + parser-test-threaded-sax-token-parser \ + parser-test-xml-namespace \ + parser-test-xml-validation \ + parser-test-zip-archive \ + sax-ns-parser-test \ + sax-parser-test \ + sax-token-parser-test \ + types-test \ + utf8-test \ + yaml-parser-test \ + xml-writer-test + +# parser-test-string-pool + +parser_test_string_pool_SOURCES = \ + string_pool.cpp \ + string_pool_test.cpp + +parser_test_string_pool_LDADD = \ + liborcus-parser-@ORCUS_API_VERSION@.la \ + $(BOOST_SYSTEM_LIBS) + +parser_test_string_pool_CPPFLAGS = $(AM_CPPFLAGS) + +# parser-test-xml-namespace + +parser_test_xml_namespace_SOURCES = \ + xml_namespace.cpp \ + xml_namespace_test.cpp + +parser_test_xml_namespace_LDADD = \ + liborcus-parser-@ORCUS_API_VERSION@.la \ + ../test/liborcus-test.a \ + $(BOOST_SYSTEM_LIBS) + +parser_test_xml_namespace_CPPFLAGS = $(AM_CPPFLAGS) + +# parser-test-xml-validation + +parser_test_xml_validation_SOURCES = \ + parser_test_xml_validation.cpp + +parser_test_xml_validation_CPPFLAGS = $(AM_CPPFLAGS) +parser_test_xml_validation_LDFLAGS = \ + $(BOOST_SYSTEM_LDFLAGS) +parser_test_xml_validation_LDADD = \ + liborcus-parser-@ORCUS_API_VERSION@.la \ + ../test/liborcus-test.a \ + $(BOOST_SYSTEM_LIBS) + +if !HAVE_FILESYSTEM +if HAVE_EXPERIMENTAL_FILESYSTEM +parser_test_xml_validation_LDFLAGS += -lstdc++fs +else +parser_test_xml_validation_LDFLAGS += $(BOOST_FILESYSTEM_LDFLAGS) +parser_test_xml_validation_LDADD += $(BOOST_FILESYSTEM_LIBS) +endif +endif + +# parser-test-base64 + +parser_test_base64_SOURCES = \ + base64.cpp \ + base64_test.cpp + +parser_test_base64_LDADD = liborcus-parser-@ORCUS_API_VERSION@.la +parser_test_base64_CPPFLAGS = $(AM_CPPFLAGS) + +# css-parser-test + +css_parser_test_SOURCES = \ + css_parser_test.cpp + +css_parser_test_LDADD = liborcus-parser-@ORCUS_API_VERSION@.la +css_parser_test_CPPFLAGS = $(AM_CPPFLAGS) + +# csv-parser-test + +csv_parser_test_SOURCES = \ + csv_parser_test.cpp + +csv_parser_test_LDADD = liborcus-parser-@ORCUS_API_VERSION@.la +csv_parser_test_CPPFLAGS = $(AM_CPPFLAGS) + +# json-parser-test + +json_parser_test_SOURCES = \ + json_parser_test.cpp + +json_parser_test_LDADD = liborcus-parser-@ORCUS_API_VERSION@.la +json_parser_test_CPPFLAGS = $(AM_CPPFLAGS) + +# yaml-parser-test + +yaml_parser_test_SOURCES = \ + yaml_parser_test.cpp + +yaml_parser_test_LDADD = liborcus-parser-@ORCUS_API_VERSION@.la +yaml_parser_test_CPPFLAGS = $(AM_CPPFLAGS) + +# sax-parser-test + +sax_parser_test_SOURCES = \ + sax_parser_test.cpp + +sax_parser_test_LDADD = liborcus-parser-@ORCUS_API_VERSION@.la +sax_parser_test_CPPFLAGS = $(AM_CPPFLAGS) + +# sax-ns-parser-test + +sax_ns_parser_test_SOURCES = \ + sax_ns_parser_test.cpp + +sax_ns_parser_test_LDADD = liborcus-parser-@ORCUS_API_VERSION@.la +sax_ns_parser_test_CPPFLAGS = $(AM_CPPFLAGS) + +# sax-token-parser-test + +sax_token_parser_test_SOURCES = \ + sax_token_parser_test.cpp + +sax_token_parser_test_LDADD = liborcus-parser-@ORCUS_API_VERSION@.la +sax_token_parser_test_CPPFLAGS = $(AM_CPPFLAGS) + +# parser-test-threaded-sax-token-parser + +parser_test_threaded_sax_token_parser_SOURCES = \ + threaded_sax_token_parser_test.cpp + +parser_test_threaded_sax_token_parser_LDADD = liborcus-parser-@ORCUS_API_VERSION@.la +parser_test_threaded_sax_token_parser_CPPFLAGS = $(AM_CPPFLAGS) + +# parser-test-threaded-json-parser + +parser_test_threaded_json_parser_SOURCES = \ + threaded_json_parser_test.cpp + +parser_test_threaded_json_parser_LDADD = liborcus-parser-@ORCUS_API_VERSION@.la +parser_test_threaded_json_parser_LDFLAGS = -pthread +parser_test_threaded_json_parser_CPPFLAGS = $(AM_CPPFLAGS) + +# parser-test-stream + +parser_test_stream_SOURCES = \ + stream_test.cpp + +parser_test_stream_LDADD = \ + liborcus-parser-@ORCUS_API_VERSION@.la \ + ../test/liborcus-test.a +parser_test_stream_CPPFLAGS = $(AM_CPPFLAGS) + +# parser-test-zip-archive + +parser_test_zip_archive_SOURCES = \ + zip_archive_test.cpp + +parser_test_zip_archive_CPPFLAGS = $(AM_CPPFLAGS) +parser_test_zip_archive_LDADD = \ + liborcus-parser-@ORCUS_API_VERSION@.la \ + ../test/liborcus-test.a \ + $(BOOST_SYSTEM_LIBS) +parser_test_zip_archive_LDFLAGS = \ + $(BOOST_SYSTEM_LDFLAGS) + +if !HAVE_FILESYSTEM +if HAVE_EXPERIMENTAL_FILESYSTEM +parser_test_zip_archive_LDFLAGS += -lstdc++fs +else +parser_test_zip_archive_LDFLAGS += $(BOOST_FILESYSTEM_LDFLAGS) +parser_test_zip_archive_LDADD += $(BOOST_FILESYSTEM_LIBS) +endif +endif + + + +# parser-test-base + +parser_test_base_SOURCES = \ + parser_base_test.cpp + +parser_test_base_LDADD = liborcus-parser-@ORCUS_API_VERSION@.la +parser_test_base_CPPFLAGS = $(AM_CPPFLAGS) + +# parser-global-test + +parser_global_test_SOURCES = \ + parser_global_test.cpp + +parser_global_test_LDADD = \ + liborcus-parser-@ORCUS_API_VERSION@.la \ + ../test/liborcus-test.a +parser_global_test_CPPFLAGS = $(AM_CPPFLAGS) + +# parser-test-json-validation + +parser_test_json_validation_SOURCES = \ + parser_test_json_validation.cpp + +parser_test_json_validation_LDADD = liborcus-parser-@ORCUS_API_VERSION@.la +parser_test_json_validation_CPPFLAGS = $(AM_CPPFLAGS) + +# types-test + +types_test_SOURCES = types_test.cpp + +types_test_LDADD = \ + liborcus-parser-@ORCUS_API_VERSION@.la \ + ../test/liborcus-test.a +types_test_CPPFLAGS = $(AM_CPPFLAGS) + +# utf8-test + +utf8_test_SOURCES = \ + utf8.cpp \ + utf8_test.cpp + +utf8_test_LDADD = liborcus-parser-@ORCUS_API_VERSION@.la +utf8_test_CPPFLAGS = $(AM_CPPFLAGS) + +# xml-writer-test + +xml_writer_test_SOURCES = xml_writer_test.cpp + +xml_writer_test_LDADD = liborcus-parser-@ORCUS_API_VERSION@.la +xml_writer_test_CPPFLAGS = $(AM_CPPFLAGS) + +# parser-test-numeric + +parser_test_numeric_SOURCES = \ + parser_test_numeric.cpp + +parser_test_numeric = liborcus-parser-@ORCUS_API_VERSION@.la +parser_test_numeric_LDADD = liborcus-parser-@ORCUS_API_VERSION@.la +parser_test_numeric_CPPFLAGS = $(AM_CPPFLAGS) + +TESTS = \ + css-parser-test \ + csv-parser-test \ + json-parser-test \ + parser-global-test \ + parser-test-base \ + parser-test-base64 \ + parser-test-json-validation \ + parser-test-numeric \ + parser-test-stream \ + parser-test-string-pool \ + parser-test-threaded-json-parser \ + parser-test-threaded-sax-token-parser \ + parser-test-xml-namespace \ + parser-test-xml-validation \ + parser-test-zip-archive \ + sax-ns-parser-test \ + sax-parser-test \ + sax-token-parser-test \ + types-test \ + utf8-test \ + yaml-parser-test \ + xml-writer-test + +distclean-local: + rm -rf $(TESTS) + +@VALGRIND_CHECK_RULES@ diff --git a/src/parser/Makefile.in b/src/parser/Makefile.in new file mode 100644 index 0000000..8ac6054 --- /dev/null +++ b/src/parser/Makefile.in @@ -0,0 +1,2328 @@ +# Makefile.in generated by automake 1.16.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2021 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@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +@HAVE_FILESYSTEM_TRUE@am__append_1 = "-DHAVE_FILESYSTEM=1" +@HAVE_EXPERIMENTAL_FILESYSTEM_TRUE@am__append_2 = "-DHAVE_EXPERIMENTAL_FILESYSTEM=1" +@HAVE_EXPERIMENTAL_FILESYSTEM_TRUE@@HAVE_FILESYSTEM_FALSE@am__append_3 = -lstdc++fs +@HAVE_EXPERIMENTAL_FILESYSTEM_FALSE@@HAVE_FILESYSTEM_FALSE@am__append_4 = $(BOOST_FILESYSTEM_LDFLAGS) +@HAVE_EXPERIMENTAL_FILESYSTEM_FALSE@@HAVE_FILESYSTEM_FALSE@am__append_5 = $(BOOST_FILESYSTEM_LIBS) +EXTRA_PROGRAMS = css-parser-test$(EXEEXT) csv-parser-test$(EXEEXT) \ + json-parser-test$(EXEEXT) parser-global-test$(EXEEXT) \ + parser-test-base$(EXEEXT) parser-test-base64$(EXEEXT) \ + parser-test-json-validation$(EXEEXT) \ + parser-test-numeric$(EXEEXT) parser-test-stream$(EXEEXT) \ + parser-test-string-pool$(EXEEXT) \ + parser-test-threaded-json-parser$(EXEEXT) \ + parser-test-threaded-sax-token-parser$(EXEEXT) \ + parser-test-xml-namespace$(EXEEXT) \ + parser-test-xml-validation$(EXEEXT) \ + parser-test-zip-archive$(EXEEXT) sax-ns-parser-test$(EXEEXT) \ + sax-parser-test$(EXEEXT) sax-token-parser-test$(EXEEXT) \ + types-test$(EXEEXT) utf8-test$(EXEEXT) \ + yaml-parser-test$(EXEEXT) xml-writer-test$(EXEEXT) +@HAVE_EXPERIMENTAL_FILESYSTEM_TRUE@@HAVE_FILESYSTEM_FALSE@am__append_6 = -lstdc++fs +@HAVE_EXPERIMENTAL_FILESYSTEM_FALSE@@HAVE_FILESYSTEM_FALSE@am__append_7 = $(BOOST_FILESYSTEM_LDFLAGS) +@HAVE_EXPERIMENTAL_FILESYSTEM_FALSE@@HAVE_FILESYSTEM_FALSE@am__append_8 = $(BOOST_FILESYSTEM_LIBS) +@HAVE_EXPERIMENTAL_FILESYSTEM_TRUE@@HAVE_FILESYSTEM_FALSE@am__append_9 = -lstdc++fs +@HAVE_EXPERIMENTAL_FILESYSTEM_FALSE@@HAVE_FILESYSTEM_FALSE@am__append_10 = $(BOOST_FILESYSTEM_LDFLAGS) +@HAVE_EXPERIMENTAL_FILESYSTEM_FALSE@@HAVE_FILESYSTEM_FALSE@am__append_11 = $(BOOST_FILESYSTEM_LIBS) +TESTS = css-parser-test$(EXEEXT) csv-parser-test$(EXEEXT) \ + json-parser-test$(EXEEXT) parser-global-test$(EXEEXT) \ + parser-test-base$(EXEEXT) parser-test-base64$(EXEEXT) \ + parser-test-json-validation$(EXEEXT) \ + parser-test-numeric$(EXEEXT) parser-test-stream$(EXEEXT) \ + parser-test-string-pool$(EXEEXT) \ + parser-test-threaded-json-parser$(EXEEXT) \ + parser-test-threaded-sax-token-parser$(EXEEXT) \ + parser-test-xml-namespace$(EXEEXT) \ + parser-test-xml-validation$(EXEEXT) \ + parser-test-zip-archive$(EXEEXT) sax-ns-parser-test$(EXEEXT) \ + sax-parser-test$(EXEEXT) sax-token-parser-test$(EXEEXT) \ + types-test$(EXEEXT) utf8-test$(EXEEXT) \ + yaml-parser-test$(EXEEXT) xml-writer-test$(EXEEXT) +subdir = src/parser +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \ + $(top_srcdir)/m4/ax_cxx_compile_stdcxx_17.m4 \ + $(top_srcdir)/m4/boost.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/m4_ax_valgrind_check.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(libdir)" +LTLIBRARIES = $(lib_LTLIBRARIES) +am__DEPENDENCIES_1 = +@HAVE_EXPERIMENTAL_FILESYSTEM_FALSE@@HAVE_FILESYSTEM_FALSE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) +liborcus_parser_@ORCUS_API_VERSION@_la_DEPENDENCIES = \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_2) +am_liborcus_parser_@ORCUS_API_VERSION@_la_OBJECTS = base64.lo \ + cell_buffer.lo css_parser_base.lo css_types.lo \ + csv_parser_base.lo exception.lo json_global.lo \ + json_parser_base.lo json_parser_thread.lo parser_base.lo \ + parser_global.lo sax_parser_base.lo sax_token_parser.lo \ + sax_token_parser_thread.lo stream.lo string_pool.lo tokens.lo \ + types.lo utf8.lo xml_namespace.lo xml_writer.lo \ + yaml_parser_base.lo zip_archive.lo zip_archive_stream.lo +liborcus_parser_@ORCUS_API_VERSION@_la_OBJECTS = \ + $(am_liborcus_parser_@ORCUS_API_VERSION@_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +liborcus_parser_@ORCUS_API_VERSION@_la_LINK = $(LIBTOOL) $(AM_V_lt) \ + --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ + $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(liborcus_parser_@ORCUS_API_VERSION@_la_LDFLAGS) $(LDFLAGS) \ + -o $@ +am_css_parser_test_OBJECTS = \ + css_parser_test-css_parser_test.$(OBJEXT) +css_parser_test_OBJECTS = $(am_css_parser_test_OBJECTS) +css_parser_test_DEPENDENCIES = liborcus-parser-@ORCUS_API_VERSION@.la +am_csv_parser_test_OBJECTS = \ + csv_parser_test-csv_parser_test.$(OBJEXT) +csv_parser_test_OBJECTS = $(am_csv_parser_test_OBJECTS) +csv_parser_test_DEPENDENCIES = liborcus-parser-@ORCUS_API_VERSION@.la +am_json_parser_test_OBJECTS = \ + json_parser_test-json_parser_test.$(OBJEXT) +json_parser_test_OBJECTS = $(am_json_parser_test_OBJECTS) +json_parser_test_DEPENDENCIES = \ + liborcus-parser-@ORCUS_API_VERSION@.la +am_parser_global_test_OBJECTS = \ + parser_global_test-parser_global_test.$(OBJEXT) +parser_global_test_OBJECTS = $(am_parser_global_test_OBJECTS) +parser_global_test_DEPENDENCIES = \ + liborcus-parser-@ORCUS_API_VERSION@.la ../test/liborcus-test.a +am_parser_test_base_OBJECTS = \ + parser_test_base-parser_base_test.$(OBJEXT) +parser_test_base_OBJECTS = $(am_parser_test_base_OBJECTS) +parser_test_base_DEPENDENCIES = \ + liborcus-parser-@ORCUS_API_VERSION@.la +am_parser_test_base64_OBJECTS = parser_test_base64-base64.$(OBJEXT) \ + parser_test_base64-base64_test.$(OBJEXT) +parser_test_base64_OBJECTS = $(am_parser_test_base64_OBJECTS) +parser_test_base64_DEPENDENCIES = \ + liborcus-parser-@ORCUS_API_VERSION@.la +am_parser_test_json_validation_OBJECTS = parser_test_json_validation-parser_test_json_validation.$(OBJEXT) +parser_test_json_validation_OBJECTS = \ + $(am_parser_test_json_validation_OBJECTS) +parser_test_json_validation_DEPENDENCIES = \ + liborcus-parser-@ORCUS_API_VERSION@.la +am_parser_test_numeric_OBJECTS = \ + parser_test_numeric-parser_test_numeric.$(OBJEXT) +parser_test_numeric_OBJECTS = $(am_parser_test_numeric_OBJECTS) +parser_test_numeric_DEPENDENCIES = \ + liborcus-parser-@ORCUS_API_VERSION@.la +am_parser_test_stream_OBJECTS = \ + parser_test_stream-stream_test.$(OBJEXT) +parser_test_stream_OBJECTS = $(am_parser_test_stream_OBJECTS) +parser_test_stream_DEPENDENCIES = \ + liborcus-parser-@ORCUS_API_VERSION@.la ../test/liborcus-test.a +am_parser_test_string_pool_OBJECTS = \ + parser_test_string_pool-string_pool.$(OBJEXT) \ + parser_test_string_pool-string_pool_test.$(OBJEXT) +parser_test_string_pool_OBJECTS = \ + $(am_parser_test_string_pool_OBJECTS) +parser_test_string_pool_DEPENDENCIES = \ + liborcus-parser-@ORCUS_API_VERSION@.la $(am__DEPENDENCIES_1) +am_parser_test_threaded_json_parser_OBJECTS = parser_test_threaded_json_parser-threaded_json_parser_test.$(OBJEXT) +parser_test_threaded_json_parser_OBJECTS = \ + $(am_parser_test_threaded_json_parser_OBJECTS) +parser_test_threaded_json_parser_DEPENDENCIES = \ + liborcus-parser-@ORCUS_API_VERSION@.la +parser_test_threaded_json_parser_LINK = $(LIBTOOL) $(AM_V_lt) \ + --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ + $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(parser_test_threaded_json_parser_LDFLAGS) $(LDFLAGS) -o $@ +am_parser_test_threaded_sax_token_parser_OBJECTS = parser_test_threaded_sax_token_parser-threaded_sax_token_parser_test.$(OBJEXT) +parser_test_threaded_sax_token_parser_OBJECTS = \ + $(am_parser_test_threaded_sax_token_parser_OBJECTS) +parser_test_threaded_sax_token_parser_DEPENDENCIES = \ + liborcus-parser-@ORCUS_API_VERSION@.la +am_parser_test_xml_namespace_OBJECTS = \ + parser_test_xml_namespace-xml_namespace.$(OBJEXT) \ + parser_test_xml_namespace-xml_namespace_test.$(OBJEXT) +parser_test_xml_namespace_OBJECTS = \ + $(am_parser_test_xml_namespace_OBJECTS) +parser_test_xml_namespace_DEPENDENCIES = \ + liborcus-parser-@ORCUS_API_VERSION@.la ../test/liborcus-test.a \ + $(am__DEPENDENCIES_1) +am_parser_test_xml_validation_OBJECTS = parser_test_xml_validation-parser_test_xml_validation.$(OBJEXT) +parser_test_xml_validation_OBJECTS = \ + $(am_parser_test_xml_validation_OBJECTS) +parser_test_xml_validation_DEPENDENCIES = \ + liborcus-parser-@ORCUS_API_VERSION@.la ../test/liborcus-test.a \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) +parser_test_xml_validation_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(parser_test_xml_validation_LDFLAGS) $(LDFLAGS) -o $@ +am_parser_test_zip_archive_OBJECTS = \ + parser_test_zip_archive-zip_archive_test.$(OBJEXT) +parser_test_zip_archive_OBJECTS = \ + $(am_parser_test_zip_archive_OBJECTS) +parser_test_zip_archive_DEPENDENCIES = \ + liborcus-parser-@ORCUS_API_VERSION@.la ../test/liborcus-test.a \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) +parser_test_zip_archive_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(AM_CXXFLAGS) $(CXXFLAGS) $(parser_test_zip_archive_LDFLAGS) \ + $(LDFLAGS) -o $@ +am_sax_ns_parser_test_OBJECTS = \ + sax_ns_parser_test-sax_ns_parser_test.$(OBJEXT) +sax_ns_parser_test_OBJECTS = $(am_sax_ns_parser_test_OBJECTS) +sax_ns_parser_test_DEPENDENCIES = \ + liborcus-parser-@ORCUS_API_VERSION@.la +am_sax_parser_test_OBJECTS = \ + sax_parser_test-sax_parser_test.$(OBJEXT) +sax_parser_test_OBJECTS = $(am_sax_parser_test_OBJECTS) +sax_parser_test_DEPENDENCIES = liborcus-parser-@ORCUS_API_VERSION@.la +am_sax_token_parser_test_OBJECTS = \ + sax_token_parser_test-sax_token_parser_test.$(OBJEXT) +sax_token_parser_test_OBJECTS = $(am_sax_token_parser_test_OBJECTS) +sax_token_parser_test_DEPENDENCIES = \ + liborcus-parser-@ORCUS_API_VERSION@.la +am_types_test_OBJECTS = types_test-types_test.$(OBJEXT) +types_test_OBJECTS = $(am_types_test_OBJECTS) +types_test_DEPENDENCIES = liborcus-parser-@ORCUS_API_VERSION@.la \ + ../test/liborcus-test.a +am_utf8_test_OBJECTS = utf8_test-utf8.$(OBJEXT) \ + utf8_test-utf8_test.$(OBJEXT) +utf8_test_OBJECTS = $(am_utf8_test_OBJECTS) +utf8_test_DEPENDENCIES = liborcus-parser-@ORCUS_API_VERSION@.la +am_xml_writer_test_OBJECTS = \ + xml_writer_test-xml_writer_test.$(OBJEXT) +xml_writer_test_OBJECTS = $(am_xml_writer_test_OBJECTS) +xml_writer_test_DEPENDENCIES = liborcus-parser-@ORCUS_API_VERSION@.la +am_yaml_parser_test_OBJECTS = \ + yaml_parser_test-yaml_parser_test.$(OBJEXT) +yaml_parser_test_OBJECTS = $(am_yaml_parser_test_OBJECTS) +yaml_parser_test_DEPENDENCIES = \ + liborcus-parser-@ORCUS_API_VERSION@.la +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/base64.Plo \ + ./$(DEPDIR)/cell_buffer.Plo ./$(DEPDIR)/css_parser_base.Plo \ + ./$(DEPDIR)/css_parser_test-css_parser_test.Po \ + ./$(DEPDIR)/css_types.Plo ./$(DEPDIR)/csv_parser_base.Plo \ + ./$(DEPDIR)/csv_parser_test-csv_parser_test.Po \ + ./$(DEPDIR)/exception.Plo ./$(DEPDIR)/json_global.Plo \ + ./$(DEPDIR)/json_parser_base.Plo \ + ./$(DEPDIR)/json_parser_test-json_parser_test.Po \ + ./$(DEPDIR)/json_parser_thread.Plo ./$(DEPDIR)/parser_base.Plo \ + ./$(DEPDIR)/parser_global.Plo \ + ./$(DEPDIR)/parser_global_test-parser_global_test.Po \ + ./$(DEPDIR)/parser_test_base-parser_base_test.Po \ + ./$(DEPDIR)/parser_test_base64-base64.Po \ + ./$(DEPDIR)/parser_test_base64-base64_test.Po \ + ./$(DEPDIR)/parser_test_json_validation-parser_test_json_validation.Po \ + ./$(DEPDIR)/parser_test_numeric-parser_test_numeric.Po \ + ./$(DEPDIR)/parser_test_stream-stream_test.Po \ + ./$(DEPDIR)/parser_test_string_pool-string_pool.Po \ + ./$(DEPDIR)/parser_test_string_pool-string_pool_test.Po \ + ./$(DEPDIR)/parser_test_threaded_json_parser-threaded_json_parser_test.Po \ + ./$(DEPDIR)/parser_test_threaded_sax_token_parser-threaded_sax_token_parser_test.Po \ + ./$(DEPDIR)/parser_test_xml_namespace-xml_namespace.Po \ + ./$(DEPDIR)/parser_test_xml_namespace-xml_namespace_test.Po \ + ./$(DEPDIR)/parser_test_xml_validation-parser_test_xml_validation.Po \ + ./$(DEPDIR)/parser_test_zip_archive-zip_archive_test.Po \ + ./$(DEPDIR)/sax_ns_parser_test-sax_ns_parser_test.Po \ + ./$(DEPDIR)/sax_parser_base.Plo \ + ./$(DEPDIR)/sax_parser_test-sax_parser_test.Po \ + ./$(DEPDIR)/sax_token_parser.Plo \ + ./$(DEPDIR)/sax_token_parser_test-sax_token_parser_test.Po \ + ./$(DEPDIR)/sax_token_parser_thread.Plo ./$(DEPDIR)/stream.Plo \ + ./$(DEPDIR)/string_pool.Plo ./$(DEPDIR)/tokens.Plo \ + ./$(DEPDIR)/types.Plo ./$(DEPDIR)/types_test-types_test.Po \ + ./$(DEPDIR)/utf8.Plo ./$(DEPDIR)/utf8_test-utf8.Po \ + ./$(DEPDIR)/utf8_test-utf8_test.Po \ + ./$(DEPDIR)/xml_namespace.Plo ./$(DEPDIR)/xml_writer.Plo \ + ./$(DEPDIR)/xml_writer_test-xml_writer_test.Po \ + ./$(DEPDIR)/yaml_parser_base.Plo \ + ./$(DEPDIR)/yaml_parser_test-yaml_parser_test.Po \ + ./$(DEPDIR)/zip_archive.Plo ./$(DEPDIR)/zip_archive_stream.Plo +am__mv = mv -f +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_@AM_V@) +am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) +am__v_CXX_0 = @echo " CXX " $@; +am__v_CXX_1 = +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) +am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) +am__v_CXXLD_0 = @echo " CXXLD " $@; +am__v_CXXLD_1 = +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(liborcus_parser_@ORCUS_API_VERSION@_la_SOURCES) \ + $(css_parser_test_SOURCES) $(csv_parser_test_SOURCES) \ + $(json_parser_test_SOURCES) $(parser_global_test_SOURCES) \ + $(parser_test_base_SOURCES) $(parser_test_base64_SOURCES) \ + $(parser_test_json_validation_SOURCES) \ + $(parser_test_numeric_SOURCES) $(parser_test_stream_SOURCES) \ + $(parser_test_string_pool_SOURCES) \ + $(parser_test_threaded_json_parser_SOURCES) \ + $(parser_test_threaded_sax_token_parser_SOURCES) \ + $(parser_test_xml_namespace_SOURCES) \ + $(parser_test_xml_validation_SOURCES) \ + $(parser_test_zip_archive_SOURCES) \ + $(sax_ns_parser_test_SOURCES) $(sax_parser_test_SOURCES) \ + $(sax_token_parser_test_SOURCES) $(types_test_SOURCES) \ + $(utf8_test_SOURCES) $(xml_writer_test_SOURCES) \ + $(yaml_parser_test_SOURCES) +DIST_SOURCES = $(liborcus_parser_@ORCUS_API_VERSION@_la_SOURCES) \ + $(css_parser_test_SOURCES) $(csv_parser_test_SOURCES) \ + $(json_parser_test_SOURCES) $(parser_global_test_SOURCES) \ + $(parser_test_base_SOURCES) $(parser_test_base64_SOURCES) \ + $(parser_test_json_validation_SOURCES) \ + $(parser_test_numeric_SOURCES) $(parser_test_stream_SOURCES) \ + $(parser_test_string_pool_SOURCES) \ + $(parser_test_threaded_json_parser_SOURCES) \ + $(parser_test_threaded_sax_token_parser_SOURCES) \ + $(parser_test_xml_namespace_SOURCES) \ + $(parser_test_xml_validation_SOURCES) \ + $(parser_test_zip_archive_SOURCES) \ + $(sax_ns_parser_test_SOURCES) $(sax_parser_test_SOURCES) \ + $(sax_token_parser_test_SOURCES) $(types_test_SOURCES) \ + $(utf8_test_SOURCES) $(xml_writer_test_SOURCES) \ + $(yaml_parser_test_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__extra_recursive_targets = check-valgrind-recursive \ + check-valgrind-memcheck-recursive \ + check-valgrind-helgrind-recursive check-valgrind-drd-recursive \ + check-valgrind-sgcheck-recursive +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +am__tty_colors_dummy = \ + mgn= red= grn= lgn= blu= brg= std=; \ + am__color_tests=no +am__tty_colors = { \ + $(am__tty_colors_dummy); \ + if test "X$(AM_COLOR_TESTS)" = Xno; then \ + am__color_tests=no; \ + elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ + am__color_tests=yes; \ + elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ + am__color_tests=yes; \ + fi; \ + if test $$am__color_tests = yes; then \ + red='[0;31m'; \ + grn='[0;32m'; \ + lgn='[1;32m'; \ + blu='[1;34m'; \ + mgn='[0;35m'; \ + brg='[1m'; \ + std='[m'; \ + fi; \ +} +am__recheck_rx = ^[ ]*:recheck:[ ]* +am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* +am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* +# A command that, given a newline-separated list of test names on the +# standard input, print the name of the tests that are to be re-run +# upon "make recheck". +am__list_recheck_tests = $(AWK) '{ \ + recheck = 1; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + { \ + if ((getline line2 < ($$0 ".log")) < 0) \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ + { \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ + { \ + break; \ + } \ + }; \ + if (recheck) \ + print $$0; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# A command that, given a newline-separated list of test names on the +# standard input, create the global log from their .trs and .log files. +am__create_global_log = $(AWK) ' \ +function fatal(msg) \ +{ \ + print "fatal: making $@: " msg | "cat >&2"; \ + exit 1; \ +} \ +function rst_section(header) \ +{ \ + print header; \ + len = length(header); \ + for (i = 1; i <= len; i = i + 1) \ + printf "="; \ + printf "\n\n"; \ +} \ +{ \ + copy_in_global_log = 1; \ + global_test_result = "RUN"; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".trs"); \ + if (line ~ /$(am__global_test_result_rx)/) \ + { \ + sub("$(am__global_test_result_rx)", "", line); \ + sub("[ ]*$$", "", line); \ + global_test_result = line; \ + } \ + else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ + copy_in_global_log = 0; \ + }; \ + if (copy_in_global_log) \ + { \ + rst_section(global_test_result ": " $$0); \ + while ((rc = (getline line < ($$0 ".log"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".log"); \ + print line; \ + }; \ + printf "\n"; \ + }; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# Restructured Text title. +am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } +# Solaris 10 'make', and several other traditional 'make' implementations, +# pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it +# by disabling -e (using the XSI extension "set +e") if it's set. +am__sh_e_setup = case $$- in *e*) set +e;; esac +# Default flags passed to test drivers. +am__common_driver_flags = \ + --color-tests "$$am__color_tests" \ + --enable-hard-errors "$$am__enable_hard_errors" \ + --expect-failure "$$am__expect_failure" +# To be inserted before the command running the test. Creates the +# directory for the log if needed. Stores in $dir the directory +# containing $f, in $tst the test, in $log the log. Executes the +# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and +# passes TESTS_ENVIRONMENT. Set up options for the wrapper that +# will run the test scripts (or their associated LOG_COMPILER, if +# thy have one). +am__check_pre = \ +$(am__sh_e_setup); \ +$(am__vpath_adj_setup) $(am__vpath_adj) \ +$(am__tty_colors); \ +srcdir=$(srcdir); export srcdir; \ +case "$@" in \ + */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ + *) am__odir=.;; \ +esac; \ +test "x$$am__odir" = x"." || test -d "$$am__odir" \ + || $(MKDIR_P) "$$am__odir" || exit $$?; \ +if test -f "./$$f"; then dir=./; \ +elif test -f "$$f"; then dir=; \ +else dir="$(srcdir)/"; fi; \ +tst=$$dir$$f; log='$@'; \ +if test -n '$(DISABLE_HARD_ERRORS)'; then \ + am__enable_hard_errors=no; \ +else \ + am__enable_hard_errors=yes; \ +fi; \ +case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ + am__expect_failure=yes;; \ + *) \ + am__expect_failure=no;; \ +esac; \ +$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) +# A shell command to get the names of the tests scripts with any registered +# extension removed (i.e., equivalently, the names of the test logs, with +# the '.log' extension removed). The result is saved in the shell variable +# '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, +# we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", +# since that might cause problem with VPATH rewrites for suffix-less tests. +# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. +am__set_TESTS_bases = \ + bases='$(TEST_LOGS)'; \ + bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ + bases=`echo $$bases` +AM_TESTSUITE_SUMMARY_HEADER = ' for $(PACKAGE_STRING)' +RECHECK_LOGS = $(TEST_LOGS) +AM_RECURSIVE_TARGETS = check recheck +TEST_SUITE_LOG = test-suite.log +TEST_EXTENSIONS = @EXEEXT@ .test +LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver +LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) +am__set_b = \ + case '$@' in \ + */*) \ + case '$*' in \ + */*) b='$*';; \ + *) b=`echo '$@' | sed 's/\.log$$//'`; \ + esac;; \ + *) \ + b='$*';; \ + esac +am__test_logs1 = $(TESTS:=.log) +am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) +TEST_LOGS = $(am__test_logs2:.test.log=.log) +TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver +TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ + $(TEST_LOG_FLAGS) +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp \ + $(top_srcdir)/test-driver +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ +BOOST_DATE_TIME_LDFLAGS = @BOOST_DATE_TIME_LDFLAGS@ +BOOST_DATE_TIME_LDPATH = @BOOST_DATE_TIME_LDPATH@ +BOOST_DATE_TIME_LIBS = @BOOST_DATE_TIME_LIBS@ +BOOST_FILESYSTEM_LDFLAGS = @BOOST_FILESYSTEM_LDFLAGS@ +BOOST_FILESYSTEM_LDPATH = @BOOST_FILESYSTEM_LDPATH@ +BOOST_FILESYSTEM_LIBS = @BOOST_FILESYSTEM_LIBS@ +BOOST_IOSTREAMS_LDFLAGS = @BOOST_IOSTREAMS_LDFLAGS@ +BOOST_IOSTREAMS_LDPATH = @BOOST_IOSTREAMS_LDPATH@ +BOOST_IOSTREAMS_LIBS = @BOOST_IOSTREAMS_LIBS@ +BOOST_LDPATH = @BOOST_LDPATH@ +BOOST_PROGRAM_OPTIONS_LDFLAGS = @BOOST_PROGRAM_OPTIONS_LDFLAGS@ +BOOST_PROGRAM_OPTIONS_LDPATH = @BOOST_PROGRAM_OPTIONS_LDPATH@ +BOOST_PROGRAM_OPTIONS_LIBS = @BOOST_PROGRAM_OPTIONS_LIBS@ +BOOST_ROOT = @BOOST_ROOT@ +BOOST_SYSTEM_LDFLAGS = @BOOST_SYSTEM_LDFLAGS@ +BOOST_SYSTEM_LDPATH = @BOOST_SYSTEM_LDPATH@ +BOOST_SYSTEM_LIBS = @BOOST_SYSTEM_LIBS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CSCOPE = @CSCOPE@ +CTAGS = @CTAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_VALGRIND_drd = @ENABLE_VALGRIND_drd@ +ENABLE_VALGRIND_helgrind = @ENABLE_VALGRIND_helgrind@ +ENABLE_VALGRIND_memcheck = @ENABLE_VALGRIND_memcheck@ +ENABLE_VALGRIND_sgcheck = @ENABLE_VALGRIND_sgcheck@ +ETAGS = @ETAGS@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +HAVE_CXX17 = @HAVE_CXX17@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +IXION_REQUIRED_API_VERSION = @IXION_REQUIRED_API_VERSION@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBIXION_CFLAGS = @LIBIXION_CFLAGS@ +LIBIXION_LIBS = @LIBIXION_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MDDS_CFLAGS = @MDDS_CFLAGS@ +MDDS_LIBS = @MDDS_LIBS@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +ORCUS_API_VERSION = @ORCUS_API_VERSION@ +ORCUS_MAJOR_VERSION = @ORCUS_MAJOR_VERSION@ +ORCUS_MICRO_VERSION = @ORCUS_MICRO_VERSION@ +ORCUS_MINOR_VERSION = @ORCUS_MINOR_VERSION@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PARQUET_CFLAGS = @PARQUET_CFLAGS@ +PARQUET_LIBS = @PARQUET_LIBS@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +POW_LIB = @POW_LIB@ +PYTHON = @PYTHON@ +PYTHON_CFLAGS = @PYTHON_CFLAGS@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_LIBS = @PYTHON_LIBS@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VALGRIND_ENABLED = @VALGRIND_ENABLED@ +VERSION = @VERSION@ +ZLIB_CFLAGS = @ZLIB_CFLAGS@ +ZLIB_LIBS = @ZLIB_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +valgrind_enabled_tools = @valgrind_enabled_tools@ +valgrind_tools = @valgrind_tools@ +AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/src/include \ + -DSRCDIR=\""$(top_srcdir)"\" $(BOOST_CPPFLAGS) \ + -D__ORCUS_PSR_BUILDING_DLL $(am__append_1) $(am__append_2) +lib_LTLIBRARIES = liborcus-parser-@ORCUS_API_VERSION@.la +liborcus_parser_@ORCUS_API_VERSION@_la_SOURCES = \ + win_stdint.h \ + base64.cpp \ + cell_buffer.cpp \ + css_parser_base.cpp \ + css_types.cpp \ + csv_parser_base.cpp \ + exception.cpp \ + json_global.cpp \ + json_parser_base.cpp \ + json_parser_thread.cpp \ + parser_base.cpp \ + parser_global.cpp \ + sax_parser_base.cpp \ + sax_token_parser.cpp \ + sax_token_parser_thread.cpp \ + stream.cpp \ + string_pool.cpp \ + tokens.cpp \ + types.cpp \ + utf8.hpp \ + utf8.cpp \ + xml_namespace.cpp \ + xml_writer.cpp \ + yaml_parser_base.cpp \ + zip_archive.cpp \ + zip_archive_stream.cpp + +liborcus_parser_@ORCUS_API_VERSION@_la_LDFLAGS = -no-undefined \ + $(BOOST_SYSTEM_LDFLAGS) $(am__append_3) $(am__append_4) +liborcus_parser_@ORCUS_API_VERSION@_la_LIBADD = $(BOOST_SYSTEM_LIBS) \ + $(ZLIB_LIBS) $(am__append_5) + +# parser-test-string-pool +parser_test_string_pool_SOURCES = \ + string_pool.cpp \ + string_pool_test.cpp + +parser_test_string_pool_LDADD = \ + liborcus-parser-@ORCUS_API_VERSION@.la \ + $(BOOST_SYSTEM_LIBS) + +parser_test_string_pool_CPPFLAGS = $(AM_CPPFLAGS) + +# parser-test-xml-namespace +parser_test_xml_namespace_SOURCES = \ + xml_namespace.cpp \ + xml_namespace_test.cpp + +parser_test_xml_namespace_LDADD = \ + liborcus-parser-@ORCUS_API_VERSION@.la \ + ../test/liborcus-test.a \ + $(BOOST_SYSTEM_LIBS) + +parser_test_xml_namespace_CPPFLAGS = $(AM_CPPFLAGS) + +# parser-test-xml-validation +parser_test_xml_validation_SOURCES = \ + parser_test_xml_validation.cpp + +parser_test_xml_validation_CPPFLAGS = $(AM_CPPFLAGS) +parser_test_xml_validation_LDFLAGS = $(BOOST_SYSTEM_LDFLAGS) \ + $(am__append_6) $(am__append_7) +parser_test_xml_validation_LDADD = \ + liborcus-parser-@ORCUS_API_VERSION@.la ../test/liborcus-test.a \ + $(BOOST_SYSTEM_LIBS) $(am__append_8) + +# parser-test-base64 +parser_test_base64_SOURCES = \ + base64.cpp \ + base64_test.cpp + +parser_test_base64_LDADD = liborcus-parser-@ORCUS_API_VERSION@.la +parser_test_base64_CPPFLAGS = $(AM_CPPFLAGS) + +# css-parser-test +css_parser_test_SOURCES = \ + css_parser_test.cpp + +css_parser_test_LDADD = liborcus-parser-@ORCUS_API_VERSION@.la +css_parser_test_CPPFLAGS = $(AM_CPPFLAGS) + +# csv-parser-test +csv_parser_test_SOURCES = \ + csv_parser_test.cpp + +csv_parser_test_LDADD = liborcus-parser-@ORCUS_API_VERSION@.la +csv_parser_test_CPPFLAGS = $(AM_CPPFLAGS) + +# json-parser-test +json_parser_test_SOURCES = \ + json_parser_test.cpp + +json_parser_test_LDADD = liborcus-parser-@ORCUS_API_VERSION@.la +json_parser_test_CPPFLAGS = $(AM_CPPFLAGS) + +# yaml-parser-test +yaml_parser_test_SOURCES = \ + yaml_parser_test.cpp + +yaml_parser_test_LDADD = liborcus-parser-@ORCUS_API_VERSION@.la +yaml_parser_test_CPPFLAGS = $(AM_CPPFLAGS) + +# sax-parser-test +sax_parser_test_SOURCES = \ + sax_parser_test.cpp + +sax_parser_test_LDADD = liborcus-parser-@ORCUS_API_VERSION@.la +sax_parser_test_CPPFLAGS = $(AM_CPPFLAGS) + +# sax-ns-parser-test +sax_ns_parser_test_SOURCES = \ + sax_ns_parser_test.cpp + +sax_ns_parser_test_LDADD = liborcus-parser-@ORCUS_API_VERSION@.la +sax_ns_parser_test_CPPFLAGS = $(AM_CPPFLAGS) + +# sax-token-parser-test +sax_token_parser_test_SOURCES = \ + sax_token_parser_test.cpp + +sax_token_parser_test_LDADD = liborcus-parser-@ORCUS_API_VERSION@.la +sax_token_parser_test_CPPFLAGS = $(AM_CPPFLAGS) + +# parser-test-threaded-sax-token-parser +parser_test_threaded_sax_token_parser_SOURCES = \ + threaded_sax_token_parser_test.cpp + +parser_test_threaded_sax_token_parser_LDADD = liborcus-parser-@ORCUS_API_VERSION@.la +parser_test_threaded_sax_token_parser_CPPFLAGS = $(AM_CPPFLAGS) + +# parser-test-threaded-json-parser +parser_test_threaded_json_parser_SOURCES = \ + threaded_json_parser_test.cpp + +parser_test_threaded_json_parser_LDADD = liborcus-parser-@ORCUS_API_VERSION@.la +parser_test_threaded_json_parser_LDFLAGS = -pthread +parser_test_threaded_json_parser_CPPFLAGS = $(AM_CPPFLAGS) + +# parser-test-stream +parser_test_stream_SOURCES = \ + stream_test.cpp + +parser_test_stream_LDADD = \ + liborcus-parser-@ORCUS_API_VERSION@.la \ + ../test/liborcus-test.a + +parser_test_stream_CPPFLAGS = $(AM_CPPFLAGS) + +# parser-test-zip-archive +parser_test_zip_archive_SOURCES = \ + zip_archive_test.cpp + +parser_test_zip_archive_CPPFLAGS = $(AM_CPPFLAGS) +parser_test_zip_archive_LDADD = \ + liborcus-parser-@ORCUS_API_VERSION@.la ../test/liborcus-test.a \ + $(BOOST_SYSTEM_LIBS) $(am__append_11) +parser_test_zip_archive_LDFLAGS = $(BOOST_SYSTEM_LDFLAGS) \ + $(am__append_9) $(am__append_10) + +# parser-test-base +parser_test_base_SOURCES = \ + parser_base_test.cpp + +parser_test_base_LDADD = liborcus-parser-@ORCUS_API_VERSION@.la +parser_test_base_CPPFLAGS = $(AM_CPPFLAGS) + +# parser-global-test +parser_global_test_SOURCES = \ + parser_global_test.cpp + +parser_global_test_LDADD = \ + liborcus-parser-@ORCUS_API_VERSION@.la \ + ../test/liborcus-test.a + +parser_global_test_CPPFLAGS = $(AM_CPPFLAGS) + +# parser-test-json-validation +parser_test_json_validation_SOURCES = \ + parser_test_json_validation.cpp + +parser_test_json_validation_LDADD = liborcus-parser-@ORCUS_API_VERSION@.la +parser_test_json_validation_CPPFLAGS = $(AM_CPPFLAGS) + +# types-test +types_test_SOURCES = types_test.cpp +types_test_LDADD = \ + liborcus-parser-@ORCUS_API_VERSION@.la \ + ../test/liborcus-test.a + +types_test_CPPFLAGS = $(AM_CPPFLAGS) + +# utf8-test +utf8_test_SOURCES = \ + utf8.cpp \ + utf8_test.cpp + +utf8_test_LDADD = liborcus-parser-@ORCUS_API_VERSION@.la +utf8_test_CPPFLAGS = $(AM_CPPFLAGS) + +# xml-writer-test +xml_writer_test_SOURCES = xml_writer_test.cpp +xml_writer_test_LDADD = liborcus-parser-@ORCUS_API_VERSION@.la +xml_writer_test_CPPFLAGS = $(AM_CPPFLAGS) + +# parser-test-numeric +parser_test_numeric_SOURCES = \ + parser_test_numeric.cpp + +parser_test_numeric = liborcus-parser-@ORCUS_API_VERSION@.la +parser_test_numeric_LDADD = liborcus-parser-@ORCUS_API_VERSION@.la +parser_test_numeric_CPPFLAGS = $(AM_CPPFLAGS) +all: all-am + +.SUFFIXES: +.SUFFIXES: .cpp .lo .log .o .obj .test .test$(EXEEXT) .trs +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/parser/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/parser/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__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ + } + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +liborcus-parser-@ORCUS_API_VERSION@.la: $(liborcus_parser_@ORCUS_API_VERSION@_la_OBJECTS) $(liborcus_parser_@ORCUS_API_VERSION@_la_DEPENDENCIES) $(EXTRA_liborcus_parser_@ORCUS_API_VERSION@_la_DEPENDENCIES) + $(AM_V_CXXLD)$(liborcus_parser_@ORCUS_API_VERSION@_la_LINK) -rpath $(libdir) $(liborcus_parser_@ORCUS_API_VERSION@_la_OBJECTS) $(liborcus_parser_@ORCUS_API_VERSION@_la_LIBADD) $(LIBS) + +css-parser-test$(EXEEXT): $(css_parser_test_OBJECTS) $(css_parser_test_DEPENDENCIES) $(EXTRA_css_parser_test_DEPENDENCIES) + @rm -f css-parser-test$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(css_parser_test_OBJECTS) $(css_parser_test_LDADD) $(LIBS) + +csv-parser-test$(EXEEXT): $(csv_parser_test_OBJECTS) $(csv_parser_test_DEPENDENCIES) $(EXTRA_csv_parser_test_DEPENDENCIES) + @rm -f csv-parser-test$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(csv_parser_test_OBJECTS) $(csv_parser_test_LDADD) $(LIBS) + +json-parser-test$(EXEEXT): $(json_parser_test_OBJECTS) $(json_parser_test_DEPENDENCIES) $(EXTRA_json_parser_test_DEPENDENCIES) + @rm -f json-parser-test$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(json_parser_test_OBJECTS) $(json_parser_test_LDADD) $(LIBS) + +parser-global-test$(EXEEXT): $(parser_global_test_OBJECTS) $(parser_global_test_DEPENDENCIES) $(EXTRA_parser_global_test_DEPENDENCIES) + @rm -f parser-global-test$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(parser_global_test_OBJECTS) $(parser_global_test_LDADD) $(LIBS) + +parser-test-base$(EXEEXT): $(parser_test_base_OBJECTS) $(parser_test_base_DEPENDENCIES) $(EXTRA_parser_test_base_DEPENDENCIES) + @rm -f parser-test-base$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(parser_test_base_OBJECTS) $(parser_test_base_LDADD) $(LIBS) + +parser-test-base64$(EXEEXT): $(parser_test_base64_OBJECTS) $(parser_test_base64_DEPENDENCIES) $(EXTRA_parser_test_base64_DEPENDENCIES) + @rm -f parser-test-base64$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(parser_test_base64_OBJECTS) $(parser_test_base64_LDADD) $(LIBS) + +parser-test-json-validation$(EXEEXT): $(parser_test_json_validation_OBJECTS) $(parser_test_json_validation_DEPENDENCIES) $(EXTRA_parser_test_json_validation_DEPENDENCIES) + @rm -f parser-test-json-validation$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(parser_test_json_validation_OBJECTS) $(parser_test_json_validation_LDADD) $(LIBS) + +parser-test-numeric$(EXEEXT): $(parser_test_numeric_OBJECTS) $(parser_test_numeric_DEPENDENCIES) $(EXTRA_parser_test_numeric_DEPENDENCIES) + @rm -f parser-test-numeric$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(parser_test_numeric_OBJECTS) $(parser_test_numeric_LDADD) $(LIBS) + +parser-test-stream$(EXEEXT): $(parser_test_stream_OBJECTS) $(parser_test_stream_DEPENDENCIES) $(EXTRA_parser_test_stream_DEPENDENCIES) + @rm -f parser-test-stream$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(parser_test_stream_OBJECTS) $(parser_test_stream_LDADD) $(LIBS) + +parser-test-string-pool$(EXEEXT): $(parser_test_string_pool_OBJECTS) $(parser_test_string_pool_DEPENDENCIES) $(EXTRA_parser_test_string_pool_DEPENDENCIES) + @rm -f parser-test-string-pool$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(parser_test_string_pool_OBJECTS) $(parser_test_string_pool_LDADD) $(LIBS) + +parser-test-threaded-json-parser$(EXEEXT): $(parser_test_threaded_json_parser_OBJECTS) $(parser_test_threaded_json_parser_DEPENDENCIES) $(EXTRA_parser_test_threaded_json_parser_DEPENDENCIES) + @rm -f parser-test-threaded-json-parser$(EXEEXT) + $(AM_V_CXXLD)$(parser_test_threaded_json_parser_LINK) $(parser_test_threaded_json_parser_OBJECTS) $(parser_test_threaded_json_parser_LDADD) $(LIBS) + +parser-test-threaded-sax-token-parser$(EXEEXT): $(parser_test_threaded_sax_token_parser_OBJECTS) $(parser_test_threaded_sax_token_parser_DEPENDENCIES) $(EXTRA_parser_test_threaded_sax_token_parser_DEPENDENCIES) + @rm -f parser-test-threaded-sax-token-parser$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(parser_test_threaded_sax_token_parser_OBJECTS) $(parser_test_threaded_sax_token_parser_LDADD) $(LIBS) + +parser-test-xml-namespace$(EXEEXT): $(parser_test_xml_namespace_OBJECTS) $(parser_test_xml_namespace_DEPENDENCIES) $(EXTRA_parser_test_xml_namespace_DEPENDENCIES) + @rm -f parser-test-xml-namespace$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(parser_test_xml_namespace_OBJECTS) $(parser_test_xml_namespace_LDADD) $(LIBS) + +parser-test-xml-validation$(EXEEXT): $(parser_test_xml_validation_OBJECTS) $(parser_test_xml_validation_DEPENDENCIES) $(EXTRA_parser_test_xml_validation_DEPENDENCIES) + @rm -f parser-test-xml-validation$(EXEEXT) + $(AM_V_CXXLD)$(parser_test_xml_validation_LINK) $(parser_test_xml_validation_OBJECTS) $(parser_test_xml_validation_LDADD) $(LIBS) + +parser-test-zip-archive$(EXEEXT): $(parser_test_zip_archive_OBJECTS) $(parser_test_zip_archive_DEPENDENCIES) $(EXTRA_parser_test_zip_archive_DEPENDENCIES) + @rm -f parser-test-zip-archive$(EXEEXT) + $(AM_V_CXXLD)$(parser_test_zip_archive_LINK) $(parser_test_zip_archive_OBJECTS) $(parser_test_zip_archive_LDADD) $(LIBS) + +sax-ns-parser-test$(EXEEXT): $(sax_ns_parser_test_OBJECTS) $(sax_ns_parser_test_DEPENDENCIES) $(EXTRA_sax_ns_parser_test_DEPENDENCIES) + @rm -f sax-ns-parser-test$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(sax_ns_parser_test_OBJECTS) $(sax_ns_parser_test_LDADD) $(LIBS) + +sax-parser-test$(EXEEXT): $(sax_parser_test_OBJECTS) $(sax_parser_test_DEPENDENCIES) $(EXTRA_sax_parser_test_DEPENDENCIES) + @rm -f sax-parser-test$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(sax_parser_test_OBJECTS) $(sax_parser_test_LDADD) $(LIBS) + +sax-token-parser-test$(EXEEXT): $(sax_token_parser_test_OBJECTS) $(sax_token_parser_test_DEPENDENCIES) $(EXTRA_sax_token_parser_test_DEPENDENCIES) + @rm -f sax-token-parser-test$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(sax_token_parser_test_OBJECTS) $(sax_token_parser_test_LDADD) $(LIBS) + +types-test$(EXEEXT): $(types_test_OBJECTS) $(types_test_DEPENDENCIES) $(EXTRA_types_test_DEPENDENCIES) + @rm -f types-test$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(types_test_OBJECTS) $(types_test_LDADD) $(LIBS) + +utf8-test$(EXEEXT): $(utf8_test_OBJECTS) $(utf8_test_DEPENDENCIES) $(EXTRA_utf8_test_DEPENDENCIES) + @rm -f utf8-test$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(utf8_test_OBJECTS) $(utf8_test_LDADD) $(LIBS) + +xml-writer-test$(EXEEXT): $(xml_writer_test_OBJECTS) $(xml_writer_test_DEPENDENCIES) $(EXTRA_xml_writer_test_DEPENDENCIES) + @rm -f xml-writer-test$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(xml_writer_test_OBJECTS) $(xml_writer_test_LDADD) $(LIBS) + +yaml-parser-test$(EXEEXT): $(yaml_parser_test_OBJECTS) $(yaml_parser_test_DEPENDENCIES) $(EXTRA_yaml_parser_test_DEPENDENCIES) + @rm -f yaml-parser-test$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(yaml_parser_test_OBJECTS) $(yaml_parser_test_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/base64.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cell_buffer.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/css_parser_base.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/css_parser_test-css_parser_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/css_types.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/csv_parser_base.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/csv_parser_test-csv_parser_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exception.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/json_global.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/json_parser_base.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/json_parser_test-json_parser_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/json_parser_thread.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parser_base.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parser_global.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parser_global_test-parser_global_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parser_test_base-parser_base_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parser_test_base64-base64.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parser_test_base64-base64_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parser_test_json_validation-parser_test_json_validation.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parser_test_numeric-parser_test_numeric.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parser_test_stream-stream_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parser_test_string_pool-string_pool.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parser_test_string_pool-string_pool_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parser_test_threaded_json_parser-threaded_json_parser_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parser_test_threaded_sax_token_parser-threaded_sax_token_parser_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parser_test_xml_namespace-xml_namespace.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parser_test_xml_namespace-xml_namespace_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parser_test_xml_validation-parser_test_xml_validation.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parser_test_zip_archive-zip_archive_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sax_ns_parser_test-sax_ns_parser_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sax_parser_base.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sax_parser_test-sax_parser_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sax_token_parser.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sax_token_parser_test-sax_token_parser_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sax_token_parser_thread.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stream.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/string_pool.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tokens.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/types.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/types_test-types_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utf8.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utf8_test-utf8.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utf8_test-utf8_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xml_namespace.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xml_writer.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xml_writer_test-xml_writer_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/yaml_parser_base.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/yaml_parser_test-yaml_parser_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zip_archive.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zip_archive_stream.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.cpp.o: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cpp.lo: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< + +css_parser_test-css_parser_test.o: css_parser_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(css_parser_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT css_parser_test-css_parser_test.o -MD -MP -MF $(DEPDIR)/css_parser_test-css_parser_test.Tpo -c -o css_parser_test-css_parser_test.o `test -f 'css_parser_test.cpp' || echo '$(srcdir)/'`css_parser_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/css_parser_test-css_parser_test.Tpo $(DEPDIR)/css_parser_test-css_parser_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='css_parser_test.cpp' object='css_parser_test-css_parser_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(css_parser_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o css_parser_test-css_parser_test.o `test -f 'css_parser_test.cpp' || echo '$(srcdir)/'`css_parser_test.cpp + +css_parser_test-css_parser_test.obj: css_parser_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(css_parser_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT css_parser_test-css_parser_test.obj -MD -MP -MF $(DEPDIR)/css_parser_test-css_parser_test.Tpo -c -o css_parser_test-css_parser_test.obj `if test -f 'css_parser_test.cpp'; then $(CYGPATH_W) 'css_parser_test.cpp'; else $(CYGPATH_W) '$(srcdir)/css_parser_test.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/css_parser_test-css_parser_test.Tpo $(DEPDIR)/css_parser_test-css_parser_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='css_parser_test.cpp' object='css_parser_test-css_parser_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(css_parser_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o css_parser_test-css_parser_test.obj `if test -f 'css_parser_test.cpp'; then $(CYGPATH_W) 'css_parser_test.cpp'; else $(CYGPATH_W) '$(srcdir)/css_parser_test.cpp'; fi` + +csv_parser_test-csv_parser_test.o: csv_parser_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(csv_parser_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT csv_parser_test-csv_parser_test.o -MD -MP -MF $(DEPDIR)/csv_parser_test-csv_parser_test.Tpo -c -o csv_parser_test-csv_parser_test.o `test -f 'csv_parser_test.cpp' || echo '$(srcdir)/'`csv_parser_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/csv_parser_test-csv_parser_test.Tpo $(DEPDIR)/csv_parser_test-csv_parser_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='csv_parser_test.cpp' object='csv_parser_test-csv_parser_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(csv_parser_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o csv_parser_test-csv_parser_test.o `test -f 'csv_parser_test.cpp' || echo '$(srcdir)/'`csv_parser_test.cpp + +csv_parser_test-csv_parser_test.obj: csv_parser_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(csv_parser_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT csv_parser_test-csv_parser_test.obj -MD -MP -MF $(DEPDIR)/csv_parser_test-csv_parser_test.Tpo -c -o csv_parser_test-csv_parser_test.obj `if test -f 'csv_parser_test.cpp'; then $(CYGPATH_W) 'csv_parser_test.cpp'; else $(CYGPATH_W) '$(srcdir)/csv_parser_test.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/csv_parser_test-csv_parser_test.Tpo $(DEPDIR)/csv_parser_test-csv_parser_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='csv_parser_test.cpp' object='csv_parser_test-csv_parser_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(csv_parser_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o csv_parser_test-csv_parser_test.obj `if test -f 'csv_parser_test.cpp'; then $(CYGPATH_W) 'csv_parser_test.cpp'; else $(CYGPATH_W) '$(srcdir)/csv_parser_test.cpp'; fi` + +json_parser_test-json_parser_test.o: json_parser_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(json_parser_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT json_parser_test-json_parser_test.o -MD -MP -MF $(DEPDIR)/json_parser_test-json_parser_test.Tpo -c -o json_parser_test-json_parser_test.o `test -f 'json_parser_test.cpp' || echo '$(srcdir)/'`json_parser_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/json_parser_test-json_parser_test.Tpo $(DEPDIR)/json_parser_test-json_parser_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='json_parser_test.cpp' object='json_parser_test-json_parser_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(json_parser_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o json_parser_test-json_parser_test.o `test -f 'json_parser_test.cpp' || echo '$(srcdir)/'`json_parser_test.cpp + +json_parser_test-json_parser_test.obj: json_parser_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(json_parser_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT json_parser_test-json_parser_test.obj -MD -MP -MF $(DEPDIR)/json_parser_test-json_parser_test.Tpo -c -o json_parser_test-json_parser_test.obj `if test -f 'json_parser_test.cpp'; then $(CYGPATH_W) 'json_parser_test.cpp'; else $(CYGPATH_W) '$(srcdir)/json_parser_test.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/json_parser_test-json_parser_test.Tpo $(DEPDIR)/json_parser_test-json_parser_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='json_parser_test.cpp' object='json_parser_test-json_parser_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(json_parser_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o json_parser_test-json_parser_test.obj `if test -f 'json_parser_test.cpp'; then $(CYGPATH_W) 'json_parser_test.cpp'; else $(CYGPATH_W) '$(srcdir)/json_parser_test.cpp'; fi` + +parser_global_test-parser_global_test.o: parser_global_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(parser_global_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT parser_global_test-parser_global_test.o -MD -MP -MF $(DEPDIR)/parser_global_test-parser_global_test.Tpo -c -o parser_global_test-parser_global_test.o `test -f 'parser_global_test.cpp' || echo '$(srcdir)/'`parser_global_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/parser_global_test-parser_global_test.Tpo $(DEPDIR)/parser_global_test-parser_global_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='parser_global_test.cpp' object='parser_global_test-parser_global_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(parser_global_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o parser_global_test-parser_global_test.o `test -f 'parser_global_test.cpp' || echo '$(srcdir)/'`parser_global_test.cpp + +parser_global_test-parser_global_test.obj: parser_global_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(parser_global_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT parser_global_test-parser_global_test.obj -MD -MP -MF $(DEPDIR)/parser_global_test-parser_global_test.Tpo -c -o parser_global_test-parser_global_test.obj `if test -f 'parser_global_test.cpp'; then $(CYGPATH_W) 'parser_global_test.cpp'; else $(CYGPATH_W) '$(srcdir)/parser_global_test.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/parser_global_test-parser_global_test.Tpo $(DEPDIR)/parser_global_test-parser_global_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='parser_global_test.cpp' object='parser_global_test-parser_global_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(parser_global_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o parser_global_test-parser_global_test.obj `if test -f 'parser_global_test.cpp'; then $(CYGPATH_W) 'parser_global_test.cpp'; else $(CYGPATH_W) '$(srcdir)/parser_global_test.cpp'; fi` + +parser_test_base-parser_base_test.o: parser_base_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(parser_test_base_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT parser_test_base-parser_base_test.o -MD -MP -MF $(DEPDIR)/parser_test_base-parser_base_test.Tpo -c -o parser_test_base-parser_base_test.o `test -f 'parser_base_test.cpp' || echo '$(srcdir)/'`parser_base_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/parser_test_base-parser_base_test.Tpo $(DEPDIR)/parser_test_base-parser_base_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='parser_base_test.cpp' object='parser_test_base-parser_base_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(parser_test_base_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o parser_test_base-parser_base_test.o `test -f 'parser_base_test.cpp' || echo '$(srcdir)/'`parser_base_test.cpp + +parser_test_base-parser_base_test.obj: parser_base_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(parser_test_base_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT parser_test_base-parser_base_test.obj -MD -MP -MF $(DEPDIR)/parser_test_base-parser_base_test.Tpo -c -o parser_test_base-parser_base_test.obj `if test -f 'parser_base_test.cpp'; then $(CYGPATH_W) 'parser_base_test.cpp'; else $(CYGPATH_W) '$(srcdir)/parser_base_test.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/parser_test_base-parser_base_test.Tpo $(DEPDIR)/parser_test_base-parser_base_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='parser_base_test.cpp' object='parser_test_base-parser_base_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(parser_test_base_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o parser_test_base-parser_base_test.obj `if test -f 'parser_base_test.cpp'; then $(CYGPATH_W) 'parser_base_test.cpp'; else $(CYGPATH_W) '$(srcdir)/parser_base_test.cpp'; fi` + +parser_test_base64-base64.o: base64.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(parser_test_base64_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT parser_test_base64-base64.o -MD -MP -MF $(DEPDIR)/parser_test_base64-base64.Tpo -c -o parser_test_base64-base64.o `test -f 'base64.cpp' || echo '$(srcdir)/'`base64.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/parser_test_base64-base64.Tpo $(DEPDIR)/parser_test_base64-base64.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='base64.cpp' object='parser_test_base64-base64.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(parser_test_base64_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o parser_test_base64-base64.o `test -f 'base64.cpp' || echo '$(srcdir)/'`base64.cpp + +parser_test_base64-base64.obj: base64.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(parser_test_base64_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT parser_test_base64-base64.obj -MD -MP -MF $(DEPDIR)/parser_test_base64-base64.Tpo -c -o parser_test_base64-base64.obj `if test -f 'base64.cpp'; then $(CYGPATH_W) 'base64.cpp'; else $(CYGPATH_W) '$(srcdir)/base64.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/parser_test_base64-base64.Tpo $(DEPDIR)/parser_test_base64-base64.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='base64.cpp' object='parser_test_base64-base64.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(parser_test_base64_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o parser_test_base64-base64.obj `if test -f 'base64.cpp'; then $(CYGPATH_W) 'base64.cpp'; else $(CYGPATH_W) '$(srcdir)/base64.cpp'; fi` + +parser_test_base64-base64_test.o: base64_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(parser_test_base64_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT parser_test_base64-base64_test.o -MD -MP -MF $(DEPDIR)/parser_test_base64-base64_test.Tpo -c -o parser_test_base64-base64_test.o `test -f 'base64_test.cpp' || echo '$(srcdir)/'`base64_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/parser_test_base64-base64_test.Tpo $(DEPDIR)/parser_test_base64-base64_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='base64_test.cpp' object='parser_test_base64-base64_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(parser_test_base64_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o parser_test_base64-base64_test.o `test -f 'base64_test.cpp' || echo '$(srcdir)/'`base64_test.cpp + +parser_test_base64-base64_test.obj: base64_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(parser_test_base64_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT parser_test_base64-base64_test.obj -MD -MP -MF $(DEPDIR)/parser_test_base64-base64_test.Tpo -c -o parser_test_base64-base64_test.obj `if test -f 'base64_test.cpp'; then $(CYGPATH_W) 'base64_test.cpp'; else $(CYGPATH_W) '$(srcdir)/base64_test.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/parser_test_base64-base64_test.Tpo $(DEPDIR)/parser_test_base64-base64_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='base64_test.cpp' object='parser_test_base64-base64_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(parser_test_base64_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o parser_test_base64-base64_test.obj `if test -f 'base64_test.cpp'; then $(CYGPATH_W) 'base64_test.cpp'; else $(CYGPATH_W) '$(srcdir)/base64_test.cpp'; fi` + +parser_test_json_validation-parser_test_json_validation.o: parser_test_json_validation.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(parser_test_json_validation_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT parser_test_json_validation-parser_test_json_validation.o -MD -MP -MF $(DEPDIR)/parser_test_json_validation-parser_test_json_validation.Tpo -c -o parser_test_json_validation-parser_test_json_validation.o `test -f 'parser_test_json_validation.cpp' || echo '$(srcdir)/'`parser_test_json_validation.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/parser_test_json_validation-parser_test_json_validation.Tpo $(DEPDIR)/parser_test_json_validation-parser_test_json_validation.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='parser_test_json_validation.cpp' object='parser_test_json_validation-parser_test_json_validation.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(parser_test_json_validation_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o parser_test_json_validation-parser_test_json_validation.o `test -f 'parser_test_json_validation.cpp' || echo '$(srcdir)/'`parser_test_json_validation.cpp + +parser_test_json_validation-parser_test_json_validation.obj: parser_test_json_validation.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(parser_test_json_validation_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT parser_test_json_validation-parser_test_json_validation.obj -MD -MP -MF $(DEPDIR)/parser_test_json_validation-parser_test_json_validation.Tpo -c -o parser_test_json_validation-parser_test_json_validation.obj `if test -f 'parser_test_json_validation.cpp'; then $(CYGPATH_W) 'parser_test_json_validation.cpp'; else $(CYGPATH_W) '$(srcdir)/parser_test_json_validation.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/parser_test_json_validation-parser_test_json_validation.Tpo $(DEPDIR)/parser_test_json_validation-parser_test_json_validation.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='parser_test_json_validation.cpp' object='parser_test_json_validation-parser_test_json_validation.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(parser_test_json_validation_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o parser_test_json_validation-parser_test_json_validation.obj `if test -f 'parser_test_json_validation.cpp'; then $(CYGPATH_W) 'parser_test_json_validation.cpp'; else $(CYGPATH_W) '$(srcdir)/parser_test_json_validation.cpp'; fi` + +parser_test_numeric-parser_test_numeric.o: parser_test_numeric.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(parser_test_numeric_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT parser_test_numeric-parser_test_numeric.o -MD -MP -MF $(DEPDIR)/parser_test_numeric-parser_test_numeric.Tpo -c -o parser_test_numeric-parser_test_numeric.o `test -f 'parser_test_numeric.cpp' || echo '$(srcdir)/'`parser_test_numeric.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/parser_test_numeric-parser_test_numeric.Tpo $(DEPDIR)/parser_test_numeric-parser_test_numeric.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='parser_test_numeric.cpp' object='parser_test_numeric-parser_test_numeric.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(parser_test_numeric_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o parser_test_numeric-parser_test_numeric.o `test -f 'parser_test_numeric.cpp' || echo '$(srcdir)/'`parser_test_numeric.cpp + +parser_test_numeric-parser_test_numeric.obj: parser_test_numeric.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(parser_test_numeric_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT parser_test_numeric-parser_test_numeric.obj -MD -MP -MF $(DEPDIR)/parser_test_numeric-parser_test_numeric.Tpo -c -o parser_test_numeric-parser_test_numeric.obj `if test -f 'parser_test_numeric.cpp'; then $(CYGPATH_W) 'parser_test_numeric.cpp'; else $(CYGPATH_W) '$(srcdir)/parser_test_numeric.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/parser_test_numeric-parser_test_numeric.Tpo $(DEPDIR)/parser_test_numeric-parser_test_numeric.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='parser_test_numeric.cpp' object='parser_test_numeric-parser_test_numeric.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(parser_test_numeric_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o parser_test_numeric-parser_test_numeric.obj `if test -f 'parser_test_numeric.cpp'; then $(CYGPATH_W) 'parser_test_numeric.cpp'; else $(CYGPATH_W) '$(srcdir)/parser_test_numeric.cpp'; fi` + +parser_test_stream-stream_test.o: stream_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(parser_test_stream_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT parser_test_stream-stream_test.o -MD -MP -MF $(DEPDIR)/parser_test_stream-stream_test.Tpo -c -o parser_test_stream-stream_test.o `test -f 'stream_test.cpp' || echo '$(srcdir)/'`stream_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/parser_test_stream-stream_test.Tpo $(DEPDIR)/parser_test_stream-stream_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='stream_test.cpp' object='parser_test_stream-stream_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(parser_test_stream_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o parser_test_stream-stream_test.o `test -f 'stream_test.cpp' || echo '$(srcdir)/'`stream_test.cpp + +parser_test_stream-stream_test.obj: stream_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(parser_test_stream_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT parser_test_stream-stream_test.obj -MD -MP -MF $(DEPDIR)/parser_test_stream-stream_test.Tpo -c -o parser_test_stream-stream_test.obj `if test -f 'stream_test.cpp'; then $(CYGPATH_W) 'stream_test.cpp'; else $(CYGPATH_W) '$(srcdir)/stream_test.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/parser_test_stream-stream_test.Tpo $(DEPDIR)/parser_test_stream-stream_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='stream_test.cpp' object='parser_test_stream-stream_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(parser_test_stream_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o parser_test_stream-stream_test.obj `if test -f 'stream_test.cpp'; then $(CYGPATH_W) 'stream_test.cpp'; else $(CYGPATH_W) '$(srcdir)/stream_test.cpp'; fi` + +parser_test_string_pool-string_pool.o: string_pool.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(parser_test_string_pool_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT parser_test_string_pool-string_pool.o -MD -MP -MF $(DEPDIR)/parser_test_string_pool-string_pool.Tpo -c -o parser_test_string_pool-string_pool.o `test -f 'string_pool.cpp' || echo '$(srcdir)/'`string_pool.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/parser_test_string_pool-string_pool.Tpo $(DEPDIR)/parser_test_string_pool-string_pool.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='string_pool.cpp' object='parser_test_string_pool-string_pool.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(parser_test_string_pool_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o parser_test_string_pool-string_pool.o `test -f 'string_pool.cpp' || echo '$(srcdir)/'`string_pool.cpp + +parser_test_string_pool-string_pool.obj: string_pool.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(parser_test_string_pool_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT parser_test_string_pool-string_pool.obj -MD -MP -MF $(DEPDIR)/parser_test_string_pool-string_pool.Tpo -c -o parser_test_string_pool-string_pool.obj `if test -f 'string_pool.cpp'; then $(CYGPATH_W) 'string_pool.cpp'; else $(CYGPATH_W) '$(srcdir)/string_pool.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/parser_test_string_pool-string_pool.Tpo $(DEPDIR)/parser_test_string_pool-string_pool.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='string_pool.cpp' object='parser_test_string_pool-string_pool.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(parser_test_string_pool_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o parser_test_string_pool-string_pool.obj `if test -f 'string_pool.cpp'; then $(CYGPATH_W) 'string_pool.cpp'; else $(CYGPATH_W) '$(srcdir)/string_pool.cpp'; fi` + +parser_test_string_pool-string_pool_test.o: string_pool_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(parser_test_string_pool_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT parser_test_string_pool-string_pool_test.o -MD -MP -MF $(DEPDIR)/parser_test_string_pool-string_pool_test.Tpo -c -o parser_test_string_pool-string_pool_test.o `test -f 'string_pool_test.cpp' || echo '$(srcdir)/'`string_pool_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/parser_test_string_pool-string_pool_test.Tpo $(DEPDIR)/parser_test_string_pool-string_pool_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='string_pool_test.cpp' object='parser_test_string_pool-string_pool_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(parser_test_string_pool_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o parser_test_string_pool-string_pool_test.o `test -f 'string_pool_test.cpp' || echo '$(srcdir)/'`string_pool_test.cpp + +parser_test_string_pool-string_pool_test.obj: string_pool_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(parser_test_string_pool_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT parser_test_string_pool-string_pool_test.obj -MD -MP -MF $(DEPDIR)/parser_test_string_pool-string_pool_test.Tpo -c -o parser_test_string_pool-string_pool_test.obj `if test -f 'string_pool_test.cpp'; then $(CYGPATH_W) 'string_pool_test.cpp'; else $(CYGPATH_W) '$(srcdir)/string_pool_test.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/parser_test_string_pool-string_pool_test.Tpo $(DEPDIR)/parser_test_string_pool-string_pool_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='string_pool_test.cpp' object='parser_test_string_pool-string_pool_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(parser_test_string_pool_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o parser_test_string_pool-string_pool_test.obj `if test -f 'string_pool_test.cpp'; then $(CYGPATH_W) 'string_pool_test.cpp'; else $(CYGPATH_W) '$(srcdir)/string_pool_test.cpp'; fi` + +parser_test_threaded_json_parser-threaded_json_parser_test.o: threaded_json_parser_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(parser_test_threaded_json_parser_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT parser_test_threaded_json_parser-threaded_json_parser_test.o -MD -MP -MF $(DEPDIR)/parser_test_threaded_json_parser-threaded_json_parser_test.Tpo -c -o parser_test_threaded_json_parser-threaded_json_parser_test.o `test -f 'threaded_json_parser_test.cpp' || echo '$(srcdir)/'`threaded_json_parser_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/parser_test_threaded_json_parser-threaded_json_parser_test.Tpo $(DEPDIR)/parser_test_threaded_json_parser-threaded_json_parser_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='threaded_json_parser_test.cpp' object='parser_test_threaded_json_parser-threaded_json_parser_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(parser_test_threaded_json_parser_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o parser_test_threaded_json_parser-threaded_json_parser_test.o `test -f 'threaded_json_parser_test.cpp' || echo '$(srcdir)/'`threaded_json_parser_test.cpp + +parser_test_threaded_json_parser-threaded_json_parser_test.obj: threaded_json_parser_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(parser_test_threaded_json_parser_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT parser_test_threaded_json_parser-threaded_json_parser_test.obj -MD -MP -MF $(DEPDIR)/parser_test_threaded_json_parser-threaded_json_parser_test.Tpo -c -o parser_test_threaded_json_parser-threaded_json_parser_test.obj `if test -f 'threaded_json_parser_test.cpp'; then $(CYGPATH_W) 'threaded_json_parser_test.cpp'; else $(CYGPATH_W) '$(srcdir)/threaded_json_parser_test.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/parser_test_threaded_json_parser-threaded_json_parser_test.Tpo $(DEPDIR)/parser_test_threaded_json_parser-threaded_json_parser_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='threaded_json_parser_test.cpp' object='parser_test_threaded_json_parser-threaded_json_parser_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(parser_test_threaded_json_parser_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o parser_test_threaded_json_parser-threaded_json_parser_test.obj `if test -f 'threaded_json_parser_test.cpp'; then $(CYGPATH_W) 'threaded_json_parser_test.cpp'; else $(CYGPATH_W) '$(srcdir)/threaded_json_parser_test.cpp'; fi` + +parser_test_threaded_sax_token_parser-threaded_sax_token_parser_test.o: threaded_sax_token_parser_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(parser_test_threaded_sax_token_parser_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT parser_test_threaded_sax_token_parser-threaded_sax_token_parser_test.o -MD -MP -MF $(DEPDIR)/parser_test_threaded_sax_token_parser-threaded_sax_token_parser_test.Tpo -c -o parser_test_threaded_sax_token_parser-threaded_sax_token_parser_test.o `test -f 'threaded_sax_token_parser_test.cpp' || echo '$(srcdir)/'`threaded_sax_token_parser_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/parser_test_threaded_sax_token_parser-threaded_sax_token_parser_test.Tpo $(DEPDIR)/parser_test_threaded_sax_token_parser-threaded_sax_token_parser_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='threaded_sax_token_parser_test.cpp' object='parser_test_threaded_sax_token_parser-threaded_sax_token_parser_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(parser_test_threaded_sax_token_parser_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o parser_test_threaded_sax_token_parser-threaded_sax_token_parser_test.o `test -f 'threaded_sax_token_parser_test.cpp' || echo '$(srcdir)/'`threaded_sax_token_parser_test.cpp + +parser_test_threaded_sax_token_parser-threaded_sax_token_parser_test.obj: threaded_sax_token_parser_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(parser_test_threaded_sax_token_parser_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT parser_test_threaded_sax_token_parser-threaded_sax_token_parser_test.obj -MD -MP -MF $(DEPDIR)/parser_test_threaded_sax_token_parser-threaded_sax_token_parser_test.Tpo -c -o parser_test_threaded_sax_token_parser-threaded_sax_token_parser_test.obj `if test -f 'threaded_sax_token_parser_test.cpp'; then $(CYGPATH_W) 'threaded_sax_token_parser_test.cpp'; else $(CYGPATH_W) '$(srcdir)/threaded_sax_token_parser_test.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/parser_test_threaded_sax_token_parser-threaded_sax_token_parser_test.Tpo $(DEPDIR)/parser_test_threaded_sax_token_parser-threaded_sax_token_parser_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='threaded_sax_token_parser_test.cpp' object='parser_test_threaded_sax_token_parser-threaded_sax_token_parser_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(parser_test_threaded_sax_token_parser_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o parser_test_threaded_sax_token_parser-threaded_sax_token_parser_test.obj `if test -f 'threaded_sax_token_parser_test.cpp'; then $(CYGPATH_W) 'threaded_sax_token_parser_test.cpp'; else $(CYGPATH_W) '$(srcdir)/threaded_sax_token_parser_test.cpp'; fi` + +parser_test_xml_namespace-xml_namespace.o: xml_namespace.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(parser_test_xml_namespace_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT parser_test_xml_namespace-xml_namespace.o -MD -MP -MF $(DEPDIR)/parser_test_xml_namespace-xml_namespace.Tpo -c -o parser_test_xml_namespace-xml_namespace.o `test -f 'xml_namespace.cpp' || echo '$(srcdir)/'`xml_namespace.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/parser_test_xml_namespace-xml_namespace.Tpo $(DEPDIR)/parser_test_xml_namespace-xml_namespace.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xml_namespace.cpp' object='parser_test_xml_namespace-xml_namespace.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(parser_test_xml_namespace_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o parser_test_xml_namespace-xml_namespace.o `test -f 'xml_namespace.cpp' || echo '$(srcdir)/'`xml_namespace.cpp + +parser_test_xml_namespace-xml_namespace.obj: xml_namespace.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(parser_test_xml_namespace_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT parser_test_xml_namespace-xml_namespace.obj -MD -MP -MF $(DEPDIR)/parser_test_xml_namespace-xml_namespace.Tpo -c -o parser_test_xml_namespace-xml_namespace.obj `if test -f 'xml_namespace.cpp'; then $(CYGPATH_W) 'xml_namespace.cpp'; else $(CYGPATH_W) '$(srcdir)/xml_namespace.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/parser_test_xml_namespace-xml_namespace.Tpo $(DEPDIR)/parser_test_xml_namespace-xml_namespace.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xml_namespace.cpp' object='parser_test_xml_namespace-xml_namespace.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(parser_test_xml_namespace_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o parser_test_xml_namespace-xml_namespace.obj `if test -f 'xml_namespace.cpp'; then $(CYGPATH_W) 'xml_namespace.cpp'; else $(CYGPATH_W) '$(srcdir)/xml_namespace.cpp'; fi` + +parser_test_xml_namespace-xml_namespace_test.o: xml_namespace_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(parser_test_xml_namespace_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT parser_test_xml_namespace-xml_namespace_test.o -MD -MP -MF $(DEPDIR)/parser_test_xml_namespace-xml_namespace_test.Tpo -c -o parser_test_xml_namespace-xml_namespace_test.o `test -f 'xml_namespace_test.cpp' || echo '$(srcdir)/'`xml_namespace_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/parser_test_xml_namespace-xml_namespace_test.Tpo $(DEPDIR)/parser_test_xml_namespace-xml_namespace_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xml_namespace_test.cpp' object='parser_test_xml_namespace-xml_namespace_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(parser_test_xml_namespace_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o parser_test_xml_namespace-xml_namespace_test.o `test -f 'xml_namespace_test.cpp' || echo '$(srcdir)/'`xml_namespace_test.cpp + +parser_test_xml_namespace-xml_namespace_test.obj: xml_namespace_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(parser_test_xml_namespace_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT parser_test_xml_namespace-xml_namespace_test.obj -MD -MP -MF $(DEPDIR)/parser_test_xml_namespace-xml_namespace_test.Tpo -c -o parser_test_xml_namespace-xml_namespace_test.obj `if test -f 'xml_namespace_test.cpp'; then $(CYGPATH_W) 'xml_namespace_test.cpp'; else $(CYGPATH_W) '$(srcdir)/xml_namespace_test.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/parser_test_xml_namespace-xml_namespace_test.Tpo $(DEPDIR)/parser_test_xml_namespace-xml_namespace_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xml_namespace_test.cpp' object='parser_test_xml_namespace-xml_namespace_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(parser_test_xml_namespace_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o parser_test_xml_namespace-xml_namespace_test.obj `if test -f 'xml_namespace_test.cpp'; then $(CYGPATH_W) 'xml_namespace_test.cpp'; else $(CYGPATH_W) '$(srcdir)/xml_namespace_test.cpp'; fi` + +parser_test_xml_validation-parser_test_xml_validation.o: parser_test_xml_validation.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(parser_test_xml_validation_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT parser_test_xml_validation-parser_test_xml_validation.o -MD -MP -MF $(DEPDIR)/parser_test_xml_validation-parser_test_xml_validation.Tpo -c -o parser_test_xml_validation-parser_test_xml_validation.o `test -f 'parser_test_xml_validation.cpp' || echo '$(srcdir)/'`parser_test_xml_validation.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/parser_test_xml_validation-parser_test_xml_validation.Tpo $(DEPDIR)/parser_test_xml_validation-parser_test_xml_validation.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='parser_test_xml_validation.cpp' object='parser_test_xml_validation-parser_test_xml_validation.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(parser_test_xml_validation_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o parser_test_xml_validation-parser_test_xml_validation.o `test -f 'parser_test_xml_validation.cpp' || echo '$(srcdir)/'`parser_test_xml_validation.cpp + +parser_test_xml_validation-parser_test_xml_validation.obj: parser_test_xml_validation.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(parser_test_xml_validation_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT parser_test_xml_validation-parser_test_xml_validation.obj -MD -MP -MF $(DEPDIR)/parser_test_xml_validation-parser_test_xml_validation.Tpo -c -o parser_test_xml_validation-parser_test_xml_validation.obj `if test -f 'parser_test_xml_validation.cpp'; then $(CYGPATH_W) 'parser_test_xml_validation.cpp'; else $(CYGPATH_W) '$(srcdir)/parser_test_xml_validation.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/parser_test_xml_validation-parser_test_xml_validation.Tpo $(DEPDIR)/parser_test_xml_validation-parser_test_xml_validation.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='parser_test_xml_validation.cpp' object='parser_test_xml_validation-parser_test_xml_validation.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(parser_test_xml_validation_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o parser_test_xml_validation-parser_test_xml_validation.obj `if test -f 'parser_test_xml_validation.cpp'; then $(CYGPATH_W) 'parser_test_xml_validation.cpp'; else $(CYGPATH_W) '$(srcdir)/parser_test_xml_validation.cpp'; fi` + +parser_test_zip_archive-zip_archive_test.o: zip_archive_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(parser_test_zip_archive_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT parser_test_zip_archive-zip_archive_test.o -MD -MP -MF $(DEPDIR)/parser_test_zip_archive-zip_archive_test.Tpo -c -o parser_test_zip_archive-zip_archive_test.o `test -f 'zip_archive_test.cpp' || echo '$(srcdir)/'`zip_archive_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/parser_test_zip_archive-zip_archive_test.Tpo $(DEPDIR)/parser_test_zip_archive-zip_archive_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='zip_archive_test.cpp' object='parser_test_zip_archive-zip_archive_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(parser_test_zip_archive_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o parser_test_zip_archive-zip_archive_test.o `test -f 'zip_archive_test.cpp' || echo '$(srcdir)/'`zip_archive_test.cpp + +parser_test_zip_archive-zip_archive_test.obj: zip_archive_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(parser_test_zip_archive_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT parser_test_zip_archive-zip_archive_test.obj -MD -MP -MF $(DEPDIR)/parser_test_zip_archive-zip_archive_test.Tpo -c -o parser_test_zip_archive-zip_archive_test.obj `if test -f 'zip_archive_test.cpp'; then $(CYGPATH_W) 'zip_archive_test.cpp'; else $(CYGPATH_W) '$(srcdir)/zip_archive_test.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/parser_test_zip_archive-zip_archive_test.Tpo $(DEPDIR)/parser_test_zip_archive-zip_archive_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='zip_archive_test.cpp' object='parser_test_zip_archive-zip_archive_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(parser_test_zip_archive_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o parser_test_zip_archive-zip_archive_test.obj `if test -f 'zip_archive_test.cpp'; then $(CYGPATH_W) 'zip_archive_test.cpp'; else $(CYGPATH_W) '$(srcdir)/zip_archive_test.cpp'; fi` + +sax_ns_parser_test-sax_ns_parser_test.o: sax_ns_parser_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sax_ns_parser_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT sax_ns_parser_test-sax_ns_parser_test.o -MD -MP -MF $(DEPDIR)/sax_ns_parser_test-sax_ns_parser_test.Tpo -c -o sax_ns_parser_test-sax_ns_parser_test.o `test -f 'sax_ns_parser_test.cpp' || echo '$(srcdir)/'`sax_ns_parser_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sax_ns_parser_test-sax_ns_parser_test.Tpo $(DEPDIR)/sax_ns_parser_test-sax_ns_parser_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='sax_ns_parser_test.cpp' object='sax_ns_parser_test-sax_ns_parser_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sax_ns_parser_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o sax_ns_parser_test-sax_ns_parser_test.o `test -f 'sax_ns_parser_test.cpp' || echo '$(srcdir)/'`sax_ns_parser_test.cpp + +sax_ns_parser_test-sax_ns_parser_test.obj: sax_ns_parser_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sax_ns_parser_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT sax_ns_parser_test-sax_ns_parser_test.obj -MD -MP -MF $(DEPDIR)/sax_ns_parser_test-sax_ns_parser_test.Tpo -c -o sax_ns_parser_test-sax_ns_parser_test.obj `if test -f 'sax_ns_parser_test.cpp'; then $(CYGPATH_W) 'sax_ns_parser_test.cpp'; else $(CYGPATH_W) '$(srcdir)/sax_ns_parser_test.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sax_ns_parser_test-sax_ns_parser_test.Tpo $(DEPDIR)/sax_ns_parser_test-sax_ns_parser_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='sax_ns_parser_test.cpp' object='sax_ns_parser_test-sax_ns_parser_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sax_ns_parser_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o sax_ns_parser_test-sax_ns_parser_test.obj `if test -f 'sax_ns_parser_test.cpp'; then $(CYGPATH_W) 'sax_ns_parser_test.cpp'; else $(CYGPATH_W) '$(srcdir)/sax_ns_parser_test.cpp'; fi` + +sax_parser_test-sax_parser_test.o: sax_parser_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sax_parser_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT sax_parser_test-sax_parser_test.o -MD -MP -MF $(DEPDIR)/sax_parser_test-sax_parser_test.Tpo -c -o sax_parser_test-sax_parser_test.o `test -f 'sax_parser_test.cpp' || echo '$(srcdir)/'`sax_parser_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sax_parser_test-sax_parser_test.Tpo $(DEPDIR)/sax_parser_test-sax_parser_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='sax_parser_test.cpp' object='sax_parser_test-sax_parser_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sax_parser_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o sax_parser_test-sax_parser_test.o `test -f 'sax_parser_test.cpp' || echo '$(srcdir)/'`sax_parser_test.cpp + +sax_parser_test-sax_parser_test.obj: sax_parser_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sax_parser_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT sax_parser_test-sax_parser_test.obj -MD -MP -MF $(DEPDIR)/sax_parser_test-sax_parser_test.Tpo -c -o sax_parser_test-sax_parser_test.obj `if test -f 'sax_parser_test.cpp'; then $(CYGPATH_W) 'sax_parser_test.cpp'; else $(CYGPATH_W) '$(srcdir)/sax_parser_test.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sax_parser_test-sax_parser_test.Tpo $(DEPDIR)/sax_parser_test-sax_parser_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='sax_parser_test.cpp' object='sax_parser_test-sax_parser_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sax_parser_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o sax_parser_test-sax_parser_test.obj `if test -f 'sax_parser_test.cpp'; then $(CYGPATH_W) 'sax_parser_test.cpp'; else $(CYGPATH_W) '$(srcdir)/sax_parser_test.cpp'; fi` + +sax_token_parser_test-sax_token_parser_test.o: sax_token_parser_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sax_token_parser_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT sax_token_parser_test-sax_token_parser_test.o -MD -MP -MF $(DEPDIR)/sax_token_parser_test-sax_token_parser_test.Tpo -c -o sax_token_parser_test-sax_token_parser_test.o `test -f 'sax_token_parser_test.cpp' || echo '$(srcdir)/'`sax_token_parser_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sax_token_parser_test-sax_token_parser_test.Tpo $(DEPDIR)/sax_token_parser_test-sax_token_parser_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='sax_token_parser_test.cpp' object='sax_token_parser_test-sax_token_parser_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sax_token_parser_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o sax_token_parser_test-sax_token_parser_test.o `test -f 'sax_token_parser_test.cpp' || echo '$(srcdir)/'`sax_token_parser_test.cpp + +sax_token_parser_test-sax_token_parser_test.obj: sax_token_parser_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sax_token_parser_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT sax_token_parser_test-sax_token_parser_test.obj -MD -MP -MF $(DEPDIR)/sax_token_parser_test-sax_token_parser_test.Tpo -c -o sax_token_parser_test-sax_token_parser_test.obj `if test -f 'sax_token_parser_test.cpp'; then $(CYGPATH_W) 'sax_token_parser_test.cpp'; else $(CYGPATH_W) '$(srcdir)/sax_token_parser_test.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sax_token_parser_test-sax_token_parser_test.Tpo $(DEPDIR)/sax_token_parser_test-sax_token_parser_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='sax_token_parser_test.cpp' object='sax_token_parser_test-sax_token_parser_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sax_token_parser_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o sax_token_parser_test-sax_token_parser_test.obj `if test -f 'sax_token_parser_test.cpp'; then $(CYGPATH_W) 'sax_token_parser_test.cpp'; else $(CYGPATH_W) '$(srcdir)/sax_token_parser_test.cpp'; fi` + +types_test-types_test.o: types_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(types_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT types_test-types_test.o -MD -MP -MF $(DEPDIR)/types_test-types_test.Tpo -c -o types_test-types_test.o `test -f 'types_test.cpp' || echo '$(srcdir)/'`types_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/types_test-types_test.Tpo $(DEPDIR)/types_test-types_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='types_test.cpp' object='types_test-types_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(types_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o types_test-types_test.o `test -f 'types_test.cpp' || echo '$(srcdir)/'`types_test.cpp + +types_test-types_test.obj: types_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(types_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT types_test-types_test.obj -MD -MP -MF $(DEPDIR)/types_test-types_test.Tpo -c -o types_test-types_test.obj `if test -f 'types_test.cpp'; then $(CYGPATH_W) 'types_test.cpp'; else $(CYGPATH_W) '$(srcdir)/types_test.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/types_test-types_test.Tpo $(DEPDIR)/types_test-types_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='types_test.cpp' object='types_test-types_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(types_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o types_test-types_test.obj `if test -f 'types_test.cpp'; then $(CYGPATH_W) 'types_test.cpp'; else $(CYGPATH_W) '$(srcdir)/types_test.cpp'; fi` + +utf8_test-utf8.o: utf8.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(utf8_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT utf8_test-utf8.o -MD -MP -MF $(DEPDIR)/utf8_test-utf8.Tpo -c -o utf8_test-utf8.o `test -f 'utf8.cpp' || echo '$(srcdir)/'`utf8.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/utf8_test-utf8.Tpo $(DEPDIR)/utf8_test-utf8.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='utf8.cpp' object='utf8_test-utf8.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(utf8_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o utf8_test-utf8.o `test -f 'utf8.cpp' || echo '$(srcdir)/'`utf8.cpp + +utf8_test-utf8.obj: utf8.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(utf8_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT utf8_test-utf8.obj -MD -MP -MF $(DEPDIR)/utf8_test-utf8.Tpo -c -o utf8_test-utf8.obj `if test -f 'utf8.cpp'; then $(CYGPATH_W) 'utf8.cpp'; else $(CYGPATH_W) '$(srcdir)/utf8.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/utf8_test-utf8.Tpo $(DEPDIR)/utf8_test-utf8.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='utf8.cpp' object='utf8_test-utf8.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(utf8_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o utf8_test-utf8.obj `if test -f 'utf8.cpp'; then $(CYGPATH_W) 'utf8.cpp'; else $(CYGPATH_W) '$(srcdir)/utf8.cpp'; fi` + +utf8_test-utf8_test.o: utf8_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(utf8_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT utf8_test-utf8_test.o -MD -MP -MF $(DEPDIR)/utf8_test-utf8_test.Tpo -c -o utf8_test-utf8_test.o `test -f 'utf8_test.cpp' || echo '$(srcdir)/'`utf8_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/utf8_test-utf8_test.Tpo $(DEPDIR)/utf8_test-utf8_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='utf8_test.cpp' object='utf8_test-utf8_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(utf8_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o utf8_test-utf8_test.o `test -f 'utf8_test.cpp' || echo '$(srcdir)/'`utf8_test.cpp + +utf8_test-utf8_test.obj: utf8_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(utf8_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT utf8_test-utf8_test.obj -MD -MP -MF $(DEPDIR)/utf8_test-utf8_test.Tpo -c -o utf8_test-utf8_test.obj `if test -f 'utf8_test.cpp'; then $(CYGPATH_W) 'utf8_test.cpp'; else $(CYGPATH_W) '$(srcdir)/utf8_test.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/utf8_test-utf8_test.Tpo $(DEPDIR)/utf8_test-utf8_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='utf8_test.cpp' object='utf8_test-utf8_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(utf8_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o utf8_test-utf8_test.obj `if test -f 'utf8_test.cpp'; then $(CYGPATH_W) 'utf8_test.cpp'; else $(CYGPATH_W) '$(srcdir)/utf8_test.cpp'; fi` + +xml_writer_test-xml_writer_test.o: xml_writer_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xml_writer_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT xml_writer_test-xml_writer_test.o -MD -MP -MF $(DEPDIR)/xml_writer_test-xml_writer_test.Tpo -c -o xml_writer_test-xml_writer_test.o `test -f 'xml_writer_test.cpp' || echo '$(srcdir)/'`xml_writer_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xml_writer_test-xml_writer_test.Tpo $(DEPDIR)/xml_writer_test-xml_writer_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xml_writer_test.cpp' object='xml_writer_test-xml_writer_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xml_writer_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o xml_writer_test-xml_writer_test.o `test -f 'xml_writer_test.cpp' || echo '$(srcdir)/'`xml_writer_test.cpp + +xml_writer_test-xml_writer_test.obj: xml_writer_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xml_writer_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT xml_writer_test-xml_writer_test.obj -MD -MP -MF $(DEPDIR)/xml_writer_test-xml_writer_test.Tpo -c -o xml_writer_test-xml_writer_test.obj `if test -f 'xml_writer_test.cpp'; then $(CYGPATH_W) 'xml_writer_test.cpp'; else $(CYGPATH_W) '$(srcdir)/xml_writer_test.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xml_writer_test-xml_writer_test.Tpo $(DEPDIR)/xml_writer_test-xml_writer_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xml_writer_test.cpp' object='xml_writer_test-xml_writer_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xml_writer_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o xml_writer_test-xml_writer_test.obj `if test -f 'xml_writer_test.cpp'; then $(CYGPATH_W) 'xml_writer_test.cpp'; else $(CYGPATH_W) '$(srcdir)/xml_writer_test.cpp'; fi` + +yaml_parser_test-yaml_parser_test.o: yaml_parser_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(yaml_parser_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT yaml_parser_test-yaml_parser_test.o -MD -MP -MF $(DEPDIR)/yaml_parser_test-yaml_parser_test.Tpo -c -o yaml_parser_test-yaml_parser_test.o `test -f 'yaml_parser_test.cpp' || echo '$(srcdir)/'`yaml_parser_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/yaml_parser_test-yaml_parser_test.Tpo $(DEPDIR)/yaml_parser_test-yaml_parser_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='yaml_parser_test.cpp' object='yaml_parser_test-yaml_parser_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(yaml_parser_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o yaml_parser_test-yaml_parser_test.o `test -f 'yaml_parser_test.cpp' || echo '$(srcdir)/'`yaml_parser_test.cpp + +yaml_parser_test-yaml_parser_test.obj: yaml_parser_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(yaml_parser_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT yaml_parser_test-yaml_parser_test.obj -MD -MP -MF $(DEPDIR)/yaml_parser_test-yaml_parser_test.Tpo -c -o yaml_parser_test-yaml_parser_test.obj `if test -f 'yaml_parser_test.cpp'; then $(CYGPATH_W) 'yaml_parser_test.cpp'; else $(CYGPATH_W) '$(srcdir)/yaml_parser_test.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/yaml_parser_test-yaml_parser_test.Tpo $(DEPDIR)/yaml_parser_test-yaml_parser_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='yaml_parser_test.cpp' object='yaml_parser_test-yaml_parser_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(yaml_parser_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o yaml_parser_test-yaml_parser_test.obj `if test -f 'yaml_parser_test.cpp'; then $(CYGPATH_W) 'yaml_parser_test.cpp'; else $(CYGPATH_W) '$(srcdir)/yaml_parser_test.cpp'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +check-valgrind-local: +check-valgrind-memcheck-local: +check-valgrind-helgrind-local: +check-valgrind-drd-local: +check-valgrind-sgcheck-local: + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +# Recover from deleted '.trs' file; this should ensure that +# "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create +# both 'foo.log' and 'foo.trs'. Break the recipe in two subshells +# to avoid problems with "make -n". +.log.trs: + rm -f $< $@ + $(MAKE) $(AM_MAKEFLAGS) $< + +# Leading 'am--fnord' is there to ensure the list of targets does not +# expand to empty, as could happen e.g. with make check TESTS=''. +am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) +am--force-recheck: + @: + +$(TEST_SUITE_LOG): $(TEST_LOGS) + @$(am__set_TESTS_bases); \ + am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ + redo_bases=`for i in $$bases; do \ + am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ + done`; \ + if test -n "$$redo_bases"; then \ + redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ + redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ + if $(am__make_dryrun); then :; else \ + rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ + fi; \ + fi; \ + if test -n "$$am__remaking_logs"; then \ + echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ + "recursion detected" >&2; \ + elif test -n "$$redo_logs"; then \ + am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ + fi; \ + if $(am__make_dryrun); then :; else \ + st=0; \ + errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ + for i in $$redo_bases; do \ + test -f $$i.trs && test -r $$i.trs \ + || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ + test -f $$i.log && test -r $$i.log \ + || { echo "$$errmsg $$i.log" >&2; st=1; }; \ + done; \ + test $$st -eq 0 || exit 1; \ + fi + @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ + ws='[ ]'; \ + results=`for b in $$bases; do echo $$b.trs; done`; \ + test -n "$$results" || results=/dev/null; \ + all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ + pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ + fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ + skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ + xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ + xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ + error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ + if test `expr $$fail + $$xpass + $$error` -eq 0; then \ + success=true; \ + else \ + success=false; \ + fi; \ + br='==================='; br=$$br$$br$$br$$br; \ + result_count () \ + { \ + if test x"$$1" = x"--maybe-color"; then \ + maybe_colorize=yes; \ + elif test x"$$1" = x"--no-color"; then \ + maybe_colorize=no; \ + else \ + echo "$@: invalid 'result_count' usage" >&2; exit 4; \ + fi; \ + shift; \ + desc=$$1 count=$$2; \ + if test $$maybe_colorize = yes && test $$count -gt 0; then \ + color_start=$$3 color_end=$$std; \ + else \ + color_start= color_end=; \ + fi; \ + echo "$${color_start}# $$desc $$count$${color_end}"; \ + }; \ + create_testsuite_report () \ + { \ + result_count $$1 "TOTAL:" $$all "$$brg"; \ + result_count $$1 "PASS: " $$pass "$$grn"; \ + result_count $$1 "SKIP: " $$skip "$$blu"; \ + result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ + result_count $$1 "FAIL: " $$fail "$$red"; \ + result_count $$1 "XPASS:" $$xpass "$$red"; \ + result_count $$1 "ERROR:" $$error "$$mgn"; \ + }; \ + { \ + echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ + $(am__rst_title); \ + create_testsuite_report --no-color; \ + echo; \ + echo ".. contents:: :depth: 2"; \ + echo; \ + for b in $$bases; do echo $$b; done \ + | $(am__create_global_log); \ + } >$(TEST_SUITE_LOG).tmp || exit 1; \ + mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ + if $$success; then \ + col="$$grn"; \ + else \ + col="$$red"; \ + test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ + fi; \ + echo "$${col}$$br$${std}"; \ + echo "$${col}Testsuite summary"$(AM_TESTSUITE_SUMMARY_HEADER)"$${std}"; \ + echo "$${col}$$br$${std}"; \ + create_testsuite_report --maybe-color; \ + echo "$$col$$br$$std"; \ + if $$success; then :; else \ + echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ + if test -n "$(PACKAGE_BUGREPORT)"; then \ + echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ + fi; \ + echo "$$col$$br$$std"; \ + fi; \ + $$success || exit 1 + +check-TESTS: + @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list + @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + trs_list=`for i in $$bases; do echo $$i.trs; done`; \ + log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ + exit $$?; +recheck: all + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + bases=`for i in $$bases; do echo $$i; done \ + | $(am__list_recheck_tests)` || exit 1; \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + log_list=`echo $$log_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ + am__force_recheck=am--force-recheck \ + TEST_LOGS="$$log_list"; \ + exit $$? +css-parser-test.log: css-parser-test$(EXEEXT) + @p='css-parser-test$(EXEEXT)'; \ + b='css-parser-test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +csv-parser-test.log: csv-parser-test$(EXEEXT) + @p='csv-parser-test$(EXEEXT)'; \ + b='csv-parser-test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +json-parser-test.log: json-parser-test$(EXEEXT) + @p='json-parser-test$(EXEEXT)'; \ + b='json-parser-test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +parser-global-test.log: parser-global-test$(EXEEXT) + @p='parser-global-test$(EXEEXT)'; \ + b='parser-global-test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +parser-test-base.log: parser-test-base$(EXEEXT) + @p='parser-test-base$(EXEEXT)'; \ + b='parser-test-base'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +parser-test-base64.log: parser-test-base64$(EXEEXT) + @p='parser-test-base64$(EXEEXT)'; \ + b='parser-test-base64'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +parser-test-json-validation.log: parser-test-json-validation$(EXEEXT) + @p='parser-test-json-validation$(EXEEXT)'; \ + b='parser-test-json-validation'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +parser-test-numeric.log: parser-test-numeric$(EXEEXT) + @p='parser-test-numeric$(EXEEXT)'; \ + b='parser-test-numeric'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +parser-test-stream.log: parser-test-stream$(EXEEXT) + @p='parser-test-stream$(EXEEXT)'; \ + b='parser-test-stream'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +parser-test-string-pool.log: parser-test-string-pool$(EXEEXT) + @p='parser-test-string-pool$(EXEEXT)'; \ + b='parser-test-string-pool'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +parser-test-threaded-json-parser.log: parser-test-threaded-json-parser$(EXEEXT) + @p='parser-test-threaded-json-parser$(EXEEXT)'; \ + b='parser-test-threaded-json-parser'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +parser-test-threaded-sax-token-parser.log: parser-test-threaded-sax-token-parser$(EXEEXT) + @p='parser-test-threaded-sax-token-parser$(EXEEXT)'; \ + b='parser-test-threaded-sax-token-parser'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +parser-test-xml-namespace.log: parser-test-xml-namespace$(EXEEXT) + @p='parser-test-xml-namespace$(EXEEXT)'; \ + b='parser-test-xml-namespace'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +parser-test-xml-validation.log: parser-test-xml-validation$(EXEEXT) + @p='parser-test-xml-validation$(EXEEXT)'; \ + b='parser-test-xml-validation'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +parser-test-zip-archive.log: parser-test-zip-archive$(EXEEXT) + @p='parser-test-zip-archive$(EXEEXT)'; \ + b='parser-test-zip-archive'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +sax-ns-parser-test.log: sax-ns-parser-test$(EXEEXT) + @p='sax-ns-parser-test$(EXEEXT)'; \ + b='sax-ns-parser-test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +sax-parser-test.log: sax-parser-test$(EXEEXT) + @p='sax-parser-test$(EXEEXT)'; \ + b='sax-parser-test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +sax-token-parser-test.log: sax-token-parser-test$(EXEEXT) + @p='sax-token-parser-test$(EXEEXT)'; \ + b='sax-token-parser-test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +types-test.log: types-test$(EXEEXT) + @p='types-test$(EXEEXT)'; \ + b='types-test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +utf8-test.log: utf8-test$(EXEEXT) + @p='utf8-test$(EXEEXT)'; \ + b='utf8-test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +yaml-parser-test.log: yaml-parser-test$(EXEEXT) + @p='yaml-parser-test$(EXEEXT)'; \ + b='yaml-parser-test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +xml-writer-test.log: xml-writer-test$(EXEEXT) + @p='xml-writer-test$(EXEEXT)'; \ + b='xml-writer-test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +.test.log: + @p='$<'; \ + $(am__set_b); \ + $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +@am__EXEEXT_TRUE@.test$(EXEEXT).log: +@am__EXEEXT_TRUE@ @p='$<'; \ +@am__EXEEXT_TRUE@ $(am__set_b); \ +@am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ +@am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ +@am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ +@am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) check-TESTS +check: check-am +all-am: Makefile $(LTLIBRARIES) +install-EXTRAPROGRAMS: install-libLTLIBRARIES + +installdirs: + for dir in "$(DESTDIR)$(libdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) + -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) + -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +check-valgrind: check-valgrind-am + +check-valgrind-am: check-valgrind-local + +check-valgrind-drd: check-valgrind-drd-am + +check-valgrind-drd-am: check-valgrind-drd-local + +check-valgrind-helgrind: check-valgrind-helgrind-am + +check-valgrind-helgrind-am: check-valgrind-helgrind-local + +check-valgrind-memcheck: check-valgrind-memcheck-am + +check-valgrind-memcheck-am: check-valgrind-memcheck-local + +check-valgrind-sgcheck: check-valgrind-sgcheck-am + +check-valgrind-sgcheck-am: check-valgrind-sgcheck-local + +clean: clean-am + +clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/base64.Plo + -rm -f ./$(DEPDIR)/cell_buffer.Plo + -rm -f ./$(DEPDIR)/css_parser_base.Plo + -rm -f ./$(DEPDIR)/css_parser_test-css_parser_test.Po + -rm -f ./$(DEPDIR)/css_types.Plo + -rm -f ./$(DEPDIR)/csv_parser_base.Plo + -rm -f ./$(DEPDIR)/csv_parser_test-csv_parser_test.Po + -rm -f ./$(DEPDIR)/exception.Plo + -rm -f ./$(DEPDIR)/json_global.Plo + -rm -f ./$(DEPDIR)/json_parser_base.Plo + -rm -f ./$(DEPDIR)/json_parser_test-json_parser_test.Po + -rm -f ./$(DEPDIR)/json_parser_thread.Plo + -rm -f ./$(DEPDIR)/parser_base.Plo + -rm -f ./$(DEPDIR)/parser_global.Plo + -rm -f ./$(DEPDIR)/parser_global_test-parser_global_test.Po + -rm -f ./$(DEPDIR)/parser_test_base-parser_base_test.Po + -rm -f ./$(DEPDIR)/parser_test_base64-base64.Po + -rm -f ./$(DEPDIR)/parser_test_base64-base64_test.Po + -rm -f ./$(DEPDIR)/parser_test_json_validation-parser_test_json_validation.Po + -rm -f ./$(DEPDIR)/parser_test_numeric-parser_test_numeric.Po + -rm -f ./$(DEPDIR)/parser_test_stream-stream_test.Po + -rm -f ./$(DEPDIR)/parser_test_string_pool-string_pool.Po + -rm -f ./$(DEPDIR)/parser_test_string_pool-string_pool_test.Po + -rm -f ./$(DEPDIR)/parser_test_threaded_json_parser-threaded_json_parser_test.Po + -rm -f ./$(DEPDIR)/parser_test_threaded_sax_token_parser-threaded_sax_token_parser_test.Po + -rm -f ./$(DEPDIR)/parser_test_xml_namespace-xml_namespace.Po + -rm -f ./$(DEPDIR)/parser_test_xml_namespace-xml_namespace_test.Po + -rm -f ./$(DEPDIR)/parser_test_xml_validation-parser_test_xml_validation.Po + -rm -f ./$(DEPDIR)/parser_test_zip_archive-zip_archive_test.Po + -rm -f ./$(DEPDIR)/sax_ns_parser_test-sax_ns_parser_test.Po + -rm -f ./$(DEPDIR)/sax_parser_base.Plo + -rm -f ./$(DEPDIR)/sax_parser_test-sax_parser_test.Po + -rm -f ./$(DEPDIR)/sax_token_parser.Plo + -rm -f ./$(DEPDIR)/sax_token_parser_test-sax_token_parser_test.Po + -rm -f ./$(DEPDIR)/sax_token_parser_thread.Plo + -rm -f ./$(DEPDIR)/stream.Plo + -rm -f ./$(DEPDIR)/string_pool.Plo + -rm -f ./$(DEPDIR)/tokens.Plo + -rm -f ./$(DEPDIR)/types.Plo + -rm -f ./$(DEPDIR)/types_test-types_test.Po + -rm -f ./$(DEPDIR)/utf8.Plo + -rm -f ./$(DEPDIR)/utf8_test-utf8.Po + -rm -f ./$(DEPDIR)/utf8_test-utf8_test.Po + -rm -f ./$(DEPDIR)/xml_namespace.Plo + -rm -f ./$(DEPDIR)/xml_writer.Plo + -rm -f ./$(DEPDIR)/xml_writer_test-xml_writer_test.Po + -rm -f ./$(DEPDIR)/yaml_parser_base.Plo + -rm -f ./$(DEPDIR)/yaml_parser_test-yaml_parser_test.Po + -rm -f ./$(DEPDIR)/zip_archive.Plo + -rm -f ./$(DEPDIR)/zip_archive_stream.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-local distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-libLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/base64.Plo + -rm -f ./$(DEPDIR)/cell_buffer.Plo + -rm -f ./$(DEPDIR)/css_parser_base.Plo + -rm -f ./$(DEPDIR)/css_parser_test-css_parser_test.Po + -rm -f ./$(DEPDIR)/css_types.Plo + -rm -f ./$(DEPDIR)/csv_parser_base.Plo + -rm -f ./$(DEPDIR)/csv_parser_test-csv_parser_test.Po + -rm -f ./$(DEPDIR)/exception.Plo + -rm -f ./$(DEPDIR)/json_global.Plo + -rm -f ./$(DEPDIR)/json_parser_base.Plo + -rm -f ./$(DEPDIR)/json_parser_test-json_parser_test.Po + -rm -f ./$(DEPDIR)/json_parser_thread.Plo + -rm -f ./$(DEPDIR)/parser_base.Plo + -rm -f ./$(DEPDIR)/parser_global.Plo + -rm -f ./$(DEPDIR)/parser_global_test-parser_global_test.Po + -rm -f ./$(DEPDIR)/parser_test_base-parser_base_test.Po + -rm -f ./$(DEPDIR)/parser_test_base64-base64.Po + -rm -f ./$(DEPDIR)/parser_test_base64-base64_test.Po + -rm -f ./$(DEPDIR)/parser_test_json_validation-parser_test_json_validation.Po + -rm -f ./$(DEPDIR)/parser_test_numeric-parser_test_numeric.Po + -rm -f ./$(DEPDIR)/parser_test_stream-stream_test.Po + -rm -f ./$(DEPDIR)/parser_test_string_pool-string_pool.Po + -rm -f ./$(DEPDIR)/parser_test_string_pool-string_pool_test.Po + -rm -f ./$(DEPDIR)/parser_test_threaded_json_parser-threaded_json_parser_test.Po + -rm -f ./$(DEPDIR)/parser_test_threaded_sax_token_parser-threaded_sax_token_parser_test.Po + -rm -f ./$(DEPDIR)/parser_test_xml_namespace-xml_namespace.Po + -rm -f ./$(DEPDIR)/parser_test_xml_namespace-xml_namespace_test.Po + -rm -f ./$(DEPDIR)/parser_test_xml_validation-parser_test_xml_validation.Po + -rm -f ./$(DEPDIR)/parser_test_zip_archive-zip_archive_test.Po + -rm -f ./$(DEPDIR)/sax_ns_parser_test-sax_ns_parser_test.Po + -rm -f ./$(DEPDIR)/sax_parser_base.Plo + -rm -f ./$(DEPDIR)/sax_parser_test-sax_parser_test.Po + -rm -f ./$(DEPDIR)/sax_token_parser.Plo + -rm -f ./$(DEPDIR)/sax_token_parser_test-sax_token_parser_test.Po + -rm -f ./$(DEPDIR)/sax_token_parser_thread.Plo + -rm -f ./$(DEPDIR)/stream.Plo + -rm -f ./$(DEPDIR)/string_pool.Plo + -rm -f ./$(DEPDIR)/tokens.Plo + -rm -f ./$(DEPDIR)/types.Plo + -rm -f ./$(DEPDIR)/types_test-types_test.Po + -rm -f ./$(DEPDIR)/utf8.Plo + -rm -f ./$(DEPDIR)/utf8_test-utf8.Po + -rm -f ./$(DEPDIR)/utf8_test-utf8_test.Po + -rm -f ./$(DEPDIR)/xml_namespace.Plo + -rm -f ./$(DEPDIR)/xml_writer.Plo + -rm -f ./$(DEPDIR)/xml_writer_test-xml_writer_test.Po + -rm -f ./$(DEPDIR)/yaml_parser_base.Plo + -rm -f ./$(DEPDIR)/yaml_parser_test-yaml_parser_test.Po + -rm -f ./$(DEPDIR)/zip_archive.Plo + -rm -f ./$(DEPDIR)/zip_archive_stream.Plo + -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-libLTLIBRARIES + +.MAKE: check-am install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-TESTS \ + check-am check-valgrind-am check-valgrind-drd-am \ + check-valgrind-drd-local check-valgrind-helgrind-am \ + check-valgrind-helgrind-local check-valgrind-local \ + check-valgrind-memcheck-am check-valgrind-memcheck-local \ + check-valgrind-sgcheck-am check-valgrind-sgcheck-local clean \ + clean-generic clean-libLTLIBRARIES clean-libtool cscopelist-am \ + ctags ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-local distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-libLTLIBRARIES \ + 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 recheck tags tags-am \ + uninstall uninstall-am uninstall-libLTLIBRARIES + +.PRECIOUS: Makefile + + +distclean-local: + rm -rf $(TESTS) + +@VALGRIND_CHECK_RULES@ + +# 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/src/parser/base64.cpp b/src/parser/base64.cpp new file mode 100644 index 0000000..31b8267 --- /dev/null +++ b/src/parser/base64.cpp @@ -0,0 +1,70 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <orcus/base64.hpp> + +#include <boost/archive/iterators/base64_from_binary.hpp> +#include <boost/archive/iterators/binary_from_base64.hpp> +#include <boost/archive/iterators/transform_width.hpp> + +using namespace boost::archive::iterators; + +namespace orcus { + +typedef transform_width<binary_from_base64<std::vector<char>::const_iterator>, 8, 6> to_binary; +typedef base64_from_binary<transform_width<std::vector<uint8_t>::const_iterator, 6, 8> > to_base64; + +std::vector<uint8_t> decode_from_base64(std::string_view base64) +{ + if (base64.size() < 4) + // Minimum of 4 characters required. + return std::vector<uint8_t>{}; + + std::vector<char> base64_seq{base64.data(), base64.data() + base64.size()}; + + // Check the number of trailing '='s (up to 2). + std::size_t pad_size = 0; + auto it = base64_seq.rbegin(); + for (; pad_size < 2; ++pad_size, ++it) + { + if (*it != '=') + break; + + *it = 'A'; // replace it with 'A' which is a base64 encoding of '\0'. + } + + std::vector<uint8_t> decoded{to_binary(base64_seq.begin()), to_binary(base64_seq.end())}; + decoded.erase(decoded.end() - pad_size, decoded.end()); + + return decoded; +} + +std::string encode_to_base64(const std::vector<uint8_t>& input) +{ + if (input.empty()) + return std::string{}; + + std::vector<uint8_t> inp = input; + size_t pad_size = (3 - inp.size() % 3) % 3; + inp.resize(inp.size() + pad_size); + + std::string encoded{to_base64(inp.begin()), to_base64(inp.end())}; + + auto it = encoded.rbegin(); + for (size_t i = 0; i < pad_size; ++i, ++it) + { + // 'A' is a base64 encoding of '\0' + // replace them with padding charachters '=' + if (*it == 'A') + *it = '='; + } + + return encoded; +} + +} +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/parser/base64_test.cpp b/src/parser/base64_test.cpp new file mode 100644 index 0000000..9608aef --- /dev/null +++ b/src/parser/base64_test.cpp @@ -0,0 +1,44 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "test_global.hpp" +#include "orcus/base64.hpp" + +#include <cstdlib> +#include <cstring> +#include <vector> +#include <string> +#include <iterator> + +using namespace orcus; +using namespace std; + +void test_base64_text_input(const char* p) +{ + cout << "input: '" << p << "'" << endl; + size_t n = strlen(p); + std::vector<uint8_t> input(p, p+n); + std::string encoded = encode_to_base64(input); + cout << "encoded: '" << encoded << "'" << endl; + + std::vector<uint8_t> decoded = decode_from_base64(encoded); + cout << "decoded: '"; + std::copy(decoded.begin(), decoded.end(), std::ostream_iterator<char>(cout, "")); + cout << "'" << endl; + + assert(input == decoded); +} + +int main() +{ + test_base64_text_input("Hello there"); + test_base64_text_input("World domination!!!"); + test_base64_text_input("World domination!!"); + test_base64_text_input("World domination!"); + return EXIT_SUCCESS; +} +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/parser/cell_buffer.cpp b/src/parser/cell_buffer.cpp new file mode 100644 index 0000000..6815d71 --- /dev/null +++ b/src/parser/cell_buffer.cpp @@ -0,0 +1,61 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "orcus/cell_buffer.hpp" + +#include <cstring> + +#define ORCUS_DEBUG_CELL_BUFFER 0 + +#if ORCUS_DEBUG_CELL_BUFFER +#include <iostream> +using std::cout; +using std::endl; +#endif + +namespace orcus { + +cell_buffer::cell_buffer() : m_buf_size(0) {} + +cell_buffer::~cell_buffer() = default; + +void cell_buffer::append(const char* p, size_t len) +{ + if (!len) + return; + +#if ORCUS_DEBUG_CELL_BUFFER + cout << "cell_buffer::append: '" << std::string(p, len) << "'" << endl; +#endif + + size_t size_needed = m_buf_size + len; + if (m_buffer.size() < size_needed) + m_buffer.resize(size_needed); + + char* p_dest = &m_buffer[m_buf_size]; + std::strncpy(p_dest, p, len); + m_buf_size += len; +} + +void cell_buffer::reset() +{ + m_buf_size = 0; +} + +std::string_view cell_buffer::str() const +{ + return std::string_view{m_buffer.data(), m_buf_size}; +} + +bool cell_buffer::empty() const +{ + return m_buf_size == 0; +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/parser/css_parser_base.cpp b/src/parser/css_parser_base.cpp new file mode 100644 index 0000000..128e5d4 --- /dev/null +++ b/src/parser/css_parser_base.cpp @@ -0,0 +1,337 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <orcus/css_parser_base.hpp> +#include <orcus/parser_global.hpp> + +#include "utf8.hpp" + +#include <cstring> +#include <cassert> +#include <cmath> +#include <limits> + +namespace orcus { namespace css { + +parser_base::parser_base(std::string_view content) : + orcus::parser_base(content.data(), content.size()), + m_simple_selector_count(0), + m_combinator(combinator_t::descendant) {} + +void parser_base::identifier(const char*& p, size_t& len, std::string_view extra) +{ + p = mp_char; + len = 1; + for (next(); has_char(); next(), ++len) + { + char c = cur_char(); + if (is_alpha(c) || is_numeric(c) || is_in(c, "-_")) + continue; + + if (!extra.empty()) + { + // See if the character is one of the extra allowed characters. + if (is_in(c, extra)) + continue; + } + return; + } +} + +uint8_t parser_base::parse_uint8() +{ + // 0 - 255 + int val = 0; + size_t len = 0; + for (; has_char() && len <= 3; next()) + { + char c = cur_char(); + if (!is_numeric(c)) + break; + + ++len; + val *= 10; + val += c - '0'; + } + + if (!len) + throw parse_error("parse_uint8: no digit encountered.", offset()); + + int maxval = std::numeric_limits<uint8_t>::max(); + if (val > maxval) + val = maxval; + + return static_cast<uint8_t>(val); +} + +std::string_view parser_base::parse_value() +{ + auto throw_invalid = [this](uint8_t n_bytes) + { + std::ostringstream os; + os << "parse_value: invalid utf-8 byte length (" << int(n_bytes) << ")"; + throw parse_error(os.str(), offset()); + }; + + auto check_byte_length_or_throw = [this](uint8_t n_bytes, std::size_t max_size) + { + if (std::size_t(n_bytes) > max_size) + { + std::ostringstream os; + os << "parse_value: utf-8 byte length is " << int(n_bytes) << " but only " << max_size << " bytes remaining."; + throw parse_error(os.str(), offset()); + } + }; + + std::size_t max_size = available_size(); + if (!max_size) + return {}; + + const char* p0 = mp_char; + std::size_t len = 0; + + char c = cur_char(); + uint8_t n_bytes = calc_utf8_byte_length(c); + + // any of '-+.#' is allowed as first character, while any of '-_.%' is + // allowed as second characters. + + switch (n_bytes) + { + case 1: + { + if (!is_alpha(c) && !is_numeric(c) && !is_in(c, "-+.#")) + parse_error::throw_with("parse_value: illegal first character of a value '", c, "'", offset()); + break; + } + case 2: + case 3: + case 4: + { + check_byte_length_or_throw(n_bytes, max_size); + break; + } + default: + throw_invalid(n_bytes); + } + + len += n_bytes; + next(n_bytes); + + while (has_char()) + { + c = cur_char(); + max_size = available_size(); + n_bytes = calc_utf8_byte_length(c); + + switch (n_bytes) + { + case 1: + { + if (!is_alpha(c) && !is_numeric(c) && !is_in(c, "-_.%")) + return {p0, len}; + break; + } + case 2: + case 3: + case 4: + { + check_byte_length_or_throw(n_bytes, max_size); + break; + } + default: + throw_invalid(n_bytes); + } + + len += n_bytes; + next(n_bytes); + } + + return {p0, len}; +} + +double parser_base::parse_percent() +{ + double v = parse_double_or_throw(); + + if (*mp_char != '%') + parse_error::throw_with( + "parse_percent: '%' expected after the numeric value, but '", *mp_char, "' found.", offset()); + + next(); // skip the '%'. + return v; +} + +double parser_base::parse_double_or_throw() +{ + double v = parse_double(); + if (std::isnan(v)) + throw parse_error("parse_double: failed to parse double precision value.", offset()); + return v; +} + +void parser_base::literal(const char*& p, size_t& len, char quote) +{ + assert(cur_char() == quote); + next(); + skip_to(p, len, quote); + + if (cur_char() != quote) + throw parse_error("literal: end quote has never been reached.", offset()); +} + +void parser_base::skip_to(const char*&p, size_t& len, char c) +{ + p = mp_char; + len = 0; + for (; has_char(); next(), ++len) + { + if (cur_char() == c) + return; + } +} + +void parser_base::skip_to_or_blank(const char*&p, size_t& len, std::string_view chars) +{ + p = mp_char; + len = 0; + for (; has_char(); next(), ++len) + { + if (is_blank(*mp_char) || is_in(*mp_char, chars)) + return; + } +} + +void parser_base::skip_blanks() +{ + skip(" \t\r\n"); +} + +void parser_base::skip_blanks_reverse() +{ + const char* p = mp_char + remaining_size(); + for (; p != mp_char; --p, --mp_end) + { + if (!is_blank(*p)) + break; + } +} + +void parser_base::shrink_stream() +{ + // Skip any leading blanks. + skip_blanks(); + + if (!remaining_size()) + return; + + // Skip any trailing blanks. + skip_blanks_reverse(); + + // Skip leading <!-- if present. + + const char* com_open = "<!--"; + size_t com_open_len = std::strlen(com_open); + if (remaining_size() < com_open_len) + // Not enough stream left. Bail out. + return; + + const char* p = mp_char; + for (size_t i = 0; i < com_open_len; ++i, ++p) + { + if (*p != com_open[i]) + return; + next(); + } + mp_char = p; + + // Skip leading blanks once again. + skip_blanks(); + + // Skip trailing --> if present. + const char* com_close = "-->"; + size_t com_close_len = std::strlen(com_close); + size_t n = remaining_size(); + if (n < com_close_len) + // Not enough stream left. Bail out. + return; + + p = mp_char + n; // move to the last char. + for (size_t i = com_close_len; i > 0; --i, --p) + { + if (*p != com_close[i-1]) + return; + } + mp_end -= com_close_len; + + skip_blanks_reverse(); +} + +bool parser_base::skip_comment() +{ + char c = cur_char(); + if (c != '/') + return false; + + if (remaining_size() > 2 && peek_char() == '*') + { + next(); + comment(); + skip_blanks(); + return true; + } + + return false; +} + +void parser_base::comment() +{ + assert(cur_char() == '*'); + + // Parse until we reach either EOF or '*/'. + bool has_star = false; + for (next(); has_char(); next()) + { + char c = cur_char(); + if (has_star && c == '/') + { + next(); + return; + } + has_star = (c == '*'); + } + + // EOF reached. +} + +void parser_base::skip_comments_and_blanks() +{ + skip_blanks(); + while (skip_comment()) + ; +} + +void parser_base::set_combinator(char c, css::combinator_t combinator) +{ + if (!m_simple_selector_count) + parse_error::throw_with( + "set_combinator: combinator '", c, "' encountered without parent element.", offset()); + + m_combinator = combinator; + next(); + skip_comments_and_blanks(); +} + +void parser_base::reset_before_block() +{ + m_simple_selector_count = 0; + m_combinator = css::combinator_t::descendant; +} + +}} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/parser/css_parser_test.cpp b/src/parser/css_parser_test.cpp new file mode 100644 index 0000000..95f4b1c --- /dev/null +++ b/src/parser/css_parser_test.cpp @@ -0,0 +1,28 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <orcus/css_parser.hpp> + +#include <cstring> + +void test_handler() +{ + const char* test_code = "p { background-color: white; }"; + + orcus::css_handler hdl; + orcus::css_parser<orcus::css_handler> parser(test_code, hdl); + parser.parse(); +} + +int main() +{ + test_handler(); + + return EXIT_SUCCESS; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/parser/css_types.cpp b/src/parser/css_types.cpp new file mode 100644 index 0000000..9079159 --- /dev/null +++ b/src/parser/css_types.cpp @@ -0,0 +1,198 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <orcus/css_types.hpp> +#include <mdds/sorted_string_map.hpp> +#include <mdds/global.hpp> + +#include <sstream> + +namespace orcus { namespace css { + +const pseudo_element_t pseudo_element_after = 0x0001; +const pseudo_element_t pseudo_element_before = 0x0002; +const pseudo_element_t pseudo_element_first_letter = 0x0004; +const pseudo_element_t pseudo_element_first_line = 0x0008; +const pseudo_element_t pseudo_element_selection = 0x0010; +const pseudo_element_t pseudo_element_backdrop = 0x0020; + +namespace { + +namespace pseudo_elem { + +using map_type = mdds::sorted_string_map<pseudo_element_t, mdds::string_view_map_entry>; + +// Keys must be sorted. +constexpr map_type::entry entries[] = { + { "after", pseudo_element_after }, + { "backdrop", pseudo_element_backdrop }, + { "before", pseudo_element_before }, + { "first-letter", pseudo_element_first_letter }, + { "first-line", pseudo_element_first_line }, + { "selection", pseudo_element_selection }, +}; + +const map_type& get() +{ + static map_type map(entries, std::size(entries), 0); + return map; +} + +} // namespace pseudo_elem + +} + +pseudo_element_t to_pseudo_element(std::string_view s) +{ + return pseudo_elem::get().find(s); +} + +const pseudo_class_t pseudo_class_active = 0x0000000000000001; +const pseudo_class_t pseudo_class_checked = 0x0000000000000002; +const pseudo_class_t pseudo_class_default = 0x0000000000000004; +const pseudo_class_t pseudo_class_dir = 0x0000000000000008; +const pseudo_class_t pseudo_class_disabled = 0x0000000000000010; +const pseudo_class_t pseudo_class_empty = 0x0000000000000020; +const pseudo_class_t pseudo_class_enabled = 0x0000000000000040; +const pseudo_class_t pseudo_class_first = 0x0000000000000080; +const pseudo_class_t pseudo_class_first_child = 0x0000000000000100; +const pseudo_class_t pseudo_class_first_of_type = 0x0000000000000200; +const pseudo_class_t pseudo_class_fullscreen = 0x0000000000000400; +const pseudo_class_t pseudo_class_focus = 0x0000000000000800; +const pseudo_class_t pseudo_class_hover = 0x0000000000001000; +const pseudo_class_t pseudo_class_indeterminate = 0x0000000000002000; +const pseudo_class_t pseudo_class_in_range = 0x0000000000004000; +const pseudo_class_t pseudo_class_invalid = 0x0000000000008000; +const pseudo_class_t pseudo_class_lang = 0x0000000000010000; +const pseudo_class_t pseudo_class_last_child = 0x0000000000020000; +const pseudo_class_t pseudo_class_last_of_type = 0x0000000000040000; +const pseudo_class_t pseudo_class_left = 0x0000000000080000; +const pseudo_class_t pseudo_class_link = 0x0000000000100000; +const pseudo_class_t pseudo_class_not = 0x0000000000200000; +const pseudo_class_t pseudo_class_nth_child = 0x0000000000400000; +const pseudo_class_t pseudo_class_nth_last_child = 0x0000000000800000; +const pseudo_class_t pseudo_class_nth_last_of_type = 0x0000000001000000; +const pseudo_class_t pseudo_class_nth_of_type = 0x0000000002000000; +const pseudo_class_t pseudo_class_only_child = 0x0000000004000000; +const pseudo_class_t pseudo_class_only_of_type = 0x0000000008000000; +const pseudo_class_t pseudo_class_optional = 0x0000000010000000; +const pseudo_class_t pseudo_class_out_of_range = 0x0000000020000000; +const pseudo_class_t pseudo_class_read_only = 0x0000000040000000; +const pseudo_class_t pseudo_class_read_write = 0x0000000080000000; +const pseudo_class_t pseudo_class_required = 0x0000000100000000; +const pseudo_class_t pseudo_class_right = 0x0000000200000000; +const pseudo_class_t pseudo_class_root = 0x0000000400000000; +const pseudo_class_t pseudo_class_scope = 0x0000000800000000; +const pseudo_class_t pseudo_class_target = 0x0000001000000000; +const pseudo_class_t pseudo_class_valid = 0x0000002000000000; +const pseudo_class_t pseudo_class_visited = 0x0000004000000000; + +namespace { + +namespace pseudo_class { + +using map_type = mdds::sorted_string_map<pseudo_class_t, mdds::string_view_map_entry>; + +// Keys must be sorted. +constexpr map_type::entry entries[] = { + { "active", pseudo_class_active }, + { "checked", pseudo_class_checked }, + { "default", pseudo_class_default }, + { "dir", pseudo_class_dir }, + { "disabled", pseudo_class_disabled }, + { "empty", pseudo_class_empty }, + { "enabled", pseudo_class_enabled }, + { "first", pseudo_class_first }, + { "first-child", pseudo_class_first_child }, + { "first-of-type", pseudo_class_first_of_type }, + { "focus", pseudo_class_focus }, + { "fullscreen", pseudo_class_fullscreen }, + { "hover", pseudo_class_hover }, + { "in-range", pseudo_class_in_range }, + { "indeterminate", pseudo_class_indeterminate }, + { "invalid", pseudo_class_invalid }, + { "lang", pseudo_class_lang }, + { "last-child", pseudo_class_last_child }, + { "last-of-type", pseudo_class_last_of_type }, + { "left", pseudo_class_left }, + { "link", pseudo_class_link }, + { "not", pseudo_class_not }, + { "nth-child", pseudo_class_nth_child }, + { "nth-last-child", pseudo_class_nth_last_child }, + { "nth-last-of-type", pseudo_class_nth_last_of_type }, + { "nth-of-type", pseudo_class_nth_of_type }, + { "only-child", pseudo_class_only_child }, + { "only-of-type", pseudo_class_only_of_type }, + { "optional", pseudo_class_optional }, + { "out-of-range", pseudo_class_out_of_range }, + { "read-only", pseudo_class_read_only }, + { "read-write", pseudo_class_read_write }, + { "required", pseudo_class_required }, + { "right", pseudo_class_right }, + { "root", pseudo_class_root }, + { "scope", pseudo_class_scope }, + { "target", pseudo_class_target }, + { "valid", pseudo_class_valid }, + { "visited", pseudo_class_visited }, +}; + +const map_type& get() +{ + static map_type map(entries, std::size(entries), 0); + return map; +} + +} // namespace pseudo_class + +} + +pseudo_class_t to_pseudo_class(std::string_view s) +{ + return pseudo_class::get().find(s); +} + +std::string pseudo_class_to_string(pseudo_class_t val) +{ + std::ostringstream os; + std::size_t n = std::size(pseudo_class::entries); + const pseudo_class::map_type::entry* p = pseudo_class::entries; + const pseudo_class::map_type::entry* p_end = p + n; + for (; p != p_end; ++p) + { + if (val & p->value) + os << ":" << p->key; + } + + return os.str(); +} + +namespace { + +typedef mdds::sorted_string_map<property_function_t> propfunc_map_type; + +// Keys must be sorted. +propfunc_map_type::entry propfunc_type_entries[] = { + { MDDS_ASCII("hsl"), property_function_t::hsl }, + { MDDS_ASCII("hsla"), property_function_t::hsla }, + { MDDS_ASCII("rgb"), property_function_t::rgb }, + { MDDS_ASCII("rgba"), property_function_t::rgba }, + { MDDS_ASCII("url"), property_function_t::url } +}; + +} + +property_function_t to_property_function(std::string_view s) +{ + static propfunc_map_type propfunc_map( + propfunc_type_entries, std::size(propfunc_type_entries), property_function_t::unknown); + + return propfunc_map.find(s.data(), s.size()); +} + +}} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/parser/csv_parser_base.cpp b/src/parser/csv_parser_base.cpp new file mode 100644 index 0000000..1bf914c --- /dev/null +++ b/src/parser/csv_parser_base.cpp @@ -0,0 +1,47 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "orcus/csv_parser_base.hpp" + +#include <cstring> + +namespace orcus { namespace csv { + +parser_config::parser_config() : + text_qualifier('\0'), + trim_cell_value(false) {} + +parser_base::parser_base( + std::string_view content, const csv::parser_config& config) : + ::orcus::parser_base(content.data(), content.size()), m_config(config) +{ + skip_bom(); +} + +bool parser_base::is_blank(char c) const +{ + return is_in(c, " \t"); +} + +bool parser_base::is_delim(char c) const +{ + return m_config.delimiters.find(c) != std::string::npos; +} + +bool parser_base::is_text_qualifier(char c) const +{ + return m_config.text_qualifier == c; +} + +void parser_base::skip_blanks() +{ + skip(" \t"); +} + +}} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/parser/csv_parser_test.cpp b/src/parser/csv_parser_test.cpp new file mode 100644 index 0000000..18470f0 --- /dev/null +++ b/src/parser/csv_parser_test.cpp @@ -0,0 +1,29 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <orcus/csv_parser.hpp> + +#include <cstring> + +void test_handler() +{ + const char* test_code = "1,2,3,4,5\n6,7,8,9,10\n"; + + orcus::csv_handler hdl; + orcus::csv::parser_config config; + orcus::csv_parser<orcus::csv_handler> parser(test_code, hdl, config); + parser.parse(); +} + +int main() +{ + test_handler(); + + return EXIT_SUCCESS; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/parser/exception.cpp b/src/parser/exception.cpp new file mode 100644 index 0000000..1d958fd --- /dev/null +++ b/src/parser/exception.cpp @@ -0,0 +1,141 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "orcus/exception.hpp" + +#include <sstream> + +using namespace std; + +namespace orcus { + +general_error::general_error(std::string msg) : + m_msg(std::move(msg)) +{ +} + +general_error::general_error(std::string_view cls, std::string_view msg) +{ + std::ostringstream os; + os << cls << ": " << msg; + m_msg = os.str(); +} + +general_error::~general_error() noexcept = default; + +const char* general_error::what() const noexcept +{ + return m_msg.c_str(); +} + +void general_error::append_msg(const std::string& s) +{ + m_msg += s; +} + +invalid_arg_error::invalid_arg_error(const std::string& msg) : + std::invalid_argument(msg) {} + +invalid_arg_error::~invalid_arg_error() noexcept {} + +xml_structure_error::xml_structure_error(std::string msg) : + general_error(std::move(msg)) {} + +xml_structure_error::~xml_structure_error() noexcept = default; + +json_structure_error::json_structure_error(std::string msg) : + general_error(std::move(msg)) {} + +json_structure_error::~json_structure_error() noexcept = default; + +invalid_map_error::invalid_map_error(std::string msg) : + general_error(std::move(msg)) {} + +invalid_map_error::~invalid_map_error() noexcept = default; + +value_error::value_error(std::string msg) : + general_error(std::move(msg)) {} + +value_error::~value_error() noexcept = default; + +xpath_error::xpath_error(std::string msg) : general_error(std::move(msg)) {} + +xpath_error::~xpath_error() noexcept = default; + +interface_error::interface_error(std::string msg) : general_error(std::move(msg)) {} + +interface_error::~interface_error() noexcept = default; + +namespace { + +std::string build_offset_msg(std::ptrdiff_t offset) +{ + std::ostringstream os; + os << " (offset=" << offset << ')'; + return os.str(); +} + +std::string build_message(std::string_view msg_before, char c, std::string_view msg_after) +{ + std::ostringstream os; + os << msg_before << c << msg_after; + return os.str(); +} + +std::string build_message( + std::string_view msg_before, std::string_view msg, std::string_view msg_after) +{ + std::ostringstream os; + os << msg_before << msg << msg_after; + return os.str(); +} + +} + +parse_error::parse_error(std::string_view cls, std::string_view msg, std::ptrdiff_t offset) : + general_error(cls, msg), m_offset(offset) +{ + append_msg(build_offset_msg(offset)); +} + +parse_error::parse_error(std::string msg, std::ptrdiff_t offset) : + general_error(std::move(msg)), m_offset(offset) +{ + append_msg(build_offset_msg(offset)); +} + +std::ptrdiff_t parse_error::offset() const +{ + return m_offset; +} + +void parse_error::throw_with( + std::string_view msg_before, char c, std::string_view msg_after, std::ptrdiff_t offset) +{ + throw parse_error(build_message(msg_before, c, msg_after), offset); +} + +void parse_error::throw_with( + std::string_view msg_before, std::string_view msg, std::string_view msg_after, std::ptrdiff_t offset) +{ + throw parse_error(build_message(msg_before, msg, msg_after), offset); +} + +malformed_xml_error::malformed_xml_error(std::string_view msg, std::ptrdiff_t offset) : + orcus::parse_error("malformed_xml_error", msg, offset) {} + +malformed_xml_error::~malformed_xml_error() = default; + +zip_error::zip_error(std::string_view msg) : general_error("zip_error", msg) +{ +} + +zip_error::~zip_error() = default; + +} // namespace orcus + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/parser/json_global.cpp b/src/parser/json_global.cpp new file mode 100644 index 0000000..f01f778 --- /dev/null +++ b/src/parser/json_global.cpp @@ -0,0 +1,46 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "orcus/json_global.hpp" +#include "orcus/parser_global.hpp" + +#include <sstream> + +namespace orcus { namespace json { + +namespace { + +const char backslash = '\\'; + +} + +std::string escape_string(const std::string& input) +{ + std::ostringstream os; + + for (auto it = input.begin(), ite = input.end(); it != ite; ++it) + { + char c = *it; + if (c == '"') + // Escape double quote, but not forward slash. + os << backslash; + else if (c == backslash) + { + // Escape a '\' if and only if the next character is not one of control characters. + auto itnext = it + 1; + if (itnext == ite || get_string_escape_char_type(*itnext) != string_escape_char_t::control_char) + os << backslash; + } + os << c; + } + + return os.str(); +} + +}} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/parser/json_parser_base.cpp b/src/parser/json_parser_base.cpp new file mode 100644 index 0000000..0dcdc3b --- /dev/null +++ b/src/parser/json_parser_base.cpp @@ -0,0 +1,104 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "orcus/json_parser_base.hpp" +#include "orcus/cell_buffer.hpp" +#include "numeric_parser.hpp" + +#include <cassert> +#include <cmath> + +namespace orcus { namespace json { + +namespace { + +const char* parse_numeric_json(const char* p, const char* p_end, double& value) +{ + using numeric_parser_type = detail::numeric_parser<detail::json_parser_trait>; + + numeric_parser_type parser(p, p_end); + double v = parser.parse(); + if (!std::isnan(v)) + p = parser.get_char_position(); + + value = v; + return p; +}; + +} // anonymous namespace + +struct parser_base::impl +{ + cell_buffer m_buffer; +}; + +parser_base::parser_base(std::string_view content) : + orcus::parser_base(content.data(), content.size()), mp_impl(std::make_unique<impl>()) +{ + + set_numeric_parser(parse_numeric_json); +} + +parser_base::~parser_base() {} + +void parser_base::skip_ws() +{ + skip(" \n\r\t"); +} + +void parser_base::parse_true() +{ + if (!parse_expected("true")) + throw parse_error("parse_true: boolean 'true' expected.", offset()); + + skip_ws(); +} + +void parser_base::parse_false() +{ + if (!parse_expected("false")) + throw parse_error("parse_false: boolean 'false' expected.", offset()); + + skip_ws(); +} + +void parser_base::parse_null() +{ + if (!parse_expected("null")) + throw parse_error("parse_null: null expected.", offset()); + + skip_ws(); +} + +double parser_base::parse_double_or_throw() +{ + double v = parse_double(); + if (std::isnan(v)) + throw parse_error("parse_double_or_throw: failed to parse double precision value.", offset()); + return v; +} + +parse_quoted_string_state parser_base::parse_string() +{ + assert(cur_char() == '"'); + size_t max_length = remaining_size(); + const char* p = mp_char; + parse_quoted_string_state ret = parse_double_quoted_string(p, max_length, mp_impl->m_buffer); + if (ret.has_control_character) + throw parse_error("parse_string: string contains a control character.", offset()); + + mp_char = p; + + if (ret.str) + skip_ws(); + + return ret; +} + +}} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/parser/json_parser_test.cpp b/src/parser/json_parser_test.cpp new file mode 100644 index 0000000..db64861 --- /dev/null +++ b/src/parser/json_parser_test.cpp @@ -0,0 +1,28 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <orcus/json_parser.hpp> + +#include <cstring> + +void test_handler() +{ + const char* test_code = "{\"key1\": [1,2,3,4,5], \"key2\": 12.3}"; + + orcus::json_handler hdl; + orcus::json_parser<orcus::json_handler> parser(test_code, hdl); + parser.parse(); +} + +int main() +{ + test_handler(); + + return EXIT_SUCCESS; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/parser/json_parser_thread.cpp b/src/parser/json_parser_thread.cpp new file mode 100644 index 0000000..a07bb61 --- /dev/null +++ b/src/parser/json_parser_thread.cpp @@ -0,0 +1,294 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <orcus/json_parser_thread.hpp> +#include <orcus/json_parser.hpp> +#include <orcus/string_pool.hpp> +#include <orcus/detail/parser_token_buffer.hpp> + +#include <sstream> +#include <string_view> +#include <algorithm> +#include <limits> + +namespace orcus { namespace json { + +parse_token::parse_token() : type(parse_token_t::unknown), value(0.0) {} + +parse_token::parse_token(parse_token_t _type) : type(_type), value(0.0) {} + +parse_token::parse_token(parse_token_t _type, std::string_view s) : + type(_type), value(s) +{ +} + +parse_token::parse_token(std::string_view s, std::ptrdiff_t offset) : + type(parse_token_t::parse_error), value(parse_error_value_t{s, offset}) +{ + assert(type == parse_token_t::parse_error); +} + +parse_token::parse_token(double v) : + type(parse_token_t::number), value(v) +{ +} + +parse_token::parse_token(const parse_token& other) : + type(other.type), value(other.value) +{ +} + +bool parse_token::operator== (const parse_token& other) const +{ + return type == other.type && value == other.value; +} + +bool parse_token::operator!= (const parse_token& other) const +{ + return !operator== (other); +} + +/** + * This impl class also acts as a handler for the parser. + * + */ +struct parser_thread::impl +{ + detail::thread::parser_token_buffer<parse_tokens_t> m_token_buffer; + string_pool m_pool; + parse_tokens_t m_parser_tokens; // token buffer for the parser thread. + + const char* mp_char; + size_t m_size; + + impl(const char* p, size_t n, size_t min_token_size, size_t max_token_size) : + m_token_buffer(min_token_size, max_token_size), + mp_char(p), m_size(n) + { + m_parser_tokens.reserve(min_token_size); + } + + void start() + { + try + { + json_parser<parser_thread::impl> parser({mp_char, m_size}, *this); + parser.parse(); + } + catch (const parse_error& e) + { + std::string_view s = m_pool.intern(e.what()).first; + m_parser_tokens.emplace_back(s, e.offset()); + } + + notify_and_finish(); + } + + void begin_parse() + { + m_parser_tokens.emplace_back(parse_token_t::begin_parse); + check_and_notify(); + } + + void end_parse() + { + m_parser_tokens.emplace_back(parse_token_t::end_parse); + check_and_notify(); + } + + void begin_array() + { + m_parser_tokens.emplace_back(parse_token_t::begin_array); + check_and_notify(); + } + + void end_array() + { + m_parser_tokens.emplace_back(parse_token_t::end_array); + check_and_notify(); + } + + void begin_object() + { + m_parser_tokens.emplace_back(parse_token_t::begin_object); + check_and_notify(); + } + + void object_key(std::string_view s, bool transient) + { + if (transient) + s = m_pool.intern(s).first; + + m_parser_tokens.emplace_back(parse_token_t::object_key, s); + check_and_notify(); + } + + void end_object() + { + m_parser_tokens.emplace_back(parse_token_t::end_object); + check_and_notify(); + } + + void boolean_true() + { + m_parser_tokens.emplace_back(parse_token_t::boolean_true); + check_and_notify(); + } + + void boolean_false() + { + m_parser_tokens.emplace_back(parse_token_t::boolean_false); + check_and_notify(); + } + + void null() + { + m_parser_tokens.emplace_back(parse_token_t::null); + check_and_notify(); + } + + void string(std::string_view s, bool transient) + { + if (transient) + s = m_pool.intern(s).first; + + m_parser_tokens.emplace_back(parse_token_t::string, s); + check_and_notify(); + } + + void number(double val) + { + m_parser_tokens.emplace_back(val); + check_and_notify(); + } + + void check_and_notify() + { + m_token_buffer.check_and_notify(m_parser_tokens); + } + + void notify_and_finish() + { + m_token_buffer.notify_and_finish(m_parser_tokens); + } + + bool next_tokens(parse_tokens_t& tokens) + { + return m_token_buffer.next_tokens(tokens); + } + + parser_stats get_stats() const + { + parser_stats stats; + stats.token_buffer_size_threshold = m_token_buffer.token_size_threshold(); + return stats; + } + + void swap_string_pool(string_pool& pool) + { + m_pool.swap(pool); + } +}; + +std::ostream& operator<< (std::ostream& os, const parse_tokens_t& tokens) +{ + using std::endl; + + os << "token size: " << tokens.size() << endl; + + std::for_each(tokens.begin(), tokens.end(), + [&](const parse_token& t) + { + switch (t.type) + { + case parse_token_t::begin_array: + os << "- begin_array" << endl; + break; + case parse_token_t::begin_object: + os << "- begin_object" << endl; + break; + case parse_token_t::begin_parse: + os << "- begin_parse" << endl; + break; + case parse_token_t::boolean_false: + os << "- boolean_false" << endl; + break; + case parse_token_t::boolean_true: + os << "- boolean_true" << endl; + break; + case parse_token_t::end_array: + os << "- end_array" << endl; + break; + case parse_token_t::end_object: + os << "- end_object" << endl; + break; + case parse_token_t::end_parse: + os << "- end_parse" << endl; + break; + case parse_token_t::null: + os << "- null" << endl; + break; + case parse_token_t::number: + os << "- number (v=" << std::get<double>(t.value) << ")" << endl; + break; + case parse_token_t::object_key: + os << "- object_key (v=" << std::get<std::string_view>(t.value) << ")" << endl; + break; + case parse_token_t::parse_error: + { + auto v = std::get<parse_error_value_t>(t.value); + os << "- parse_error (v=" << v.str << ", offset=" << v.offset << ")" << endl; + break; + } + case parse_token_t::string: + os << "- string (" << std::get<std::string_view>(t.value) << ")" << endl; + break; + case parse_token_t::unknown: + os << "- unknown" << endl; + break; + default: + ; + } + } + ); + + return os; +} + +parser_thread::parser_thread(const char* p, size_t n, size_t min_token_size) : + mp_impl(std::make_unique<parser_thread::impl>( + p, n, min_token_size, std::numeric_limits<size_t>::max()/2)) {} + +parser_thread::parser_thread(const char* p, size_t n, size_t min_token_size, size_t max_token_size) : + mp_impl(std::make_unique<parser_thread::impl>( + p, n, min_token_size, max_token_size)) {} + +parser_thread::~parser_thread() {} + +void parser_thread::start() +{ + mp_impl->start(); +} + +bool parser_thread::next_tokens(parse_tokens_t& tokens) +{ + return mp_impl->next_tokens(tokens); +} + +parser_stats parser_thread::get_stats() const +{ + return mp_impl->get_stats(); +} + +void parser_thread::swap_string_pool(string_pool& pool) +{ + mp_impl->swap_string_pool(pool); +} + +}} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/parser/parser_base.cpp b/src/parser/parser_base.cpp new file mode 100644 index 0000000..e49af71 --- /dev/null +++ b/src/parser/parser_base.cpp @@ -0,0 +1,222 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "orcus/parser_base.hpp" +#include "orcus/parser_global.hpp" +#include "cpu_features.hpp" + +#include <sstream> +#include <cstring> +#include <limits> +#include <cassert> +#include <algorithm> + +#ifdef __ORCUS_CPU_FEATURES +#include <immintrin.h> +#endif + +namespace orcus { + +parser_base::parser_base(const char* p, size_t n) : + mp_begin(p), mp_char(p), mp_end(p+n), + m_func_parse_numeric(parse_numeric) +{ +} + +void parser_base::prev(size_t dec) +{ + mp_char -= dec; +} + +char parser_base::peek_char(std::size_t offset) const +{ + return *(mp_char + offset); +} + +std::string_view parser_base::peek_chars(std::size_t length) const +{ + return {mp_char, length}; +} + +void parser_base::skip_bom() +{ + // Skip one or more UTF-8 BOM's. + constexpr std::string_view BOM = "\xEF\xBB\xBF"; + + while (true) + { + if (available_size() < 3) + return; + + if (peek_chars(3) != BOM) + return; + + next(3); + } +} + +void parser_base::skip(std::string_view chars_to_skip) +{ +#if defined(__ORCUS_CPU_FEATURES) && defined(__SSE4_2__) + __m128i match = _mm_loadu_si128((const __m128i*)chars_to_skip.data()); + const int mode = _SIDD_LEAST_SIGNIFICANT | _SIDD_CMP_EQUAL_ANY | _SIDD_UBYTE_OPS | _SIDD_NEGATIVE_POLARITY; + + int n_total = available_size(); + + while (n_total) + { + __m128i char_block = _mm_loadu_si128((const __m128i*)mp_char); + + // Find position of the first character that is NOT any of the + // characters to skip. + int n = std::min<int>(16, n_total); + int r = _mm_cmpestri(match, chars_to_skip.size(), char_block, n, mode); + + if (!r) + // No characters to skip. Bail out. + break; + + mp_char += r; // Move the current char position. + + if (r < 16) + // No need to move to the next segment. Stop here. + break; + + // Skip 16 chars to the next segment. + n_total -= 16; + } +#else + for (; has_char(); next()) + { + if (!is_in(*mp_char, chars_to_skip)) + break; + } +#endif +} + +void parser_base::skip_space_and_control() +{ +#if defined(__ORCUS_CPU_FEATURES) && defined(__AVX2__) + size_t n_total = available_size(); + const __m256i ws = _mm256_set1_epi8(' '); // whitespaces + const __m256i sb = _mm256_set1_epi8(0x80); // signed bit on. + + while (n_total) + { + // The 'results' stores (for each 8-bit int) 0x00 if the char is less + // than or equal to whitespace, or the char is "negative" i.e. the + // signed bit is on IOW greater than 127. + __m256i char_block = _mm256_loadu_si256(reinterpret_cast<const __m256i*>(mp_char)); + __m256i results = _mm256_cmpgt_epi8(char_block, ws); // NB: this is a signed comparison. + results = _mm256_or_si256(results, _mm256_and_si256(char_block, sb)); + int r = _mm256_movemask_epi8(results); + r = _tzcnt_u32(r); + r = std::min<size_t>(r, n_total); + + if (!r) + // No characters to skip. Bail out. + break; + + mp_char += r; // Move the current char position. + + if (r < 32) + // No need to move to the next segment. Stop here. + break; + + n_total -= 32; + } + +#elif defined(__ORCUS_CPU_FEATURES) && defined(__SSE4_2__) + __m128i match = _mm_loadu_si128((const __m128i*)"\0 "); + const int mode = _SIDD_LEAST_SIGNIFICANT | _SIDD_CMP_RANGES | _SIDD_UBYTE_OPS | _SIDD_NEGATIVE_POLARITY; + + size_t n_total = available_size(); + + while (n_total) + { + __m128i char_block = _mm_loadu_si128((const __m128i*)mp_char); + + // Find position of the first character that is NOT any of the + // characters to skip. + int n = std::min<size_t>(16u, n_total); + int r = _mm_cmpestri(match, 2, char_block, n, mode); + + if (!r) + // No characters to skip. Bail out. + break; + + mp_char += r; // Move the current char position. + + if (r < 16) + // No need to move to the next segment. Stop here. + break; + + // Skip 16 chars to the next segment. + n_total -= 16; + } +#else + for (; mp_char != mp_end && ((unsigned char)*mp_char) <= (unsigned char)' '; ++mp_char) + ; +#endif +} + +bool parser_base::parse_expected(std::string_view expected) +{ + if (expected.size() > available_size()) + return false; + +#if defined(__ORCUS_CPU_FEATURES) && defined(__SSE4_2__) + __m128i v_expected = _mm_loadu_si128((const __m128i*)expected.data()); + __m128i v_char_block = _mm_loadu_si128((const __m128i*)mp_char); + + const int mode = _SIDD_CMP_EQUAL_ORDERED | _SIDD_UBYTE_OPS | _SIDD_BIT_MASK; + __m128i res = _mm_cmpestrm(v_expected, expected.size(), v_char_block, expected.size(), mode); + int mask = _mm_cvtsi128_si32(res); + + if (mask) + mp_char += expected.size(); + + return mask; +#else + const char* p = expected.data(); + for (size_t i = 0; i < expected.size(); ++i, ++p, next()) + { + if (cur_char() != *p) + return false; + } + + return true; +#endif +} + +double parser_base::parse_double() +{ + size_t max_length = available_size(); + const char* p = mp_char; + double val; + p = m_func_parse_numeric(p, p + max_length, val); + if (p == mp_char) + return std::numeric_limits<double>::quiet_NaN(); + + mp_char = p; + return val; +} + +size_t parser_base::remaining_size() const +{ + size_t n = available_size(); + return n ? (n - 1) : 0; +} + +std::ptrdiff_t parser_base::offset() const +{ + return std::distance(mp_begin, mp_char); +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/parser/parser_base_test.cpp b/src/parser/parser_base_test.cpp new file mode 100644 index 0000000..74994da --- /dev/null +++ b/src/parser/parser_base_test.cpp @@ -0,0 +1,74 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "test_global.hpp" +#include "orcus/parser_base.hpp" + +using namespace std; +using namespace orcus; + +void test_skip_space_and_control() +{ + class _test_type : public orcus::parser_base + { + public: + _test_type(const char* p, size_t n) : orcus::parser_base(p, n) {} + + void run() + { + skip_space_and_control(); + } + + bool has_char() const + { + return orcus::parser_base::has_char(); + } + + size_t available_size() const + { + return orcus::parser_base::available_size(); + } + + char get_char() const + { + return *mp_char; + } + }; + + // Create a series of variable-legnth blank strings and make sure the + // function correctly skips all the empty characters. + + for (size_t i = 0; i < 32; ++i) + { + std::string s(i, ' '); + assert(s.size() == i); + + _test_type test(s.data(), s.size()); + assert(test.available_size() == s.size()); + + test.run(); + assert(!test.has_char()); // There should be no more characters to parse. + + s.push_back('a'); + + _test_type test2(s.data(), s.size()); + assert(test2.available_size() == s.size()); + + test2.run(); + assert(test2.has_char()); // The current position should be on the 'a'. + assert(test2.get_char() == 'a'); + } +} + +int main() +{ + test_skip_space_and_control(); + + return EXIT_SUCCESS; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/parser/parser_global.cpp b/src/parser/parser_global.cpp new file mode 100644 index 0000000..5489e21 --- /dev/null +++ b/src/parser/parser_global.cpp @@ -0,0 +1,515 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <orcus/parser_global.hpp> +#include <orcus/cell_buffer.hpp> +#include <orcus/exception.hpp> + +#include "numeric_parser.hpp" + +#include <cassert> +#include <cmath> +#include <iostream> +#include <limits> +#include <algorithm> +#include <cctype> + +namespace orcus { + +const size_t parse_quoted_string_state::error_no_closing_quote = 1; +const size_t parse_quoted_string_state::error_illegal_escape_char = 2; + +bool is_blank(char c) +{ + return is_in(c, " \t\n\r"); +} + +bool is_alpha(char c) +{ + return std::isalpha(static_cast<unsigned char>(c)); +} + +bool is_numeric(char c) +{ + return std::isdigit(static_cast<unsigned char>(c)); +} + +bool is_in(char c, std::string_view allowed) +{ +#ifdef __ORCUS_DEBUG_UTILS + if (allowed.empty()) + throw std::invalid_argument("'allowed' string should not be empty."); +#endif + auto f = [c](char c_allowed) { return c == c_allowed; }; + return std::any_of(allowed.begin(), allowed.end(), f); +} + +const char* parse_numeric(const char* p, const char* p_end, double& value) +{ + using numeric_parser_type = detail::numeric_parser<detail::generic_parser_trait>; + + numeric_parser_type parser(p, p_end); + double v = parser.parse(); + if (!std::isnan(v)) + p = parser.get_char_position(); + + value = v; + return p; +} + +const char* parse_integer(const char* p, const char* p_end, long& value) +{ + if (p >= p_end) + return p; + + long result = 0.0; + bool negative_sign = false; + + // Check for presence of a sign. + if (p != p_end) + { + switch (*p) + { + case '+': + ++p; + break; + case '-': + negative_sign = true; + ++p; + break; + default: + ; + } + } + + for (; p != p_end; ++p) + { + if (*p < '0' || '9' < *p) + { + value = negative_sign ? -result : result; + return p; + } + + result *= 10; + result += *p - '0'; + } + + value = negative_sign ? -result : result; + return p; +} + +string_escape_char_t get_string_escape_char_type(char c) +{ + switch (c) + { + case '"': + case '\\': + case '/': + return string_escape_char_t::valid; + case 'b': // backspace + case 'f': // formfeed + case 'n': // newline + case 'r': // carriage return + case 't': // horizontal tab + return string_escape_char_t::control_char; + default: + ; + } + + return string_escape_char_t::invalid; +} + +namespace { + +parse_quoted_string_state parse_string_with_escaped_char( + const char*& p, size_t max_length, const char* p_parsed, size_t n_parsed, char c, + cell_buffer& buffer) +{ + const char* p_end = p + max_length; + + parse_quoted_string_state ret; + ret.str = nullptr; + ret.length = 0; + ret.transient = true; + ret.has_control_character = false; + + // Start the buffer with the string we've parsed so far. + buffer.reset(); + if (p_parsed && n_parsed) + buffer.append(p_parsed, n_parsed); + buffer.append(&c, 1); + + ++p; + if (p == p_end) + { + ret.length = parse_quoted_string_state::error_no_closing_quote; + return ret; + } + + size_t len = 0; + const char* p_head = p; + bool escape = false; + + for (; p != p_end; ++p, ++len) + { + c = *p; + + if (escape) + { + escape = false; + + switch (get_string_escape_char_type(c)) + { + case string_escape_char_t::valid: + buffer.append(p_head, len-1); + buffer.append(&c, 1); + ++p; + len = 0; + p_head = p; + break; + case string_escape_char_t::control_char: + // do nothing on control characters. + break; + case string_escape_char_t::invalid: + default: + ret.length = parse_quoted_string_state::error_illegal_escape_char; + return ret; + } + } + + switch (*p) + { + case '"': + { + // closing quote. + buffer.append(p_head, len); + ++p; // skip the quote. + std::string_view s = buffer.str(); + ret.str = s.data(); + ret.length = s.size(); + return ret; + } + case '\\': + { + escape = true; + continue; + } + default: + ; + } + } + + ret.length = parse_quoted_string_state::error_no_closing_quote; + return ret; +} + +parse_quoted_string_state parse_single_quoted_string_buffered( + const char*& p, const char* p_end, cell_buffer& buffer) +{ + const char* p0 = p; + size_t len = 0; + char last = 0; + + parse_quoted_string_state ret; + ret.transient = true; + ret.has_control_character = false; + + for (; p != p_end; ++p) + { + if (!p0) + p0 = p; + + char c = *p; + switch (c) + { + case '\'': + { + if (last == c) + { + // Second "'" in series. This is an encoded single quote. + buffer.append(p0, len); + p0 = nullptr; + last = 0; + len = 0; + continue; + } + } + break; + default: + { + if (last == '\'') + { + buffer.append(p0, len-1); + auto s = buffer.str(); + ret.str = s.data(); + ret.length = s.size(); + return ret; + } + } + } + + last = c; + ++len; + } + + if (last == '\'') + { + buffer.append(p0, len-1); + auto s = buffer.str(); + ret.str = s.data(); + ret.length = s.size(); + return ret; + } + + ret.str = nullptr; + ret.length = parse_quoted_string_state::error_no_closing_quote; + return ret; +} + +} + +parse_quoted_string_state parse_single_quoted_string( + const char*& p, size_t max_length, cell_buffer& buffer) +{ + assert(*p == '\''); + const char* p_end = p + max_length; + ++p; + + parse_quoted_string_state ret; + ret.str = p; + ret.length = 0; + ret.transient = false; + ret.has_control_character = false; + + if (p == p_end) + { + ret.str = nullptr; + ret.length = parse_quoted_string_state::error_no_closing_quote; + return ret; + } + + char last = 0; + char c = 0; + for (; p != p_end; last = c, ++p, ++ret.length) + { + c = *p; + switch (c) + { + case '\'': + { + if (last == c) + { + // Encoded single quote. + buffer.reset(); + buffer.append(ret.str, ret.length); + ++p; + return parse_single_quoted_string_buffered(p, p_end, buffer); + } + } + break; + default: + { + if (last == '\'') + { + --ret.length; + return ret; + } + } + + } + } + + if (last == '\'') + { + --ret.length; + return ret; + } + + ret.str = nullptr; + ret.length = parse_quoted_string_state::error_no_closing_quote; + return ret; +} + +const char* parse_to_closing_single_quote(const char* p, size_t max_length) +{ + assert(*p == '\''); + const char* p_end = p + max_length; + ++p; + + if (p == p_end) + return nullptr; + + char last = 0; + for (; p != p_end; ++p) + { + char c = *p; + switch (c) + { + case '\'': + if (last == '\'') + { + last = 0; + continue; + } + break; + default: + { + if (last == '\'') + return p; + } + } + + last = c; + } + + if (last == '\'') + return p; + + return nullptr; +} + +parse_quoted_string_state parse_double_quoted_string( + const char*& p, size_t max_length, cell_buffer& buffer) +{ + if (max_length == 0 || !p || *p != '"') + throw invalid_arg_error("parse_double_quoted_string: invalid input string"); + + parse_quoted_string_state ret; + ret.str = nullptr; + ret.length = 0; + ret.transient = false; + ret.has_control_character = false; + + const char* p_end = p + max_length; + ++p; // skip the opening quote. + + ret.str = p; + + if (p == p_end) + { + // The string contains only the opening quote. + ret.str = nullptr; + ret.length = parse_quoted_string_state::error_no_closing_quote; + return ret; + } + + bool escape = false; + + for (; p != p_end; ++p, ++ret.length) + { + char c = *p; + + if (escape) + { + escape = false; + + switch (get_string_escape_char_type(c)) + { + case string_escape_char_t::valid: + return parse_string_with_escaped_char(p, max_length, ret.str, ret.length-1, c, buffer); + case string_escape_char_t::control_char: + // do nothing on control characters. + break; + case string_escape_char_t::invalid: + default: + ret.str = nullptr; + ret.length = parse_quoted_string_state::error_illegal_escape_char; + return ret; + } + } + + switch (*p) + { + case '"': + { + // closing quote. + ++p; // skip the quote. + return ret; + } + case '\\': + { + escape = true; + continue; + } + default: + ; + } + + if (0x00 <= c && c <= 0x1F) + { + // This is an unescaped control character. + ret.has_control_character = true; + } + } + + ret.str = nullptr; + ret.length = parse_quoted_string_state::error_no_closing_quote; + return ret; +} + +const char* parse_to_closing_double_quote(const char* p, size_t max_length) +{ + assert(*p == '"'); + const char* p_end = p + max_length; + ++p; + + if (p == p_end) + return nullptr; + + bool escape = false; + + for (; p != p_end; ++p) + { + if (escape) + { + char c = *p; + escape = false; + + if (get_string_escape_char_type(c) == string_escape_char_t::invalid) + return nullptr; + } + + switch (*p) + { + case '"': + // closing quote. + ++p; // skip the quote. + return p; + case '\\': + escape = true; + break; + default: + ; + } + } + + return nullptr; +} + +std::string_view trim(std::string_view str) +{ + const char* p = str.data(); + const char* p_end = p + str.size(); + + // Find the first non-space character. + p = std::find_if_not(p, p_end, is_blank); + + if (p == p_end) + { + // This string is empty. + return std::string_view{}; + } + + // Find the last non-space character. + auto last = std::find_if_not(std::reverse_iterator(p_end), std::reverse_iterator(p), is_blank); + std::size_t n = std::distance(p, last.base()); + + return std::string_view{p, n}; +} + +} +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/parser/parser_global_test.cpp b/src/parser/parser_global_test.cpp new file mode 100644 index 0000000..680a221 --- /dev/null +++ b/src/parser/parser_global_test.cpp @@ -0,0 +1,175 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "test_global.hpp" +#include <orcus/parser_global.hpp> +#include <orcus/cell_buffer.hpp> + +#include <vector> +#include <cmath> +#include <cstring> +#include <limits> + +namespace { + +void test_parse_numbers() +{ + orcus::test::stack_printer __sp__(__func__); + + struct test_case + { + const char* str; + double val; + }; + + std::vector<test_case> test_cases = { + {"1", 1.0}, + {"1.0", 1.0}, + {"-1.0", -1.0}, + {"2e2", 200.0}, + {"1.2", 1.2}, + {"-0.0001", -0.0001}, + {"-0.0", 0.0}, + {"+.", std::numeric_limits<double>::signaling_NaN()}, + {"+e", std::numeric_limits<double>::signaling_NaN()}, + {"+e1", std::numeric_limits<double>::signaling_NaN()}, + {"+ ", std::numeric_limits<double>::signaling_NaN()}, + {"- ", std::numeric_limits<double>::signaling_NaN()} + }; + + for (const test_case& test_data : test_cases) + { + const char* str = test_data.str; + double val; + orcus::parse_numeric(str, str + std::strlen(test_data.str), val); + if (std::isnan(test_data.val)) + { + assert(std::isnan(val)); + } + else + { + assert(val == test_data.val); + } + } +} + +void test_parse_integers() +{ + orcus::test::stack_printer __sp__(__func__); + + std::string_view test_str = "-100"; + + long value; + const char* p = test_str.data(); + const char* p_end = p + test_str.size(); + const char* p_last = orcus::parse_integer(p, p_end, value); + + assert(value == -100); + assert(p_last == p_end); + + --p_end; + p_last = orcus::parse_integer(p, p_end, value); + assert(value == -10); + assert(p_last == p_end); + + --p_end; + p_last = orcus::parse_integer(p, p_end, value); + assert(value == -1); + assert(p_last == p_end); + + test_str = "13.4"; // the parsing should end on the '.' + p = test_str.data(); + p_end = p + test_str.size(); + p_last = orcus::parse_integer(p, p_end, value); + assert(value == 13); + assert(p_last == p + 2); + + // What if the p_end points to an earlier address than the p ... + std::swap(p, p_end); + assert(p > p_end); + p_last = orcus::parse_integer(p, p_end, value); + assert(p == p_last); + + // Empty char range + p = test_str.data(); + p_end = p; + p_last = orcus::parse_integer(p, p_end, value); + assert(p_last == p); +} + +void test_parse_double_quoted_strings() +{ + orcus::test::stack_printer __sp__(__func__); + + struct test_case + { + std::string input; + const char* expected_p; + size_t expected_n; + }; + + std::vector<test_case> test_cases = { + { "\"", nullptr, orcus::parse_quoted_string_state::error_no_closing_quote }, + { "\"\"", "", 0 }, + { "\"a\"", "a", 1 }, + + }; + + for (const test_case& tc : test_cases) + { + orcus::cell_buffer buf; + const char* p = tc.input.data(); + size_t n = tc.input.size(); + orcus::parse_quoted_string_state ret = orcus::parse_double_quoted_string(p, n, buf); + + if (tc.expected_p) + { + std::string expected(tc.expected_p, tc.expected_n); + std::string actual(ret.str, ret.length); + assert(expected == actual); + } + else + { + assert(ret.str == nullptr); + assert(ret.length == tc.expected_n); + } + } + +} + +void test_trim() +{ + // test for trimming. + std::string s1("test"), s2(" test"), s3(" test "), s4("test "); + std::string_view sv1(s1), sv2(s2), sv3(s3), sv4(s4); + assert(sv1 != sv2); + assert(sv1 != sv3); + assert(sv2 != sv3); + assert(sv1 != sv4); + + std::string_view trimmed = orcus::trim(sv1); + assert(sv1 == trimmed); // nothing to trim. + assert(sv1 == orcus::trim(sv2)); + assert(sv1 == orcus::trim(sv3)); + assert(sv1 == orcus::trim(sv4)); + assert(sv1.size() == orcus::trim(sv2).size()); + assert(sv1.size() == orcus::trim(sv3).size()); +} + +} + +int main() +{ + test_parse_numbers(); + test_parse_integers(); + test_parse_double_quoted_strings(); + test_trim(); + + return 0; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/parser/parser_test_json_validation.cpp b/src/parser/parser_test_json_validation.cpp new file mode 100644 index 0000000..a001226 --- /dev/null +++ b/src/parser/parser_test_json_validation.cpp @@ -0,0 +1,439 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "orcus/json_parser.hpp" +#include "orcus/stream.hpp" + +#include <vector> +#include <iostream> +#include <fstream> + +namespace { + +// These test cases originate from https://github.com/nst/JSONTestSuite +// +// The name of these files tell if their contents should be accepted or +// rejected. +// +// * y_ content must be accepted by parsers +// * n_ content must be rejected by parsers +// * i_ parsers are free to accept or reject content + +std::vector<const char*> test_files_indeterminate = { + "i_number_double_huge_neg_exp.json", + "i_number_huge_exp.json", + "i_number_neg_int_huge_exp.json", + "i_number_pos_double_huge_exp.json", + "i_number_real_neg_overflow.json", + "i_number_real_pos_overflow.json", + "i_number_real_underflow.json", + "i_number_too_big_neg_int.json", + "i_number_too_big_pos_int.json", + "i_number_very_big_negative_int.json", + "i_object_key_lone_2nd_surrogate.json", + "i_string_1st_surrogate_but_2nd_missing.json", + "i_string_1st_valid_surrogate_2nd_invalid.json", + "i_string_incomplete_surrogate_and_escape_valid.json", + "i_string_incomplete_surrogate_pair.json", + "i_string_incomplete_surrogates_escape_valid.json", + "i_string_invalid_lonely_surrogate.json", + "i_string_invalid_surrogate.json", + "i_string_invalid_utf-8.json", + "i_string_inverted_surrogates_U+1D11E.json", + "i_string_iso_latin_1.json", + "i_string_lone_second_surrogate.json", + "i_string_lone_utf8_continuation_byte.json", + "i_string_not_in_unicode_range.json", + "i_string_overlong_sequence_2_bytes.json", + "i_string_overlong_sequence_6_bytes.json", + "i_string_overlong_sequence_6_bytes_null.json", + "i_string_truncated-utf-8.json", + "i_string_utf16BE_no_BOM.json", + "i_string_utf16LE_no_BOM.json", + "i_string_UTF-16LE_with_BOM.json", + "i_string_UTF-8_invalid_sequence.json", + "i_string_UTF8_surrogate_U+D800.json", + "i_structure_500_nested_arrays.json", + "i_structure_UTF-8_BOM_empty_object.json" +}; + +std::vector<const char*> test_files_failed = { + "n_array_1_true_without_comma.json", + "n_array_a_invalid_utf8.json", + "n_array_colon_instead_of_comma.json", + "n_array_comma_after_close.json", + "n_array_comma_and_number.json", + "n_array_double_comma.json", + "n_array_double_extra_comma.json", + "n_array_extra_close.json", + "n_array_extra_comma.json", + "n_array_incomplete_invalid_value.json", + "n_array_incomplete.json", + "n_array_inner_array_no_comma.json", + "n_array_invalid_utf8.json", + "n_array_items_separated_by_semicolon.json", + "n_array_just_comma.json", + "n_array_just_minus.json", + "n_array_missing_value.json", + "n_array_newlines_unclosed.json", + "n_array_number_and_comma.json", + "n_array_number_and_several_commas.json", + "n_array_spaces_vertical_tab_formfeed.json", + "n_array_star_inside.json", + "n_array_unclosed.json", + "n_array_unclosed_trailing_comma.json", + "n_array_unclosed_with_new_lines.json", + "n_array_unclosed_with_object_inside.json", + "n_incomplete_false.json", + "n_incomplete_null.json", + "n_incomplete_true.json", + "n_multidigit_number_then_00.json", + "n_number_0.1.2.json", + "n_number_-01.json", + "n_number_0.3e.json", + "n_number_0.3e+.json", + "n_number_0_capital_E.json", + "n_number_0_capital_E+.json", + "n_number_0.e1.json", + "n_number_0e.json", + "n_number_0e+.json", + "n_number_1_000.json", + "n_number_1.0e-.json", + "n_number_1.0e.json", + "n_number_1.0e+.json", + "n_number_-1.0..json", + "n_number_1eE2.json", + "n_number_.-1.json", + "n_number_+1.json", + "n_number_.2e-3.json", + "n_number_2.e-3.json", + "n_number_2.e+3.json", + "n_number_2.e3.json", + "n_number_-2..json", + "n_number_9.e+.json", + "n_number_expression.json", + "n_number_hex_1_digit.json", + "n_number_hex_2_digits.json", + "n_number_infinity.json", + "n_number_+Inf.json", + "n_number_Inf.json", + "n_number_invalid+-.json", + "n_number_invalid-negative-real.json", + "n_number_invalid-utf-8-in-bigger-int.json", + "n_number_invalid-utf-8-in-exponent.json", + "n_number_invalid-utf-8-in-int.json", + "n_number_++.json", + "n_number_minus_infinity.json", + "n_number_minus_sign_with_trailing_garbage.json", + "n_number_minus_space_1.json", + "n_number_-NaN.json", + "n_number_NaN.json", + "n_number_neg_int_starting_with_zero.json", + "n_number_neg_real_without_int_part.json", + "n_number_neg_with_garbage_at_end.json", + "n_number_real_garbage_after_e.json", + "n_number_real_with_invalid_utf8_after_e.json", + "n_number_real_without_fractional_part.json", + "n_number_starting_with_dot.json", + "n_number_U+FF11_fullwidth_digit_one.json", + "n_number_with_alpha_char.json", + "n_number_with_alpha.json", + "n_number_with_leading_zero.json", + "n_object_bad_value.json", + "n_object_bracket_key.json", + "n_object_comma_instead_of_colon.json", + "n_object_double_colon.json", + "n_object_emoji.json", + "n_object_garbage_at_end.json", + "n_object_key_with_single_quotes.json", + "n_object_lone_continuation_byte_in_key_and_trailing_comma.json", + "n_object_missing_colon.json", + "n_object_missing_key.json", + "n_object_missing_semicolon.json", + "n_object_missing_value.json", + "n_object_no-colon.json", + "n_object_non_string_key_but_huge_number_instead.json", + "n_object_non_string_key.json", + "n_object_repeated_null_null.json", + "n_object_several_trailing_commas.json", + "n_object_single_quote.json", + "n_object_trailing_comma.json", + "n_object_trailing_comment.json", + "n_object_trailing_comment_open.json", + "n_object_trailing_comment_slash_open_incomplete.json", + "n_object_trailing_comment_slash_open.json", + "n_object_two_commas_in_a_row.json", + "n_object_unquoted_key.json", + "n_object_unterminated-value.json", + "n_object_with_single_string.json", + "n_object_with_trailing_garbage.json", + "n_single_space.json", + "n_string_1_surrogate_then_escape.json", + "n_string_1_surrogate_then_escape_u1.json", + "n_string_1_surrogate_then_escape_u1x.json", + "n_string_1_surrogate_then_escape_u.json", + "n_string_accentuated_char_no_quotes.json", + "n_string_backslash_00.json", + "n_string_escaped_backslash_bad.json", + "n_string_escaped_ctrl_char_tab.json", + "n_string_escaped_emoji.json", + "n_string_escape_x.json", + "n_string_incomplete_escaped_character.json", + "n_string_incomplete_escape.json", + "n_string_incomplete_surrogate_escape_invalid.json", + "n_string_incomplete_surrogate.json", + "n_string_invalid_backslash_esc.json", + "n_string_invalid_unicode_escape.json", + "n_string_invalid_utf8_after_escape.json", + "n_string_invalid-utf-8-in-escape.json", + "n_string_leading_uescaped_thinspace.json", + "n_string_no_quotes_with_bad_escape.json", + "n_string_single_doublequote.json", + "n_string_single_quote.json", + "n_string_single_string_no_double_quotes.json", + "n_string_start_escape_unclosed.json", + "n_string_unescaped_crtl_char.json", + "n_string_unescaped_newline.json", + "n_string_unescaped_tab.json", + "n_string_unicode_CapitalU.json", + "n_string_with_trailing_garbage.json", + // "n_structure_100000_opening_arrays.json", + "n_structure_angle_bracket_..json", + "n_structure_angle_bracket_null.json", + "n_structure_array_trailing_garbage.json", + "n_structure_array_with_extra_array_close.json", + "n_structure_array_with_unclosed_string.json", + "n_structure_ascii-unicode-identifier.json", + "n_structure_capitalized_True.json", + "n_structure_close_unopened_array.json", + "n_structure_comma_instead_of_closing_brace.json", + "n_structure_double_array.json", + "n_structure_end_array.json", + "n_structure_incomplete_UTF8_BOM.json", + "n_structure_lone-invalid-utf-8.json", + "n_structure_lone-open-bracket.json", + "n_structure_no_data.json", + "n_structure_null-byte-outside-string.json", + "n_structure_number_with_trailing_garbage.json", + "n_structure_object_followed_by_closing_object.json", + "n_structure_object_unclosed_no_value.json", + "n_structure_object_with_comment.json", + "n_structure_object_with_trailing_garbage.json", + "n_structure_open_array_apostrophe.json", + "n_structure_open_array_comma.json", + // "n_structure_open_array_object.json", + "n_structure_open_array_open_object.json", + "n_structure_open_array_open_string.json", + "n_structure_open_array_string.json", + "n_structure_open_object_close_array.json", + "n_structure_open_object_comma.json", + "n_structure_open_object.json", + "n_structure_open_object_open_array.json", + "n_structure_open_object_open_string.json", + "n_structure_open_object_string_with_apostrophes.json", + "n_structure_open_open.json", + "n_structure_single_eacute.json", + "n_structure_single_star.json", + "n_structure_trailing_#.json", + "n_structure_U+2060_word_joined.json", + "n_structure_uescaped_LF_before_string.json", + "n_structure_unclosed_array.json", + "n_structure_unclosed_array_partial_null.json", + "n_structure_unclosed_array_unfinished_false.json", + "n_structure_unclosed_array_unfinished_true.json", + "n_structure_unclosed_object.json", + "n_structure_unicode-identifier.json", + "n_structure_UTF8_BOM_no_data.json", + "n_structure_whitespace_formfeed.json", + "n_structure_whitespace_U+2060_word_joiner.json" +}; + +std::vector<const char*> test_files_pass = { + "y_array_arraysWithSpaces.json", + "y_array_empty.json", + "y_array_empty-string.json", + "y_array_ending_with_newline.json", + "y_array_false.json", + "y_array_heterogeneous.json", + "y_array_null.json", + "y_array_with_1_and_newline.json", + "y_array_with_leading_space.json", + "y_array_with_several_null.json", + "y_array_with_trailing_space.json", + "y_number_0e+1.json", + "y_number_0e1.json", + "y_number_after_space.json", + "y_number_double_close_to_zero.json", + "y_number_int_with_exp.json", + "y_number.json", + "y_number_minus_zero.json", + "y_number_negative_int.json", + "y_number_negative_one.json", + "y_number_negative_zero.json", + "y_number_real_capital_e.json", + "y_number_real_capital_e_neg_exp.json", + "y_number_real_capital_e_pos_exp.json", + "y_number_real_exponent.json", + "y_number_real_fraction_exponent.json", + "y_number_real_neg_exp.json", + "y_number_real_pos_exponent.json", + "y_number_simple_int.json", + "y_number_simple_real.json", + "y_object_basic.json", + "y_object_duplicated_key_and_value.json", + "y_object_duplicated_key.json", + "y_object_empty.json", + "y_object_empty_key.json", + // "y_object_escaped_null_in_key.json", + "y_object_extreme_numbers.json", + "y_object.json", + "y_object_long_strings.json", + "y_object_simple.json", + // "y_object_string_unicode.json", + "y_object_with_newlines.json", + // "y_string_1_2_3_bytes_UTF-8_sequences.json", + // "y_string_accepted_surrogate_pair.json", + // "y_string_accepted_surrogate_pairs.json", + "y_string_allowed_escapes.json", + "y_string_backslash_and_u_escaped_zero.json", + "y_string_backslash_doublequotes.json", + "y_string_comments.json", + "y_string_double_escape_a.json", + "y_string_double_escape_n.json", + // "y_string_escaped_control_character.json", + // "y_string_escaped_noncharacter.json", + "y_string_in_array.json", + "y_string_in_array_with_leading_space.json", + // "y_string_last_surrogates_1_and_2.json", + // "y_string_nbsp_uescaped.json", + "y_string_nonCharacterInUTF-8_U+10FFFF.json", + "y_string_nonCharacterInUTF-8_U+FFFF.json", + // "y_string_null_escape.json", + // "y_string_one-byte-utf-8.json", + "y_string_pi.json", + "y_string_reservedCharacterInUTF-8_U+1BFFF.json", + "y_string_simple_ascii.json", + // "y_string_space.json", + // "y_string_surrogates_U+1D11E_MUSICAL_SYMBOL_G_CLEF.json", + // "y_string_three-byte-utf-8.json", + // "y_string_two-byte-utf-8.json", + "y_string_u+2028_line_sep.json", + "y_string_u+2029_par_sep.json", + // "y_string_uescaped_newline.json", + // "y_string_uEscape.json", + "y_string_unescaped_char_delete.json", + "y_string_unicode_2.json", + // "y_string_unicodeEscapedBackslash.json", + // "y_string_unicode_escaped_double_quote.json", + // "y_string_unicode.json", + // "y_string_unicode_U+10FFFE_nonchar.json", + // "y_string_unicode_U+1FFFE_nonchar.json", + // "y_string_unicode_U+200B_ZERO_WIDTH_SPACE.json", + // "y_string_unicode_U+2064_invisible_plus.json", + // "y_string_unicode_U+FDD0_nonchar.json", + // "y_string_unicode_U+FFFE_nonchar.json", + "y_string_utf8.json", + "y_string_with_del_character.json", + // "y_structure_lonely_false.json", + // "y_structure_lonely_int.json", + // "y_structure_lonely_negative_real.json", + // "y_structure_lonely_null.json", + // "y_structure_lonely_string.json", + // "y_structure_lonely_true.json", + // "y_structure_string_empty.json", + "y_structure_trailing_newline.json", + "y_structure_true_in_array.json", + "y_structure_whitespace_array.json", +}; + +std::string load_file(const std::string& file_name) +{ + std::string file_path = std::string(SRCDIR) + "/test/json/validation/" + file_name; + std::ifstream f(file_path); + std::stringstream buffer; + buffer << f.rdbuf(); + return buffer.str(); +} + +void test_pass() +{ + orcus::json_handler hdl; + + for (const char* test_file_name : test_files_pass) + { + std::string content = load_file(test_file_name); + std::cout << test_file_name << std::endl; + try + { + orcus::json_parser<orcus::json_handler> parser(content, hdl); + parser.parse(); + } + catch (const orcus::parse_error& e) + { + std::cout << e.what() << std::endl; + std::cout << orcus::create_parse_error_output(content, e.offset()) << std::endl; + assert(false); + } + } +} + +void test_fail() +{ + orcus::json_handler hdl; + + for (const char* test_file_name : test_files_failed) + { + std::string content = load_file(test_file_name); + std::cout << test_file_name << std::endl; + bool failed = false; + try { + orcus::json_parser<orcus::json_handler> parser(content, hdl); + parser.parse(); + } + catch (const orcus::parse_error&) + { + failed = true; + } + + if (!failed) + { + std::cout << "invalid json string has been parsed as valid: content='" << content << "'" << std::endl; + assert(false); + } + } +} + +void test_indeterminate() +{ + orcus::json_handler hdl; + + for (const char* test_file_name : test_files_indeterminate) + { + std::string content = load_file(test_file_name); + std::cout << test_file_name << std::endl; + try { + orcus::json_parser<orcus::json_handler> parser(content, hdl); + parser.parse(); + } + catch (const orcus::parse_error&) + { + } + + } +} + +} + +int main() +{ + test_pass(); + test_fail(); + test_indeterminate(); + return 0; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/parser/parser_test_numeric.cpp b/src/parser/parser_test_numeric.cpp new file mode 100644 index 0000000..b16ed9a --- /dev/null +++ b/src/parser/parser_test_numeric.cpp @@ -0,0 +1,105 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "test_global.hpp" +#include "numeric_parser.hpp" + +#include <cassert> +#include <iostream> +#include <vector> +#include <limits> + +using namespace orcus; +using std::cout; +using std::endl; + +namespace { + +struct check +{ + std::string_view str; + double expected; +}; + +const double invalid = std::numeric_limits<double>::quiet_NaN(); + +template<typename ParserT> +bool run_checks(const std::vector<check>& checks) +{ + for (const check& c : checks) + { + ParserT parser(c.str.data(), c.str.data() + c.str.size()); + double v = parser.parse(); + + if (std::isnan(c.expected)) + { + if (!std::isnan(v)) + { + cout << "'" << c.str << "' was expected to be invalid, but parser parsed as if it was valid." << endl; + return false; + } + } + else + { + if (v != c.expected) + { + cout << "'" << c.str << "' was expected to be parsed as (" << c.expected << "), but the parser parsed it as (" << v << ")" << endl; + return false; + } + } + } + + return true; +} + +} + +void test_generic_number_parsing() +{ + using parser_type = detail::numeric_parser<detail::generic_parser_trait>; + + std::vector<check> checks = { + { "-6.e3", -6e3 }, + { "true", invalid }, + { "1", 1.0 }, + { "1.0", 1.0 }, + { "-1.0", -1.0 }, + { "-01", -1.0 }, + { "2e2", 200.0 }, + { "1.2", 1.2 }, + { "-0.0001", -0.0001 }, + { "-0.0", 0.0 }, + { "+.", invalid }, + { "+e", invalid }, + { "+e1", invalid }, + { "+ ", invalid }, + { "- ", invalid } + }; + + assert(run_checks<parser_type>(checks)); +} + +void test_json_number_parsing() +{ + using parser_type = detail::numeric_parser<detail::json_parser_trait>; + + std::vector<check> checks = { + { "-01", invalid }, // Leading zeros are invalid. + }; + + assert(run_checks<parser_type>(checks)); +} + +int main() +{ + test_generic_number_parsing(); + test_json_number_parsing(); + + return EXIT_SUCCESS; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/parser/parser_test_xml_validation.cpp b/src/parser/parser_test_xml_validation.cpp new file mode 100644 index 0000000..3be1804 --- /dev/null +++ b/src/parser/parser_test_xml_validation.cpp @@ -0,0 +1,95 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "test_global.hpp" +#include <orcus/sax_parser.hpp> +#include <orcus/stream.hpp> + +#include <iostream> +#include <boost/range/iterator_range.hpp> + +#include "filesystem_env.hpp" + +void test_valid() +{ + ORCUS_TEST_FUNC_SCOPE; + + struct _handler : public orcus::sax_handler {}; + + fs::path root_dir = fs::path{SRCDIR} / "test" / "xml" / "valids"; + + if (!fs::is_directory(root_dir)) + return; + + for (const fs::path& entry : boost::make_iterator_range(fs::directory_iterator{root_dir}, {})) + { + std::cout << "input file: " << entry << std::endl; + + orcus::file_content content(entry.string()); + + _handler hdl; + orcus::sax_parser<_handler> parser(content.str(), hdl); + + try + { + parser.parse(); + } + catch (const orcus::malformed_xml_error& e) + { + std::cerr << orcus::create_parse_error_output(content.str(), e.offset()) << std::endl; + std::cerr << e.what() << std::endl; + assert(!"This was supposed to be a valid XML!"); + + } + } +} + +void test_invalid() +{ + ORCUS_TEST_FUNC_SCOPE; + + struct _handler : public orcus::sax_handler {}; + + fs::path root_dir = fs::path{SRCDIR} / "test" / "xml" / "invalids"; + + if (!fs::is_directory(root_dir)) + return; + + for (const fs::path& entry : boost::make_iterator_range(fs::directory_iterator{root_dir}, {})) + { + std::cout << "input file: " << entry << std::endl; + + orcus::file_content content(entry.string()); + + _handler hdl; + orcus::sax_parser<_handler> parser(content.str(), hdl); + + try + { + parser.parse(); + assert(!"exception was expected, but one was not thrown."); + } + catch (const orcus::malformed_xml_error& e) + { + std::cerr << orcus::create_parse_error_output(content.str(), e.offset()) << std::endl; + std::cerr << e.what() << std::endl; + } + catch (...) + { + assert(!"wrong exception was thrown."); + } + } +} + +int main() +{ + test_valid(); + test_invalid(); + + return EXIT_SUCCESS; +} +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/parser/sax_ns_parser_test.cpp b/src/parser/sax_ns_parser_test.cpp new file mode 100644 index 0000000..eb7443f --- /dev/null +++ b/src/parser/sax_ns_parser_test.cpp @@ -0,0 +1,78 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <orcus/sax_ns_parser.hpp> +#include <orcus/xml_namespace.hpp> + +#include <cstring> + +void test_handler() +{ + const char* test_code = "<?xml version=\"1.0\"?><root/>"; + orcus::sax_ns_handler hdl; + orcus::xmlns_repository repo; + orcus::xmlns_context cxt = repo.create_context(); + + orcus::sax_ns_parser<orcus::sax_ns_handler> parser(test_code, cxt, hdl); + parser.parse(); +} + +/** + * Test for unqualified attribute NOT belonging to the default namespace, + * according to + * https://stackoverflow.com/questions/3312390/xml-default-namespaces-for-unqualified-attribute-names + */ +void test_default_attr_ns() +{ + const orcus::xmlns_id_t default_ns = "test:foo"; + + struct _handler : public orcus::sax_ns_handler + { + orcus::xmlns_id_t default_ns_expected; + + void start_element(const orcus::sax_ns_parser_element& elem) + { + // All elements should belong to the default namespace. + assert(elem.ns == default_ns_expected); + } + + void attribute(std::string_view /*name*/, std::string_view /*val*/) {} + + void attribute(const orcus::sax_ns_parser_attribute& attr) + { + // Attribute's namespace should be empty. + assert(attr.ns == orcus::XMLNS_UNKNOWN_ID); + assert(attr.name == "attr"); + assert(attr.value == "1"); + } + }; + + const char* test_code = "<?xml version=\"1.0\"?><root xmlns='test:foo'><elem attr='1'/></root>"; + + const orcus::xmlns_id_t predefined[] = { default_ns, nullptr }; + + orcus::xmlns_repository repo; + repo.add_predefined_values(predefined); + + orcus::xmlns_context cxt = repo.create_context(); + + _handler hdl; + hdl.default_ns_expected = default_ns; + + orcus::sax_ns_parser<_handler> parser(test_code, cxt, hdl); + parser.parse(); +} + +int main() +{ + test_handler(); + test_default_attr_ns(); + + return EXIT_SUCCESS; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/parser/sax_parser_base.cpp b/src/parser/sax_parser_base.cpp new file mode 100644 index 0000000..58f750e --- /dev/null +++ b/src/parser/sax_parser_base.cpp @@ -0,0 +1,421 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "orcus/sax_parser_base.hpp" + +#include "utf8.hpp" + +#include <cstring> +#include <vector> +#include <memory> + +#ifdef __ORCUS_CPU_FEATURES +#include <immintrin.h> +#endif + +namespace orcus { namespace sax { + +char decode_xml_encoded_char(const char* p, size_t n) +{ + if (n == 2) + { + if (!std::strncmp(p, "lt", n)) + return '<'; + else if (!std::strncmp(p, "gt", n)) + return '>'; + else + return '\0'; + } + else if (n == 3) + { + if (!std::strncmp(p, "amp", n)) + return '&'; + else + return '\0'; + } + else if (n == 4) + { + if (!std::strncmp(p, "apos", n)) + return '\''; + else if (!std::strncmp(p, "quot", 4)) + return '"'; + else + return '\0'; + } + + return '\0'; +} + +std::string decode_xml_unicode_char(const char* p, size_t n) +{ + if (*p == '#' && n >= 2) + { + uint32_t point = 0; + if (p[1] == 'x') + { + if (n == 2) + throw orcus::xml_structure_error( + "invalid number of characters for hexadecimal unicode reference"); + + point = std::stoi(std::string(p + 2, n - 2), nullptr, 16); + } + else + point = std::stoi(std::string(p + 1, n - 1), nullptr, 10); + + if (point < 0x80) + { + // is it really necessary to do the bit manipulation here? + std::string s(1, static_cast<char>(point & 0x7F)); + return s; + } + else if (point < 0x0800) + { + std::string s(1, static_cast<char>((point >> 6 & 0x1F) | 0xC0)); + s += static_cast<char>((point & 0x3F) | 0x80); + return s; + } + else if (point < 0x010000) + { + std::string s(1, static_cast<char>((point >> 12 & 0x0F) | 0xE0)); + s += static_cast<char>((point >> 6 & 0x3F) | 0x80); + s += static_cast<char>((point & 0x3F) | 0x80); + return s; + } + else if (point < 0x110000) + { + std::string s(1, static_cast<char>((point >> 18 & 0x07) | 0xF0)); + s += static_cast<char>((point >> 12 & 0x3F) | 0x80); + s += static_cast<char>((point >> 6 & 0x3F) | 0x80); + s += static_cast<char>((point & 0x3F) | 0x80); + return s; + } + else + { + // should not happen as that is not represented by utf-8 + assert(false); + } + } + + return std::string(); +} + +struct parser_base::impl +{ + std::vector<std::unique_ptr<cell_buffer>> m_cell_buffers; +}; + +parser_base::parser_base(const char* content, size_t size) : + ::orcus::parser_base(content, size), + mp_impl(std::make_unique<impl>()), + m_nest_level(0), + m_buffer_pos(0), + m_root_elem_open(true) +{ + mp_impl->m_cell_buffers.push_back(std::make_unique<cell_buffer>()); +} + +parser_base::~parser_base() {} + +void parser_base::inc_buffer_pos() +{ + ++m_buffer_pos; + if (m_buffer_pos == mp_impl->m_cell_buffers.size()) + mp_impl->m_cell_buffers.push_back(std::make_unique<cell_buffer>()); +} + +cell_buffer& parser_base::get_cell_buffer() +{ + return *mp_impl->m_cell_buffers[m_buffer_pos]; +} + +void parser_base::comment() +{ + // Parse until we reach '-->'. + size_t len = available_size(); + assert(len > 3); + char c = cur_char(); + size_t i = 0; + bool hyphen = false; + for (; i < len; ++i, c = next_and_char()) + { + if (c == '-') + { + if (!hyphen) + // first hyphen. + hyphen = true; + else + // second hyphen. + break; + } + else + hyphen = false; + } + + if (len - i < 2 || next_and_char() != '>') + throw malformed_xml_error( + "'--' should not occur in comment other than in the closing tag.", offset()); + + next(); +} + +void parser_base::expects_next(const char* p, size_t n) +{ + if (available_size() < n+1) + throw malformed_xml_error( + "not enough stream left to check for an expected string segment.", offset()); + + const char* p0 = p; + const char* p_end = p + n; + char c = next_and_char(); + for (; p != p_end; ++p, c = next_and_char()) + { + if (c == *p) + continue; + + std::ostringstream os; + os << "'" << std::string(p0, n) << "' was expected, but not found."; + throw malformed_xml_error(os.str(), offset()); + } +} + +void parser_base::parse_encoded_char(cell_buffer& buf) +{ + assert(cur_char() == '&'); + next(); + const char* p0 = mp_char; + for (; has_char(); next()) + { + if (cur_char() != ';') + continue; + + size_t n = mp_char - p0; + if (!n) + throw malformed_xml_error("empty encoded character.", offset()); + +#if ORCUS_DEBUG_SAX_PARSER + cout << "sax_parser::parse_encoded_char: raw='" << std::string(p0, n) << "'" << endl; +#endif + + char c = decode_xml_encoded_char(p0, n); + if (c) + buf.append(&c, 1); + else + { + std::string utf8 = decode_xml_unicode_char(p0, n); + + if (!utf8.empty()) + { + buf.append(utf8.data(), utf8.size()); + c = '1'; // just to avoid hitting the !c case below + } + } + + // Move to the character past ';' before returning to the parent call. + next(); + + if (!c) + { +#if ORCUS_DEBUG_SAX_PARSER + cout << "sax_parser::parse_encoded_char: not a known encoding name. Use the original." << endl; +#endif + // Unexpected encoding name. Use the original text. + buf.append(p0, mp_char-p0); + } + + return; + } + + throw malformed_xml_error( + "error parsing encoded character: terminating character is not found.", offset()); +} + +void parser_base::value_with_encoded_char(cell_buffer& buf, std::string_view& str, char quote_char) +{ + assert(cur_char() == '&'); + parse_encoded_char(buf); + + const char* p0 = mp_char; + + while (has_char()) + { + if (cur_char() == '&') + { + if (mp_char > p0) + buf.append(p0, mp_char-p0); + + parse_encoded_char(buf); + p0 = mp_char; + } + + if (cur_char() == quote_char) + break; + + if (cur_char() != '&') + next(); + } + + if (mp_char > p0) + buf.append(p0, mp_char-p0); + + if (!buf.empty()) + str = buf.str(); + + // Skip the closing quote. + assert(!has_char() || cur_char() == quote_char); + if (has_char()) + next(); +} + +bool parser_base::value(std::string_view& str, bool decode) +{ + char c = cur_char_checked(); + if (c != '"' && c != '\'') + throw malformed_xml_error("value must be quoted", offset()); + + char quote_char = c; + + c = next_char_checked(); + + const char* p0 = mp_char; + for (; c != quote_char; c = next_char_checked()) + { + if (decode && c == '&') + { + // This value contains one or more encoded characters. + cell_buffer& buf = get_cell_buffer(); + buf.reset(); + buf.append(p0, mp_char-p0); + value_with_encoded_char(buf, str, quote_char); + return true; + } + } + + str = std::string_view(p0, mp_char-p0); + + // Skip the closing quote. + next(); + + return false; +} + +void parser_base::name(std::string_view& str) +{ + const char* p0 = mp_char; + mp_char = parse_utf8_xml_name_start_char(mp_char, mp_end); + if (mp_char == p0) + { + ::std::ostringstream os; + os << "name must begin with an alphabet, but got this instead '" << cur_char() << "'"; + throw malformed_xml_error(os.str(), offset()); + } + +#if defined(__ORCUS_CPU_FEATURES) && defined(__SSE4_2__) + + const __m128i match = _mm_loadu_si128((const __m128i*)"azAZ09--__.."); + const int mode = _SIDD_LEAST_SIGNIFICANT | _SIDD_CMP_RANGES | _SIDD_UBYTE_OPS | _SIDD_NEGATIVE_POLARITY; + + size_t n_total = available_size(); + + while (n_total) + { + __m128i char_block = _mm_loadu_si128((const __m128i*)mp_char); + + int n = std::min<size_t>(16u, n_total); + int r = _mm_cmpestri(match, 12, char_block, n, mode); + mp_char += r; // Move the current char position. + n_total -= r; + + if (r < 16 && n_total) + { + // There is a character that does not match the SSE-based ASCII-only check. + // It may either by an ascii character that is not allowed, in which case stop, + // or it may possibly be an allowed utf-8 character, in which case move over it + // using the slow function. + + const char* p = parse_utf8_xml_name_char(mp_char, mp_end); + if (p == mp_char) + break; + + n_total -= p - mp_char; + mp_char = p; + } + + } + cur_char_checked(); // check end of xml stream + +#else + for(;;) + { + cur_char_checked(); // check end of xml stream + const char* p = parse_utf8_xml_name_char(mp_char, mp_end); + + if (p == mp_char) + break; + + mp_char = p; + } +#endif + + str = std::string_view(p0, mp_char-p0); +} + +void parser_base::element_name(parser_element& elem, std::ptrdiff_t begin_pos) +{ + elem.begin_pos = begin_pos; + name(elem.name); + if (cur_char() == ':') + { + elem.ns = elem.name; + next_check(); + name(elem.name); + } +} + +void parser_base::attribute_name(std::string_view& attr_ns, std::string_view& attr_name) +{ + name(attr_name); + if (cur_char() == ':') + { + // Attribute name is namespaced. + attr_ns = attr_name; + next_check(); + name(attr_name); + } +} + +void parser_base::characters_with_encoded_char(cell_buffer& buf) +{ + assert(cur_char() == '&'); + parse_encoded_char(buf); + + const char* p0 = mp_char; + + while (has_char()) + { + if (cur_char() == '&') + { + if (mp_char > p0) + buf.append(p0, mp_char-p0); + + parse_encoded_char(buf); + p0 = mp_char; + } + + if (cur_char() == '<') + break; + + if (cur_char() != '&') + next(); + } + + if (mp_char > p0) + buf.append(p0, mp_char-p0); +} + +}} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/parser/sax_parser_test.cpp b/src/parser/sax_parser_test.cpp new file mode 100644 index 0000000..ec8b1f1 --- /dev/null +++ b/src/parser/sax_parser_test.cpp @@ -0,0 +1,67 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "test_global.hpp" +#include <orcus/sax_parser.hpp> +#include <cstring> + +using namespace std; + +void test_handler() +{ + const char* test_code = "<?xml version=\"1.0\"?><root/>"; + + orcus::sax_handler hdl; + orcus::sax_parser<orcus::sax_handler> parser(test_code, hdl); + parser.parse(); +} + +void test_attr_equal_with_whitespace() +{ + struct _handler : public orcus::sax_handler {}; + + const char* content = + "<?xml version=\"1.0\"?>" + "<root attr1='some value' attr2 = \"some value\"/>" + ; + + _handler hdl; + orcus::sax_parser<_handler> parser(content, hdl); + parser.parse(); +} + +void test_attr_with_encoded_chars_single_quotes() +{ + struct _handler : public orcus::sax_handler + { + void attribute(const orcus::sax::parser_attribute& attr) + { + if (attr.name == "attr1") + assert(attr.value == "'some value'"); + } + }; + + const char* content = + "<?xml version=\"1.0\"?>" + "<root attr1=''some value''/>" + ; + + _handler hdl; + orcus::sax_parser<_handler> parser(content, hdl); + parser.parse(); +} + +int main() +{ + test_handler(); + test_attr_equal_with_whitespace(); + test_attr_with_encoded_chars_single_quotes(); + + return EXIT_SUCCESS; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/parser/sax_token_parser.cpp b/src/parser/sax_token_parser.cpp new file mode 100644 index 0000000..fdf80c6 --- /dev/null +++ b/src/parser/sax_token_parser.cpp @@ -0,0 +1,110 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "orcus/sax_token_parser.hpp" +#include "orcus/tokens.hpp" + +#include <mdds/sorted_string_map.hpp> +#include <cctype> + +namespace orcus { + +namespace { + +enum class decl_attr_type { unknown, version, encoding, standalone }; + +namespace decl_attr { + +using map_type = mdds::sorted_string_map<decl_attr_type, mdds::string_view_map_entry>; + +// Keys must be sorted. +constexpr map_type::entry entries[] = { + { "encoding", decl_attr_type::encoding }, + { "standalone", decl_attr_type::standalone }, + { "version", decl_attr_type::version }, +}; + +const map_type& get() +{ + static map_type mt(entries, std::size(entries), decl_attr_type::unknown); + return mt; +} + +} // namespace decl_attr + +} + +sax_token_handler_wrapper_base::sax_token_handler_wrapper_base(const tokens& _tokens) : + m_tokens(_tokens) {} + +xml_token_t sax_token_handler_wrapper_base::tokenize(std::string_view name) const +{ + xml_token_t token = XML_UNKNOWN_TOKEN; + if (!name.empty()) + token = m_tokens.get_token(name); + return token; +} + +void sax_token_handler_wrapper_base::set_element(const sax_ns_parser_element& elem) +{ + m_elem.ns = elem.ns; + m_elem.name = tokenize(elem.name); + m_elem.raw_name = elem.name; +} + +void sax_token_handler_wrapper_base::attribute(std::string_view name, std::string_view val) +{ + decl_attr_type dat = decl_attr::get().find(name); + + switch (dat) + { + case decl_attr_type::version: + { + const char* p = val.data(); + const char* p_end = p + val.size(); + + long v; + const char* endptr = parse_integer(p, p_end, v); + + if (!endptr || endptr >= p_end || *endptr != '.') + break; + + m_declaration.version_major = v; + p = endptr + 1; + + endptr = parse_integer(p, p_end, v); + + if (!endptr || endptr > p_end) + break; + + m_declaration.version_minor = v; + break; + } + case decl_attr_type::encoding: + { + m_declaration.encoding = to_character_set(val); + break; + } + case decl_attr_type::standalone: + m_declaration.standalone = (val == "yes") ? true : false; + break; + default: + ; + } +} + +void sax_token_handler_wrapper_base::attribute(const sax_ns_parser_attribute& attr) +{ + m_elem.attrs.push_back( + xml_token_attr_t( + attr.ns, tokenize(attr.name), attr.name, + attr.value, attr.transient)); +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/parser/sax_token_parser_test.cpp b/src/parser/sax_token_parser_test.cpp new file mode 100644 index 0000000..d473196 --- /dev/null +++ b/src/parser/sax_token_parser_test.cpp @@ -0,0 +1,239 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "test_global.hpp" +#include "orcus/sax_token_parser.hpp" +#include "orcus/tokens.hpp" +#include "orcus/xml_namespace.hpp" + +#include <cstring> + +using namespace std; +using namespace orcus; + +void test_handler() +{ + const char* test_code = "<?xml version=\"1.0\"?><root/>"; + + orcus::sax_token_handler hdl; + orcus::tokens token_map(nullptr, 0); + orcus::xmlns_repository repo; + orcus::xmlns_context cxt = repo.create_context(); + orcus::sax_token_parser<orcus::sax_token_handler> parser(test_code, token_map, cxt, hdl); + parser.parse(); +} + +void test_sax_token_parser_1() +{ + // Test XML content. + const char* content = "<?xml version=\"1.0\"?><root><andy/><bruce/><charlie/><david/><edward/><frank/></root>"; + + // Array of tokens to define for this test. + const char* token_names[] = { + "??", // 0 + "andy", // 1 + "bruce", // 2 + "charlie", // 3 + "david", // 4 + "edward" // 5 + }; + + size_t token_count = std::size(token_names); + + // Token constants. + const xml_token_t op_andy = 1; + const xml_token_t op_bruce = 2; + const xml_token_t op_charlie = 3; + const xml_token_t op_david = 4; + const xml_token_t op_edward = 5; + + struct check + { + const char* raw_name; + xml_token_t token; + bool start_element; + }; + + // Expected outcome. + const check checks[] = { + { "root", XML_UNKNOWN_TOKEN, true }, // name not on the master token list. + { "andy", op_andy, true }, + { "andy", op_andy, false }, + { "bruce", op_bruce, true }, + { "bruce", op_bruce, false }, + { "charlie", op_charlie, true }, + { "charlie", op_charlie, false }, + { "david", op_david, true }, + { "david", op_david, false }, + { "edward", op_edward, true }, + { "edward", op_edward, false }, + { "frank", XML_UNKNOWN_TOKEN, true }, // name not on the master token list. + { "frank", XML_UNKNOWN_TOKEN, false }, // name not on the master token list. + { "root", XML_UNKNOWN_TOKEN, false }, // name not on the master token list. + }; + + class handler + { + const check* mp_head; + const check* mp_check; + public: + handler(const check* p) : mp_head(p), mp_check(p) {} + + void declaration(const orcus::xml_declaration_t&) {} + + void start_element(const orcus::xml_token_element_t& elem) + { + assert(std::string_view(mp_check->raw_name) == elem.raw_name); + assert(mp_check->token == elem.name); + assert(mp_check->start_element); + ++mp_check; + } + + void end_element(const orcus::xml_token_element_t& elem) + { + assert(std::string_view(mp_check->raw_name) == elem.raw_name); + assert(mp_check->token == elem.name); + assert(!mp_check->start_element); + ++mp_check; + } + + void characters(std::string_view /*val*/, bool /*transient*/) {} + + size_t get_token_count() const + { + return std::distance(mp_head, mp_check); + } + }; + + handler hdl(checks); + tokens token_map(token_names, token_count); + xmlns_repository ns_repo; + xmlns_context ns_cxt = ns_repo.create_context(); + sax_token_parser<handler> parser(content, token_map, ns_cxt, hdl); + parser.parse(); + + assert(hdl.get_token_count() == std::size(checks)); +} + +void test_unicode_string() +{ + const char* content1 = "<?xml version=\"1.0\"?><root>!</root>"; + const char* content2 = "<?xml version=\"1.0\"?><root>¶</root>"; + const char* content3 = "<?xml version=\"1.0\"?><root>₹</root>"; + + class handler + { + std::string_view str; + public: + handler(std::string_view _str): + str(_str) + {} + + void declaration(const orcus::xml_declaration_t&) {} + + void start_element(const orcus::xml_token_element_t& /*elem*/) + { + } + + void end_element(const orcus::xml_token_element_t& /*elem*/) + { + } + + void characters(std::string_view val, bool /*transient*/) + { + std::cout << "charachters:" << std::endl; + std::cout << val << std::endl; + assert(val == str); + } + }; + + const char* token_names[] = { + "???", + }; + size_t token_count = std::size(token_names); + + tokens token_map(token_names, token_count); + xmlns_repository ns_repo; + xmlns_context ns_cxt = ns_repo.create_context(); + handler hdl(u8"\u0021"); + sax_token_parser<handler> parser1(content1, token_map, ns_cxt, hdl); + parser1.parse(); + hdl = handler(u8"\u00B6"); + sax_token_parser<handler> parser2(content2, token_map, ns_cxt, hdl); + parser2.parse(); + hdl = handler(u8"\u20B9"); + sax_token_parser<handler> parser3(content3, token_map, ns_cxt, hdl); + parser3.parse(); +} + +void test_declaration() +{ + class handler + { + xml_declaration_t& m_decl; + public: + handler(xml_declaration_t& decl) : m_decl(decl) {} + + void declaration(const xml_declaration_t& decl) + { + m_decl = decl; + } + + void start_element(const xml_token_element_t&) {} + void end_element(const xml_token_element_t&) {} + void characters(std::string_view, bool) {} + }; + + std::vector<const char*> token_names = {}; + tokens token_map(token_names.data(), token_names.size()); + xmlns_repository ns_repo; + xmlns_context ns_cxt = ns_repo.create_context(); + + struct check + { + std::string content; + xml_declaration_t decl; + }; + + std::vector<check> checks = + { + { + "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"no\"?><root/>", + { 1, 0, character_set_t::utf_8, false } + }, + { + "<?xml version=\"1.1\" encoding=\"windows-1253\" standalone=\"yes\"?><root/>", + { 1, 1, character_set_t::windows_1253, true } + }, + { + "<?xml version=\"2.0\" encoding=\"US-ASCII\" standalone=\"yes\"?><root/>", + { 2, 0, character_set_t::us_ascii, true } + }, + }; + + for (const check& c : checks) + { + xml_declaration_t decl; + handler hdl(decl); + sax_token_parser<handler> parser(c.content, token_map, ns_cxt, hdl); + parser.parse(); + + assert(decl == c.decl); + } +} + +int main() +{ + test_handler(); + test_sax_token_parser_1(); + test_unicode_string(); + test_declaration(); + + return EXIT_SUCCESS; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/parser/sax_token_parser_thread.cpp b/src/parser/sax_token_parser_thread.cpp new file mode 100644 index 0000000..3d7b16b --- /dev/null +++ b/src/parser/sax_token_parser_thread.cpp @@ -0,0 +1,204 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "orcus/sax_token_parser_thread.hpp" +#include "orcus/sax_token_parser.hpp" +#include "orcus/string_pool.hpp" +#include "orcus/detail/parser_token_buffer.hpp" +#include "orcus/tokens.hpp" +#include "orcus/xml_namespace.hpp" + +#include <limits> +#include <iostream> + +namespace orcus { namespace sax { + +parse_token::parse_token() : type(parse_token_t::unknown) {} + +parse_token::parse_token(std::string_view _characters) : + type(parse_token_t::characters), + value(_characters) +{ +} + +parse_token::parse_token(parse_token_t _type, const xml_token_element_t* _element) : + type(_type), value(_element) +{ +} + +parse_token::parse_token(std::string_view msg, std::ptrdiff_t offset) : + type(parse_token_t::parse_error), + value(parse_error_value_t{msg, offset}) +{ +} + +parse_token::parse_token(const parse_token& other) : + type(other.type), value(other.value) +{ +} + +bool parse_token::operator== (const parse_token& other) const +{ + return type == other.type && value == other.value; +} + +bool parse_token::operator!= (const parse_token& other) const +{ + return !operator==(other); +} + +struct parser_thread::impl +{ + orcus::detail::thread::parser_token_buffer<parse_tokens_t> m_token_buffer; + string_pool m_pool; + std::vector<std::unique_ptr<xml_token_element_t>> m_element_store; + + parse_tokens_t m_parser_tokens; // token buffer for the parser thread. + + const char* mp_char; + size_t m_size; + const tokens& m_tokens; + xmlns_context& m_ns_cxt; + + impl(const char* p, size_t n, const tokens& tks, xmlns_context& ns_cxt, size_t min_token_size, size_t max_token_size) : + m_token_buffer(min_token_size, max_token_size), + mp_char(p), m_size(n), m_tokens(tks), m_ns_cxt(ns_cxt) + { + } + + void check_and_notify() + { + m_token_buffer.check_and_notify(m_parser_tokens); + } + + void notify_and_finish() + { + m_token_buffer.notify_and_finish(m_parser_tokens); + } + + void abort() + { + m_token_buffer.abort(); + } + + void declaration(const orcus::xml_declaration_t& /*decl*/) + { + } + + void start_element(const orcus::xml_token_element_t& elem) + { + m_element_store.emplace_back(std::make_unique<orcus::xml_token_element_t>(elem)); + orcus::xml_token_element_t& this_elem = *m_element_store.back(); + + // Go through all attributes and intern transient strings. + std::for_each(this_elem.attrs.begin(), this_elem.attrs.end(), + [&](xml_token_attr_t& attr) + { + if (attr.transient) + { + attr.value = m_pool.intern(attr.value).first; + attr.transient = false; + } + } + ); + + m_parser_tokens.emplace_back(parse_token_t::start_element, m_element_store.back().get()); + check_and_notify(); + } + + void end_element(const orcus::xml_token_element_t& elem) + { + assert(elem.attrs.empty()); + + m_element_store.emplace_back(std::make_unique<orcus::xml_token_element_t>(elem)); + m_parser_tokens.emplace_back(parse_token_t::end_element, m_element_store.back().get()); + check_and_notify(); + } + + void characters(std::string_view val, bool transient) + { + if (transient) + m_parser_tokens.emplace_back(m_pool.intern(val).first); + else + m_parser_tokens.emplace_back(val); + + check_and_notify(); + } + + void start() + { + try + { + try + { + orcus::sax_token_parser<impl> parser({mp_char, m_size}, m_tokens, m_ns_cxt, *this); + parser.parse(); + } + catch (const malformed_xml_error& e) + { + std::string_view s = m_pool.intern(e.what()).first; + m_parser_tokens.emplace_back(s, e.offset()); + } + + // TODO : add more exceptions that need to be tokenized and processed by the client thread. + + notify_and_finish(); + } + catch (const orcus::detail::parsing_aborted_error&) + { + // This is used only to abort the parsing thread prematurely. + } + } + + bool next_tokens(parse_tokens_t& tokens) + { + return m_token_buffer.next_tokens(tokens); + } + + void swap_string_pool(string_pool& pool) + { + m_pool.swap(pool); + } +}; + +parser_thread::parser_thread( + const char* p, size_t n, const orcus::tokens& tks, xmlns_context& ns_cxt, size_t min_token_size) : + mp_impl(std::make_unique<parser_thread::impl>( + p, n, tks, ns_cxt, min_token_size, std::numeric_limits<size_t>::max()/2)) {} + +parser_thread::parser_thread( + const char* p, size_t n, const orcus::tokens& tks, xmlns_context& ns_cxt, size_t min_token_size, size_t max_token_size) : + mp_impl(std::make_unique<parser_thread::impl>( + p, n, tks, ns_cxt, min_token_size, max_token_size)) {} + +parser_thread::~parser_thread() +{ +} + +void parser_thread::start() +{ + mp_impl->start(); +} + +bool parser_thread::next_tokens(parse_tokens_t& tokens) +{ + return mp_impl->next_tokens(tokens); +} + +void parser_thread::swap_string_pool(string_pool& pool) +{ + mp_impl->swap_string_pool(pool); +} + +void parser_thread::abort() +{ + mp_impl->abort(); +} + +}} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/parser/stream.cpp b/src/parser/stream.cpp new file mode 100644 index 0000000..c0bbb28 --- /dev/null +++ b/src/parser/stream.cpp @@ -0,0 +1,447 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <orcus/stream.hpp> +#include <orcus/exception.hpp> + +#include "utf8.hpp" + +#include <sstream> +#include <fstream> +#include <tuple> +#include <cassert> +#include <algorithm> +#include <locale> +#include <codecvt> +#include <iostream> + +#include "filesystem_env.hpp" + +#include <boost/interprocess/file_mapping.hpp> +#include <boost/interprocess/mapped_region.hpp> + +namespace bip = boost::interprocess; + +namespace orcus { + +namespace { + +enum class unicode_t +{ + unknown, + utf16_be, + utf16_le +}; + +unicode_t check_unicode_type(const char* p, size_t n) +{ + if (n > 2) + { + if (p[0] == '\xFE' && p[1] == '\xFF') + return unicode_t::utf16_be; + + if (p[0] == '\xFF' && p[1] == '\xFE') + return unicode_t::utf16_le; + } + + return unicode_t::unknown; +} + +std::string convert_utf16_to_utf8(const char* p, size_t n, unicode_t ut) +{ + assert(ut == unicode_t::utf16_be || ut == unicode_t::utf16_le); + + if (n & 0x01) + throw std::invalid_argument("size of a UTF-16 string must be divisible by 2."); + + p += 2; // skip the BOM. + + size_t n_buf = n / 2u - 1; + std::u16string buf(n_buf, 0); + + switch (ut) + { + case unicode_t::utf16_be: + { + for (size_t i = 0; i < n_buf; ++i) + { + size_t offset = i * 2; + buf[i] = static_cast<char16_t>(p[offset+1] | p[offset] << 8); + } + break; + } + case unicode_t::utf16_le: + { + for (size_t i = 0; i < n_buf; ++i) + { + size_t offset = i * 2; + buf[i] = static_cast<char16_t>(p[offset] | p[offset+1]); + } + break; + } + default: + ; + } + +#if defined(_MSC_VER) + // char16_t does not work with MSVC just yet. This is a workaround. c.f. + // https://stackoverflow.com/questions/32055357/visual-studio-c-2015-stdcodecvt-with-char16-t-or-char32-t + const int16_t* pi16 = reinterpret_cast<const int16_t*>(buf.data()); + const int16_t* pi16_end = pi16 + buf.size(); + std::wstring_convert<std::codecvt_utf8_utf16<int16_t>, int16_t> conversion; + return conversion.to_bytes(pi16, pi16_end); +#else + std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> conversion; + return conversion.to_bytes(buf); +#endif +} + +std::tuple<std::string_view, size_t, size_t> find_line_with_offset(std::string_view strm, std::ptrdiff_t offset) +{ + const char* p0 = strm.data(); + const char* p_end = p0 + strm.size(); + const char* p_offset = p0 + offset; + + if (p_offset >= p_end) + { + std::ostringstream os; + os << "offset value of " << offset << " is out-of-bound for a stream of length " << strm.size(); + throw std::invalid_argument(os.str()); + } + + // Determine the line number. + std::size_t line_num = 0; + for (const char* p = p0; p != p_offset; ++p) + { + if (*p == '\n') + ++line_num; + } + + // Determine the beginning of the line. + const char* p_line_start = p_offset; + + // if the error points at the new line character + // we have most likely an unterminated quote. + // Report the line with the actual error. + if (*p_offset == '\n' && offset > 0) + --p_line_start; + + for (; p0 <= p_line_start; --p_line_start) + { + if (*p_line_start == '\n') + break; + } + + ++p_line_start; + assert(p0 <= p_line_start); + + // Determine the end of the line. + const char* p_line_end = p_offset; + for (; p_line_end < p_end; ++p_line_end) + { + if (*p_line_end == '\n') + // one character after the last character of the line. + break; + } + + assert(p_line_start <= p_offset); + std::size_t offset_on_line = std::distance(p_line_start, p_offset); + std::string_view line(p_line_start, p_line_end - p_line_start); + + return std::make_tuple(line, line_num, offset_on_line); +} + +} // anonymous namespace + +struct file_content::impl +{ + boost::uintmax_t content_size; + bip::file_mapping mapped_file; + bip::mapped_region mapped_region; + + std::string buffer; // its own buffer in case of stream conversion. + + const char* content; + + impl() : content_size(0), content(nullptr) {} + + impl(std::string_view filepath) : + content_size(fs::file_size(std::string{filepath}.c_str())), + mapped_file(std::string{filepath}.c_str(), bip::read_only), + mapped_region(mapped_file, bip::read_only, 0, content_size), + content(nullptr) + { + content = static_cast<const char*>(mapped_region.get_address()); + } +}; + +file_content::file_content() : + mp_impl(std::make_unique<impl>()) {} + +file_content::file_content(file_content&& other) = default; + +file_content::file_content(std::string_view filepath) : + mp_impl(std::make_unique<impl>(filepath)) {} + +file_content::~file_content() = default; + +const char* file_content::data() const +{ + return mp_impl->content; +} + +size_t file_content::size() const +{ + return mp_impl->content_size; +} + +bool file_content::empty() const +{ + return mp_impl->content_size == 0; +} + +void file_content::swap(file_content& other) +{ + std::swap(mp_impl, other.mp_impl); +} + +void file_content::load(std::string_view filepath) +{ + file_content tmp(filepath); + swap(tmp); +} + +void file_content::convert_to_utf8() +{ + unicode_t ut = check_unicode_type(mp_impl->content, mp_impl->content_size); + + switch (ut) + { + case unicode_t::utf16_be: + case unicode_t::utf16_le: + { + // Convert to utf-8 stream, and reset the content pointer and size. + mp_impl->buffer = convert_utf16_to_utf8(mp_impl->content, mp_impl->content_size, ut); + mp_impl->content = mp_impl->buffer.data(); + mp_impl->content_size = mp_impl->buffer.size(); + break; + } + default: + ; + } +} + +std::string_view file_content::str() const +{ + return std::string_view(mp_impl->content, mp_impl->content_size); +} + +struct memory_content::impl +{ + std::string_view content; + std::string buffer; // its own buffer in case of stream conversion. + + impl() {} + impl(std::string_view s) : content(s) {} +}; + +memory_content::memory_content() : mp_impl(std::make_unique<impl>()) {} + +memory_content::memory_content(std::string_view s) : + mp_impl(std::make_unique<impl>(s)) {} + +memory_content::memory_content(memory_content&& other) = default; +memory_content::~memory_content() = default; + +const char* memory_content::data() const +{ + return mp_impl->content.data(); +} + +size_t memory_content::size() const +{ + return mp_impl->content.size(); +} + +bool memory_content::empty() const +{ + return mp_impl->content.empty(); +} + +void memory_content::swap(memory_content& other) +{ + std::swap(mp_impl, other.mp_impl); +} + +void memory_content::convert_to_utf8() +{ + unicode_t ut = check_unicode_type(mp_impl->content.data(), mp_impl->content.size()); + + switch (ut) + { + case unicode_t::utf16_be: + case unicode_t::utf16_le: + { + // Convert to utf-8 stream, and reset the content pointer and size. + mp_impl->buffer = convert_utf16_to_utf8(mp_impl->content.data(), mp_impl->content.size(), ut); + mp_impl->content = mp_impl->buffer; + break; + } + default: + ; + } +} + +std::string_view memory_content::str() const +{ + return mp_impl->content; +} + +line_with_offset::line_with_offset(std::string _line, std::size_t _line_number, std::size_t _offset_on_line) : + line(std::move(_line)), + line_number(_line_number), + offset_on_line(_offset_on_line) +{} + +line_with_offset::line_with_offset(const line_with_offset& other) = default; +line_with_offset::line_with_offset(line_with_offset&& other) = default; +line_with_offset::~line_with_offset() = default; + +bool line_with_offset::operator== (const line_with_offset& other) const +{ + return line == other.line && line_number == other.line_number && offset_on_line == other.offset_on_line; +} + +bool line_with_offset::operator!= (const line_with_offset& other) const +{ + return !operator==(other); +} + +std::string create_parse_error_output(std::string_view strm, std::ptrdiff_t offset) +{ + if (strm.empty() || offset < 0) + return std::string(); + + const size_t max_line_length = 60; + offset = std::min<std::ptrdiff_t>(strm.size() - 1, offset); + + auto line_info = find_line_with_offset(strm, offset); + std::string_view line = std::get<0>(line_info); + size_t line_num = std::get<1>(line_info); + size_t offset_on_line = std::get<2>(line_info); + + if (offset_on_line < 30) + { + std::ostringstream os; + os << (line_num+1) << ":" << (offset_on_line+1) << ": "; + size_t line_num_width = os.str().size(); + + // Truncate line if it's too long. + if (line.size() > max_line_length) + line = std::string_view(line.data(), max_line_length); + + os << line << std::endl; + + for (size_t i = 0; i < (offset_on_line+line_num_width); ++i) + os << ' '; + os << '^'; + return os.str(); + } + + // The error line is too long. Only show a segment of the line where the + // error occurred. + + const size_t fixed_offset = 20; + + size_t line_start = offset_on_line - fixed_offset; + size_t line_end = line_start + max_line_length; + if (line_end > line.size()) + line_end = line.size(); + + size_t line_length = line_end - line_start; + + line = std::string_view(line.data()+line_start, line_length); + + std::ostringstream os; + os << line_num << ":" << (line_start+1) << ": "; + size_t line_num_width = os.str().size(); + + os << line << std::endl; + + for (size_t i = 0; i < (fixed_offset+line_num_width); ++i) + os << ' '; + os << '^'; + + return os.str(); +} + +line_with_offset locate_line_with_offset(std::string_view strm, std::ptrdiff_t offset) +{ + auto line_info = find_line_with_offset(strm, offset); + std::string_view line = std::get<0>(line_info); + size_t line_num = std::get<1>(line_info); + size_t offset_on_line = std::get<2>(line_info); + + return line_with_offset(std::string{line}, line_num, offset_on_line); +} + +size_t locate_first_different_char(std::string_view left, std::string_view right) +{ + if (left.empty() || right.empty()) + // If one of them is empty, then the first characters are considered + // different. + return 0; + + size_t n = std::min(left.size(), right.size()); + const char* p1 = left.data(); + const char* p2 = right.data(); + const char* p1_end = p1 + n; + + for (; p1 != p1_end; ++p1, ++p2) + { + if (*p1 != *p2) + return std::distance(left.data(), p1); + } + + return n; +} + +std::size_t calc_logical_string_length(std::string_view s) +{ + std::size_t length = 0; + + const char* p = s.data(); + const char* p_end = p + s.size(); + + while (p < p_end) + { + ++length; + + auto n_bytes = calc_utf8_byte_length(*p); + if (!n_bytes || n_bytes > 4) + { + std::ostringstream os; + os << "'" << s << "' contains invalid character at position " << std::distance(s.data(), p); + throw std::invalid_argument(os.str()); + } + + p += n_bytes; + } + + if (p != p_end) + { + std::ostringstream os; + os << "last character of '" << s << "' ended prematurely"; + throw std::invalid_argument(os.str()); + } + + return length; +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/parser/stream_test.cpp b/src/parser/stream_test.cpp new file mode 100644 index 0000000..1a6e9fb --- /dev/null +++ b/src/parser/stream_test.cpp @@ -0,0 +1,144 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "test_global.hpp" +#include "orcus/stream.hpp" + +#include <cstdlib> +#include <string> +#include <vector> + +using namespace std; +using namespace orcus; + +void test_stream_create_error_output() +{ + test::stack_printer __sp__(__func__); + + string output = create_parse_error_output("{}", 1); + cout << output << endl; + const char* expected = "1:2: {}\n ^"; + assert(output == expected); +} + +void test_stream_locate_first_different_char() +{ + test::stack_printer __sp__(__func__); + + struct test_case + { + const char* left; + const char* right; + size_t expected; + }; + + std::vector<test_case> test_cases = { + { "", "a", 0 }, + { "a", "", 0 }, + { "", "", 0 }, + { " ", "b", 0 }, + { "abc", "abc", 3 }, + { "abcd", "abce", 3 }, + { "abc", "bbc", 0 }, + { "abc", "acc", 1 }, + }; + + for (const test_case& tc : test_cases) + { + size_t actual = locate_first_different_char(tc.left, tc.right); + assert(actual == tc.expected); + } +} + +void test_stream_logical_string_length() +{ + test::stack_printer __sp__(__func__); + + struct check + { + std::string_view value; + std::size_t length; + }; + + constexpr check checks[] = { + { "東京", 2 }, + { "大阪は暑い", 5 }, + { "New York", 8 }, + { "日本は英語で言うとJapan", 14 }, + { "fabriqué", 8 }, + { "garçon", 6 }, + { "вход", 4 }, + { "выход", 5 }, + { "помогите", 8 }, + { "Nähe", 4 }, + }; + + for (auto [value, expected_len] : checks) + { + std::size_t len = calc_logical_string_length(value); + std::cout << "'" << value << "' (length=" << len << ")" << std::endl; + assert(len == expected_len); + } +} + +void test_stream_locate_line_with_offset() +{ + test::stack_printer __sp__(__func__); + + std::string strm = "one\ntwo\nthree"; + + struct check + { + std::ptrdiff_t offset; + line_with_offset expected; + }; + + const std::vector<check> checks = { + { 0, { "one", 0, 0 } }, + { 1, { "one", 0, 1 } }, + { 2, { "one", 0, 2 } }, + { 3, { "one", 0, 3 } }, // on line break + { 4, { "two", 1, 0 } }, + { 5, { "two", 1, 1 } }, + { 6, { "two", 1, 2 } }, + { 7, { "two", 1, 3 } }, // on line break + { 8, { "three", 2, 0 } }, + { 9, { "three", 2, 1 } }, + { 10, { "three", 2, 2 } }, + { 11, { "three", 2, 3 } }, + { 12, { "three", 2, 4 } }, + }; + + for (const auto& c : checks) + { + auto res = locate_line_with_offset(strm, c.offset); + assert(res == c.expected); + } + + try + { + auto res = locate_line_with_offset(strm, strm.size()); + assert(!"exception should have been thrown for out-of-bound offset!"); + } + catch (const std::invalid_argument& e) + { + // expected + cout << "exception thrown as expected: '" << e.what() << "'" << endl; + } +} + +int main() +{ + test_stream_create_error_output(); + test_stream_locate_first_different_char(); + test_stream_logical_string_length(); + test_stream_locate_line_with_offset(); + + return EXIT_SUCCESS; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/parser/string_pool.cpp b/src/parser/string_pool.cpp new file mode 100644 index 0000000..e438da5 --- /dev/null +++ b/src/parser/string_pool.cpp @@ -0,0 +1,137 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <orcus/string_pool.hpp> +#include <orcus/exception.hpp> + +#include <iostream> +#include <unordered_set> +#include <vector> +#include <memory> +#include <cassert> +#include <algorithm> +#include <string_view> + +#include <boost/pool/object_pool.hpp> + +namespace orcus { + +using std::cout; +using std::endl; + +using string_set_type = std::unordered_set<std::string_view>; +using string_store_type = boost::object_pool<std::string>; +using string_stores_type = std::vector<std::unique_ptr<string_store_type>>; + +struct string_pool::impl +{ + string_stores_type m_stores; + string_set_type m_set; + + impl() + { + // first element is the active store used for the current instance. + m_stores.push_back(std::make_unique<string_store_type>(256, 0)); + } +}; + +string_pool::string_pool() : mp_impl(std::make_unique<impl>()) {} + +string_pool::string_pool(string_pool&& other) : mp_impl(std::move(other.mp_impl)) {} + +string_pool::~string_pool() = default; + +std::pair<std::string_view, bool> string_pool::intern(std::string_view str) +{ + if (str.empty()) + return std::pair<std::string_view, bool>(std::string_view(), false); + + string_set_type::const_iterator itr = mp_impl->m_set.find(str); + if (itr == mp_impl->m_set.end()) + { + // This string has not been interned. Intern it. + string_store_type& store = *mp_impl->m_stores[0]; + std::string* p = store.construct(str); + if (!p) + throw general_error("failed to intern a new string instance."); + + std::pair<string_set_type::iterator,bool> r = + mp_impl->m_set.emplace(p->data(), p->size()); + if (!r.second) + throw general_error("failed to intern a new string instance."); + + std::string_view ps = *r.first; + assert(ps == str); + + return std::pair<std::string_view, bool>(ps, true); + } + + // This string has already been interned. + + std::string_view stored_str = *itr; + assert(stored_str == str); + return std::pair<std::string_view, bool>(stored_str, false); +} + +std::vector<std::string_view> string_pool::get_interned_strings() const +{ + std::vector<std::string_view> sorted; + sorted.reserve(mp_impl->m_set.size()); + + for (std::string_view ps : mp_impl->m_set) + sorted.push_back(ps); + + std::sort(sorted.begin(), sorted.end()); + + return sorted; +} + +void string_pool::dump() const +{ + auto sorted = get_interned_strings(); + + cout << "interned string count: " << sorted.size() << endl; + + // Dump them all to stdout. + size_t counter = 0; + for (std::string_view s : sorted) + cout << counter++ << ": '" << s << "'" << endl; +} + +void string_pool::clear() +{ + mp_impl = std::make_unique<impl>(); +} + +size_t string_pool::size() const +{ + return mp_impl->m_set.size(); +} + +void string_pool::swap(string_pool& other) +{ + std::swap(mp_impl, other.mp_impl); +} + +void string_pool::merge(string_pool& other) +{ + while (!other.mp_impl->m_stores.empty()) + { + mp_impl->m_stores.push_back( + std::move(other.mp_impl->m_stores.back())); + other.mp_impl->m_stores.pop_back(); + } + + for (std::string_view p : other.mp_impl->m_set) + mp_impl->m_set.insert(p); + + other.mp_impl->m_set.clear(); +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/parser/string_pool_test.cpp b/src/parser/string_pool_test.cpp new file mode 100644 index 0000000..7d3f864 --- /dev/null +++ b/src/parser/string_pool_test.cpp @@ -0,0 +1,134 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "test_global.hpp" +#include <orcus/string_pool.hpp> + +#include <type_traits> + +using namespace orcus; + +void test_basic() +{ + const char* static_text = "test"; + + string_pool pool; + assert(pool.size() == 0); + + std::pair<std::string_view, bool> ret = pool.intern("foo"); + assert(ret.first == "foo"); + assert(ret.second); // new instance + + ret = pool.intern("foo"); + assert(ret.first == "foo"); + assert(!ret.second); // existing instance. + + // Empty strings should not be interned. + ret = pool.intern(""); + assert(ret.first.empty()); + assert(!ret.second); + + ret = pool.intern("A"); + std::cout << "interned string: " << ret.first << std::endl; + assert(ret.second); + assert(pool.size() == 2); + + // Duplicate string. + ret = pool.intern("A"); + std::cout << "interned string: " << ret.first << std::endl; + assert(!ret.second); + + ret = pool.intern("B"); + std::cout << "interned string: " << ret.first << std::endl; + assert(pool.size() == 3); + + // Interning an already-intern string should return a string_view with + // identical memory address. + std::string_view str = ret.first; + std::string_view str2 = pool.intern(str).first; + assert(str == str2); + assert(pool.size() == 3); + assert(str.data() == str2.data()); // their memory address should be identical. + + std::string_view static_str(static_text); + ret = pool.intern(static_str); + str = ret.first; + std::cout << "interned string: " << str << std::endl; + assert(pool.size() == 4); + assert(str == static_str); + assert(str.data() != static_str.data()); + + // Make sure that the pool remains usable after calling clear(). + pool.clear(); + assert(pool.size() == 0); + ret = pool.intern(static_str); + assert(ret.second); // it should be a new string + assert(ret.first == static_str); +} + +void test_merge() +{ + string_pool pool1; + std::unique_ptr<string_pool> pool2(std::make_unique<string_pool>()); + + pool1.intern("A"); + pool1.intern("B"); + pool1.intern("C"); + std::string_view v1 = pool1.intern("same value").first; + + pool2->intern("D"); + pool2->intern("E"); + pool2->intern("F"); + std::string_view v2 = pool2->intern("same value").first; + + assert(pool1.size() == 4); + assert(pool2->size() == 4); + + pool1.merge(*pool2); + + assert(pool1.size() == 7); + assert(pool2->size() == 0); + + pool2.reset(); // Delete the pool2 instance altogether. + + // This should not create a new entry. + auto r = pool1.intern("F"); + assert(!r.second); + + // v2 still points to the original string in pool2, which should now be in + // the merged store in pool1 (thus valid). + assert(v1 == v2); + + std::vector<std::string_view> entries = pool1.get_interned_strings(); + assert(entries.size() == pool1.size()); +} + +void test_move() +{ + static_assert(!std::is_copy_constructible_v<orcus::string_pool>); + static_assert(std::is_move_constructible_v<orcus::string_pool>); + + string_pool pool1; + pool1.intern("A"); + pool1.intern("B"); + pool1.intern("C"); + pool1.intern("D"); + pool1.intern("E"); + + string_pool pool2 = std::move(pool1); + assert(pool2.size() == 5); +} + +int main() +{ + test_basic(); + test_merge(); + test_move(); + + return EXIT_SUCCESS; +} +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/parser/threaded_json_parser_test.cpp b/src/parser/threaded_json_parser_test.cpp new file mode 100644 index 0000000..5ac8053 --- /dev/null +++ b/src/parser/threaded_json_parser_test.cpp @@ -0,0 +1,187 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "test_global.hpp" +#include <orcus/threaded_json_parser.hpp> + +#include <cstring> + +using namespace orcus; +using namespace std; + +class handler +{ + json::parse_tokens_t m_tokens; + +public: + void begin_parse() + { + m_tokens.emplace_back(json::parse_token_t::begin_parse); + } + + void end_parse() + { + m_tokens.emplace_back(json::parse_token_t::end_parse); + } + + void begin_array() + { + m_tokens.emplace_back(json::parse_token_t::begin_array); + } + + void end_array() + { + m_tokens.emplace_back(json::parse_token_t::end_array); + } + + void begin_object() + { + m_tokens.emplace_back(json::parse_token_t::begin_object); + } + + void object_key(const char* p, size_t len, bool transient) + { + assert(!transient); // transient is never true with the threaded parser. + m_tokens.emplace_back(json::parse_token_t::object_key, std::string_view{p, len}); + } + + void end_object() + { + m_tokens.emplace_back(json::parse_token_t::end_object); + } + + void boolean_true() + { + m_tokens.emplace_back(json::parse_token_t::boolean_true); + } + + void boolean_false() + { + m_tokens.emplace_back(json::parse_token_t::boolean_false); + } + + void null() + { + m_tokens.emplace_back(json::parse_token_t::null); + } + + void string(const char* p, size_t len, bool transient) + { + assert(!transient); // transient is never true with the threaded parser. + m_tokens.emplace_back(json::parse_token_t::string, std::string_view{p, len}); + } + + void number(double val) + { + m_tokens.emplace_back(val); + } + + const json::parse_tokens_t& get_tokens() const + { + return m_tokens; + } +}; + +void test_parser(const char* src, const json::parse_tokens_t& expected) +{ + cout << "source: " << src << endl; + + handler hdl; + threaded_json_parser<handler> parser(src, std::strlen(src), hdl, 5, 5); + parser.parse(); + + if (hdl.get_tokens() != expected) + { + cout << "Expected tokens:" << endl; + cout << expected; + cout << "Actual tokens:" << endl; + cout << hdl.get_tokens(); + abort(); + } +} + +void test_threaded_json_parser_basic() +{ + struct test_case + { + const char* source; + json::parse_tokens_t expected; + }; + + test_case tcs[] = + { + { + "[1,2,3]", + { + { json::parse_token_t::begin_parse }, + { json::parse_token_t::begin_array }, + { 1.0 }, + { 2.0 }, + { 3.0 }, + { json::parse_token_t::end_array }, + { json::parse_token_t::end_parse }, + } + }, + { + "{\"foo\": [true, false, null]}", + { + { json::parse_token_t::begin_parse }, + { json::parse_token_t::begin_object }, + { json::parse_token_t::object_key, std::string_view{"foo"} }, + { json::parse_token_t::begin_array }, + { json::parse_token_t::boolean_true }, + { json::parse_token_t::boolean_false }, + { json::parse_token_t::null }, + { json::parse_token_t::end_array }, + { json::parse_token_t::end_object }, + { json::parse_token_t::end_parse }, + } + } + }; + + for (size_t i = 0, n = std::size(tcs); i < n; ++i) + test_parser(tcs[i].source, tcs[i].expected); +} + +void test_threaded_json_parser_invalid() +{ + const char* invalids[] = { + "[foo]", + "[qwerty]", + "[1,2] null", + "{\"key\" 1: 12}", + "[1,,2]", + "\"key\": {\"inner\": 12}" + }; + + for (size_t i = 0; i < std::size(invalids); ++i) + { + const char* src = invalids[i]; + + try + { + handler hdl; + threaded_json_parser<handler> parser(src, std::strlen(src), hdl, 1); + parser.parse(); + assert(false); + } + catch (const parse_error&) + { + // works as expected. + cout << "invalid source: " << src << endl; + } + } +} + +int main() +{ + test_threaded_json_parser_basic(); + test_threaded_json_parser_invalid(); + return EXIT_SUCCESS; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/parser/threaded_sax_token_parser_test.cpp b/src/parser/threaded_sax_token_parser_test.cpp new file mode 100644 index 0000000..1338b2a --- /dev/null +++ b/src/parser/threaded_sax_token_parser_test.cpp @@ -0,0 +1,190 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "test_global.hpp" +#include "orcus/threaded_sax_token_parser.hpp" +#include "orcus/tokens.hpp" +#include "orcus/xml_namespace.hpp" +#include "orcus/parser_base.hpp" +#include "orcus/stream.hpp" + +#include <cstring> + +using namespace std; +using namespace orcus; + +void test_sax_token_parser_1() +{ + // Array of tokens to define for this test. + const char* token_names[] = { + "??", // 0 + "andy", // 1 + "bruce", // 2 + "charlie", // 3 + "david", // 4 + "edward" // 5 + }; + + size_t token_count = std::size(token_names); + + // Token constants. + const xml_token_t op_andy = 1; + const xml_token_t op_bruce = 2; + const xml_token_t op_charlie = 3; + const xml_token_t op_david = 4; + const xml_token_t op_edward = 5; + + struct check + { + const char* raw_name; + xml_token_t token; + bool start_element; + }; + + tokens token_map(token_names, token_count); + xmlns_repository ns_repo; + xmlns_context ns_cxt = ns_repo.create_context(); + + { + // Test XML content. + const char* content = "<?xml version=\"1.0\"?><root><andy/><bruce/><charlie/><david/><edward/><frank/></root>"; + size_t content_size = strlen(content); + + // Expected outcome. + const check checks[] = { + { "root", XML_UNKNOWN_TOKEN, true }, // name not on the master token list. + { "andy", op_andy, true }, + { "andy", op_andy, false }, + { "bruce", op_bruce, true }, + { "bruce", op_bruce, false }, + { "charlie", op_charlie, true }, + { "charlie", op_charlie, false }, + { "david", op_david, true }, + { "david", op_david, false }, + { "edward", op_edward, true }, + { "edward", op_edward, false }, + { "frank", XML_UNKNOWN_TOKEN, true }, // name not on the master token list. + { "frank", XML_UNKNOWN_TOKEN, false }, // name not on the master token list. + { "root", XML_UNKNOWN_TOKEN, false }, // name not on the master token list. + }; + + class handler + { + const check* mp_head; + const check* mp_check; + public: + handler(const check* p) : mp_head(p), mp_check(p) {} + + void start_element(const orcus::xml_token_element_t& elem) + { + assert(std::string_view(mp_check->raw_name) == elem.raw_name); + assert(mp_check->token == elem.name); + assert(mp_check->start_element); + ++mp_check; + } + + void end_element(const orcus::xml_token_element_t& elem) + { + assert(std::string_view(mp_check->raw_name) == elem.raw_name); + assert(mp_check->token == elem.name); + assert(!mp_check->start_element); + ++mp_check; + } + + void characters(std::string_view /*val*/, bool /*transient*/) {} + + size_t get_token_count() const + { + return std::distance(mp_head, mp_check); + } + }; + + handler hdl(checks); + threaded_sax_token_parser<handler> parser(content, content_size, token_map, ns_cxt, hdl, 1, 100); + parser.parse(); + + assert(hdl.get_token_count() == std::size(checks)); + } + + { + // This content intentially contains invalid XML part at offset 28. + const char* content = "<?xml version=\"1.0\"?><root><<andy/><bruce/><charlie/><david/><edward/><frank/></root>"; + size_t content_size = strlen(content); + + class handler + { + public: + handler() {} + + void start_element(const orcus::xml_token_element_t& /*elem*/) {} + + void end_element(const orcus::xml_token_element_t& /*elem*/) {} + + void characters(std::string_view /*val*/, bool /*transient*/) {} + }; + + try + { + handler hdl; + threaded_sax_token_parser<handler> parser(content, content_size, token_map, ns_cxt, hdl, 1, 100); + parser.parse(); + assert(!"An exception was expected, but one was not thrown."); + } + catch (const malformed_xml_error& e) + { + assert(e.offset() == 28u); + } + catch (const std::exception&) + { + assert(!"Wrong exception was thrown!"); + } + } + + { + // Test XML content. + const char* content = "<?xml version=\"1.0\"?><root><andy/><bruce/><charlie/><david/><edward/><frank/></root>"; + size_t content_size = strlen(content); + + class mock_exception : public std::exception {}; + + class handler + { + public: + handler() {} + + void start_element(const orcus::xml_token_element_t& /*elem*/) {} + + void end_element(const orcus::xml_token_element_t& /*elem*/) + { + throw mock_exception(); + } + + void characters(std::string_view /*val*/, bool /*transient*/) {} + }; + + handler hdl; + threaded_sax_token_parser<handler> parser(content, content_size, token_map, ns_cxt, hdl, 1, 100); + + try + { + parser.parse(); + assert(!"A mock exception was expected but not thrown."); + } + catch (const mock_exception&) + { + // expected. + } + } +} + +int main() +{ + test_sax_token_parser_1(); + return EXIT_SUCCESS; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/parser/tokens.cpp b/src/parser/tokens.cpp new file mode 100644 index 0000000..5d3c533 --- /dev/null +++ b/src/parser/tokens.cpp @@ -0,0 +1,44 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <orcus/tokens.hpp> + +namespace orcus { + +tokens::tokens(const char** token_names, size_t token_name_count) : + m_token_names(token_names), + m_token_name_count(token_name_count) +{ + for (size_t i = 0; i < m_token_name_count; ++i) + m_tokens.emplace(m_token_names[i], xml_token_t(i)); +} + +tokens::~tokens() = default; + +bool tokens::is_valid_token(xml_token_t token) const +{ + return token != XML_UNKNOWN_TOKEN; +} + +xml_token_t tokens::get_token(std::string_view name) const +{ + token_map_type::const_iterator itr = m_tokens.find(name); + if (itr == m_tokens.end()) + return XML_UNKNOWN_TOKEN; + return itr->second; +} + +std::string_view tokens::get_token_name(xml_token_t token) const +{ + if (size_t(token) >= m_token_name_count) + return ""; + + return m_token_names[token]; +} + +} +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/parser/types.cpp b/src/parser/types.cpp new file mode 100644 index 0000000..5d469c5 --- /dev/null +++ b/src/parser/types.cpp @@ -0,0 +1,1454 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <orcus/types.hpp> +#include <orcus/parser_global.hpp> +#include <orcus/xml_namespace.hpp> + +#include <limits> +#include <sstream> +#include <string_view> +#include <iomanip> +#include <mdds/sorted_string_map.hpp> + +#include "ostream_utils.hpp" + +namespace orcus { + +parse_error_value_t::parse_error_value_t() : + offset(0) +{ +} + +parse_error_value_t::parse_error_value_t(const parse_error_value_t& other) = default; + +parse_error_value_t::parse_error_value_t(std::string_view _str, std::ptrdiff_t _offset) : + str(_str), offset(_offset) +{ +} + +parse_error_value_t& parse_error_value_t::operator=(const parse_error_value_t& other) = default; + +bool parse_error_value_t::operator==(const parse_error_value_t& other) const +{ + return str == other.str && offset == other.offset; +} + +bool parse_error_value_t::operator!=(const parse_error_value_t& other) const +{ + return !operator==(other); +} + +xml_name_t::xml_name_t() noexcept : ns(XMLNS_UNKNOWN_ID), name() {} +xml_name_t::xml_name_t(xmlns_id_t _ns, std::string_view _name) : ns(_ns), name(_name) {} +xml_name_t::xml_name_t(const xml_name_t& other) = default; + +xml_name_t& xml_name_t::operator= (const xml_name_t& other) = default; + +bool xml_name_t::operator== (const xml_name_t& other) const noexcept +{ + return ns == other.ns && name == other.name; +} + +bool xml_name_t::operator!= (const xml_name_t& other) const noexcept +{ + return !operator==(other); +} + +std::string xml_name_t::to_string(const xmlns_context& cxt, to_string_type type) const +{ + std::ostringstream os; + + if (ns) + { + std::string_view ns_str; + switch (type) + { + case use_alias: + ns_str = cxt.get_alias(ns); + break; + case use_short_name: + ns_str = cxt.get_short_name(ns); + break; + + } + if (!ns_str.empty()) + os << ns_str << ':'; + } + os << name; + + return os.str(); +} + +std::string xml_name_t::to_string(const xmlns_repository& repo) const +{ + std::ostringstream os; + + if (ns) + { + std::string ns_str = repo.get_short_name(ns); + if (!ns_str.empty()) + os << ns_str << ':'; + } + os << name; + + return os.str(); +} + +xml_token_attr_t::xml_token_attr_t() : + ns(XMLNS_UNKNOWN_ID), name(XML_UNKNOWN_TOKEN), transient(false) {} + +xml_token_attr_t::xml_token_attr_t(const xml_token_attr_t& other) = default; + +xml_token_attr_t::xml_token_attr_t( + xmlns_id_t _ns, xml_token_t _name, std::string_view _value, bool _transient) : + ns(_ns), name(_name), value(_value), transient(_transient) {} + +xml_token_attr_t::xml_token_attr_t( + xmlns_id_t _ns, xml_token_t _name, std::string_view _raw_name, std::string_view _value, bool _transient) : + ns(_ns), name(_name), raw_name(_raw_name), value(_value), transient(_transient) {} + +xml_token_attr_t& xml_token_attr_t::operator=(const xml_token_attr_t& other) = default; + +xml_token_element_t::xml_token_element_t() : ns(nullptr), name(XML_UNKNOWN_TOKEN) {} + +xml_token_element_t::xml_token_element_t( + xmlns_id_t _ns, xml_token_t _name, std::string_view _raw_name, std::vector<xml_token_attr_t>&& _attrs) : + ns(_ns), name(_name), raw_name(_raw_name), attrs(std::move(_attrs)) {} + +xml_token_element_t::xml_token_element_t(const xml_token_element_t& other) : + ns(other.ns), name(other.name), raw_name(other.raw_name), attrs(other.attrs) {} + +xml_token_element_t::xml_token_element_t(xml_token_element_t&& other) : + ns(other.ns), name(other.name), raw_name(other.raw_name), attrs(std::move(other.attrs)) {} + +xml_declaration_t::xml_declaration_t() : + version_major(1), + version_minor(0), + encoding(character_set_t::unspecified), + standalone(false) {} + +xml_declaration_t::xml_declaration_t(uint8_t _version_major, uint8_t _version_minor, character_set_t _encoding, bool _standalone) : + version_major(_version_major), version_minor(_version_minor), encoding(_encoding), standalone(_standalone) {} + +xml_declaration_t::xml_declaration_t(const xml_declaration_t& other) : + version_major(other.version_major), + version_minor(other.version_minor), + encoding(other.encoding), + standalone(other.standalone) {} + +xml_declaration_t::~xml_declaration_t() {} + +xml_declaration_t& xml_declaration_t::operator= (const xml_declaration_t& other) +{ + version_major = other.version_major; + version_minor = other.version_minor; + encoding = other.encoding; + standalone = other.standalone; + return *this; +} + +bool xml_declaration_t::operator== (const xml_declaration_t& other) const +{ + return version_major == other.version_major && version_minor == other.version_minor && + encoding == other.encoding && standalone == other.standalone; +} + +bool xml_declaration_t::operator!= (const xml_declaration_t& other) const +{ + return !operator== (other); +} + +length_t::length_t() : unit(length_unit_t::unknown), value(0.0) {} + +length_t::length_t(length_unit_t _unit, double _value) : unit(_unit), value(_value) {} + +length_t::length_t(const length_t& other) = default; + +length_t& length_t::operator= (const length_t& other) = default; + +std::string length_t::to_string() const +{ + std::ostringstream os; + os << value; + + switch (unit) + { + case length_unit_t::centimeter: + os << " cm"; + break; + case length_unit_t::inch: + os << " in"; + break; + case length_unit_t::point: + os << " pt"; + break; + case length_unit_t::twip: + os << " twip"; + break; + case length_unit_t::unknown: + default: + ; + } + + return os.str(); +} + +bool length_t::operator== (const length_t& other) const noexcept +{ + return value == other.value && unit == other.unit; +} + +bool length_t::operator!= (const length_t& other) const noexcept +{ + return !operator== (other); +} + +date_time_t::date_time_t() : + year(0), month(0), day(0), hour(0), minute(0), second(0.0) {} + +date_time_t::date_time_t(int _year, int _month, int _day) : + year(_year), month(_month), day(_day), hour(0), minute(0), second(0.0) {} + +date_time_t::date_time_t(int _year, int _month, int _day, int _hour, int _minute, double _second) : + year(_year), month(_month), day(_day), hour(_hour), minute(_minute), second(_second) {} + +date_time_t::date_time_t(const date_time_t& other) = default; +date_time_t::~date_time_t() = default; + +date_time_t& date_time_t::operator= (date_time_t other) +{ + swap(other); + return *this; +} + +void date_time_t::swap(date_time_t& other) +{ + std::swap(year, other.year); + std::swap(month, other.month); + std::swap(day, other.day); + std::swap(hour, other.hour); + std::swap(minute, other.minute); + std::swap(second, other.second); +} + +date_time_t date_time_t::from_chars(std::string_view str) +{ + auto flush_int = [](int& store, const char*& digit, size_t& digit_len) + { + long v; + parse_integer(digit, digit + digit_len, v); + store = v; + + digit = nullptr; + digit_len = 0; + }; + + auto process_char = [](const char* p, const char*& digit, size_t& digit_len) + { + if (!digit) + { + digit = p; + digit_len = 1; + return; + } + + ++digit_len; + }; + + date_time_t ret; + int dash_count = 0, t_count = 0, colon_count = 0; + + const char* p = str.data(); + const char* p_end = p + str.size(); + const char* digit = p; + size_t digit_len = 0; + + bool valid = true; + for (; p != p_end && valid; ++p) + { + switch (*p) + { + case '-': + { + if (t_count || colon_count || !digit) + { + // Invalid date-time value. All dashes must occur before + // any of 'T' and ':' occur. + valid = false; + break; + } + + switch (dash_count) + { + case 0: + // Flush year. + flush_int(ret.year, digit, digit_len); + break; + case 1: + // Flush month. + flush_int(ret.month, digit, digit_len); + break; + default: + valid = false; + } + ++dash_count; + } + break; + case 'T': + { + if (t_count || dash_count != 2 || !digit) + { + // Invalid date-time value. + valid = false; + break; + } + + // Flush day. + flush_int(ret.day, digit, digit_len); + ++t_count; + } + break; + case ':': + { + if (!t_count || !digit) + { + // Invalid date-time value. + valid = false; + break; + } + + switch (colon_count) + { + case 0: + // Flush hour. + flush_int(ret.hour, digit, digit_len); + break; + case 1: + // Flush minute. + flush_int(ret.minute, digit, digit_len); + break; + default: + valid = false; + } + + ++colon_count; + } + break; + default: + { + if (t_count) + { + // Time element. + switch (colon_count) + { + case 0: + // Hour + process_char(p, digit, digit_len); + break; + case 1: + // Minute + process_char(p, digit, digit_len); + break; + case 2: + // Second + process_char(p, digit, digit_len); + break; + default: + valid = false; + } + } + else + { + // Date element. + switch (dash_count) + { + case 0: + // Year + process_char(p, digit, digit_len); + break; + case 1: + // Month + process_char(p, digit, digit_len); + break; + case 2: + // Day + process_char(p, digit, digit_len); + break; + default: + valid = false; + } + } + } + } + + } + + if (!valid || !digit) + return ret; + + if (t_count) + { + // Flush second. + ret.second = strtod(digit, nullptr); + } + else + { + // Flush day. + flush_int(ret.day, digit, digit_len); + } + + return ret; +} + +bool date_time_t::operator== (const date_time_t& other) const +{ + return year == other.year && month == other.month && day == other.day && + hour == other.hour && minute == other.minute && second == other.second; +} + +bool date_time_t::operator!= (const date_time_t& other) const +{ + return !operator== (other); +} + +bool date_time_t::operator< (const date_time_t& other) const +{ + if (year != other.year) + return year < other.year; + + if (month != other.month) + return month < other.month; + + if (day != other.day) + return day < other.day; + + if (hour != other.hour) + return hour < other.hour; + + if (minute != other.minute) + return minute < other.minute; + + return second < other.second; +} + +std::string date_time_t::to_string() const +{ + std::ostringstream os; + + // NB: setfill is sticky for the entire run whereas setw gets reset for each + // value. + os << std::setfill('0'); + + os << std::setw(4) << year + << "-" << std::setw(2) << month + << "-" << std::setw(2) << day + << "T" << std::setw(2) << hour + << ":" << std::setw(2) << minute + << ":" << std::setw(2) << second; + + return os.str(); +} + +namespace { + +namespace dump_format { + +using map_type = mdds::sorted_string_map<dump_format_t, mdds::string_view_map_entry>; + +// Keys must be sorted. +constexpr map_type::entry entries[] = { + { "check", dump_format_t::check }, + { "csv", dump_format_t::csv }, + { "debug-state", dump_format_t::debug_state }, + { "flat", dump_format_t::flat }, + { "html", dump_format_t::html }, + { "json", dump_format_t::json }, + { "none", dump_format_t::none }, + { "xml", dump_format_t::xml }, + { "yaml", dump_format_t::yaml }, +}; + +const map_type& get() +{ + static map_type mt(entries, std::size(entries), dump_format_t::unknown); + return mt; +} + +} // namespace dump_format + +namespace charset { + +using map_type = mdds::sorted_string_map<character_set_t, mdds::string_view_map_entry>; + +// Keys must be sorted. +constexpr map_type::entry entries[] = { + { "437", character_set_t::ibm437 }, + { "850", character_set_t::ibm850 }, + { "851", character_set_t::ibm851 }, + { "852", character_set_t::ibm852 }, + { "855", character_set_t::ibm855 }, + { "857", character_set_t::ibm857 }, + { "860", character_set_t::ibm860 }, + { "861", character_set_t::ibm861 }, + { "862", character_set_t::ibm862 }, + { "863", character_set_t::ibm863 }, + { "865", character_set_t::ibm865 }, + { "866", character_set_t::ibm866 }, + { "869", character_set_t::ibm869 }, + { "904", character_set_t::ibm904 }, + { "adobe-standard-encoding", character_set_t::adobe_standard_encoding }, + { "adobe-symbol-encoding", character_set_t::adobe_symbol_encoding }, + { "ami-1251", character_set_t::amiga_1251 }, + { "ami1251", character_set_t::amiga_1251 }, + { "amiga-1251", character_set_t::amiga_1251 }, + { "amiga1251", character_set_t::amiga_1251 }, + { "ansi_x3.110-1983", character_set_t::ansi_x3_110_1983 }, + { "ansi_x3.4-1968", character_set_t::us_ascii }, + { "ansi_x3.4-1986", character_set_t::us_ascii }, + { "arabic", character_set_t::iso_8859_6 }, + { "arabic7", character_set_t::asmo_449 }, + { "asmo-708", character_set_t::iso_8859_6 }, + { "asmo_449", character_set_t::asmo_449 }, + { "big5", character_set_t::big5 }, + { "big5-hkscs", character_set_t::big5_hkscs }, + { "bocu-1", character_set_t::bocu_1 }, + { "brf", character_set_t::brf }, + { "bs_4730", character_set_t::bs_4730 }, + { "bs_viewdata", character_set_t::bs_viewdata }, + { "ca", character_set_t::csa_z243_4_1985_1 }, + { "ccsid00858", character_set_t::ibm00858 }, + { "ccsid00924", character_set_t::ibm00924 }, + { "ccsid01140", character_set_t::ibm01140 }, + { "ccsid01141", character_set_t::ibm01141 }, + { "ccsid01142", character_set_t::ibm01142 }, + { "ccsid01143", character_set_t::ibm01143 }, + { "ccsid01144", character_set_t::ibm01144 }, + { "ccsid01145", character_set_t::ibm01145 }, + { "ccsid01146", character_set_t::ibm01146 }, + { "ccsid01147", character_set_t::ibm01147 }, + { "ccsid01148", character_set_t::ibm01148 }, + { "ccsid01149", character_set_t::ibm01149 }, + { "cesu-8", character_set_t::cesu_8 }, + { "chinese", character_set_t::gb_2312_80 }, + { "cn", character_set_t::gb_1988_80 }, + { "cp-ar", character_set_t::ibm868 }, + { "cp-gr", character_set_t::ibm869 }, + { "cp-is", character_set_t::ibm861 }, + { "cp00858", character_set_t::ibm00858 }, + { "cp00924", character_set_t::ibm00924 }, + { "cp01140", character_set_t::ibm01140 }, + { "cp01141", character_set_t::ibm01141 }, + { "cp01142", character_set_t::ibm01142 }, + { "cp01143", character_set_t::ibm01143 }, + { "cp01144", character_set_t::ibm01144 }, + { "cp01145", character_set_t::ibm01145 }, + { "cp01146", character_set_t::ibm01146 }, + { "cp01147", character_set_t::ibm01147 }, + { "cp01148", character_set_t::ibm01148 }, + { "cp01149", character_set_t::ibm01149 }, + { "cp037", character_set_t::ibm037 }, + { "cp038", character_set_t::ibm038 }, + { "cp1026", character_set_t::ibm1026 }, + { "cp154", character_set_t::ptcp154 }, + { "cp273", character_set_t::ibm273 }, + { "cp274", character_set_t::ibm274 }, + { "cp275", character_set_t::ibm275 }, + { "cp278", character_set_t::ibm278 }, + { "cp280", character_set_t::ibm280 }, + { "cp281", character_set_t::ibm281 }, + { "cp284", character_set_t::ibm284 }, + { "cp285", character_set_t::ibm285 }, + { "cp290", character_set_t::ibm290 }, + { "cp297", character_set_t::ibm297 }, + { "cp367", character_set_t::us_ascii }, + { "cp420", character_set_t::ibm420 }, + { "cp423", character_set_t::ibm423 }, + { "cp424", character_set_t::ibm424 }, + { "cp437", character_set_t::ibm437 }, + { "cp500", character_set_t::ibm500 }, + { "cp50220", character_set_t::cp50220 }, + { "cp51932", character_set_t::cp51932 }, + { "cp775", character_set_t::ibm775 }, + { "cp819", character_set_t::iso_8859_1 }, + { "cp850", character_set_t::ibm850 }, + { "cp851", character_set_t::ibm851 }, + { "cp852", character_set_t::ibm852 }, + { "cp855", character_set_t::ibm855 }, + { "cp857", character_set_t::ibm857 }, + { "cp860", character_set_t::ibm860 }, + { "cp861", character_set_t::ibm861 }, + { "cp862", character_set_t::ibm862 }, + { "cp863", character_set_t::ibm863 }, + { "cp864", character_set_t::ibm864 }, + { "cp865", character_set_t::ibm865 }, + { "cp866", character_set_t::ibm866 }, + { "cp868", character_set_t::ibm868 }, + { "cp869", character_set_t::ibm869 }, + { "cp870", character_set_t::ibm870 }, + { "cp871", character_set_t::ibm871 }, + { "cp880", character_set_t::ibm880 }, + { "cp891", character_set_t::ibm891 }, + { "cp903", character_set_t::ibm903 }, + { "cp904", character_set_t::ibm904 }, + { "cp905", character_set_t::ibm905 }, + { "cp918", character_set_t::ibm918 }, + { "cp936", character_set_t::gbk }, + { "csa7-1", character_set_t::csa_z243_4_1985_1 }, + { "csa7-2", character_set_t::csa_z243_4_1985_2 }, + { "csa71", character_set_t::csa_z243_4_1985_1 }, + { "csa72", character_set_t::csa_z243_4_1985_2 }, + { "csa_t500-1983", character_set_t::ansi_x3_110_1983 }, + { "csa_z243.4-1985-1", character_set_t::csa_z243_4_1985_1 }, + { "csa_z243.4-1985-2", character_set_t::csa_z243_4_1985_2 }, + { "csa_z243.4-1985-gr", character_set_t::csa_z243_4_1985_gr }, + { "csadobestandardencoding", character_set_t::adobe_standard_encoding }, + { "csascii", character_set_t::us_ascii }, + { "csbig5", character_set_t::big5 }, + { "csbig5hkscs", character_set_t::big5_hkscs }, + { "csbocu-1", character_set_t::bocu_1 }, + { "csbocu1", character_set_t::bocu_1 }, + { "csbrf", character_set_t::brf }, + { "cscesu-8", character_set_t::cesu_8 }, + { "cscesu8", character_set_t::cesu_8 }, + { "cscp50220", character_set_t::cp50220 }, + { "cscp51932", character_set_t::cp51932 }, + { "csdecmcs", character_set_t::dec_mcs }, + { "csdkus", character_set_t::dk_us }, + { "csebcdicatdea", character_set_t::ebcdic_at_de_a }, + { "csebcdiccafr", character_set_t::ebcdic_ca_fr }, + { "csebcdicdkno", character_set_t::ebcdic_dk_no }, + { "csebcdicdknoa", character_set_t::ebcdic_dk_no_a }, + { "csebcdices", character_set_t::ebcdic_es }, + { "csebcdicesa", character_set_t::ebcdic_es_a }, + { "csebcdicess", character_set_t::ebcdic_es_s }, + { "csebcdicfise", character_set_t::ebcdic_fi_se }, + { "csebcdicfisea", character_set_t::ebcdic_fi_se_a }, + { "csebcdicfr", character_set_t::ebcdic_fr }, + { "csebcdicit", character_set_t::ebcdic_it }, + { "csebcdicpt", character_set_t::ebcdic_pt }, + { "csebcdicuk", character_set_t::ebcdic_uk }, + { "csebcdicus", character_set_t::ebcdic_us }, + { "cseucfixwidjapanese", character_set_t::extended_unix_code_fixed_width_for_japanese }, + { "cseuckr", character_set_t::euc_kr }, + { "cseucpkdfmtjapanese", character_set_t::euc_jp }, + { "csgb18030", character_set_t::gb18030 }, + { "csgb2312", character_set_t::gb2312 }, + { "csgbk", character_set_t::gbk }, + { "cshalfwidthkatakana", character_set_t::jis_x0201 }, + { "cshpdesktop", character_set_t::hp_desktop }, + { "cshplegal", character_set_t::hp_legal }, + { "cshpmath8", character_set_t::hp_math8 }, + { "cshppifont", character_set_t::hp_pi_font }, + { "cshppsmath", character_set_t::adobe_symbol_encoding }, + { "cshproman8", character_set_t::hp_roman8 }, + { "csibbm904", character_set_t::ibm904 }, + { "csibm00858", character_set_t::ibm00858 }, + { "csibm00924", character_set_t::ibm00924 }, + { "csibm01140", character_set_t::ibm01140 }, + { "csibm01141", character_set_t::ibm01141 }, + { "csibm01142", character_set_t::ibm01142 }, + { "csibm01143", character_set_t::ibm01143 }, + { "csibm01144", character_set_t::ibm01144 }, + { "csibm01145", character_set_t::ibm01145 }, + { "csibm01146", character_set_t::ibm01146 }, + { "csibm01147", character_set_t::ibm01147 }, + { "csibm01148", character_set_t::ibm01148 }, + { "csibm01149", character_set_t::ibm01149 }, + { "csibm037", character_set_t::ibm037 }, + { "csibm038", character_set_t::ibm038 }, + { "csibm1026", character_set_t::ibm1026 }, + { "csibm1047", character_set_t::ibm1047 }, + { "csibm273", character_set_t::ibm273 }, + { "csibm274", character_set_t::ibm274 }, + { "csibm275", character_set_t::ibm275 }, + { "csibm277", character_set_t::ibm277 }, + { "csibm278", character_set_t::ibm278 }, + { "csibm280", character_set_t::ibm280 }, + { "csibm281", character_set_t::ibm281 }, + { "csibm284", character_set_t::ibm284 }, + { "csibm285", character_set_t::ibm285 }, + { "csibm290", character_set_t::ibm290 }, + { "csibm297", character_set_t::ibm297 }, + { "csibm420", character_set_t::ibm420 }, + { "csibm423", character_set_t::ibm423 }, + { "csibm424", character_set_t::ibm424 }, + { "csibm500", character_set_t::ibm500 }, + { "csibm851", character_set_t::ibm851 }, + { "csibm855", character_set_t::ibm855 }, + { "csibm857", character_set_t::ibm857 }, + { "csibm860", character_set_t::ibm860 }, + { "csibm861", character_set_t::ibm861 }, + { "csibm863", character_set_t::ibm863 }, + { "csibm864", character_set_t::ibm864 }, + { "csibm865", character_set_t::ibm865 }, + { "csibm866", character_set_t::ibm866 }, + { "csibm868", character_set_t::ibm868 }, + { "csibm869", character_set_t::ibm869 }, + { "csibm870", character_set_t::ibm870 }, + { "csibm871", character_set_t::ibm871 }, + { "csibm880", character_set_t::ibm880 }, + { "csibm891", character_set_t::ibm891 }, + { "csibm903", character_set_t::ibm903 }, + { "csibm905", character_set_t::ibm905 }, + { "csibm918", character_set_t::ibm918 }, + { "csibmebcdicatde", character_set_t::ebcdic_at_de }, + { "csibmsymbols", character_set_t::ibm_symbols }, + { "csibmthai", character_set_t::ibm_thai }, + { "csinvariant", character_set_t::invariant }, + { "csiso102t617bit", character_set_t::t_61_7bit }, + { "csiso10367box", character_set_t::iso_10367_box }, + { "csiso103t618bit", character_set_t::t_61_8bit }, + { "csiso10646utf1", character_set_t::iso_10646_utf_1 }, + { "csiso10swedish", character_set_t::sen_850200_b }, + { "csiso111ecmacyrillic", character_set_t::ecma_cyrillic }, + { "csiso115481", character_set_t::iso_11548_1 }, + { "csiso11swedishfornames", character_set_t::sen_850200_c }, + { "csiso121canadian1", character_set_t::csa_z243_4_1985_1 }, + { "csiso122canadian2", character_set_t::csa_z243_4_1985_2 }, + { "csiso123csaz24341985gr", character_set_t::csa_z243_4_1985_gr }, + { "csiso128t101g2", character_set_t::t_101_g2 }, + { "csiso139csn369103", character_set_t::csn_369103 }, + { "csiso13jisc6220jp", character_set_t::jis_c6220_1969_jp }, + { "csiso141jusib1002", character_set_t::jus_i_b1_002 }, + { "csiso143iecp271", character_set_t::iec_p27_1 }, + { "csiso146serbian", character_set_t::jus_i_b1_003_serb }, + { "csiso147macedonian", character_set_t::jus_i_b1_003_mac }, + { "csiso14jisc6220ro", character_set_t::jis_c6220_1969_ro }, + { "csiso150", character_set_t::greek_ccitt }, + { "csiso150greekccitt", character_set_t::greek_ccitt }, + { "csiso151cuba", character_set_t::nc_nc00_10_81 }, + { "csiso153gost1976874", character_set_t::gost_19768_74 }, + { "csiso158lap", character_set_t::latin_lap }, + { "csiso159jisx02121990", character_set_t::jis_x0212_1990 }, + { "csiso15italian", character_set_t::it }, + { "csiso16portuguese", character_set_t::pt }, + { "csiso17spanish", character_set_t::es }, + { "csiso18greek7old", character_set_t::greek7_old }, + { "csiso19latingreek", character_set_t::latin_greek }, + { "csiso2022cn", character_set_t::iso_2022_cn }, + { "csiso2022cnext", character_set_t::iso_2022_cn_ext }, + { "csiso2022jp", character_set_t::iso_2022_jp }, + { "csiso2022jp2", character_set_t::iso_2022_jp_2 }, + { "csiso2022kr", character_set_t::iso_2022_kr }, + { "csiso2033", character_set_t::iso_2033_1983 }, + { "csiso21german", character_set_t::din_66003 }, + { "csiso25french", character_set_t::nf_z_62_010_1973 }, + { "csiso27latingreek1", character_set_t::latin_greek_1 }, + { "csiso2intlrefversion", character_set_t::iso_646_irv_1983 }, + { "csiso42jisc62261978", character_set_t::jis_c6226_1978 }, + { "csiso47bsviewdata", character_set_t::bs_viewdata }, + { "csiso49inis", character_set_t::inis }, + { "csiso4unitedkingdom", character_set_t::bs_4730 }, + { "csiso50inis8", character_set_t::inis_8 }, + { "csiso51iniscyrillic", character_set_t::inis_cyrillic }, + { "csiso54271981", character_set_t::iso_5427_1981 }, + { "csiso5427cyrillic", character_set_t::iso_5427 }, + { "csiso5428greek", character_set_t::iso_5428_1980 }, + { "csiso57gb1988", character_set_t::gb_1988_80 }, + { "csiso58gb231280", character_set_t::gb_2312_80 }, + { "csiso60danishnorwegian", character_set_t::ns_4551_1 }, + { "csiso60norwegian1", character_set_t::ns_4551_1 }, + { "csiso61norwegian2", character_set_t::ns_4551_2 }, + { "csiso646basic1983", character_set_t::iso_646_basic_1983 }, + { "csiso646danish", character_set_t::ds_2089 }, + { "csiso6937add", character_set_t::iso_6937_2_25 }, + { "csiso69french", character_set_t::nf_z_62_010 }, + { "csiso70videotexsupp1", character_set_t::videotex_suppl }, + { "csiso84portuguese2", character_set_t::pt2 }, + { "csiso85spanish2", character_set_t::es2 }, + { "csiso86hungarian", character_set_t::msz_7795_3 }, + { "csiso87jisx0208", character_set_t::jis_c6226_1983 }, + { "csiso885913", character_set_t::iso_8859_13 }, + { "csiso885914", character_set_t::iso_8859_14 }, + { "csiso885915", character_set_t::iso_8859_15 }, + { "csiso885916", character_set_t::iso_8859_16 }, + { "csiso88596e", character_set_t::iso_8859_6_e }, + { "csiso88596i", character_set_t::iso_8859_6_i }, + { "csiso88598e", character_set_t::iso_8859_8_e }, + { "csiso88598i", character_set_t::iso_8859_8_i }, + { "csiso8859supp", character_set_t::iso_8859_supp }, + { "csiso88greek7", character_set_t::greek7 }, + { "csiso89asmo449", character_set_t::asmo_449 }, + { "csiso90", character_set_t::iso_ir_90 }, + { "csiso91jisc62291984a", character_set_t::jis_c6229_1984_a }, + { "csiso92jisc62991984b", character_set_t::jis_c6229_1984_b }, + { "csiso93jis62291984badd", character_set_t::jis_c6229_1984_b_add }, + { "csiso94jis62291984hand", character_set_t::jis_c6229_1984_hand }, + { "csiso95jis62291984handadd", character_set_t::jis_c6229_1984_hand_add }, + { "csiso96jisc62291984kana", character_set_t::jis_c6229_1984_kana }, + { "csiso99naplps", character_set_t::ansi_x3_110_1983 }, + { "csisolatin1", character_set_t::iso_8859_1 }, + { "csisolatin2", character_set_t::iso_8859_2 }, + { "csisolatin3", character_set_t::iso_8859_3 }, + { "csisolatin4", character_set_t::iso_8859_4 }, + { "csisolatin5", character_set_t::iso_8859_9 }, + { "csisolatin6", character_set_t::iso_8859_10 }, + { "csisolatinarabic", character_set_t::iso_8859_6 }, + { "csisolatincyrillic", character_set_t::iso_8859_5 }, + { "csisolatingreek", character_set_t::iso_8859_7 }, + { "csisolatinhebrew", character_set_t::iso_8859_8 }, + { "csisotextcomm", character_set_t::iso_6937_2_add }, + { "csjisencoding", character_set_t::jis_encoding }, + { "cskoi7switched", character_set_t::koi7_switched }, + { "cskoi8r", character_set_t::koi8_r }, + { "cskoi8u", character_set_t::koi8_u }, + { "csksc56011987", character_set_t::ks_c_5601_1987 }, + { "csksc5636", character_set_t::ksc5636 }, + { "cskz1048", character_set_t::kz_1048 }, + { "csmacintosh", character_set_t::macintosh }, + { "csmicrosoftpublishing", character_set_t::microsoft_publishing }, + { "csmnem", character_set_t::mnem }, + { "csmnemonic", character_set_t::mnemonic }, + { "csn_369103", character_set_t::csn_369103 }, + { "csnatsdano", character_set_t::nats_dano }, + { "csnatsdanoadd", character_set_t::nats_dano_add }, + { "csnatssefi", character_set_t::nats_sefi }, + { "csnatssefiadd", character_set_t::nats_sefi_add }, + { "csosdebcdicdf03irv", character_set_t::osd_ebcdic_df03_irv }, + { "csosdebcdicdf041", character_set_t::osd_ebcdic_df04_1 }, + { "csosdebcdicdf0415", character_set_t::osd_ebcdic_df04_15 }, + { "cspc775baltic", character_set_t::ibm775 }, + { "cspc850multilingual", character_set_t::ibm850 }, + { "cspc862latinhebrew", character_set_t::ibm862 }, + { "cspc8codepage437", character_set_t::ibm437 }, + { "cspc8danishnorwegian", character_set_t::pc8_danish_norwegian }, + { "cspc8turkish", character_set_t::pc8_turkish }, + { "cspcp852", character_set_t::ibm852 }, + { "csptcp154", character_set_t::ptcp154 }, + { "csscsu", character_set_t::scsu }, + { "csshiftjis", character_set_t::shift_jis }, + { "cstis620", character_set_t::tis_620 }, + { "cstscii", character_set_t::tscii }, + { "csucs4", character_set_t::iso_10646_ucs_4 }, + { "csunicode", character_set_t::iso_10646_ucs_2 }, + { "csunicode11", character_set_t::unicode_1_1 }, + { "csunicode11utf7", character_set_t::unicode_1_1_utf_7 }, + { "csunicodeascii", character_set_t::iso_10646_ucs_basic }, + { "csunicodeibm1261", character_set_t::iso_unicode_ibm_1261 }, + { "csunicodeibm1264", character_set_t::iso_unicode_ibm_1264 }, + { "csunicodeibm1265", character_set_t::iso_unicode_ibm_1265 }, + { "csunicodeibm1268", character_set_t::iso_unicode_ibm_1268 }, + { "csunicodeibm1276", character_set_t::iso_unicode_ibm_1276 }, + { "csunicodejapanese", character_set_t::iso_10646_j_1 }, + { "csunicodelatin1", character_set_t::iso_10646_unicode_latin1 }, + { "csunknown8bit", character_set_t::unknown_8bit }, + { "csusdk", character_set_t::us_dk }, + { "csutf16", character_set_t::utf_16 }, + { "csutf16be", character_set_t::utf_16be }, + { "csutf16le", character_set_t::utf_16le }, + { "csutf32", character_set_t::utf_32 }, + { "csutf32be", character_set_t::utf_32be }, + { "csutf32le", character_set_t::utf_32le }, + { "csutf7", character_set_t::utf_7 }, + { "csutf7imap", character_set_t::utf_7_imap }, + { "csutf8", character_set_t::utf_8 }, + { "csventurainternational", character_set_t::ventura_international }, + { "csventuramath", character_set_t::ventura_math }, + { "csventuraus", character_set_t::ventura_us }, + { "csviqr", character_set_t::viqr }, + { "csviscii", character_set_t::viscii }, + { "cswindows1250", character_set_t::windows_1250 }, + { "cswindows1251", character_set_t::windows_1251 }, + { "cswindows1252", character_set_t::windows_1252 }, + { "cswindows1253", character_set_t::windows_1253 }, + { "cswindows1254", character_set_t::windows_1254 }, + { "cswindows1255", character_set_t::windows_1255 }, + { "cswindows1256", character_set_t::windows_1256 }, + { "cswindows1257", character_set_t::windows_1257 }, + { "cswindows1258", character_set_t::windows_1258 }, + { "cswindows30latin1", character_set_t::iso_8859_1_windows_3_0_latin_1 }, + { "cswindows31j", character_set_t::windows_31j }, + { "cswindows31latin1", character_set_t::iso_8859_1_windows_3_1_latin_1 }, + { "cswindows31latin2", character_set_t::iso_8859_2_windows_latin_2 }, + { "cswindows31latin5", character_set_t::iso_8859_9_windows_latin_5 }, + { "cswindows874", character_set_t::windows_874 }, + { "cuba", character_set_t::nc_nc00_10_81 }, + { "cyrillic", character_set_t::iso_8859_5 }, + { "cyrillic-asian", character_set_t::ptcp154 }, + { "de", character_set_t::din_66003 }, + { "dec", character_set_t::dec_mcs }, + { "dec-mcs", character_set_t::dec_mcs }, + { "din_66003", character_set_t::din_66003 }, + { "dk", character_set_t::ds_2089 }, + { "dk-us", character_set_t::dk_us }, + { "ds2089", character_set_t::ds_2089 }, + { "ds_2089", character_set_t::ds_2089 }, + { "e13b", character_set_t::iso_2033_1983 }, + { "ebcdic-at-de", character_set_t::ebcdic_at_de }, + { "ebcdic-at-de-a", character_set_t::ebcdic_at_de_a }, + { "ebcdic-be", character_set_t::ibm274 }, + { "ebcdic-br", character_set_t::ibm275 }, + { "ebcdic-ca-fr", character_set_t::ebcdic_ca_fr }, + { "ebcdic-cp-ar1", character_set_t::ibm420 }, + { "ebcdic-cp-ar2", character_set_t::ibm918 }, + { "ebcdic-cp-be", character_set_t::ibm500 }, + { "ebcdic-cp-ca", character_set_t::ibm037 }, + { "ebcdic-cp-ch", character_set_t::ibm500 }, + { "ebcdic-cp-dk", character_set_t::ibm277 }, + { "ebcdic-cp-es", character_set_t::ibm284 }, + { "ebcdic-cp-fi", character_set_t::ibm278 }, + { "ebcdic-cp-fr", character_set_t::ibm297 }, + { "ebcdic-cp-gb", character_set_t::ibm285 }, + { "ebcdic-cp-gr", character_set_t::ibm423 }, + { "ebcdic-cp-he", character_set_t::ibm424 }, + { "ebcdic-cp-is", character_set_t::ibm871 }, + { "ebcdic-cp-it", character_set_t::ibm280 }, + { "ebcdic-cp-nl", character_set_t::ibm037 }, + { "ebcdic-cp-no", character_set_t::ibm277 }, + { "ebcdic-cp-roece", character_set_t::ibm870 }, + { "ebcdic-cp-se", character_set_t::ibm278 }, + { "ebcdic-cp-tr", character_set_t::ibm905 }, + { "ebcdic-cp-us", character_set_t::ibm037 }, + { "ebcdic-cp-wt", character_set_t::ibm037 }, + { "ebcdic-cp-yu", character_set_t::ibm870 }, + { "ebcdic-cyrillic", character_set_t::ibm880 }, + { "ebcdic-de-273+euro", character_set_t::ibm01141 }, + { "ebcdic-dk-277+euro", character_set_t::ibm01142 }, + { "ebcdic-dk-no", character_set_t::ebcdic_dk_no }, + { "ebcdic-dk-no-a", character_set_t::ebcdic_dk_no_a }, + { "ebcdic-es", character_set_t::ebcdic_es }, + { "ebcdic-es-284+euro", character_set_t::ibm01145 }, + { "ebcdic-es-a", character_set_t::ebcdic_es_a }, + { "ebcdic-es-s", character_set_t::ebcdic_es_s }, + { "ebcdic-fi-278+euro", character_set_t::ibm01143 }, + { "ebcdic-fi-se", character_set_t::ebcdic_fi_se }, + { "ebcdic-fi-se-a", character_set_t::ebcdic_fi_se_a }, + { "ebcdic-fr", character_set_t::ebcdic_fr }, + { "ebcdic-fr-297+euro", character_set_t::ibm01147 }, + { "ebcdic-gb-285+euro", character_set_t::ibm01146 }, + { "ebcdic-int", character_set_t::ibm038 }, + { "ebcdic-international-500+euro", character_set_t::ibm01148 }, + { "ebcdic-is-871+euro", character_set_t::ibm01149 }, + { "ebcdic-it", character_set_t::ebcdic_it }, + { "ebcdic-it-280+euro", character_set_t::ibm01144 }, + { "ebcdic-jp-e", character_set_t::ibm281 }, + { "ebcdic-jp-kana", character_set_t::ibm290 }, + { "ebcdic-latin9--euro", character_set_t::ibm00924 }, + { "ebcdic-no-277+euro", character_set_t::ibm01142 }, + { "ebcdic-pt", character_set_t::ebcdic_pt }, + { "ebcdic-se-278+euro", character_set_t::ibm01143 }, + { "ebcdic-uk", character_set_t::ebcdic_uk }, + { "ebcdic-us", character_set_t::ebcdic_us }, + { "ebcdic-us-37+euro", character_set_t::ibm01140 }, + { "ecma-114", character_set_t::iso_8859_6 }, + { "ecma-118", character_set_t::iso_8859_7 }, + { "ecma-cyrillic", character_set_t::ecma_cyrillic }, + { "elot_928", character_set_t::iso_8859_7 }, + { "es", character_set_t::es }, + { "es2", character_set_t::es2 }, + { "euc-jp", character_set_t::euc_jp }, + { "euc-kr", character_set_t::euc_kr }, + { "extended_unix_code_fixed_width_for_japanese", character_set_t::extended_unix_code_fixed_width_for_japanese }, + { "extended_unix_code_packed_format_for_japanese", character_set_t::euc_jp }, + { "fi", character_set_t::sen_850200_b }, + { "fr", character_set_t::nf_z_62_010 }, + { "gb", character_set_t::bs_4730 }, + { "gb18030", character_set_t::gb18030 }, + { "gb2312", character_set_t::gb2312 }, + { "gb_1988-80", character_set_t::gb_1988_80 }, + { "gb_2312-80", character_set_t::gb_2312_80 }, + { "gbk", character_set_t::gbk }, + { "gost_19768-74", character_set_t::gost_19768_74 }, + { "greek", character_set_t::iso_8859_7 }, + { "greek-ccitt", character_set_t::greek_ccitt }, + { "greek7", character_set_t::greek7 }, + { "greek7-old", character_set_t::greek7_old }, + { "greek8", character_set_t::iso_8859_7 }, + { "hebrew", character_set_t::iso_8859_8 }, + { "hp-desktop", character_set_t::hp_desktop }, + { "hp-legal", character_set_t::hp_legal }, + { "hp-math8", character_set_t::hp_math8 }, + { "hp-pi-font", character_set_t::hp_pi_font }, + { "hp-roman8", character_set_t::hp_roman8 }, + { "hu", character_set_t::msz_7795_3 }, + { "hz-gb-2312", character_set_t::hz_gb_2312 }, + { "ibm-1047", character_set_t::ibm1047 }, + { "ibm-symbols", character_set_t::ibm_symbols }, + { "ibm-thai", character_set_t::ibm_thai }, + { "ibm00858", character_set_t::ibm00858 }, + { "ibm00924", character_set_t::ibm00924 }, + { "ibm01140", character_set_t::ibm01140 }, + { "ibm01141", character_set_t::ibm01141 }, + { "ibm01142", character_set_t::ibm01142 }, + { "ibm01143", character_set_t::ibm01143 }, + { "ibm01144", character_set_t::ibm01144 }, + { "ibm01145", character_set_t::ibm01145 }, + { "ibm01146", character_set_t::ibm01146 }, + { "ibm01147", character_set_t::ibm01147 }, + { "ibm01148", character_set_t::ibm01148 }, + { "ibm01149", character_set_t::ibm01149 }, + { "ibm037", character_set_t::ibm037 }, + { "ibm038", character_set_t::ibm038 }, + { "ibm1026", character_set_t::ibm1026 }, + { "ibm1047", character_set_t::ibm1047 }, + { "ibm273", character_set_t::ibm273 }, + { "ibm274", character_set_t::ibm274 }, + { "ibm275", character_set_t::ibm275 }, + { "ibm277", character_set_t::ibm277 }, + { "ibm278", character_set_t::ibm278 }, + { "ibm280", character_set_t::ibm280 }, + { "ibm281", character_set_t::ibm281 }, + { "ibm284", character_set_t::ibm284 }, + { "ibm285", character_set_t::ibm285 }, + { "ibm290", character_set_t::ibm290 }, + { "ibm297", character_set_t::ibm297 }, + { "ibm367", character_set_t::us_ascii }, + { "ibm420", character_set_t::ibm420 }, + { "ibm423", character_set_t::ibm423 }, + { "ibm424", character_set_t::ibm424 }, + { "ibm437", character_set_t::ibm437 }, + { "ibm500", character_set_t::ibm500 }, + { "ibm775", character_set_t::ibm775 }, + { "ibm819", character_set_t::iso_8859_1 }, + { "ibm850", character_set_t::ibm850 }, + { "ibm851", character_set_t::ibm851 }, + { "ibm852", character_set_t::ibm852 }, + { "ibm855", character_set_t::ibm855 }, + { "ibm857", character_set_t::ibm857 }, + { "ibm860", character_set_t::ibm860 }, + { "ibm861", character_set_t::ibm861 }, + { "ibm862", character_set_t::ibm862 }, + { "ibm863", character_set_t::ibm863 }, + { "ibm864", character_set_t::ibm864 }, + { "ibm865", character_set_t::ibm865 }, + { "ibm866", character_set_t::ibm866 }, + { "ibm868", character_set_t::ibm868 }, + { "ibm869", character_set_t::ibm869 }, + { "ibm870", character_set_t::ibm870 }, + { "ibm871", character_set_t::ibm871 }, + { "ibm880", character_set_t::ibm880 }, + { "ibm891", character_set_t::ibm891 }, + { "ibm903", character_set_t::ibm903 }, + { "ibm904", character_set_t::ibm904 }, + { "ibm905", character_set_t::ibm905 }, + { "ibm918", character_set_t::ibm918 }, + { "iec_p27-1", character_set_t::iec_p27_1 }, + { "inis", character_set_t::inis }, + { "inis-8", character_set_t::inis_8 }, + { "inis-cyrillic", character_set_t::inis_cyrillic }, + { "invariant", character_set_t::invariant }, + { "irv", character_set_t::iso_646_irv_1983 }, + { "iso-10646", character_set_t::iso_10646_unicode_latin1 }, + { "iso-10646-j-1", character_set_t::iso_10646_j_1 }, + { "iso-10646-ucs-2", character_set_t::iso_10646_ucs_2 }, + { "iso-10646-ucs-4", character_set_t::iso_10646_ucs_4 }, + { "iso-10646-ucs-basic", character_set_t::iso_10646_ucs_basic }, + { "iso-10646-unicode-latin1", character_set_t::iso_10646_unicode_latin1 }, + { "iso-10646-utf-1", character_set_t::iso_10646_utf_1 }, + { "iso-11548-1", character_set_t::iso_11548_1 }, + { "iso-2022-cn", character_set_t::iso_2022_cn }, + { "iso-2022-cn-ext", character_set_t::iso_2022_cn_ext }, + { "iso-2022-jp", character_set_t::iso_2022_jp }, + { "iso-2022-jp-2", character_set_t::iso_2022_jp_2 }, + { "iso-2022-kr", character_set_t::iso_2022_kr }, + { "iso-8859-1", character_set_t::iso_8859_1 }, + { "iso-8859-1-windows-3.0-latin-1", character_set_t::iso_8859_1_windows_3_0_latin_1 }, + { "iso-8859-1-windows-3.1-latin-1", character_set_t::iso_8859_1_windows_3_1_latin_1 }, + { "iso-8859-10", character_set_t::iso_8859_10 }, + { "iso-8859-11", character_set_t::tis_620 }, + { "iso-8859-13", character_set_t::iso_8859_13 }, + { "iso-8859-14", character_set_t::iso_8859_14 }, + { "iso-8859-15", character_set_t::iso_8859_15 }, + { "iso-8859-16", character_set_t::iso_8859_16 }, + { "iso-8859-2", character_set_t::iso_8859_2 }, + { "iso-8859-2-windows-latin-2", character_set_t::iso_8859_2_windows_latin_2 }, + { "iso-8859-3", character_set_t::iso_8859_3 }, + { "iso-8859-4", character_set_t::iso_8859_4 }, + { "iso-8859-5", character_set_t::iso_8859_5 }, + { "iso-8859-6", character_set_t::iso_8859_6 }, + { "iso-8859-6-e", character_set_t::iso_8859_6_e }, + { "iso-8859-6-i", character_set_t::iso_8859_6_i }, + { "iso-8859-7", character_set_t::iso_8859_7 }, + { "iso-8859-8", character_set_t::iso_8859_8 }, + { "iso-8859-8-e", character_set_t::iso_8859_8_e }, + { "iso-8859-8-i", character_set_t::iso_8859_8_i }, + { "iso-8859-9", character_set_t::iso_8859_9 }, + { "iso-8859-9-windows-latin-5", character_set_t::iso_8859_9_windows_latin_5 }, + { "iso-celtic", character_set_t::iso_8859_14 }, + { "iso-ir-10", character_set_t::sen_850200_b }, + { "iso-ir-100", character_set_t::iso_8859_1 }, + { "iso-ir-101", character_set_t::iso_8859_2 }, + { "iso-ir-102", character_set_t::t_61_7bit }, + { "iso-ir-103", character_set_t::t_61_8bit }, + { "iso-ir-109", character_set_t::iso_8859_3 }, + { "iso-ir-11", character_set_t::sen_850200_c }, + { "iso-ir-110", character_set_t::iso_8859_4 }, + { "iso-ir-111", character_set_t::ecma_cyrillic }, + { "iso-ir-121", character_set_t::csa_z243_4_1985_1 }, + { "iso-ir-122", character_set_t::csa_z243_4_1985_2 }, + { "iso-ir-123", character_set_t::csa_z243_4_1985_gr }, + { "iso-ir-126", character_set_t::iso_8859_7 }, + { "iso-ir-127", character_set_t::iso_8859_6 }, + { "iso-ir-128", character_set_t::t_101_g2 }, + { "iso-ir-13", character_set_t::jis_c6220_1969_jp }, + { "iso-ir-138", character_set_t::iso_8859_8 }, + { "iso-ir-139", character_set_t::csn_369103 }, + { "iso-ir-14", character_set_t::jis_c6220_1969_ro }, + { "iso-ir-141", character_set_t::jus_i_b1_002 }, + { "iso-ir-142", character_set_t::iso_6937_2_add }, + { "iso-ir-143", character_set_t::iec_p27_1 }, + { "iso-ir-144", character_set_t::iso_8859_5 }, + { "iso-ir-146", character_set_t::jus_i_b1_003_serb }, + { "iso-ir-147", character_set_t::jus_i_b1_003_mac }, + { "iso-ir-148", character_set_t::iso_8859_9 }, + { "iso-ir-149", character_set_t::ks_c_5601_1987 }, + { "iso-ir-15", character_set_t::it }, + { "iso-ir-150", character_set_t::greek_ccitt }, + { "iso-ir-151", character_set_t::nc_nc00_10_81 }, + { "iso-ir-152", character_set_t::iso_6937_2_25 }, + { "iso-ir-153", character_set_t::gost_19768_74 }, + { "iso-ir-154", character_set_t::iso_8859_supp }, + { "iso-ir-155", character_set_t::iso_10367_box }, + { "iso-ir-157", character_set_t::iso_8859_10 }, + { "iso-ir-158", character_set_t::latin_lap }, + { "iso-ir-159", character_set_t::jis_x0212_1990 }, + { "iso-ir-16", character_set_t::pt }, + { "iso-ir-17", character_set_t::es }, + { "iso-ir-18", character_set_t::greek7_old }, + { "iso-ir-19", character_set_t::latin_greek }, + { "iso-ir-199", character_set_t::iso_8859_14 }, + { "iso-ir-2", character_set_t::iso_646_irv_1983 }, + { "iso-ir-21", character_set_t::din_66003 }, + { "iso-ir-226", character_set_t::iso_8859_16 }, + { "iso-ir-25", character_set_t::nf_z_62_010_1973 }, + { "iso-ir-27", character_set_t::latin_greek_1 }, + { "iso-ir-37", character_set_t::iso_5427 }, + { "iso-ir-4", character_set_t::bs_4730 }, + { "iso-ir-42", character_set_t::jis_c6226_1978 }, + { "iso-ir-47", character_set_t::bs_viewdata }, + { "iso-ir-49", character_set_t::inis }, + { "iso-ir-50", character_set_t::inis_8 }, + { "iso-ir-51", character_set_t::inis_cyrillic }, + { "iso-ir-54", character_set_t::iso_5427_1981 }, + { "iso-ir-55", character_set_t::iso_5428_1980 }, + { "iso-ir-57", character_set_t::gb_1988_80 }, + { "iso-ir-58", character_set_t::gb_2312_80 }, + { "iso-ir-6", character_set_t::us_ascii }, + { "iso-ir-60", character_set_t::ns_4551_1 }, + { "iso-ir-61", character_set_t::ns_4551_2 }, + { "iso-ir-69", character_set_t::nf_z_62_010 }, + { "iso-ir-70", character_set_t::videotex_suppl }, + { "iso-ir-8-1", character_set_t::nats_sefi }, + { "iso-ir-8-2", character_set_t::nats_sefi_add }, + { "iso-ir-84", character_set_t::pt2 }, + { "iso-ir-85", character_set_t::es2 }, + { "iso-ir-86", character_set_t::msz_7795_3 }, + { "iso-ir-87", character_set_t::jis_c6226_1983 }, + { "iso-ir-88", character_set_t::greek7 }, + { "iso-ir-89", character_set_t::asmo_449 }, + { "iso-ir-9-1", character_set_t::nats_dano }, + { "iso-ir-9-2", character_set_t::nats_dano_add }, + { "iso-ir-90", character_set_t::iso_ir_90 }, + { "iso-ir-91", character_set_t::jis_c6229_1984_a }, + { "iso-ir-92", character_set_t::jis_c6229_1984_b }, + { "iso-ir-93", character_set_t::jis_c6229_1984_b_add }, + { "iso-ir-94", character_set_t::jis_c6229_1984_hand }, + { "iso-ir-95", character_set_t::jis_c6229_1984_hand_add }, + { "iso-ir-96", character_set_t::jis_c6229_1984_kana }, + { "iso-ir-98", character_set_t::iso_2033_1983 }, + { "iso-ir-99", character_set_t::ansi_x3_110_1983 }, + { "iso-unicode-ibm-1261", character_set_t::iso_unicode_ibm_1261 }, + { "iso-unicode-ibm-1264", character_set_t::iso_unicode_ibm_1264 }, + { "iso-unicode-ibm-1265", character_set_t::iso_unicode_ibm_1265 }, + { "iso-unicode-ibm-1268", character_set_t::iso_unicode_ibm_1268 }, + { "iso-unicode-ibm-1276", character_set_t::iso_unicode_ibm_1276 }, + { "iso5427cyrillic1981", character_set_t::iso_5427_1981 }, + { "iso646-ca", character_set_t::csa_z243_4_1985_1 }, + { "iso646-ca2", character_set_t::csa_z243_4_1985_2 }, + { "iso646-cn", character_set_t::gb_1988_80 }, + { "iso646-cu", character_set_t::nc_nc00_10_81 }, + { "iso646-de", character_set_t::din_66003 }, + { "iso646-dk", character_set_t::ds_2089 }, + { "iso646-es", character_set_t::es }, + { "iso646-es2", character_set_t::es2 }, + { "iso646-fi", character_set_t::sen_850200_b }, + { "iso646-fr", character_set_t::nf_z_62_010 }, + { "iso646-fr1", character_set_t::nf_z_62_010_1973 }, + { "iso646-gb", character_set_t::bs_4730 }, + { "iso646-hu", character_set_t::msz_7795_3 }, + { "iso646-it", character_set_t::it }, + { "iso646-jp", character_set_t::jis_c6220_1969_ro }, + { "iso646-jp-ocr-b", character_set_t::jis_c6229_1984_b }, + { "iso646-kr", character_set_t::ksc5636 }, + { "iso646-no", character_set_t::ns_4551_1 }, + { "iso646-no2", character_set_t::ns_4551_2 }, + { "iso646-pt", character_set_t::pt }, + { "iso646-pt2", character_set_t::pt2 }, + { "iso646-se", character_set_t::sen_850200_b }, + { "iso646-se2", character_set_t::sen_850200_c }, + { "iso646-us", character_set_t::us_ascii }, + { "iso646-yu", character_set_t::jus_i_b1_002 }, + { "iso_10367-box", character_set_t::iso_10367_box }, + { "iso_11548-1", character_set_t::iso_11548_1 }, + { "iso_2033-1983", character_set_t::iso_2033_1983 }, + { "iso_5427", character_set_t::iso_5427 }, + { "iso_5427:1981", character_set_t::iso_5427_1981 }, + { "iso_5428:1980", character_set_t::iso_5428_1980 }, + { "iso_646.basic:1983", character_set_t::iso_646_basic_1983 }, + { "iso_646.irv:1983", character_set_t::iso_646_irv_1983 }, + { "iso_646.irv:1991", character_set_t::us_ascii }, + { "iso_6937-2-25", character_set_t::iso_6937_2_25 }, + { "iso_6937-2-add", character_set_t::iso_6937_2_add }, + { "iso_8859-1", character_set_t::iso_8859_1 }, + { "iso_8859-10:1992", character_set_t::iso_8859_10 }, + { "iso_8859-14", character_set_t::iso_8859_14 }, + { "iso_8859-14:1998", character_set_t::iso_8859_14 }, + { "iso_8859-15", character_set_t::iso_8859_15 }, + { "iso_8859-16", character_set_t::iso_8859_16 }, + { "iso_8859-16:2001", character_set_t::iso_8859_16 }, + { "iso_8859-1:1987", character_set_t::iso_8859_1 }, + { "iso_8859-2", character_set_t::iso_8859_2 }, + { "iso_8859-2:1987", character_set_t::iso_8859_2 }, + { "iso_8859-3", character_set_t::iso_8859_3 }, + { "iso_8859-3:1988", character_set_t::iso_8859_3 }, + { "iso_8859-4", character_set_t::iso_8859_4 }, + { "iso_8859-4:1988", character_set_t::iso_8859_4 }, + { "iso_8859-5", character_set_t::iso_8859_5 }, + { "iso_8859-5:1988", character_set_t::iso_8859_5 }, + { "iso_8859-6", character_set_t::iso_8859_6 }, + { "iso_8859-6-e", character_set_t::iso_8859_6_e }, + { "iso_8859-6-i", character_set_t::iso_8859_6_i }, + { "iso_8859-6:1987", character_set_t::iso_8859_6 }, + { "iso_8859-7", character_set_t::iso_8859_7 }, + { "iso_8859-7:1987", character_set_t::iso_8859_7 }, + { "iso_8859-8", character_set_t::iso_8859_8 }, + { "iso_8859-8-e", character_set_t::iso_8859_8_e }, + { "iso_8859-8-i", character_set_t::iso_8859_8_i }, + { "iso_8859-8:1988", character_set_t::iso_8859_8 }, + { "iso_8859-9", character_set_t::iso_8859_9 }, + { "iso_8859-9:1989", character_set_t::iso_8859_9 }, + { "iso_8859-supp", character_set_t::iso_8859_supp }, + { "iso_9036", character_set_t::asmo_449 }, + { "iso_tr_11548-1", character_set_t::iso_11548_1 }, + { "it", character_set_t::it }, + { "jis_c6220-1969", character_set_t::jis_c6220_1969_jp }, + { "jis_c6220-1969-jp", character_set_t::jis_c6220_1969_jp }, + { "jis_c6220-1969-ro", character_set_t::jis_c6220_1969_ro }, + { "jis_c6226-1978", character_set_t::jis_c6226_1978 }, + { "jis_c6226-1983", character_set_t::jis_c6226_1983 }, + { "jis_c6229-1984-a", character_set_t::jis_c6229_1984_a }, + { "jis_c6229-1984-b", character_set_t::jis_c6229_1984_b }, + { "jis_c6229-1984-b-add", character_set_t::jis_c6229_1984_b_add }, + { "jis_c6229-1984-hand", character_set_t::jis_c6229_1984_hand }, + { "jis_c6229-1984-hand-add", character_set_t::jis_c6229_1984_hand_add }, + { "jis_c6229-1984-kana", character_set_t::jis_c6229_1984_kana }, + { "jis_encoding", character_set_t::jis_encoding }, + { "jis_x0201", character_set_t::jis_x0201 }, + { "jis_x0208-1983", character_set_t::jis_c6226_1983 }, + { "jis_x0212-1990", character_set_t::jis_x0212_1990 }, + { "jp", character_set_t::jis_c6220_1969_ro }, + { "jp-ocr-a", character_set_t::jis_c6229_1984_a }, + { "jp-ocr-b", character_set_t::jis_c6229_1984_b }, + { "jp-ocr-b-add", character_set_t::jis_c6229_1984_b_add }, + { "jp-ocr-hand", character_set_t::jis_c6229_1984_hand }, + { "jp-ocr-hand-add", character_set_t::jis_c6229_1984_hand_add }, + { "js", character_set_t::jus_i_b1_002 }, + { "jus_i.b1.002", character_set_t::jus_i_b1_002 }, + { "jus_i.b1.003-mac", character_set_t::jus_i_b1_003_mac }, + { "jus_i.b1.003-serb", character_set_t::jus_i_b1_003_serb }, + { "katakana", character_set_t::jis_c6220_1969_jp }, + { "koi7-switched", character_set_t::koi7_switched }, + { "koi8-e", character_set_t::ecma_cyrillic }, + { "koi8-r", character_set_t::koi8_r }, + { "koi8-u", character_set_t::koi8_u }, + { "korean", character_set_t::ks_c_5601_1987 }, + { "ks_c_5601-1987", character_set_t::ks_c_5601_1987 }, + { "ks_c_5601-1989", character_set_t::ks_c_5601_1987 }, + { "ksc5636", character_set_t::ksc5636 }, + { "ksc_5601", character_set_t::ks_c_5601_1987 }, + { "kz-1048", character_set_t::kz_1048 }, + { "l1", character_set_t::iso_8859_1 }, + { "l10", character_set_t::iso_8859_16 }, + { "l2", character_set_t::iso_8859_2 }, + { "l3", character_set_t::iso_8859_3 }, + { "l4", character_set_t::iso_8859_4 }, + { "l5", character_set_t::iso_8859_9 }, + { "l6", character_set_t::iso_8859_10 }, + { "l8", character_set_t::iso_8859_14 }, + { "lap", character_set_t::latin_lap }, + { "latin-9", character_set_t::iso_8859_15 }, + { "latin-greek", character_set_t::latin_greek }, + { "latin-greek-1", character_set_t::latin_greek_1 }, + { "latin-lap", character_set_t::latin_lap }, + { "latin1", character_set_t::iso_8859_1 }, + { "latin1-2-5", character_set_t::iso_8859_supp }, + { "latin10", character_set_t::iso_8859_16 }, + { "latin2", character_set_t::iso_8859_2 }, + { "latin3", character_set_t::iso_8859_3 }, + { "latin4", character_set_t::iso_8859_4 }, + { "latin5", character_set_t::iso_8859_9 }, + { "latin6", character_set_t::iso_8859_10 }, + { "latin8", character_set_t::iso_8859_14 }, + { "mac", character_set_t::macintosh }, + { "macedonian", character_set_t::jus_i_b1_003_mac }, + { "macintosh", character_set_t::macintosh }, + { "microsoft-publishing", character_set_t::microsoft_publishing }, + { "mnem", character_set_t::mnem }, + { "mnemonic", character_set_t::mnemonic }, + { "ms936", character_set_t::gbk }, + { "ms_kanji", character_set_t::shift_jis }, + { "msz_7795.3", character_set_t::msz_7795_3 }, + { "naplps", character_set_t::ansi_x3_110_1983 }, + { "nats-dano", character_set_t::nats_dano }, + { "nats-dano-add", character_set_t::nats_dano_add }, + { "nats-sefi", character_set_t::nats_sefi }, + { "nats-sefi-add", character_set_t::nats_sefi_add }, + { "nc_nc00-10:81", character_set_t::nc_nc00_10_81 }, + { "nf_z_62-010", character_set_t::nf_z_62_010 }, + { "nf_z_62-010_(1973)", character_set_t::nf_z_62_010_1973 }, + { "no", character_set_t::ns_4551_1 }, + { "no2", character_set_t::ns_4551_2 }, + { "ns_4551-1", character_set_t::ns_4551_1 }, + { "ns_4551-2", character_set_t::ns_4551_2 }, + { "osd_ebcdic_df03_irv", character_set_t::osd_ebcdic_df03_irv }, + { "osd_ebcdic_df04_1", character_set_t::osd_ebcdic_df04_1 }, + { "osd_ebcdic_df04_15", character_set_t::osd_ebcdic_df04_15 }, + { "pc-multilingual-850+euro", character_set_t::ibm00858 }, + { "pc8-danish-norwegian", character_set_t::pc8_danish_norwegian }, + { "pc8-turkish", character_set_t::pc8_turkish }, + { "pt", character_set_t::pt }, + { "pt154", character_set_t::ptcp154 }, + { "pt2", character_set_t::pt2 }, + { "ptcp154", character_set_t::ptcp154 }, + { "r8", character_set_t::hp_roman8 }, + { "ref", character_set_t::iso_646_basic_1983 }, + { "rk1048", character_set_t::kz_1048 }, + { "roman8", character_set_t::hp_roman8 }, + { "scsu", character_set_t::scsu }, + { "se", character_set_t::sen_850200_b }, + { "se2", character_set_t::sen_850200_c }, + { "sen_850200_b", character_set_t::sen_850200_b }, + { "sen_850200_c", character_set_t::sen_850200_c }, + { "serbian", character_set_t::jus_i_b1_003_serb }, + { "shift_jis", character_set_t::shift_jis }, + { "st_sev_358-88", character_set_t::gost_19768_74 }, + { "strk1048-2002", character_set_t::kz_1048 }, + { "t.101-g2", character_set_t::t_101_g2 }, + { "t.61", character_set_t::t_61_8bit }, + { "t.61-7bit", character_set_t::t_61_7bit }, + { "t.61-8bit", character_set_t::t_61_8bit }, + { "tis-620", character_set_t::tis_620 }, + { "tscii", character_set_t::tscii }, + { "uk", character_set_t::bs_4730 }, + { "unicode-1-1", character_set_t::unicode_1_1 }, + { "unicode-1-1-utf-7", character_set_t::unicode_1_1_utf_7 }, + { "unknown-8bit", character_set_t::unknown_8bit }, + { "us", character_set_t::us_ascii }, + { "us-ascii", character_set_t::us_ascii }, + { "us-dk", character_set_t::us_dk }, + { "utf-16", character_set_t::utf_16 }, + { "utf-16be", character_set_t::utf_16be }, + { "utf-16le", character_set_t::utf_16le }, + { "utf-32", character_set_t::utf_32 }, + { "utf-32be", character_set_t::utf_32be }, + { "utf-32le", character_set_t::utf_32le }, + { "utf-7", character_set_t::utf_7 }, + { "utf-7-imap", character_set_t::utf_7_imap }, + { "utf-8", character_set_t::utf_8 }, + { "ventura-international", character_set_t::ventura_international }, + { "ventura-math", character_set_t::ventura_math }, + { "ventura-us", character_set_t::ventura_us }, + { "videotex-suppl", character_set_t::videotex_suppl }, + { "viqr", character_set_t::viqr }, + { "viscii", character_set_t::viscii }, + { "windows-1250", character_set_t::windows_1250 }, + { "windows-1251", character_set_t::windows_1251 }, + { "windows-1252", character_set_t::windows_1252 }, + { "windows-1253", character_set_t::windows_1253 }, + { "windows-1254", character_set_t::windows_1254 }, + { "windows-1255", character_set_t::windows_1255 }, + { "windows-1256", character_set_t::windows_1256 }, + { "windows-1257", character_set_t::windows_1257 }, + { "windows-1258", character_set_t::windows_1258 }, + { "windows-31j", character_set_t::windows_31j }, + { "windows-874", character_set_t::windows_874 }, + { "windows-936", character_set_t::gbk }, + { "x0201", character_set_t::jis_x0201 }, + { "x0201-7", character_set_t::jis_c6220_1969_jp }, + { "x0208", character_set_t::jis_c6226_1983 }, + { "x0212", character_set_t::jis_x0212_1990 }, + { "yu", character_set_t::jus_i_b1_002 }, +};const map_type& get() +{ + static map_type mt(entries, std::size(entries), character_set_t::unspecified); + return mt; +} + +} // namespace charset + +} // anonymous namespace + +dump_format_t to_dump_format_enum(std::string_view s) +{ + return dump_format::get().find(s); +} + +character_set_t to_character_set(std::string_view s) +{ + // Convert the source encoding string to all lower-case first. + std::string val_lower{s}; + std::transform(val_lower.begin(), val_lower.end(), val_lower.begin(), + [](unsigned char c) + { + return std::tolower(c); + } + ); + + return charset::get().find(val_lower); +} + +std::vector<std::pair<std::string_view, dump_format_t>> get_dump_format_entries() +{ + std::vector<std::pair<std::string_view, dump_format_t>> ret; + for (const auto& e : dump_format::entries) + ret.emplace_back(e.key, e.value); + + return ret; +} + +std::ostream& operator<< (std::ostream& os, const length_t& v) +{ + os << v.to_string(); + return os; +} + +std::ostream& operator<< (std::ostream& os, const date_time_t& v) +{ + os << v.to_string(); + return os; +} + +std::ostream& operator<< (std::ostream& os, format_t v) +{ + static const char* values[] = { + "unknown", + "ods", + "xlsx", + "gnumeric", + "xls-xml", + "csv" + }; + + size_t vi = static_cast<std::underlying_type_t<format_t>>(v); + size_t n = std::size(values); + + if (vi >= n) + os << "???"; + else + os << values[vi]; + + return os; +} + +const std::size_t INDEX_NOT_FOUND = std::numeric_limits<size_t>::max(); +const xmlns_id_t XMLNS_UNKNOWN_ID = nullptr; +const xml_token_t XML_UNKNOWN_TOKEN = 0; + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/parser/types_test.cpp b/src/parser/types_test.cpp new file mode 100644 index 0000000..ae22fdd --- /dev/null +++ b/src/parser/types_test.cpp @@ -0,0 +1,47 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "test_global.hpp" +#include <orcus/types.hpp> + +void test_character_set_t() +{ + orcus::test::stack_printer __sp__(__func__); + + using orcus::character_set_t; + + struct test_case + { + std::string_view input; + character_set_t expected; + }; + + constexpr test_case tests[] = { + { "utf-8", character_set_t::utf_8 }, + { "UTF-8", character_set_t::utf_8 }, + { "EUC-JP", character_set_t::euc_jp }, + { "GBK", character_set_t::gbk }, + { "Shift_JIS", character_set_t::shift_jis }, + { "MS_Kanji", character_set_t::shift_jis }, + { "csShiftJIS", character_set_t::shift_jis }, + { "GB2312", character_set_t::gb2312 }, + }; + + for (const auto& test : tests) + { + assert(orcus::to_character_set(test.input) == test.expected); + } +} + +int main() +{ + test_character_set_t(); + + return EXIT_SUCCESS; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/parser/utf8.cpp b/src/parser/utf8.cpp new file mode 100644 index 0000000..e02d224 --- /dev/null +++ b/src/parser/utf8.cpp @@ -0,0 +1,524 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "utf8.hpp" + +#include <cassert> +#include <stdexcept> +#include <limits> + +// https://en.wikipedia.org/wiki/UTF-8#Encoding +// https://www.w3.org/TR/2006/REC-xml11-20060816/#NT-NameStartChar + +namespace orcus { + +namespace { + +bool valid_second_byte(uint8_t b) +{ + return (b & 0xC0) == 0x80; +} + +bool parse_1b_start_char(uint8_t c1) +{ + if (c1 == '_') + return true; + + if ('a' <= c1 && c1 <= 'z') + return true; + + if ('A' <= c1 && c1 <= 'Z') + return true; + + return false; +} + +bool parse_1b_second_char(uint8_t c1) +{ + if (c1 == '-' || c1 == '.') + return true; + + if ('0' <= c1 && c1 <= '9') + return true; + + return false; +} + +// [ #xC0- #xD6]: C3 80 -> C3 96 +// [ #xD8- #xF6]: C3 98 -> C3 B6 +// [ #xF8-#x2FF]: C3 B8 -> CB BF +// [#x370-#x37D]: CD B0 -> CD BD +// +// [#x37F-#x1FFF]: (split) +// [#x37F-#x07FF]: CD BF -> DF BF +// +bool parse_2b_start_char(uint8_t c1, uint8_t c2) +{ + if (c1 == 0xC3) + { + if (0x80 <= c2 && c2 <= 0x96) + return true; + + if (0x98 <= c2 && c2 <= 0xB6) + return true; + + if (0xB8 <= c2) + return true; + } + + // C4 80 -> CB BF + if (0xC4 <= c1 && c1 <= 0xCB) + return 0x80 <= c2 && c2 <= 0xBF; + + // CD B0 -> CD BD + // CD BF -> DF BF + + if (c1 == 0xCD) + { + if (0xB0 <= c2 && c2 <= 0xBD) + return true; + + return c2 == 0xBF; + } + + // CE xx -> DF xx + return 0xCE <= c1 && c1 <= 0xDF; +} + +// #xB7: C2 B7 +// [#x0300-#x036F]: CC 80 -> CD AF +bool parse_2b_second_char(uint8_t c1, uint8_t c2) +{ + // C2 B7 + if (c1 == 0xC2) + return c2 == 0xB7; + + // CC 80 -> CD AF + // - CC xx + // - CD xx -> CD AF + + if (c1 == 0xCC) + return true; + + if (c1 == 0xCD) + return c2 <= 0xAF; + + return false; +} + +// [#x800-#x1FFF]: E0 A0 80 -> E1 BF BF +// +// [#x200C-#x200D]: E2 80 8C -> E2 80 8D +// [#x2070-#x218F]: E2 81 B0 -> E2 86 8F +// [#x2C00-#x2FEF]: E2 B0 80 -> E2 BF AF +// [#x3001-#xD7FF]: E3 80 81 -> ED 9F BF +// [#xF900-#xFDCF]: EF A4 80 -> EF B7 8F +// [#xFDF0-#xFFFD]: EF B7 B0 -> EF BF BD +bool parse_3b_start_char(uint8_t c1, uint8_t c2, uint8_t c3) +{ + // E0 A0 80 -> E1 BF BF + // - E0 A0 80 -> E0 BF BF + // - E1 xx xx + + if (c1 == 0xE0) + { + // A0 80 -> BF BF + return (0xA0 <= c2 && c2 <= 0xBF && 0x80 <= c3 && c3 <= 0xBF); + } + + if (c1 == 0xE1) + // entire E1 xx xx range is valid. + return true; + + if (c1 == 0xE2) + { + // E2 80 8C -> E2 80 8D + // E2 81 B0 -> E2 86 8F + // E2 B0 80 -> E2 BF AF + + if (c2 == 0x80) + // 8C -> 8D + return c3 == 0x8C || c3 == 0x8D; + + // 81 B0 -> 86 8F + if (c2 == 0x81) + return c3 >= 0xB0; + + if (0x82 <= c2 && c2 <= 0x85) + return true; + + if (c2 == 0x86) + return c3 <= 0x8F; + + // B0 80 -> BF AF + if (0xB0 <= c2 && c2 <= 0xBE) + return true; + + if (c2 == 0xBF) + return c3 <= 0xAF; + } + + // E3 80 81 -> ED 9F BF + // - E3 80 81 -> E3 80 BF + // - E3 81 xx + // - E4 xx xx -> EC xx xx + // - ED xx xx -> ED 9F xx + if (c1 == 0xE3) + { + if (c2 == 0x80) + return c3 >= 0x81; + + return 0x81 <= c2; + } + + if (0xE4 <= c1 && c1 <= 0xEC) + return true; + + if (c1 == 0xED) + return c2 <= 0x9F; + + // EF A4 80 -> EF B7 8F + // - EF A4 xx + // - EF A5 xx -> EF B6 xx + // - EF B7 xx -> EF B7 8F + // EF B7 B0 -> EF BF BD + // - EF B7 B0 -> EF B7 xx + // - EF B8 xx -> EF BE xx + // - EF BF xx -> EF BF BD + if (c1 == 0xEF) + { + if (c2 == 0xA4) + return true; + + if (0xA5 <= c2 && c2 <= 0xB6) + return true; + + if (c2 == 0xB7) + { + if (c3 <= 0x8F) + return true; + + return 0xB0 <= c3; + } + + if (0xB8 <= c2 && c2 <= 0xBE) + return true; + + if (c2 == 0xBF) + return c3 <= 0xBD; + } + + return false; +} + +// [#x203F-#x2040]: E2 80 BF -> E2 81 80 +bool parse_3b_second_char(uint8_t c1, uint8_t c2, uint8_t c3) +{ + if (c1 != 0xE2) + return false; + + if (c2 == 0x80) + return c3 == 0xBF; + + if (c2 == 0x81) + return c3 == 0x80; + + return false; +} + +// [#x10000-#xEFFFF]: F0 90 80 80 -> F3 AF BF BF +bool parse_4b_char(uint8_t c1, uint8_t c2, uint8_t /*c3*/, uint8_t /*c4*/) +{ + // F0 90 80 80 -> F3 AF BF BF + // - F0 90 xx xx -> F0 xx xx xx + // - F1 xx xx xx -> F2 xx xx xx + // - F3 xx xx xx -> F3 AF xx xx + if (c1 == 0xF0) + return 0x90 <= c2; + + if (0xF1 <= c1 && c1 <= 0xF2) + return true; + + if (c1 == 0xF3) + return c2 <= 0xAF; + + return false; +} + +uint8_t calc_encoded_length(uint32_t cp) +{ + if (cp <= 0x7F) + return 1; + + if (0x80 <= cp && cp <= 0x7FF) + return 2; + + if (0x800 <= cp && cp <= 0xFFFF) + return 3; + + if (0x10000 <= cp && cp <= 0x10FFFF) + return 4; + + throw std::runtime_error("invalid utf-8 range."); +} + +// input must be less than or equal to 0x7FF +// +// b1: 0b110xxxxx (5) +// b2: 0b10xxxxxx (6) +std::vector<char> encode_2b(uint32_t cp) +{ + assert(cp <= 0x7FF); + + // Get the lowest 6 bits + char low = (cp & 0x3F); + low |= 0x80; + + // Get the next 5 bits + cp = cp >> 6; + char high = (cp & 0x1F); + high |= 0xC0; + + std::vector<char> ret = { high, low }; + return ret; +} + +// input must be less than or equal to 0xFFFF +// +// b1: 0b1110xxxx (4) +// b2: 0b10xxxxxx (6) +// b3: 0b10xxxxxx (6) +std::vector<char> encode_3b(uint32_t cp) +{ + assert(cp <= 0xFFFF); + + // Get the lowest 6 bits + char low = (cp & 0x3F); + low |= 0x80; + cp = cp >> 6; + + // Get the middle 6 bits + char mid = (cp & 0x3F); + mid |= 0x80; + cp = cp >> 6; + + // Get the next 4 bits + char high = (cp & 0x0F); + high |= 0xE0; + + std::vector<char> ret = { high, mid, low }; + return ret; +} + +// input must be less than or equal to 0x10FFFF +// +// b1: 0b11110xxx (3) +// b2: 0b10xxxxxx (6) +// b3: 0b10xxxxxx (6) +// b4: 0b10xxxxxx (6) +std::vector<char> encode_4b(uint32_t cp) +{ + assert(cp <= 0x10FFFF); + + // Get the lowest 6 bits + char low = (cp & 0x3F); + low |= 0x80; + cp = cp >> 6; + + // Get the next 6 bits + char mid1 = (cp & 0x3F); + mid1 |= 0x80; + cp = cp >> 6; + + // Get the next 6 bits + char mid2 = (cp & 0x3F); + mid2 |= 0x80; + cp = cp >> 6; + + // Get the next 3 bits + char high = (cp & 0x07); + high |= 0xF0; + + std::vector<char> ret = { high, mid2, mid1, low }; + return ret; +} + +} // anonymous namespace + +const char* parse_utf8_xml_name_start_char(const char* p, const char* p_end) +{ + size_t n_remaining = p_end - p; + if (!n_remaining) + return p; + + uint8_t n_bytes = calc_utf8_byte_length(*p); + + switch (n_bytes) + { + case 1: + return parse_1b_start_char(*p) ? p + 1 : p; + case 2: + { + if (n_remaining < 2) + return p; + + uint8_t c1 = p[0]; + uint8_t c2 = p[1]; + + if (!valid_second_byte(c2)) + return p; + + return parse_2b_start_char(c1, c2) ? p + 2 : p; + } + case 3: + { + if (n_remaining < 3) + return p; + + uint8_t c1 = p[0]; + uint8_t c2 = p[1]; + uint8_t c3 = p[2]; + + if (!valid_second_byte(c2) || !valid_second_byte(c3)) + return p; + + return parse_3b_start_char(c1, c2, c3) ? p + 3 : p; + } + case 4: + { + if (n_remaining < 4) + return p; + + uint8_t c1 = p[0]; + uint8_t c2 = p[1]; + uint8_t c3 = p[2]; + uint8_t c4 = p[3]; + + if (!valid_second_byte(c2) || !valid_second_byte(c3) || !valid_second_byte(c4)) + return p; + + return parse_4b_char(c1, c2, c3, c4) ? p + 4 : p; + } + } + + return p; +} + +const char* parse_utf8_xml_name_char(const char* p, const char* p_end) +{ + size_t n_remaining = p_end - p; + if (!n_remaining) + return p; + + uint8_t n_bytes = calc_utf8_byte_length(*p); + + switch (n_bytes) + { + case 1: + { + if (parse_1b_start_char(*p)) + return p + 1; + + return parse_1b_second_char(*p) ? p + 1 : p; + } + case 2: + { + if (n_remaining < 2) + return p; + + uint8_t c1 = p[0]; + uint8_t c2 = p[1]; + + if (!valid_second_byte(c2)) + return p; + + if (parse_2b_start_char(c1, c2)) + return p + 2; + + return parse_2b_second_char(c1, c2) ? p + 2 : p; + } + case 3: + { + if (n_remaining < 3) + return p; + + uint8_t c1 = p[0]; + uint8_t c2 = p[1]; + uint8_t c3 = p[2]; + + if (!valid_second_byte(c2) || !valid_second_byte(c3)) + return p; + + if (parse_3b_start_char(c1, c2, c3)) + return p + 3; + + return parse_3b_second_char(c1, c2, c3) ? p + 3 : p; + } + case 4: + { + if (n_remaining < 4) + return p; + + uint8_t c1 = p[0]; + uint8_t c2 = p[1]; + uint8_t c3 = p[2]; + uint8_t c4 = p[3]; + + if (!valid_second_byte(c2) || !valid_second_byte(c3) || !valid_second_byte(c4)) + return p; + + return parse_4b_char(c1, c2, c3, c4) ? p + 4 : p; + } + } + + return p; +} + +std::vector<char> encode_utf8(uint32_t cp) +{ + uint8_t n_encoded = calc_encoded_length(cp); + + switch (n_encoded) + { + case 1: + // no conversion + return std::vector<char>(1, cp); + case 2: + return encode_2b(cp); + case 3: + return encode_3b(cp); + case 4: + return encode_4b(cp); + } + + throw std::logic_error("this should never be reached."); +} + +uint8_t calc_utf8_byte_length(uint8_t c1) +{ + if ((c1 & 0x80) == 0x00) + // highest bit is not set. + return 1; + + if ((c1 & 0xE0) == 0xC0) + // highest 3 bits are 110. + return 2; + + if ((c1 & 0xF0) == 0xE0) + // highest 4 bits are 1110. + return 3; + + if ((c1 & 0xFC) == 0xF0) + // highest 5 bits are 11110. + return 4; + + return std::numeric_limits<uint8_t>::max(); +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/parser/utf8.hpp b/src/parser/utf8.hpp new file mode 100644 index 0000000..01457de --- /dev/null +++ b/src/parser/utf8.hpp @@ -0,0 +1,28 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_ORCUS_PARSER_UTF8_HPP +#define INCLUDED_ORCUS_PARSER_UTF8_HPP + +#include <vector> +#include <cstdint> + +namespace orcus { + +const char* parse_utf8_xml_name_start_char(const char* p, const char* p_end); + +const char* parse_utf8_xml_name_char(const char* p, const char* p_end); + +std::vector<char> encode_utf8(uint32_t cp); + +uint8_t calc_utf8_byte_length(uint8_t c1); + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/parser/utf8_test.cpp b/src/parser/utf8_test.cpp new file mode 100644 index 0000000..88dcd3e --- /dev/null +++ b/src/parser/utf8_test.cpp @@ -0,0 +1,170 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "test_global.hpp" +#include "utf8.hpp" + +#include <iostream> +#include <vector> +#include <string> +#include <cassert> +#include <functional> +#include <iomanip> + +using namespace orcus; +using std::cout; +using std::endl; + +struct cp_range_t +{ + uint32_t lower; + uint32_t upper; + bool valid; +}; + +using parse_func_t = std::function<const char*(const char*, const char*)>; + +bool check_cp_ranges(parse_func_t parse, std::vector<cp_range_t> ranges) +{ + for (const cp_range_t& range : ranges) + { + for (uint32_t cp = range.lower; cp <= range.upper; ++cp) + { + std::vector<char> buf; + + try + { + buf = encode_utf8(cp); + } + catch (const std::exception& e) + { + cout << "failed to encode 0x" << std::hex << std::uppercase << cp + << " as utf-8: " << e.what() << endl; + return false; + } + + const char* p = buf.data(); + const char* p_end = p + buf.size(); + const char* ret = parse(p, p_end); + + if ((ret == p_end) != range.valid) + { + cout << "failed to parse 0x" << std::hex << std::uppercase << cp + << " (utf-8:"; + + for (char b : buf) + cout << ' ' << short(0xFF & b); + cout << ")" << endl; + cout << "expected to be " << (range.valid ? "valid" : "invalid") + << ", but was " << (range.valid ? "invalid" : "valid") << endl; + return false; + } + } + } + + return true; +} + +void test_xml_name_start_char() +{ + bool res = check_cp_ranges( + parse_utf8_xml_name_start_char, + { + { 0x00, 0x40, false }, + { 'A', 'Z', true }, + { '[', '^', false }, + { '_', '_', true }, + { '`', '`', false }, + { 'a', 'z', true }, + { '{', 0xBF, false }, + { 0xC0, 0xD6, true }, + { 0xD7, 0xD7, false }, + { 0xD8, 0xF6, true }, + { 0xF7, 0xF7, false }, + { 0xF8, 0x2FF, true }, + { 0x300, 0x36F, false }, + { 0x370, 0x37D, true }, + { 0x37E, 0x37E, false }, + { 0x37F, 0x1FFF, true }, + { 0x2000, 0x200B, false }, + { 0x200C, 0x200D, true }, + { 0x200E, 0x206F, false }, + { 0x2070, 0x218F, true }, + { 0x2190, 0x2BFF, false }, + { 0x2C00, 0x2FEF, true }, + { 0x2FF0, 0x3000, false }, + { 0x3001, 0xD7FF, true }, + { 0xD800, 0xF8FF, false }, + { 0xF900, 0xFDCF, true }, + { 0xFDD0, 0xFDEF, false }, + { 0xFDF0, 0xFFFD, true }, + { 0xFFFE, 0xFFFF, false }, + { 0x10000, 0xEFFFF, true }, + { 0xF0000, 0xF0000, false }, // just check one byte past last valid byte. + } + ); + assert(res); +} + +void test_xml_name_char() +{ + bool res = check_cp_ranges( + parse_utf8_xml_name_char, + { + { 0x00, ',', false }, + { '-', '.', true }, // 0x2D - 0x2E + { '/', '/', false }, + { '0', '9', true }, + { ':', '@', false }, + { 'A', 'Z', true }, + { '[', '^', false }, + { '_', '_', true }, // 0x5F + { '`', '`', false }, + { 'a', 'z', true }, + { '{', 0xB6, false }, + { 0xB7, 0xB7, true }, + { 0xB8, 0xBF, false }, + { 0xC0, 0xD6, true }, + { 0xD7, 0xD7, false }, + { 0xD8, 0xF6, true }, + { 0xF7, 0xF7, false }, + { 0xF8, 0x2FF, true }, + { 0x300, 0x36F, true }, + { 0x370, 0x37D, true }, + { 0x37E, 0x37E, false }, + { 0x37F, 0x1FFF, true }, + { 0x2000, 0x200B, false }, + { 0x200C, 0x200D, true }, + { 0x200E, 0x203E, false }, + { 0x203F, 0x2040, true }, + { 0x2041, 0x206F, false }, + { 0x2070, 0x218F, true }, + { 0x2190, 0x2BFF, false }, + { 0x2C00, 0x2FEF, true }, + { 0x2FF0, 0x3000, false }, + { 0x3001, 0xD7FF, true }, + { 0xD800, 0xF8FF, false }, + { 0xF900, 0xFDCF, true }, + { 0xFDD0, 0xFDEF, false }, + { 0xFDF0, 0xFFFD, true }, + { 0xFFFE, 0xFFFF, false }, + { 0x10000, 0xEFFFF, true }, + { 0xF0000, 0xF0000, false }, // just check one byte past last valid byte. + } + ); + assert(res); +} + +int main() +{ + test_xml_name_start_char(); + test_xml_name_char(); + + return EXIT_SUCCESS; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/parser/win_stdint.h b/src/parser/win_stdint.h new file mode 100644 index 0000000..e51d46f --- /dev/null +++ b/src/parser/win_stdint.h @@ -0,0 +1,46 @@ +/************************************************************************* + * + * Copyright (c) 2013 Markus Mohrhard + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + ************************************************************************/ + +#ifndef WIN_STDINT +#define WIN_STDINT + +#if _MSC_VER <= 1500 + +typedef signed __int16 int16_t; +typedef unsigned __int16 uint16_t; +typedef __int32 int32_t; +typedef unsigned __int32 uint32_t; +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; + +#else + +#include <stdint.h> + +#endif // visual studio version + +#endif
\ No newline at end of file diff --git a/src/parser/xml_namespace.cpp b/src/parser/xml_namespace.cpp new file mode 100644 index 0000000..2aafea3 --- /dev/null +++ b/src/parser/xml_namespace.cpp @@ -0,0 +1,490 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <orcus/xml_namespace.hpp> +#include <orcus/exception.hpp> +#include <orcus/string_pool.hpp> + +#include <unordered_map> +#include <vector> +#include <limits> +#include <sstream> +#include <algorithm> +#include <cassert> + +#define ORCUS_DEBUG_XML_NAMESPACE 0 + +using namespace std; + +#if ORCUS_DEBUG_XML_NAMESPACE +#include <cstdio> +#include <iostream> +#endif + +namespace orcus { + +namespace { + +#if ORCUS_DEBUG_XML_NAMESPACE +template<typename _MapType> +void print_map_keys(const _MapType& map_store) +{ + cout << "keys: ("; + bool first = true; + typename _MapType::const_iterator it = map_store.begin(), it_end = map_store.end(); + for (; it != it_end; ++it) + { + if (first) + first = false; + else + cout << " "; + cout << "'" << it->first << "'"; + } + cout << ")"; +}; +#endif + +} + +typedef std::unordered_map<std::string_view, std::size_t> strid_map_type; + +struct xmlns_repository::impl +{ + size_t m_predefined_ns_size; + string_pool m_pool; /// storage of live string instances. + std::vector<std::string_view> m_identifiers; /// map strings to numerical identifiers. + strid_map_type m_strid_map; /// string-to-numerical identifiers map for quick lookup. + + impl() : m_predefined_ns_size(0) {} +}; + +xmlns_repository::xmlns_repository() : mp_impl(std::make_unique<impl>()) {} +xmlns_repository::xmlns_repository(xmlns_repository&& other) : mp_impl(std::move(other.mp_impl)) {} +xmlns_repository::~xmlns_repository() = default; + +xmlns_repository& xmlns_repository::operator= (xmlns_repository&& other) +{ + mp_impl = std::move(other.mp_impl); + return *this; +} + +xmlns_id_t xmlns_repository::intern(std::string_view uri) +{ + // See if the uri is already registered. + strid_map_type::iterator it = mp_impl->m_strid_map.find(uri); + if (it != mp_impl->m_strid_map.end()) + return it->first.data(); + + try + { + auto r = mp_impl->m_pool.intern(uri); + std::string_view uri_interned = r.first; + + if (!uri_interned.empty()) + { + // Intern successful. + if (r.second) + { + // This is a new instance. Assign a numerical identifier. + mp_impl->m_strid_map.insert( + strid_map_type::value_type(r.first, mp_impl->m_identifiers.size())); +#if ORCUS_DEBUG_XML_NAMESPACE + cout << "xmlns_repository::intern: uri='" << uri_interned << "' (" << mp_impl->m_identifiers.size() << ")" << endl; +#endif + mp_impl->m_identifiers.push_back(r.first); + +#if ORCUS_DEBUG_XML_NAMESPACE + cout << "pool size=" << mp_impl->m_pool.size() << ", predefined ns size=" << mp_impl->m_predefined_ns_size << + ", identifiers size=" << mp_impl->m_identifiers.size() << ", map size=" << mp_impl->m_strid_map.size() << endl; +#endif + assert(mp_impl->m_pool.size()+mp_impl->m_predefined_ns_size == mp_impl->m_identifiers.size()); + assert(mp_impl->m_pool.size()+mp_impl->m_predefined_ns_size == mp_impl->m_strid_map.size()); + } + return uri_interned.data(); + } + } + catch (const general_error&) + { + } + + return XMLNS_UNKNOWN_ID; +} + +void xmlns_repository::add_predefined_values(const xmlns_id_t* predefined_ns) +{ + if (!predefined_ns) + return; + + const xmlns_id_t* val = &predefined_ns[0]; + for (; *val; ++val) + { + std::string_view s(*val); + mp_impl->m_strid_map.insert( + strid_map_type::value_type(s, mp_impl->m_identifiers.size())); + mp_impl->m_identifiers.push_back(s); + + ++mp_impl->m_predefined_ns_size; + +#if ORCUS_DEBUG_XML_NAMESPACE + cout << "xlmns_repository: predefined ns='" << s << "'" << endl; +#endif + } +} + +xmlns_context xmlns_repository::create_context() +{ + return xmlns_context(*this); +} + +xmlns_id_t xmlns_repository::get_identifier(size_t index) const +{ + if (index >= mp_impl->m_identifiers.size()) + return XMLNS_UNKNOWN_ID; + + // All identifier strings are interned which means they are all null-terminated. + return mp_impl->m_identifiers[index].data(); +} + +string xmlns_repository::get_short_name(xmlns_id_t ns_id) const +{ + size_t index = get_index(ns_id); + + if (index == INDEX_NOT_FOUND) + return string("???"); + + std::ostringstream os; + os << "ns" << index; + return os.str(); +} + +size_t xmlns_repository::get_index(xmlns_id_t ns_id) const +{ + if (!ns_id) + return INDEX_NOT_FOUND; + + auto it = mp_impl->m_strid_map.find(std::string_view(ns_id)); + if (it == mp_impl->m_strid_map.end()) + return INDEX_NOT_FOUND; + + return it->second; +} + +typedef std::vector<xmlns_id_t> xmlns_list_type; +typedef std::unordered_map<std::string_view, xmlns_list_type> alias_map_type; + +struct xmlns_context::impl +{ + xmlns_repository* repo = nullptr; + xmlns_list_type m_all_ns; /// all namespaces ever used in this context. + xmlns_list_type m_default; + alias_map_type m_map; + + bool m_trim_all_ns = true; + + impl() {} + impl(xmlns_repository& _repo) : repo(&_repo) {} + impl(const impl& r) : + repo(r.repo), m_all_ns(r.m_all_ns), m_default(r.m_default), m_map(r.m_map), m_trim_all_ns(r.m_trim_all_ns) {} +}; + +xmlns_context::xmlns_context() : mp_impl(std::make_unique<impl>()) {} +xmlns_context::xmlns_context(xmlns_repository& repo) : mp_impl(std::make_unique<impl>(repo)) {} +xmlns_context::xmlns_context(const xmlns_context& r) : mp_impl(std::make_unique<impl>(*r.mp_impl)) {} +xmlns_context::xmlns_context(xmlns_context&& r) : mp_impl(std::move(r.mp_impl)) +{ + r.mp_impl = std::make_unique<impl>(); +} + +xmlns_context::~xmlns_context() = default; + +xmlns_context& xmlns_context::operator= (const xmlns_context& r) +{ + xmlns_context tmp(r); + tmp.swap(*this); + return *this; +} + +xmlns_context& xmlns_context::operator= (xmlns_context&& r) +{ + xmlns_context tmp(std::move(r)); + tmp.swap(*this); + return *this; +} + +xmlns_id_t xmlns_context::push(std::string_view alias, std::string_view uri) +{ + if (!mp_impl->repo) + throw general_error("this context is not associated with any repo."); + +#if ORCUS_DEBUG_XML_NAMESPACE + cout << "xmlns_context::push: key='" << alias << "', uri='" << uri << "'" << endl; +#endif + mp_impl->m_trim_all_ns = true; + + xmlns_id_t id = mp_impl->repo->intern(uri); + std::string_view uri_interned = id ? std::string_view(id) : std::string_view(); + + if (alias.empty()) + { + // empty alias value is associated with default namespace. + mp_impl->m_default.push_back(uri_interned.data()); + mp_impl->m_all_ns.push_back(uri_interned.data()); + return mp_impl->m_default.back(); + } + + // See if this alias already exists. + alias_map_type::iterator it = mp_impl->m_map.find(alias); + if (it == mp_impl->m_map.end()) + { + // This is the first time this alias is used. + xmlns_list_type nslist; + nslist.push_back(uri_interned.data()); + mp_impl->m_all_ns.push_back(uri_interned.data()); + std::pair<alias_map_type::iterator,bool> r = + mp_impl->m_map.insert(alias_map_type::value_type(alias, nslist)); + + if (!r.second) + // insertion failed. + throw general_error("Failed to insert new namespace."); + + return nslist.back(); + } + + // The alias already exists. + xmlns_list_type& nslist = it->second; + nslist.push_back(uri_interned.data()); + mp_impl->m_all_ns.push_back(uri_interned.data()); + return nslist.back(); +} + +void xmlns_context::pop(std::string_view alias) +{ +#if ORCUS_DEBUG_XML_NAMESPACE + cout << "xmlns_context::pop: alias='" << alias << "'" << endl; +#endif + if (alias.empty()) + { + // empty alias value is associated with default namespace. + if (mp_impl->m_default.empty()) + throw general_error("default namespace stack is empty."); + + mp_impl->m_default.pop_back(); + return; + } + + // See if this alias really exists. + alias_map_type::iterator it = mp_impl->m_map.find(alias); + if (it == mp_impl->m_map.end()) + { + std::ostringstream os; + os << "alias named '" << alias << "' was attempted to be popped, but was not found in the stack"; + throw general_error(os.str()); + } + + xmlns_list_type& nslist = it->second; + if (nslist.empty()) + throw general_error("namespace stack for this key is empty."); + + nslist.pop_back(); +} + +xmlns_id_t xmlns_context::get(std::string_view alias) const +{ +#if ORCUS_DEBUG_XML_NAMESPACE + cout << "xmlns_context::get: alias='" << alias << "', default ns stack size=" + << mp_impl->m_default.size() << ", non-default alias count=" << mp_impl->m_map.size(); + cout << ", "; + print_map_keys(mp_impl->m_map); + cout << endl; +#endif + if (alias.empty()) + return mp_impl->m_default.empty() ? XMLNS_UNKNOWN_ID : mp_impl->m_default.back(); + + alias_map_type::const_iterator it = mp_impl->m_map.find(alias); + if (it == mp_impl->m_map.end()) + { +#if ORCUS_DEBUG_XML_NAMESPACE + cout << "xmlns_context::get: alias not in this context" << endl; +#endif + return XMLNS_UNKNOWN_ID; + } + +#if ORCUS_DEBUG_XML_NAMESPACE + cout << "xmlns_context::get: alias stack size=" << it->second.size() << endl; +#endif + return it->second.empty() ? XMLNS_UNKNOWN_ID : it->second.back(); +} + +size_t xmlns_context::get_index(xmlns_id_t ns_id) const +{ + if (!mp_impl->repo) + throw general_error("this context is not associated with any repo."); + + return mp_impl->repo->get_index(ns_id); +} + +string xmlns_context::get_short_name(xmlns_id_t ns_id) const +{ + if (!mp_impl->repo) + throw general_error("this context is not associated with any repo."); + + return mp_impl->repo->get_short_name(ns_id); +} + +std::string_view xmlns_context::get_alias(xmlns_id_t ns_id) const +{ + alias_map_type::const_iterator it = mp_impl->m_map.begin(), it_end = mp_impl->m_map.end(); + for (; it != it_end; ++it) + { + const xmlns_list_type& lst = it->second; + if (lst.empty()) + continue; + + if (lst.back() == ns_id) + return it->first; + } + + return std::string_view{}; +} + +namespace { + +#if ORCUS_DEBUG_XML_NAMESPACE +struct print_ns +{ + void operator() (xmlns_id_t ns_id) const + { + const char* p = ns_id; + printf("%p: %s\n", p, p); + } +}; +#endif + +struct ns_item +{ + size_t index; + xmlns_id_t ns; + + ns_item(size_t _index, xmlns_id_t _ns) : index(_index), ns(_ns) {} +}; + +struct less_ns_by_index +{ + bool operator() (const ns_item& left, const ns_item& right) const + { + return left.index < right.index; + } +}; + +class push_back_ns_to_item +{ + vector<ns_item>& m_store; + const xmlns_context& m_cxt; +public: + push_back_ns_to_item(vector<ns_item>& store, const xmlns_context& cxt) : m_store(store), m_cxt(cxt) {} + void operator() (xmlns_id_t ns) + { + size_t num_id = m_cxt.get_index(ns); + if (num_id != INDEX_NOT_FOUND) + m_store.push_back(ns_item(num_id, ns)); + } +}; + +class push_back_item_to_ns +{ + std::vector<xmlns_id_t>& m_store; +public: + push_back_item_to_ns(std::vector<xmlns_id_t>& store) : m_store(store) {} + void operator() (const ns_item& item) + { + m_store.push_back(item.ns); + } +}; + +} + +std::vector<xmlns_id_t> xmlns_context::get_all_namespaces() const +{ +#if ORCUS_DEBUG_XML_NAMESPACE + cout << "xmlns_context::get_all_namespaces: count=" << mp_impl->m_all_ns.size() << endl; + std::for_each(mp_impl->m_all_ns.begin(), mp_impl->m_all_ns.end(), print_ns()); +#endif + + std::vector<xmlns_id_t> nslist; + + if (mp_impl->m_trim_all_ns) + { + xmlns_list_type& all_ns = mp_impl->m_all_ns; + + nslist.assign(mp_impl->m_all_ns.begin(), mp_impl->m_all_ns.end()); + + // Sort it and remove duplicate. + std::sort(all_ns.begin(), all_ns.end()); + xmlns_list_type::iterator it_unique_end = + std::unique(all_ns.begin(), all_ns.end()); + all_ns.erase(it_unique_end, all_ns.end()); + + // Now, sort by indices. + vector<ns_item> items; + std::for_each(all_ns.begin(), all_ns.end(), push_back_ns_to_item(items, *this)); + std::sort(items.begin(), items.end(), less_ns_by_index()); + + all_ns.clear(); + std::for_each(items.begin(), items.end(), push_back_item_to_ns(all_ns)); + + mp_impl->m_trim_all_ns = false; + } + + nslist.assign(mp_impl->m_all_ns.begin(), mp_impl->m_all_ns.end()); + return nslist; +} + +void xmlns_context::dump(std::ostream& os) const +{ + vector<xmlns_id_t> nslist = get_all_namespaces(); + vector<xmlns_id_t>::const_iterator it = nslist.begin(), it_end = nslist.end(); + for (; it != it_end; ++it) + { + xmlns_id_t ns_id = *it; + size_t num_id = get_index(ns_id); + if (num_id == INDEX_NOT_FOUND) + continue; + + os << "ns" << num_id << "=\"" << ns_id << '"' << endl; + } +} + +void xmlns_context::dump_state(std::ostream& os) const +{ + os << "namespaces:" << std::endl; + for (xmlns_id_t ns_id : get_all_namespaces()) + { + size_t num_id = get_index(ns_id); + if (num_id == INDEX_NOT_FOUND) + continue; + + os << " ns" << num_id << ": \"" << ns_id << '"' << std::endl; + } + + os << "aliases:" << std::endl; + for (const auto& [alias, ns_list] : mp_impl->m_map) + { + os << " " << alias << ":" << std::endl; + + for (const xmlns_id_t ns : ns_list) + os << " - " << ns << std::endl; + } +} + +void xmlns_context::swap(xmlns_context& other) noexcept +{ + mp_impl.swap(other.mp_impl); +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/parser/xml_namespace_test.cpp b/src/parser/xml_namespace_test.cpp new file mode 100644 index 0000000..de3891e --- /dev/null +++ b/src/parser/xml_namespace_test.cpp @@ -0,0 +1,239 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "test_global.hpp" +#include "orcus/xml_namespace.hpp" + +#include <cstdlib> +#include <vector> +#include <algorithm> + +using namespace orcus; + +namespace { + +void test_basic() +{ + ORCUS_TEST_FUNC_SCOPE; + + std::string_view xmlns1("http://some.xmlns/"); + std::string_view xmlns2("http://other.xmlns/"); + + xmlns_repository repo; + xmlns_context cxt1 = repo.create_context(); + xmlns_context cxt2 = repo.create_context(); + + std::string_view empty, myns("myns"); + { + // context 1 + xmlns_id_t test1 = cxt1.push(empty, xmlns1); // register default namespace. + assert(cxt1.get(empty) == test1); + xmlns_id_t test2 = cxt1.push(myns, xmlns2); + assert(cxt1.get(myns) == test2); + assert(test1 != test2); + } + + { + // context 2 + xmlns_id_t test1 = cxt2.push(empty, xmlns2); // register default namespace. + assert(cxt2.get(empty) == test1); + xmlns_id_t test2 = cxt2.push(myns, xmlns1); + assert(cxt2.get(myns) == test2); + assert(test1 != test2); + } + + // Now, compare the registered namespaces between the two namespaces. + assert(cxt1.get(empty) == cxt2.get(myns)); + assert(cxt1.get(myns) == cxt2.get(empty)); +} + +void test_all_namespaces() +{ + ORCUS_TEST_FUNC_SCOPE; + + std::string_view key1("a"), key2("b"), key3("c"); + std::string_view ns1("foo"), ns2("baa"), ns3("hmm"); + + xmlns_repository repo; + xmlns_context cxt = repo.create_context(); + xmlns_id_t ns; + + ns = cxt.push(key1, ns1); + assert(ns1 == ns); + ns = cxt.push(key2, ns2); + assert(ns2 == ns); + ns = cxt.push(key3, ns3); + assert(ns3 == ns); + + std::vector<xmlns_id_t> all_ns = cxt.get_all_namespaces(); + assert(all_ns.size() == 3); + assert(ns1 == all_ns[0]); + assert(ns2 == all_ns[1]); + assert(ns3 == all_ns[2]); +} + +const xmlns_id_t NS_test_name1 = "test:name:1"; +const xmlns_id_t NS_test_name2 = "test:name:2"; +const xmlns_id_t NS_test_name3 = "test:name:3"; + +xmlns_id_t NS_test_all[] = { + NS_test_name1, + NS_test_name2, + NS_test_name3, + nullptr +}; + +xmlns_id_t NS_test_all_reverse[] = { + NS_test_name3, + NS_test_name2, + NS_test_name1, + nullptr +}; + +void test_predefined_ns() +{ + xmlns_repository ns_repo; + ns_repo.add_predefined_values(NS_test_all); + xmlns_context cxt = ns_repo.create_context(); + xmlns_id_t ns_id = cxt.push("tn1", "test:name:1"); + assert(ns_id == NS_test_name1); + ns_id = cxt.push("tn2", "test:name:2"); + assert(ns_id == NS_test_name2); + ns_id = cxt.push("tn3", "test:name:3"); + assert(ns_id == NS_test_name3); + assert(cxt.get("tn1") == NS_test_name1); + assert(cxt.get("tn2") == NS_test_name2); + assert(cxt.get("tn3") == NS_test_name3); +} + +void test_xml_name_t() +{ + ORCUS_TEST_FUNC_SCOPE; + + xml_name_t name1; + name1.ns = NS_test_name1; + name1.name = "foo"; + + xml_name_t name2 = name1; + assert(name1 == name2); + + name2.name = "foo2"; + assert(name1 != name2); + + xml_name_t name3 = name1; + name3.ns = NS_test_name2; + assert(name1 != name3); +} + +void test_ns_context() +{ + ORCUS_TEST_FUNC_SCOPE; + + xmlns_repository repo; + repo.add_predefined_values(NS_test_all); + + xmlns_repository repo2; + repo2.add_predefined_values(NS_test_all_reverse); + + xmlns_context cxt; + cxt = repo.create_context(); // copy assignment + size_t id1 = cxt.get_index(NS_test_name3); + xmlns_context cxt2 = cxt; // copy ctor + size_t id2 = cxt2.get_index(NS_test_name3); + + assert(id1 == id2); + + xmlns_context cxt3 = repo2.create_context(); + id2 = cxt3.get_index(NS_test_name3); + + assert(id1 != id2); + + cxt3 = std::move(cxt2); // move assignment + id2 = cxt3.get_index(NS_test_name3); + + assert(id1 == id2); + + try + { + id1 = cxt2.get_index(NS_test_name2); + assert(!"exception was supposed to be thrown due to no associated repos."); + } + catch (const std::exception&) + { + // expected + } + + xmlns_context cxt4(std::move(cxt3)); // move ctor + id1 = cxt4.get_index(NS_test_name3); + + xmlns_context cxt5 = repo.create_context(); + id2 = cxt5.get_index(NS_test_name3); + + assert(id1 == id2); + + try + { + id1 = cxt3.get_index(NS_test_name2); + assert(!"exception was supposed to be thrown due to no associated repos."); + } + catch (const std::exception&) + { + // expected + } + + cxt4 = repo.create_context(); + cxt5 = repo2.create_context(); + id1 = cxt4.get_index(NS_test_name1); + id2 = cxt5.get_index(NS_test_name1); + + assert(id1 != id2); + + cxt3 = repo.create_context(); + cxt5.swap(cxt3); + id2 = cxt5.get_index(NS_test_name1); + + assert(id1 == id2); +} + +void test_repo_move() +{ + ORCUS_TEST_FUNC_SCOPE; + + static_assert(!std::is_copy_constructible_v<xmlns_repository>); + static_assert(std::is_move_constructible_v<xmlns_repository>); + + xmlns_repository repo; + repo.add_predefined_values(NS_test_all); + + xmlns_repository repo_moved = std::move(repo); // move construction + xmlns_repository repo_moved2; + repo_moved2 = std::move(repo_moved); // move assignment + + xmlns_id_t ns_id = repo_moved2.get_identifier(0); + assert(ns_id != XMLNS_UNKNOWN_ID); + ns_id = repo_moved2.get_identifier(1); + assert(ns_id != XMLNS_UNKNOWN_ID); + ns_id = repo_moved2.get_identifier(2); + assert(ns_id != XMLNS_UNKNOWN_ID); + ns_id = repo_moved2.get_identifier(3); + assert(ns_id == XMLNS_UNKNOWN_ID); +} + +} // anonymous namespace + +int main() +{ + test_basic(); + test_all_namespaces(); + test_predefined_ns(); + test_xml_name_t(); + test_ns_context(); + test_repo_move(); + + return EXIT_SUCCESS; +} +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/parser/xml_writer.cpp b/src/parser/xml_writer.cpp new file mode 100644 index 0000000..a2f6c2f --- /dev/null +++ b/src/parser/xml_writer.cpp @@ -0,0 +1,326 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <orcus/xml_writer.hpp> +#include <orcus/xml_namespace.hpp> +#include <orcus/string_pool.hpp> + +#include <vector> + +/** To markup code that coverity warns might throw exceptions + which won't throw in practice, or where std::terminate is + an acceptable response if they do +*/ +#if defined(__COVERITY__) +#define suppress_fun_call_w_exception(expr) \ + do \ + { \ + try \ + { \ + expr; \ + } \ + catch (const std::exception& e) \ + { \ + std::cerr << "Fatal exception: " << e.what() << std::endl; \ + std::terminate(); \ + } \ + } while (false) +#else +#define suppress_fun_call_w_exception(expr) \ + do \ + { \ + expr; \ + } while (false) +#endif + +namespace orcus { + +namespace { + +struct _elem +{ + xml_name_t name; + std::vector<std::string_view> ns_aliases; + bool open; + + _elem(const xml_name_t& _name) : name(_name), open(true) {} +}; + +struct _attr +{ + xml_name_t name; + std::string_view value; + + _attr(const xml_name_t& _name, std::string_view _value) : + name(_name), + value(_value) + {} +}; + +void write_content_encoded(std::string_view content, std::ostream& os) +{ + auto _flush = [&os](const char*& p0, const char* p) + { + size_t n = std::distance(p0, p); + os.write(p0, n); + p0 = nullptr; + }; + + constexpr std::string_view cv_lt = "<"; + constexpr std::string_view cv_gt = ">"; + constexpr std::string_view cv_amp = "&"; + constexpr std::string_view cv_apos = "'"; + constexpr std::string_view cv_quot = """; + + const char* p = content.data(); + const char* p_end = p + content.size(); + const char* p0 = nullptr; + + for (; p != p_end; ++p) + { + if (!p0) + p0 = p; + + switch (*p) + { + case '<': + _flush(p0, p); + os.write(cv_lt.data(), cv_lt.size()); + break; + case '>': + _flush(p0, p); + os.write(cv_gt.data(), cv_gt.size()); + break; + case '&': + _flush(p0, p); + os.write(cv_amp.data(), cv_amp.size()); + break; + case '\'': + _flush(p0, p); + os.write(cv_apos.data(), cv_apos.size()); + break; + case '"': + _flush(p0, p); + os.write(cv_quot.data(), cv_quot.size()); + break; + } + } + + if (p0) + _flush(p0, p); +} + +} // anonymous namespace + +struct xml_writer::scope::impl +{ + xml_writer* parent; + xml_name_t elem; + + impl() : parent(nullptr) {} + + impl(xml_writer* _parent, const xml_name_t& _elem) : + parent(_parent), + elem(_elem) + { + parent->push_element(elem); + } + + ~impl() + { + suppress_fun_call_w_exception(parent->pop_element()); + } +}; + +xml_writer::scope::scope(xml_writer* parent, const xml_name_t& elem) : + mp_impl(std::make_unique<impl>(parent, elem)) +{ +} + +xml_writer::scope::scope(scope&& other) : + mp_impl(std::move(other.mp_impl)) +{ + // NB: we shouldn't have to create an impl instance for the other object + // since everything happens in the impl, and the envelop class doesn't + // access the impl internals. +} + +xml_writer::scope::~scope() {} + +xml_writer::scope& xml_writer::scope::operator= (scope&& other) +{ + scope tmp(std::move(other)); + mp_impl.swap(tmp.mp_impl); + return *this; +} + +struct xml_writer::impl +{ + xmlns_repository& ns_repo; + std::ostream& os; + std::vector<_elem> elem_stack; + std::vector<std::string_view> ns_decls; + std::vector<_attr> attrs; + + string_pool str_pool; + xmlns_repository repo; + xmlns_context cxt; + + impl(xmlns_repository& _ns_repo, std::ostream& _os) : + ns_repo(_ns_repo), + os(_os), + cxt(ns_repo.create_context()) + {} + + void print(const xml_name_t& name) + { + std::string_view alias = cxt.get_alias(name.ns); + if (!alias.empty()) + os << alias << ':'; + os << name.name; + } + + xml_name_t intern(const xml_name_t& name) + { + xml_name_t interned = name; + interned.name = str_pool.intern(interned.name).first; + return interned; + } + + std::string_view intern(std::string_view value) + { + return str_pool.intern(value).first; + } +}; + +xml_writer::xml_writer(xmlns_repository& ns_repo, std::ostream& os) : + mp_impl(std::make_unique<impl>(ns_repo, os)) +{ + os << "<?xml version=\"1.0\"?>"; +} + +xml_writer::xml_writer(xml_writer&& other) : + mp_impl(std::move(other.mp_impl)) +{ + other.mp_impl = std::make_unique<impl>(mp_impl->ns_repo, mp_impl->os); +} + +xml_writer& xml_writer::operator= (xml_writer&& other) +{ + xml_writer tmp(std::move(other)); + mp_impl.swap(tmp.mp_impl); + return *this; +} + +void xml_writer::pop_elements() +{ + // Pop all the elements currently on the stack. + while (!mp_impl->elem_stack.empty()) + pop_element(); +} + +xml_writer::~xml_writer() +{ + suppress_fun_call_w_exception(pop_elements()); +} + +void xml_writer::close_current_element() +{ + if (!mp_impl->elem_stack.empty() && mp_impl->elem_stack.back().open) + { + mp_impl->os << '>'; + mp_impl->elem_stack.back().open = false; + } +} + +xml_writer::scope xml_writer::push_element_scope(const xml_name_t& name) +{ + return scope(this, name); +} + +void xml_writer::push_element(const xml_name_t& _name) +{ + close_current_element(); + + auto& os = mp_impl->os; + xml_name_t name = mp_impl->intern(_name); + + os << '<'; + mp_impl->print(name); + + for (std::string_view alias : mp_impl->ns_decls) + { + os << " xmlns"; + if (!alias.empty()) + os << ':' << alias; + os << "=\""; + xmlns_id_t ns = mp_impl->cxt.get(alias); + os << ns << '"'; + } + + for (const _attr& attr : mp_impl->attrs) + { + os << ' '; + mp_impl->print(attr.name); + os << "=\""; + os << attr.value << '"'; + } + + mp_impl->attrs.clear(); + mp_impl->ns_decls.clear(); + + mp_impl->elem_stack.emplace_back(name); +} + +xmlns_id_t xml_writer::add_namespace(std::string_view alias, std::string_view value) +{ + std::string_view alias_safe = mp_impl->intern(alias); + xmlns_id_t ns = mp_impl->cxt.push(alias_safe, mp_impl->intern(value)); + mp_impl->ns_decls.push_back(alias_safe); + return ns; +} + +void xml_writer::add_attribute(const xml_name_t& name, std::string_view value) +{ + mp_impl->attrs.emplace_back(mp_impl->intern(name), mp_impl->intern(value)); +} + +void xml_writer::add_content(std::string_view content) +{ + close_current_element(); + write_content_encoded(content, mp_impl->os); +} + +xml_name_t xml_writer::pop_element() +{ + auto& os = mp_impl->os; + + const _elem& elem = mp_impl->elem_stack.back(); + auto name = elem.name; + + if (elem.open) + { + // self-closing element. + os << "/>"; + } + else + { + os << "</"; + mp_impl->print(name); + os << '>'; + } + + for (std::string_view alias : mp_impl->elem_stack.back().ns_aliases) + mp_impl->cxt.pop(alias); + + mp_impl->elem_stack.pop_back(); + return name; +} + +} // namespace orcus + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/parser/xml_writer_test.cpp b/src/parser/xml_writer_test.cpp new file mode 100644 index 0000000..a6e4bed --- /dev/null +++ b/src/parser/xml_writer_test.cpp @@ -0,0 +1,106 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "test_global.hpp" +#include "orcus/xml_writer.hpp" +#include "orcus/xml_namespace.hpp" +#include "orcus/sax_parser.hpp" + +#include <iostream> +#include <sstream> + +using namespace orcus; + +void test_encoded_content() +{ + const std::vector<std::string> test_contents = { + "1 < 2 but 3 > 2", + "ladies & gentlemen", + "'testing single quotes'", + "\"testing double quotes\"", + }; + + struct _handler : public sax_handler + { + std::ostringstream os_content; + + void characters(std::string_view val, bool /*transient*/) + { + os_content << val; + } + }; + + for (const std::string& test_content : test_contents) + { + xmlns_repository repo; + std::ostringstream os; + + { + xml_writer writer(repo, os); + auto scope_root = writer.push_element_scope({nullptr, "root"}); + writer.add_content(test_content); + } + + std::string stream = os.str(); + + _handler hdl; + + sax_parser<_handler> parser(stream, hdl); + parser.parse(); + + std::string content_read = hdl.os_content.str(); + assert(test_content == content_read); + } +} + +void test_move() +{ + xmlns_repository repo; + + { + std::ostringstream os; + xml_writer writer(repo, os); + + writer.push_element({nullptr, "foo"}); + + { + xml_writer moved(std::move(writer)); // move constructor + moved.add_content("stuff"); + } + + std::string stream = os.str(); + assert(stream == "<?xml version=\"1.0\"?><foo>stuff</foo>"); + } + + { + std::ostringstream os; + xml_writer writer(repo, os); + + writer.push_element({nullptr, "foo2"}); + + { + std::ostringstream os2; + xml_writer moved(repo, os2); + + moved = std::move(writer); // move assignment. + moved.add_content("stuff2"); + } + + std::string stream = os.str(); + assert(stream == "<?xml version=\"1.0\"?><foo2>stuff2</foo2>"); + } +} + +int main() +{ + test_encoded_content(); + test_move(); + + return EXIT_SUCCESS; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/parser/yaml_parser_base.cpp b/src/parser/yaml_parser_base.cpp new file mode 100644 index 0000000..df4db23 --- /dev/null +++ b/src/parser/yaml_parser_base.cpp @@ -0,0 +1,512 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <orcus/yaml_parser_base.hpp> +#include <orcus/cell_buffer.hpp> +#include <orcus/parser_global.hpp> + +#include <mdds/sorted_string_map.hpp> + +#include <limits> +#include <vector> +#include <deque> +#include <sstream> +#include <algorithm> + +namespace orcus { namespace yaml { + +struct scope +{ + size_t width; + detail::scope_t type; + + scope(size_t _width) : width(_width), type(detail::scope_t::unset) {} +}; + +struct parser_base::impl +{ + cell_buffer m_buffer; + std::vector<scope> m_scopes; + std::deque<std::string_view> m_line_buffer; + const char* m_document; + + size_t m_comment_length; + + bool m_in_literal_block; + bool m_parsed_to_end_of_line; + + detail::parse_token_t m_last_token; + + impl() : + m_document(nullptr), + m_comment_length(0), + m_in_literal_block(false), + m_parsed_to_end_of_line(false), + m_last_token(detail::parse_token_t::unknown) {} +}; + +const size_t parser_base::parse_indent_blank_line = std::numeric_limits<size_t>::max(); +const size_t parser_base::parse_indent_end_of_stream = std::numeric_limits<size_t>::max() - 1; +const size_t parser_base::scope_empty = std::numeric_limits<size_t>::max() - 2; + +parser_base::parser_base(std::string_view content) : + orcus::parser_base(content.data(), content.size()), mp_impl(std::make_unique<impl>()) {} + +parser_base::~parser_base() = default; + +void parser_base::push_parse_token(detail::parse_token_t t) +{ + mp_impl->m_last_token = t; +} + +detail::parse_token_t parser_base::get_last_parse_token() const +{ + return mp_impl->m_last_token; +} + +size_t parser_base::offset_last_char_of_line() const +{ + // The current parser position should be on the linefeed char after + // calling parse_to_end_of_line(). + assert(mp_impl->m_parsed_to_end_of_line); + + size_t pos = offset(); // character past the '\n'. + pos -= 1; // move back to the '\n'. + + if (mp_impl->m_comment_length) + { + assert(mp_impl->m_comment_length < pos); + pos -= mp_impl->m_comment_length; // should be on the '#' character. + } + + pos -= 1; + + // Ignore any trailing whitespaces. + const char* p = mp_begin + pos; + for (; mp_begin < p && *p == ' '; --p, --pos) + ; + + return pos; +} + +size_t parser_base::parse_indent() +{ + for (size_t indent = 0; has_char(); next(), ++indent) + { + char c = cur_char(); + switch (c) + { + case '#': + skip_comment(); + return parse_indent_blank_line; + case '\n': + next(); + return parse_indent_blank_line; + case ' ': + continue; + default: + return indent; + } + } + + return parse_indent_end_of_stream; +} + +std::string_view parser_base::parse_to_end_of_line() +{ + const char* p = mp_char; + size_t len = 0; + for (; has_char(); next(), ++len) + { + switch (cur_char()) + { + case '#': + skip_comment(); + break; + case '\'': + { + const char* p_open_quote = mp_char; + + // character immediately after the closing quote. + const char* p_end = + parse_to_closing_single_quote(mp_char, remaining_size()); + + if (!p_end) + throw parse_error("parse_to_end_of_line: closing single quote was expected but not found.", offset()); + + size_t diff = p_end - p_open_quote - 1; + + // Move the cursor to the closing quote. + next(diff); + len += diff; + assert(cur_char() == '\''); + continue; + } + break; + case '"': + { + const char* p_open_quote = mp_char; + + // character immediately after the closing quote. + const char* p_end = + parse_to_closing_double_quote(mp_char, remaining_size()); + + if (!p_end) + throw parse_error("parse_to_end_of_line: closing double quote was expected but not found.", offset()); + + size_t diff = p_end - p_open_quote - 1; + + // Move the cursor to the closing quote. + next(diff); + len += diff; + assert(cur_char() == '"'); + continue; + } + break; + case '\n': + next(); + break; + default: + continue; + } + break; + } + + std::string_view ret(p, len); + mp_impl->m_parsed_to_end_of_line = true; + return ret; +} + +void parser_base::skip_comment() +{ + assert(cur_char() == '#'); + + size_t n = 1; + + for (; has_char(); next(), ++n) + { + if (cur_char() == '\n') + { + next(); + break; + } + } + + mp_impl->m_comment_length = n; +} + +void parser_base::reset_on_new_line() +{ + mp_impl->m_comment_length = 0; + mp_impl->m_parsed_to_end_of_line = false; +} + +size_t parser_base::get_scope() const +{ + return (mp_impl->m_scopes.empty()) ? scope_empty : mp_impl->m_scopes.back().width; +} + +void parser_base::push_scope(size_t scope_width) +{ + mp_impl->m_scopes.emplace_back(scope_width); +} + +void parser_base::clear_scopes() +{ + mp_impl->m_scopes.clear(); +} + +detail::scope_t parser_base::get_scope_type() const +{ + assert(!mp_impl->m_scopes.empty()); + return mp_impl->m_scopes.back().type; +} + +void parser_base::set_scope_type(detail::scope_t type) +{ + assert(!mp_impl->m_scopes.empty()); + mp_impl->m_scopes.back().type = type; +} + +size_t parser_base::pop_scope() +{ + assert(!mp_impl->m_scopes.empty()); + mp_impl->m_scopes.pop_back(); + return get_scope(); +} + +void parser_base::push_line_back(const char* p, size_t n) +{ + mp_impl->m_line_buffer.emplace_back(p, n); +} + +std::string_view parser_base::pop_line_front() +{ + assert(!mp_impl->m_line_buffer.empty()); + + std::string_view ret = mp_impl->m_line_buffer.front(); + mp_impl->m_line_buffer.pop_front(); + return ret; +} + +bool parser_base::has_line_buffer() const +{ + return !mp_impl->m_line_buffer.empty(); +} + +size_t parser_base::get_line_buffer_count() const +{ + return mp_impl->m_line_buffer.size(); +} + +std::string_view parser_base::merge_line_buffer() +{ + assert(!mp_impl->m_line_buffer.empty()); + + char sep = mp_impl->m_in_literal_block ? '\n' : ' '; + + cell_buffer& buf = mp_impl->m_buffer; + buf.reset(); + + auto it = mp_impl->m_line_buffer.begin(); + buf.append(it->data(), it->size()); + ++it; + + std::for_each(it, mp_impl->m_line_buffer.end(), + [&](std::string_view line) + { + buf.append(&sep, 1); + buf.append(line.data(), line.size()); + } + ); + + mp_impl->m_line_buffer.clear(); + mp_impl->m_in_literal_block = false; + + return buf.str(); +} + +const char* parser_base::get_doc_hash() const +{ + return mp_impl->m_document; +} + +void parser_base::set_doc_hash(const char* hash) +{ + mp_impl->m_document = hash; +} + +namespace { + +namespace keyword { + +using map_type = mdds::sorted_string_map<detail::keyword_t, mdds::string_view_map_entry>; + +constexpr map_type::entry entries[] = { + { "FALSE", detail::keyword_t::boolean_false }, + { "False", detail::keyword_t::boolean_false }, + { "N", detail::keyword_t::boolean_false }, + { "NO", detail::keyword_t::boolean_false }, + { "NULL", detail::keyword_t::null }, + { "No", detail::keyword_t::boolean_false }, + { "Null", detail::keyword_t::null }, + { "OFF", detail::keyword_t::boolean_false }, + { "ON", detail::keyword_t::boolean_true }, + { "Off", detail::keyword_t::boolean_false }, + { "On", detail::keyword_t::boolean_true }, + { "TRUE", detail::keyword_t::boolean_true }, + { "True", detail::keyword_t::boolean_true }, + { "Y", detail::keyword_t::boolean_true }, + { "YES", detail::keyword_t::boolean_true }, + { "Yes", detail::keyword_t::boolean_true }, + { "false", detail::keyword_t::boolean_false }, + { "n", detail::keyword_t::boolean_false }, + { "no", detail::keyword_t::boolean_false }, + { "null", detail::keyword_t::null }, + { "off", detail::keyword_t::boolean_false }, + { "on", detail::keyword_t::boolean_true }, + { "true", detail::keyword_t::boolean_true }, + { "y", detail::keyword_t::boolean_true }, + { "yes", detail::keyword_t::boolean_true }, + { "~", detail::keyword_t::null }, +}; + +const map_type& get() +{ + static const map_type map(entries, std::size(entries), detail::keyword_t::unknown); + return map; +} + +} // namespace keyword + +void throw_quoted_string_parse_error( + const char* func_name, const parse_quoted_string_state& ret, std::ptrdiff_t offset) +{ + std::ostringstream os; + os << func_name << ": failed to parse "; + if (ret.length == parse_quoted_string_state::error_illegal_escape_char) + os << "due to the presence of illegal escape character."; + else if (ret.length == parse_quoted_string_state::error_no_closing_quote) + os << "because the closing quote was not found."; + else + os << "due to unknown reason."; + + throw parse_error(os.str(), offset); +} + +} + +detail::keyword_t parser_base::parse_keyword(const char* p, size_t len) +{ + return keyword::get().find({p, len}); +} + +parser_base::key_value parser_base::parse_key_value(const char* p, size_t len) +{ + size_t scope = get_scope(); + assert(scope != scope_empty); + + assert(*p != ' '); + assert(len); + + const char* p_end = p + len; + + key_value kv; + + char last = 0; + bool key_found = false; + + const char* p_head = p; + + for (; p != p_end; ++p) + { + if (*p == ' ') + { + if (!key_found) + { + if (last == ':') + { + // Key found. + std::size_t n = p - p_head - 1; + kv.key = trim({p_head, n}); + key_found = true; + p_head = nullptr; + } + } + } + else + { + if (!p_head) + p_head = p; + } + + last = *p; + } + + assert(p_head); + + if (key_found) + { + // Key has already been found and the value comes after the ':'. + kv.value = std::string_view(p_head, p-p_head); + } + else if (last == ':') + { + // Line only contains a key and ends with ':'. + std::size_t n = p - p_head - 1; + kv.key = trim({p_head, n}); + } + else + { + // Key has not been found. + detail::scope_t st = get_scope_type(); + if (st == detail::scope_t::map) + throw parse_error("key was expected, but not found.", offset_last_char_of_line()); + } + + return kv; +} + +std::string_view parser_base::parse_single_quoted_string_value(const char*& p, size_t max_length) +{ + parse_quoted_string_state ret = + parse_single_quoted_string(p, max_length, mp_impl->m_buffer); + + if (!ret.str) + throw_quoted_string_parse_error("parse_single_quoted_string_value", ret, offset()); + + return std::string_view(ret.str, ret.length); +} + +std::string_view parser_base::parse_double_quoted_string_value(const char*& p, size_t max_length) +{ + parse_quoted_string_state ret = + parse_double_quoted_string(p, max_length, mp_impl->m_buffer); + + if (!ret.str) + throw_quoted_string_parse_error("parse_double_quoted_string_value", ret, offset()); + + return std::string_view(ret.str, ret.length); +} + +void parser_base::skip_blanks(const char*& p, size_t len) +{ + const char* p_end = p + len; + for (; p != p_end && *p == ' '; ++p) + ; +} + +void parser_base::start_literal_block() +{ + mp_impl->m_in_literal_block = true; +} + +bool parser_base::in_literal_block() const +{ + return mp_impl->m_in_literal_block; +} + +void parser_base::handle_line_in_literal(size_t indent) +{ + size_t cur_scope = get_scope(); + + if (!has_line_buffer()) + { + // Start a new multi-line string scope. + + if (indent == cur_scope) + throw parse_error("parse: first line of a literal block must be indented.", offset()); + + push_scope(indent); + set_scope_type(yaml::detail::scope_t::multi_line_string); + } + else + { + // The current scope is already a multi-line scope. + assert(get_scope_type() == yaml::detail::scope_t::multi_line_string); + size_t leading_indent = indent - cur_scope; + prev(leading_indent); + } + + std::string_view line = parse_to_end_of_line(); + push_line_back(line.data(), line.size()); +} + +void parser_base::handle_line_in_multi_line_string() +{ + if (get_scope_type() != yaml::detail::scope_t::multi_line_string) + set_scope_type(yaml::detail::scope_t::multi_line_string); + + std::string_view line = parse_to_end_of_line(); + line = trim(line); + assert(!line.empty()); + push_line_back(line.data(), line.size()); +} + +}} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/parser/yaml_parser_test.cpp b/src/parser/yaml_parser_test.cpp new file mode 100644 index 0000000..88103db --- /dev/null +++ b/src/parser/yaml_parser_test.cpp @@ -0,0 +1,32 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <orcus/yaml_parser.hpp> + +#include <string> + +void test_handler() +{ + constexpr std::string_view test_code = + "section-one:\n" + " - item 1\n" + " - item 2\n" + "\n"; + + orcus::yaml_handler hdl; + orcus::yaml_parser<orcus::yaml_handler> parser(test_code, hdl); + parser.parse(); +} + +int main() +{ + test_handler(); + + return EXIT_SUCCESS; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/parser/zip_archive.cpp b/src/parser/zip_archive.cpp new file mode 100644 index 0000000..50d5da5 --- /dev/null +++ b/src/parser/zip_archive.cpp @@ -0,0 +1,601 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <orcus/zip_archive.hpp> +#include <orcus/zip_archive_stream.hpp> +#include <orcus/string_pool.hpp> + +#include <cstdio> +#include <cstdlib> +#include <cstring> +#include <iostream> +#include <unordered_map> +#include <sstream> +#include <string_view> +#include <iomanip> + +#include <zlib.h> +#include <zconf.h> + +#define ORCUS_DEBUG_ZIP_ARCHIVE 0 + +namespace orcus { + +namespace { + +struct zip_file_param +{ + enum compress_method_type { stored = 0, deflated = 8 }; + + std::string_view filename; + compress_method_type compress_method; + std::size_t offset_file_header; + std::size_t size_compressed; + std::size_t size_uncompressed; + + uint16_t version_made_by; + uint16_t minimum_version_needed; + uint16_t flags; + uint16_t last_modified_time; + uint16_t last_modified_date; + + uint16_t filename_length; + uint16_t extra_field_length; + uint16_t comment_length; + + uint16_t disk_id_where_file_starts; + uint16_t file_attributes_internal; + uint32_t file_attributes_external; + + uint32_t crc32; +}; + +class zip_inflater +{ + z_stream m_zlib_cxt; + + zip_inflater(); // disabled +public: + zip_inflater(std::vector<unsigned char>& raw_buf, std::vector<unsigned char>& dest_buf, const zip_file_param& param) + { + memset(&m_zlib_cxt, 0, sizeof(m_zlib_cxt)); + m_zlib_cxt.next_in = static_cast<Bytef*>(&raw_buf[0]); + m_zlib_cxt.avail_in = param.size_compressed; + + m_zlib_cxt.next_out = static_cast<Bytef*>(&dest_buf[0]); + m_zlib_cxt.avail_out = param.size_uncompressed; + } + + ~zip_inflater() + { + inflateEnd(&m_zlib_cxt); + } + + bool init() + { + int err = inflateInit2(&m_zlib_cxt, -MAX_WBITS); + return err == Z_OK; + } + + bool inflate() + { + int err = ::inflate(&m_zlib_cxt, Z_SYNC_FLUSH); + if (err >= 0 && m_zlib_cxt.msg) + return false; + + return true; + } +}; + +/** + * Stream doesn't know its size; only its starting offset position within + * the file stream. + */ +class zip_stream_parser +{ + zip_archive_stream* m_stream; + size_t m_pos; + size_t m_pos_internal; + + void read_string_to_buffer(size_t n, std::vector<unsigned char>& buf) + { + if (!n) + throw zip_error("attempt to read string of zero size."); + + m_stream->seek(m_pos+m_pos_internal); + m_stream->read(&buf[0], n); + m_pos_internal += n; + } + +public: + zip_stream_parser() : m_stream(nullptr), m_pos(0), m_pos_internal(0) {} + zip_stream_parser(zip_archive_stream* stream, size_t pos) : m_stream(stream), m_pos(pos), m_pos_internal(0) {} + + std::string read_string(size_t n) + { + std::vector<unsigned char> buf(n+1, '\0'); + read_string_to_buffer(n, buf); + return std::string(reinterpret_cast<const char*>(&buf[0])); + } + + std::vector<uint8_t> read_bytes(std::size_t n) + { + if (!n) + throw zip_error("attempt to read string of zero size."); + + std::vector<uint8_t> buf; + m_stream->seek(m_pos+m_pos_internal); + m_stream->read(buf.data(), n); + m_pos_internal += n; + return buf; + } + + std::string_view read_string(size_t n, string_pool& pool) + { + std::vector<unsigned char> buf(n+1, '\0'); + read_string_to_buffer(n, buf); + return pool.intern({reinterpret_cast<const char*>(buf.data()), n}).first; + } + + void skip_bytes(size_t n) + { + m_pos_internal += n; + } + + uint32_t read_4bytes() + { + m_stream->seek(m_pos+m_pos_internal); + unsigned char buf[4]; + m_stream->read(&buf[0], 4); + m_pos_internal += 4; + + uint32_t ret = buf[0]; + ret |= (buf[1] << 8); + ret |= (buf[2] << 16); + ret |= (buf[3] << 24); + + return ret; + } + + uint16_t read_2bytes() + { + m_stream->seek(m_pos+m_pos_internal); + unsigned char buf[2]; + m_stream->read(&buf[0], 2); + m_pos_internal += 2; + + uint16_t ret = buf[0]; + ret |= (buf[1] << 8); + + return ret; + } + + size_t tell() const + { + return m_pos + m_pos_internal; + } +}; + +/** + * Content of the end part of the central directory. + */ +struct central_dir_end +{ + uint32_t magic_number; + uint16_t this_disk_id; + uint16_t central_dir_disk_id; + uint16_t num_central_dir_records_local; + uint16_t num_celtral_dir_records_total; + uint32_t size_central_dir; + size_t central_dir_pos; + uint16_t comment_length; +}; + +} // anonymous namespace + + +zip_file_entry_header::zip_file_entry_header() = default; +zip_file_entry_header::zip_file_entry_header(const zip_file_entry_header& other) = default; +zip_file_entry_header::zip_file_entry_header(zip_file_entry_header&& other) = default; +zip_file_entry_header::~zip_file_entry_header() = default; + +zip_file_entry_header& zip_file_entry_header::operator=(const zip_file_entry_header& other) = default; +zip_file_entry_header& zip_file_entry_header::operator=(zip_file_entry_header&& other) = default; + +std::ostream& operator<<(std::ostream& os, const zip_file_entry_header& header) +{ + os << "header signature: 0x" << std::hex << std::setfill('0') << std::setw(8) << header.header_signature << "\n" + << "version needed to extract: " << header.required_version << "\n" + << "general purpose bit flag: 0x" << std::hex << std::setfill('0') << std::setw(4) << header.flag << "\n" + << "compression method: " << header.compression_method << "\n" + << "last modified time: " << header.last_modified_time << "\n" + << "last modified date: " << header.last_modified_date << "\n" + << "crc32: 0x" << std::hex << std::setfill('0') << std::setw(8) << header.crc32 << "\n" + << "compressed size: " << header.compressed_size << "\n" + << "uncompressed size: " << header.uncompressed_size << "\n" + << "filename: " << header.filename << "\n" + << "extra field length: " << header.extra_field.size(); + + return os; +} + +class zip_archive::impl +{ + typedef std::vector<zip_file_param> file_params_type; + typedef std::unordered_map<std::string_view, std::size_t> filename_map_type; + + string_pool m_pool; + zip_archive_stream* m_stream; + off_t m_stream_size; + size_t m_central_dir_pos; + + zip_stream_parser m_central_dir_end; + + file_params_type m_file_params; + filename_map_type m_filenames; + +public: + impl(zip_archive_stream* stream); + + void load(); + zip_file_entry_header get_file_entry_header(std::size_t index) const; + zip_file_entry_header get_file_entry_header(std::string_view name) const; + std::string_view get_file_entry_name(size_t pos) const; + + size_t get_file_entry_count() const + { + return m_file_params.size(); + } + + std::vector<unsigned char> read_file_entry(std::string_view entry_name) const; + +private: + + /** + * Find the central directory of a zip file, located toward the end before + * the global comment, and starts with the byte sequence of 0x504b0506. + */ + size_t seek_central_dir(); + + void read_central_dir_end(); + void read_file_entries(); +}; + +zip_archive::impl::impl(zip_archive_stream* stream) : + m_stream(stream), m_stream_size(0), m_central_dir_pos(0) +{ + if (!m_stream) + throw zip_error("null stream is not allowed."); + + m_stream_size = m_stream->size(); +} + +void zip_archive::impl::load() +{ + size_t central_dir_end_pos = seek_central_dir(); + if (!central_dir_end_pos) + throw zip_error("failed to seek the end position of the central directory"); + + m_central_dir_end = zip_stream_parser(m_stream, central_dir_end_pos); + + // Read the end part of the central directory. + read_central_dir_end(); + + // Read file entries that are in the front part of the central directory. + read_file_entries(); +} + +zip_file_entry_header zip_archive::impl::get_file_entry_header(std::size_t index) const +{ + if (index >= m_file_params.size()) + throw zip_error("invalid file entry index."); + + const zip_file_param& param = m_file_params[index]; + zip_stream_parser file_header(m_stream, param.offset_file_header); + + zip_file_entry_header header; + + header.header_signature = file_header.read_4bytes(); + header.required_version = file_header.read_2bytes(); + header.flag = file_header.read_2bytes(); + header.compression_method = file_header.read_2bytes(); + header.last_modified_time = file_header.read_2bytes(); + header.last_modified_date = file_header.read_2bytes(); + header.crc32 = file_header.read_4bytes(); + header.compressed_size = file_header.read_4bytes(); + header.uncompressed_size = file_header.read_4bytes(); + uint16_t filename_len = file_header.read_2bytes(); + uint16_t extra_field_len = file_header.read_2bytes(); + + if (filename_len) + header.filename = file_header.read_string(filename_len); + + if (extra_field_len) + header.extra_field = file_header.read_bytes(extra_field_len); + + return header; +} + +zip_file_entry_header zip_archive::impl::get_file_entry_header(std::string_view name) const +{ + auto it = m_filenames.find(name); + if (it == m_filenames.end()) + { + std::ostringstream os; + os << "file entry named '" << name << "' not found"; + throw zip_error(os.str()); + } + + return get_file_entry_header(it->second); +} + +void zip_archive::impl::read_file_entries() +{ + m_file_params.clear(); + + zip_stream_parser central_dir(m_stream, m_central_dir_pos); + uint32_t magic_num = central_dir.read_4bytes(); + + while (magic_num == 0x02014b50) + { + zip_file_param param; + + param.version_made_by = central_dir.read_2bytes(); + param.minimum_version_needed = central_dir.read_2bytes(); + param.flags = central_dir.read_2bytes(); + param.compress_method = + static_cast<zip_file_param::compress_method_type>(central_dir.read_2bytes()); + + param.last_modified_time = central_dir.read_2bytes(); + param.last_modified_date = central_dir.read_2bytes(); + param.crc32 = central_dir.read_4bytes(); + param.size_compressed = central_dir.read_4bytes(); + param.size_uncompressed = central_dir.read_4bytes(); + param.filename_length = central_dir.read_2bytes(); + param.extra_field_length = central_dir.read_2bytes(); + param.comment_length = central_dir.read_2bytes(); + param.disk_id_where_file_starts = central_dir.read_2bytes(); + param.file_attributes_internal = central_dir.read_2bytes(); + param.file_attributes_external = central_dir.read_4bytes(); + param.offset_file_header = central_dir.read_4bytes(); + + if (param.filename_length) + param.filename = central_dir.read_string(param.filename_length, m_pool); + + if (param.extra_field_length) + // Ignore extra field for now. + central_dir.skip_bytes(param.extra_field_length); + + if (param.comment_length) + // Ignore file comment for now. + central_dir.skip_bytes(param.comment_length); + + magic_num = central_dir.read_4bytes(); // magic number for the next entry. + + m_file_params.push_back(param); + m_filenames.insert(filename_map_type::value_type(param.filename, m_file_params.size()-1)); + +#if ORCUS_DEBUG_ZIP_ARCHIVE + std::cout << "-- file entries" << std::endl; + printf( " magic number: 0x%8.8x\n", magic_num); + std::cout << " version made by: " << param.version_made_by << std::endl; + std::cout << " minimum version needed to extract: " << param.minimum_version_needed << std::endl; + printf( " general purpose bit flag: 0x%4.4x\n", param.flags); + std::cout << " compression method: " << param.compress_method << " (0=stored, 8=deflated)" << std::endl; + std::cout << " file last modified time: " << param.last_modified_time << std::endl; + std::cout << " file last modified date: " << param.last_modified_date << std::endl; + printf( " crc32: 0x%8.8x\n", param.crc32); + std::cout << " compressed size: " << param.size_compressed << std::endl; + std::cout << " uncompressed size: " << param.size_uncompressed << std::endl; + std::cout << " file name length: " << param.filename_length << std::endl; + std::cout << " extra field length: " << param.extra_field_length << std::endl; + std::cout << " file comment length: " << param.comment_length << std::endl; + std::cout << " disk number where file starts: " << param.disk_id_where_file_starts << std::endl; + printf( " internal file attributes: 0x%4.4x\n", param.file_attributes_internal); + printf( " external file attributes: 0x%8.8x\n", param.file_attributes_external); + std::cout << " relative offset of local file header: " << param.offset_file_header << std::endl; + + if (param.filename_length) + std::cout << " filename: '" << param.filename << "'" << std::endl; + + std::cout << "--" << std::endl; +#endif + } +} + +std::string_view zip_archive::impl::get_file_entry_name(std::size_t pos) const +{ + if (pos >= m_file_params.size()) + return std::string_view{}; + + return m_file_params[pos].filename; +} + +std::vector<unsigned char> zip_archive::impl::read_file_entry(std::string_view entry_name) const +{ + filename_map_type::const_iterator it = m_filenames.find(entry_name); + if (it == m_filenames.end()) + { + std::ostringstream os; + os << "entry named '" << entry_name << "' not found"; + throw zip_error(os.str()); + } + + + size_t index = it->second; + if (index >= m_file_params.size()) + throw zip_error("entry index is out-of-bound"); + + const zip_file_param& param = m_file_params[index]; + + // Skip the file header section. + zip_stream_parser file_header(m_stream, param.offset_file_header); + file_header.skip_bytes(4); + file_header.skip_bytes(2); + file_header.skip_bytes(2); + file_header.skip_bytes(2); + file_header.skip_bytes(2); + file_header.skip_bytes(2); + file_header.skip_bytes(4); + file_header.skip_bytes(4); + file_header.skip_bytes(4); + uint16_t filename_len = file_header.read_2bytes(); + uint16_t extra_field_len = file_header.read_2bytes(); + file_header.skip_bytes(filename_len); + file_header.skip_bytes(extra_field_len); + + // Data section is immediately followed by the header section. + m_stream->seek(file_header.tell()); + + std::vector<unsigned char> raw_buf(param.size_compressed+1, 0); + m_stream->read(raw_buf.data(), param.size_compressed); + + switch (param.compress_method) + { + case zip_file_param::stored: + { + // Not compressed at all. + return raw_buf; + } + case zip_file_param::deflated: + { + // deflate compression + std::vector<unsigned char> zip_buf(param.size_uncompressed+1, 0); // null-terminated + zip_inflater inflater(raw_buf, zip_buf, param); + if (!inflater.init()) + throw zip_error("error during initialization of inflater"); + + if (!inflater.inflate()) + throw zip_error("error during inflate."); + + return zip_buf; + } + } + + throw std::logic_error("compress method can be either 'stored' or 'deflated', but neither has happened"); +} + +size_t zip_archive::impl::seek_central_dir() +{ + // Search for the position of 0x06054b50 (read in little endian order - so + // it's 0x50, 0x4b, 0x05, 0x06 in this order) somewhere near the end of + // the stream. + + unsigned char magic[] = { 0x06, 0x05, 0x4b, 0x50 }; + size_t n_magic = 4; + + off_t max_comment_size = 0xffff; + + size_t buf_size = 22 + max_comment_size; // central directory size is 22 + n (n maxing at 0xffff). + std::vector<unsigned char> buf(buf_size); + + // Read stream backward and try to find the magic number. + + size_t read_end_pos = m_stream_size; + while (read_end_pos) + { + if (read_end_pos < buf.size()) + // Last segment to read. + buf.resize(read_end_pos); + + size_t read_pos = read_end_pos - buf.size(); + m_stream->seek(read_pos); + m_stream->read(&buf[0], buf.size()); + + // Search this byte segment for the magic number. + std::vector<unsigned char>::reverse_iterator i = buf.rbegin(), ie = buf.rend(); + size_t magic_pos = 0; + for (; i != ie; ++i) + { + // 06 05 4b 50 + if (*i == magic[magic_pos]) + { + ++magic_pos; + if (magic_pos == n_magic) + { + // magic number is found. + size_t dist = distance(buf.rbegin(), i) + 1; + size_t pos = read_end_pos - dist; + return pos; + } + } + else + magic_pos = 0; + } + + read_end_pos -= buf.size(); + } + + return 0; +} + +void zip_archive::impl::read_central_dir_end() +{ + central_dir_end content; + content.magic_number = m_central_dir_end.read_4bytes(); + content.this_disk_id = m_central_dir_end.read_2bytes(); + content.central_dir_disk_id = m_central_dir_end.read_2bytes(); + content.num_central_dir_records_local = m_central_dir_end.read_2bytes(); + content.num_celtral_dir_records_total = m_central_dir_end.read_2bytes(); + content.size_central_dir = m_central_dir_end.read_4bytes(); + content.central_dir_pos = m_central_dir_end.read_4bytes(); + m_central_dir_pos = content.central_dir_pos; + + content.comment_length = m_central_dir_end.read_2bytes(); + +#if ORCUS_DEBUG_ZIP_ARCHIVE + std::cout << "-- central directory content" << std::endl; + printf(" magic number: 0x%8.8x\n", content.magic_number); + std::cout << " number of this disk: " << content.this_disk_id << std::endl; + std::cout << " disk where central directory starts: " << content.central_dir_disk_id << std::endl; + std::cout << " number of central directory records on this disk: " << content.num_central_dir_records_local << std::endl; + std::cout << " total number of central directory records: " << content.num_celtral_dir_records_total << std::endl; + std::cout << " size of central directory: " << content.size_central_dir << std::endl; + std::cout << " offset of start of central directory, relative to start of archive: " << content.central_dir_pos << std::endl; + std::cout << " comment length: " << content.comment_length << std::endl; + std::cout << "--" << std::endl; +#endif +} + +zip_archive::zip_archive(zip_archive_stream* stream) : mp_impl(std::make_unique<impl>(stream)) +{ +} + +zip_archive::~zip_archive() = default; + +void zip_archive::load() +{ + mp_impl->load(); +} + +zip_file_entry_header zip_archive::get_file_entry_header(std::size_t index) const +{ + return mp_impl->get_file_entry_header(index); +} + +zip_file_entry_header zip_archive::get_file_entry_header(std::string_view name) const +{ + return mp_impl->get_file_entry_header(name); +} + +std::string_view zip_archive::get_file_entry_name(std::size_t index) const +{ + return mp_impl->get_file_entry_name(index); +} + +size_t zip_archive::get_file_entry_count() const +{ + return mp_impl->get_file_entry_count(); +} + +std::vector<unsigned char> zip_archive::read_file_entry(std::string_view entry_name) const +{ + return mp_impl->read_file_entry(entry_name); +} + +} +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/parser/zip_archive_stream.cpp b/src/parser/zip_archive_stream.cpp new file mode 100644 index 0000000..776ac14 --- /dev/null +++ b/src/parser/zip_archive_stream.cpp @@ -0,0 +1,113 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "orcus/zip_archive_stream.hpp" +#include "orcus/zip_archive.hpp" + +#include <sstream> +#include <cstring> + +#ifdef _MSC_VER +#define fseeko _fseeki64 +#define ftello _ftelli64 +#endif + +using namespace std; + +namespace orcus { + +zip_archive_stream::~zip_archive_stream() {} + +zip_archive_stream_fd::zip_archive_stream_fd(const char* filepath) : + m_stream(fopen(filepath, "rb")) +{ + if (!m_stream) + { + // Fail early at instantiation time. + ostringstream os; + os << "failed to open " << filepath << " for reading"; + throw zip_error(os.str()); + } +} + +zip_archive_stream_fd::~zip_archive_stream_fd() +{ + if (m_stream) + fclose(m_stream); +} + +size_t zip_archive_stream_fd::size() const +{ + if (fseeko(m_stream, 0, SEEK_END)) + throw zip_error("failed to set seek position to the end of stream."); + + return ftello(m_stream); +} + +size_t zip_archive_stream_fd::tell() const +{ + return ftello(m_stream); +} + +void zip_archive_stream_fd::read(unsigned char* buffer, size_t length) const +{ + size_t size_read = fread(buffer, 1, length, m_stream); + if (size_read != length) + throw zip_error("actual size read doesn't match what was expected."); +} + +void zip_archive_stream_fd::seek(size_t pos) +{ + if (fseeko(m_stream, pos, SEEK_SET)) + { + ostringstream os; + os << "failed to set seek position to " << pos << "."; + throw zip_error(os.str()); + } +} + + +zip_archive_stream_blob::zip_archive_stream_blob(const uint8_t* blob, std::size_t size) : + m_blob(blob), m_cur(blob), m_size(size) {} + +zip_archive_stream_blob::~zip_archive_stream_blob() {} + +size_t zip_archive_stream_blob::size() const +{ + return m_size; +} + +size_t zip_archive_stream_blob::tell() const +{ + return std::distance(m_blob, m_cur); +} + +void zip_archive_stream_blob::seek(size_t pos) +{ + if (pos > m_size) + { + ostringstream os; + os << "failed to seek position to " << pos << "."; + throw zip_error(os.str()); + } + m_cur = m_blob + pos; +} + +void zip_archive_stream_blob::read(unsigned char* buffer, size_t length) const +{ + if (!length) + return; + // First, make sure we have enough blob to satisfy the requested stream length. + const size_t length_available = m_size - tell(); + if (length_available < length) + throw zip_error("There is not enough stream left to fill requested length."); + + memcpy(buffer, m_cur, length); +} + +} +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/parser/zip_archive_test.cpp b/src/parser/zip_archive_test.cpp new file mode 100644 index 0000000..bbaa597 --- /dev/null +++ b/src/parser/zip_archive_test.cpp @@ -0,0 +1,98 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "test_global.hpp" +#include <algorithm> +#include <cstdlib> +#include <vector> + +#include <orcus/zip_archive_stream.hpp> +#include <orcus/zip_archive.hpp> + +#include "filesystem_env.hpp" + +#define ASSERT_THROW(expr) \ +try \ +{ \ + expr; \ + assert(0); \ +} \ +catch (...) \ +{ \ +} + +using namespace orcus; + +void test_zip_archive_stream(zip_archive_stream* const strm, const unsigned char* const data, std::size_t const length) +{ + assert(strm->size() == length); + assert(strm->tell() == 0); + + std::vector<unsigned char> buffer(length, 0); + unsigned char* buf = buffer.data(); + + strm->read(buf, 2); + assert(std::equal(data, data + 2, buf)); + assert(strm->tell() == 0); + strm->read(buf, length); + assert(std::equal(data, data + length, buf)); + ASSERT_THROW(strm->read(buf, length + 1)); + strm->read(buf, 0); + + strm->seek(2); + assert(strm->tell() == 2); + strm->read(buf, 2); + assert(std::equal(data + 2, data + 4, buf)); + strm->seek(length); + assert(strm->tell() == length); + ASSERT_THROW(strm->seek(length + 1)); + assert(strm->tell() == length); +} + +void test_zip_archive_stream_blob() +{ + ORCUS_TEST_FUNC_SCOPE; + + const unsigned char data[] = "My hovercraft is full of eels."; + zip_archive_stream_blob strm(data, sizeof(data)); + test_zip_archive_stream(&strm, data, sizeof(data)); +} + +void test_zip_archive_file_entry_header() +{ + ORCUS_TEST_FUNC_SCOPE; + + fs::path filepath{SRCDIR"/test/ods/raw-values-1/input.ods"}; + assert(fs::is_regular_file(filepath)); + + zip_archive_stream_fd strm(filepath.string().c_str()); + + zip_archive archive(&strm); + archive.load(); + std::size_t n_entries = archive.get_file_entry_count(); + for (std::size_t i = 0; i < n_entries; ++i) + { + std::string_view name = archive.get_file_entry_name(i); + std::cout << "* entry name: " << name << std::endl; + zip_file_entry_header header = archive.get_file_entry_header(i); + assert(header.filename == name); + assert(header.header_signature == 0x04034b50); + + // 0 = none; 8 = deflate + assert(header.compression_method == 0 || header.compression_method == 8); + } +} + +int main() +{ + test_zip_archive_stream_blob(); + test_zip_archive_file_entry_header(); + + return EXIT_SUCCESS; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |