Version 3.6.0.4, tag libreoffice-3.6.0.4
[LibreOffice.git] / svx / workben / msview / xmlconfig.cxx
blobb97e5f0d7bc9364fe31b4f532653003bdf46dcf0
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
30 #include <com/sun/star/xml/sax/XDocumentHandler.hpp>
31 #include <com/sun/star/xml/sax/InputSource.hpp>
32 #include <com/sun/star/xml/sax/XParser.hpp>
33 #include <com/sun/star/xml/sax/SAXParseException.hpp>
34 #include <com/sun/star/io/IOException.hpp>
35 #include <cppuhelper/implbase1.hxx>
36 #include <comphelper/processfactory.hxx>
37 #include <unotools/ucbstreamhelper.hxx>
38 #include <unotools/streamwrap.hxx>
39 #include "comphelper/anytostring.hxx"
40 #include "cppuhelper/exc_hlp.hxx"
41 #include "rtl/ref.hxx"
43 #include <svx/msdffimp.hxx>
45 #include "xmlconfig.hxx"
47 #include <stdio.h>
48 #include <ctype.h>
49 #include <stack>
51 using ::rtl::OUString;
52 using ::com::sun::star::io::XInputStream;
53 using ::com::sun::star::io::IOException;
55 using namespace ::com::sun::star::uno;
56 using namespace ::com::sun::star::xml::sax;
58 ///////////////////////////////////////////////////////////////////////
60 AtomConfigMap gAtomConfigMap;
62 ///////////////////////////////////////////////////////////////////////
64 class ConfigHandler : public ::cppu::WeakAggImplHelper1<XDocumentHandler>
66 public:
67 // XDocumentHandler
68 virtual void SAL_CALL startDocument(void) throw( SAXException, RuntimeException );
69 virtual void SAL_CALL endDocument(void) throw( SAXException, RuntimeException );
70 virtual void SAL_CALL startElement(const OUString& aName, const Reference< XAttributeList > & xAttribs) throw( SAXException, RuntimeException );
71 virtual void SAL_CALL endElement(const OUString& aName) throw( SAXException, RuntimeException );
72 virtual void SAL_CALL characters(const OUString& aChars) throw( SAXException, RuntimeException );
73 virtual void SAL_CALL ignorableWhitespace(const OUString& aWhitespaces) throw( SAXException, RuntimeException );
74 virtual void SAL_CALL processingInstruction(const OUString& aTarget, const OUString& aData) throw( SAXException, RuntimeException );
75 virtual void SAL_CALL setDocumentLocator(const Reference< XLocator > & xLocator) throw( SAXException, RuntimeException );
77 private:
78 void errorThrow( const OUString& rErrorMessage ) throw (SAXException );
79 ElementConfigType parseType( const OUString& rErrorMessage ) throw ( SAXException );
80 void addElement( ElementConfigPtr& rElementConfig ) throw ( SAXException );
81 OUString getAttribute( const Reference< XAttributeList > & xAttribs, const sal_Char* pName ) throw( SAXException );
83 ElementConfigPtr importAtomConfig( const Reference< XAttributeList > & xAttribs, bool bIsContainer ) throw( SAXException );
84 ElementConfigPtr importElementConfig( const Reference< XAttributeList > & xAttribs ) throw( SAXException );
85 ElementConfigPtr importSwitchConfig( const Reference< XAttributeList > & xAttribs ) throw( SAXException );
86 ElementConfigPtr importCaseConfig( const Reference< XAttributeList > & xAttribs ) throw( SAXException );
87 ElementConfigPtr importValueElementConfig( const Reference< XAttributeList > & xAttribs ) throw( SAXException );
89 std::stack< ElementConfigPtr > maElementStack;
92 void ConfigHandler::errorThrow( const OUString& rErrorMessage ) throw (SAXException )
94 Reference< XInterface > aContext;
95 Any aWrappedException;
96 throw SAXException(rErrorMessage, aContext, aWrappedException);
99 ElementConfigType ConfigHandler::parseType( const OUString& sType ) throw (SAXException )
101 if ( sType == "uint" )
103 return ECT_UINT;
105 else if ( sType == "byte" )
107 return ECT_BYTE;
109 else if ( sType == "unistring" )
111 return ECT_UNISTRING;
113 else if ( sType == "float" )
115 return ETC_FLOAT;
117 else if ( sType == "hexdump" )
120 else
122 OUString aMessage( "unknown type: " );
123 aMessage += sType;
124 errorThrow( aMessage );
127 return ECT_HEXDUMP;
130 void ConfigHandler::addElement( ElementConfigPtr& rElementConfig ) throw ( SAXException )
132 ElementConfigContainer* pParent = dynamic_cast< ElementConfigContainer* >( maElementStack.top().get() );
134 if( !pParent )
135 errorThrow( OUString( "illegal parent for element" ) );
138 pParent->addElementConfig( rElementConfig );
141 OUString ConfigHandler::getAttribute( const Reference< XAttributeList > & xAttribs, const sal_Char* pName ) throw( SAXException )
143 OUString aName( OUString::createFromAscii( pName ) );
145 const sal_Int16 nAttrCount = xAttribs.is() ? xAttribs->getLength() : 0;
146 sal_Int16 i;
147 for(i=0; i < nAttrCount; i++)
149 if( xAttribs->getNameByIndex( i ) == aName )
150 return xAttribs->getValueByIndex( i );
153 OUString aMessage( "missing required attribute: " );
154 aMessage += aName;
155 errorThrow( aMessage );
157 return OUString();
160 void SAL_CALL ConfigHandler::startDocument(void) throw( SAXException, RuntimeException )
164 void SAL_CALL ConfigHandler::endDocument(void) throw( SAXException, RuntimeException )
168 void SAL_CALL ConfigHandler::startElement(const OUString& aName, const Reference< XAttributeList > & xAttribs) throw( SAXException, RuntimeException )
170 ElementConfigPtr pElement;
172 if ( aName == "config" )
174 return;
177 if ( aName == "container" )
179 pElement = importAtomConfig( xAttribs, true );
181 else if ( aName == "atom" )
183 pElement = importAtomConfig( xAttribs, false );
185 else if ( aName == "element" )
187 pElement = importElementConfig( xAttribs );
189 else if ( aName == "value" )
191 pElement = importValueElementConfig( xAttribs );
193 else if ( aName == "switch" )
195 pElement = importSwitchConfig( xAttribs );
197 else if ( aName == "case" )
199 pElement = importCaseConfig( xAttribs );
202 if( !pElement.get() )
204 OUString aMessage( OUString( "unknown config element: ") );
205 aMessage += aName;
206 errorThrow( aMessage );
209 maElementStack.push( pElement );
212 sal_Int32 toInt( const OUString& rText )
214 if( rText.compareToAscii("0x",2) == 0)
216 sal_Int32 nValue = 0;
217 const sal_Unicode *p = rText;
218 p += 2;
219 sal_Int32 nLength = rText.getLength() - 2;
220 while( (nLength--) > 0 )
222 nValue <<= 4;
223 if( *p >= '0' && *p <= '9' )
225 nValue += *p - '0';
227 else if( *p >= 'a' && *p <= 'f' )
229 nValue += *p - ('a' - 10);
231 else if( *p >= 'A' && *p <= 'F' )
233 nValue += *p - ('A' - 10 );
235 p++;
238 return nValue;
240 else
242 return rText.toInt32();
246 ElementConfigPtr ConfigHandler::importAtomConfig( const Reference< XAttributeList > & xAttribs, bool bIsContainer ) throw (SAXException)
248 if( !maElementStack.empty() )
249 errorThrow( OUString( "atom elements must be root" ) );
251 ElementConfigPtr aPtr( new AtomConfig( getAttribute(xAttribs,"name"), bIsContainer ) );
252 gAtomConfigMap[ (UINT16)toInt(getAttribute(xAttribs,"id"))] = aPtr;
253 return aPtr;
256 ElementConfigPtr ConfigHandler::importElementConfig( const Reference< XAttributeList > & xAttribs ) throw (SAXException)
258 ElementConfigType nType = parseType( getAttribute( xAttribs, "type" ) );
259 ElementConfigPtr pElementConfig( new ElementConfigContainer( getAttribute( xAttribs, "name" ), nType ) );
260 addElement( pElementConfig );
261 return pElementConfig;
264 ElementConfigPtr ConfigHandler::importValueElementConfig( const Reference< XAttributeList > & xAttribs ) throw (SAXException)
266 ElementConfigPtr pElementConfig( new ElementValueConfig( getAttribute( xAttribs, "name" ), getAttribute( xAttribs, "value" ) ) );
267 addElement( pElementConfig );
268 return pElementConfig;
271 ElementConfigPtr ConfigHandler::importSwitchConfig( const Reference< XAttributeList > & xAttribs ) throw (SAXException)
273 ElementConfigType nType = parseType( getAttribute( xAttribs, "type" ) );
274 ElementConfigPtr pElementConfig( new SwitchElementConfig( nType ) );
275 addElement( pElementConfig );
276 return pElementConfig;
279 ElementConfigPtr ConfigHandler::importCaseConfig( const Reference< XAttributeList > & xAttribs ) throw (SAXException)
281 ElementConfigPtr pElementConfig( new CaseElementConfig( getAttribute( xAttribs, "value" ) ) );
282 addElement( pElementConfig );
283 return pElementConfig;
286 void SAL_CALL ConfigHandler::endElement(const OUString& aName) throw( SAXException, RuntimeException )
288 if ( aName == "config" )
290 return;
293 maElementStack.pop();
296 void SAL_CALL ConfigHandler::characters(const OUString& aChars) throw( SAXException, RuntimeException )
300 void SAL_CALL ConfigHandler::ignorableWhitespace(const OUString& aWhitespaces) throw( SAXException, RuntimeException )
304 void SAL_CALL ConfigHandler::processingInstruction(const OUString& aTarget, const OUString& aData) throw( SAXException, RuntimeException )
308 void SAL_CALL ConfigHandler::setDocumentLocator(const Reference< XLocator > & xLocator) throw( SAXException, RuntimeException )
312 void load_config( const OUString& rPath )
316 // create stream
317 SvStream* pIStm = ::utl::UcbStreamHelper::CreateStream( rPath, STREAM_READ );
318 Reference<XInputStream> xInputStream( new utl::OInputStreamWrapper( pIStm, sal_True ) );
320 // prepare ParserInputSrouce
321 InputSource aParserInput;
322 aParserInput.sSystemId = rPath;
323 aParserInput.aInputStream = xInputStream;
325 // get parser
326 Reference< XParser > xParser(
327 comphelper::getProcessServiceFactory()->createInstance(
328 OUString("com.sun.star.xml.sax.Parser") ),
329 UNO_QUERY_THROW );
331 // get filter
332 ConfigHandler* pConfigHandler = new ConfigHandler();
333 Reference< XDocumentHandler > xFilter( pConfigHandler );
335 // connect parser and filter
336 xParser->setDocumentHandler( xFilter );
338 // finally, parser the stream
339 xParser->parseStream( aParserInput );
341 catch( Exception& )
343 OSL_FAIL(
344 (rtl::OString("load_config(), "
345 "exception caught: ") +
346 rtl::OUStringToOString(
347 comphelper::anyToString( cppu::getCaughtException() ),
348 RTL_TEXTENCODING_UTF8 )).getStr() );
352 ///////////////////////////////////////////////////////////////////////
354 rtl::OUString ElementConfig::format( SvStream& rStream, sal_Size& nLength ) const
356 OUString aRet;
357 if( maName.getLength() )
359 aRet += maName;
360 aRet += OUString( " = " );
363 switch( mnType )
365 case ECT_BYTE: aRet += dump_byte( rStream, nLength ); break;
366 case ECT_UINT: aRet += dump_uint( rStream, nLength ); break;
367 case ECT_UNISTRING: aRet += dump_unistring( rStream, nLength ); break;
368 case ETC_FLOAT: aRet += dump_float( rStream, nLength ); break;
369 case ECT_HEXDUMP:
370 default: aRet += dump_hex( rStream, nLength ); break;
373 return aRet;
376 rtl::OUString ElementConfig::dump_hex( SvStream& rStream, sal_Size& nLength )
378 char buffer[128];
379 OUString aOut, aEmpty;
380 OUString aHex, aAscii;
381 sal_Char c;
382 int nRow = 0;
383 while( nLength && (rStream.GetError() == 0) )
385 rStream >> c;
386 nLength--;
388 unsigned int i = c;
389 i &= 0xff;
390 sprintf( buffer, "%02x ", i );
391 aHex += OUString::createFromAscii( buffer );
393 if( !isprint( c ) )
394 c = '.';
396 aAscii += OUString( (sal_Unicode) c );
397 nRow++;
399 if( (nRow == 16) || (nLength==0) )
401 while( aHex.getLength() < (16*3) )
402 aHex += OUString( " " );
403 aOut += aHex;
404 aOut += aAscii;
405 aOut += OUString( "\n\r" );
406 aHex = aEmpty;
407 aAscii = aEmpty;
408 nRow = 0;
412 aOut += aHex;
413 aOut += aAscii;
415 return aOut;
418 rtl::OUString ElementConfig::dump_byte( SvStream& rStream, sal_Size& nLength )
420 OUString aRet;
421 if( nLength >= sizeof(sal_Char) )
423 sal_Char c;
424 rStream >> c;
426 char buffer[128];
427 sprintf( buffer, "%u", (int)c );
428 aRet += OUString::createFromAscii( buffer );
429 nLength -= sizeof(sal_Char);
432 return aRet;
435 rtl::OUString ElementConfig::dump_uint( SvStream& rStream, sal_Size& nLength )
437 OUString aRet;
438 if( nLength >= sizeof( sal_uInt32 ) )
440 sal_uInt32 c;
441 rStream >> c;
443 char buffer[128];
444 sprintf( buffer, "%u", c );
445 aRet += OUString::createFromAscii( buffer );
446 nLength-= sizeof( sal_uInt32 );
449 return aRet;
452 rtl::OUString ElementConfig::dump_unistring( SvStream& rStream, sal_Size& nLength )
454 String aString = SvxMSDffManager::MSDFFReadZString( rStream, nLength, sal_True );
455 nLength = 0;
456 return aString;
459 rtl::OUString ElementConfig::dump_float( SvStream& rStream, sal_Size& nLength )
461 OUString aRet;
462 if( nLength >= sizeof( float ) )
464 float c;
465 rStream >> c;
467 char buffer[128];
468 sprintf( buffer, "%g", (double)c );
469 aRet += OUString::createFromAscii( buffer );
470 nLength-= sizeof( float );
473 return aRet;
476 ///////////////////////////////////////////////////////////////////////
478 rtl::OUString ElementConfigContainer::format( SvStream& rStream, sal_Size& nLength ) const
480 OUString aRet;
482 if( getType() == ETC_CONTAINER )
485 ElementConfigList::const_iterator aIter( maElementConfigList.begin() );
486 const ElementConfigList::const_iterator aEnd( maElementConfigList.end() );
487 while( (aIter != aEnd) && (nLength > 0) )
489 aRet += (*aIter++)->format( rStream, nLength );
490 if( (aIter != aEnd) || (nLength != 0) )
491 aRet += OUString( "\n\r" );
494 if( nLength )
495 aRet += ElementConfig::dump_hex( rStream, nLength );
497 else
499 aRet = getName();
500 if( aRet.getLength() )
501 aRet += OUString( " = " );
503 OUString aValue;
504 switch( getType() )
506 case ECT_BYTE: aValue = dump_byte( rStream, nLength ); break;
507 case ECT_UINT: aValue = dump_uint( rStream, nLength ); break;
508 case ECT_UNISTRING: aValue = dump_unistring( rStream, nLength ); break;
509 case ETC_FLOAT: aValue = dump_float( rStream, nLength ); break;
510 case ECT_HEXDUMP:
511 default: aValue = dump_hex( rStream, nLength ); break;
514 if( aValue.getLength() )
516 if( !maElementConfigList.empty() )
518 ElementConfigList::const_iterator aIter( maElementConfigList.begin() );
519 const ElementConfigList::const_iterator aEnd( maElementConfigList.end() );
520 while( (aIter != aEnd) && (nLength > 0) )
522 ElementValueConfig* pValue = dynamic_cast< ElementValueConfig* >( (*aIter++).get() );
523 if( pValue && pValue->getValue() == aValue )
525 aValue = pValue->getName();
526 break;
531 else
533 aValue = OUString( "<empty!?>" );
536 aRet += aValue;
539 return aRet;
542 ///////////////////////////////////////////////////////////////////////
544 rtl::OUString SwitchElementConfig::format( SvStream& rStream, sal_Size& nLength ) const
546 OUString aValue;
548 switch( getType() )
550 case ECT_BYTE: aValue = dump_byte( rStream, nLength ); break;
551 case ECT_UINT: aValue = dump_uint( rStream, nLength ); break;
552 case ETC_FLOAT: aValue = dump_float( rStream, nLength ); break;
553 case ECT_UNISTRING: aValue = dump_unistring( rStream, nLength ); break;
556 if( aValue.getLength() )
558 ElementConfigList::const_iterator aIter( maElementConfigList.begin() );
559 const ElementConfigList::const_iterator aEnd( maElementConfigList.end() );
560 while( (aIter != aEnd) && (nLength > 0) )
562 CaseElementConfig* pCase = dynamic_cast< CaseElementConfig* >( (*aIter++).get() );
563 if( pCase && pCase->getValue() == aValue )
564 return pCase->format( rStream, nLength );
568 return ElementConfig::dump_hex( rStream, nLength );
571 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */