1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sdext.hxx"
26 
27 #include "odfemitter.hxx"
28 
29 #include <rtl/ustrbuf.hxx>
30 #include <cppuhelper/exc_hlp.hxx>
31 #include <com/sun/star/io/XInputStream.hpp>
32 #include <com/sun/star/io/XOutputStream.hpp>
33 #include <boost/bind.hpp>
34 
35 using namespace com::sun::star;
36 
37 namespace pdfi
38 {
39 
40 class OdfEmitter : public XmlEmitter
41 {
42 private:
43     uno::Reference<io::XOutputStream> m_xOutput;
44     uno::Sequence<sal_Int8>           m_aLineFeed;
45     uno::Sequence<sal_Int8>           m_aBuf;
46 
47 public:
48     explicit OdfEmitter( const uno::Reference<io::XOutputStream>& xOutput );
49 
50     virtual void beginTag( const char* pTag, const PropertyMap& rProperties );
51     virtual void write( const rtl::OUString& rString );
52     virtual void endTag( const char* pTag );
53 };
54 
OdfEmitter(const uno::Reference<io::XOutputStream> & xOutput)55 OdfEmitter::OdfEmitter( const uno::Reference<io::XOutputStream>& xOutput ) :
56     m_xOutput( xOutput ),
57     m_aLineFeed(1),
58     m_aBuf()
59 {
60     OSL_PRECOND(m_xOutput.is(), "OdfEmitter(): invalid output stream");
61     m_aLineFeed[0] = '\n';
62 
63     rtl::OUStringBuffer aElement;
64     aElement.appendAscii("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
65     write(aElement.makeStringAndClear());
66 }
67 
beginTag(const char * pTag,const PropertyMap & rProperties)68 void OdfEmitter::beginTag( const char* pTag, const PropertyMap& rProperties )
69 {
70     OSL_PRECOND(pTag,"Invalid tag string");
71 
72     rtl::OUStringBuffer aElement;
73     aElement.appendAscii("<");
74     aElement.appendAscii(pTag);
75     aElement.appendAscii(" ");
76 
77     std::vector<rtl::OUString>        aAttributes;
78     PropertyMap::const_iterator       aCurr(rProperties.begin());
79     const PropertyMap::const_iterator aEnd(rProperties.end());
80     while( aCurr != aEnd )
81     {
82         rtl::OUStringBuffer aAttribute;
83         aAttribute.append(aCurr->first);
84         aAttribute.appendAscii("=\"");
85         aAttribute.append(aCurr->second);
86         aAttribute.appendAscii("\" ");
87         aAttributes.push_back(aAttribute.makeStringAndClear());
88         ++aCurr;
89     }
90 
91     // since the hash map's sorting is undefined (and varies across
92     // platforms, and even between different compile-time settings),
93     // sort the attributes.
94     std::sort(aAttributes.begin(), aAttributes.end());
95     std::for_each(aAttributes.begin(),
96                   aAttributes.end(),
97                   boost::bind( (rtl::OUStringBuffer& (rtl::OUStringBuffer::*)(const rtl::OUString&))
98                                (&rtl::OUStringBuffer::append),
99                                boost::ref(aElement),
100                                _1 ));
101     aElement.appendAscii(">");
102 
103     write(aElement.makeStringAndClear());
104 }
105 
write(const rtl::OUString & rText)106 void OdfEmitter::write( const rtl::OUString& rText )
107 {
108     const rtl::OString aStr = rtl::OUStringToOString(rText,RTL_TEXTENCODING_UTF8);
109     const sal_Int32 nLen( aStr.getLength() );
110     m_aBuf.realloc( nLen );
111     const sal_Char* pStr = aStr.getStr();
112     std::copy(pStr,pStr+nLen,m_aBuf.getArray());
113 
114     m_xOutput->writeBytes(m_aBuf);
115     m_xOutput->writeBytes(m_aLineFeed);
116 }
117 
endTag(const char * pTag)118 void OdfEmitter::endTag( const char* pTag )
119 {
120     rtl::OUStringBuffer aElement;
121     aElement.appendAscii("</");
122     aElement.appendAscii(pTag);
123     aElement.appendAscii(">");
124     write(aElement.makeStringAndClear());
125 }
126 
createOdfEmitter(const uno::Reference<io::XOutputStream> & xOut)127 XmlEmitterSharedPtr createOdfEmitter( const uno::Reference<io::XOutputStream>& xOut )
128 {
129     return XmlEmitterSharedPtr(new OdfEmitter(xOut));
130 }
131 
132 }
133