Warning, file /office/calligra/filters/libmsooxml/MsooXmlReader_p.h was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 * This file is part of Office 2007 Filters for Calligra 0003 * 0004 * Copyright (C) 2009-2010 Nokia Corporation and/or its subsidiary(-ies). 0005 * 0006 * Contact: Suresh Chande suresh.chande@nokia.com 0007 * 0008 * This library is free software; you can redistribute it and/or 0009 * modify it under the terms of the GNU Lesser General Public License 0010 * version 2.1 as published by the Free Software Foundation. 0011 * 0012 * This library is distributed in the hope that it will be useful, but 0013 * WITHOUT ANY WARRANTY; without even the implied warranty of 0014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0015 * Lesser General Public License for more details. 0016 * 0017 * You should have received a copy of the GNU Lesser General Public 0018 * License along with this library; if not, write to the Free Software 0019 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 0020 * 02110-1301 USA 0021 * 0022 */ 0023 0024 #ifndef MSOOXMLREADER_P_H 0025 #define MSOOXMLREADER_P_H 0026 0027 #include <klocalizedstring.h> 0028 0029 #ifndef MSOOXML_CURRENT_CLASS 0030 #error Please include MsooXmlReader_p.h after defining MSOOXML_CURRENT_CLASS and MSOOXML_CURRENT_NS! 0031 #endif 0032 0033 #define PASTE2(a, b) a##b 0034 #define PASTE(a, b) PASTE2( a, b) // indirection needed because only function-like macro parameters can be pasted 0035 0036 #define PASTE3_(a, b, c) a##b##c 0037 #define PASTE3(a, b, c) PASTE3_( a, b, c) // indirection needed because only function-like macro parameters can be pasted 0038 0039 #define JOIN2(a, b) a#b 0040 #define JOIN(a, b) JOIN2( a, b) // indirection needed because only function-like macro parameters can be pasted 0041 0042 #define STRINGIFY(s) JOIN("", s) 0043 0044 //! Used to pass context: creates enum value {el}_{CURRENT_EL} 0045 #define PASS_CONTEXT(el) PASTE3(el, _, CURRENT_EL) 0046 0047 #define TRY_READ_WITH_ARGS_INTERNAL(name, args, context) \ 0048 args \ 0049 RETURN_IF_ERROR( read_ ## name (context) ) 0050 0051 #define TRY_READ_WITH_ARGS(name, args) \ 0052 TRY_READ_WITH_ARGS_INTERNAL(name, m_read_ ## name ## _args = args,) 0053 0054 #define TRY_READ_WITH_ARGS_IN_CONTEXT(name, args) \ 0055 TRY_READ_WITH_ARGS_INTERNAL(name, m_read_ ## name ## _args = args, PASS_CONTEXT(name)) 0056 0057 #define TRY_READ(name) \ 0058 TRY_READ_WITH_ARGS_INTERNAL(name, ,) 0059 0060 #define TRY_READ_IN_CONTEXT(name) \ 0061 TRY_READ_WITH_ARGS_INTERNAL(name, , PASS_CONTEXT(name)) 0062 0063 #ifdef MSOOXML_CURRENT_NS 0064 # define QUALIFIED_NAME(name) \ 0065 JOIN(MSOOXML_CURRENT_NS ":",name) 0066 #else 0067 # define QUALIFIED_NAME(name) \ 0068 STRINGIFY(name) 0069 #endif 0070 0071 #ifdef NDEBUG 0072 # define PUSH_NAME_INTERNAL 0073 # define POP_NAME_INTERNAL 0074 #else // DEBUG 0075 //! returns caller name at the current scope or "top level" 0076 #define CALL_STACK_TOP_NAME (m_callsNamesDebug.isEmpty() \ 0077 ? QByteArray("top level") : m_callsNamesDebug.top()).constData() 0078 # define PUSH_NAME 0079 //! put at beginning of each read_*() method on call stack, only in debug mode 0080 # define PUSH_NAME_INTERNAL \ 0081 /*debugMsooXml << CALL_STACK_TOP_NAME << "==>" << QUALIFIED_NAME(CURRENT_EL); */\ 0082 m_callsNamesDebug.push(STRINGIFY(CURRENT_EL)); 0083 //! put at the end of each read_*() method on call stack, only in debug mode 0084 # define POP_NAME_INTERNAL \ 0085 m_callsNamesDebug.pop(); \ 0086 /*debugMsooXml << CALL_STACK_TOP_NAME << "<==" << QUALIFIED_NAME(CURRENT_EL); */ 0087 #endif 0088 0089 #define READ_PROLOGUE2(method) \ 0090 if (!expectEl(QUALIFIED_NAME(CURRENT_EL))) { \ 0091 return KoFilter::WrongFormat; \ 0092 } \ 0093 PUSH_NAME_INTERNAL \ 0094 0095 #define READ_PROLOGUE \ 0096 READ_PROLOGUE2(CURRENT_EL) 0097 0098 #define READ_PROLOGUE_IF_NS(ns) \ 0099 if (!expectEl(JOIN(STRINGIFY(ns) ":",CURRENT_EL))) { \ 0100 return KoFilter::WrongFormat; \ 0101 } \ 0102 PUSH_NAME_INTERNAL \ 0103 0104 #define READ_EPILOGUE_WITHOUT_RETURN \ 0105 POP_NAME_INTERNAL \ 0106 if (!expectElEnd(QUALIFIED_NAME(CURRENT_EL))) { \ 0107 /*debugMsooXml << "READ_EPILOGUE:" << QUALIFIED_NAME(CURRENT_EL) << "not found!"; */\ 0108 return KoFilter::WrongFormat; \ 0109 } \ 0110 /*debugMsooXml << "/READ_EPILOGUE_WITHOUT_RETURN";*/ 0111 0112 #define READ_EPILOGUE \ 0113 /*debugMsooXml << "READ_EPILOGUE";*/ \ 0114 READ_EPILOGUE_WITHOUT_RETURN \ 0115 return KoFilter::OK; 0116 0117 #define READ_EPILOGUE_IF_NS(ns) \ 0118 POP_NAME_INTERNAL \ 0119 if (!expectElEnd((JOIN(STRINGIFY(ns) ":",CURRENT_EL)))) { \ 0120 return KoFilter::WrongFormat; \ 0121 } \ 0122 return KoFilter::OK; 0123 0124 #define BREAK_IF_END_OF_QSTRING(name) \ 0125 /*debugMsooXml << "BREAK_IF_END_OF" << name << "found:" << qualifiedName();*/ \ 0126 if (isEndElement() && qualifiedName() == name) { \ 0127 break; \ 0128 } 0129 0130 #define BREAK_IF_END_OF(name) \ 0131 BREAK_IF_END_OF_QSTRING(QLatin1String(QUALIFIED_NAME(name))) 0132 0133 #define BREAK_IF_END_OF_WITH_NS(ns, name) \ 0134 BREAK_IF_END_OF_QSTRING(QLatin1String(JOIN(STRINGIFY(ns) ":",name))) 0135 0136 //inline bool aaaa(const char * aa) { debugMsooXml << "aa" << aa; return true; } 0137 0138 #define QUALIFIED_NAME_IS(name) \ 0139 (qualifiedName() == QLatin1String(QUALIFIED_NAME(name))) 0140 0141 #define TRY_READ_IF_INTERNAL(name, qname, context) \ 0142 if (qualifiedName() == QLatin1String(qname)) { \ 0143 if (!isStartElement()) { /* sanity check */ \ 0144 raiseError(i18n("Start element \"%1\" expected, found \"%2\"", \ 0145 QLatin1String(STRINGIFY(name)), tokenString())); \ 0146 return KoFilter::WrongFormat; \ 0147 } \ 0148 /*debugMsooXml << "TRY_READ_IF " STRINGIFY(name) " started";*/ \ 0149 TRY_READ_WITH_ARGS_INTERNAL(name, , context) \ 0150 /*debugMsooXml << "TRY_READ_IF " STRINGIFY(name) " finished";*/ \ 0151 } 0152 0153 #define TRY_READ_IF_IN_CONTEXT_INTERNAL(name, context) \ 0154 TRY_READ_IF_INTERNAL(name, QUALIFIED_NAME(name), context) 0155 0156 #define TRY_READ_IF_NS_IN_CONTEXT_INTERNAL(ns, name, context) \ 0157 TRY_READ_IF_INTERNAL(name, JOIN(STRINGIFY(ns) ":", name), context) 0158 0159 //! Tries to read element @a name by entering into read_{name} function. 0160 //! Must be enclosed within if (isStartElement()), otherwise error will be returned. 0161 #define TRY_READ_IF_IN_CONTEXT(name) \ 0162 TRY_READ_IF_IN_CONTEXT_INTERNAL(name, PASS_CONTEXT(name)) 0163 0164 #define TRY_READ_IF_NS_IN_CONTEXT(ns, name) \ 0165 TRY_READ_IF_NS_IN_CONTEXT_INTERNAL(ns, name, PASS_CONTEXT(name)) 0166 0167 #define TRY_READ_IF(name) \ 0168 TRY_READ_IF_IN_CONTEXT_INTERNAL(name,) 0169 0170 #define ELSE_TRY_READ_IF(name) \ 0171 else TRY_READ_IF_IN_CONTEXT_INTERNAL(name,) 0172 0173 #define ELSE_TRY_READ_IF_IN_CONTEXT(name) \ 0174 else TRY_READ_IF_IN_CONTEXT_INTERNAL(name, PASS_CONTEXT(name)) 0175 0176 #define ELSE_TRY_READ_IF_NS_IN_CONTEXT(ns, name) \ 0177 else TRY_READ_IF_NS_IN_CONTEXT_INTERNAL(ns, name, PASS_CONTEXT(name)) 0178 0179 #define TRY_READ_IF_NS_INTERNAL(ns, name) \ 0180 if (qualifiedName() == QLatin1String(JOIN(STRINGIFY(ns) ":", name))) { \ 0181 /*debugMsooXml << "TRY_READ_IF_NS " JOIN(STRINGIFY(ns) ":", name) " started";*/ \ 0182 TRY_READ(name); \ 0183 /*debugMsooXml << "TRY_READ_IF_NS " JOIN(STRINGIFY(ns) ":", name) " finished";*/ \ 0184 } 0185 0186 //! Like TRY_READ_IF() but namespace for explicit namespace @a ns. 0187 #define TRY_READ_IF_NS(ns, name) \ 0188 if (!isStartElement()) { /* sanity check */ \ 0189 raiseError(i18n("Start element \"%1\" expected, found \"%2\"", QLatin1String(JOIN(STRINGIFY(ns) ":", name)), tokenString())); \ 0190 return KoFilter::WrongFormat; \ 0191 } \ 0192 else TRY_READ_IF_NS_INTERNAL(ns, name) 0193 0194 #define ELSE_TRY_READ_IF_NS(ns, name) \ 0195 else TRY_READ_IF_NS_INTERNAL(ns, name) 0196 0197 #define ELSE_WRONG_FORMAT \ 0198 else { \ 0199 return KoFilter::WrongFormat; \ 0200 } 0201 0202 #define ELSE_WRONG_FORMAT_DEBUG(dbg) \ 0203 else { \ 0204 debugMsooXml << dbg; \ 0205 return KoFilter::WrongFormat; \ 0206 } 0207 0208 //! Reads optional attribute of name @a atrname and allocates variable of the same name. 0209 /*! Requires the following line to be present above: 0210 @code 0211 const QXmlStreamAttributes attrs( attributes() ); 0212 @endcode 0213 */ 0214 #define TRY_READ_ATTR(atrname) \ 0215 QString atrname( attrs.value(QUALIFIED_NAME(atrname)).toString() ); 0216 0217 //! Reads optional attribute of name @a atrname into the variable @a destination. 0218 /*! Requires the following line to be present above: 0219 @code 0220 const QXmlStreamAttributes attrs( attributes() ); 0221 @endcode 0222 */ 0223 #define TRY_READ_ATTR_INTO(atrname, destination) \ 0224 destination = attrs.value(QUALIFIED_NAME(atrname)).toString(); \ 0225 /*debugMsooXml << "TRY_READ_ATTR_INTO: " STRINGIFY(destination) << "=" << destination;*/ 0226 0227 //! Reads optional attribute of name @a atrname with explicitly specified namespace @a ns. 0228 /*! Creates QString variable with name \<ns\>_\<atrame\> 0229 */ 0230 /*! Requires the following line to be present above: 0231 @code 0232 const QXmlStreamAttributes attrs( attributes() ); 0233 @endcode 0234 */ 0235 #define TRY_READ_ATTR_WITH_NS(ns, atrname) \ 0236 QString PASTE3(ns, _, atrname)( attrs.value(JOIN(STRINGIFY(ns) ":", atrname)).toString() ); 0237 0238 //! Reads optional attribute of name @a atrname with explicitly specified namespace @a ns 0239 //! into the variable @a destination. 0240 /*! Requires the following line to be present above: 0241 @code 0242 const QXmlStreamAttributes attrs( attributes() ); 0243 @endcode 0244 */ 0245 #define TRY_READ_ATTR_WITH_NS_INTO(ns, atrname, destination) \ 0246 destination = attrs.value(JOIN(STRINGIFY(ns) ":", atrname)).toString(); \ 0247 /*debugMsooXml << "TRY_READ_ATTR_WITH_NS_INTO: " STRINGIFY(destination) << "=" << destination;*/ 0248 0249 inline QString atrToString(const QXmlStreamAttributes& attrs, const char* atrname) 0250 { 0251 const QStringRef v(attrs.value(atrname)); 0252 return v.isNull() ? QString() : v.toString(); 0253 } 0254 0255 //! Reads optional attribute of name @a atrname without namespace. 0256 /*! Creates QString variable with name \<atrname\> 0257 */ 0258 /*! Requires the following line to be present above: 0259 @code 0260 const QXmlStreamAttributes attrs( attributes() ); 0261 @endcode 0262 */ 0263 #define TRY_READ_ATTR_WITHOUT_NS(atrname) \ 0264 QString atrname( atrToString(attrs, STRINGIFY(atrname)) ); 0265 0266 //! Reads required attribute of name @a atrname and allocates variable of the same name 0267 //! If there is no such attribute, returns KoFilter::WrongFormat. 0268 /*! Requires the following line to be present above: 0269 @code 0270 const QXmlStreamAttributes attrs( attributes() ); 0271 @endcode 0272 */ 0273 #define READ_ATTR(atrname) \ 0274 QString atrname; \ 0275 if (attrs.hasAttribute(QUALIFIED_NAME(atrname))) { \ 0276 atrname = attrs.value(QUALIFIED_NAME(atrname)).toString(); \ 0277 } \ 0278 ELSE_WRONG_FORMAT_DEBUG( "READ_ATTR: " QUALIFIED_NAME(atrname) " not found" ) 0279 0280 //! Like @ref READ_ATTR(atrname) but reads the attribute into the variable @a destination. 0281 #define READ_ATTR_INTO(atrname, destination) \ 0282 if (attrs.hasAttribute(QUALIFIED_NAME(atrname))) { \ 0283 destination = attrs.value(QUALIFIED_NAME(atrname)).toString(); \ 0284 } \ 0285 ELSE_WRONG_FORMAT_DEBUG( "READ_ATTR_INTO: " QUALIFIED_NAME(atrname) " not found" ) 0286 0287 //! Reads required attribute of name @a atrname with explicitly specified namespace @a ns 0288 /*! into the variable @a destination. 0289 */ 0290 /*! Requires the following line to be present above: 0291 @code 0292 const QXmlStreamAttributes attrs( attributes() ); 0293 @endcode 0294 */ 0295 #define READ_ATTR_WITH_NS_INTO(ns, atrname, destination) \ 0296 if (attrs.hasAttribute(JOIN(STRINGIFY(ns) ":", atrname))) { \ 0297 destination = attrs.value(JOIN(STRINGIFY(ns) ":", atrname)).toString(); \ 0298 } \ 0299 ELSE_WRONG_FORMAT_DEBUG( "READ_ATTR_WITH_NS_INTO: " JOIN(STRINGIFY(ns) ":", atrname) " not found" ) 0300 0301 //! Reads required attribute of name @a atrname with explicitly specified namespace @a ns. 0302 /*! Creates QString variable with name \<ns\>_\<atrame\> 0303 */ 0304 /*! Requires the following line to be present above: 0305 @code 0306 const QXmlStreamAttributes attrs( attributes() ); 0307 @endcode 0308 */ 0309 #define READ_ATTR_WITH_NS(ns, atrname) \ 0310 QString PASTE3(ns, _, atrname); \ 0311 if (attrs.hasAttribute(JOIN(STRINGIFY(ns) ":", atrname))) { \ 0312 PASTE3(ns, _, atrname) = attrs.value(JOIN(STRINGIFY(ns) ":", atrname)).toString(); \ 0313 } \ 0314 ELSE_WRONG_FORMAT_DEBUG( "READ_ATTR_WITH_NS: " JOIN(STRINGIFY(ns) ":", atrname) " not found" ) 0315 0316 //! Reads required attribute of name @a atrname without namespace. 0317 /*! Creates QString variable with name \<atrname\> 0318 */ 0319 /*! Requires the following line to be present above: 0320 @code 0321 const QXmlStreamAttributes attrs( attributes() ); 0322 @endcode 0323 */ 0324 #define READ_ATTR_WITHOUT_NS(atrname) \ 0325 QString atrname; \ 0326 if (attrs.hasAttribute(STRINGIFY(atrname))) { \ 0327 atrname = attrs.value(STRINGIFY(atrname)).toString(); \ 0328 } \ 0329 ELSE_WRONG_FORMAT_DEBUG( "READ_ATTR_WITHOUT_NS: " STRINGIFY(atrname) " not found" ) 0330 0331 //! Like @ref READ_ATTR_WITHOUT_NS(atrname) but reads the attribute into the variable @a destination. 0332 #define READ_ATTR_WITHOUT_NS_INTO(atrname, destination) \ 0333 if (attrs.hasAttribute(STRINGIFY(atrname))) { \ 0334 destination = attrs.value(STRINGIFY(atrname)).toString(); \ 0335 } \ 0336 ELSE_WRONG_FORMAT_DEBUG( "READ_ATTR_WITHOUT_NS_INTO: " STRINGIFY(atrname) " not found" ) 0337 0338 0339 /*! Requires the following line to be present above: 0340 @code 0341 const QXmlStreamAttributes attrs( attributes() ); 0342 @endcode 0343 */ 0344 #define TRY_READ_ATTR_QSTRING(atrname) \ 0345 QString atrname( attrs.value(m_defaultNamespace + atrname).toString() ); 0346 0347 //! Like @ref TRY_READ_ATTR_WITHOUT_NS(atrname) but reads the attribute into the variable @a destination. 0348 #define TRY_READ_ATTR_WITHOUT_NS_INTO(atrname, destination) \ 0349 destination = attrs.value(STRINGIFY(atrname)).toString(); 0350 0351 //! reads boolean attribute "val" prefixed with default namespace, defaults to true 0352 #define READ_BOOLEAN_VAL \ 0353 readBooleanAttr(QUALIFIED_NAME(val), true) 0354 0355 //! Converts @a string into integer @a destination; returns KoFilter::WrongFormat on failure. 0356 //! @warning @a destination is left unchanged if @a string is empty, so it is up to developer to initialize it. 0357 #define STRING_TO_INT(string, destination, debugElement) \ 0358 if (string.isEmpty()) {} else { \ 0359 bool ok; \ 0360 const int val_tmp = string.toInt(&ok); \ 0361 if (!ok) { \ 0362 debugMsooXml << "STRING_TO_INT: error converting" << string << "to int (attribute" << debugElement << ")"; \ 0363 return KoFilter::WrongFormat; \ 0364 } \ 0365 destination = val_tmp; \ 0366 } 0367 0368 //! Converts @a string into longlong @a destination; returns KoFilter::WrongFormat on failure. 0369 //! @warning @a destination is left unchanged if @a string is empty, so it is up to developer to initialize it. 0370 #define STRING_TO_LONGLONG(string, destination, debugElement) \ 0371 if (string.isEmpty()) {} else { \ 0372 bool ok; \ 0373 const quint64 val_tmp = string.toLongLong(&ok); \ 0374 if (!ok) { \ 0375 debugMsooXml << "STRING_TO_LONGLONG: error converting" << string << "to LONGLONG (attribute" << debugElement << ")"; \ 0376 return KoFilter::WrongFormat; \ 0377 } \ 0378 destination = val_tmp; \ 0379 } 0380 0381 //! Converts @a string into a qreal value in @a destination; returns KoFilter::WrongFormat on failure. 0382 //! @warning @a destination is left unchanged if @a string is empty, so it is up to developer to initialize it. 0383 #define STRING_TO_QREAL(string, destination, debugElement) \ 0384 if (string.isEmpty()) {} else { \ 0385 bool ok; \ 0386 const qreal val_tmp = string.toDouble(&ok); \ 0387 if (!ok) { \ 0388 debugMsooXml << "STRING_TO_DOUBLE: error converting" << string << "to qreal (attribute" << debugElement << ")"; \ 0389 return KoFilter::WrongFormat; \ 0390 } \ 0391 destination = val_tmp; \ 0392 } 0393 0394 //! Skips everything until end of CURRENT_EL is pulled 0395 #define SKIP_EVERYTHING \ 0396 /*debugMsooXml << "Skipping everything in element" << qualifiedName() << "...";*/ \ 0397 const QString qn(qualifiedName().toString()); \ 0398 /*debugMsooXml << *this; */\ 0399 while (true) { \ 0400 readNext(); \ 0401 if (atEnd()) \ 0402 break; \ 0403 if (isEndElement() && qualifiedName() == qn) { \ 0404 break; \ 0405 } \ 0406 } 0407 0408 //! Skips elements, which cannot be interpreted at this time in order to avoid them 0409 // being read somewhere else 0410 #define SKIP_UNKNOWN \ 0411 else { \ 0412 skipCurrentElement(); \ 0413 } 0414 0415 #define SKIP_EVERYTHING_AND_RETURN \ 0416 SKIP_EVERYTHING \ 0417 return KoFilter::OK; 0418 0419 #define BIND_READ_METHOD(name, method) \ 0420 m_readMethods.insert(QLatin1String(name), &MSOOXML_CURRENT_CLASS::read_ ## method); 0421 0422 #define BIND_READ(name) \ 0423 BIND_READ_METHOD(STRINGIFY(name), name) 0424 0425 #define BIND_READ_SKIP(name) \ 0426 BIND_READ_METHOD(STRINGIFY(name), SKIP) 0427 0428 #define BIND_READ_METHOD_HASH(hash, name, method) \ 0429 hash.insert(QLatin1String(name), &MSOOXML_CURRENT_CLASS::read_ ## method); 0430 0431 #define BIND_READ_HASH(hash, name) \ 0432 BIND_READ_METHOD_HASH(hash, STRINGIFY(name), name) 0433 0434 #define BIND_READ_HASH_SKIP(hash, name) \ 0435 BIND_READ_METHOD_HASH(hash, STRINGIFY(name), SKIP) 0436 0437 #endif