summaryrefslogtreecommitdiffstats
path: root/lib/store/KoXmlWriter.h
diff options
context:
space:
mode:
authortpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-01-20 01:29:50 +0000
committertpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-01-20 01:29:50 +0000
commit8362bf63dea22bbf6736609b0f49c152f975eb63 (patch)
tree0eea3928e39e50fae91d4e68b21b1e6cbae25604 /lib/store/KoXmlWriter.h
downloadkoffice-8362bf63dea22bbf6736609b0f49c152f975eb63.tar.gz
koffice-8362bf63dea22bbf6736609b0f49c152f975eb63.zip
Added old abandoned KDE3 version of koffice
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/koffice@1077364 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'lib/store/KoXmlWriter.h')
-rw-r--r--lib/store/KoXmlWriter.h281
1 files changed, 281 insertions, 0 deletions
diff --git a/lib/store/KoXmlWriter.h b/lib/store/KoXmlWriter.h
new file mode 100644
index 00000000..232f9a65
--- /dev/null
+++ b/lib/store/KoXmlWriter.h
@@ -0,0 +1,281 @@
+/* This file is part of the KDE project
+ Copyright (C) 2004 David Faure <[email protected]>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef XMLWRITER_H
+#define XMLWRITER_H
+
+#include <qstring.h>
+#include <qvaluestack.h>
+#include <qmap.h>
+#include <koffice_export.h>
+
+class QIODevice;
+
+/**
+ * A class for writing out XML (to any QIODevice), with a special attention on performance.
+ * The XML is being written out along the way, which avoids requiring the entire
+ * document in memory (like QDom does), and avoids using QTextStream at all
+ * (which in Qt3 has major performance issues when converting to utf8).
+ */
+class KOSTORE_EXPORT KoXmlWriter
+{
+public:
+ /**
+ * Create a KoXmlWriter instance to write out an XML document into
+ * the given QIODevice.
+ */
+ KoXmlWriter( QIODevice* dev, int indentLevel = 0 );
+
+ /// Destructor
+ ~KoXmlWriter();
+
+ QIODevice *device() const { return m_dev; }
+
+ /**
+ * Start the XML document.
+ * This writes out the \<?xml?\> tag with utf8 encoding, and the DOCTYPE.
+ * @param rootElemName the name of the root element, used in the DOCTYPE tag.
+ * @param publicId the public identifier, e.g. "-//OpenOffice.org//DTD OfficeDocument 1.0//EN"
+ * @param systemId the system identifier, e.g. "office.dtd" or a full URL to it.
+ */
+ void startDocument( const char* rootElemName, const char* publicId = 0, const char* systemId = 0 );
+
+ /// Call this to terminate an XML document.
+ void endDocument();
+
+ /**
+ * Start a new element, as a child of the current element.
+ * @param tagName the name of the tag. Warning: this string must
+ * remain alive until endElement, no copy is internally made.
+ * Usually tagName is a string constant so this is no problem anyway.
+ * @param indentInside if set to false, there will be no indentation inside
+ * this tag. This is useful for elements where whitespace matters.
+ */
+ void startElement( const char* tagName, bool indentInside = true );
+
+ /**
+ * Overloaded version of addAttribute( const char*, const char* ),
+ * which is a bit slower because it needs to convert @p value to utf8 first.
+ */
+ inline void addAttribute( const char* attrName, const QString& value ) {
+ addAttribute( attrName, value.utf8() );
+ }
+ /**
+ * Add an attribute whose value is an integer
+ */
+ inline void addAttribute( const char* attrName, int value ) {
+ QCString str;
+ str.setNum( value );
+ addAttribute( attrName, str.data() );
+ }
+ /**
+ * Add an attribute whose value is an unsigned integer
+ */
+ inline void addAttribute( const char* attrName, uint value ) {
+ QCString str;
+ str.setNum( value );
+ addAttribute( attrName, str.data() );
+ }
+ /**
+ * Add an attribute whose value is a floating point number
+ * The number is written out with the highest possible precision
+ * (unlike QString::number and setNum, which default to 6 digits)
+ */
+ void addAttribute( const char* attrName, double value );
+ /**
+ * Add an attribute which represents a distance, measured in pt
+ * The number is written out with the highest possible precision
+ * (unlike QString::number and setNum, which default to 6 digits),
+ * and the unit name ("pt") is appended to it.
+ */
+ void addAttributePt( const char* attrName, double value );
+
+ /// Overloaded version of the one taking a const char* argument, for convenience
+ inline void addAttribute( const char* attrName, const QCString& value ) {
+ addAttribute( attrName, value.data() );
+ }
+ /**
+ * Add an attribute to the current element.
+ */
+ void addAttribute( const char* attrName, const char* value );
+ /**
+ * Terminate the current element. After this you should start a new one (sibling),
+ * add a sibling text node, or close another one (end of siblings).
+ */
+ void endElement();
+ /**
+ * Overloaded version of addTextNode( const char* ),
+ * which is a bit slower because it needs to convert @p str to utf8 first.
+ */
+ inline void addTextNode( const QString& str ) {
+ addTextNode( str.utf8() );
+ }
+ /// Overloaded version of the one taking a const char* argument
+ inline void addTextNode( const QCString& cstr ) {
+ addTextNode( cstr.data() );
+ }
+ /**
+ * @brief Adds a text node as a child of the current element.
+ *
+ * This is appends the litteral content of @p str to the contents of the element.
+ * E.g. addTextNode( "foo" ) inside a \<p\> element gives \<p\>foo\</p\>,
+ * and startElement( "b" ); endElement( "b" ); addTextNode( "foo" ) gives \<p\>\<b/\>foo\</p\>
+ */
+ void addTextNode( const char* cstr );
+
+ /**
+ * @brief Adds a processing instruction
+ *
+ * This writes a processing instruction, like <?foo bar blah?>, where foo
+ * is the target, and the rest is the data.
+ *
+ * Processing instructions are used in XML to keep processor-specific
+ * information in the text of the document.
+ */
+ void addProcessingInstruction( const char* cstr );
+
+ /**
+ * This is quite a special-purpose method, not for everyday use.
+ * It adds a complete element (with its attributes and child elements)
+ * as a child of the current element. The string is supposed to be escaped
+ * for XML already, so it will usually come from another KoXmlWriter.
+ */
+ void addCompleteElement( const char* cstr );
+
+ /**
+ * This is quite a special-purpose method, not for everyday use.
+ * It adds a complete element (with its attributes and child elements)
+ * as a child of the current element. The iodevice is supposed to be escaped
+ * for XML already, so it will usually come from another KoXmlWriter.
+ * This is usually used with KTempFile.
+ */
+ void addCompleteElement( QIODevice* dev );
+
+ // #### Maybe we want to subclass KoXmlWriter for manifest files.
+ /**
+ * Special helper for writing "manifest" files
+ * This is equivalent to startElement/2*addAttribute/endElement
+ * This API will probably have to change (or not be used anymore)
+ * when we add support for encrypting/signing.
+ * @note OASIS-specific
+ */
+ void addManifestEntry( const QString& fullPath, const QString& mediaType );
+
+ /**
+ * Special helper for writing config item into settings.xml
+ * @note OASIS-specific
+ */
+ void addConfigItem( const QString & configName, const QString& value );
+ /// @note OASIS-specific
+ void addConfigItem( const QString & configName, bool value );
+ /// @note OASIS-specific
+ void addConfigItem( const QString & configName, int value );
+ /// @note OASIS-specific
+ void addConfigItem( const QString & configName, double value );
+ /// @note OASIS-specific
+ void addConfigItem( const QString & configName, long value );
+ /// @note OASIS-specific
+ void addConfigItem( const QString & configName, short value );
+
+ // TODO addConfigItem for datetime and base64Binary
+
+ /**
+ * @brief Adds a text span as nodes of the current element.
+ *
+ * Unlike KoXmlWriter::addTextNode it handles tabulations, linebreaks,
+ * and multiple spaces by using the appropriate OASIS tags.
+ *
+ * @param text the text to write
+ *
+ * @note OASIS-specific
+ */
+ void addTextSpan( const QString& text );
+ /**
+ * Overloaded version of addTextSpan which takes an additional tabCache map.
+ * @param text the text to write
+ * @param tabCache optional map allowing to find a tab for a given character index
+ * @note OASIS-specific
+ */
+ void addTextSpan( const QString& text, const QMap<int, int>& tabCache );
+
+ /**
+ * @return the current indentation level.
+ * Useful when creating a sub-KoXmlWriter (see addCompleteElement)
+ */
+ int indentLevel() const { return m_tags.size() + m_baseIndentLevel; }
+
+private:
+ struct Tag {
+ Tag( const char* t = 0, bool ind = true )
+ : tagName( t ), hasChildren( false ), lastChildIsText( false ),
+ openingTagClosed( false ), indentInside( ind ) {}
+ const char* tagName;
+ bool hasChildren; ///< element or text children
+ bool lastChildIsText; ///< last child is a text node
+ bool openingTagClosed; ///< true once the '\>' in \<tag a="b"\> is written out
+ bool indentInside; ///< whether to indent the contents of this tag
+ };
+
+ /// Write out \n followed by the number of spaces required.
+ void writeIndent();
+
+ // writeCString is much faster than writeString.
+ // Try to use it as much as possible, especially with constants.
+ void writeString( const QString& str );
+
+ // unused and possibly incorrect if length != size
+ //inline void writeCString( const QCString& cstr ) {
+ // m_dev->writeBlock( cstr.data(), cstr.size() - 1 );
+ //}
+
+ inline void writeCString( const char* cstr ) {
+ m_dev->writeBlock( cstr, qstrlen( cstr ) );
+ }
+ inline void writeChar( char c ) {
+ m_dev->putch( c );
+ }
+ inline void closeStartElement( Tag& tag ) {
+ if ( !tag.openingTagClosed ) {
+ tag.openingTagClosed = true;
+ writeChar( '>' );
+ }
+ }
+ char* escapeForXML( const char* source, int length ) const;
+ bool prepareForChild();
+ void prepareForTextNode();
+ void init();
+
+ QIODevice* m_dev;
+ QValueStack<Tag> m_tags;
+ int m_baseIndentLevel;
+
+ class Private;
+ Private *d;
+
+ char* m_indentBuffer; // maybe make it static, but then it needs a KStaticDeleter,
+ // and would eat 1K all the time... Maybe refcount it :)
+ char* m_escapeBuffer; // can't really be static if we want to be thread-safe
+ static const int s_escapeBufferLen = 10000;
+
+ KoXmlWriter( const KoXmlWriter & ); // forbidden
+ KoXmlWriter& operator=( const KoXmlWriter & ); // forbidden
+};
+
+#endif /* XMLWRITER_H */
+