bump product version to 5.0.4.1
[LibreOffice.git] / oox / source / mathml / importutils.cxx
bloba759c3f0ed9561eb1cceb57f9b708477b1325b1c
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
10 #include "oox/mathml/importutils.hxx"
12 #include <assert.h>
14 #include <oox/token/namespacemap.hxx>
15 #include <oox/token/tokenmap.hxx>
16 #include <oox/token/tokens.hxx>
17 #include <oox/token/namespaces.hxx>
18 #include <rtl/ustring.hxx>
20 #define OPENING( token ) XML_STREAM_OPENING( token )
21 #define CLOSING( token ) XML_STREAM_CLOSING( token )
23 using namespace com::sun::star;
25 namespace oox
28 namespace formulaimport
31 namespace
33 // a class that inherits from AttributeList, builds the internal data and then will be sliced off
34 // during conversion to the base class
35 class AttributeListBuilder
36 : public XmlStream::AttributeList
38 public:
39 explicit AttributeListBuilder( const uno::Reference< xml::sax::XFastAttributeList >& a );
42 AttributeListBuilder::AttributeListBuilder( const uno::Reference< xml::sax::XFastAttributeList >& a )
44 if( a.get() == NULL )
45 return;
46 uno::Sequence< xml::FastAttribute > aFastAttrSeq = a->getFastAttributes();
47 const xml::FastAttribute* pFastAttr = aFastAttrSeq.getConstArray();
48 sal_Int32 nFastAttrLength = aFastAttrSeq.getLength();
49 for( int i = 0;
50 i < nFastAttrLength;
51 ++i )
53 attrs[ pFastAttr[ i ].Token ] = pFastAttr[ i ].Value;
57 static OString tokenToString( int token )
59 const uno::Sequence< sal_Int8 > aTokenNameSeq = StaticTokenMap::get().getUtf8TokenName( token & TOKEN_MASK );
60 OString tokenname( reinterpret_cast< const char* >( aTokenNameSeq.getConstArray() ), aTokenNameSeq.getLength() );
61 if( tokenname.isEmpty())
62 tokenname = "???";
63 int nmsp = ( token & NMSP_MASK & ~( TAG_OPENING | TAG_CLOSING ));
64 #if 0 // this is awfully long
65 OString namespacename = StaticNamespaceMap::get().count( nmsp ) != 0
66 ? StaticNamespaceMap::get()[ nmsp ] : OString( "???" );
67 #else
68 OString namespacename;
69 // only few are needed actually
70 switch( nmsp )
72 case NMSP_officeMath:
73 namespacename = "m";
74 break;
75 case NMSP_doc:
76 namespacename = "w";
77 break;
78 default:
79 namespacename = "?";
80 break;
82 #endif
83 if( token == OPENING( token ))
84 return "<" + namespacename + ":" + tokenname + ">";
85 if( token == CLOSING( token ))
86 return "</" + namespacename + ":" + tokenname + ">";
87 // just the name itself, not specified whether opening or closing
88 return namespacename + ":" + tokenname;
91 } // namespace
93 OUString& XmlStream::AttributeList::operator[] (int token)
95 return attrs[token];
98 OUString XmlStream::AttributeList::attribute( int token, const OUString& def ) const
100 std::map< int, OUString >::const_iterator find = attrs.find( token );
101 if( find != attrs.end())
102 return find->second;
103 return def;
106 bool XmlStream::AttributeList::attribute( int token, bool def ) const
108 std::map< int, OUString >::const_iterator find = attrs.find( token );
109 if( find != attrs.end())
111 const OUString sValue = find->second;
112 if( sValue.equalsIgnoreAsciiCase("true") ||
113 sValue.equalsIgnoreAsciiCase("on") ||
114 sValue.equalsIgnoreAsciiCase("t") ||
115 sValue.equalsIgnoreAsciiCase("1") )
116 return true;
117 if( sValue.equalsIgnoreAsciiCase("false") ||
118 sValue.equalsIgnoreAsciiCase("off") ||
119 sValue.equalsIgnoreAsciiCase("f") ||
120 sValue.equalsIgnoreAsciiCase("0") )
121 return false;
122 SAL_WARN( "oox.xmlstream", "Cannot convert \'" << sValue << "\' to bool." );
124 return def;
127 sal_Unicode XmlStream::AttributeList::attribute( int token, sal_Unicode def ) const
129 std::map< int, OUString >::const_iterator find = attrs.find( token );
130 if( find != attrs.end())
132 if( !find->second.isEmpty() )
134 if( find->second.getLength() != 1 )
135 SAL_WARN( "oox.xmlstream", "Cannot convert \'" << find->second << "\' to sal_Unicode, stripping." );
136 return find->second[ 0 ];
139 return def;
142 XmlStream::Tag::Tag( int t, const uno::Reference< xml::sax::XFastAttributeList >& a, const OUString& txt )
143 : token( t )
144 , attributes( AttributeListBuilder( a ))
145 , text( txt )
149 XmlStream::Tag::Tag( int t, const AttributeList& a )
150 : token( t )
151 , attributes( a )
155 XmlStream::Tag::operator bool() const
157 return token != XML_TOKEN_INVALID;
160 XmlStream::XmlStream()
161 : pos( 0 )
163 // make sure our extra bit does not conflict with values used by oox
164 assert( TAG_OPENING > ( 1024 << NMSP_SHIFT ));
167 bool XmlStream::atEnd() const
169 return pos >= tags.size();
172 XmlStream::Tag XmlStream::currentTag() const
174 if( pos >= tags.size())
175 return Tag();
176 return tags[ pos ];
179 int XmlStream::currentToken() const
181 if( pos >= tags.size())
182 return XML_TOKEN_INVALID;
183 return tags[ pos ].token;
186 void XmlStream::moveToNextTag()
188 if( pos < tags.size())
189 ++pos;
192 XmlStream::Tag XmlStream::ensureOpeningTag( int token )
194 return checkTag( OPENING( token ), false );
197 XmlStream::Tag XmlStream::checkOpeningTag( int token )
199 return checkTag( OPENING( token ), true );
202 void XmlStream::ensureClosingTag( int token )
204 checkTag( CLOSING( token ), false );
207 XmlStream::Tag XmlStream::checkTag( int token, bool optional )
209 // either it's the following tag, or find it
210 int savedPos = pos;
211 if( optional )
212 { // avoid printing debug messages about skipping tags if the optional one
213 // will not be found and the position will be reset back
214 if( currentToken() != token && !findTagInternal( token, true ))
216 pos = savedPos;
217 return Tag();
220 if( currentToken() == token || findTag( token ))
222 Tag ret = currentTag();
223 moveToNextTag();
224 return ret; // ok
226 if( optional )
227 { // not a problem, just rewind
228 pos = savedPos;
229 return Tag();
231 SAL_WARN( "oox.xmlstream", "Expected tag " << tokenToString( token ) << " not found." );
232 return Tag();
235 bool XmlStream::findTag( int token )
237 return findTagInternal( token, false );
240 bool XmlStream::findTagInternal( int token, bool silent )
242 int depth = 0;
243 for(;
244 !atEnd();
245 moveToNextTag())
247 if( depth > 0 ) // we're inside a nested element, skip those
249 if( currentToken() == OPENING( currentToken()))
251 if( !silent )
252 SAL_INFO( "oox.xmlstream", "Skipping tag " << tokenToString( currentToken()));
253 ++depth;
255 else if( currentToken() == CLOSING( currentToken()))
257 if( !silent )
258 SAL_INFO( "oox.xmlstream", "Skipping tag " << tokenToString( currentToken()));
259 --depth;
261 else
263 if( !silent )
264 SAL_WARN( "oox.xmlstream", "Malformed token " << currentToken() << " ("
265 << tokenToString( currentToken()) << ")" );
266 abort();
268 continue;
270 if( currentToken() == token )
271 return true; // ok, found
272 if( currentToken() == CLOSING( currentToken()))
273 return false; // that would be leaving current element, so not found
274 if( currentToken() == OPENING( currentToken()))
276 if( !silent )
277 SAL_INFO( "oox.xmlstream", "Skipping tag " << tokenToString( currentToken()));
278 ++depth;
280 else
281 abort();
283 if( !silent )
284 SAL_WARN( "oox.xmlstream", "Unexpected end of stream reached." );
285 return false;
288 void XmlStream::skipElementInternal( int token, bool silent )
290 int closing = ( token & ~TAG_OPENING ) | TAG_CLOSING; // make it a closing tag
291 assert( currentToken() == OPENING( token ));
292 if( !silent )
293 SAL_INFO( "oox.xmlstream", "Skipping unexpected element " << tokenToString( currentToken()));
294 moveToNextTag();
295 // and just find the matching closing tag
296 if( findTag( closing ))
298 if( !silent )
299 SAL_INFO( "oox.xmlstream", "Skipped unexpected element " << tokenToString( token ));
300 moveToNextTag(); // and skip it too
301 return;
303 // this one is an unexpected problem, do not silent it
304 SAL_WARN( "oox.xmlstream", "Expected end of element " << tokenToString( token ) << " not found." );
307 void XmlStream::handleUnexpectedTag()
309 if( atEnd())
310 return;
311 if( currentToken() == CLOSING( currentToken()))
313 SAL_INFO( "oox.xmlstream", "Skipping unexpected tag " << tokenToString( currentToken()));
314 moveToNextTag(); // just skip it
315 return;
317 skipElementInternal( currentToken(), false ); // otherwise skip the entire element
320 void XmlStreamBuilder::appendOpeningTag( int token, const uno::Reference< xml::sax::XFastAttributeList >& attrs )
322 tags.push_back( Tag( OPENING( token ), attrs ));
325 void XmlStreamBuilder::appendOpeningTag( int token, const AttributeList& attrs )
327 tags.push_back( Tag( OPENING( token ), attrs ));
330 void XmlStreamBuilder::appendClosingTag( int token )
332 tags.push_back( Tag( CLOSING( token )));
335 void XmlStreamBuilder::appendCharacters( const OUString& chars )
337 assert( !tags.empty());
338 tags.back().text += chars;
341 } // namespace
342 } // namespace
344 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */