diff options
author | Luboš Luňák <l.lunak@suse.cz> | 2011-11-21 17:32:09 +0100 |
---|---|---|
committer | Luboš Luňák <l.lunak@suse.cz> | 2011-11-24 18:43:58 +0100 |
commit | 4d5ca442d89ee36e7b1abb622e9f3d85b36e0d0c (patch) | |
tree | 5498db37fe943bdeb9def518425b0b7c661f42b8 | |
parent | f8f1ccbaf942adf9a6b16b13a9cddb1b96a6774b (diff) |
streamline and document the API for mathml xml stream reading
-rw-r--r-- | oox/inc/oox/mathml/importutils.hxx | 65 | ||||
-rw-r--r-- | oox/source/mathml/importutils.cxx | 47 | ||||
-rw-r--r-- | starmath/source/ooxmlimport.cxx | 91 | ||||
-rw-r--r-- | starmath/source/ooxmlimport.hxx | 12 |
4 files changed, 119 insertions, 96 deletions
diff --git a/oox/inc/oox/mathml/importutils.hxx b/oox/inc/oox/mathml/importutils.hxx index 01baf981eb1f..f7c353da9887 100644 --- a/oox/inc/oox/mathml/importutils.hxx +++ b/oox/inc/oox/mathml/importutils.hxx @@ -50,24 +50,60 @@ const int TAG_CLOSING = 1 << 30; #define OPENING( token ) ( TAG_OPENING | token ) #define CLOSING( token ) ( TAG_CLOSING | token ) +/** + Class for storing a stream of xml tokens. + + A part of an XML file can be parsed and stored in this stream, from which it can be read + as if parsed linearly. The purpose of this class is to allow simpler handling of XML + files, unlike the usual LO way of using callbacks, context handlers and similar needlesly + complicated stuff (YMMV). + + @since 3.5.0 +*/ class OOX_DLLPUBLIC XmlStream { public: XmlStream(); - bool nextIsEnd() const; - int peekNextToken() const; - int getNextToken(); - oox::AttributeList getAttributes(); - rtl::OUString getCharacters(); + /** + Structure representing a tag, including its attributes and content text immediatelly following it. + */ + struct Tag + { + Tag( int token = XML_TOKEN_INVALID, + const com::sun::star::uno::Reference< com::sun::star::xml::sax::XFastAttributeList >& attributes = com::sun::star::uno::Reference< com::sun::star::xml::sax::XFastAttributeList >(), + const rtl::OUString& text = rtl::OUString()); + int token; ///< tag type, or XML_TOKEN_INVALID + AttributeList attributes; + rtl::OUString text; + }; + /** + @return true if current position is at the end of the XML stream + */ + bool atEnd() const; + /** + @return data about the current tag + */ + Tag currentTag() const; + /** + @return the token for the current tag + */ + int currentToken() const; + /** + Moves position to the next tag. + */ + void moveToNextTag(); protected: - // TODO one list containing all 3? - std::vector< int > tokens; - std::vector< oox::AttributeList > attributes; - std::vector< rtl::OUString > characters; - int pos; + std::vector< Tag > tags; + unsigned int pos; }; -// use this to create the data and then cast to the base class for reading +/** + This class is used for creating XmlStream. + + Simply use this class and then pass it as XmlStream to the consumer. + + @since 3.5.0 +*/ class OOX_DLLPUBLIC XmlStreamBuilder : public XmlStream { @@ -79,6 +115,13 @@ public: void appendCharacters( const rtl::OUString& characters ); }; +inline XmlStream::Tag::Tag( int t, const com::sun::star::uno::Reference< com::sun::star::xml::sax::XFastAttributeList >& a, const rtl::OUString& txt ) +: token( t ) +, attributes( a ) +, text( txt ) +{ +} + } // namespace } // namespace diff --git a/oox/source/mathml/importutils.cxx b/oox/source/mathml/importutils.cxx index 1381724ec407..95f81c802e83 100644 --- a/oox/source/mathml/importutils.cxx +++ b/oox/source/mathml/importutils.cxx @@ -41,62 +41,51 @@ namespace formulaimport { XmlStream::XmlStream() -: pos( -1 ) +: pos( 0 ) { // make sure our extra bit does not conflict with values used by oox assert( TAG_OPENING > ( 1024 << NMSP_SHIFT )); } -bool XmlStream::nextIsEnd() const +bool XmlStream::atEnd() const { - return pos + 1 >= int( tokens.size()); + return pos >= tags.size(); } -int XmlStream::getNextToken() +XmlStream::Tag XmlStream::currentTag() const { - ++pos; - if( pos < int( tokens.size())) - return tokens[ pos ]; - return XML_TOKEN_INVALID; + if( pos >= tags.size()) + return Tag(); + return tags[ pos ]; } -int XmlStream::peekNextToken() const +int XmlStream::currentToken() const { - if( pos - 1 < int( tokens.size())) - return tokens[ pos + 1 ]; - return XML_TOKEN_INVALID; + if( pos >= tags.size()) + return XML_TOKEN_INVALID; + return tags[ pos ].token; } -AttributeList XmlStream::getAttributes() +void XmlStream::moveToNextTag() { - assert( pos < int( attributes.size())); - return attributes[ pos ]; -} - -rtl::OUString XmlStream::getCharacters() -{ - assert( pos < int( characters.size())); - return characters[ pos ]; + if( pos < tags.size()) + ++pos; } void XmlStreamBuilder::appendOpeningTag( int token, const uno::Reference< xml::sax::XFastAttributeList >& attrs ) { - tokens.push_back( OPENING( token )); - attributes.push_back( AttributeList( attrs )); - characters.push_back( rtl::OUString()); + tags.push_back( Tag( OPENING( token ), attrs )); } void XmlStreamBuilder::appendClosingTag( int token ) { - tokens.push_back( CLOSING( token )); - attributes.push_back( AttributeList( uno::Reference< xml::sax::XFastAttributeList >())); - characters.push_back( rtl::OUString()); + tags.push_back( Tag( CLOSING( token ))); } void XmlStreamBuilder::appendCharacters( const rtl::OUString& chars ) { - assert( !characters.empty()); - characters.back() = chars; + assert( !tags.empty()); + tags.back().text = chars; } } // namespace diff --git a/starmath/source/ooxmlimport.cxx b/starmath/source/ooxmlimport.cxx index dc53cc72996d..16f887ca6c15 100644 --- a/starmath/source/ooxmlimport.cxx +++ b/starmath/source/ooxmlimport.cxx @@ -70,17 +70,16 @@ OUString SmOoxmlImport::handleStream() { checkOpeningTag( M_TOKEN( oMath )); OUString ret; - bool out = false; - while( !out && !stream.nextIsEnd()) + while( !stream.atEnd()) { - switch( stream.peekNextToken()) + XmlStream::Tag tag = stream.currentTag(); + if( tag.token == CLOSING( M_TOKEN( oMath ))) + break; + switch( tag.token ) { case OPENING( M_TOKEN( f )): ret += STR( " " ) + handleF(); break; - case CLOSING( M_TOKEN( oMath )): - out = true; - break; default: handleUnexpectedTag(); break; @@ -94,7 +93,7 @@ OUString SmOoxmlImport::handleStream() OUString SmOoxmlImport::handleF() { checkOpeningTag( M_TOKEN( f )); - if( stream.peekNextToken() == OPENING_TAG( M_TOKEN( fPr ))) + if( stream.currentToken() == OPENING_TAG( M_TOKEN( fPr ))) { // TODO } @@ -119,18 +118,18 @@ OUString SmOoxmlImport::readR() // checkClosingTag( OOX_TOKEN( doc, rPr )); // TODO can there be more t's ? - checkOpeningTag( M_TOKEN( t )); - OUString text = stream.getCharacters(); - if( !stream.getAttributes().getBool( OOX_TOKEN( xml, space ), false )) + XmlStream::Tag rtag = checkOpeningTag( M_TOKEN( t )); + OUString text = rtag.text; + if( !rtag.attributes.getBool( OOX_TOKEN( xml, space ), false )) text = text.trim(); checkClosingTag( M_TOKEN( t )); checkClosingTag( M_TOKEN( r )); return text; } -void SmOoxmlImport::checkOpeningTag( int token ) +XmlStream::Tag SmOoxmlImport::checkOpeningTag( int token ) { - checkTag( OPENING( token ), "opening" ); + return checkTag( OPENING( token ), "opening" ); } void SmOoxmlImport::checkClosingTag( int token ) @@ -138,80 +137,69 @@ void SmOoxmlImport::checkClosingTag( int token ) checkTag( CLOSING( token ), "closing" ); } -void SmOoxmlImport::checkTag( int token, const char* txt ) +XmlStream::Tag SmOoxmlImport::checkTag( int token, const char* txt ) { - if( stream.peekNextToken() == token ) - { - stream.getNextToken(); // read it - return; // ok - } - if( recoverAndFindTag( token )) + // either it's the following tag, or find it + if( stream.currentToken() == token || recoverAndFindTag( token )) { - stream.getNextToken(); // read it - return; // ok, skipped some tokens + XmlStream::Tag ret = stream.currentTag(); + stream.moveToNextTag(); + return ret; // ok } fprintf( stderr, "Expected %s tag %d not found.\n", txt, token ); + return XmlStream::Tag(); } bool SmOoxmlImport::recoverAndFindTag( int token ) { int depth = 0; - for(;;) + for(; + !stream.atEnd(); + stream.moveToNextTag()) { if( depth > 0 ) // we're inside a nested element, skip those { - int next = stream.getNextToken(); - if( next == OPENING( next )) + if( stream.currentToken() == OPENING( stream.currentToken())) { - fprintf( stderr, "Skipping opening tag %d\n", next ); + fprintf( stderr, "Skipping opening tag %d\n", stream.currentToken()); ++depth; } - else if( next == CLOSING( next )) + else if( stream.currentToken() == CLOSING( stream.currentToken())) { // TODO debug output without the OPENING/CLOSING bits set - fprintf( stderr, "Skipping closing tag %d\n", next ); + fprintf( stderr, "Skipping closing tag %d\n", stream.currentToken()); --depth; } - else if( next == XML_TOKEN_INVALID ) // end of stream - { - fprintf( stderr, "Unexpected end of stream reached.\n" ); - return false; - } else { - fprintf( stderr, "Malformed token %d\n", next ); + fprintf( stderr, "Malformed token %d\n", stream.currentToken()); abort(); } continue; } - int next = stream.peekNextToken(); - if( next == CLOSING( next )) + if( stream.currentToken() == CLOSING( stream.currentToken())) return false; // that would be leaving current element, so not found - if( next == token ) + if( stream.currentToken() == token ) return true; // ok, found - if( next == OPENING( next )) + if( stream.currentToken() == OPENING( stream.currentToken())) { - fprintf( stderr, "Skipping opening tag %d\n", next ); - stream.getNextToken(); + fprintf( stderr, "Skipping opening tag %d\n", stream.currentToken()); ++depth; } - else if( next == XML_TOKEN_INVALID ) - { - fprintf( stderr, "Unexpected end of stream reached.\n" ); - return false; - } else abort(); } + fprintf( stderr, "Unexpected end of stream reached.\n" ); + return false; } void SmOoxmlImport::skipElement( int token ) { int closing = ( token & ~TAG_OPENING ) | TAG_CLOSING; // make it a closing tag - assert( stream.peekNextToken() == OPENING( token )); + assert( stream.currentToken() == OPENING( token )); // just find the matching closing tag if( recoverAndFindTag( closing )) { - stream.getNextToken(); // read it + stream.moveToNextTag(); // and skip it too return; } fprintf( stderr, "Expected end of element %d not found.\n", token ); @@ -219,15 +207,14 @@ void SmOoxmlImport::skipElement( int token ) void SmOoxmlImport::handleUnexpectedTag() { - int next = stream.peekNextToken(); - if( next == XML_TOKEN_INVALID ) - return; // end of stream - if( next == CLOSING( next )) + if( stream.atEnd()) + return; + if( stream.currentToken() == CLOSING( stream.currentToken())) { - stream.getNextToken(); // just skip it + stream.moveToNextTag(); // just skip it return; } - skipElement( stream.peekNextToken()); + skipElement( stream.currentToken()); // otherwise skip the entire element } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/starmath/source/ooxmlimport.hxx b/starmath/source/ooxmlimport.hxx index 1eebc8180120..043b44a19ec2 100644 --- a/starmath/source/ooxmlimport.hxx +++ b/starmath/source/ooxmlimport.hxx @@ -47,19 +47,23 @@ private: rtl::OUString handleF(); rtl::OUString readR(); /** - Checks that the next token is the given opening tag, if not, writes out a warning + Checks that the current tag is the given opening token, if not, writes out a warning and tries to recover (skips tags until found or until the current element would end). + In both cases the position is moved to the next tag. + @return the matching found opening tag, or empty tag */ - void checkOpeningTag( int token ); + oox::formulaimport::XmlStream::Tag checkOpeningTag( int token ); /** - Checks that the next token is the given opening tag, if not, writes out a warning + Checks that the current tag is the given opening token, if not, writes out a warning and tries to recover (skips tags until found or until the current element would end). + In both cases the position is moved to the next tag. */ void checkClosingTag( int token ); // helper for the two above - void checkTag( int token, const char* txt ); + oox::formulaimport::XmlStream::Tag checkTag( int token, const char* txt ); /** Tries to find the given token, until either found (returns true) or end of current element. + Position in the stream is set to make the tag current. */ bool recoverAndFindTag( int token ); /** |