build fix
[LibreOffice.git] / sax / test / saxdemo.cxx
blob419ce7ea799b93daaec582a7711b50c9949a16ed
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/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 // testcomponent - Loads a service and its testcomponent from dlls performs a test.
22 // Expands the dll-names depending on the actual environment.
23 // Example : testcomponent com.sun.star.io.Pipe stm
25 // Therefore the testcode must exist in teststm and the testservice must be named test.com.sun.star.uno.io.Pipe
28 #include <stdio.h>
29 #include <vector>
30 #include <cstring>
32 #include <com/sun/star/registry/XImplementationRegistration.hpp>
33 #include <com/sun/star/lang/XComponent.hpp>
35 #include <com/sun/star/xml/sax/SAXParseException.hpp>
36 #include <com/sun/star/xml/sax/XParser.hpp>
37 #include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp>
39 #include <com/sun/star/io/XOutputStream.hpp>
40 #include <com/sun/star/io/XActiveDataSource.hpp>
42 #include <cppuhelper/servicefactory.hxx>
43 #include <cppuhelper/implbase.hxx>
45 #include <osl/diagnose.h>
47 using namespace ::std;
48 using namespace ::cppu;
49 using namespace ::com::sun::star::uno;
50 using namespace ::com::sun::star::lang;
51 using namespace ::com::sun::star::registry;
52 using namespace ::com::sun::star::xml::sax;
53 using namespace ::com::sun::star::io;
56 /************
57 * Sequence of bytes -> InputStream
58 ************/
59 class OInputStream : public WeakImplHelper < XInputStream >
61 public:
62 explicit OInputStream( const Sequence< sal_Int8 >&seq ) :
63 m_seq( seq ),
64 nPos( 0 )
67 public:
68 virtual sal_Int32 SAL_CALL readBytes( Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead )
69 throw(NotConnectedException, BufferSizeExceededException, IOException, RuntimeException)
71 nBytesToRead = (nBytesToRead > m_seq.getLength() - nPos ) ?
72 m_seq.getLength() - nPos :
73 nBytesToRead;
74 aData = Sequence< sal_Int8 > ( &(m_seq.getConstArray()[nPos]) , nBytesToRead );
75 nPos += nBytesToRead;
76 return nBytesToRead;
78 virtual sal_Int32 SAL_CALL readSomeBytes(
79 css::uno::Sequence< sal_Int8 >& aData,
80 sal_Int32 nMaxBytesToRead )
81 throw(NotConnectedException, BufferSizeExceededException, IOException, RuntimeException)
83 return readBytes( aData, nMaxBytesToRead );
85 virtual void SAL_CALL skipBytes( sal_Int32 /* nBytesToSkip */ )
86 throw(NotConnectedException, BufferSizeExceededException, IOException, RuntimeException)
88 // not implemented
90 virtual sal_Int32 SAL_CALL available( )
91 throw(NotConnectedException, IOException, RuntimeException)
93 return m_seq.getLength() - nPos;
95 virtual void SAL_CALL closeInput( )
96 throw(NotConnectedException, IOException, RuntimeException)
98 // not needed
100 Sequence< sal_Int8> m_seq;
101 sal_Int32 nPos;
105 // Helper : create an input stream from a file
107 Reference< XInputStream > createStreamFromFile(
108 const char *pcFile )
110 FILE *f = fopen( pcFile , "rb" );
111 Reference< XInputStream > r;
113 if( f ) {
114 fseek( f , 0 , SEEK_END );
115 int nLength = ftell( f );
116 fseek( f , 0 , SEEK_SET );
118 Sequence<sal_Int8> seqIn(nLength);
119 fread( seqIn.getArray() , nLength , 1 , f );
121 r.set( new OInputStream( seqIn ) );
122 fclose( f );
124 return r;
128 // The document handler, which is needed for the saxparser
129 // The Documenthandler for reading sax
131 class TestDocumentHandler :
132 public WeakImplHelper< XExtendedDocumentHandler , XEntityResolver , XErrorHandler >
134 public:
135 TestDocumentHandler( )
139 public: // Error handler
140 virtual void SAL_CALL error(const Any& aSAXParseException) throw (SAXException, RuntimeException)
142 printf( "Error !\n" );
143 throw SAXException(
144 OUString( "error from error handler") ,
145 Reference < XInterface >() ,
146 aSAXParseException );
148 virtual void SAL_CALL fatalError(const Any& /* aSAXParseException */) throw (SAXException, RuntimeException)
150 printf( "Fatal Error !\n" );
152 virtual void SAL_CALL warning(const Any& /* aSAXParseException */) throw (SAXException, RuntimeException)
154 printf( "Warning !\n" );
158 public: // ExtendedDocumentHandler
160 virtual void SAL_CALL startDocument() throw (SAXException, RuntimeException)
162 m_iElementCount = 0;
163 m_iAttributeCount = 0;
164 m_iWhitespaceCount =0;
165 m_iCharCount=0;
166 printf( "document started\n" );
168 virtual void SAL_CALL endDocument() throw (SAXException, RuntimeException)
170 printf( "document finished\n" );
171 printf( "(ElementCount %d),(AttributeCount %d),(WhitespaceCount %d),(CharCount %d)\n",
172 m_iElementCount, m_iAttributeCount, m_iWhitespaceCount , m_iCharCount );
175 virtual void SAL_CALL startElement(const OUString& /* aName */,
176 const Reference< XAttributeList > & xAttribs)
177 throw (SAXException,RuntimeException)
179 m_iElementCount ++;
180 m_iAttributeCount += xAttribs->getLength();
183 virtual void SAL_CALL endElement(const OUString& /* aName */) throw (SAXException,RuntimeException)
185 // ignored
188 virtual void SAL_CALL characters(const OUString& aChars) throw (SAXException,RuntimeException)
190 m_iCharCount += aChars.getLength();
192 virtual void SAL_CALL ignorableWhitespace(const OUString& aWhitespaces) throw (SAXException,RuntimeException)
194 m_iWhitespaceCount += aWhitespaces.getLength();
197 virtual void SAL_CALL processingInstruction(const OUString& /* aTarget */, const OUString& /* aData */) throw (SAXException,RuntimeException)
199 // ignored
202 virtual void SAL_CALL setDocumentLocator(const Reference< XLocator> & /* xLocator */)
203 throw (SAXException,RuntimeException)
205 // ignored
208 virtual InputSource SAL_CALL resolveEntity(
209 const OUString& sPublicId,
210 const OUString& sSystemId)
211 throw (RuntimeException)
213 InputSource source;
214 source.sSystemId = sSystemId;
215 source.sPublicId = sPublicId;
217 source.aInputStream = createStreamFromFile(
218 OUStringToOString( sSystemId, RTL_TEXTENCODING_ASCII_US).getStr() );
220 return source;
223 virtual void SAL_CALL startCDATA() throw (SAXException,RuntimeException)
226 virtual void SAL_CALL endCDATA() throw (SAXException,RuntimeException)
229 virtual void SAL_CALL comment(const OUString& /* sComment */) throw (SAXException,RuntimeException)
232 virtual void SAL_CALL unknown(const OUString& /* sString */) throw (SAXException,RuntimeException)
236 virtual void SAL_CALL allowLineBreak() throw (SAXException, RuntimeException )
241 public:
242 int m_iElementCount;
243 int m_iAttributeCount;
244 int m_iWhitespaceCount;
245 int m_iCharCount;
249 // helper implementation for writing
250 // implements an XAttributeList
252 struct AttributeListImpl_impl;
253 class AttributeListImpl : public WeakImplHelper< XAttributeList >
255 public:
256 AttributeListImpl();
257 AttributeListImpl( const AttributeListImpl & );
258 ~AttributeListImpl();
260 public:
261 virtual sal_Int16 SAL_CALL getLength() throw (RuntimeException);
262 virtual OUString SAL_CALL getNameByIndex(sal_Int16 i) throw (RuntimeException);
263 virtual OUString SAL_CALL getTypeByIndex(sal_Int16 i) throw (RuntimeException);
264 virtual OUString SAL_CALL getTypeByName(const OUString& aName) throw (RuntimeException);
265 virtual OUString SAL_CALL getValueByIndex(sal_Int16 i) throw (RuntimeException);
266 virtual OUString SAL_CALL getValueByName(const OUString& aName) throw (RuntimeException);
268 public:
269 void addAttribute( const OUString &sName ,
270 const OUString &sType ,
271 const OUString &sValue );
272 void clear();
274 private:
275 struct AttributeListImpl_impl *m_pImpl;
279 struct TagAttribute
281 TagAttribute(){}
282 TagAttribute( const OUString &s_Name,
283 const OUString &s_Type ,
284 const OUString &s_Value )
286 this->sName = s_Name;
287 this->sType = s_Type;
288 this->sValue = s_Value;
291 OUString sName;
292 OUString sType;
293 OUString sValue;
296 struct AttributeListImpl_impl
298 AttributeListImpl_impl()
300 // performance improvement during adding
301 vecAttribute.reserve(20);
303 vector<struct TagAttribute> vecAttribute;
307 sal_Int16 AttributeListImpl::getLength() throw (RuntimeException)
309 return (sal_Int16) m_pImpl->vecAttribute.size();
313 AttributeListImpl::AttributeListImpl( const AttributeListImpl &r )
315 m_pImpl = new AttributeListImpl_impl;
316 *m_pImpl = *(r.m_pImpl);
319 OUString AttributeListImpl::getNameByIndex(sal_Int16 i) throw (RuntimeException)
321 if( i < sal::static_int_cast<sal_Int16>(m_pImpl->vecAttribute.size()) ) {
322 return m_pImpl->vecAttribute[i].sName;
324 return OUString();
328 OUString AttributeListImpl::getTypeByIndex(sal_Int16 i) throw (RuntimeException)
330 if( i < sal::static_int_cast<sal_Int16>(m_pImpl->vecAttribute.size()) ) {
331 return m_pImpl->vecAttribute[i].sType;
333 return OUString();
336 OUString AttributeListImpl::getValueByIndex(sal_Int16 i) throw (RuntimeException)
338 if( i < sal::static_int_cast<sal_Int16>(m_pImpl->vecAttribute.size()) ) {
339 return m_pImpl->vecAttribute[i].sValue;
341 return OUString();
345 OUString AttributeListImpl::getTypeByName( const OUString& sName ) throw (RuntimeException)
347 vector<struct TagAttribute>::iterator ii = m_pImpl->vecAttribute.begin();
349 for( ; ii != m_pImpl->vecAttribute.end() ; ++ii ) {
350 if( (*ii).sName == sName ) {
351 return (*ii).sType;
354 return OUString();
357 OUString AttributeListImpl::getValueByName(const OUString& sName) throw (RuntimeException)
359 vector<struct TagAttribute>::iterator ii = m_pImpl->vecAttribute.begin();
361 for( ; ii != m_pImpl->vecAttribute.end() ; ++ii ) {
362 if( (*ii).sName == sName ) {
363 return (*ii).sValue;
366 return OUString();
370 AttributeListImpl::AttributeListImpl()
372 m_pImpl = new AttributeListImpl_impl;
376 AttributeListImpl::~AttributeListImpl()
378 delete m_pImpl;
382 void AttributeListImpl::addAttribute( const OUString &sName ,
383 const OUString &sType ,
384 const OUString &sValue )
386 m_pImpl->vecAttribute.push_back( TagAttribute( sName , sType , sValue ) );
389 void AttributeListImpl::clear()
391 m_pImpl->vecAttribute.clear();
395 // helper function for writing
396 // ensures that linebreaks are inserted
397 // when writing a long text.
398 // Note: this implementation may be a bit slow,
399 // but it shows, how the SAX-Writer handles the allowLineBreak calls.
401 void writeParagraphHelper(
402 const Reference< XExtendedDocumentHandler > &r ,
403 const OUString & s)
405 int nMax = s.getLength();
406 int nStart = 0;
407 int n = 1;
409 Sequence<sal_uInt16> seq( s.getLength() );
410 memcpy( seq.getArray() , s.getStr() , s.getLength() * sizeof( sal_uInt16 ) );
412 for( n = 1 ; n < nMax ; n++ ){
413 if( 32 == seq.getArray()[n] ) {
414 r->allowLineBreak();
415 r->characters( s.copy( nStart , n - nStart ) );
416 nStart = n;
419 r->allowLineBreak();
420 r->characters( s.copy( nStart , n - nStart ) );
424 // helper implementation for SAX-Writer
425 // writes data to a file
427 class OFileWriter :
428 public WeakImplHelper< XOutputStream >
430 public:
431 explicit OFileWriter( char *pcFile ) { strncpy( m_pcFile , pcFile, 256 - 1 ); m_f = 0; }
434 public:
435 virtual void SAL_CALL writeBytes(const Sequence< sal_Int8 >& aData)
436 throw (NotConnectedException, BufferSizeExceededException, RuntimeException);
437 virtual void SAL_CALL flush()
438 throw (NotConnectedException, BufferSizeExceededException, RuntimeException);
439 virtual void SAL_CALL closeOutput()
440 throw (NotConnectedException, BufferSizeExceededException, RuntimeException);
441 private:
442 char m_pcFile[256];
443 FILE *m_f;
447 void OFileWriter::writeBytes(const Sequence< sal_Int8 >& aData)
448 throw (NotConnectedException, BufferSizeExceededException, RuntimeException)
450 if( ! m_f ) {
451 m_f = fopen( m_pcFile , "w" );
454 fwrite( aData.getConstArray() , 1 , aData.getLength() , m_f );
458 void OFileWriter::flush()
459 throw (NotConnectedException, BufferSizeExceededException, RuntimeException)
461 fflush( m_f );
464 void OFileWriter::closeOutput()
465 throw (NotConnectedException, BufferSizeExceededException, RuntimeException)
467 fclose( m_f );
468 m_f = 0;
472 // Needed to switch on solaris threads
473 #ifdef SOLARIS
474 extern "C" void ChangeGlobalInit();
475 #endif
476 int main (int argc, char **argv)
479 if( argc < 3) {
480 printf( "usage : saxdemo inputfile outputfile\n" );
481 exit( 0 );
483 #ifdef SOLARIS
484 // switch on threads in solaris
485 ChangeGlobalInit();
486 #endif
488 // create service manager
489 Reference< XMultiServiceFactory > xSMgr = createRegistryServiceFactory(
490 OUString( "applicat.rdb" ) );
492 Reference < XImplementationRegistration > xReg;
495 // Create registration service
496 Reference < XInterface > x = xSMgr->createInstance( "com.sun.star.registry.ImplementationRegistration" );
497 xReg.set( x , UNO_QUERY );
499 catch( Exception & ) {
500 printf( "Couldn't create ImplementationRegistration service\n" );
501 exit(1);
504 OString sTestName;
507 // Load dll for the tested component
508 OUString aDllName( "sax.uno" SAL_DLLEXTENSION );
509 xReg->registerImplementation(
510 OUString("com.sun.star.loader.SharedLibrary"),
511 aDllName,
512 Reference< XSimpleRegistry > () );
514 catch( Exception &e ) {
515 printf( "Couldn't reach sax dll\n" );
516 printf( "%s\n" , OUStringToOString( e.Message , RTL_TEXTENCODING_ASCII_US ).getStr() );
518 exit(1);
522 // parser demo
523 // read xml from a file and count elements
525 Reference< XInterface > x = xSMgr->createInstance( "com.sun.star.xml.sax.Parser" );
526 if( x.is() )
528 Reference< XParser > rParser( x , UNO_QUERY );
530 // create and connect the document handler to the parser
531 TestDocumentHandler *pDocHandler = new TestDocumentHandler( );
533 Reference < XDocumentHandler > rDocHandler( (XDocumentHandler *) pDocHandler );
534 Reference< XEntityResolver > rEntityResolver( (XEntityResolver *) pDocHandler );
536 rParser->setDocumentHandler( rDocHandler );
537 rParser->setEntityResolver( rEntityResolver );
539 // create the input stream
540 InputSource source;
541 source.aInputStream = createStreamFromFile( argv[1] );
542 source.sSystemId = OUString::createFromAscii( argv[1] );
546 // start parsing
547 rParser->parseStream( source );
550 catch( Exception & e )
552 OString o1 = OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8 );
553 printf( "Exception during parsing : %s\n" , o1.getStr() );
556 else
558 printf( "couldn't create sax-parser component\n" );
562 // The SAX-Writer demo
564 x= xSMgr->createInstance("com.sun.star.xml.sax.Writer");
565 if( x.is() )
567 printf( "start writing to %s\n" , argv[2] );
569 OFileWriter *pw = new OFileWriter( argv[2] );
570 Reference< XActiveDataSource > source( x , UNO_QUERY );
571 source->setOutputStream( Reference< XOutputStream> ( (XOutputStream*) pw ) );
573 AttributeListImpl *pList = new AttributeListImpl;
574 Reference< XAttributeList > rList( (XAttributeList *) pList );
576 Reference< XExtendedDocumentHandler > r( x , UNO_QUERY );
577 r->startDocument();
579 pList->addAttribute( OUString( "Arg1" ),
580 OUString( "CDATA") ,
581 OUString( "foo\n u") );
582 pList->addAttribute( OUString( "Arg2") ,
583 OUString( "CDATA") ,
584 OUString( "foo2") );
586 r->startElement( OUString( "tag1") , rList );
587 // tells the writer to insert a linefeed
588 r->ignorableWhitespace( OUString() );
590 r->characters( OUString( "huhu") );
591 r->ignorableWhitespace( OUString() );
593 r->startElement( OUString( "hi") , rList );
594 r->ignorableWhitespace( OUString() );
596 // the enpassant must be converted & -> &amp;
597 r->characters( OUString( "&#252;") );
598 r->ignorableWhitespace( OUString() );
600 // '>' must not be converted
601 r->startCDATA();
602 r->characters( OUString( " > foo < ") );
603 r->endCDATA();
604 r->ignorableWhitespace( OUString() );
606 OUString testParagraph = OUString(
607 "This is only a test to check, if the writer inserts line feeds "
608 "if needed or if the writer puts the whole text into one line." );
609 writeParagraphHelper( r , testParagraph );
611 r->ignorableWhitespace( OUString() );
612 r->comment( OUString( "This is a comment !") );
613 r->ignorableWhitespace( OUString() );
615 r->startElement( OUString( "emptytagtest") , rList );
616 r->endElement( OUString( "emptytagtest") );
617 r->ignorableWhitespace( OUString() );
619 r->endElement( OUString( "hi") );
620 r->ignorableWhitespace( OUString() );
622 r->endElement( OUString( "tag1") );
623 r->endDocument();
625 printf( "finished writing\n" );
627 else
629 printf( "couldn't create sax-writer component\n" );
633 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */