Merge lp:~adrianboguszewski/inkscape/sax-parser into lp:~inkscape.dev/inkscape/trunk

Proposed by Adrian Boguszewski
Status: Needs review
Proposed branch: lp:~adrianboguszewski/inkscape/sax-parser
Merge into: lp:~inkscape.dev/inkscape/trunk
Diff against target: 6517 lines (+4413/-1153)
67 files modified
CMakeLists.txt (+1/-0)
CMakeScripts/ConfigCompileFlags.cmake (+1/-1)
src/CMakeLists.txt (+2/-0)
src/document.cpp (+3/-2)
src/extension/implementation/xslt.cpp (+8/-5)
src/extension/internal/filter/filter-file.cpp (+3/-2)
src/extension/internal/filter/filter.cpp (+2/-1)
src/extension/internal/svg.cpp (+4/-4)
src/extension/loader.h (+2/-1)
src/extension/prefdialog.cpp (+2/-1)
src/extension/system.cpp (+3/-2)
src/inkscape.cpp (+11/-15)
src/libxml++/CMakeLists.txt (+34/-0)
src/libxml++/README (+8/-0)
src/libxml++/document.cc (+126/-0)
src/libxml++/document.h (+139/-0)
src/libxml++/dtd.cc (+147/-0)
src/libxml++/dtd.h (+136/-0)
src/libxml++/exceptions/exception.cc (+125/-0)
src/libxml++/exceptions/exception.h (+99/-0)
src/libxml++/exceptions/internal_error.cc (+23/-0)
src/libxml++/exceptions/internal_error.h (+39/-0)
src/libxml++/exceptions/parse_error.cc (+23/-0)
src/libxml++/exceptions/parse_error.h (+42/-0)
src/libxml++/exceptions/validity_error.cc (+23/-0)
src/libxml++/exceptions/validity_error.h (+42/-0)
src/libxml++/exceptions/wrapped_exception.cc (+46/-0)
src/libxml++/exceptions/wrapped_exception.h (+56/-0)
src/libxml++/io/istreamparserinputbuffer.cc (+44/-0)
src/libxml++/io/istreamparserinputbuffer.h (+36/-0)
src/libxml++/io/parserinputbuffer.cc (+84/-0)
src/libxml++/io/parserinputbuffer.h (+75/-0)
src/libxml++/keepblanks.cc (+29/-0)
src/libxml++/keepblanks.h (+35/-0)
src/libxml++/libxml++config.h (+26/-0)
src/libxml++/noncopyable.cc (+21/-0)
src/libxml++/noncopyable.h (+31/-0)
src/libxml++/parsers/parser.cc (+365/-0)
src/libxml++/parsers/parser.h (+220/-0)
src/libxml++/parsers/saxparser.cc (+711/-0)
src/libxml++/parsers/saxparser.h (+261/-0)
src/preferences.cpp (+5/-3)
src/shortcuts.cpp (+16/-16)
src/ui/dialog/template-load-tab.cpp (+2/-1)
src/ui/interface.cpp (+2/-1)
src/xml/CMakeLists.txt (+3/-1)
src/xml/comment-node.h (+9/-0)
src/xml/node.h (+27/-4)
src/xml/pi-node.h (+6/-0)
src/xml/repr-io.cpp (+169/-1060)
src/xml/repr-io.h (+45/-0)
src/xml/repr-util.cpp (+7/-2)
src/xml/repr.h (+0/-25)
src/xml/simple-document.cpp (+12/-0)
src/xml/simple-document.h (+2/-0)
src/xml/simple-node.cpp (+89/-0)
src/xml/simple-node.h (+25/-3)
src/xml/svg-parser.cpp (+266/-0)
src/xml/svg-parser.h (+85/-0)
src/xml/text-node.h (+15/-0)
testfiles/CMakeLists.txt (+5/-1)
testfiles/doc-per-case-test.cpp (+4/-0)
testfiles/src/object-set-test.cpp (+1/-1)
testfiles/src/repr-io-test.cpp (+73/-0)
testfiles/src/sp-object-test.cpp (+1/-1)
testfiles/src/svg-parser-test.cpp (+237/-0)
testfiles/src/svg-writer-test.cpp (+219/-0)
To merge this branch: bzr merge lp:~adrianboguszewski/inkscape/sax-parser
Reviewer Review Type Date Requested Status
Mc Pending
Review via email: mp+310142@code.launchpad.net

Description of the change

Added new file loading and saving, new sax parser and libxml++.

To post a comment you must log in.

Unmerged revisions

15065. By Adrian Boguszewski

Merged trunk

15064. By Adrian Boguszewski

Fixed Windows file loading

15063. By Adrian Boguszewski

Merged trunk

15062. By Adrian Boguszewski

Fixed libxml++ compilation on Windows

15061. By Adrian Boguszewski

Merged trunk

15060. By Adrian Boguszewski

Fixed memory management in sax parser

15059. By Adrian Boguszewski

Renamed some variables

15058. By Adrian Boguszewski

Added empty entity to sax parser

15057. By Adrian Boguszewski

Improved compressed file reading

15056. By Adrian Boguszewski

Fixed too many text nodes

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'CMakeLists.txt'
--- CMakeLists.txt 2016-10-01 06:05:10 +0000
+++ CMakeLists.txt 2016-11-06 17:18:04 +0000
@@ -86,6 +86,7 @@
86 message("No gmock/gtest found! Perhaps you wish to run 'bash download-gtest.sh' to download it.")86 message("No gmock/gtest found! Perhaps you wish to run 'bash download-gtest.sh' to download it.")
87endif()87endif()
8888
89include(CMakeScripts/ConfigCompileFlags.cmake)
89include(CMakeScripts/DefineDependsandFlags.cmake) # Includes, Compiler Flags, and Link Libraries90include(CMakeScripts/DefineDependsandFlags.cmake) # Includes, Compiler Flags, and Link Libraries
90include(CMakeScripts/HelperMacros.cmake) # Misc Utility Macros91include(CMakeScripts/HelperMacros.cmake) # Misc Utility Macros
9192
9293
=== modified file 'CMakeScripts/ConfigCompileFlags.cmake'
--- CMakeScripts/ConfigCompileFlags.cmake 2016-08-09 09:33:34 +0000
+++ CMakeScripts/ConfigCompileFlags.cmake 2016-11-06 17:18:04 +0000
@@ -14,6 +14,6 @@
14set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 ${COMPILE_PROFILING_FLAGS} ")14set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 ${COMPILE_PROFILING_FLAGS} ")
15set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2 ${COMPILE_PROFILING_FLAGS} ")15set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2 ${COMPILE_PROFILING_FLAGS} ")
1616
17set(CMAKE_MAKE_PROGRAM "${CMAKE_MAKE_PROGRAM} ")17set(CMAKE_MAKE_PROGRAM ${CMAKE_MAKE_PROGRAM})
1818
19message(STATUS "${CMAKE_CXX_FLAGS}")19message(STATUS "${CMAKE_CXX_FLAGS}")
2020
=== modified file 'src/CMakeLists.txt'
--- src/CMakeLists.txt 2016-10-22 22:11:58 +0000
+++ src/CMakeLists.txt 2016-11-06 17:18:04 +0000
@@ -458,6 +458,7 @@
458add_subdirectory(inkgc)458add_subdirectory(inkgc)
459add_subdirectory(libuemf)459add_subdirectory(libuemf)
460add_subdirectory(libvpsc)460add_subdirectory(libvpsc)
461add_subdirectory(libxml++)
461add_subdirectory(livarot)462add_subdirectory(livarot)
462add_subdirectory(libnrtype)463add_subdirectory(libnrtype)
463add_subdirectory(libdepixelize)464add_subdirectory(libdepixelize)
@@ -515,6 +516,7 @@
515 avoid_LIB516 avoid_LIB
516 cola_LIB517 cola_LIB
517 vpsc_LIB518 vpsc_LIB
519 xmlpp_LIB
518 livarot_LIB520 livarot_LIB
519 uemf_LIB521 uemf_LIB
520 2geom_LIB522 2geom_LIB
521523
=== modified file 'src/document.cpp'
--- src/document.cpp 2016-10-02 22:44:54 +0000
+++ src/document.cpp 2016-11-06 17:18:04 +0000
@@ -42,6 +42,7 @@
42#include <string>42#include <string>
43#include <cstring>43#include <cstring>
44#include <2geom/transforms.h>44#include <2geom/transforms.h>
45#include <xml/repr-io.h>
4546
46#include "widgets/desktop-widget.h"47#include "widgets/desktop-widget.h"
47#include "desktop.h"48#include "desktop.h"
@@ -496,7 +497,7 @@
496 Inkscape::XML::Node *rroot;497 Inkscape::XML::Node *rroot;
497 gchar *s, *p;498 gchar *s, *p;
498 /* Try to fetch repr from file */499 /* Try to fetch repr from file */
499 rdoc = sp_repr_read_file(uri, SP_SVG_NS_URI);500 rdoc = Inkscape::XML::read_svg_file(uri, false, SP_SVG_NS_URI);
500 /* If file cannot be loaded, return NULL without warning */501 /* If file cannot be loaded, return NULL without warning */
501 if (rdoc == NULL) return NULL;502 if (rdoc == NULL) return NULL;
502 rroot = rdoc->root();503 rroot = rdoc->root();
@@ -542,7 +543,7 @@
542{543{
543 SPDocument *doc = NULL;544 SPDocument *doc = NULL;
544545
545 Inkscape::XML::Document *rdoc = sp_repr_read_mem(buffer, length, SP_SVG_NS_URI);546 Inkscape::XML::Document *rdoc = Inkscape::XML::read_svg_buffer(buffer, false, SP_SVG_NS_URI);
546 if ( rdoc ) {547 if ( rdoc ) {
547 // Only continue to create a non-null doc if it could be loaded548 // Only continue to create a non-null doc if it could be loaded
548 Inkscape::XML::Node *rroot = rdoc->root();549 Inkscape::XML::Node *rroot = rdoc->root();
549550
=== modified file 'src/extension/implementation/xslt.cpp'
--- src/extension/implementation/xslt.cpp 2016-08-03 13:29:38 +0000
+++ src/extension/implementation/xslt.cpp 2016-11-06 17:18:04 +0000
@@ -29,8 +29,7 @@
2929
30#include <libxslt/transform.h>30#include <libxslt/transform.h>
31#include <libxslt/xsltutils.h>31#include <libxslt/xsltutils.h>
3232#include <xml/repr-io.h>
33Inkscape::XML::Document * sp_repr_do_read (xmlDocPtr doc, const gchar * default_ns);
3433
35/* Namespaces */34/* Namespaces */
36namespace Inkscape {35namespace Inkscape {
@@ -146,9 +145,14 @@
146 xmlDocPtr result = xsltApplyStylesheet(_stylesheet, filein, params);145 xmlDocPtr result = xsltApplyStylesheet(_stylesheet, filein, params);
147 xmlFreeDoc(filein);146 xmlFreeDoc(filein);
148147
149 Inkscape::XML::Document * rdoc = sp_repr_do_read( result, SP_SVG_NS_URI);148 xmlChar *str;
149 int size;
150 xmlDocDumpMemory(result, &str, &size);
150 xmlFreeDoc(result);151 xmlFreeDoc(result);
151152
153 Inkscape::XML::Document * rdoc = Inkscape::XML::read_svg_buffer((char*) str, false, SP_SVG_NS_URI);
154 xmlFree(str);
155
152 if (rdoc == NULL) {156 if (rdoc == NULL) {
153 return NULL;157 return NULL;
154 }158 }
@@ -197,8 +201,7 @@
197 return;201 return;
198 }202 }
199203
200 if (!sp_repr_save_rebased_file(repr->document(), tempfilename_out.c_str(), SP_SVG_NS_URI,204 if (!Inkscape::XML::save_svg_file(repr->document(), tempfilename_out.c_str(), SP_SVG_NS_URI, doc->getBase(), filename)) {
201 doc->getBase(), filename)) {
202 throw Inkscape::Extension::Output::save_failed();205 throw Inkscape::Extension::Output::save_failed();
203 }206 }
204207
205208
=== modified file 'src/extension/internal/filter/filter-file.cpp'
--- src/extension/internal/filter/filter-file.cpp 2014-06-26 19:40:39 +0000
+++ src/extension/internal/filter/filter-file.cpp 2016-11-06 17:18:04 +0000
@@ -21,6 +21,7 @@
21/* System includes */21/* System includes */
22#include <glibmm/i18n.h>22#include <glibmm/i18n.h>
23#include <glibmm/fileutils.h>23#include <glibmm/fileutils.h>
24#include <xml/repr-io.h>
2425
25namespace Inkscape {26namespace Inkscape {
26namespace Extension {27namespace Extension {
@@ -84,7 +85,7 @@
84void85void
85Filter::filters_load_file (gchar * filename, gchar * menuname)86Filter::filters_load_file (gchar * filename, gchar * menuname)
86{87{
87 Inkscape::XML::Document *doc = sp_repr_read_file(filename, INKSCAPE_EXTENSION_URI);88 Inkscape::XML::Document *doc = Inkscape::XML::read_svg_file(filename, true, INKSCAPE_EXTENSION_URI);
88 if (doc == NULL) {89 if (doc == NULL) {
89 g_warning("File (%s) is not parseable as XML. Ignored.", filename);90 g_warning("File (%s) is not parseable as XML. Ignored.", filename);
90 return;91 return;
@@ -162,7 +163,7 @@
162 node->setAttribute("xmlns:inkscape", SP_INKSCAPE_NS_URI);163 node->setAttribute("xmlns:inkscape", SP_INKSCAPE_NS_URI);
163164
164 mywriter writer;165 mywriter writer;
165 sp_repr_write_stream(node, writer, 0, FALSE, g_quark_from_static_string("svg"), 0, 0);166 node->serialize(writer, "svg", 0, 0, false, false);
166167
167 Inkscape::Extension::build_from_mem(xml_str, new Filter(g_strdup(writer.c_str())));168 Inkscape::Extension::build_from_mem(xml_str, new Filter(g_strdup(writer.c_str())));
168 g_free(xml_str);169 g_free(xml_str);
169170
=== modified file 'src/extension/internal/filter/filter.cpp'
--- src/extension/internal/filter/filter.cpp 2016-07-03 18:53:39 +0000
+++ src/extension/internal/filter/filter.cpp 2016-11-06 17:18:04 +0000
@@ -7,6 +7,7 @@
7 * Released under GNU GPL, read the file 'COPYING' for more information7 * Released under GNU GPL, read the file 'COPYING' for more information
8 */8 */
99
10#include <xml/repr-io.h>
10#include "desktop.h"11#include "desktop.h"
11#include "selection.h"12#include "selection.h"
12#include "document-private.h"13#include "document-private.h"
@@ -64,7 +65,7 @@
64Inkscape::XML::Document *65Inkscape::XML::Document *
65Filter::get_filter (Inkscape::Extension::Extension * ext) {66Filter::get_filter (Inkscape::Extension::Extension * ext) {
66 gchar const * filter = get_filter_text(ext);67 gchar const * filter = get_filter_text(ext);
67 return sp_repr_read_mem(filter, strlen(filter), NULL);68 return Inkscape::XML::read_svg_buffer(filter, true);
68}69}
6970
70void71void
7172
=== modified file 'src/extension/internal/svg.cpp'
--- src/extension/internal/svg.cpp 2016-10-01 21:30:34 +0000
+++ src/extension/internal/svg.cpp 2016-11-06 17:18:04 +0000
@@ -15,7 +15,7 @@
15 */15 */
1616
17#ifdef HAVE_CONFIG_H17#ifdef HAVE_CONFIG_H
18# include <config.h>18#include <config.h>
19#endif19#endif
20#include "sp-object.h"20#include "sp-object.h"
21#include "svg.h"21#include "svg.h"
@@ -25,11 +25,12 @@
25#include <vector>25#include <vector>
26#include "xml/attribute-record.h"26#include "xml/attribute-record.h"
27#include "xml/simple-document.h"27#include "xml/simple-document.h"
28#include "xml/repr-io.h"
28#include "sp-root.h"29#include "sp-root.h"
29#include "document.h"30#include "document.h"
3031
31#ifdef WITH_GNOME_VFS32#ifdef WITH_GNOME_VFS
32# include <libgnomevfs/gnome-vfs.h>33#include <libgnomevfs/gnome-vfs.h>
33#endif34#endif
3435
35namespace Inkscape {36namespace Inkscape {
@@ -293,8 +294,7 @@
293 rdoc = new_rdoc;294 rdoc = new_rdoc;
294 }295 }
295296
296 if (!sp_repr_save_rebased_file(rdoc, filename, SP_SVG_NS_URI,297 if (!Inkscape::XML::save_svg_file(rdoc, filename, SP_SVG_NS_URI, doc->getBase(), filename)) {
297 doc->getBase(), filename)) {
298 throw Inkscape::Extension::Output::save_failed();298 throw Inkscape::Extension::Output::save_failed();
299 }299 }
300300
301301
=== modified file 'src/extension/loader.h'
--- src/extension/loader.h 2016-08-03 15:12:14 +0000
+++ src/extension/loader.h 2016-11-06 17:18:04 +0000
@@ -1,4 +1,5 @@
1/** @file1/** @file#include <config.h>
2
2 * Loader for external plug-ins.3 * Loader for external plug-ins.
3 *//*4 *//*
4 *5 *
56
=== modified file 'src/extension/prefdialog.cpp'
--- src/extension/prefdialog.cpp 2016-07-28 10:22:07 +0000
+++ src/extension/prefdialog.cpp 2016-11-06 17:18:04 +0000
@@ -12,6 +12,7 @@
12#include <gtkmm/checkbutton.h>12#include <gtkmm/checkbutton.h>
13#include <gtkmm/separator.h>13#include <gtkmm/separator.h>
14#include <glibmm/i18n.h>14#include <glibmm/i18n.h>
15#include <xml/repr-io.h>
1516
16#include "ui/dialog-events.h"17#include "ui/dialog-events.h"
17#include "xml/repr.h"18#include "xml/repr.h"
@@ -81,7 +82,7 @@
8182
82 if (_effect != NULL && !_effect->no_live_preview) {83 if (_effect != NULL && !_effect->no_live_preview) {
83 if (_param_preview == NULL) {84 if (_param_preview == NULL) {
84 XML::Document * doc = sp_repr_read_mem(live_param_xml, strlen(live_param_xml), NULL);85 XML::Document * doc = Inkscape::XML::read_svg_buffer(live_param_xml, true);
85 if (doc == NULL) {86 if (doc == NULL) {
86 std::cout << "Error encountered loading live parameter XML !!!" << std::endl;87 std::cout << "Error encountered loading live parameter XML !!!" << std::endl;
87 return;88 return;
8889
=== modified file 'src/extension/system.cpp'
--- src/extension/system.cpp 2016-08-03 13:29:38 +0000
+++ src/extension/system.cpp 2016-11-06 17:18:04 +0000
@@ -40,6 +40,7 @@
40#include "loader.h"40#include "loader.h"
4141
42#include <glibmm/miscutils.h>42#include <glibmm/miscutils.h>
43#include <xml/repr-io.h>
4344
44namespace Inkscape {45namespace Inkscape {
45namespace Extension {46namespace Extension {
@@ -546,7 +547,7 @@
546Extension *547Extension *
547build_from_file(gchar const *filename)548build_from_file(gchar const *filename)
548{549{
549 Inkscape::XML::Document *doc = sp_repr_read_file(filename, INKSCAPE_EXTENSION_URI);550 Inkscape::XML::Document *doc = Inkscape::XML::read_svg_file(filename, true, INKSCAPE_EXTENSION_URI);
550 std::string dir = Glib::path_get_dirname(filename);551 std::string dir = Glib::path_get_dirname(filename);
551 Extension *ext = build_from_reprdoc(doc, NULL, &dir);552 Extension *ext = build_from_reprdoc(doc, NULL, &dir);
552 if (ext != NULL)553 if (ext != NULL)
@@ -568,7 +569,7 @@
568Extension *569Extension *
569build_from_mem(gchar const *buffer, Implementation::Implementation *in_imp)570build_from_mem(gchar const *buffer, Implementation::Implementation *in_imp)
570{571{
571 Inkscape::XML::Document *doc = sp_repr_read_mem(buffer, strlen(buffer), INKSCAPE_EXTENSION_URI);572 Inkscape::XML::Document *doc = Inkscape::XML::read_svg_buffer(buffer, true, INKSCAPE_EXTENSION_URI);
572 g_return_val_if_fail(doc != NULL, NULL);573 g_return_val_if_fail(doc != NULL, NULL);
573 Extension *ext = build_from_reprdoc(doc, in_imp, NULL);574 Extension *ext = build_from_reprdoc(doc, in_imp, NULL);
574 Inkscape::GC::release(doc);575 Inkscape::GC::release(doc);
575576
=== modified file 'src/inkscape.cpp'
--- src/inkscape.cpp 2016-09-02 22:45:03 +0000
+++ src/inkscape.cpp 2016-11-06 17:18:04 +0000
@@ -48,6 +48,7 @@
48#include <glibmm/i18n.h>48#include <glibmm/i18n.h>
49#include <glibmm/miscutils.h>49#include <glibmm/miscutils.h>
50#include <glibmm/convert.h>50#include <glibmm/convert.h>
51#include <xml/repr-io.h>
5152
52#include "desktop.h"53#include "desktop.h"
5354
@@ -322,21 +323,17 @@
322 baseName = 0;323 baseName = 0;
323324
324 // Try to save the file325 // Try to save the file
325 FILE *file = Inkscape::IO::fopen_utf8name(full_path, "w");
326 gchar *errortext = 0;326 gchar *errortext = 0;
327 if (file) {327 try {
328 try{328 if (!Inkscape::XML::save_svg_file(repr->document(), full_path, SP_SVG_NS_URI)) {
329 sp_repr_save_stream(repr->document(), file, SP_SVG_NS_URI);
330 } catch (Inkscape::Extension::Output::no_extension_found &e) {
331 errortext = g_strdup(_("Autosave failed! Could not find inkscape extension to save document."));
332 } catch (Inkscape::Extension::Output::save_failed &e) {
333 gchar *safeUri = Inkscape::IO::sanitizeString(full_path);329 gchar *safeUri = Inkscape::IO::sanitizeString(full_path);
334 errortext = g_strdup_printf(_("Autosave failed! File %s could not be saved."), safeUri);330 errortext = g_strdup_printf(_("Autosave failed! File %s could not be saved."), safeUri);
335 g_free(safeUri);331 g_free(safeUri);
336 }332 }
337 fclose(file);333
338 }334 } catch (Inkscape::Extension::Output::no_extension_found &e) {
339 else {335 errortext = g_strdup(_("Autosave failed! Could not find inkscape extension to save document."));
336 } catch (Inkscape::Extension::Output::save_failed &e) {
340 gchar *safeUri = Inkscape::IO::sanitizeString(full_path);337 gchar *safeUri = Inkscape::IO::sanitizeString(full_path);
341 errortext = g_strdup_printf(_("Autosave failed! File %s could not be saved."), safeUri);338 errortext = g_strdup_printf(_("Autosave failed! File %s could not be saved."), safeUri);
342 g_free(safeUri);339 g_free(safeUri);
@@ -701,15 +698,14 @@
701 file = Inkscape::IO::fopen_utf8name(filename, "w");698 file = Inkscape::IO::fopen_utf8name(filename, "w");
702 if (file) {699 if (file) {
703 g_snprintf (c, 1024, "%s", filename); // we want the complete path to be stored in c (for reporting purposes)700 g_snprintf (c, 1024, "%s", filename); // we want the complete path to be stored in c (for reporting purposes)
701 fclose (file);
704 break;702 break;
705 }703 }
706 }704 }
707705
708 // Save706 // Save
709 if (file) {707 if (Inkscape::XML::save_svg_file(repr->document(), c, SP_SVG_NS_URI)) {
710 sp_repr_save_stream (repr->document(), file, SP_SVG_NS_URI);
711 savednames = g_slist_prepend (savednames, g_strdup (c));708 savednames = g_slist_prepend (savednames, g_strdup (c));
712 fclose (file);
713 } else {709 } else {
714 failednames = g_slist_prepend (failednames, (doc->getName()) ? g_strdup(doc->getName()) : g_strdup (_("Untitled document")));710 failednames = g_slist_prepend (failednames, (doc->getName()) ? g_strdup(doc->getName()) : g_strdup (_("Untitled document")));
715 }711 }
@@ -819,7 +815,7 @@
819815
820 if ( g_file_get_contents(fn, &menus_xml, &len, NULL) ) {816 if ( g_file_get_contents(fn, &menus_xml, &len, NULL) ) {
821 // load the menus_xml file817 // load the menus_xml file
822 _menus = sp_repr_read_mem(menus_xml, len, NULL);818 _menus = Inkscape::XML::read_svg_buffer(menus_xml, true);
823819
824 g_free(menus_xml);820 g_free(menus_xml);
825 menus_xml = 0;821 menus_xml = 0;
@@ -828,7 +824,7 @@
828 fn = 0;824 fn = 0;
829825
830 if ( !_menus ) {826 if ( !_menus ) {
831 _menus = sp_repr_read_mem(menus_skeleton, MENUS_SKELETON_SIZE, NULL);827 _menus = Inkscape::XML::read_svg_buffer(menus_skeleton, true);
832 }828 }
833829
834 return (_menus != 0);830 return (_menus != 0);
835831
=== added directory 'src/libxml++'
=== added file 'src/libxml++/CMakeLists.txt'
--- src/libxml++/CMakeLists.txt 1970-01-01 00:00:00 +0000
+++ src/libxml++/CMakeLists.txt 2016-11-06 17:18:04 +0000
@@ -0,0 +1,34 @@
1set(libxmlpp_SRC
2 document.cc
3 dtd.cc
4 keepblanks.cc
5 noncopyable.cc
6 exceptions/exception.cc
7 exceptions/internal_error.cc
8 exceptions/parse_error.cc
9 exceptions/validity_error.cc
10 exceptions/wrapped_exception.cc
11 io/istreamparserinputbuffer.cc
12 io/parserinputbuffer.cc
13 parsers/parser.cc
14 parsers/saxparser.cc
15
16 # -------
17 # Headers
18 document.h
19 dtd.h
20 keepblanks.h
21 libxml++config.h
22 noncopyable.h
23 exceptions/exception.h
24 exceptions/internal_error.h
25 exceptions/parse_error.h
26 exceptions/validity_error.h
27 exceptions/wrapped_exception.h
28 io/istreamparserinputbuffer.h
29 io/parserinputbuffer.h
30 parsers/parser.h
31 parsers/saxparser.h
32 )
33
34add_inkscape_lib(xmlpp_LIB "${libxmlpp_SRC}")
035
=== added file 'src/libxml++/README'
--- src/libxml++/README 1970-01-01 00:00:00 +0000
+++ src/libxml++/README 2016-11-06 17:18:04 +0000
@@ -0,0 +1,8 @@
1This code is a part of libxml++ library (ver 3.0) with local modifications
2inter alia:
3* DOM parser and node classes are removed
4* Enabled SAX2 interface
5* Added new SAX parser methods to handle Processing Instructions
6 and namespace information from nodes
7
8Full library is available here: http://libxmlplusplus.sourceforge.net/
0\ No newline at end of file9\ No newline at end of file
110
=== added file 'src/libxml++/document.cc'
--- src/libxml++/document.cc 1970-01-01 00:00:00 +0000
+++ src/libxml++/document.cc 2016-11-06 17:18:04 +0000
@@ -0,0 +1,126 @@
1/* document.cc
2 * this file is part of libxml++
3 *
4 * copyright (C) 2003 by the libxml++ development team
5 *
6 * this file is covered by the GNU Lesser General Public License,
7 * which should be included with libxml++ as the file COPYING.
8 */
9
10#include <libxml++/document.h>
11#include <libxml++/exceptions/internal_error.h>
12
13#include <libxml/tree.h>
14
15namespace xmlpp
16{
17
18static const char* get_encoding_or_utf8(const Glib::ustring& encoding)
19{
20 if(encoding.empty())
21 {
22 //If we don't specify this to the xmlDocDump* functions (using nullptr instead),
23 //then some other encoding is used, causing them to fail on non-ASCII characters.
24 return "UTF-8";
25 }
26 else
27 return encoding.c_str();
28}
29
30
31Document::Init::Init()
32{
33 xmlInitParser(); //Not always necessary, but necessary for thread safety.
34}
35
36Document::Init::~Init() noexcept
37{
38 //We don't call this because it breaks libxml generally and should only be
39 //called at the very end of a process, such as at the end of a main().
40 //libxml might still be used by the application, so we don't want to break
41 //that.
42 //This is important even here, which usually happens only when the library
43 //is unloaded, because that might happen during normal application use,
44 //if the application does dynamic library loading, for instance to load
45 //plugins.
46 //See http://xmlsoft.org/html/libxml-parser.html#xmlCleanupParser
47 //xmlCleanupParser(); //As per xmlInitParser(), or memory leak will happen.
48}
49
50Document::Init Document::init_;
51
52Document::Document(const Glib::ustring& version)
53 : impl_(xmlNewDoc((const xmlChar*)version.c_str()))
54{
55 if (!impl_)
56 throw internal_error("Could not create Document.");
57 impl_->_private = this;
58}
59
60Document::Document(xmlDoc* doc)
61 : impl_(doc)
62{
63 if (!impl_)
64 throw internal_error("xmlDoc pointer cannot be nullptr");
65
66 impl_->_private = this;
67}
68
69Document::~Document()
70{
71 xmlFreeDoc(impl_);
72}
73
74Glib::ustring Document::get_encoding() const
75{
76 Glib::ustring encoding;
77 if(impl_->encoding)
78 encoding = (const char*)impl_->encoding;
79
80 return encoding;
81}
82
83Dtd* Document::get_internal_subset() const
84{
85 auto dtd = xmlGetIntSubset(impl_);
86 if(!dtd)
87 return nullptr;
88
89 if(!dtd->_private)
90 dtd->_private = new Dtd(dtd);
91
92 return reinterpret_cast<Dtd*>(dtd->_private);
93}
94
95void Document::set_internal_subset(const Glib::ustring& name,
96 const Glib::ustring& external_id,
97 const Glib::ustring& system_id)
98{
99 auto dtd = xmlCreateIntSubset(impl_,
100 (const xmlChar*)name.c_str(),
101 external_id.empty() ? nullptr : (const xmlChar*)external_id.c_str(),
102 system_id.empty() ? nullptr : (const xmlChar*)system_id.c_str());
103
104 if (dtd && !dtd->_private)
105 dtd->_private = new Dtd(dtd);
106}
107
108void Document::set_entity_declaration(const Glib::ustring& name, XmlEntityType type,
109 const Glib::ustring& publicId, const Glib::ustring& systemId,
110 const Glib::ustring& content)
111{
112 auto entity = xmlAddDocEntity(impl_, (const xmlChar*)name.c_str(),
113 static_cast<int>(type),
114 publicId.empty() ? nullptr : (const xmlChar*)publicId.c_str(),
115 systemId.empty() ? nullptr : (const xmlChar*)systemId.c_str(),
116 (const xmlChar*)content.c_str());
117 if (!entity)
118 throw internal_error("Could not add entity declaration " + name);
119}
120
121_xmlEntity* Document::get_entity(const Glib::ustring& name)
122{
123 return xmlGetDocEntity(impl_, (const xmlChar*) name.c_str());
124}
125
126} //namespace xmlpp
0127
=== added file 'src/libxml++/document.h'
--- src/libxml++/document.h 1970-01-01 00:00:00 +0000
+++ src/libxml++/document.h 2016-11-06 17:18:04 +0000
@@ -0,0 +1,139 @@
1/* document.h
2 * this file is part of libxml++
3 *
4 * parts of the code copyright (C) 2003 by Stefan Seefeld
5 * others copyright (C) 2003 by libxml++ developer's team
6 *
7 * this file is covered by the GNU Lesser General Public License,
8 * which should be included with libxml++ as the file COPYING.
9 */
10
11#ifndef __LIBXMLPP_DOCUMENT_H
12#define __LIBXMLPP_DOCUMENT_H
13
14#include <libxml++/dtd.h>
15
16#include <string>
17#include <ostream>
18
19/* std::string or Glib::ustring in function prototypes in libxml++?
20 *
21 * If it's propagated to a libxml2 function that takes a xmlChar*, it's
22 * UTF-8 encoded, and Glib::ustring is the right choice.
23 *
24 * If it's propagated to a libxml2 function that takes a char*, it's not
25 * necessarily UTF-8 encoded, and std::string is usually the right choice.
26 * Most of these strings are filenames or URLs.
27 */
28
29#ifndef DOXYGEN_SHOULD_SKIP_THIS
30extern "C" {
31 struct _xmlDoc;
32 struct _xmlEntity;
33}
34#endif //DOXYGEN_SHOULD_SKIP_THIS
35
36namespace xmlpp
37{
38
39// xmlpp::XmlEntityType is similar to xmlEntityType in libxml2.
40/** The valid entity types.
41 */
42enum class XmlEntityType
43{
44 INTERNAL_GENERAL = 1,
45 EXTERNAL_GENERAL_PARSED = 2,
46 EXTERNAL_GENERAL_UNPARSED = 3,
47 INTERNAL_PARAMETER = 4,
48 EXTERNAL_PARAMETER = 5,
49 INTERNAL_PREDEFINED = 6
50};
51
52//TODO: Make Document inherit from Node, when we can break ABI one day?
53//
54//libxml might intend xmlDoc to derive (theoretically) from xmlNode.
55//This is suggested because the xmlNodeSet returned by xmlXPathEval (see the
56//Node::find() implementation) can contain either xmlNode or xmlDocument elements.
57// See https://bugzilla.gnome.org/show_bug.cgi?id=754673#c8 for an explanation
58// why it has not been done in libxml++ 3.0.
59/**
60 * Represents an XML document in the DOM model.
61 */
62class Document : public NonCopyable
63{
64 //Ensure that libxml is properly initialised:
65 class Init
66 {
67 public:
68 Init();
69 ~Init() noexcept;
70 };
71
72 friend class SaxParser;
73
74public:
75 /** Create a new document.
76 * @param version XML version.
77 * @throws xmlpp::internal_error If memory allocation fails.
78 */
79 explicit Document(const Glib::ustring& version = "1.0");
80
81 /** Create a new C++ wrapper for an xmlDoc struct.
82 * The created xmlpp::Document takes ownership of the xmlDoc.
83 * When the Document is deleted, so is the xmlDoc and all its nodes.
84 * @param doc A pointer to an xmlDoc struct. Must not be <tt>nullptr</tt>.
85 * @throws xmlpp::internal_error If @a doc is <tt>nullptr</tt>.
86 */
87 explicit Document(_xmlDoc* doc);
88
89 ~Document() override;
90
91 /** @return The encoding used in the source from which the document has been loaded.
92 */
93 Glib::ustring get_encoding() const;
94
95 /** Get the internal subset of this document.
96 * @returns A pointer to the DTD, or <tt>nullptr</tt> if not found.
97 */
98 Dtd* get_internal_subset() const;
99
100 /** Create the internal subset of this document.
101 * If the document already has an internal subset, a new one is not created.
102 * @param name The DTD name.
103 * @param external_id The external (PUBLIC) ID, or an empty string.
104 * @param system_id The system ID, or an empty string.
105 */
106 void set_internal_subset(const Glib::ustring& name,
107 const Glib::ustring& external_id,
108 const Glib::ustring& system_id);
109
110 /** Add an Entity declaration to the document.
111 * @param name The name of the entity that will be used in an entity reference.
112 * @param type The type of entity.
113 * @param publicId The public ID of the subset.
114 * @param systemId The system ID of the subset.
115 * @param content The value of the Entity. In entity reference substitutions, this
116 * is the replacement value.
117 * @throws xmlpp::internal_error
118 */
119 virtual void set_entity_declaration(const Glib::ustring& name, XmlEntityType type,
120 const Glib::ustring& publicId, const Glib::ustring& systemId,
121 const Glib::ustring& content);
122
123protected:
124 /** Retrieve an Entity.
125 * The entity can be from an external subset or internally declared.
126 * @param name The name of the entity to get.
127 * @returns A pointer to the libxml2 entity structure, or <tt>nullptr</tt> if not found.
128 */
129 _xmlEntity* get_entity(const Glib::ustring& name);
130
131private:
132 static Init init_;
133
134 _xmlDoc* impl_;
135};
136
137} //namespace xmlpp
138
139#endif //__LIBXMLPP_DOCUMENT_H
0140
=== added file 'src/libxml++/dtd.cc'
--- src/libxml++/dtd.cc 1970-01-01 00:00:00 +0000
+++ src/libxml++/dtd.cc 2016-11-06 17:18:04 +0000
@@ -0,0 +1,147 @@
1/* dtd.cc
2 * libxml++ and this file are copyright (C) 2000 by Ari Johnson, and
3 * are covered by the GNU Lesser General Public License, which should be
4 * included with libxml++ as the file COPYING.
5 */
6
7#include <libxml++/dtd.h>
8#include <libxml++/exceptions/parse_error.h>
9#include <libxml++/io/istreamparserinputbuffer.h>
10
11#include <libxml/tree.h>
12
13namespace xmlpp
14{
15
16struct Dtd::Impl
17{
18 Impl() noexcept : dtd(nullptr), is_dtd_owner(false) {}
19
20 _xmlDtd* dtd;
21 bool is_dtd_owner;
22};
23
24Dtd::Dtd()
25: pimpl_(new Impl)
26{
27}
28
29Dtd::Dtd(_xmlDtd* dtd, bool take_ownership)
30: pimpl_(new Impl)
31{
32 pimpl_->dtd = dtd;
33 if (dtd)
34 {
35 pimpl_->dtd->_private = this;
36 pimpl_->is_dtd_owner = take_ownership;
37 }
38}
39
40Dtd::Dtd(const std::string& filename)
41: pimpl_(new Impl)
42{
43 parse_subset("", filename);
44}
45
46Dtd::Dtd(const Glib::ustring& external, const Glib::ustring& system)
47: pimpl_(new Impl)
48{
49 parse_subset(external, system);
50}
51
52Dtd::~Dtd()
53{
54 release_underlying();
55}
56
57void Dtd::parse_file(const std::string& filename)
58{
59 parse_subset("", filename);
60}
61
62void Dtd::parse_subset(const Glib::ustring& external, const Glib::ustring& system)
63{
64 release_underlying(); // Free any existing dtd.
65 xmlResetLastError();
66
67 auto dtd = xmlParseDTD(
68 external.empty() ? nullptr : (const xmlChar*)external.c_str(),
69 system.empty() ? nullptr : (const xmlChar*)system.c_str());
70
71 if (!dtd)
72 {
73 throw parse_error("Dtd could not be parsed.\n" + format_xml_error());
74 }
75
76 pimpl_->dtd = dtd;
77 pimpl_->dtd->_private = this;
78 pimpl_->is_dtd_owner = true;
79}
80
81void Dtd::parse_memory(const Glib::ustring& contents)
82{
83 // Prepare an istream with buffer
84 std::istringstream is(contents);
85
86 parse_stream(is);
87}
88
89void Dtd::parse_stream(std::istream& in)
90{
91 release_underlying(); // Free any existing dtd.
92 xmlResetLastError();
93
94 IStreamParserInputBuffer ibuff(in);
95
96 auto dtd = xmlIOParseDTD(nullptr, ibuff.cobj(), XML_CHAR_ENCODING_UTF8);
97
98 if (!dtd)
99 {
100 throw parse_error("Dtd could not be parsed.\n" + format_xml_error());
101 }
102
103 pimpl_->dtd = dtd;
104 pimpl_->dtd->_private = this;
105 pimpl_->is_dtd_owner = true;
106}
107
108Glib::ustring Dtd::get_name() const
109{
110 return (pimpl_->dtd && pimpl_->dtd->name) ? (const char*)pimpl_->dtd->name : "";
111}
112
113Glib::ustring Dtd::get_external_id() const
114{
115 return (pimpl_->dtd && pimpl_->dtd->ExternalID) ? (const char*)pimpl_->dtd->ExternalID : "";
116}
117
118Glib::ustring Dtd::get_system_id() const
119{
120 return (pimpl_->dtd && pimpl_->dtd->SystemID) ? (const char*)pimpl_->dtd->SystemID : "";
121}
122
123_xmlDtd* Dtd::cobj() noexcept
124{
125 return pimpl_->dtd;
126}
127
128const _xmlDtd* Dtd::cobj() const noexcept
129{
130 return pimpl_->dtd;
131}
132
133void Dtd::release_underlying()
134{
135 if (pimpl_->dtd)
136 {
137 pimpl_->dtd->_private = nullptr;
138 if (pimpl_->is_dtd_owner)
139 {
140 xmlFreeDtd(pimpl_->dtd);
141 pimpl_->is_dtd_owner = false;
142 }
143 pimpl_->dtd = nullptr;
144 }
145}
146
147} //namespace xmlpp
0148
=== added file 'src/libxml++/dtd.h'
--- src/libxml++/dtd.h 1970-01-01 00:00:00 +0000
+++ src/libxml++/dtd.h 2016-11-06 17:18:04 +0000
@@ -0,0 +1,136 @@
1/* dtd.h
2 * libxml++ and this file are copyright (C) 2000 by Ari Johnson, and
3 * are covered by the GNU Lesser General Public License, which should be
4 * included with libxml++ as the file COPYING.
5 */
6
7#ifndef __LIBXMLPP_DTD_H
8#define __LIBXMLPP_DTD_H
9
10#include <libxml++/noncopyable.h>
11#include <glibmm/ustring.h>
12#include <string>
13#include <memory> // std::unique_ptr
14
15#ifndef DOXYGEN_SHOULD_SKIP_THIS
16extern "C" {
17 struct _xmlDtd;
18}
19#endif //DOXYGEN_SHOULD_SKIP_THIS
20
21namespace xmlpp
22{
23
24//TODO: Derive from Node?
25// See https://bugzilla.gnome.org/show_bug.cgi?id=754673#c8 for an explanation
26// why it has not been done in libxml++ 3.0.
27/** Represents an XML DTD for validating XML files.
28 * DTD = Document Type Definition
29 */
30class Dtd : public NonCopyable
31{
32public:
33 Dtd();
34
35 /** Create a Dtd from the underlying libxml DTD element.
36 * @param dtd A pointer to the libxml DTD element.
37 * @param take_ownership If <tt>true</tt>, this Dtd instance takes ownership of
38 * the libxml DTD element. The caller must not delete it.<br>
39 * If <tt>false</tt>, this Dtd does not take ownership of the libxml
40 * DTD element. The caller must guarantee that the libxml DTD element
41 * exists as long as this Dtd keeps a pointer to it. The caller is
42 * responsible for deleting the libxml DTD element when it's no longer
43 * needed, unless it belongs to a Document, in which case it's deleted
44 * when the Document is deleted.
45 */
46 explicit Dtd(_xmlDtd* dtd, bool take_ownership = false);
47
48 /** Create a Dtd and parse an external subset (DTD file) immediately.
49 *
50 * @newin{3,0}
51 *
52 * @param filename The URL of the DTD.
53 * @throws xmlpp::parse_error
54 */
55 explicit Dtd(const std::string& filename);
56
57 /** Create a Dtd and parse an external subset (DTD file) immediately.
58 *
59 * @newin{3,0}
60 *
61 * @param external The external ID of the DTD.
62 * @param system The URL of the DTD.
63 * @throws xmlpp::parse_error
64 */
65 Dtd(const Glib::ustring& external, const Glib::ustring& system);
66
67 ~Dtd() override;
68
69 /** Parse an external subset (DTD file).
70 * If another DTD has been parsed before, that DTD is replaced by the new one
71 * (deleted if this Dtd owns it).
72 *
73 * @newin{3,0}
74 *
75 * @param filename The URL of the DTD.
76 * @throws xmlpp::parse_error
77 */
78 void parse_file(const std::string& filename);
79
80 /** Parse an external subset (DTD file).
81 * If another DTD has been parsed before, that DTD is replaced by the new one
82 * (deleted if this Dtd owns it).
83 *
84 * @newin{3,0}
85 *
86 * @param external The external ID of the DTD.
87 * @param system The URL of the DTD.
88 * @throws xmlpp::parse_error
89 */
90 void parse_subset(const Glib::ustring& external, const Glib::ustring& system);
91
92 /** Parse a DTD from a string.
93 * If another DTD has been parsed before, that DTD is replaced by the new one
94 * (deleted if this Dtd owns it).
95 *
96 * @newin{3,0}
97 *
98 * @param contents The DTD as a string.
99 * @throws xmlpp::parse_error
100 */
101 void parse_memory(const Glib::ustring& contents);
102
103 /** Parse a DTD from a stream.
104 * If another DTD has been parsed before, that DTD is replaced by the new one
105 * (deleted if this Dtd owns it).
106 *
107 * @newin{3,0}
108 *
109 * @param in The stream.
110 * @throws xmlpp::parse_error
111 */
112 void parse_stream(std::istream& in);
113
114 Glib::ustring get_name() const;
115 Glib::ustring get_external_id() const;
116 Glib::ustring get_system_id() const;
117
118 /** Access the underlying libxml implementation.
119 */
120 _xmlDtd* cobj() noexcept;
121
122 /** Access the underlying libxml implementation.
123 */
124 const _xmlDtd* cobj() const noexcept;
125
126protected:
127 void release_underlying();
128
129private:
130 struct Impl;
131 std::unique_ptr<Impl> pimpl_;
132};
133
134} // namespace xmlpp
135
136#endif //__LIBXMLPP_DTD_H
0137
=== added directory 'src/libxml++/exceptions'
=== added file 'src/libxml++/exceptions/exception.cc'
--- src/libxml++/exceptions/exception.cc 1970-01-01 00:00:00 +0000
+++ src/libxml++/exceptions/exception.cc 2016-11-06 17:18:04 +0000
@@ -0,0 +1,125 @@
1#include "exception.h"
2#include <libxml/xmlerror.h>
3#include <libxml/parser.h>
4#include <cstdio>
5#include <vector>
6
7namespace xmlpp {
8
9exception::exception(const Glib::ustring& message)
10: message_(message)
11{
12}
13
14exception::~exception() noexcept
15{}
16
17const char* exception::what() const noexcept
18{
19 return message_.c_str();
20}
21
22void exception::raise() const
23{
24 throw *this;
25}
26
27exception* exception::clone() const
28{
29 return new exception(*this);
30}
31
32Glib::ustring format_xml_error(const _xmlError* error)
33{
34 if (!error)
35 error = xmlGetLastError();
36
37 if (!error || error->code == XML_ERR_OK)
38 return ""; // No error
39
40 Glib::ustring str;
41
42 if (error->file && *error->file != '\0')
43 {
44 str += "File ";
45 str += error->file;
46 }
47
48 if (error->line > 0)
49 {
50 str += (str.empty() ? "Line " : ", line ") + Glib::ustring::format(error->line);
51 if (error->int2 > 0)
52 str += ", column " + Glib::ustring::format(error->int2);
53 }
54
55 const bool two_lines = !str.empty();
56 if (two_lines)
57 str += ' ';
58
59 switch (error->level)
60 {
61 case XML_ERR_WARNING:
62 str += "(warning):";
63 break;
64 case XML_ERR_ERROR:
65 str += "(error):";
66 break;
67 case XML_ERR_FATAL:
68 str += "(fatal):";
69 break;
70 default:
71 str += "():";
72 break;
73 }
74
75 str += two_lines ? '\n' : ' ';
76
77 if (error->message && *error->message != '\0')
78 str += error->message;
79 else
80 str += "Error code " + Glib::ustring::format(error->code);
81
82 // If the string does not end with end-of-line, append an end-of-line.
83 if (*str.rbegin() != '\n')
84 str += '\n';
85
86 return str;
87}
88
89Glib::ustring format_xml_parser_error(const _xmlParserCtxt* parser_context)
90{
91 if (!parser_context)
92 return "Error. xmlpp::format_xml_parser_error() called with parser_context == nullptr\n";
93
94 const auto error = xmlCtxtGetLastError(const_cast<_xmlParserCtxt*>(parser_context));
95
96 if (!error)
97 return ""; // No error
98
99 Glib::ustring str;
100
101 if (!parser_context->wellFormed)
102 str += "Document not well-formed.\n";
103
104 return str + format_xml_error(error);
105}
106
107Glib::ustring format_printf_message(const char* fmt, va_list args)
108{
109 // This code was inspired by the example at
110 // http://en.cppreference.com/w/cpp/io/c/vfprintf
111 va_list args2;
112 va_copy(args2, args);
113 // Number of characters (bytes) in the resulting string;
114 // error, if < 0.
115 const int nchar = std::vsnprintf(nullptr, 0, fmt, args2);
116 va_end(args2);
117 if (nchar < 0)
118 return Glib::ustring::format("Error code from std::vsnprintf = ", nchar);
119
120 std::vector<char> buf(nchar+1);
121 std::vsnprintf(buf.data(), buf.size(), fmt, args);
122 return Glib::ustring(buf.data());
123}
124
125} //namespace xmlpp
0126
=== added file 'src/libxml++/exceptions/exception.h'
--- src/libxml++/exceptions/exception.h 1970-01-01 00:00:00 +0000
+++ src/libxml++/exceptions/exception.h 2016-11-06 17:18:04 +0000
@@ -0,0 +1,99 @@
1/* exception.h
2 *
3 * Copyright (C) 2002 The libxml++ development team
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the Free
17 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20#ifndef __LIBXMLPP_EXCEPTION_H
21#define __LIBXMLPP_EXCEPTION_H
22
23#include <exception>
24#include <cstdarg> // va_list
25#include <glibmm/ustring.h>
26
27#include <libxml++/libxml++config.h>
28
29extern "C" {
30 struct _xmlError;
31 struct _xmlParserCtxt;
32}
33
34namespace xmlpp
35{
36
37/** Base class for all xmlpp exceptions.
38 */
39class LIBXMLPP_API exception : public std::exception
40{
41public:
42 explicit exception(const Glib::ustring& message);
43 ~exception() noexcept override;
44
45 const char* what() const noexcept override;
46
47 virtual void raise() const;
48 virtual exception* clone() const;
49
50private:
51 Glib::ustring message_;
52};
53
54/** Format an _xmlError struct into a text string, suitable for printing.
55 *
56 * @newin{2,36}
57 *
58 * @param error Pointer to an _xmlError struct or <tt>nullptr</tt>.
59 * If <tt>nullptr</tt>, the error returned by xmlGetLastError() is used.
60 * @returns A formatted text string. If the error struct does not contain an
61 * error (error->code == XML_ERR_OK), an empty string is returned.
62 */
63Glib::ustring format_xml_error(const _xmlError* error = nullptr);
64
65/** Format a parser error into a text string, suitable for printing.
66 *
67 * @newin{2,36}
68 *
69 * @param parser_context Pointer to an _xmlParserCtxt struct.
70 * @returns A formatted text string. If the parser context does not contain an
71 * error (parser_context->lastError.code == XML_ERR_OK), an empty
72 * string is returned.
73 */
74Glib::ustring format_xml_parser_error(const _xmlParserCtxt* parser_context);
75
76/** Format a message from a function with C-style variadic parameters.
77 *
78 * Helper function that formats a message supplied in the form of a printf-style
79 * format specification and zero or more ... parameters.
80 *
81 * @code
82 * // Typical call:
83 * void f(const char* fmt, ...)
84 * {
85 * va_list args;
86 * va_start(args, fmt);
87 * Glib::ustring msg = xmlpp::format_printf_message(fmt, args);
88 * va_end(args);
89 * // ...
90 * }
91 * @endcode
92 *
93 * @newin{3,0}
94 */
95Glib::ustring format_printf_message(const char* fmt, va_list args);
96
97} // namespace xmlpp
98
99#endif // __LIBXMLPP_EXCEPTION_H
0100
=== added file 'src/libxml++/exceptions/internal_error.cc'
--- src/libxml++/exceptions/internal_error.cc 1970-01-01 00:00:00 +0000
+++ src/libxml++/exceptions/internal_error.cc 2016-11-06 17:18:04 +0000
@@ -0,0 +1,23 @@
1#include "internal_error.h"
2
3namespace xmlpp {
4
5internal_error::internal_error(const Glib::ustring& message)
6: exception(message)
7{
8}
9
10internal_error::~internal_error() noexcept
11{}
12
13void internal_error::raise() const
14{
15 throw *this;
16}
17
18exception* internal_error::clone() const
19{
20 return new internal_error(*this);
21}
22
23} //namespace xmlpp
024
=== added file 'src/libxml++/exceptions/internal_error.h'
--- src/libxml++/exceptions/internal_error.h 1970-01-01 00:00:00 +0000
+++ src/libxml++/exceptions/internal_error.h 2016-11-06 17:18:04 +0000
@@ -0,0 +1,39 @@
1/* internal_error.h
2 *
3 * Copyright (C) 2002 The libxml++ development team
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the Free
17 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20#ifndef __LIBXMLPP_INTERNAL_ERROR_H
21#define __LIBXMLPP_INTERNAL_ERROR_H
22
23#include <libxml++/exceptions/exception.h>
24
25namespace xmlpp {
26
27class internal_error : public exception
28{
29public:
30 explicit internal_error(const Glib::ustring& message);
31 ~internal_error() noexcept override;
32
33 void raise() const override;
34 exception* clone() const override;
35};
36
37} // namespace xmlpp
38
39#endif // __LIBXMLPP_INTERNAL_ERROR_H
040
=== added file 'src/libxml++/exceptions/parse_error.cc'
--- src/libxml++/exceptions/parse_error.cc 1970-01-01 00:00:00 +0000
+++ src/libxml++/exceptions/parse_error.cc 2016-11-06 17:18:04 +0000
@@ -0,0 +1,23 @@
1#include "parse_error.h"
2
3namespace xmlpp {
4
5parse_error::parse_error(const Glib::ustring& message)
6: exception(message)
7{
8}
9
10parse_error::~parse_error() noexcept
11{}
12
13void parse_error::raise() const
14{
15 throw *this;
16}
17
18exception* parse_error::clone() const
19{
20 return new parse_error(*this);
21}
22
23} //namespace xmlpp
024
=== added file 'src/libxml++/exceptions/parse_error.h'
--- src/libxml++/exceptions/parse_error.h 1970-01-01 00:00:00 +0000
+++ src/libxml++/exceptions/parse_error.h 2016-11-06 17:18:04 +0000
@@ -0,0 +1,42 @@
1/* parse_error.h
2 *
3 * Copyright (C) 2002 The libxml++ development team
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the Free
17 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20#ifndef __LIBXMLPP_PARSE_ERROR_H
21#define __LIBXMLPP_PARSE_ERROR_H
22
23#include <libxml++/exceptions/exception.h>
24
25namespace xmlpp
26{
27
28/** This exception will be thrown when the parser encounters an error in the XML document.
29 */
30class parse_error : public exception
31{
32public:
33 explicit parse_error(const Glib::ustring& message);
34 ~parse_error() noexcept override;
35
36 void raise() const override;
37 exception* clone() const override;
38};
39
40} // namespace xmlpp
41
42#endif // __LIBXMLPP_PARSE_ERROR_H
043
=== added file 'src/libxml++/exceptions/validity_error.cc'
--- src/libxml++/exceptions/validity_error.cc 1970-01-01 00:00:00 +0000
+++ src/libxml++/exceptions/validity_error.cc 2016-11-06 17:18:04 +0000
@@ -0,0 +1,23 @@
1#include "validity_error.h"
2
3namespace xmlpp {
4
5validity_error::validity_error(const Glib::ustring& message)
6: parse_error(message)
7{
8}
9
10validity_error::~validity_error() noexcept
11{}
12
13void validity_error::raise() const
14{
15 throw *this;
16}
17
18exception* validity_error::clone() const
19{
20 return new validity_error(*this);
21}
22
23} //namespace xmlpp
024
=== added file 'src/libxml++/exceptions/validity_error.h'
--- src/libxml++/exceptions/validity_error.h 1970-01-01 00:00:00 +0000
+++ src/libxml++/exceptions/validity_error.h 2016-11-06 17:18:04 +0000
@@ -0,0 +1,42 @@
1/* validity_error.h
2 *
3 * Copyright (C) 2002 The libxml++ development team
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the Free
17 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20#ifndef __LIBXMLPP_VALIDITY_ERROR_H
21#define __LIBXMLPP_VALIDITY_ERROR_H
22
23#include <libxml++/exceptions/parse_error.h>
24
25namespace xmlpp
26{
27
28/** This exception will be thrown when the parser encounters a validity error in the XML document.
29 */
30class validity_error : public parse_error
31{
32public:
33 explicit validity_error(const Glib::ustring& message);
34 ~validity_error() noexcept override;
35
36 void raise() const override;
37 exception* clone() const override;
38};
39
40} // namespace xmlpp
41
42#endif // __LIBXMLPP_VALIDITY_ERROR_H
043
=== added file 'src/libxml++/exceptions/wrapped_exception.cc'
--- src/libxml++/exceptions/wrapped_exception.cc 1970-01-01 00:00:00 +0000
+++ src/libxml++/exceptions/wrapped_exception.cc 2016-11-06 17:18:04 +0000
@@ -0,0 +1,46 @@
1/* Copyright (C) 2015 The libxml++ development team
2 *
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public
5 * License as published by the Free Software Foundation; either
6 * version 2.1 of the License, or (at your option) any later version.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 */
17
18#include "wrapped_exception.h"
19
20namespace xmlpp
21{
22
23#ifdef LIBXMLXX_HAVE_EXCEPTION_PTR
24
25wrapped_exception::wrapped_exception(std::exception_ptr exception_ptr)
26 : exception("Wrapped exception"), exception_ptr_(exception_ptr)
27{
28}
29
30wrapped_exception::~wrapped_exception() noexcept
31{
32}
33
34void wrapped_exception::raise() const
35{
36 std::rethrow_exception(exception_ptr_);
37}
38
39exception* wrapped_exception::clone() const
40{
41 return new wrapped_exception(exception_ptr_);
42}
43
44#endif // LIBXMLXX_HAVE_EXCEPTION_PTR
45
46} // namespace xmlpp
047
=== added file 'src/libxml++/exceptions/wrapped_exception.h'
--- src/libxml++/exceptions/wrapped_exception.h 1970-01-01 00:00:00 +0000
+++ src/libxml++/exceptions/wrapped_exception.h 2016-11-06 17:18:04 +0000
@@ -0,0 +1,56 @@
1/* Copyright (C) 2015 The libxml++ development team
2 *
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public
5 * License as published by the Free Software Foundation; either
6 * version 2.1 of the License, or (at your option) any later version.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 */
17
18#ifndef __LIBXMLPP_WRAPPED_EXCEPTION_H
19#define __LIBXMLPP_WRAPPED_EXCEPTION_H
20
21#include <exception>
22
23#include <libxml++/exceptions/exception.h>
24#include <libxml++config.h>
25
26namespace xmlpp
27{
28
29#ifdef LIBXMLXX_HAVE_EXCEPTION_PTR
30
31#ifndef DOXYGEN_SHOULD_SKIP_THIS
32/** Helper class for propagating an exception through C code.
33 * Should not be used by applications.
34 * Does not exist in systems that don't support std::exception_ptr.
35 *
36 * @newin{2,40}
37 */
38class wrapped_exception : public exception
39{
40public:
41 explicit wrapped_exception(std::exception_ptr exception_ptr);
42 ~wrapped_exception() noexcept override;
43
44 void raise() const override;
45 exception* clone() const override;
46
47private:
48 std::exception_ptr exception_ptr_;
49};
50#endif //DOXYGEN_SHOULD_SKIP_THIS
51
52#endif // LIBXMLXX_HAVE_EXCEPTION_PTR
53
54} // namespace xmlpp
55
56#endif // __LIBXMLPP_WRAPPED_EXCEPTION_H
057
=== added directory 'src/libxml++/io'
=== added file 'src/libxml++/io/istreamparserinputbuffer.cc'
--- src/libxml++/io/istreamparserinputbuffer.cc 1970-01-01 00:00:00 +0000
+++ src/libxml++/io/istreamparserinputbuffer.cc 2016-11-06 17:18:04 +0000
@@ -0,0 +1,44 @@
1/* istreamparserinputbuffer
2 * this file is part of libxml++
3 *
4 * copyright (C) 2003 by libxml++ developer's team
5 *
6 * this file is covered by the GNU Lesser General Public License,
7 * which should be included with libxml++ as the file COPYING.
8 */
9
10#include <libxml++/io/istreamparserinputbuffer.h>
11
12namespace xmlpp
13{
14 IStreamParserInputBuffer::IStreamParserInputBuffer(
15 std::istream & input)
16 : ParserInputBuffer(), input_(input)
17 {
18 }
19
20 IStreamParserInputBuffer::~IStreamParserInputBuffer()
21 {
22 }
23
24 int IStreamParserInputBuffer::do_read(
25 char * buffer,
26 int len)
27 {
28 int l=0;
29 if(input_)
30 {
31 // This is the correct statement - but gcc 2.95.3 lacks this method
32 //l = input_.readsome(buffer, len);
33 input_.read(buffer, len);
34 l = input_.gcount();
35 }
36
37 return l;
38 }
39
40 bool IStreamParserInputBuffer::do_close()
41 {
42 return input_.good();
43 }
44}
045
=== added file 'src/libxml++/io/istreamparserinputbuffer.h'
--- src/libxml++/io/istreamparserinputbuffer.h 1970-01-01 00:00:00 +0000
+++ src/libxml++/io/istreamparserinputbuffer.h 2016-11-06 17:18:04 +0000
@@ -0,0 +1,36 @@
1/* inputstreamparserinputbuffer.h
2 * this file is part of libxml++
3 *
4 * copyright (C) 2003 by libxml++ developer's team
5 *
6 * this file is covered by the GNU Lesser General Public License,
7 * which should be included with libxml++ as the file COPYING.
8 */
9
10#ifndef __LIBXMLPP_ISTREAMPARSEROUTPUTBUFFER_H
11#define __LIBXMLPP_ISTREAMPARSEROUTPUTBUFFER_H
12
13#include <libxml++/io/parserinputbuffer.h>
14
15#include <istream>
16
17namespace xmlpp
18{
19 class IStreamParserInputBuffer: public ParserInputBuffer
20 {
21 public:
22 /**
23 * @param input The istream datas will be read from
24 */
25 IStreamParserInputBuffer(std::istream& input);
26 ~IStreamParserInputBuffer() override;
27
28 private:
29 int do_read(char * buffer, int len) override;
30 bool do_close() override;
31
32 std::istream& input_;
33 };
34}
35
36#endif
037
=== added file 'src/libxml++/io/parserinputbuffer.cc'
--- src/libxml++/io/parserinputbuffer.cc 1970-01-01 00:00:00 +0000
+++ src/libxml++/io/parserinputbuffer.cc 2016-11-06 17:18:04 +0000
@@ -0,0 +1,84 @@
1/* parserinputbuffer.cc
2 * this file is part of libxml++
3 *
4 * copyright (C) 2003 by libxml++ developer's team
5 *
6 * this file is covered by the GNU Lesser General Public License,
7 * which should be included with libxml++ as the file COPYING.
8 */
9
10#include <libxml++/io/parserinputbuffer.h>
11#include <libxml++/exceptions/internal_error.h>
12
13#include <libxml/globals.h> //Needed by libxml/xmlIO.h
14#include <libxml/xmlIO.h>
15
16namespace xmlpp
17{
18
19 struct ParserInputBufferCallback
20 {
21 static int on_read(void * context, char * buffer, int len)
22 {
23 auto tmp = static_cast<ParserInputBuffer*>(context);
24 return tmp->do_read(buffer, len);
25 }
26
27 static int on_close(void * context)
28 {
29 auto tmp = static_cast<ParserInputBuffer*>(context);
30 return tmp->do_close();
31 }
32 };
33
34
35 ParserInputBuffer::ParserInputBuffer()
36 {
37 impl_ = xmlParserInputBufferCreateIO(
38 &ParserInputBufferCallback::on_read,
39 &ParserInputBufferCallback::on_close,
40 static_cast<void*>(this),
41 XML_CHAR_ENCODING_NONE);
42 if (!impl_)
43 {
44 throw internal_error("Cannot initialise underlying xmlParserInputBuffer");
45 }
46 }
47
48 ParserInputBuffer::~ParserInputBuffer()
49 {
50 }
51
52 bool ParserInputBuffer::on_close()
53 {
54 bool result = do_close();
55 // the underlying structure is being freed by libxml, the pointer will soon be
56 // invalid.
57 impl_ = nullptr;
58
59 return result;
60 }
61
62 int ParserInputBuffer::on_read(
63 char * buffer,
64 int len)
65 {
66 return do_read(buffer, len);
67 }
68
69 bool ParserInputBuffer::do_close()
70 {
71 return true;
72 }
73
74 _xmlParserInputBuffer* ParserInputBuffer::cobj() noexcept
75 {
76 return impl_;
77 }
78
79 const _xmlParserInputBuffer* ParserInputBuffer::cobj() const noexcept
80 {
81 return impl_;
82 }
83
84}
085
=== added file 'src/libxml++/io/parserinputbuffer.h'
--- src/libxml++/io/parserinputbuffer.h 1970-01-01 00:00:00 +0000
+++ src/libxml++/io/parserinputbuffer.h 2016-11-06 17:18:04 +0000
@@ -0,0 +1,75 @@
1/* parserinputbuffer.h
2 * this file is part of libxml++
3 *
4 * copyright (C) 2003 by libxml++ developer's team
5 *
6 * this file is covered by the GNU Lesser General Public License,
7 * which should be included with libxml++ as the file COPYING.
8 */
9
10#ifndef __LIBXMLPP_PARSERINPUTBUFFER_H
11#define __LIBXMLPP_PARSERINPUTBUFFER_H
12
13#include <string>
14#include <libxml++/noncopyable.h>
15
16extern "C"
17{
18 struct _xmlParserInputBuffer;
19}
20
21namespace xmlpp
22{
23 struct ParserInputBufferCallback;
24
25 /** Base class for xmlParserInputBuffer wrapper
26 *
27 * It can be derived from to create a new output buffer.
28 * A child class has to override do_write(), and possibly
29 * do_close() if some actions are required before buffer closing.
30 */
31 class ParserInputBuffer: public NonCopyable
32 {
33 public:
34 ParserInputBuffer();
35 ~ParserInputBuffer() override;
36
37 public:
38 /** gives an access to the underlying libxml structure to the children
39 */
40 _xmlParserInputBuffer* cobj() noexcept;
41
42 /** gives an access to the underlying libxml structure to the children
43 */
44 const _xmlParserInputBuffer* cobj() const noexcept;
45
46 private:
47 int on_read(char * buffer, int len);
48 bool on_close();
49
50 /** Function called when some data are read from the buffer.
51 * @param buffer The datas encoded in the charset given to the constructor
52 * @param len bytes to read
53 * @return Number of bytes read
54 *
55 * This function MUST be overriden in derived classes.
56 */
57 virtual int do_read(char * buffer, int len) = 0;
58
59 /** Function called before closing the buffer.
60 * Derived classes should override it if some actions are required before
61 * closing the buffer, instead of doing them in the destructor.
62 */
63 virtual bool do_close();
64
65 /**
66 * Underlying libxml2 structure.
67 */
68 _xmlParserInputBuffer* impl_;
69
70 friend struct ParserInputBufferCallback;
71 };
72
73}
74
75#endif
076
=== added file 'src/libxml++/keepblanks.cc'
--- src/libxml++/keepblanks.cc 1970-01-01 00:00:00 +0000
+++ src/libxml++/keepblanks.cc 2016-11-06 17:18:04 +0000
@@ -0,0 +1,29 @@
1/* keepblanks.cc
2 * libxml++ and this file are
3 * copyright (C) 2003 by The libxml++ Development Team, and
4 * are covered by the GNU Lesser General Public License, which should be
5 * included with libxml++ as the file COPYING.
6 */
7
8#include <libxml++/keepblanks.h>
9
10#include <libxml/globals.h>
11
12namespace xmlpp
13{
14#if _MSC_VER == 1200 // detect MSVC 6.0
15 const bool KeepBlanks::Default = true;
16#endif
17
18 KeepBlanks::KeepBlanks(bool value) noexcept
19 {
20 oldIndentTreeOutput_ = xmlIndentTreeOutput;
21 oldKeepBlanksDefault_ = xmlKeepBlanksDefault( value?1:0 );
22 }
23
24 KeepBlanks::~KeepBlanks() noexcept
25 {
26 xmlKeepBlanksDefault(oldKeepBlanksDefault_);
27 xmlIndentTreeOutput = oldIndentTreeOutput_;
28 }
29}
030
=== added file 'src/libxml++/keepblanks.h'
--- src/libxml++/keepblanks.h 1970-01-01 00:00:00 +0000
+++ src/libxml++/keepblanks.h 2016-11-06 17:18:04 +0000
@@ -0,0 +1,35 @@
1/* keepblanks.h
2 * libxml++ and this file are
3 * copyright (C) 2003 by The libxml++ Development Team, and
4 * are covered by the GNU Lesser General Public License, which should be
5 * included with libxml++ as the file COPYING.
6 */
7
8#ifndef __LIBXMLPP_KEEPBLANKS_H
9#define __LIBXMLPP_KEEPBLANKS_H
10
11namespace xmlpp
12{
13 /** This class sets KeepBlanksDefault and IndentTreeOutput of libxmlpp
14 * and restores their initial values in its destructor. As a consequence
15 * the wanted setting is kept during instance lifetime.
16 */
17 class KeepBlanks {
18 public:
19#if _MSC_VER == 1200 // detect MSVC 6.0
20 static const bool Default;
21#else
22 static const bool Default = true;
23#endif
24
25 public:
26 KeepBlanks(bool value) noexcept;
27 ~KeepBlanks() noexcept;
28
29 private:
30 int oldKeepBlanksDefault_;
31 int oldIndentTreeOutput_;
32 };
33}
34
35#endif // __LIBXMLPP_KEEPBLANKS_H
036
=== added file 'src/libxml++/libxml++config.h'
--- src/libxml++/libxml++config.h 1970-01-01 00:00:00 +0000
+++ src/libxml++/libxml++config.h 2016-11-06 17:18:04 +0000
@@ -0,0 +1,26 @@
1/* libxml++config.h. Generated from libxml++config.h.in by configure. */
2#ifndef _LIBXMLPP_CONFIG_H
3#define _LIBXMLPP_CONFIG_H
4
5#include <glibmmconfig.h>
6
7/* Define to omit deprecated API from the library. */
8/* #undef LIBXMLXX_DISABLE_DEPRECATED */
9
10/* Defined if the C++ library supports std::exception_ptr. */
11#define LIBXMLXX_HAVE_EXCEPTION_PTR 1
12
13/* Major version number of libxml++. */
14#define LIBXMLXX_MAJOR_VERSION 3
15
16/* Minor version number of libxml++. */
17#define LIBXMLXX_MINOR_VERSION 0
18
19/* Micro version number of libxml++. */
20#define LIBXMLXX_MICRO_VERSION 0
21
22/* Create static library */
23#define LIBXMLPP_API
24
25#endif /* _LIBXMLPP_CONFIG_H */
26
027
=== added file 'src/libxml++/noncopyable.cc'
--- src/libxml++/noncopyable.cc 1970-01-01 00:00:00 +0000
+++ src/libxml++/noncopyable.cc 2016-11-06 17:18:04 +0000
@@ -0,0 +1,21 @@
1/* noncopyable.cc
2 * libxml++ and this file are
3 * copyright (C) 2000 by The libxml++ Development Team, and
4 * are covered by the GNU Lesser General Public License, which should be
5 * included with libxml++ as the file COPYING.
6 */
7
8#include <libxml++/noncopyable.h>
9
10namespace xmlpp
11{
12
13NonCopyable::NonCopyable() noexcept
14{
15}
16
17NonCopyable::~NonCopyable()
18{
19}
20
21} //namespace xmlpp
022
=== added file 'src/libxml++/noncopyable.h'
--- src/libxml++/noncopyable.h 1970-01-01 00:00:00 +0000
+++ src/libxml++/noncopyable.h 2016-11-06 17:18:04 +0000
@@ -0,0 +1,31 @@
1/* noncopyable.h
2 * libxml++ and this file are
3 * copyright (C) 2000 by The libxml++ Development Team, and
4 * are covered by the GNU Lesser General Public License, which should be
5 * included with libxml++ as the file COPYING.
6 */
7
8#ifndef __LIBXMLPP_NONCOPYABLE_H
9#define __LIBXMLPP_NONCOPYABLE_H
10
11namespace xmlpp
12{
13
14/** A base for classes which cannot be copied or moved.
15 */
16class NonCopyable
17{
18protected:
19 NonCopyable() noexcept;
20 virtual ~NonCopyable();
21
22 NonCopyable(const NonCopyable&) = delete;
23 NonCopyable& operator=(const NonCopyable&) = delete;
24 NonCopyable(NonCopyable&&) = delete;
25 NonCopyable& operator=(NonCopyable&&) = delete;
26};
27
28} // namespace xmlpp
29
30#endif //__LIBXMLPP_NONCOPYABLE_H
31
032
=== added directory 'src/libxml++/parsers'
=== added file 'src/libxml++/parsers/parser.cc'
--- src/libxml++/parsers/parser.cc 1970-01-01 00:00:00 +0000
+++ src/libxml++/parsers/parser.cc 2016-11-06 17:18:04 +0000
@@ -0,0 +1,365 @@
1/* parser.cc
2 * libxml++ and this file are copyright (C) 2000 by Ari Johnson, and
3 * are covered by the GNU Lesser General Public License, which should be
4 * included with libxml++ as the file COPYING.
5 */
6
7#include "libxml++/exceptions/wrapped_exception.h"
8#include "libxml++/parsers/parser.h"
9
10#include <libxml/parser.h>
11
12namespace xmlpp
13{
14
15struct Parser::Impl
16{
17 Impl()
18 :
19 throw_messages_(true), validate_(false), substitute_entities_(false),
20 include_default_attributes_(false), set_options_(0), clear_options_(0)
21 {}
22
23 // Built gradually - used in an exception at the end of parsing.
24 Glib::ustring parser_error_;
25 Glib::ustring parser_warning_;
26 Glib::ustring validate_error_;
27 Glib::ustring validate_warning_;
28
29 bool throw_messages_;
30 bool validate_;
31 bool substitute_entities_;
32 bool include_default_attributes_;
33 int set_options_;
34 int clear_options_;
35};
36
37Parser::Parser()
38: context_(nullptr), exception_(nullptr), pimpl_(new Impl)
39{
40}
41
42Parser::~Parser()
43{
44 release_underlying();
45}
46
47void Parser::set_validate(bool val) noexcept
48{
49 pimpl_->validate_ = val;
50}
51
52bool Parser::get_validate() const noexcept
53{
54 return pimpl_->validate_;
55}
56
57void Parser::set_substitute_entities(bool val) noexcept
58{
59 pimpl_->substitute_entities_ = val;
60}
61
62bool Parser::get_substitute_entities() const noexcept
63{
64 return pimpl_->substitute_entities_;
65}
66
67void Parser::set_throw_messages(bool val) noexcept
68{
69 pimpl_->throw_messages_ = val;
70}
71
72bool Parser::get_throw_messages() const noexcept
73{
74 return pimpl_->throw_messages_;
75}
76
77void Parser::set_include_default_attributes(bool val) noexcept
78{
79 pimpl_->include_default_attributes_ = val;
80}
81
82bool Parser::get_include_default_attributes() noexcept
83{
84 return pimpl_->include_default_attributes_;
85}
86
87void Parser::set_parser_options(int set_options, int clear_options) noexcept
88{
89 pimpl_->set_options_ = set_options;
90 pimpl_->clear_options_ = clear_options;
91}
92
93void Parser::get_parser_options(int& set_options, int& clear_options) noexcept
94{
95 set_options = pimpl_->set_options_;
96 clear_options = pimpl_->clear_options_;
97}
98
99void Parser::initialize_context()
100{
101 //Clear these temporary buffers:
102 pimpl_->parser_error_.erase();
103 pimpl_->parser_warning_.erase();
104 pimpl_->validate_error_.erase();
105 pimpl_->validate_warning_.erase();
106
107 //Disactivate any non-standards-compliant libxml1 features.
108 //These are disactivated by default, but if we don't deactivate them for each context
109 //then some other code which uses a global function, such as xmlKeepBlanksDefault(),
110 // could cause this to use the wrong settings:
111 context_->linenumbers = 1; // TRUE - This is the default anyway.
112
113 //Turn on/off validation, entity substitution and default attribute inclusion.
114 int options = context_->options;
115 if (pimpl_->validate_)
116 options |= XML_PARSE_DTDVALID;
117 else
118 options &= ~XML_PARSE_DTDVALID;
119
120 if (pimpl_->substitute_entities_)
121 options |= XML_PARSE_NOENT;
122 else
123 options &= ~XML_PARSE_NOENT;
124
125 if (pimpl_->include_default_attributes_)
126 options |= XML_PARSE_DTDATTR;
127 else
128 options &= ~XML_PARSE_DTDATTR;
129
130 //Turn on/off any parser options.
131 options |= pimpl_->set_options_;
132 options &= ~pimpl_->clear_options_;
133
134 xmlCtxtUseOptions(context_, options);
135
136 if (context_->sax && pimpl_->throw_messages_)
137 {
138 //Tell the parser context about the callbacks.
139 context_->sax->fatalError = &callback_parser_error;
140 context_->sax->error = &callback_parser_error;
141 context_->sax->warning = &callback_parser_warning;
142 }
143
144 if (pimpl_->throw_messages_)
145 {
146 //Tell the validity context about the callbacks:
147 //(These are only called if validation is on - see above)
148 context_->vctxt.error = &callback_validity_error;
149 context_->vctxt.warning = &callback_validity_warning;
150 }
151
152 //Allow callback_error_or_warning() to retrieve the C++ instance:
153 context_->_private = this;
154}
155
156void Parser::release_underlying()
157{
158 if(context_)
159 {
160 context_->_private = nullptr; //Not really necessary.
161
162 if( context_->myDoc != nullptr )
163 {
164 xmlFreeDoc(context_->myDoc);
165 }
166
167 xmlFreeParserCtxt(context_);
168 context_ = nullptr;
169 }
170}
171
172void Parser::on_parser_error(const Glib::ustring& message)
173{
174 //Throw an exception later when the whole message has been received:
175 pimpl_->parser_error_ += message;
176}
177
178void Parser::on_parser_warning(const Glib::ustring& message)
179{
180 //Throw an exception later when the whole message has been received:
181 pimpl_->parser_warning_ += message;
182}
183void Parser::on_validity_error(const Glib::ustring& message)
184{
185 //Throw an exception later when the whole message has been received:
186 pimpl_->validate_error_ += message;
187}
188
189void Parser::on_validity_warning(const Glib::ustring& message)
190{
191 //Throw an exception later when the whole message has been received:
192 pimpl_->validate_warning_ += message;
193}
194
195void Parser::check_for_error_and_warning_messages()
196{
197 Glib::ustring msg(exception_ ? exception_->what() : "");
198 bool parser_msg = false;
199 bool validity_msg = false;
200
201 if (!pimpl_->parser_error_.empty())
202 {
203 parser_msg = true;
204 msg += "\nParser error:\n" + pimpl_->parser_error_;
205 pimpl_->parser_error_.erase();
206 }
207
208 if (!pimpl_->parser_warning_.empty())
209 {
210 parser_msg = true;
211 msg += "\nParser warning:\n" + pimpl_->parser_warning_;
212 pimpl_->parser_warning_.erase();
213 }
214
215 if (!pimpl_->validate_error_.empty())
216 {
217 validity_msg = true;
218 msg += "\nValidity error:\n" + pimpl_->validate_error_;
219 pimpl_->validate_error_.erase();
220 }
221
222 if (!pimpl_->validate_warning_.empty())
223 {
224 validity_msg = true;
225 msg += "\nValidity warning:\n" + pimpl_->validate_warning_;
226 pimpl_->validate_warning_.erase();
227 }
228
229 if (validity_msg)
230 exception_.reset(new validity_error(msg));
231 else if (parser_msg)
232 exception_.reset(new parse_error(msg));
233}
234
235//static
236void Parser::callback_parser_error(void* ctx, const char* msg, ...)
237{
238 va_list var_args;
239 va_start(var_args, msg);
240 callback_error_or_warning(MsgType::ParserError, ctx, msg, var_args);
241 va_end(var_args);
242}
243
244//static
245void Parser::callback_parser_warning(void* ctx, const char* msg, ...)
246{
247 va_list var_args;
248 va_start(var_args, msg);
249 callback_error_or_warning(MsgType::ParserWarning, ctx, msg, var_args);
250 va_end(var_args);
251}
252
253//static
254void Parser::callback_validity_error(void* ctx, const char* msg, ...)
255{
256 va_list var_args;
257 va_start(var_args, msg);
258 callback_error_or_warning(MsgType::ValidityError, ctx, msg, var_args);
259 va_end(var_args);
260}
261
262//static
263void Parser::callback_validity_warning(void* ctx, const char* msg, ...)
264{
265 va_list var_args;
266 va_start(var_args, msg);
267 callback_error_or_warning(MsgType::ValidityWarning, ctx, msg, var_args);
268 va_end(var_args);
269}
270
271//static
272void Parser::callback_error_or_warning(MsgType msg_type, void* ctx,
273 const char* msg, va_list var_args)
274{
275 //See xmlHTMLValidityError() in xmllint.c in libxml for more about this:
276
277 auto context = (xmlParserCtxtPtr)ctx;
278 if(context)
279 {
280 auto parser = static_cast<Parser*>(context->_private);
281 if(parser)
282 {
283 auto ubuff = format_xml_error(&context->lastError);
284 if (ubuff.empty())
285 {
286 // Usually the result of formatting var_args with the format string msg
287 // is the same string as is stored in context->lastError.message.
288 // It's unnecessary to use msg and var_args, if format_xml_error()
289 // returns an error message (as it usually does).
290
291 //Convert the ... to a string:
292 ubuff = format_printf_message(msg, var_args);
293 }
294
295 try
296 {
297 switch (msg_type)
298 {
299 case MsgType::ParserError:
300 parser->on_parser_error(ubuff);
301 break;
302 case MsgType::ParserWarning:
303 parser->on_parser_warning(ubuff);
304 break;
305 case MsgType::ValidityError:
306 parser->on_validity_error(ubuff);
307 break;
308 case MsgType::ValidityWarning:
309 parser->on_validity_warning(ubuff);
310 break;
311 }
312 }
313 catch (...)
314 {
315 parser->handle_exception();
316 }
317 }
318 }
319}
320
321void Parser::handle_exception()
322{
323 try
324 {
325 throw; // Re-throw current exception
326 }
327 catch (const exception& e)
328 {
329 exception_.reset(e.clone());
330 }
331#ifdef LIBXMLXX_HAVE_EXCEPTION_PTR
332 catch (...)
333 {
334 exception_.reset(new wrapped_exception(std::current_exception()));
335 }
336#else
337 catch (const std::exception& e)
338 {
339 exception_.reset(new exception(e.what()));
340 }
341 catch (...)
342 {
343 exception_.reset(new exception("An exception was thrown that is not derived from std::exception or xmlpp::exception.\n"
344 "It could not be caught and rethrown because this platform does not support std::exception_ptr."));
345 }
346#endif
347
348 if (context_)
349 xmlStopParser(context_);
350
351 //release_underlying();
352}
353
354void Parser::check_for_exception()
355{
356 check_for_error_and_warning_messages();
357
358 if (exception_)
359 {
360 std::unique_ptr<exception> tmp(std::move(exception_));
361 tmp->raise();
362 }
363}
364
365} // namespace xmlpp
0366
=== added file 'src/libxml++/parsers/parser.h'
--- src/libxml++/parsers/parser.h 1970-01-01 00:00:00 +0000
+++ src/libxml++/parsers/parser.h 2016-11-06 17:18:04 +0000
@@ -0,0 +1,220 @@
1/* parser.h
2 * libxml++ and this file are copyright (C) 2000 by Ari Johnson, and
3 * are covered by the GNU Lesser General Public License, which should be
4 * included with libxml++ as the file COPYING.
5 */
6
7#ifndef __LIBXMLPP_PARSER_H
8#define __LIBXMLPP_PARSER_H
9
10#ifdef _MSC_VER //Ignore warnings about the Visual C++ Bug, where we can not do anything
11#pragma warning (disable : 4786)
12#endif
13
14#include <libxml++/noncopyable.h>
15#include <libxml++/exceptions/validity_error.h>
16#include <libxml++/exceptions/internal_error.h>
17
18#include <string>
19#include <istream>
20#include <cstdarg> // va_list
21#include <memory> // std::unique_ptr
22
23#ifndef DOXYGEN_SHOULD_SKIP_THIS
24extern "C" {
25 struct _xmlParserCtxt;
26}
27#endif //DOXYGEN_SHOULD_SKIP_THIS
28
29namespace xmlpp {
30
31/** XML parser.
32 *
33 * Abstract base class for DOM parser and SAX parser.
34 */
35class Parser : public NonCopyable
36{
37public:
38 Parser();
39 ~Parser() override;
40
41 using size_type = unsigned int;
42
43 /** By default, the parser will not validate the XML file.
44 * @param val Whether the document should be validated.
45 */
46 void set_validate(bool val = true) noexcept;
47
48 /** See set_validate().
49 * @returns Whether the parser will validate the XML file.
50 */
51 bool get_validate() const noexcept;
52
53 /** Set whether the parser will automatically substitute entity references with the text of the entities' definitions.
54 * For instance, this affects the text returned by ContentNode::get_content().
55 * By default, the parser will not substitute entities, so that you do not lose the entity reference information.
56 * @param val Whether entities will be substitued.
57 */
58 void set_substitute_entities(bool val = true) noexcept;
59
60 /** See set_substitute_entities().
61 * @returns Whether entities will be substituted during parsing.
62 */
63 bool get_substitute_entities() const noexcept;
64
65 /** Set whether the parser will collect and throw error and warning messages.
66 *
67 * If messages are collected, they are included in an exception thrown at the
68 * end of parsing.
69 *
70 * - DOM parser
71 *
72 * If the messages are not collected, they are written on stderr.
73 * The messages written on stderr are slightly different, and may be
74 * preferred in a program started from the command-line. The default, if
75 * set_throw_messages() is not called, is to collect and throw messages.
76 *
77 * - SAX parser
78 *
79 * If the messages are not collected, the error handling on_*() methods in
80 * the user's SAX parser subclass are called. This is the default, if
81 * set_throw_messages() is not called.
82 *
83 * @newin{2,36}
84 *
85 * @param val Whether messages will be collected and thrown in an exception.
86 */
87 void set_throw_messages(bool val = true) noexcept;
88
89 /** See set_throw_messages().
90 *
91 * @newin{2,36}
92 *
93 * @returns Whether messages will be collected and thrown in an exception.
94 */
95 bool get_throw_messages() const noexcept;
96
97 /** Set whether default attribute values from the DTD shall be included in the node tree.
98 * If set, attributes not assigned a value in the XML file, but with a default value
99 * in the DTD file, will be included in the node tree that the parser creates.
100 * These attributes will be represented by AttributeNode instances (not AttributeDeclaration
101 * instances), just like attributes which are assigned a value in the XML file.
102 *
103 * @newin{2,38}
104 *
105 * @param val Whether attributes with default values will be included in the node tree.
106 */
107 void set_include_default_attributes(bool val = true) noexcept;
108
109 /** See set_include_default_attributes().
110 *
111 * @newin{2,38}
112 *
113 * @returns Whether attributes with default values will be included in the node tree.
114 */
115 bool get_include_default_attributes() noexcept;
116
117 /** Set and/or clear parser option flags.
118 * See the libxml2 documentation, enum xmlParserOption, for a list of parser options.
119 * This method overrides other methods that set parser options, such as set_validate(),
120 * set_substitute_entities() and set_include_default_attributes(). Use set_parser_options()
121 * only if no other method can set the parser options you want.
122 *
123 * @newin{2,38}
124 *
125 * @param set_options Set bits correspond to flags that shall be set during parsing.
126 * @param clear_options Set bits correspond to flags that shall be cleared during parsing.
127 * Bits that are set in neither @a set_options nor @a clear_options are not affected.
128 */
129 void set_parser_options(int set_options = 0, int clear_options = 0) noexcept;
130
131 /** See set_parser_options().
132 *
133 * @newin{2,38}
134 *
135 * @param [out] set_options Set bits correspond to flags that shall be set during parsing.
136 * @param [out] clear_options Set bits correspond to flags that shall be cleared during parsing.
137 * Bits that are set in neither @a set_options nor @a clear_options are not affected.
138 */
139 void get_parser_options(int& set_options, int& clear_options) noexcept;
140
141 /** Parse an XML document from a file.
142 * @throw exception
143 * @param filename The path to the file.
144 */
145 virtual void parse_file(const std::string& filename) = 0;
146
147 /** Parse an XML document from raw memory.
148 * @throw exception
149 * @param contents The XML document as an array of bytes.
150 * @param bytes_count The number of bytes in the @a contents array.
151 */
152 virtual void parse_memory_raw(const unsigned char* contents, size_type bytes_count) = 0;
153
154 /** Parse an XML document from a string.
155 * @throw exception
156 * @param contents The XML document as a string.
157 */
158 virtual void parse_memory(const Glib::ustring& contents) = 0;
159
160 /** Parse an XML document from a stream.
161 * @throw exception
162 * @param in The stream.
163 */
164 virtual void parse_stream(std::istream& in) = 0;
165
166 //TODO: Add stop_parser()/stop_parsing(), wrapping xmlStopParser()?
167
168protected:
169 virtual void initialize_context();
170 virtual void release_underlying();
171
172 virtual void on_parser_error(const Glib::ustring& message);
173 virtual void on_parser_warning(const Glib::ustring& message);
174 virtual void on_validity_error(const Glib::ustring& message);
175 virtual void on_validity_warning(const Glib::ustring& message);
176
177 /// To be called in an exception handler.
178 virtual void handle_exception();
179 virtual void check_for_exception();
180
181 virtual void check_for_error_and_warning_messages();
182
183 static void callback_parser_error(void* ctx, const char* msg, ...);
184 static void callback_parser_warning(void* ctx, const char* msg, ...);
185 static void callback_validity_error(void* ctx, const char* msg, ...);
186 static void callback_validity_warning(void* ctx, const char* msg, ...);
187
188 enum class MsgType
189 {
190 ParserError,
191 ParserWarning,
192 ValidityError,
193 ValidityWarning
194 };
195
196 static void callback_error_or_warning(MsgType msg_type, void* ctx,
197 const char* msg, va_list var_args);
198
199 _xmlParserCtxt* context_;
200 std::unique_ptr<exception> exception_;
201
202private:
203 struct Impl;
204 std::unique_ptr<Impl> pimpl_;
205};
206
207/** Equivalent to Parser::parse_stream().
208 *
209 * @newin{2,38}
210 */
211inline std::istream& operator>>(std::istream& in, Parser& parser)
212{
213 parser.parse_stream(in);
214 return in;
215}
216
217} // namespace xmlpp
218
219#endif //__LIBXMLPP_PARSER_H
220
0221
=== added file 'src/libxml++/parsers/saxparser.cc'
--- src/libxml++/parsers/saxparser.cc 1970-01-01 00:00:00 +0000
+++ src/libxml++/parsers/saxparser.cc 2016-11-06 17:18:04 +0000
@@ -0,0 +1,711 @@
1/* saxparser.cc
2 * libxml++ and this file are copyright (C) 2000 by Ari Johnson, and
3 * are covered by the GNU Lesser General Public License, which should be
4 * included with libxml++ as the file COPYING.
5 *
6 * 2002/01/05 Valentin Rusu - fixed some potential buffer overruns
7 * 2002/01/21 Valentin Rusu - added CDATA handlers
8 */
9
10#include "libxml++/parsers/saxparser.h"
11#include "libxml++/keepblanks.h"
12
13#include <libxml/parser.h>
14#include <libxml/parserInternals.h> // for xmlCreateFileParserCtxt
15
16#include <cstdarg> //For va_list.
17#include <iostream>
18
19namespace xmlpp {
20
21struct SaxParserCallback
22{
23 static xmlEntityPtr get_entity(void* context, const xmlChar* name);
24 static void entity_decl(void* context, const xmlChar* name, int type, const xmlChar* publicId, const xmlChar* systemId, xmlChar* content);
25 static void start_document(void* context);
26 static void end_document(void* context);
27 static void start_element(void* context, const xmlChar* name, const xmlChar** p);
28 static void end_element(void* context, const xmlChar* name);
29 static void start_element_ns(void *context, const xmlChar *name, const xmlChar *prefix, const xmlChar *URI, int nb_namespaces,
30 const xmlChar **namespaces, int nb_attributes, int nb_defaulted, const xmlChar **attributes);
31 static void end_element_ns(void *context, const xmlChar *name, const xmlChar *prefix, const xmlChar *URI);
32 static void characters(void* context, const xmlChar* ch, int len);
33 static void comment(void* context, const xmlChar* value);
34 static void processing_instruction(void* context, const xmlChar* target, const xmlChar* data);
35 static void warning(void* context, const char* fmt, ...);
36 static void error(void* context, const char* fmt, ...);
37 static void fatal_error(void* context, const char* fmt, ...);
38 static void cdata_block(void* context, const xmlChar* value, int len);
39 static void internal_subset(void* context, const xmlChar* name, const xmlChar*publicId, const xmlChar*systemId);
40};
41
42
43
44SaxParser::SaxParser(bool use_get_entity)
45 : sax_handler_(new _xmlSAXHandler), entity_resolver_doc_(new Document)
46{
47 xmlSAXHandler temp = {
48 SaxParserCallback::internal_subset,
49 nullptr, // isStandalone
50 nullptr, // hasInternalSubset
51 nullptr, // hasExternalSubset
52 nullptr, // resolveEntity
53 use_get_entity ? SaxParserCallback::get_entity : nullptr, // getEntity
54 SaxParserCallback::entity_decl, // entityDecl
55 nullptr, // notationDecl
56 nullptr, // attributeDecl
57 nullptr, // elementDecl
58 nullptr, // unparsedEntityDecl
59 nullptr, // setDocumentLocator
60 SaxParserCallback::start_document, // startDocument
61 SaxParserCallback::end_document, // endDocument
62 SaxParserCallback::start_element, // startElement
63 SaxParserCallback::end_element, // endElement
64 nullptr, // reference
65 SaxParserCallback::characters, // characters
66 nullptr, // ignorableWhitespace
67 SaxParserCallback::processing_instruction, // processingInstruction
68 SaxParserCallback::comment, // comment
69 SaxParserCallback::warning, // warning
70 SaxParserCallback::error, // error
71 SaxParserCallback::fatal_error, // fatalError
72 nullptr, // getParameterEntity
73 SaxParserCallback::cdata_block, // cdataBlock
74 nullptr, // externalSubset
75 XML_SAX2_MAGIC, // initialized
76 nullptr, // private
77 SaxParserCallback::start_element_ns, // startElementNs
78 SaxParserCallback::end_element_ns, // endElementNs
79 nullptr, // serror
80 };
81 *sax_handler_ = temp;
82
83 // The default action is to call on_warning(), on_error(), on_fatal_error().
84 set_throw_messages(false);
85}
86
87SaxParser::~SaxParser()
88{
89 release_underlying();
90}
91
92xmlEntityPtr SaxParser::on_get_entity(const Glib::ustring& name)
93{
94 return entity_resolver_doc_->get_entity(name);
95}
96
97void SaxParser::on_entity_declaration(const Glib::ustring& name, XmlEntityType type, const Glib::ustring& publicId, const Glib::ustring& systemId, const Glib::ustring& content)
98{
99 entity_resolver_doc_->set_entity_declaration(name, type, publicId, systemId, content);
100}
101
102void SaxParser::on_start_document()
103{
104}
105
106void SaxParser::on_end_document()
107{
108}
109
110void SaxParser::on_start_element(const Glib::ustring& /* name */, const AttributeList& /* attributes */)
111{
112}
113
114void SaxParser::on_end_element(const Glib::ustring& /* name */)
115{
116}
117
118void SaxParser::on_start_element_ns(const Glib::ustring& /* name */, const Glib::ustring& /* prefix */, const Glib::ustring& /* uri */, const NamespaceList& /* namespaces */, const AttributeList& /* attributes */)
119{
120}
121
122void SaxParser::on_end_element_ns(const Glib::ustring& /* name */, const Glib::ustring& /* prefix */, const Glib::ustring& /* uri */)
123{
124}
125
126void SaxParser::on_characters(const Glib::ustring& /* text */)
127{
128}
129
130void SaxParser::on_comment(const Glib::ustring& /* text */)
131{
132}
133
134void SaxParser::on_processing_instruction(const Glib::ustring &target, const Glib::ustring &data)
135{
136}
137
138void SaxParser::on_warning(const Glib::ustring& /* text */)
139{
140}
141
142void SaxParser::on_error(const Glib::ustring& /* text */)
143{
144}
145
146void SaxParser::on_fatal_error(const Glib::ustring& text)
147{
148 throw parse_error("Fatal error: " + text);
149}
150
151void SaxParser::on_cdata_block(const Glib::ustring& /* text */)
152{
153}
154
155void SaxParser::on_internal_subset(const Glib::ustring& name,
156 const Glib::ustring& publicId,
157 const Glib::ustring& systemId)
158{
159 entity_resolver_doc_->set_internal_subset(name, publicId, systemId);
160}
161
162// implementation of this function is inspired by the SAX documentation by James Henstridge.
163// (http://www.daa.com.au/~james/gnome/xml-sax/implementing.html)
164void SaxParser::parse()
165{
166 if(!context_)
167 {
168 throw internal_error("Parser context not created.");
169 }
170
171 auto old_sax = context_->sax;
172 context_->sax = sax_handler_.get();
173
174 xmlResetLastError();
175 initialize_context();
176
177 const int parseError = xmlParseDocument(context_);
178
179 context_->sax = old_sax;
180
181 auto error_str = format_xml_parser_error(context_);
182 if (error_str.empty() && parseError == -1)
183 error_str = "xmlParseDocument() failed.";
184
185 release_underlying(); // Free context_
186
187 check_for_exception();
188
189 if(!error_str.empty())
190 {
191 throw parse_error(error_str);
192 }
193}
194
195void SaxParser::parse_file(const std::string& filename)
196{
197 if(context_)
198 {
199 throw parse_error("Attempt to start a second parse while a parse is in progress.");
200 }
201
202 KeepBlanks k(KeepBlanks::Default);
203
204 context_ = xmlCreateFileParserCtxt(filename.c_str());
205 parse();
206}
207
208void SaxParser::parse_memory_raw(const unsigned char* contents, size_type bytes_count)
209{
210 if(context_)
211 {
212 throw parse_error("Attempt to start a second parse while a parse is in progress.");
213 }
214
215 KeepBlanks k(KeepBlanks::Default);
216
217 context_ = xmlCreateMemoryParserCtxt((const char*)contents, bytes_count);
218 parse();
219}
220
221void SaxParser::parse_memory(const Glib::ustring& contents)
222{
223 parse_memory_raw((const unsigned char*)contents.c_str(), contents.bytes());
224}
225
226void SaxParser::parse_stream(std::istream& in)
227{
228 if(context_)
229 {
230 throw parse_error("Attempt to start a second parse while a parse is in progress.");
231 }
232
233 KeepBlanks k(KeepBlanks::Default);
234 xmlResetLastError();
235
236 context_ = xmlCreatePushParserCtxt(
237 sax_handler_.get(),
238 nullptr, // user_data
239 nullptr, // chunk
240 0, // size
241 nullptr); // no filename for fetching external entities
242
243 if(!context_)
244 {
245 throw internal_error("Could not create parser context\n" + format_xml_error());
246 }
247
248 initialize_context();
249
250 // std::string or Glib::ustring?
251 // Output from the XML parser is UTF-8 encoded.
252 // But the istream "in" is input, i.e. an XML file. It can use any encoding.
253 // If it's not UTF-8, the file itself must contain information about which
254 // encoding it uses. See the XML specification. Thus use std::string.
255 int firstParseError = XML_ERR_OK;
256 std::string line;
257 while (!exception_ && std::getline(in, line))
258 {
259 // since getline does not get the line separator, we have to add it since the parser care
260 // about layout in certain cases.
261 line += '\n';
262
263 const int parseError = xmlParseChunk(context_, line.c_str(),
264 line.size() /* This is a std::string, not a ustring, so this is the number of bytes. */,
265 0 /* don't terminate */);
266
267 // Save the first error code if any, but read on.
268 // More errors might be reported and then thrown by check_for_exception().
269 if (parseError != XML_ERR_OK && firstParseError == XML_ERR_OK)
270 firstParseError = parseError;
271 }
272
273 if (!exception_)
274 {
275 //This is called just to terminate parsing.
276 const int parseError = xmlParseChunk(context_, nullptr /* chunk */, 0 /* size */, 1 /* terminate (1 or 0) */);
277
278 if (parseError != XML_ERR_OK && firstParseError == XML_ERR_OK)
279 firstParseError = parseError;
280 }
281
282 auto error_str = format_xml_parser_error(context_);
283 if (error_str.empty() && firstParseError != XML_ERR_OK)
284 error_str = "Error code from xmlParseChunk(): " + Glib::ustring::format(firstParseError);
285
286 release_underlying(); // Free context_
287
288 check_for_exception();
289
290 if(!error_str.empty())
291 {
292 throw parse_error(error_str);
293 }
294}
295
296void SaxParser::parse_chunk(const Glib::ustring& chunk)
297{
298 parse_chunk_raw((const unsigned char*)chunk.c_str(), chunk.bytes());
299}
300
301void SaxParser::parse_chunk_raw(const unsigned char* contents, size_type bytes_count)
302{
303 KeepBlanks k(KeepBlanks::Default);
304 xmlResetLastError();
305
306 if(!context_)
307 {
308 context_ = xmlCreatePushParserCtxt(
309 sax_handler_.get(),
310 nullptr, // user_data
311 nullptr, // chunk
312 0, // size
313 nullptr); // no filename for fetching external entities
314
315 if(!context_)
316 {
317 throw internal_error("Could not create parser context\n" + format_xml_error());
318 }
319 initialize_context();
320 }
321 else
322 xmlCtxtResetLastError(context_);
323
324 int parseError = XML_ERR_OK;
325 if (!exception_)
326 parseError = xmlParseChunk(context_, (const char*)contents, bytes_count, 0 /* don't terminate */);
327
328 check_for_exception();
329
330 auto error_str = format_xml_parser_error(context_);
331 if (error_str.empty() && parseError != XML_ERR_OK)
332 error_str = "Error code from xmlParseChunk(): " + Glib::ustring::format(parseError);
333 if(!error_str.empty())
334 {
335 throw parse_error(error_str);
336 }
337}
338
339void SaxParser::finish_chunk_parsing()
340{
341 xmlResetLastError();
342 if(!context_)
343 {
344 context_ = xmlCreatePushParserCtxt(
345 sax_handler_.get(),
346 nullptr, // user_data
347 nullptr, // chunk
348 0, // size
349 nullptr); // no filename for fetching external entities
350
351 if(!context_)
352 {
353 throw internal_error("Could not create parser context\n" + format_xml_error());
354 }
355 initialize_context();
356 }
357 else
358 xmlCtxtResetLastError(context_);
359
360 int parseError = XML_ERR_OK;
361 if (!exception_)
362 //This is called just to terminate parsing.
363 parseError = xmlParseChunk(context_, nullptr /* chunk */, 0 /* size */, 1 /* terminate (1 or 0) */);
364
365 auto error_str = format_xml_parser_error(context_);
366 if (error_str.empty() && parseError != XML_ERR_OK)
367 error_str = "Error code from xmlParseChunk(): " + Glib::ustring::format(parseError);
368
369 release_underlying(); // Free context_
370
371 check_for_exception();
372
373 if(!error_str.empty())
374 {
375 throw parse_error(error_str);
376 }
377}
378
379void SaxParser::release_underlying()
380{
381 Parser::release_underlying();
382}
383
384void SaxParser::initialize_context()
385{
386 Parser::initialize_context();
387 // Start with an empty Document for entity resolution.
388 entity_resolver_doc_.reset(new Document);
389}
390
391xmlEntityPtr SaxParserCallback::get_entity(void* context, const xmlChar* name)
392{
393 auto the_context = static_cast<_xmlParserCtxt*>(context);
394 auto parser = static_cast<SaxParser*>(the_context->_private);
395 xmlEntityPtr result = nullptr;
396
397 try
398 {
399 result = parser->on_get_entity((const char*)name);
400 }
401 catch (...)
402 {
403 parser->handle_exception();
404 }
405
406 return result;
407}
408
409void SaxParserCallback::entity_decl(void* context, const xmlChar* name, int type, const xmlChar* publicId, const xmlChar* systemId, xmlChar* content)
410{
411 auto the_context = static_cast<_xmlParserCtxt*>(context);
412 auto parser = static_cast<SaxParser*>(the_context->_private);
413
414 try
415 {
416 parser->on_entity_declaration(
417 ( name ? Glib::ustring((const char*)name) : ""),
418 static_cast<XmlEntityType>(type),
419 ( publicId ? Glib::ustring((const char*)publicId) : ""),
420 ( systemId ? Glib::ustring((const char*)systemId) : ""),
421 ( content ? Glib::ustring((const char*)content) : "") );
422 }
423 catch (...)
424 {
425 parser->handle_exception();
426 }
427}
428
429void SaxParserCallback::start_document(void* context)
430{
431 auto the_context = static_cast<_xmlParserCtxt*>(context);
432 auto parser = static_cast<SaxParser*>(the_context->_private);
433
434 try
435 {
436 parser->on_start_document();
437 }
438 catch (...)
439 {
440 parser->handle_exception();
441 }
442}
443
444void SaxParserCallback::end_document(void* context)
445{
446 auto the_context = static_cast<_xmlParserCtxt*>(context);
447 auto parser = static_cast<SaxParser*>(the_context->_private);
448
449 if (parser->exception_)
450 return;
451
452 try
453 {
454 parser->on_end_document();
455 }
456 catch (...)
457 {
458 parser->handle_exception();
459 }
460}
461
462void SaxParserCallback::start_element(void* context,
463 const xmlChar* name,
464 const xmlChar** p)
465{
466 auto the_context = static_cast<_xmlParserCtxt*>(context);
467 auto parser = static_cast<SaxParser*>(the_context->_private);
468
469 SaxParser::AttributeList attributes;
470
471 if(p)
472 for(const xmlChar** cur = p; cur && *cur; cur += 2)
473 attributes.push_back(
474 SaxParser::Attribute( (char*)*cur, (char*)*(cur + 1) ));
475
476 try
477 {
478 parser->on_start_element(Glib::ustring((const char*) name), attributes);
479 }
480 catch (...)
481 {
482 parser->handle_exception();
483 }
484}
485
486void SaxParserCallback::end_element(void* context, const xmlChar* name)
487{
488 auto the_context = static_cast<_xmlParserCtxt*>(context);
489 auto parser = static_cast<SaxParser*>(the_context->_private);
490
491 try
492 {
493 parser->on_end_element(Glib::ustring((const char*) name));
494 }
495 catch (...)
496 {
497 parser->handle_exception();
498 }
499}
500
501void SaxParserCallback::start_element_ns(void *context, const xmlChar *name, const xmlChar *prefix, const xmlChar *URI,
502 int nb_namespaces, const xmlChar **namespaces, int nb_attributes,
503 int nb_defaulted, const xmlChar **attributes)
504{
505 auto the_context = static_cast<_xmlParserCtxt*>(context);
506 auto parser = static_cast<SaxParser*>(the_context->_private);
507
508 SaxParser::AttributeList attrs;
509 SaxParser::NamespaceList nss;
510 try
511 {
512 const auto pref = prefix ? Glib::ustring((const char*) prefix) : "";
513 const auto uri = URI ? Glib::ustring((const char*) URI) : "";
514 for (int i = 0; i < nb_namespaces; ++i)
515 {
516 const auto p = namespaces[i * 2] ? Glib::ustring((const char*) namespaces[i * 2]) : "";
517 const auto u = namespaces[i * 2 + 1] ? Glib::ustring((const char*) namespaces[i * 2 + 1]) : "";
518 nss.push_back(SaxParser::Namespace(p, u));
519 }
520
521 unsigned int index = 0;
522 for (int ia = 0; ia < nb_attributes; ++ia, index += 5 )
523 {
524 const auto attrName = attributes[index] ? Glib::ustring((const char*) attributes[index]) : "";
525 const auto attrPrefix = attributes[index + 1] ? Glib::ustring((const char*) attributes[index + 1]) : "";
526 const auto attrUri = attributes[index + 2] ? Glib::ustring((const char*) attributes[index + 2]) : "";
527 const auto attrValueBegin = attributes[index + 3];
528 const auto attrValueEnd = attributes[index + 4];
529 Glib::ustring value((const char *)attrValueBegin, (const char *)attrValueEnd);
530 attrs.push_back(SaxParser::Attribute(attrName, value, attrPrefix, attrUri));
531 }
532 parser->on_start_element_ns(Glib::ustring((const char *) name), pref, uri, nss, attrs);
533 }
534 catch (...)
535 {
536 parser->handle_exception();
537 }
538}
539
540void SaxParserCallback::end_element_ns(void *context, const xmlChar *name, const xmlChar *prefix, const xmlChar *URI)
541{
542 auto the_context = static_cast<_xmlParserCtxt*>(context);
543 auto parser = static_cast<SaxParser*>(the_context->_private);
544
545 try
546 {
547 const auto pref = prefix ? Glib::ustring((const char*) prefix) : "";
548 const auto uri = URI ? Glib::ustring((const char*) URI) : "";
549
550 parser->on_end_element_ns(Glib::ustring((const char*) name), pref, uri);
551 }
552 catch (...)
553 {
554 parser->handle_exception();
555 }
556}
557
558void SaxParserCallback::characters(void * context, const xmlChar* ch, int len)
559{
560 auto the_context = static_cast<_xmlParserCtxt*>(context);
561 auto parser = static_cast<SaxParser*>(the_context->_private);
562
563 try
564 {
565 // Here we force the use of Glib::ustring::ustring( InputIterator begin, InputIterator end )
566 // instead of Glib::ustring::ustring( const char*, size_type ) because it
567 // expects the length of the string in characters, not in bytes.
568 parser->on_characters(
569 Glib::ustring(
570 reinterpret_cast<const char *>(ch),
571 reinterpret_cast<const char *>(ch + len) ) );
572 }
573 catch (...)
574 {
575 parser->handle_exception();
576 }
577}
578
579void SaxParserCallback::comment(void* context, const xmlChar* value)
580{
581 auto the_context = static_cast<_xmlParserCtxt*>(context);
582 auto parser = static_cast<SaxParser*>(the_context->_private);
583
584 try
585 {
586 parser->on_comment(Glib::ustring((const char*) value));
587 }
588 catch (...)
589 {
590 parser->handle_exception();
591 }
592}
593
594void SaxParserCallback::warning(void* context, const char* fmt, ...)
595{
596 auto the_context = static_cast<_xmlParserCtxt*>(context);
597 auto parser = static_cast<SaxParser*>(the_context->_private);
598
599 va_list arg;
600 va_start(arg, fmt);
601 const Glib::ustring buff = format_printf_message(fmt, arg);
602 va_end(arg);
603
604 try
605 {
606 parser->on_warning(buff);
607 }
608 catch (...)
609 {
610 parser->handle_exception();
611 }
612}
613
614void SaxParserCallback::error(void* context, const char* fmt, ...)
615{
616 auto the_context = static_cast<_xmlParserCtxt*>(context);
617 auto parser = static_cast<SaxParser*>(the_context->_private);
618
619 if (parser->exception_)
620 return;
621
622 va_list arg;
623 va_start(arg, fmt);
624 const Glib::ustring buff = format_printf_message(fmt, arg);
625 va_end(arg);
626
627 try
628 {
629 parser->on_error(buff);
630 }
631 catch (...)
632 {
633 parser->handle_exception();
634 }
635}
636
637void SaxParserCallback::fatal_error(void* context, const char* fmt, ...)
638{
639 auto the_context = static_cast<_xmlParserCtxt*>(context);
640 auto parser = static_cast<SaxParser*>(the_context->_private);
641
642 va_list arg;
643 va_start(arg, fmt);
644 const Glib::ustring buff = format_printf_message(fmt, arg);
645 va_end(arg);
646
647 try
648 {
649 parser->on_fatal_error(buff);
650 }
651 catch (...)
652 {
653 parser->handle_exception();
654 }
655}
656
657void SaxParserCallback::cdata_block(void* context, const xmlChar* value, int len)
658{
659 auto the_context = static_cast<_xmlParserCtxt*>(context);
660 auto parser = static_cast<SaxParser*>(the_context->_private);
661
662 try
663 {
664 // Here we force the use of Glib::ustring::ustring( InputIterator begin, InputIterator end )
665 // see comments in SaxParserCallback::characters
666 parser->on_cdata_block(
667 Glib::ustring(
668 reinterpret_cast<const char *>(value),
669 reinterpret_cast<const char *>(value + len) ) );
670 }
671 catch (...)
672 {
673 parser->handle_exception();
674 }
675}
676
677void SaxParserCallback::internal_subset(void* context, const xmlChar* name,
678 const xmlChar* publicId, const xmlChar* systemId)
679{
680 auto the_context = static_cast<_xmlParserCtxt*>(context);
681 auto parser = static_cast<SaxParser*>(the_context->_private);
682
683 try
684 {
685 const auto pid = publicId ? Glib::ustring((const char*) publicId) : "";
686 const auto sid = systemId ? Glib::ustring((const char*) systemId) : "";
687
688 parser->on_internal_subset( Glib::ustring((const char*) name), pid, sid);
689 }
690 catch (...)
691 {
692 parser->handle_exception();
693 }
694}
695
696void SaxParserCallback::processing_instruction(void *context, const xmlChar *target, const xmlChar *data)
697{
698 auto the_context = static_cast<_xmlParserCtxt*>(context);
699 auto parser = static_cast<SaxParser*>(the_context->_private);
700
701 try
702 {
703 parser->on_processing_instruction(Glib::ustring((const char*) target), Glib::ustring((const char*) data));
704 }
705 catch (...)
706 {
707 parser->handle_exception();
708 }
709}
710
711} // namespace xmlpp
0712
=== added file 'src/libxml++/parsers/saxparser.h'
--- src/libxml++/parsers/saxparser.h 1970-01-01 00:00:00 +0000
+++ src/libxml++/parsers/saxparser.h 2016-11-06 17:18:04 +0000
@@ -0,0 +1,261 @@
1/* saxparser.h
2 * libxml++ and this file are copyright (C) 2000 by Ari Johnson, and
3 * are covered by the GNU Lesser General Public License, which should be
4 * included with libxml++ as the file COPYING.
5 */
6
7#ifndef __LIBXMLPP_PARSERS_SAXPARSER_H
8#define __LIBXMLPP_PARSERS_SAXPARSER_H
9
10#include <libxml++/parsers/parser.h>
11
12#include <deque>
13#include <memory>
14#include "libxml++/document.h"
15
16#ifndef DOXYGEN_SHOULD_SKIP_THIS
17extern "C" {
18 struct _xmlSAXHandler;
19 struct _xmlEntity;
20}
21#endif //DOXYGEN_SHOULD_SKIP_THIS
22
23namespace xmlpp {
24
25/** SAX XML parser.
26 * Derive your own class and override the on_*() methods.
27 * SAX = Simple API for XML
28 *
29 * In a system that does not support std::exception_ptr: If an overridden on_*()
30 * method throws an exception which is not derived from xmlpp::exception,
31 * that exception is replaced by a xmlpp::exception before it is propagated
32 * out of the parse method, such as parse_file().
33 */
34class SaxParser : public Parser
35{
36public:
37 /**
38 * Simple structure used in the start_element callbacks, in which
39 * the namespaces are a list of prefix/uri pairs.
40 */
41 struct Namespace
42 {
43 Glib::ustring prefix;
44 Glib::ustring uri;
45
46 Namespace()
47 {
48 }
49
50 Namespace(Glib::ustring const & p, Glib::ustring const & u)
51 : prefix(p), uri(u)
52 {
53 }
54 };
55 /**
56 * Simple structure used in the start_element callbacks, in which
57 * the attributes are a list of name/value/namespace tuples.
58 */
59 struct Attribute
60 {
61 Glib::ustring name;
62 Glib::ustring value;
63 Namespace ns;
64
65 Attribute(Glib::ustring const & n, Glib::ustring const & v)
66 : name(n), value(v)
67 {
68 }
69
70 Attribute(Glib::ustring const & n, Glib::ustring const & v, Glib::ustring const & p, Glib::ustring const & u)
71 : name(n), value(v), ns(Namespace(p, u))
72 {
73 }
74 };
75
76 using AttributeList = std::deque<Attribute>;
77 using NamespaceList = std::deque<Namespace>;
78
79 /** This functor is a helper to find an attribute by name in an
80 * AttributeList using the standard algorithm std::find_if
81 *
82 * Example:@n
83 * <code>
84 * Glib::ustring name = "foo";@n
85 * AttributeList::const_iterator attribute = std::find_if(attributes.begin(), attributes.end(), AttributeHasName(name));
86 * </code>
87 */
88 struct AttributeHasName
89 {
90 Glib::ustring const & name;
91
92 AttributeHasName(Glib::ustring const & n)
93 : name(n)
94 {
95 }
96
97 bool operator()(Attribute const & attribute)
98 {
99 return attribute.name == name;
100 }
101 };
102
103 /**
104 * @param use_get_entity Set this to true if you will override on_get_entity().
105 * In theory, if you do not override on_get_entity() the parser should behave exactly the same
106 * whether you use true or false here. But the default implementation of on_get_entity(), needed
107 * if you override on_get_entity() might not have the same behaviour as the underlying default
108 * behaviour of libxml, so the libxml implementation is the default here.
109 */
110 SaxParser(bool use_get_entity = false);
111 ~SaxParser() override;
112
113 /** Parse an XML document from a file.
114 * @param filename The path to the file.
115 * @throws xmlpp::internal_error
116 * @throws xmlpp::parse_error
117 * @throws xmlpp::validity_error
118 */
119 void parse_file(const std::string& filename) override;
120
121 /** Parse an XML document from a string.
122 * @param contents The XML document as a string.
123 * @throws xmlpp::internal_error
124 * @throws xmlpp::parse_error
125 * @throws xmlpp::validity_error
126 */
127 void parse_memory(const Glib::ustring& contents) override;
128
129 /** Parse an XML document from raw memory.
130 * @param contents The XML document as an array of bytes.
131 * @param bytes_count The number of bytes in the @a contents array.
132 * @throws xmlpp::internal_error
133 * @throws xmlpp::parse_error
134 * @throws xmlpp::validity_error
135 */
136 void parse_memory_raw(const unsigned char* contents, size_type bytes_count) override;
137
138 /** Parse an XML document from a stream.
139 * @param in The stream.
140 * @throws xmlpp::internal_error
141 * @throws xmlpp::parse_error
142 * @throws xmlpp::validity_error
143 */
144 void parse_stream(std::istream& in) override;
145
146 /** Parse a chunk of data.
147 *
148 * This lets you pass a document in small chunks, e.g. from a network
149 * connection. The on_* virtual functions are called each time the chunks
150 * provide enough information to advance the parser.
151 *
152 * The first call to parse_chunk() will setup the parser. When the last chunk
153 * has been parsed, call finish_chunk_parsing() to finish the parse.
154 *
155 * @param chunk The next piece of the XML document.
156 * @throws xmlpp::internal_error
157 * @throws xmlpp::parse_error
158 * @throws xmlpp::validity_error
159 */
160 void parse_chunk(const Glib::ustring& chunk);
161
162 /** Parse a chunk of data.
163 *
164 * @newin{2,24}
165 *
166 * This lets you pass a document in small chunks, e.g. from a network
167 * connection. The on_* virtual functions are called each time the chunks
168 * provide enough information to advance the parser.
169 *
170 * The first call to parse_chunk_raw() will setup the parser. When the last chunk
171 * has been parsed, call finish_chunk_parsing() to finish the parse.
172 *
173 * @param contents The next piece of the XML document as an array of bytes.
174 * @param bytes_count The number of bytes in the @a contents array.
175 * @throws xmlpp::internal_error
176 * @throws xmlpp::parse_error
177 * @throws xmlpp::validity_error
178 */
179 void parse_chunk_raw(const unsigned char* contents, size_type bytes_count);
180
181 /** Finish a chunk-wise parse.
182 *
183 * Call this after the last call to parse_chunk() or parse_chunk_raw().
184 * Don't use this function with the other parsing methods.
185 * @throws xmlpp::internal_error
186 * @throws xmlpp::parse_error
187 * @throws xmlpp::validity_error
188 */
189 void finish_chunk_parsing();
190
191protected:
192
193 virtual void on_start_document();
194 virtual void on_end_document();
195 virtual void on_start_element(const Glib::ustring& name, const AttributeList& attributes);
196 virtual void on_end_element(const Glib::ustring& name);
197 virtual void on_start_element_ns(const Glib::ustring& name, const Glib::ustring& prefix, const Glib::ustring& uri, const NamespaceList& namespaces, const AttributeList& attributes);
198 virtual void on_end_element_ns(const Glib::ustring& name, const Glib::ustring& prefix, const Glib::ustring& uri);
199 virtual void on_characters(const Glib::ustring& characters);
200 virtual void on_comment(const Glib::ustring& text);
201 virtual void on_processing_instruction(const Glib::ustring& target, const Glib::ustring& data);
202 virtual void on_warning(const Glib::ustring& text);
203 virtual void on_error(const Glib::ustring& text);
204
205 /** @throws xmlpp::parse_error
206 */
207 virtual void on_fatal_error(const Glib::ustring& text);
208 virtual void on_cdata_block(const Glib::ustring& text);
209
210 /** Override this to receive information about the document's DTD and any entity declarations.
211 */
212 virtual void on_internal_subset(const Glib::ustring& name, const Glib::ustring& publicId, const Glib::ustring& systemId);
213
214 /** Override this method to resolve entities references in your derived parser, instead of using the default entity resolution,
215 * or to be informed when entity references are encountered.
216 *
217 * If you override this function then you must also specify true for use_get_entity constructor parameter.
218 * You will probably need to override on_entity_declaration() as well so that you can use that information when
219 * resolving the entity reference.
220 *
221 * This is known to be difficult, because it requires both an understanding of the W3C specifications and knowledge of the
222 * libxml internals. Entity resolution is easier with the DomParser.
223 *
224 * Call this method in this base class for default processing. For instance, if you just want to know about the existence of
225 * an entity reference, without affecting the normal substitution, just override and call the base class.
226 *
227 * Unlike the DomParser, the SaxParser will also tell you about entity references for the 5 predefined entities.
228 *
229 * @param name The entity reference name.
230 * @returns The resolved xmlEntity for the entity reference, or <tt>nullptr</tt> if not found.
231 * You must include libxml/parser.h in order to use this C struct.
232 * This instance will not be freed by the caller.
233 */
234 virtual _xmlEntity* on_get_entity(const Glib::ustring& name);
235
236 /** Override this to receive information about every entity declaration.
237 * If you override this function, and you want normal entity substitution to work, then you must call the base class in your override.
238 *
239 * This would be useful when overriding on_get_entity().
240 * @throws xmlpp::internal_error
241 */
242 virtual void on_entity_declaration(const Glib::ustring& name, XmlEntityType type, const Glib::ustring& publicId, const Glib::ustring& systemId, const Glib::ustring& content);
243
244 void release_underlying() override;
245 void initialize_context() override;
246
247private:
248 void parse();
249
250 std::unique_ptr<_xmlSAXHandler> sax_handler_;
251
252 // A separate xmlpp::Document that is just used for entity resolution,
253 // and never seen in the API:
254 std::unique_ptr<Document> entity_resolver_doc_;
255
256 friend struct SaxParserCallback;
257};
258
259} // namespace xmlpp
260
261#endif //__LIBXMLPP_PARSERS_SAXPARSER_H
0262
=== modified file 'src/preferences.cpp'
--- src/preferences.cpp 2016-09-20 11:19:44 +0000
+++ src/preferences.cpp 2016-11-06 17:18:04 +0000
@@ -17,6 +17,7 @@
17#include <glibmm/i18n.h>17#include <glibmm/i18n.h>
18#include <glib/gstdio.h>18#include <glib/gstdio.h>
19#include <gtk/gtk.h>19#include <gtk/gtk.h>
20#include <xml/repr-io.h>
20#include "preferences.h"21#include "preferences.h"
21#include "preferences-skeleton.h"22#include "preferences-skeleton.h"
22#include "inkscape.h"23#include "inkscape.h"
@@ -123,7 +124,7 @@
123 */124 */
124void Preferences::_loadDefaults()125void Preferences::_loadDefaults()
125{126{
126 _prefs_doc = sp_repr_read_mem(preferences_skeleton, PREFERENCES_SKELETON_SIZE, NULL);127 _prefs_doc = Inkscape::XML::read_svg_buffer(preferences_skeleton, true);
127}128}
128129
129/**130/**
@@ -231,7 +232,8 @@
231 }232 }
232233
233 // 4. Is it valid XML?234 // 4. Is it valid XML?
234 Inkscape::XML::Document *prefs_read = sp_repr_read_mem(prefs_xml, len, NULL);235 Inkscape::XML::Document *prefs_read = Inkscape::XML::read_svg_buffer(prefs_xml, true);
236
235 g_free(prefs_xml);237 g_free(prefs_xml);
236 if (!prefs_read) {238 if (!prefs_read) {
237 gchar *msg = g_strdup_printf(_("The preferences file %s is not a valid XML document."),239 gchar *msg = g_strdup_printf(_("The preferences file %s is not a valid XML document."),
@@ -281,7 +283,7 @@
281 // There are many other factors, so ask if you would like to learn them. - JAC283 // There are many other factors, so ask if you would like to learn them. - JAC
282 Glib::ustring utf8name = Glib::filename_to_utf8(_prefs_filename);284 Glib::ustring utf8name = Glib::filename_to_utf8(_prefs_filename);
283 if (!utf8name.empty()) {285 if (!utf8name.empty()) {
284 sp_repr_save_file(_prefs_doc, utf8name.c_str());286 Inkscape::XML::save_svg_file(_prefs_doc, utf8name);
285 }287 }
286 }288 }
287}289}
288290
=== modified file 'src/shortcuts.cpp'
--- src/shortcuts.cpp 2016-08-03 13:29:38 +0000
+++ src/shortcuts.cpp 2016-11-06 17:18:04 +0000
@@ -32,6 +32,7 @@
32#include <glibmm/i18n.h>32#include <glibmm/i18n.h>
33#include <glibmm/convert.h>33#include <glibmm/convert.h>
34#include <glibmm/miscutils.h>34#include <glibmm/miscutils.h>
35#include <xml/repr-io.h>
3536
36#include "helper/action.h"37#include "helper/action.h"
37#include "io/sys.h"38#include "io/sys.h"
@@ -160,7 +161,7 @@
160161
161 char const *filename = get_path(USER, KEYS, "default.xml");162 char const *filename = get_path(USER, KEYS, "default.xml");
162163
163 XML::Document *doc=sp_repr_read_file(filename, NULL);164 XML::Document *doc = Inkscape::XML::read_svg_file(filename, true);
164 if (!doc) {165 if (!doc) {
165 g_warning("Unable to read keys file %s", filename);166 g_warning("Unable to read keys file %s", filename);
166 return;167 return;
@@ -183,8 +184,7 @@
183 iter=root->firstChild();184 iter=root->firstChild();
184 }185 }
185186
186187 Inkscape::XML::save_svg_file(doc, filename);
187 sp_repr_save_file(doc, filename, NULL);
188188
189 GC::release(doc);189 GC::release(doc);
190}190}
@@ -196,10 +196,10 @@
196 "<keys name=\"My custom shortcuts\">"196 "<keys name=\"My custom shortcuts\">"
197 "</keys>";197 "</keys>";
198198
199 Inkscape::XML::Document *doc = sp_repr_read_mem(buffer, strlen(buffer), NULL);199 Inkscape::XML::Document *doc = Inkscape::XML::read_svg_buffer(buffer, true);
200 sp_repr_save_file(doc, filename, NULL);200 Inkscape::XML::save_svg_file(doc, filename);
201201
202 return sp_repr_read_file(filename, NULL);202 return Inkscape::XML::read_svg_file(filename, true);
203}203}
204204
205/*205/*
@@ -242,7 +242,7 @@
242 if (!Inkscape::IO::file_test(full, G_FILE_TEST_IS_DIR)) {242 if (!Inkscape::IO::file_test(full, G_FILE_TEST_IS_DIR)) {
243243
244 // Get the "key name" from the root element of each file244 // Get the "key name" from the root element of each file
245 XML::Document *doc=sp_repr_read_file(full, NULL);245 XML::Document *doc = Inkscape::XML::read_svg_file(full, true);
246 if (!doc) {246 if (!doc) {
247 g_warning("Unable to read keyboard shortcut file %s", full);247 g_warning("Unable to read keyboard shortcut file %s", full);
248 continue;248 continue;
@@ -385,15 +385,15 @@
385}385}
386386
387void sp_shortcut_file_import_do(char const *importname) {387void sp_shortcut_file_import_do(char const *importname) {
388 XML::Document *doc = Inkscape::XML::read_svg_file(importname, true);
388389
389 XML::Document *doc=sp_repr_read_file(importname, NULL);
390 if (!doc) {390 if (!doc) {
391 g_warning("Unable to read keyboard shortcut file %s", importname);391 g_warning("Unable to read keyboard shortcut file %s", importname);
392 return;392 return;
393 }393 }
394394
395 char const *filename = get_path(USER, KEYS, "default.xml");395 char const *filename = get_path(USER, KEYS, "default.xml");
396 sp_repr_save_file(doc, filename, NULL);396 Inkscape::XML::save_svg_file(doc, filename);
397397
398 GC::release(doc);398 GC::release(doc);
399399
@@ -404,13 +404,13 @@
404404
405 char const *filename = get_path(USER, KEYS, "default.xml");405 char const *filename = get_path(USER, KEYS, "default.xml");
406406
407 XML::Document *doc=sp_repr_read_file(filename, NULL);407 XML::Document *doc = Inkscape::XML::read_svg_file(filename, true);
408 if (!doc) {408 if (!doc) {
409 g_warning("Unable to read keyboard shortcut file %s", filename);409 g_warning("Unable to read keyboard shortcut file %s", filename);
410 return;410 return;
411 }411 }
412412
413 sp_repr_save_file(doc, exportname, NULL);413 Inkscape::XML::save_svg_file(doc, exportname);
414414
415 GC::release(doc);415 GC::release(doc);
416}416}
@@ -428,7 +428,7 @@
428428
429 char const *filename = get_path(USER, KEYS, "default.xml");429 char const *filename = get_path(USER, KEYS, "default.xml");
430430
431 XML::Document *doc=sp_repr_read_file(filename, NULL);431 XML::Document *doc = Inkscape::XML::read_svg_file(filename, true);
432 if (!doc) {432 if (!doc) {
433 g_warning("Unable to read keyboard shortcut file %s", filename);433 g_warning("Unable to read keyboard shortcut file %s", filename);
434 return;434 return;
@@ -486,7 +486,7 @@
486 iter = iter->next();486 iter = iter->next();
487 }487 }
488488
489 sp_repr_save_file(doc, filename, NULL);489 Inkscape::XML::save_svg_file(doc, filename);
490490
491 GC::release(doc);491 GC::release(doc);
492492
@@ -496,7 +496,7 @@
496496
497 char const *filename = get_path(USER, KEYS, "default.xml");497 char const *filename = get_path(USER, KEYS, "default.xml");
498498
499 XML::Document *doc=sp_repr_read_file(filename, NULL);499 XML::Document *doc = Inkscape::XML::read_svg_file(filename, true);
500 if (!doc) {500 if (!doc) {
501 g_warning("Unable to read keyboard shortcut file %s, creating ....", filename);501 g_warning("Unable to read keyboard shortcut file %s, creating ....", filename);
502 doc = sp_shortcut_create_template_file(filename);502 doc = sp_shortcut_create_template_file(filename);
@@ -541,13 +541,13 @@
541 doc->root()->appendChild(newnode);541 doc->root()->appendChild(newnode);
542 }542 }
543543
544 sp_repr_save_file(doc, filename, NULL);544 Inkscape::XML::save_svg_file(doc, filename);
545545
546 GC::release(doc);546 GC::release(doc);
547547
548}548}
549static void read_shortcuts_file(char const *filename, bool const is_user_set) {549static void read_shortcuts_file(char const *filename, bool const is_user_set) {
550 XML::Document *doc=sp_repr_read_file(filename, NULL);550 XML::Document *doc = Inkscape::XML::read_svg_file(filename, true);
551 if (!doc) {551 if (!doc) {
552 g_warning("Unable to read keys file %s", filename);552 g_warning("Unable to read keys file %s", filename);
553 return;553 return;
554554
=== modified file 'src/ui/dialog/template-load-tab.cpp'
--- src/ui/dialog/template-load-tab.cpp 2016-08-03 13:29:38 +0000
+++ src/ui/dialog/template-load-tab.cpp 2016-11-06 17:18:04 +0000
@@ -17,6 +17,7 @@
17#include <gtkmm/messagedialog.h>17#include <gtkmm/messagedialog.h>
18#include <gtkmm/scrolledwindow.h>18#include <gtkmm/scrolledwindow.h>
19#include <iostream>19#include <iostream>
20#include <xml/repr-io.h>
2021
21#include "extension/db.h"22#include "extension/db.h"
22#include "inkscape.h"23#include "inkscape.h"
@@ -234,7 +235,7 @@
234 n = result.display_name.rfind(".svg");235 n = result.display_name.rfind(".svg");
235 result.display_name.replace(n, 4, 1, ' ');236 result.display_name.replace(n, 4, 1, ' ');
236 237
237 Inkscape::XML::Document *rdoc = sp_repr_read_file(path.data(), SP_SVG_NS_URI);238 Inkscape::XML::Document *rdoc = Inkscape::XML::read_svg_file(path.data(), false, SP_SVG_NS_URI);
238 if (rdoc){239 if (rdoc){
239 Inkscape::XML::Node *myRoot = rdoc->root();240 Inkscape::XML::Node *myRoot = rdoc->root();
240 if (strcmp(myRoot->name(), "svg:svg") != 0){ // Wrong file format241 if (strcmp(myRoot->name(), "svg:svg") != 0){ // Wrong file format
241242
=== modified file 'src/ui/interface.cpp'
--- src/ui/interface.cpp 2016-10-24 22:58:43 +0000
+++ src/ui/interface.cpp 2016-11-06 17:18:04 +0000
@@ -29,6 +29,7 @@
29#include <glibmm/miscutils.h>29#include <glibmm/miscutils.h>
30#include <gtkmm/imagemenuitem.h>30#include <gtkmm/imagemenuitem.h>
31#include <gtkmm/separatormenuitem.h>31#include <gtkmm/separatormenuitem.h>
32#include <xml/repr-io.h>
3233
33#include "inkscape.h"34#include "inkscape.h"
34#include "extension/db.h"35#include "extension/db.h"
@@ -1174,7 +1175,7 @@
1174 case SVG_XML_DATA: {1175 case SVG_XML_DATA: {
1175 gchar *svgdata = (gchar *)gtk_selection_data_get_data (data);1176 gchar *svgdata = (gchar *)gtk_selection_data_get_data (data);
11761177
1177 Inkscape::XML::Document *rnewdoc = sp_repr_read_mem(svgdata, gtk_selection_data_get_length (data), SP_SVG_NS_URI);1178 Inkscape::XML::Document *rnewdoc = Inkscape::XML::read_svg_buffer(svgdata, false, SP_SVG_NS_URI);
11781179
1179 if (rnewdoc == NULL) {1180 if (rnewdoc == NULL) {
1180 sp_ui_error_dialog(_("Could not parse SVG data"));1181 sp_ui_error_dialog(_("Could not parse SVG data"));
11811182
=== modified file 'src/xml/CMakeLists.txt'
--- src/xml/CMakeLists.txt 2011-10-08 06:34:23 +0000
+++ src/xml/CMakeLists.txt 2016-11-06 17:18:04 +0000
@@ -16,7 +16,7 @@
16 subtree.cpp16 subtree.cpp
17 helper-observer.cpp17 helper-observer.cpp
18 rebase-hrefs.cpp18 rebase-hrefs.cpp
1919 svg-parser.cpp
2020
21 # -------21 # -------
22 # Headers22 # Headers
@@ -42,12 +42,14 @@
42 rebase-hrefs-test.h42 rebase-hrefs-test.h
43 rebase-hrefs.h43 rebase-hrefs.h
44 repr-action-test.h44 repr-action-test.h
45 repr-io.h
45 repr-sorting.h46 repr-sorting.h
46 repr.h47 repr.h
47 simple-document.h48 simple-document.h
48 simple-node.h49 simple-node.h
49 sp-css-attr.h50 sp-css-attr.h
50 subtree.h51 subtree.h
52 svg-parser.h
51 text-node.h53 text-node.h
52)54)
5355
5456
=== modified file 'src/xml/comment-node.h'
--- src/xml/comment-node.h 2011-12-08 11:53:54 +0000
+++ src/xml/comment-node.h 2016-11-06 17:18:04 +0000
@@ -17,6 +17,7 @@
1717
18#include <glib.h>18#include <glib.h>
19#include "xml/simple-node.h"19#include "xml/simple-node.h"
20#include "io/inkscapestream.h"
2021
21namespace Inkscape {22namespace Inkscape {
2223
@@ -37,6 +38,14 @@
3738
38 Inkscape::XML::NodeType type() const { return Inkscape::XML::COMMENT_NODE; }39 Inkscape::XML::NodeType type() const { return Inkscape::XML::COMMENT_NODE; }
3940
41 void serialize(Inkscape::IO::Writer& out, const Glib::ustring& defaultPrefix, int indent, int indent_level, bool inline_attributes, bool preserve_spaces) override {
42 Glib::ustring real_indentation((unsigned long) (indent * indent_level), ' ');
43 out.writeUString(real_indentation);
44 out.writeString("<!--");
45 out.writeString(content());
46 out.writeString("-->\n");
47 }
48
40protected:49protected:
41 SimpleNode *_duplicate(Document* doc) const { return new CommentNode(*this, doc); }50 SimpleNode *_duplicate(Document* doc) const { return new CommentNode(*this, doc); }
42};51};
4352
=== modified file 'src/xml/node.h'
--- src/xml/node.h 2014-12-16 14:05:47 +0000
+++ src/xml/node.h 2016-11-06 17:18:04 +0000
@@ -23,6 +23,11 @@
23#include "util/list.h"23#include "util/list.h"
2424
25namespace Inkscape {25namespace Inkscape {
26
27namespace IO {
28class Writer;
29}
30
26namespace XML {31namespace XML {
2732
28struct AttributeRecord;33struct AttributeRecord;
@@ -193,8 +198,17 @@
193 * @param value The node's new content198 * @param value The node's new content
194 */199 */
195 virtual void setContent(char const *value)=0;200 virtual void setContent(char const *value)=0;
196 201
197 //@{202 /**
203 * @brief Change a namespace of this node
204 *
205 * The strings passed to this method are copied, so you can free them after use.
206 *
207 * @param prefix namespace prefix
208 * @param uri namespace uri
209 */
210 virtual void setNamespace(Glib::ustring const &prefix, Glib::ustring const &uri) = 0;
211
198 /**212 /**
199 * @brief Change an attribute of this node213 * @brief Change an attribute of this node
200 *214 *
@@ -470,9 +484,18 @@
470 */484 */
471 virtual void synthesizeEvents(NodeEventVector const *vector, void *data)=0;485 virtual void synthesizeEvents(NodeEventVector const *vector, void *data)=0;
472486
487 /**
488 * @brief serialize node and all descendants into given stream
489 * @param out output writer
490 * @param indent size of indent in characters
491 * @param indent_level level of indent, every child should have indent_level of parent plus 1
492 * @param inline_attributes whether attributes should be printed in one line
493 * @param preserve_spaces whether xml:space is set to 'preserve'
494 * @param defaultPrefix prefix for default namespace
495 */
496 virtual void serialize(Inkscape::IO::Writer& out, const Glib::ustring& defaultPrefix, int indent, int indent_level, bool inline_attributes, bool preserve_spaces) = 0;
497
473 virtual void recursivePrintTree(unsigned level)=0;498 virtual void recursivePrintTree(unsigned level)=0;
474
475 /*@}*/
476499
477protected:500protected:
478 Node(Node const &) : Anchored() {}501 Node(Node const &) : Anchored() {}
479502
=== modified file 'src/xml/pi-node.h'
--- src/xml/pi-node.h 2014-10-08 02:22:03 +0000
+++ src/xml/pi-node.h 2016-11-06 17:18:04 +0000
@@ -15,6 +15,7 @@
15#define SEEN_INKSCAPE_XML_PI_NODE_H15#define SEEN_INKSCAPE_XML_PI_NODE_H
1616
17#include "xml/simple-node.h"17#include "xml/simple-node.h"
18#include "io/inkscapestream.h"
1819
19namespace Inkscape {20namespace Inkscape {
2021
@@ -34,6 +35,11 @@
3435
35 Inkscape::XML::NodeType type() const { return Inkscape::XML::PI_NODE; }36 Inkscape::XML::NodeType type() const { return Inkscape::XML::PI_NODE; }
3637
38 void serialize(Inkscape::IO::Writer& out, const Glib::ustring& defaultPrefix, int indent, int indent_level, bool inline_attributes, bool preserve_spaces) override {
39 out.printf("<?%s %s?>\n", name(), content());
40 }
41
42
37protected:43protected:
38 SimpleNode *_duplicate(Document* doc) const { return new PINode(*this, doc); }44 SimpleNode *_duplicate(Document* doc) const { return new PINode(*this, doc); }
39};45};
4046
=== modified file 'src/xml/repr-io.cpp'
--- src/xml/repr-io.cpp 2016-08-03 13:29:38 +0000
+++ src/xml/repr-io.cpp 2016-11-06 17:18:04 +0000
@@ -1,1091 +1,200 @@
1/*1/*
2 * Dirty DOM-like tree2 * IO functions for svg files.
3 *3 *
4 * Authors:4 * Authors:
5 * Lauris Kaplinski <lauris@kaplinski.com>5 * Adrian Boguszewski
6 * bulia byak <buliabyak@users.sf.net>
7 *6 *
8 * Copyright (C) 1999-2002 Lauris Kaplinski7 * Copyright (C) 2016 Adrian Boguszewski
9 *8 *
10 * Released under GNU GPL, read the file 'COPYING' for more information9 * Released under GNU GPL, read the file 'COPYING' for more information
11 */10 */
1211
13#ifdef HAVE_CONFIG_H
14#include <config.h>
15#endif
16
17#include <cstring>
18#include <string>
19#include <stdexcept>
20
21#include <libxml/parser.h>
22
23#include "xml/repr.h"
24#include "xml/attribute-record.h"
25#include "xml/rebase-hrefs.h"
26#include "xml/simple-document.h"
27#include "xml/text-node.h"
28
29#include "io/sys.h"
30#include "io/uristream.h"12#include "io/uristream.h"
31#include "io/stringstream.h"13#include "io/stringstream.h"
32#include "io/gzipstream.h"14#include "io/gzipstream.h"
33
34#include "extension/extension.h"
35
36#include "attribute-rel-util.h"15#include "attribute-rel-util.h"
37#include "attribute-sort-util.h"16#include "attribute-sort-util.h"
38
39#include "preferences.h"17#include "preferences.h"
4018#include "repr-io.h"
19#include "rebase-hrefs.h"
20#include "simple-node.h"
21#include "util/list.h"
22#include "svg-parser.h"
23#include "xml/attribute-record.h"
24#include <boost/algorithm/string.hpp>
25#include <io/sys.h>
41#include <glibmm/miscutils.h>26#include <glibmm/miscutils.h>
4227#include <giomm/file.h>
43using Inkscape::IO::Writer;28
44using Inkscape::Util::List;29using namespace Inkscape::Util;
45using Inkscape::Util::cons;
46using Inkscape::XML::Document;
47using Inkscape::XML::SimpleDocument;
48using Inkscape::XML::Node;
49using Inkscape::XML::AttributeRecord;
50using Inkscape::XML::calc_abs_doc_base;
51using Inkscape::XML::rebase_href_attrs;
52
53Document *sp_repr_do_read (xmlDocPtr doc, const gchar *default_ns);
54static Node *sp_repr_svg_read_node (Document *xml_doc, xmlNodePtr node, const gchar *default_ns, std::map<std::string, std::string> &prefix_map);
55static gint sp_repr_qualified_name (gchar *p, gint len, xmlNsPtr ns, const xmlChar *name, const gchar *default_ns, std::map<std::string, std::string> &prefix_map);
56static void sp_repr_write_stream_root_element(Node *repr, Writer &out,
57 bool add_whitespace, gchar const *default_ns,
58 int inlineattrs, int indent,
59 gchar const *old_href_abs_base,
60 gchar const *new_href_abs_base);
61
62static void sp_repr_write_stream_element(Node *repr, Writer &out,
63 gint indent_level, bool add_whitespace,
64 Glib::QueryQuark elide_prefix,
65 List<AttributeRecord const> attributes,
66 int inlineattrs, int indent,
67 gchar const *old_href_abs_base,
68 gchar const *new_href_abs_base);
69
70#ifdef HAVE_LIBWMF
71static xmlDocPtr sp_wmf_convert (const char * file_name);
72static char * sp_wmf_image_name (void * context);
73#endif /* HAVE_LIBWMF */
74
75
76class XmlSource
77{
78public:
79 XmlSource()
80 : filename(0),
81 encoding(0),
82 fp(NULL),
83 firstFewLen(0),
84 LoadEntities(false),
85 cachedData(),
86 cachedPos(0),
87 dummy("x"),
88 instr(NULL),
89 gzin(NULL)
90 {
91 for (int k=0;k<4;k++)
92 {
93 firstFew[k]=0;
94 }
95 }
96 virtual ~XmlSource()
97 {
98 close();
99 if ( encoding ) {
100 g_free(encoding);
101 encoding = 0;
102 }
103 }
104
105 int setFile( char const * filename, bool load_entities );
106
107 xmlDocPtr readXml();
108
109 static int readCb( void * context, char * buffer, int len );
110 static int closeCb( void * context );
111
112 char const* getEncoding() const { return encoding; }
113 int read( char * buffer, int len );
114 int close();
115private:
116 const char* filename;
117 char* encoding;
118 FILE* fp;
119 unsigned char firstFew[4];
120 int firstFewLen;
121 bool LoadEntities; // Checks for SYSTEM Entities (requires cached data)
122 std::string cachedData;
123 unsigned int cachedPos;
124 Inkscape::URI dummy;
125 Inkscape::IO::UriInputStream* instr;
126 Inkscape::IO::GzipInputStream* gzin;
127};
128
129int XmlSource::setFile(char const *filename, bool load_entities=false)
130{
131 int retVal = -1;
132
133 this->filename = filename;
134
135 fp = Inkscape::IO::fopen_utf8name(filename, "r");
136 if ( fp ) {
137 // First peek in the file to see what it is
138 memset( firstFew, 0, sizeof(firstFew) );
139
140 size_t some = fread( firstFew, 1, 4, fp );
141 if ( fp ) {
142 // first check for compression
143 if ( (some >= 2) && (firstFew[0] == 0x1f) && (firstFew[1] == 0x8b) ) {
144 //g_message(" the file being read is gzip'd. extract it");
145 fclose(fp);
146 fp = 0;
147 fp = Inkscape::IO::fopen_utf8name(filename, "r");
148 instr = new Inkscape::IO::UriInputStream(fp, dummy);
149 gzin = new Inkscape::IO::GzipInputStream(*instr);
150
151 memset( firstFew, 0, sizeof(firstFew) );
152 some = 0;
153 int single = 0;
154 while ( some < 4 && single >= 0 )
155 {
156 single = gzin->get();
157 if ( single >= 0 ) {
158 firstFew[some++] = 0x0ff & single;
159 } else {
160 break;
161 }
162 }
163 }
164
165 int encSkip = 0;
166 if ( (some >= 2) &&(firstFew[0] == 0xfe) && (firstFew[1] == 0xff) ) {
167 encoding = g_strdup("UTF-16BE");
168 encSkip = 2;
169 } else if ( (some >= 2) && (firstFew[0] == 0xff) && (firstFew[1] == 0xfe) ) {
170 encoding = g_strdup("UTF-16LE");
171 encSkip = 2;
172 } else if ( (some >= 3) && (firstFew[0] == 0xef) && (firstFew[1] == 0xbb) && (firstFew[2] == 0xbf) ) {
173 encoding = g_strdup("UTF-8");
174 encSkip = 3;
175 }
176
177 if ( encSkip ) {
178 memmove( firstFew, firstFew + encSkip, (some - encSkip) );
179 some -= encSkip;
180 }
181
182 firstFewLen = some;
183 retVal = 0; // no error
184 }
185 }
186 if(load_entities) {
187 this->cachedData = std::string("");
188 this->cachedPos = 0;
189
190 // First get data from file in typical way (cache it all)
191 char *buffer = new char [4096];
192 while(true) {
193 int len = this->read(buffer, 4096);
194 if(len <= 0) break;
195 buffer[len] = 0;
196 this->cachedData += buffer;
197 }
198 delete[] buffer;
199
200 // Check for SYSTEM or PUBLIC entities and remove them from the cache
201 GMatchInfo *info;
202 gint start, end;
203
204 GRegex *regex = g_regex_new(
205 "<!ENTITY\\s+[^>\\s]+\\s+(SYSTEM|PUBLIC\\s+\"[^>\"]+\")\\s+\"[^>\"]+\"\\s*>",
206 G_REGEX_CASELESS, G_REGEX_MATCH_NEWLINE_ANY, NULL);
207
208 g_regex_match (regex, this->cachedData.c_str(), G_REGEX_MATCH_NEWLINE_ANY, &info);
209
210 while (g_match_info_matches (info)) {
211 if (g_match_info_fetch_pos (info, 1, &start, &end))
212 this->cachedData.erase(start, end - start);
213 g_match_info_next (info, NULL);
214 }
215 g_match_info_free(info);
216 g_regex_unref(regex);
217 }
218 // Do this after loading cache, so reads don't return cache to fill cache.
219 this->LoadEntities = load_entities;
220 return retVal;
221}
222
223xmlDocPtr XmlSource::readXml()
224{
225 int parse_options = XML_PARSE_HUGE | XML_PARSE_RECOVER;
226
227 Inkscape::Preferences *prefs = Inkscape::Preferences::get();
228 bool allowNetAccess = prefs->getBool("/options/externalresources/xml/allow_net_access", false);
229 if (!allowNetAccess) parse_options |= XML_PARSE_NONET;
230
231 // Allow NOENT only if we're filtering out SYSTEM and PUBLIC entities
232 if (LoadEntities) parse_options |= XML_PARSE_NOENT;
233
234 return xmlReadIO( readCb, closeCb, this,
235 filename, getEncoding(), parse_options);
236}
237
238int XmlSource::readCb( void * context, char * buffer, int len )
239{
240 int retVal = -1;
241
242 if ( context ) {
243 XmlSource* self = static_cast<XmlSource*>(context);
244 retVal = self->read( buffer, len );
245 }
246 return retVal;
247}
248
249int XmlSource::closeCb(void * context)
250{
251 if ( context ) {
252 XmlSource* self = static_cast<XmlSource*>(context);
253 self->close();
254 }
255 return 0;
256}
257
258int XmlSource::read( char *buffer, int len )
259{
260 int retVal = 0;
261 size_t got = 0;
262
263 if ( LoadEntities ) {
264 if (cachedPos >= cachedData.length()) {
265 return -1;
266 } else {
267 retVal = cachedData.copy(buffer, len, cachedPos);
268 cachedPos += retVal;
269 return retVal; // Do NOT continue.
270 }
271 } else if ( firstFewLen > 0 ) {
272 int some = (len < firstFewLen) ? len : firstFewLen;
273 memcpy( buffer, firstFew, some );
274 if ( len < firstFewLen ) {
275 memmove( firstFew, firstFew + some, (firstFewLen - some) );
276 }
277 firstFewLen -= some;
278 got = some;
279 } else if ( gzin ) {
280 int single = 0;
281 while ( (static_cast<int>(got) < len) && (single >= 0) )
282 {
283 single = gzin->get();
284 if ( single >= 0 ) {
285 buffer[got++] = 0x0ff & single;
286 } else {
287 break;
288 }
289 }
290 } else {
291 got = fread( buffer, 1, len, fp );
292 }
293
294 if ( feof(fp) ) {
295 retVal = got;
296 } else if ( ferror(fp) ) {
297 retVal = -1;
298 } else {
299 retVal = got;
300 }
301
302 return retVal;
303}
304
305int XmlSource::close()
306{
307 if ( gzin ) {
308 gzin->close();
309 delete gzin;
310 gzin = 0;
311 }
312 if ( instr ) {
313 instr->close();
314 fp = 0;
315 delete instr;
316 instr = 0;
317 }
318 if ( fp ) {
319 fclose(fp);
320 fp = 0;
321 }
322 return 0;
323}
324
325/**
326 * Reads XML from a file, including WMF files, and returns the Document.
327 * The default namespace can also be specified, if desired.
328 */
329Document *sp_repr_read_file (const gchar * filename, const gchar *default_ns)
330{
331 // g_warning( "Reading file: %s", filename );
332 xmlDocPtr doc = 0;
333 Document * rdoc = 0;
334
335 xmlSubstituteEntitiesDefault(1);
336
337 g_return_val_if_fail (filename != NULL, NULL);
338 if (!Inkscape::IO::file_test( filename, G_FILE_TEST_EXISTS )) {
339 g_warning("Can't open file: %s (doesn't exist)", filename);
340 return NULL;
341 }
342 /* fixme: A file can disappear at any time, including between now and when we actually try to
343 * open it. Get rid of the above test once we're sure that we correctly handle
344 * non-existence. */
345
346 // TODO: bulia, please look over
347 gsize bytesRead = 0;
348 gsize bytesWritten = 0;
349 GError* error = NULL;
350 // TODO: need to replace with our own fopen and reading
351 gchar* localFilename = g_filename_from_utf8 ( filename,
352 -1, &bytesRead, &bytesWritten, &error);
353 g_return_val_if_fail( localFilename != NULL, NULL );
354
355 Inkscape::IO::dump_fopen_call( filename, "N" );
356
357#ifdef HAVE_LIBWMF
358 if (strlen (localFilename) > 4) {
359 if ( (strcmp (localFilename + strlen (localFilename) - 4,".wmf") == 0)
360 || (strcmp (localFilename + strlen (localFilename) - 4,".WMF") == 0)) {
361 doc = sp_wmf_convert (localFilename);
362 }
363 }
364#endif // !HAVE_LIBWMF
365
366 if ( !doc ) {
367 XmlSource src;
368
369 if ( (src.setFile(filename) == 0) ) {
370 doc = src.readXml();
371 rdoc = sp_repr_do_read( doc, default_ns );
372 // For some reason, failed ns loading results in this
373 // We try a system check version of load with NOENT for adobe
374 if(rdoc && strcmp(rdoc->root()->name(), "ns:svg") == 0) {
375 xmlFreeDoc( doc );
376 src.setFile(filename, true);
377 doc = src.readXml();
378 rdoc = sp_repr_do_read( doc, default_ns );
379 }
380 }
381 }
382
383
384 if ( doc ) {
385 xmlFreeDoc( doc );
386 }
387
388 if ( localFilename ) {
389 g_free( localFilename );
390 }
391
392 return rdoc;
393}
394
395/**
396 * Reads and parses XML from a buffer, returning it as an Document
397 */
398Document *sp_repr_read_mem (const gchar * buffer, gint length, const gchar *default_ns)
399{
400 xmlDocPtr doc;
401 Document * rdoc;
402
403 xmlSubstituteEntitiesDefault(1);
404
405 g_return_val_if_fail (buffer != NULL, NULL);
406
407 doc = xmlParseMemory (const_cast<gchar *>(buffer), length);
408
409 rdoc = sp_repr_do_read (doc, default_ns);
410 if (doc) {
411 xmlFreeDoc (doc);
412 }
413 return rdoc;
414}
415
416/**
417 * Reads and parses XML from a buffer, returning it as an Document
418 */
419Document *sp_repr_read_buf (const Glib::ustring &buf, const gchar *default_ns)
420{
421 return sp_repr_read_mem(buf.c_str(), buf.size(), default_ns);
422}
423
42430
425namespace Inkscape {31namespace Inkscape {
42632
427struct compare_quark_ids {33namespace XML {
428 bool operator()(Glib::QueryQuark const &a, Glib::QueryQuark const &b) const {34
429 return a.id() < b.id();35using namespace Inkscape::IO;
430 }36
431};37static SVGParser _parser;
43238
433}39static void clean_attributes(Document *doc) {
43440 // Clean unnecessary attributes and style properties from SVG documents (controlled by preferences)
435namespace {
436
437typedef std::map<Glib::QueryQuark, Glib::QueryQuark, Inkscape::compare_quark_ids> PrefixMap;
438
439Glib::QueryQuark qname_prefix(Glib::QueryQuark qname) {
440 static PrefixMap prefix_map;
441 PrefixMap::iterator iter = prefix_map.find(qname);
442 if ( iter != prefix_map.end() ) {
443 return (*iter).second;
444 } else {
445 gchar const *name_string=g_quark_to_string(qname);
446 gchar const *prefix_end=strchr(name_string, ':');
447 if (prefix_end) {
448 Glib::Quark prefix=Glib::ustring(name_string, prefix_end);
449 prefix_map.insert(PrefixMap::value_type(qname, prefix));
450 return prefix;
451 } else {
452 return GQuark(0);
453 }
454 }
455}
456
457}
458
459namespace {
460
461void promote_to_namespace(Node *repr, const gchar *prefix) {
462 if ( repr->type() == Inkscape::XML::ELEMENT_NODE ) {
463 GQuark code = repr->code();
464 if (!qname_prefix(code).id()) {
465 gchar *svg_name = g_strconcat(prefix, ":", g_quark_to_string(code), NULL);
466 repr->setCodeUnsafe(g_quark_from_string(svg_name));
467 g_free(svg_name);
468 }
469 for ( Node *child = repr->firstChild() ; child ; child = child->next() ) {
470 promote_to_namespace(child, prefix);
471 }
472 }
473}
474
475}
476
477/**
478 * Reads in a XML file to create a Document
479 */
480Document *sp_repr_do_read (xmlDocPtr doc, const gchar *default_ns)
481{
482 if (doc == NULL) {
483 return NULL;
484 }
485 xmlNodePtr node=xmlDocGetRootElement (doc);
486 if (node == NULL) {
487 return NULL;
488 }
489
490 std::map<std::string, std::string> prefix_map;
491
492 Document *rdoc = new Inkscape::XML::SimpleDocument();
493
494 Node *root=NULL;
495 for ( node = doc->children ; node != NULL ; node = node->next ) {
496 if (node->type == XML_ELEMENT_NODE) {
497 Node *repr=sp_repr_svg_read_node(rdoc, node, default_ns, prefix_map);
498 rdoc->appendChild(repr);
499 Inkscape::GC::release(repr);
500
501 if (!root) {
502 root = repr;
503 } else {
504 root = NULL;
505 break;
506 }
507 } else if ( node->type == XML_COMMENT_NODE || node->type == XML_PI_NODE ) {
508 Node *repr=sp_repr_svg_read_node(rdoc, node, default_ns, prefix_map);
509 rdoc->appendChild(repr);
510 Inkscape::GC::release(repr);
511 }
512 }
513
514 if (root != NULL) {
515 /* promote elements of some XML documents that don't use namespaces
516 * into their default namespace */
517 if ( default_ns && !strchr(root->name(), ':') ) {
518 if ( !strcmp(default_ns, SP_SVG_NS_URI) ) {
519 promote_to_namespace(root, "svg");
520 }
521 if ( !strcmp(default_ns, INKSCAPE_EXTENSION_URI) ) {
522 promote_to_namespace(root, INKSCAPE_EXTENSION_NS_NC);
523 }
524 }
525
526
527 // Clean unnecessary attributes and style properties from SVG documents. (Controlled by
528 // preferences.) Note: internal Inkscape svg files will also be cleaned (filters.svg,
529 // icons.svg). How can one tell if a file is internal?
530 if ( !strcmp(root->name(), "svg:svg" ) ) {
531 Inkscape::Preferences *prefs = Inkscape::Preferences::get();
532 bool clean = prefs->getBool("/options/svgoutput/check_on_reading");
533 if( clean ) {
534 sp_attribute_clean_tree( root );
535 }
536 }
537 }
538
539 return rdoc;
540}
541
542gint sp_repr_qualified_name (gchar *p, gint len, xmlNsPtr ns, const xmlChar *name, const gchar */*default_ns*/, std::map<std::string, std::string> &prefix_map)
543{
544 const xmlChar *prefix;
545 if (ns){
546 if (ns->href ) {
547 prefix = reinterpret_cast<const xmlChar*>( sp_xml_ns_uri_prefix(reinterpret_cast<const gchar*>(ns->href),
548 reinterpret_cast<const char*>(ns->prefix)) );
549 prefix_map[reinterpret_cast<const char*>(prefix)] = reinterpret_cast<const char*>(ns->href);
550 }
551 else {
552 prefix = NULL;
553 }
554 }
555 else {
556 prefix = NULL;
557 }
558
559 if (prefix) {
560 return g_snprintf (p, len, "%s:%s", reinterpret_cast<const gchar*>(prefix), name);
561 } else {
562 return g_snprintf (p, len, "%s", name);
563 }
564}
565
566static Node *sp_repr_svg_read_node (Document *xml_doc, xmlNodePtr node, const gchar *default_ns, std::map<std::string, std::string> &prefix_map)
567{
568 xmlAttrPtr prop;
569 xmlNodePtr child;
570 gchar c[256];
571
572 if (node->type == XML_TEXT_NODE || node->type == XML_CDATA_SECTION_NODE) {
573
574 if (node->content == NULL || *(node->content) == '\0') {
575 return NULL; // empty text node
576 }
577
578 bool preserve = (xmlNodeGetSpacePreserve (node) == 1);
579
580 xmlChar *p;
581 for (p = node->content; *p && g_ascii_isspace (*p) && !preserve; p++)
582 ; // skip all whitespace
583
584 if (!(*p)) { // this is an all-whitespace node, and preserve == default
585 return NULL; // we do not preserve all-whitespace nodes unless we are asked to
586 }
587
588 // We keep track of original node type so that CDATA sections are preserved on output.
589 return xml_doc->createTextNode(reinterpret_cast<gchar *>(node->content),
590 node->type == XML_CDATA_SECTION_NODE );
591 }
592
593 if (node->type == XML_COMMENT_NODE) {
594 return xml_doc->createComment(reinterpret_cast<gchar *>(node->content));
595 }
596
597 if (node->type == XML_PI_NODE) {
598 return xml_doc->createPI(reinterpret_cast<const gchar *>(node->name),
599 reinterpret_cast<const gchar *>(node->content));
600 }
601
602 if (node->type == XML_ENTITY_DECL) {
603 return NULL;
604 }
605
606 sp_repr_qualified_name (c, 256, node->ns, node->name, default_ns, prefix_map);
607 Node *repr = xml_doc->createElement(c);
608 /* TODO remember node->ns->prefix if node->ns != NULL */
609
610 for (prop = node->properties; prop != NULL; prop = prop->next) {
611 if (prop->children) {
612 sp_repr_qualified_name (c, 256, prop->ns, prop->name, default_ns, prefix_map);
613 repr->setAttribute(c, reinterpret_cast<gchar*>(prop->children->content));
614 /* TODO remember prop->ns->prefix if prop->ns != NULL */
615 }
616 }
617
618 if (node->content) {
619 repr->setContent(reinterpret_cast<gchar*>(node->content));
620 }
621
622 for (child = node->xmlChildrenNode; child != NULL; child = child->next) {
623 Node *crepr = sp_repr_svg_read_node (xml_doc, child, default_ns, prefix_map);
624 if (crepr) {
625 repr->appendChild(crepr);
626 Inkscape::GC::release(crepr);
627 }
628 }
629
630 return repr;
631}
632
633
634static void sp_repr_save_writer(Document *doc, Inkscape::IO::Writer *out,
635 gchar const *default_ns,
636 gchar const *old_href_abs_base,
637 gchar const *new_href_abs_base)
638{
639 Inkscape::Preferences *prefs = Inkscape::Preferences::get();41 Inkscape::Preferences *prefs = Inkscape::Preferences::get();
640 bool inlineattrs = prefs->getBool("/options/svgoutput/inlineattrs");42 bool clean = prefs->getBool("/options/svgoutput/check_on_reading");
641 int indent = prefs->getInt("/options/svgoutput/indent", 2);43 if(clean) {
64244 sp_attribute_clean_tree(doc->root());
643 /* fixme: do this The Right Way */45 }
644 out->writeString( "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n" );46}
64547
646 const gchar *str = static_cast<Node *>(doc)->attribute("doctype");48Document* read_svg_file(const Glib::ustring& filename, const bool& is_internal, const Glib::ustring& default_ns) {
647 if (str) {49 if (!Inkscape::IO::file_test(filename.c_str(), G_FILE_TEST_EXISTS)) {
648 out->writeString( str );50 g_warning("Can't open file: %s (doesn't exist)", filename.c_str());
649 }51 return nullptr;
65052 }
651 for (Node *repr = sp_repr_document_first_child(doc);53
652 repr; repr = repr->next())54 Glib::RefPtr<Gio::File> file = Gio::File::create_for_path(filename);
653 {55 Glib::RefPtr<Gio::FileInfo> info = file->query_info();
654 Inkscape::XML::NodeType const node_type = repr->type();56 std::string content_type = info->get_content_type();
655 if ( node_type == Inkscape::XML::ELEMENT_NODE ) {57
656 sp_repr_write_stream_root_element(repr, *out, TRUE, default_ns, inlineattrs, indent,58 Document *doc;
657 old_href_abs_base, new_href_abs_base);59 if(content_type == "image/svg+xml" || content_type == "application/xml" || content_type == "text/html"
658 } else {60 // Windows doesn't support mime type
659 sp_repr_write_stream(repr, *out, 0, TRUE, GQuark(0), inlineattrs, indent,61 || content_type == ".svg" || content_type == ".xml" || content_type == ".inx" || content_type == ".htm" || content_type == ".html") {
660 old_href_abs_base, new_href_abs_base);62 doc = _parser.parseFile(filename, default_ns);
661 if ( node_type == Inkscape::XML::COMMENT_NODE ) {63 } else if (content_type == "image/svg+xml-compressed" || content_type == "application/x-gzip"
662 out->writeChar('\n');64 // the same as above
663 }65 || content_type == ".svgz") {
664 }66 doc = _parser.parseCompressedFile(filename, default_ns);
665 }67 } else {
666}68 g_warning("Unrecognized content type: %s.", content_type.c_str());
66769 return nullptr;
66870 }
669Glib::ustring sp_repr_save_buf(Document *doc)71
670{ 72 if(!is_internal) {
671 Inkscape::IO::StringOutputStream souts;73 clean_attributes(doc);
672 Inkscape::IO::OutputStreamWriter outs(souts);74 }
67375 return doc;
674 sp_repr_save_writer(doc, &outs, SP_INKSCAPE_NS_URI, 0, 0);76}
67577
676 outs.close();78Document* read_svg_buffer(const Glib::ustring& source, const bool& is_internal, const Glib::ustring& default_ns) {
677 Glib::ustring buf = souts.getString();79 Document *doc = _parser.parseBuffer(source, default_ns);
67880 if(!is_internal) {
679 return buf;81 clean_attributes(doc);
680}82 }
68183 return doc;
68284}
683void sp_repr_save_stream(Document *doc, FILE *fp, gchar const *default_ns, bool compress,85
684 gchar const *const old_href_abs_base,86static void rebase_attributes(Node* node, const Glib::ustring& old_href_base, const Glib::ustring& new_href_base) {
685 gchar const *const new_href_abs_base)87 for(auto iter = rebase_href_attrs(old_href_base.c_str(), new_href_base.c_str(), node->attributeList()); iter; ++iter) {
686{88 node->setAttribute(g_quark_to_string(iter->key), iter->value);
687 Inkscape::URI dummy("x");89 }
688 Inkscape::IO::UriOutputStream bout(fp, dummy);90
689 Inkscape::IO::GzipOutputStream *gout = compress ? new Inkscape::IO::GzipOutputStream(bout) : NULL;91 for (Node *child = node->firstChild(); child != nullptr; child = child->next()) {
690 Inkscape::IO::OutputStreamWriter *out = compress ? new Inkscape::IO::OutputStreamWriter( *gout ) : new Inkscape::IO::OutputStreamWriter( bout );92 if (child->type() == ELEMENT_NODE) {
69193 rebase_attributes(child, old_href_base, new_href_base);
692 sp_repr_save_writer(doc, out, default_ns, old_href_abs_base, new_href_abs_base);94 }
69395 }
694 delete out;96}
695 delete gout;97
696}98static void add_namespace_to_doc(Document* doc, const Glib::ustring& node_name) {
69799 if (node_name.find(":") != Glib::ustring::npos) {
698100 Glib::ustring prefix = node_name.substr(0, node_name.find(":"));
699101 Glib::ustring extendedPrefix = "xmlns:" + prefix;
700/**102 SimpleNode* root = dynamic_cast<SimpleNode*>(doc->root());
701 * Returns true if file successfully saved.103 if (root->namespaces().find(g_quark_from_string(extendedPrefix.c_str())) == root->namespaces().end()
702 *104 && prefix != "xml") {
703 * \param filename The actual file to do I/O to, which might be a temp file.105 root->setNamespace(extendedPrefix, sp_xml_ns_prefix_uri(prefix.c_str()));
704 *106 }
705 * \param for_filename The base URI [actually filename] to assume for purposes of rewriting107 }
706 * xlink:href attributes.108}
707 */109
708bool sp_repr_save_rebased_file(Document *doc, gchar const *const filename, gchar const *default_ns,110static void find_all_prefixes(Document* doc, Node* node) {
709 gchar const *old_base, gchar const *for_filename)111 add_namespace_to_doc(doc, node->name());
710{112 for (List<AttributeRecord const> iter = node->attributeList(); iter; ++iter) {
711 if (!filename) {113 add_namespace_to_doc(doc, g_quark_to_string(iter->key));
712 return false;114 }
713 }115 for (Node *child = node->firstChild(); child != nullptr; child = child->next()) {
714116 if (child->type() == ELEMENT_NODE) {
715 bool compress;117 find_all_prefixes(doc, child);
716 {118 }
717 size_t const filename_len = strlen(filename);119 }
718 compress = ( filename_len > 5120}
719 && strcasecmp(".svgz", filename + filename_len - 5) == 0 );121
720 }122static void serialize(Writer& writer, Document* doc, const Glib::ustring& default_ns, const Glib::ustring& old_base, const Glib::ustring& new_base) {
721123 if (old_base != "") {
722 Inkscape::IO::dump_fopen_call( filename, "B" );124 Glib::ustring old_href_abs_base = calc_abs_doc_base(old_base.c_str());
723 FILE *file = Inkscape::IO::fopen_utf8name(filename, "w");125 Glib::ustring new_href_abs_base;
724 if (file == NULL) {126 if (Glib::path_is_absolute(new_base)) {
725 return false;127 new_href_abs_base = Glib::path_get_dirname(new_base);
726 }
727
728 Glib::ustring old_href_abs_base;
729 Glib::ustring new_href_abs_base;
730 if (for_filename) {
731 old_href_abs_base = calc_abs_doc_base(old_base);
732 if (Glib::path_is_absolute(for_filename)) {
733 new_href_abs_base = Glib::path_get_dirname(for_filename);
734 } else {128 } else {
735 Glib::ustring const cwd = Glib::get_current_dir();129 Glib::ustring const cwd = Glib::get_current_dir();
736 Glib::ustring const for_abs_filename = Glib::build_filename(cwd, for_filename);130 Glib::ustring const for_abs_filename = Glib::build_filename(cwd, new_base);
737 new_href_abs_base = Glib::path_get_dirname(for_abs_filename);131 new_href_abs_base = Glib::path_get_dirname(for_abs_filename);
738 }132 }
739133 rebase_attributes(doc->root(), old_href_abs_base, new_href_abs_base);
740 /* effic: Once we're confident that we never need (or never want) to resort134 }
741 * to using sodipodi:absref instead of the xlink:href value,135
742 * then we should do `if streq() { free them and set both to NULL; }'. */136 Inkscape::Preferences *prefs = Inkscape::Preferences::get();
743 }
744 sp_repr_save_stream(doc, file, default_ns, compress, old_href_abs_base.c_str(), new_href_abs_base.c_str());
745
746 if (fclose (file) != 0) {
747 return false;
748 }
749
750 return true;
751}
752
753/**
754 * Returns true iff file successfully saved.
755 */
756bool sp_repr_save_file(Document *doc, gchar const *const filename, gchar const *default_ns)
757{
758 return sp_repr_save_rebased_file(doc, filename, default_ns, NULL, NULL);
759}
760
761
762/* (No doubt this function already exists elsewhere.) */
763static void repr_quote_write (Writer &out, const gchar * val)
764{
765 if (val) {
766 for (; *val != '\0'; val++) {
767 switch (*val) {
768 case '"': out.writeString( "&quot;" ); break;
769 case '&': out.writeString( "&amp;" ); break;
770 case '<': out.writeString( "&lt;" ); break;
771 case '>': out.writeString( "&gt;" ); break;
772 default: out.writeChar( *val ); break;
773 }
774 }
775 }
776}
777
778static void repr_write_comment( Writer &out, const gchar * val, bool addWhitespace, gint indentLevel, int indent )
779{
780 if ( indentLevel > 16 ) {
781 indentLevel = 16;
782 }
783 if (addWhitespace && indent) {
784 for (gint i = 0; i < indentLevel; i++) {
785 for (gint j = 0; j < indent; j++) {
786 out.writeString(" ");
787 }
788 }
789 }
790
791 out.writeString("<!--");
792 // WARNING out.printf() and out.writeString() are *NOT* non-ASCII friendly.
793 if (val) {
794 for (const gchar* cur = val; *cur; cur++ ) {
795 out.writeChar(*cur);
796 }
797 } else {
798 out.writeString(" ");
799 }
800 out.writeString("-->");
801
802 if (addWhitespace) {
803 out.writeString("\n");
804 }
805}
806
807namespace {
808
809typedef std::map<Glib::QueryQuark, gchar const *, Inkscape::compare_quark_ids> LocalNameMap;
810typedef std::map<Glib::QueryQuark, Inkscape::Util::ptr_shared<char>, Inkscape::compare_quark_ids> NSMap;
811
812gchar const *qname_local_name(Glib::QueryQuark qname) {
813 static LocalNameMap local_name_map;
814 LocalNameMap::iterator iter = local_name_map.find(qname);
815 if ( iter != local_name_map.end() ) {
816 return (*iter).second;
817 } else {
818 gchar const *name_string=g_quark_to_string(qname);
819 gchar const *prefix_end=strchr(name_string, ':');
820 if (prefix_end) {
821 return prefix_end + 1;
822 } else {
823 return name_string;
824 }
825 }
826}
827
828void add_ns_map_entry(NSMap &ns_map, Glib::QueryQuark prefix) {
829 using Inkscape::Util::ptr_shared;
830 using Inkscape::Util::share_unsafe;
831
832 static const Glib::QueryQuark xml_prefix("xml");
833
834 NSMap::iterator iter=ns_map.find(prefix);
835 if ( iter == ns_map.end() ) {
836 if (prefix.id()) {
837 gchar const *uri=sp_xml_ns_prefix_uri(g_quark_to_string(prefix));
838 if (uri) {
839 ns_map.insert(NSMap::value_type(prefix, share_unsafe(uri)));
840 } else if ( prefix != xml_prefix ) {
841 g_warning("No namespace known for normalized prefix %s", g_quark_to_string(prefix));
842 }
843 } else {
844 ns_map.insert(NSMap::value_type(prefix, ptr_shared<char>()));
845 }
846 }
847}
848
849void populate_ns_map(NSMap &ns_map, Node &repr) {
850 if ( repr.type() == Inkscape::XML::ELEMENT_NODE ) {
851 add_ns_map_entry(ns_map, qname_prefix(repr.code()));
852 for ( List<AttributeRecord const> iter=repr.attributeList() ;
853 iter ; ++iter )
854 {
855 Glib::QueryQuark prefix=qname_prefix(iter->key);
856 if (prefix.id()) {
857 add_ns_map_entry(ns_map, prefix);
858 }
859 }
860 for ( Node *child=repr.firstChild() ;
861 child ; child = child->next() )
862 {
863 populate_ns_map(ns_map, *child);
864 }
865 }
866}
867
868}
869
870static void sp_repr_write_stream_root_element(Node *repr, Writer &out,
871 bool add_whitespace, gchar const *default_ns,
872 int inlineattrs, int indent,
873 gchar const *const old_href_base,
874 gchar const *const new_href_base)
875{
876 using Inkscape::Util::ptr_shared;
877
878 g_assert(repr != NULL);
879
880 // Clean unnecessary attributes and stype properties. (Controlled by preferences.)137 // Clean unnecessary attributes and stype properties. (Controlled by preferences.)
881 Inkscape::Preferences *prefs = Inkscape::Preferences::get();
882 bool clean = prefs->getBool("/options/svgoutput/check_on_writing");138 bool clean = prefs->getBool("/options/svgoutput/check_on_writing");
883 if (clean) sp_attribute_clean_tree( repr );139 if (clean) {
140 sp_attribute_clean_tree(doc->root());
141 }
142
143 // find all used prefixes
144 find_all_prefixes(doc, doc->root());
145 if (default_ns != "") {
146 doc->root()->setNamespace("xmlns", default_ns);
147 }
148 Glib::ustring defaultPrefix = sp_xml_ns_uri_prefix(default_ns.c_str(), "");
149
150 bool inlineAttributes = prefs->getBool("/options/svgoutput/inlineattrs");
151 int indent = prefs->getInt("/options/svgoutput/indent", 2);
884152
885 // Sort attributes in a canonical order (helps with "diffing" SVG files).153 // Sort attributes in a canonical order (helps with "diffing" SVG files).
886 bool sort = prefs->getBool("/options/svgoutput/sort_attributes");154 bool sort = prefs->getBool("/options/svgoutput/sort_attributes");
887 if (sort) sp_attribute_sort_tree( repr );
888
889 Glib::QueryQuark xml_prefix=g_quark_from_static_string("xml");
890
891 NSMap ns_map;
892 populate_ns_map(ns_map, *repr);
893
894 Glib::QueryQuark elide_prefix=GQuark(0);
895 if ( default_ns && ns_map.find(GQuark(0)) == ns_map.end() ) {
896 elide_prefix = g_quark_from_string(sp_xml_ns_uri_prefix(default_ns, NULL));
897 }
898
899 List<AttributeRecord const> attributes=repr->attributeList();
900 for ( NSMap::iterator iter=ns_map.begin() ; iter != ns_map.end() ; ++iter )
901 {
902 Glib::QueryQuark prefix=(*iter).first;
903 ptr_shared<char> ns_uri=(*iter).second;
904
905 if (prefix.id()) {
906 if ( prefix != xml_prefix ) {
907 if ( elide_prefix == prefix ) {
908 attributes = cons(AttributeRecord(g_quark_from_static_string("xmlns"), ns_uri), attributes);
909 }
910
911 Glib::ustring attr_name="xmlns:";
912 attr_name.append(g_quark_to_string(prefix));
913 GQuark key = g_quark_from_string(attr_name.c_str());
914 attributes = cons(AttributeRecord(key, ns_uri), attributes);
915 }
916 } else {
917 // if there are non-namespaced elements, we can't globally
918 // use a default namespace
919 elide_prefix = GQuark(0);
920 }
921 }
922
923 return sp_repr_write_stream_element(repr, out, 0, add_whitespace, elide_prefix, attributes,
924 inlineattrs, indent, old_href_base, new_href_base);
925}
926
927void sp_repr_write_stream( Node *repr, Writer &out, gint indent_level,
928 bool add_whitespace, Glib::QueryQuark elide_prefix,
929 int inlineattrs, int indent,
930 gchar const *const old_href_base,
931 gchar const *const new_href_base)
932{
933 switch (repr->type()) {
934 case Inkscape::XML::TEXT_NODE: {
935 if( dynamic_cast<const Inkscape::XML::TextNode *>(repr)->is_CData() ) {
936 // Preserve CDATA sections, not converting '&' to &amp;, etc.
937 out.printf( "<![CDATA[%s]]>", repr->content() );
938 } else {
939 repr_quote_write( out, repr->content() );
940 }
941 break;
942 }
943 case Inkscape::XML::COMMENT_NODE: {
944 repr_write_comment( out, repr->content(), add_whitespace, indent_level, indent );
945 break;
946 }
947 case Inkscape::XML::PI_NODE: {
948 out.printf( "<?%s %s?>", repr->name(), repr->content() );
949 break;
950 }
951 case Inkscape::XML::ELEMENT_NODE: {
952 sp_repr_write_stream_element( repr, out, indent_level,
953 add_whitespace, elide_prefix,
954 repr->attributeList(),
955 inlineattrs, indent,
956 old_href_base, new_href_base);
957 break;
958 }
959 case Inkscape::XML::DOCUMENT_NODE: {
960 g_assert_not_reached();
961 break;
962 }
963 default: {
964 g_assert_not_reached();
965 }
966 }
967}
968
969
970void sp_repr_write_stream_element( Node * repr, Writer & out,
971 gint indent_level, bool add_whitespace,
972 Glib::QueryQuark elide_prefix,
973 List<AttributeRecord const> attributes,
974 int inlineattrs, int indent,
975 gchar const *old_href_base,
976 gchar const *new_href_base )
977{
978 Node *child = 0;
979 bool loose = false;
980
981 g_return_if_fail (repr != NULL);
982
983 if ( indent_level > 16 ) {
984 indent_level = 16;
985 }
The diff has been truncated for viewing.