Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include "oox/helper/attributelist.hxx"
21 :
22 : #include <osl/diagnose.h>
23 : #include <rtl/ustrbuf.hxx>
24 : #include "oox/token/tokenmap.hxx"
25 :
26 : namespace oox {
27 :
28 : // ============================================================================
29 :
30 : using namespace ::com::sun::star;
31 : using namespace ::com::sun::star::uno;
32 : using namespace ::com::sun::star::xml::sax;
33 :
34 : using ::rtl::OUString;
35 : using ::rtl::OUStringBuffer;
36 :
37 : // ============================================================================
38 :
39 : namespace {
40 :
41 : const sal_Int32 XSTRING_ENCCHAR_LEN = 7;
42 :
43 410 : bool lclAddHexDigit( sal_Unicode& orcChar, sal_Unicode cDigit, int nBitShift )
44 : {
45 410 : if( ('0' <= cDigit) && (cDigit <= '9') ) { orcChar |= ((cDigit - '0') << nBitShift); return true; }
46 2 : if( ('a' <= cDigit) && (cDigit <= 'f') ) { orcChar |= ((cDigit - 'a' + 10) << nBitShift); return true; }
47 2 : if( ('A' <= cDigit) && (cDigit <= 'F') ) { orcChar |= ((cDigit - 'A' + 10) << nBitShift); return true; }
48 2 : return false;
49 : }
50 :
51 2552 : sal_Unicode lclGetXChar( const sal_Unicode*& rpcStr, const sal_Unicode* pcEnd )
52 : {
53 2552 : sal_Unicode cChar = 0;
54 4240 : if( (pcEnd - rpcStr >= XSTRING_ENCCHAR_LEN) &&
55 1068 : (rpcStr[ 0 ] == '_') &&
56 106 : (rpcStr[ 1 ] == 'x') &&
57 104 : (rpcStr[ 6 ] == '_') &&
58 104 : lclAddHexDigit( cChar, rpcStr[ 2 ], 12 ) &&
59 102 : lclAddHexDigit( cChar, rpcStr[ 3 ], 8 ) &&
60 102 : lclAddHexDigit( cChar, rpcStr[ 4 ], 4 ) &&
61 102 : lclAddHexDigit( cChar, rpcStr[ 5 ], 0 ) )
62 : {
63 102 : rpcStr += XSTRING_ENCCHAR_LEN;
64 102 : return cChar;
65 : }
66 2450 : return *rpcStr++;
67 : }
68 :
69 : } // namespace
70 :
71 : // ----------------------------------------------------------------------------
72 :
73 76 : sal_Int32 AttributeConversion::decodeToken( const OUString& rValue )
74 : {
75 76 : return StaticTokenMap::get().getTokenFromUnicode( rValue );
76 : }
77 :
78 632 : OUString AttributeConversion::decodeXString( const OUString& rValue )
79 : {
80 : // string shorter than one encoded character - no need to decode
81 632 : if( rValue.getLength() < XSTRING_ENCCHAR_LEN )
82 356 : return rValue;
83 276 : OUStringBuffer aBuffer;
84 276 : const sal_Unicode* pcStr = rValue.getStr();
85 276 : const sal_Unicode* pcEnd = pcStr + rValue.getLength();
86 3104 : while( pcStr < pcEnd )
87 2552 : aBuffer.append( lclGetXChar( pcStr, pcEnd ) );
88 276 : return aBuffer.makeStringAndClear();
89 : }
90 :
91 916 : double AttributeConversion::decodeDouble( const OUString& rValue )
92 : {
93 916 : return rValue.toDouble();
94 : }
95 :
96 6814 : sal_Int32 AttributeConversion::decodeInteger( const OUString& rValue )
97 : {
98 6814 : return rValue.toInt32();
99 : }
100 :
101 8 : sal_uInt32 AttributeConversion::decodeUnsigned( const OUString& rValue )
102 : {
103 8 : return getLimitedValue< sal_uInt32, sal_Int64 >( rValue.toInt64(), 0, SAL_MAX_UINT32 );
104 : }
105 :
106 0 : sal_Int64 AttributeConversion::decodeHyper( const OUString& rValue )
107 : {
108 0 : return rValue.toInt64();
109 : }
110 :
111 464 : sal_Int32 AttributeConversion::decodeIntegerHex( const OUString& rValue )
112 : {
113 464 : return rValue.toInt32( 16 );
114 : }
115 :
116 : // ============================================================================
117 :
118 24178 : AttributeList::AttributeList( const Reference< XFastAttributeList >& rxAttribs ) :
119 24178 : mxAttribs( rxAttribs )
120 : {
121 : OSL_ENSURE( mxAttribs.is(), "AttributeList::AttributeList - missing attribute list interface" );
122 24178 : }
123 :
124 4616 : bool AttributeList::hasAttribute( sal_Int32 nAttrToken ) const
125 : {
126 4616 : return mxAttribs->hasAttribute( nAttrToken );
127 : }
128 :
129 : // optional return values -----------------------------------------------------
130 :
131 778 : OptValue< sal_Int32 > AttributeList::getToken( sal_Int32 nAttrToken ) const
132 : {
133 778 : sal_Int32 nToken = mxAttribs->getOptionalValueToken( nAttrToken, XML_TOKEN_INVALID );
134 778 : return OptValue< sal_Int32 >( nToken != XML_TOKEN_INVALID, nToken );
135 : }
136 :
137 1210 : OptValue< OUString > AttributeList::getString( sal_Int32 nAttrToken ) const
138 : {
139 : // check if the attribute exists (empty string may be different to missing attribute)
140 1210 : if( mxAttribs->hasAttribute( nAttrToken ) )
141 458 : return OptValue< OUString >( mxAttribs->getOptionalValue( nAttrToken ) );
142 752 : return OptValue< OUString >();
143 : }
144 :
145 652 : OptValue< OUString > AttributeList::getXString( sal_Int32 nAttrToken ) const
146 : {
147 : // check if the attribute exists (empty string may be different to missing attribute)
148 652 : if( mxAttribs->hasAttribute( nAttrToken ) )
149 628 : return OptValue< OUString >( AttributeConversion::decodeXString( mxAttribs->getOptionalValue( nAttrToken ) ) );
150 24 : return OptValue< OUString >();
151 : }
152 :
153 1136 : OptValue< double > AttributeList::getDouble( sal_Int32 nAttrToken ) const
154 : {
155 1136 : OUString aValue = mxAttribs->getOptionalValue( nAttrToken );
156 1136 : bool bValid = !aValue.isEmpty();
157 1136 : return OptValue< double >( bValid, bValid ? AttributeConversion::decodeDouble( aValue ) : 0.0 );
158 : }
159 :
160 17014 : OptValue< sal_Int32 > AttributeList::getInteger( sal_Int32 nAttrToken ) const
161 : {
162 17014 : OUString aValue = mxAttribs->getOptionalValue( nAttrToken );
163 17014 : bool bValid = !aValue.isEmpty();
164 17014 : return OptValue< sal_Int32 >( bValid, bValid ? AttributeConversion::decodeInteger( aValue ) : 0 );
165 : }
166 :
167 8 : OptValue< sal_uInt32 > AttributeList::getUnsigned( sal_Int32 nAttrToken ) const
168 : {
169 8 : OUString aValue = mxAttribs->getOptionalValue( nAttrToken );
170 8 : bool bValid = !aValue.isEmpty();
171 8 : return OptValue< sal_uInt32 >( bValid, AttributeConversion::decodeUnsigned( aValue ) );
172 : }
173 :
174 0 : OptValue< sal_Int64 > AttributeList::getHyper( sal_Int32 nAttrToken ) const
175 : {
176 0 : OUString aValue = mxAttribs->getOptionalValue( nAttrToken );
177 0 : bool bValid = !aValue.isEmpty();
178 0 : return OptValue< sal_Int64 >( bValid, bValid ? AttributeConversion::decodeHyper( aValue ) : 0 );
179 : }
180 :
181 464 : OptValue< sal_Int32 > AttributeList::getIntegerHex( sal_Int32 nAttrToken ) const
182 : {
183 464 : OUString aValue = mxAttribs->getOptionalValue( nAttrToken );
184 464 : bool bValid = !aValue.isEmpty();
185 464 : return OptValue< sal_Int32 >( bValid, bValid ? AttributeConversion::decodeIntegerHex( aValue ) : 0 );
186 : }
187 :
188 9982 : OptValue< bool > AttributeList::getBool( sal_Int32 nAttrToken ) const
189 : {
190 : // boolean attributes may be "t", "f", "true", "false", "on", "off", "1", or "0"
191 9982 : switch( getToken( nAttrToken, XML_TOKEN_INVALID ) )
192 : {
193 0 : case XML_t: return OptValue< bool >( true ); // used in VML
194 810 : case XML_true: return OptValue< bool >( true );
195 0 : case XML_on: return OptValue< bool >( true );
196 0 : case XML_f: return OptValue< bool >( false ); // used in VML
197 2570 : case XML_false: return OptValue< bool >( false );
198 0 : case XML_off: return OptValue< bool >( false );
199 : }
200 6602 : OptValue< sal_Int32 > onValue = getInteger( nAttrToken );
201 6602 : return OptValue< bool >( onValue.has(), onValue.get() != 0 );
202 : }
203 :
204 0 : OptValue< util::DateTime > AttributeList::getDateTime( sal_Int32 nAttrToken ) const
205 : {
206 0 : OUString aValue = mxAttribs->getOptionalValue( nAttrToken );
207 0 : util::DateTime aDateTime;
208 0 : bool bValid = (aValue.getLength() == 19) && (aValue[ 4 ] == '-') && (aValue[ 7 ] == '-') &&
209 0 : (aValue[ 10 ] == 'T') && (aValue[ 13 ] == ':') && (aValue[ 16 ] == ':');
210 0 : if( bValid )
211 : {
212 0 : aDateTime.Year = static_cast< sal_uInt16 >( aValue.copy( 0, 4 ).toInt32() );
213 0 : aDateTime.Month = static_cast< sal_uInt16 >( aValue.copy( 5, 2 ).toInt32() );
214 0 : aDateTime.Day = static_cast< sal_uInt16 >( aValue.copy( 8, 2 ).toInt32() );
215 0 : aDateTime.Hours = static_cast< sal_uInt16 >( aValue.copy( 11, 2 ).toInt32() );
216 0 : aDateTime.Minutes = static_cast< sal_uInt16 >( aValue.copy( 14, 2 ).toInt32() );
217 0 : aDateTime.Seconds = static_cast< sal_uInt16 >( aValue.copy( 17, 2 ).toInt32() );
218 : }
219 0 : return OptValue< util::DateTime >( bValid, aDateTime );
220 : }
221 :
222 : // defaulted return values ----------------------------------------------------
223 :
224 19794 : sal_Int32 AttributeList::getToken( sal_Int32 nAttrToken, sal_Int32 nDefault ) const
225 : {
226 19794 : return mxAttribs->getOptionalValueToken( nAttrToken, nDefault );
227 : }
228 :
229 9396 : OUString AttributeList::getString( sal_Int32 nAttrToken, const OUString& rDefault ) const
230 : {
231 : // try to avoid slow exception throw/catch if we can
232 9396 : if (rDefault.isEmpty())
233 9344 : return mxAttribs->getOptionalValue( nAttrToken );
234 :
235 : try
236 : {
237 52 : return mxAttribs->getValue( nAttrToken );
238 : }
239 40 : catch( Exception& )
240 : {
241 : }
242 40 : return rDefault;
243 : }
244 :
245 648 : OUString AttributeList::getXString( sal_Int32 nAttrToken, const OUString& rDefault ) const
246 : {
247 648 : return getXString( nAttrToken ).get( rDefault );
248 : }
249 :
250 1136 : double AttributeList::getDouble( sal_Int32 nAttrToken, double fDefault ) const
251 : {
252 1136 : return getDouble( nAttrToken ).get( fDefault );
253 : }
254 :
255 9824 : sal_Int32 AttributeList::getInteger( sal_Int32 nAttrToken, sal_Int32 nDefault ) const
256 : {
257 9824 : return getInteger( nAttrToken ).get( nDefault );
258 : }
259 :
260 8 : sal_uInt32 AttributeList::getUnsigned( sal_Int32 nAttrToken, sal_uInt32 nDefault ) const
261 : {
262 8 : return getUnsigned( nAttrToken ).get( nDefault );
263 : }
264 :
265 0 : sal_Int64 AttributeList::getHyper( sal_Int32 nAttrToken, sal_Int64 nDefault ) const
266 : {
267 0 : return getHyper( nAttrToken ).get( nDefault );
268 : }
269 :
270 464 : sal_Int32 AttributeList::getIntegerHex( sal_Int32 nAttrToken, sal_Int32 nDefault ) const
271 : {
272 464 : return getIntegerHex( nAttrToken ).get( nDefault );
273 : }
274 :
275 9800 : bool AttributeList::getBool( sal_Int32 nAttrToken, bool bDefault ) const
276 : {
277 9800 : return getBool( nAttrToken ).get( bDefault );
278 : }
279 :
280 0 : util::DateTime AttributeList::getDateTime( sal_Int32 nAttrToken, const util::DateTime& rDefault ) const
281 : {
282 0 : return getDateTime( nAttrToken ).get( rDefault );
283 : }
284 :
285 : // ============================================================================
286 :
287 : } // namespace oox
288 :
289 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|